richk@6720: /* $Id$ */ richk@6720: richk@6720: #ifndef BLITTER_FACTORY_HPP richk@6720: #define BLITTER_FACTORY_HPP richk@6720: richk@6720: #include "base.hpp" rubidium@6870: #include "../debug.h" rubidium@6872: #include "../string_func.h" richk@6720: #include richk@6720: #include richk@6720: richk@6720: /** richk@6720: * The base factory, keeping track of all blitters. richk@6720: */ richk@6720: class BlitterFactoryBase { richk@6720: private: richk@6720: char *name; richk@6720: typedef std::map Blitters; richk@6720: richk@6720: static Blitters &GetBlitters() richk@6720: { richk@6720: static Blitters &s_blitters = *new Blitters(); richk@6720: return s_blitters; richk@6720: } richk@6720: richk@6720: static Blitter **GetActiveBlitter() richk@6720: { richk@6720: static Blitter *s_blitter = NULL; richk@6720: return &s_blitter; richk@6720: } richk@6720: richk@6720: protected: richk@6720: /** richk@6720: * Register a blitter internally, based on his name. richk@6720: * @param name the name of the blitter. richk@6720: * @note an assert() will be trigger if 2 blitters with the same name try to register. richk@6720: */ richk@6720: void RegisterBlitter(const char *name) richk@6720: { richk@6720: /* Don't register nameless Blitters */ richk@6720: if (name == NULL) return; richk@6720: richk@6720: this->name = strdup(name); rubidium@6872: #if !defined(NDEBUG) || defined(WITH_ASSERT) richk@6725: /* NDEBUG disables asserts and gives a warning: unused variable 'P' */ richk@6725: std::pair P = richk@6725: #endif /* !NDEBUG */ richk@6725: GetBlitters().insert(Blitters::value_type(name, this)); richk@6720: assert(P.second); richk@6720: } richk@6720: richk@6720: public: richk@6720: BlitterFactoryBase() : richk@6720: name(NULL) richk@6720: {} richk@6720: richk@6720: virtual ~BlitterFactoryBase() { if (this->name != NULL) GetBlitters().erase(this->name); free(this->name); } richk@6720: richk@6720: /** richk@6720: * Find the requested blitter and return his class. richk@6720: * @param name the blitter to select. richk@6720: * @post Sets the blitter so GetCurrentBlitter() returns it too. richk@6720: */ richk@6720: static Blitter *SelectBlitter(const char *name) richk@6720: { rubidium@6870: const char *default_blitter = "8bpp-optimized"; rubidium@6870: richk@6720: if (GetBlitters().size() == 0) return NULL; rubidium@6870: const char *bname = (StrEmpty(name)) ? default_blitter : name; richk@6720: richk@6720: Blitters::iterator it = GetBlitters().begin(); richk@6720: for (; it != GetBlitters().end(); it++) { richk@6720: BlitterFactoryBase *b = (*it).second; rubidium@6870: if (strcasecmp(bname, b->name) == 0) { richk@6720: Blitter *newb = b->CreateInstance(); richk@6720: delete *GetActiveBlitter(); richk@6720: *GetActiveBlitter() = newb; rubidium@6870: rubidium@6870: DEBUG(driver, 1, "Successfully %s blitter '%s'",StrEmpty(name) ? "probed" : "loaded", bname); richk@6720: return newb; richk@6720: } richk@6720: } richk@6720: return NULL; richk@6720: } richk@6720: richk@6720: /** richk@6720: * Get the current active blitter (always set by calling SelectBlitter). richk@6720: */ richk@6720: static Blitter *GetCurrentBlitter() richk@6720: { richk@6720: return *GetActiveBlitter(); richk@6720: } richk@6720: richk@6720: richk@6720: static char *GetBlittersInfo(char *p, const char *last) richk@6720: { richk@6720: p += snprintf(p, last - p, "List of blitters:\n"); richk@6720: Blitters::iterator it = GetBlitters().begin(); richk@6720: for (; it != GetBlitters().end(); it++) { richk@6720: BlitterFactoryBase *b = (*it).second; richk@6720: p += snprintf(p, last - p, "%18s: %s\n", b->name, b->GetDescription()); richk@6720: } richk@6720: p += snprintf(p, last - p, "\n"); richk@6720: richk@6720: return p; richk@6720: } richk@6720: richk@6720: /** richk@6720: * Get a nice description of the blitter-class. richk@6720: */ richk@6720: virtual const char *GetDescription() = 0; richk@6720: richk@6720: /** richk@6720: * Create an instance of this Blitter-class. richk@6720: */ richk@6720: virtual Blitter *CreateInstance() = 0; richk@6720: }; richk@6720: richk@6720: /** richk@6720: * A template factory, so ->GetName() works correctly. This because else some compiler will complain. richk@6720: */ richk@6720: template richk@6720: class BlitterFactory: public BlitterFactoryBase { richk@6720: public: richk@6720: BlitterFactory() { this->RegisterBlitter(((T *)this)->GetName()); } richk@6720: richk@6720: /** richk@6720: * Get the long, human readable, name for the Blitter-class. richk@6720: */ richk@6720: const char *GetName(); richk@6720: }; richk@6720: rubidium@6872: extern char _ini_blitter[32]; rubidium@6872: richk@6720: #endif /* BLITTER_FACTORY_HPP */