Main Page | Namespace List | Class Hierarchy | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages

sdl_cvideo.cpp

Go to the documentation of this file.
00001 #include "cvideo.h"
00002 #include "cgame.h"
00003 #include "cdebug.h"
00004 
00005 #include <SDL.h>
00006 
00014 namespace SDLDriver {
00015   /* Convert a CRect structure to an SDL_Rect structure. */
00016   void crect_to_sdl_rect(const CRect &cr, SDL_Rect &sr) {
00017     sr.x = cr.pos.x;
00018     sr.y = cr.pos.y;
00019     sr.w = cr.size.x;
00020     sr.h = cr.size.y;
00021   }
00022 
00023   /* The screen.  Due to the massive level of decoupling
00024      between the high-level video system manager and the
00025      low-level SDL implementation layers, it's just easier
00026      to store our own pointer to the screen and change it
00027      whenever the higher-level layer asks the lower-level
00028      layer for it to be changed.
00029      
00030      Note that this variable is at the module level; it's
00031      static, using internal linkage, so it's not a global
00032      variable, which hopefully makes it not too evil. */
00033   static SDL_Surface *g_screen;
00034 
00039 class CSurfaceImplSDL : public CSurfaceImpl {
00040   /* The reference count of the surface (how many variables are
00041      currently referring to us?).  Used for basic
00042      garbage collection. */
00043   int reference_count;
00044 
00045   /* The actual SDL surface representing the bitmap. */
00046   SDL_Surface *sdl_surface;
00047 
00048 public:
00050   CSurfaceImplSDL() : reference_count(0), sdl_surface(0) { }
00051 
00053   CSurfaceImplSDL(int w, int h) : reference_count(0)
00054   {
00055     int flags = 0;
00056 
00057     SDL_PixelFormat *pf = g_screen->format;
00058     
00059     sdl_surface = SDL_CreateRGBSurface(flags, w, h, pf->BitsPerPixel,
00060       pf->Rmask, pf->Gmask, pf->Bmask, pf->Amask);
00061     inc_ref_count();
00062   }
00063 
00065   CSurfaceImplSDL(const char *filename) : reference_count(0)
00066   {
00067     sdl_surface = SDL_LoadBMP(filename);
00068     if (!sdl_surface) {
00069       CDebug::log("Couldn't load BMP.\n", 1);
00070     }
00071     inc_ref_count();
00072   }
00073 
00077   virtual ~CSurfaceImplSDL() {
00078     /* Make sure no CSurface objects are pointing to us. */
00079     assert(reference_count == 0);
00080     /* Free our bitmap surface. */
00081     SDL_FreeSurface(sdl_surface);
00082   }
00083 
00084   virtual void set_transparent_color(CColor color) {
00085     SDL_SetColorKey(sdl_surface, SDL_SRCCOLORKEY | SDL_RLEACCEL, color);
00086         SDL_Surface *bitmap = SDL_DisplayFormatAlpha(sdl_surface);
00087     SDL_FreeSurface(sdl_surface);
00088     sdl_surface = bitmap;
00089   }
00090 
00091   virtual void inc_ref_count() {
00092     reference_count++;
00093   }
00094 
00096   virtual void dec_ref_count() {
00097     assert(reference_count > 0);
00098     reference_count--;
00099     printf("CSurfaceImplSDL detached: --refcount = %d (%dx%d).\n", reference_count, 
00100       sdl_surface->w, sdl_surface->h);
00101   }
00102 
00104   virtual int is_empty() { return (reference_count == 0); }
00105 
00106   virtual int get_depth() { return sdl_surface->format->BitsPerPixel; }
00107 
00108   virtual int get_width() { return sdl_surface->w; }
00109 
00110   virtual int get_height() { return sdl_surface->h; }
00111 
00112   virtual void blit(CSurfaceImpl &source) { SDL_BlitSurface( ((CSurfaceImplSDL *) &source)->sdl_surface, NULL, sdl_surface, NULL); }
00113 
00114   virtual void blit(CSurfaceImpl &source, CPoint &dest_pos) {
00115     SDL_Rect r;
00116 
00117     r.x = dest_pos.x;
00118     r.y = dest_pos.y;
00119 
00120     SDL_BlitSurface( ((CSurfaceImplSDL *) &source)->sdl_surface, NULL, sdl_surface, &r);
00121   }
00122 
00123   virtual void blit(CSurfaceImpl &source, CPoint &dest_pos, CRect &src_rect) {
00124     SDL_Rect r_src, r_dst;
00125 
00126     crect_to_sdl_rect(src_rect, r_src);
00127 
00128     r_dst.x = dest_pos.x;
00129     r_dst.y = dest_pos.y;
00130     
00131     SDL_BlitSurface( ((CSurfaceImplSDL *) &source)->sdl_surface, &r_src, sdl_surface, &r_dst);
00132   }
00133 
00134   virtual void fill_rect(const CRect &rect, CColor color) {
00135     SDL_Rect sdl_rect;
00136 
00137     crect_to_sdl_rect(rect, sdl_rect);
00138 
00139     SDL_FillRect( sdl_surface, &sdl_rect, color);
00140   }
00141 
00142   virtual void set_clipping_rect(CRect &rect) {
00143     SDL_Rect sdl_rect;
00144 
00145     crect_to_sdl_rect(rect, sdl_rect);
00146 
00147     SDL_SetClipRect(sdl_surface, &sdl_rect);
00148   }
00149 
00150   virtual void clear_clipping_rect() {
00151     SDL_SetClipRect(sdl_surface, NULL);
00152   }
00153 
00154   virtual void flip() {
00155     SDL_Flip(sdl_surface);
00156   }
00157 
00158   void update_rects(CRectList &rects) {
00159     int num_rects = (int) rects.size();
00160 
00161     SDL_Rect *sdl_rects = new SDL_Rect[num_rects];
00162 
00163     SDL_Rect *curr_rect = sdl_rects;
00164 
00165     for (CRectList::iterator i = rects.begin(); i != rects.end(); i++) {
00166       crect_to_sdl_rect(*i, *curr_rect);
00167       curr_rect++;
00168     }
00169 
00170     SDL_UpdateRects(sdl_surface, num_rects, sdl_rects);
00171 
00172     delete[] sdl_rects;
00173   }
00174 
00175   virtual void set_video_mode(int width, int height, int depth, int is_fullscreen)
00176   {
00177     int flags = SDL_SWSURFACE;
00178     int actual_depth = SDL_VideoModeOK(width, height, depth, flags);
00179     
00180     if (is_fullscreen) {
00181       flags = flags | SDL_FULLSCREEN;
00182     }
00183     sdl_surface = SDL_SetVideoMode(width, height, actual_depth, flags);
00184     if ( sdl_surface == NULL ) {
00185       CDebug::log("couldn't init screen.\n", 1);
00186     }
00187     g_screen = sdl_surface;
00188     reference_count = 1;
00189   }
00190 };
00191 
00195 class CVideoSystemSDL : CVideoSystem {
00196  private:
00197   friend class CVideoSystemFactorySDL;
00198 
00199   /* Reference to the display. */
00200   CScreen *screen;
00201 
00202   CVideoSystemSDL(int width, int height, int depth, int is_fullscreen) {
00203     if ( SDL_Init( SDL_INIT_VIDEO ) < 0) {
00204       CDebug::log("couldn't init SDL.\n", 1);
00205     }
00206     CSurfaceImplSDL *impl = new CSurfaceImplSDL();
00207     impl->set_video_mode(width, height, depth, is_fullscreen);
00208     screen = new CScreen(impl);
00209   }
00210 
00211  protected:
00212   virtual CSurfaceImpl *make_csurface_impl(int w, int h) {
00213    return new CSurfaceImplSDL(w, h);
00214   }
00215   virtual CSurfaceImpl *make_csurface_impl(const char *filename) {
00216     return new CSurfaceImplSDL(filename);
00217   }
00218   virtual uint32 make_color(uint8 r, uint8 g, uint8 b) {
00219     SDL_PixelFormat *pf = g_screen->format;
00220     return SDL_MapRGB(pf, r, g, b);
00221   }
00222 
00223  public:
00224   virtual ~CVideoSystemSDL() {
00225     delete screen;
00226     SDL_Quit();
00227   }
00228 
00229   virtual CScreen &get_screen() { return *screen; }
00230 };
00231 
00234 class CVideoSystemFactorySDL : public CVideoSystemFactory {
00235   /* These instance variables hold information about how we want
00236      our screen to be displayed once the factory is told to create the
00237      actual singleton. */
00238   int w, h, d, is_f;
00239   virtual CVideoSystem *make_singleton() {
00240     return new CVideoSystemSDL(w, h, d, is_f);
00241   }
00242  public:
00248   CVideoSystemFactorySDL(int width, int height, int depth, int is_fullscreen) : 
00249     w(width), h(height), d(depth), is_f(is_fullscreen) { }
00250 };
00251 
00252   CVideoSystemFactory *make_video_system_factory(int width, int height, int depth, int is_fullscreen) {
00253     return new CVideoSystemFactorySDL(width, height, depth, is_fullscreen);
00254   }
00255 }

Generated on Wed Aug 27 11:58:42 2003 for GFW by doxygen 1.3.3