00001 #include "cvideo.h"
00002 #include "cgame.h"
00003 #include "cdebug.h"
00004
00005 #include <SDL.h>
00006
00014 namespace SDLDriver {
00015
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
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 static SDL_Surface *g_screen;
00034
00039 class CSurfaceImplSDL : public CSurfaceImpl {
00040
00041
00042
00043 int reference_count;
00044
00045
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
00079 assert(reference_count == 0);
00080
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
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
00236
00237
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 }