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 */

Generated on Wed Oct 1 17:03:20 2008 for openttd by  doxygen 1.5.6