factory.hpp

Go to the documentation of this file.
00001 /* $Id: factory.hpp 26215 2014-01-03 08:29:07Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef BLITTER_FACTORY_HPP
00013 #define BLITTER_FACTORY_HPP
00014 
00015 #include "base.hpp"
00016 #include "../debug.h"
00017 #include "../string_func.h"
00018 #include "../core/string_compare_type.hpp"
00019 #include <map>
00020 
00021 #if defined(WITH_COCOA)
00022 bool QZ_CanDisplay8bpp();
00023 #endif /* defined(WITH_COCOA) */
00024 
00028 class BlitterFactory {
00029 private:
00030   const char *name;        
00031   const char *description; 
00032 
00033   typedef std::map<const char *, BlitterFactory *, StringCompare> Blitters; 
00034 
00039   static Blitters &GetBlitters()
00040   {
00041     static Blitters &s_blitters = *new Blitters();
00042     return s_blitters;
00043   }
00044 
00049   static Blitter **GetActiveBlitter()
00050   {
00051     static Blitter *s_blitter = NULL;
00052     return &s_blitter;
00053   }
00054 
00055 protected:
00065   BlitterFactory(const char *name, const char *description, bool usable = true) :
00066       name(strdup(name)), description(strdup(description))
00067   {
00068     if (usable) {
00069       /*
00070        * Only add when the blitter is usable. Do not bail out or
00071        * do more special things since the blitters are always
00072        * instantiated upon start anyhow and freed upon shutdown.
00073        */
00074       std::pair<Blitters::iterator, bool> P = GetBlitters().insert(Blitters::value_type(this->name, this));
00075       assert(P.second);
00076     } else {
00077       DEBUG(driver, 1, "Not registering blitter %s as it is not usable", name);
00078     }
00079   }
00080 
00081 public:
00082   virtual ~BlitterFactory()
00083   {
00084     GetBlitters().erase(this->name);
00085     if (GetBlitters().empty()) delete &GetBlitters();
00086 
00087     free(this->name);
00088     free(this->description);
00089   }
00090 
00096   static Blitter *SelectBlitter(const char *name)
00097   {
00098     BlitterFactory *b = GetBlitterFactory(name);
00099     if (b == NULL) return NULL;
00100 
00101     Blitter *newb = b->CreateInstance();
00102     delete *GetActiveBlitter();
00103     *GetActiveBlitter() = newb;
00104 
00105     DEBUG(driver, 1, "Successfully %s blitter '%s'", StrEmpty(name) ? "probed" : "loaded", newb->GetName());
00106     return newb;
00107   }
00108 
00114   static BlitterFactory *GetBlitterFactory(const char *name)
00115   {
00116 #if defined(DEDICATED)
00117     const char *default_blitter = "null";
00118 #else
00119     const char *default_blitter = "8bpp-optimized";
00120 
00121 #if defined(WITH_COCOA)
00122     /* Some people reported lack of fullscreen support in 8 bpp mode.
00123      * While we prefer 8 bpp since it's faster, we will still have to test for support. */
00124     if (!QZ_CanDisplay8bpp()) {
00125       /* The main display can't go to 8 bpp fullscreen mode.
00126        * We will have to switch to 32 bpp by default. */
00127       default_blitter = "32bpp-anim";
00128     }
00129 #endif /* defined(WITH_COCOA) */
00130 #endif /* defined(DEDICATED) */
00131     if (GetBlitters().size() == 0) return NULL;
00132     const char *bname = (StrEmpty(name)) ? default_blitter : name;
00133 
00134     Blitters::iterator it = GetBlitters().begin();
00135     for (; it != GetBlitters().end(); it++) {
00136       BlitterFactory *b = (*it).second;
00137       if (strcasecmp(bname, b->name) == 0) {
00138         return b;
00139       }
00140     }
00141     return NULL;
00142   }
00143 
00147   static Blitter *GetCurrentBlitter()
00148   {
00149     return *GetActiveBlitter();
00150   }
00151 
00158   static char *GetBlittersInfo(char *p, const char *last)
00159   {
00160     p += seprintf(p, last, "List of blitters:\n");
00161     Blitters::iterator it = GetBlitters().begin();
00162     for (; it != GetBlitters().end(); it++) {
00163       BlitterFactory *b = (*it).second;
00164       p += seprintf(p, last, "%18s: %s\n", b->name, b->GetDescription());
00165     }
00166     p += seprintf(p, last, "\n");
00167 
00168     return p;
00169   }
00170 
00174   const char *GetName() const
00175   {
00176     return this->name;
00177   }
00178 
00182   const char *GetDescription() const
00183   {
00184     return this->description;
00185   }
00186 
00190   virtual Blitter *CreateInstance() = 0;
00191 };
00192 
00193 extern char *_ini_blitter;
00194 extern bool _blitter_autodetected;
00195 
00196 #endif /* BLITTER_FACTORY_HPP */