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