# factory.hpp

    00001 /* $Id: factory.hpp 14267 2008-09-07 21:41:47Z rubidium $ */
    00002
    00003 #ifndef BLITTER_FACTORY_HPP
    00004 #define BLITTER_FACTORY_HPP
    00005
    00006 #include "base.hpp"
    00007 #include "../debug.h"
    00008 #include "../string_func.h"
    00009 #include <string>
    00010 #include <map>
    00011
    00012 #if defined(WITH_COCOA)
    00013 bool QZ_CanDisplay8bpp();
    00014 #endif /* defined(WITH_COCOA) */
    00015
    00019 class BlitterFactoryBase {
    00020 private:
    00021   char *name;
    00022   typedef std::map<std::string, BlitterFactoryBase *> Blitters;
    00023
    00024   static Blitters &GetBlitters()
    00025   {
    00026     static Blitters &s_blitters = *new Blitters();
    00027     return s_blitters;
    00028   }
    00029
    00030   static Blitter **GetActiveBlitter()
    00031   {
    00032     static Blitter *s_blitter = NULL;
    00033     return &s_blitter;
    00034   }
    00035
    00036 protected:
    00042   void RegisterBlitter(const char *name)
    00043   {
    00044     /* Don't register nameless Blitters */
    00045     if (name == NULL) return;
    00046
    00047     this->name = strdup(name);
    00048 #if !defined(NDEBUG) || defined(WITH_ASSERT)
    00049     /* NDEBUG disables asserts and gives a warning: unused variable 'P' */
    00050     std::pair<Blitters::iterator, bool> P =
    00051 #endif /* !NDEBUG */
    00052     GetBlitters().insert(Blitters::value_type(name, this));
    00053     assert(P.second);
    00054   }
    00055
    00056 public:
    00057   BlitterFactoryBase() :
    00058     name(NULL)
    00059   {}
    00060
    00061   virtual ~BlitterFactoryBase() { if (this->name != NULL) GetBlitters().erase(this->name); free(this->name); }
    00062
    00068   static Blitter *SelectBlitter(const char *name)
    00069   {
    00070     const char *default_blitter = "8bpp-optimized";
    00071
    00072 #if defined(WITH_COCOA)
    00073     /* Some people reported lack of fullscreen support in 8 bpp mode.
    00074      * While we prefer 8 bpp since it's faster, we will still have to test for support. */
    00075     if (!QZ_CanDisplay8bpp()) {
    00076       /* The main display can't go to 8 bpp fullscreen mode.
    00077        * We will have to switch to 32 bpp by default. */
    00078       default_blitter = "32bpp-anim";
    00079     }
    00080 #endif /* defined(WITH_COCOA) */
    00081     if (GetBlitters().size() == 0) return NULL;
    00082     const char *bname = (StrEmpty(name)) ? default_blitter : name;
    00083
    00084     Blitters::iterator it = GetBlitters().begin();
    00085     for (; it != GetBlitters().end(); it++) {
    00086       BlitterFactoryBase *b = (*it).second;
    00087       if (strcasecmp(bname, b->name) == 0) {
    00088         Blitter *newb = b->CreateInstance();
    00089         delete *GetActiveBlitter();
    00090         *GetActiveBlitter() = newb;
    00091
    00092         DEBUG(driver, 1, "Successfully %s blitter '%s'",StrEmpty(name) ? "probed" : "loaded", bname);
    00093         return newb;
    00094       }
    00095     }
    00096     return NULL;
    00097   }
    00098
    00102   static Blitter *GetCurrentBlitter()
    00103   {
    00104     return *GetActiveBlitter();
    00105   }
    00106
    00107
    00108   static char *GetBlittersInfo(char *p, const char *last)
    00109   {
    00110     p += snprintf(p, last - p, "List of blitters:\n");
    00111     Blitters::iterator it = GetBlitters().begin();
    00112     for (; it != GetBlitters().end(); it++) {
    00113       BlitterFactoryBase *b = (*it).second;
    00114       p += snprintf(p, last - p, "%18s: %s\n", b->name, b->GetDescription());
    00115     }
    00116     p += snprintf(p, last - p, "\n");
    00117
    00118     return p;
    00119   }
    00120
    00124   virtual const char *GetDescription() = 0;
    00125
    00129   virtual Blitter *CreateInstance() = 0;
    00130 };
    00131
    00135 template <class T>
    00136 class BlitterFactory: public BlitterFactoryBase {
    00137 public:
    00138   BlitterFactory() { this->RegisterBlitter(((T *)this)->GetName()); }
    00139
    00143   const char *GetName();
    00144 };
    00145
    00146 extern char _ini_blitter[32];
    00147
    00148 #endif /* BLITTER_FACTORY_HPP */