truelight@6937: /* $Id$ */ truelight@6937: rubidium@9111: /** @file factory.hpp Factory to 'query' all available blitters. */ rubidium@9111: truelight@6937: #ifndef BLITTER_FACTORY_HPP truelight@6937: #define BLITTER_FACTORY_HPP truelight@6937: truelight@6937: #include "base.hpp" truelight@7568: #include "../debug.h" rubidium@8214: #include "../string_func.h" truelight@6937: #include truelight@6937: #include truelight@6937: truelight@6937: /** truelight@6937: * The base factory, keeping track of all blitters. truelight@6937: */ truelight@6937: class BlitterFactoryBase { truelight@6937: private: truelight@6937: char *name; truelight@6937: typedef std::map Blitters; truelight@6937: truelight@6937: static Blitters &GetBlitters() truelight@6937: { truelight@6937: static Blitters &s_blitters = *new Blitters(); truelight@6937: return s_blitters; truelight@6937: } truelight@6937: truelight@6937: static Blitter **GetActiveBlitter() truelight@6937: { truelight@6937: static Blitter *s_blitter = NULL; truelight@6937: return &s_blitter; truelight@6937: } truelight@6937: truelight@6937: protected: truelight@6937: /** truelight@6937: * Register a blitter internally, based on his name. truelight@6937: * @param name the name of the blitter. truelight@6937: * @note an assert() will be trigger if 2 blitters with the same name try to register. truelight@6937: */ truelight@6937: void RegisterBlitter(const char *name) truelight@6937: { truelight@6937: /* Don't register nameless Blitters */ truelight@6937: if (name == NULL) return; truelight@6937: truelight@6937: this->name = strdup(name); smatz@9436: smatz@9436: std::pair P = GetBlitters().insert(Blitters::value_type(name, this)); truelight@6937: assert(P.second); truelight@6937: } truelight@6937: truelight@6937: public: truelight@6937: BlitterFactoryBase() : truelight@6937: name(NULL) truelight@6937: {} truelight@6937: glx@9294: virtual ~BlitterFactoryBase() glx@9294: { glx@9294: if (this->name == NULL) return; glx@9294: GetBlitters().erase(this->name); glx@9294: if (GetBlitters().empty()) delete &GetBlitters(); glx@9294: free(this->name); glx@9294: } truelight@6937: truelight@6937: /** truelight@6937: * Find the requested blitter and return his class. truelight@6937: * @param name the blitter to select. truelight@6937: * @post Sets the blitter so GetCurrentBlitter() returns it too. truelight@6937: */ truelight@6937: static Blitter *SelectBlitter(const char *name) truelight@6937: { truelight@7567: const char *default_blitter = "8bpp-optimized"; truelight@7567: bjarni@9561: #if defined(__APPLE__) bjarni@9561: /* MacOS X 10.5 removed 8bpp fullscreen support. bjarni@9561: * Because of this we will pick 32bpp by default */ bjarni@9561: if (MacOSVersionIsAtLeast(10, 5, 0)) { bjarni@9561: default_blitter = "32bpp-anim"; bjarni@9561: } bjarni@9561: #endif /* defined(__APPLE__) */ truelight@6937: if (GetBlitters().size() == 0) return NULL; truelight@7567: const char *bname = (StrEmpty(name)) ? default_blitter : name; truelight@6937: truelight@6937: Blitters::iterator it = GetBlitters().begin(); truelight@6937: for (; it != GetBlitters().end(); it++) { truelight@6937: BlitterFactoryBase *b = (*it).second; truelight@7567: if (strcasecmp(bname, b->name) == 0) { truelight@6937: Blitter *newb = b->CreateInstance(); rubidium@7091: delete *GetActiveBlitter(); truelight@6937: *GetActiveBlitter() = newb; truelight@7568: truelight@7568: DEBUG(driver, 1, "Successfully %s blitter '%s'",StrEmpty(name) ? "probed" : "loaded", bname); truelight@6937: return newb; truelight@6937: } truelight@6937: } truelight@6937: return NULL; truelight@6937: } truelight@6937: truelight@6937: /** truelight@6937: * Get the current active blitter (always set by calling SelectBlitter). truelight@6937: */ truelight@6937: static Blitter *GetCurrentBlitter() truelight@6937: { truelight@6937: return *GetActiveBlitter(); truelight@6937: } truelight@6937: truelight@6937: truelight@6937: static char *GetBlittersInfo(char *p, const char *last) truelight@6937: { truelight@6937: p += snprintf(p, last - p, "List of blitters:\n"); truelight@6937: Blitters::iterator it = GetBlitters().begin(); truelight@6937: for (; it != GetBlitters().end(); it++) { truelight@6937: BlitterFactoryBase *b = (*it).second; truelight@6937: p += snprintf(p, last - p, "%18s: %s\n", b->name, b->GetDescription()); truelight@6937: } truelight@6937: p += snprintf(p, last - p, "\n"); truelight@6937: truelight@6937: return p; truelight@6937: } truelight@6937: truelight@6937: /** truelight@6937: * Get a nice description of the blitter-class. truelight@6937: */ truelight@6937: virtual const char *GetDescription() = 0; truelight@6937: truelight@6937: /** truelight@6937: * Create an instance of this Blitter-class. truelight@6937: */ truelight@6937: virtual Blitter *CreateInstance() = 0; truelight@6937: }; truelight@6937: truelight@6937: /** truelight@6937: * A template factory, so ->GetName() works correctly. This because else some compiler will complain. truelight@6937: */ truelight@6937: template truelight@6937: class BlitterFactory: public BlitterFactoryBase { truelight@6937: public: truelight@6937: BlitterFactory() { this->RegisterBlitter(((T *)this)->GetName()); } truelight@6937: truelight@6937: /** truelight@6937: * Get the long, human readable, name for the Blitter-class. truelight@6937: */ truelight@6937: const char *GetName(); truelight@6937: }; truelight@6937: rubidium@8275: extern char _ini_blitter[32]; rubidium@8275: truelight@6937: #endif /* BLITTER_FACTORY_HPP */