BaseSoftRenderSurface.cpp

Go to the documentation of this file.
00001         /*
00002 BaseSoftRenderSurface.cpp : Abstract BaseSoftRenderSurface source file
00003 
00004 Copyright (C) 2003 The Pentagram Team
00005 
00006 This program is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU General Public License
00008 as published by the Free Software Foundation; either version 2
00009 of the License, or (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with this program; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 */
00020 
00021 #include "pent_include.h"
00022 #include <SDL.h>
00023 
00024 #include "SoftRenderSurface.h"
00025 #include "Palette.h"
00026 #include "Texture.h"
00027 
00028 using Pentagram::Rect;
00029 
00031 //                       //
00032 // BaseSoftRenderSurface //
00033 //                       //
00035 
00036 //
00037 // BaseSoftRenderSurface::BaseSoftRenderSurface(SDL_Surface *s)
00038 //
00039 // Desc: Constructor for BaseSoftRenderSurface from a SDL_Surface
00040 //
00041 BaseSoftRenderSurface::BaseSoftRenderSurface(SDL_Surface *s) :
00042         pixels(0), pixels00(0), zbuffer(0), zbuffer00(0),
00043         bytes_per_pixel(0), bits_per_pixel(0), format_type(0), 
00044         ox(0), oy(0), width(0), height(0), pitch(0), zpitch(0),
00045         flipped(false), clip_window(0,0,0,0), lock_count(0),
00046         sdl_surf(s), rtt_tex(0)
00047 {
00048         clip_window.ResizeAbs(width = sdl_surf->w, height = sdl_surf->h);
00049         pitch = sdl_surf->pitch;
00050         bits_per_pixel = sdl_surf->format->BitsPerPixel;
00051         bytes_per_pixel = sdl_surf->format->BytesPerPixel;
00052 
00053         RenderSurface::format.s_bpp = bits_per_pixel;
00054         RenderSurface::format.s_bytes_per_pixel = bytes_per_pixel;
00055         RenderSurface::format.r_loss = sdl_surf->format->Rloss;
00056         RenderSurface::format.g_loss = sdl_surf->format->Gloss;
00057         RenderSurface::format.b_loss = sdl_surf->format->Bloss;
00058         RenderSurface::format.a_loss = sdl_surf->format->Aloss;
00059         RenderSurface::format.r_loss16 = format.r_loss+8;
00060         RenderSurface::format.g_loss16 = format.g_loss+8;
00061         RenderSurface::format.b_loss16 = format.b_loss+8;
00062         RenderSurface::format.a_loss16 = format.a_loss+8;
00063         RenderSurface::format.r_shift = sdl_surf->format->Rshift;
00064         RenderSurface::format.g_shift = sdl_surf->format->Gshift;
00065         RenderSurface::format.b_shift = sdl_surf->format->Bshift;
00066         RenderSurface::format.a_shift = sdl_surf->format->Ashift;
00067         RenderSurface::format.r_mask = sdl_surf->format->Rmask;
00068         RenderSurface::format.g_mask = sdl_surf->format->Gmask;
00069         RenderSurface::format.b_mask = sdl_surf->format->Bmask;
00070         RenderSurface::format.a_mask = sdl_surf->format->Amask;
00071 
00072         SetPixelsPointer();
00073 
00074         // Trickery to get the alpha channel
00075         if (format.a_mask == 0 && bytes_per_pixel==4)
00076         {
00077                 uint32 mask = ~(format.r_mask|format.g_mask|format.b_mask);
00078 
00079                 // Using all bits????
00080                 if (!mask) return;
00081 
00082                 // Check the mask to make sure that it's 'sane'
00083                 int i;
00084                 int last = 0;
00085                 int first = 0;
00086                 int zero = 32;
00087 
00088                 for (i = 0; i < 32; i++)
00089                 {
00090                         if ((1<<i) & mask)
00091                         {
00092                                 last = first = i;
00093                                 break;
00094                         }
00095                 }
00096 
00097                 for (; i < 32; i++)
00098                 {
00099                         if ((1<<i) & mask)
00100                                 last = i;
00101                         else if (i < zero)
00102                                 zero = i;
00103                 }
00104 
00105                 // something screwy going on
00106                 if (zero < last) return;
00107 
00108                 // Set it
00109                 format.a_shift = first;
00110                 format.a_loss = 8-(last+1-first);
00111                 format.a_loss16 = format.a_loss+8;
00112                 format.a_mask = mask;
00113         }
00114 }
00115 
00116 
00117 //
00118 // BaseSoftRenderSurface::BaseSoftRenderSurface(int w, int h, int bpp, int rsft, int gsft, int bsft)
00119 //
00120 // Desc: Constructor for Generic BaseSoftRenderSurface
00121 //
00122 BaseSoftRenderSurface::BaseSoftRenderSurface(int w, int h, int bpp, 
00123                                                                                         int rsft, int gsft, int bsft, int asft) :
00124         pixels(0), pixels00(0), zbuffer(0), zbuffer00(0),
00125         bytes_per_pixel(0), bits_per_pixel(0), format_type(0), 
00126         ox(0), oy(0), width(0), height(0), pitch(0), zpitch(0),
00127         flipped(false), clip_window(0,0,0,0), lock_count(0), sdl_surf(0), rtt_tex(0)
00128 {
00129         clip_window.ResizeAbs(width = w, height = h);
00130 
00131         switch (bpp) {
00132                 case 15:
00133                         format.r_loss = 3;
00134                         format.g_loss = 3;
00135                         format.b_loss = 3;
00136                         format.a_loss = 7;
00137                         bpp = 16;
00138                         break;
00139 
00140                 case 16:
00141                         format.r_loss = 3;
00142                         format.g_loss = 2;
00143                         format.b_loss = 3;
00144                         format.a_loss = 0;
00145                         break;
00146 
00147                 case 32:
00148                         format.r_loss = 0;
00149                         format.g_loss = 0;
00150                         format.b_loss = 0;
00151                         format.a_loss = 0;
00152                         break;
00153 
00154                 default:
00155                         break;
00156         }
00157 
00158         pitch = w*bpp/8;
00159         bits_per_pixel = bpp;
00160         bytes_per_pixel = bpp/8;
00161 
00162         RenderSurface::format.s_bpp = bpp;
00163         RenderSurface::format.s_bytes_per_pixel = bytes_per_pixel;
00164         RenderSurface::format.r_loss16 = format.r_loss+8;
00165         RenderSurface::format.g_loss16 = format.g_loss+8;
00166         RenderSurface::format.b_loss16 = format.b_loss+8;
00167         RenderSurface::format.a_loss16 = format.a_loss+8;
00168         RenderSurface::format.r_shift = rsft;
00169         RenderSurface::format.g_shift = gsft;
00170         RenderSurface::format.b_shift = bsft;
00171         RenderSurface::format.a_shift = asft;
00172         RenderSurface::format.r_mask = (0xFF>>format.r_loss)<<rsft;
00173         RenderSurface::format.g_mask = (0xFF>>format.g_loss)<<gsft;
00174         RenderSurface::format.b_mask = (0xFF>>format.b_loss)<<bsft;
00175         RenderSurface::format.a_mask = (0xFF>>format.a_loss)<<asft;
00176 
00177         SetPixelsPointer();
00178 }
00179 
00180 
00181 //
00182 // BaseSoftRenderSurface::BaseSoftRenderSurface(int w, int h, uint8 *buf)
00183 //
00184 // Desc: Constructor for Generic BaseSoftRenderSurface which matches screen params
00185 //
00186 BaseSoftRenderSurface::BaseSoftRenderSurface(int w, int h, uint8 *buf) :
00187         pixels(0), pixels00(0), zbuffer(0), zbuffer00(0),
00188         bytes_per_pixel(0), bits_per_pixel(0), format_type(0), 
00189         ox(0), oy(0), width(0), height(0), pitch(0), zpitch(0),
00190         flipped(false), clip_window(0,0,0,0), lock_count(0), sdl_surf(0), rtt_tex(0)
00191 {
00192         clip_window.ResizeAbs(width = w, height = h);
00193 
00194         int bpp = RenderSurface::format.s_bpp;
00195 
00196         pitch = w*bpp/8;
00197         bits_per_pixel = bpp;
00198         bytes_per_pixel = bpp/8;
00199         pixels00 = buf;
00200 
00201         SetPixelsPointer();
00202 }
00203 
00204 //
00205 // BaseSoftRenderSurface::BaseSoftRenderSurface(int w, int h, uint8 *buf)
00206 //
00207 // Desc: Constructor for Generic BaseSoftRenderSurface which matches screen params
00208 //
00209 BaseSoftRenderSurface::BaseSoftRenderSurface(int w, int h) :
00210         pixels(0), pixels00(0), zbuffer(0), zbuffer00(0),
00211         bytes_per_pixel(0), bits_per_pixel(0), format_type(0), 
00212         ox(0), oy(0), width(0), height(0), pitch(0), zpitch(0),
00213         flipped(false), clip_window(0,0,0,0), lock_count(0), sdl_surf(0), rtt_tex(0)
00214 {
00215         clip_window.ResizeAbs(width = w, height = h);
00216 
00217         int bpp = RenderSurface::format.s_bpp;
00218 
00219         pitch = w*bpp/8;
00220         bits_per_pixel = bpp;
00221         bytes_per_pixel = bpp/8;
00222         pixels00 = new uint8[pitch * height];
00223 
00224         rtt_tex = new Texture;
00225         rtt_tex->buffer = reinterpret_cast<uint32*>(pixels00);
00226         rtt_tex->width = width;
00227         rtt_tex->height = height;
00228         rtt_tex->format = TEX_FMT_NATIVE;
00229         rtt_tex->CalcLOG2s();
00230 
00231         SetPixelsPointer();
00232 }
00233 
00234 
00235 //
00236 // BaseSoftRenderSurface::~BaseSoftRenderSurface()
00237 //
00238 // Desc: Destructor
00239 //
00240 BaseSoftRenderSurface::~BaseSoftRenderSurface()
00241 {
00242         if (rtt_tex)
00243         {
00244                 delete rtt_tex;
00245                 rtt_tex = 0;
00246 
00247                 delete [] pixels00;
00248                 pixels00 = 0;
00249 
00250                 delete [] zbuffer00;
00251                 zbuffer00 = 0;
00252         }
00253 }
00254 
00255 
00256 //
00257 // BaseSoftRenderSurface::BeginPainting()
00258 //
00259 // Desc: Prepare the surface for drawing this frame (in effect lock it for drawing)
00260 // Returns: Non Zero on error
00261 //
00262 ECode BaseSoftRenderSurface::BeginPainting()
00263 {
00264         if (!lock_count) {
00265 
00266                 if (sdl_surf) {
00267 
00268                         // SDL_Surface requires locking
00269                         if (SDL_MUSTLOCK(sdl_surf))
00270                         {
00271                                 // Did the lock fail?
00272                                 if (SDL_LockSurface(sdl_surf)!=0) {
00273                                         pixels = pixels00 = 0;
00274                                         // TODO: SetLastError(GR_SOFT_ERROR_SDL_LOCK_FAILED, "SDL Surface Lock Failed!");
00275                                         perr << "Error: SDL Surface Lock Failed!" << std::endl;
00276                                         return GR_SOFT_ERROR_SDL_LOCK_FAILED;
00277                                 }
00278                         }
00279 
00280                         // Pixels pointer
00281                         pixels00 = static_cast<uint8*>(sdl_surf->pixels);
00282                         pitch = sdl_surf->pitch;
00283                         if (flipped) pitch = -pitch;
00284                 }
00285                 else  {
00286                         ECode ret = GenericLock();
00287                         if (ret.failed()) return ret;
00288                 }
00289         }
00290 
00291         lock_count++;
00292         
00293         if (pixels00 == 0) 
00294         {
00295                 // TODO: SetLastError(GR_SOFT_ERROR_LOCKED_NULL_PIXELS, "Surface Locked with NULL BaseSoftRenderSurface::pixels pointer!");
00296                 perr << "Error: Surface Locked with NULL BaseSoftRenderSurface::pixels pointer!" << std::endl;
00297                 return GR_SOFT_ERROR_LOCKED_NULL_PIXELS;
00298         }
00299 
00300         // Origin offset pointers
00301         SetPixelsPointer();
00302 
00303         // No error
00304         return P_NO_ERROR;
00305 }
00306 
00307 
00308 //
00309 // BaseSoftRenderSurface::EndPainting()
00310 //
00311 // Desc: Prepare the surface for drawing this frame (in effect lock it for drawing)
00312 // Returns: Non Zero on error
00313 //
00314 ECode BaseSoftRenderSurface::EndPainting()
00315 {
00316         // Already Unlocked
00317         if (!lock_count)
00318         {
00319                 // TODO: SetLastError(GR_SOFT_ERROR_BEGIN_END_MISMATCH, "BeginPainting()/EndPainting() Mismatch!");
00320                 perr << "Error: BeginPainting()/EndPainting() Mismatch!" << std::endl;
00321                 return GR_SOFT_ERROR_BEGIN_END_MISMATCH;
00322         }
00323 
00324         // Decrement counter
00325         --lock_count;
00326 
00327         if (!lock_count) { 
00328                 if (sdl_surf) {
00329                         // Unlock the SDL_Surface if required
00330                         if (SDL_MUSTLOCK(sdl_surf)) SDL_UnlockSurface(sdl_surf);
00331 
00332                         // Clear pointers
00333                         pixels=pixels00=0;
00334 
00335                         // Present
00336                         SDL_Flip (sdl_surf);
00337                 }
00338                 else {
00339                         ECode ret = GenericUnlock();
00340                         if (ret.failed()) return ret;
00341                 }
00342         }
00343 
00344         // No error
00345         return P_NO_ERROR;
00346 }
00347 
00348 //
00349 // Texture *BaseSoftRenderSurface::GetSurfaceAsTexture()
00350 //
00351 // Desc: Get the surface as a Texture. Only valid for SecondaryRenderSurfaces
00352 //
00353 Texture *BaseSoftRenderSurface::GetSurfaceAsTexture()
00354 { 
00355         if (!rtt_tex)
00356         {
00357                 perr << "Error: GetSurfaceAsTexture(): Surface doesn't render-to-texture" << std::endl;
00358         }
00359 
00360         return rtt_tex; 
00361 }
00362 
00363 //
00364 // void BaseSoftRenderSurface::CreateNativePalette(Palette* palette)
00365 //
00366 // Desc: Create a palette of colours native to the surface
00367 //
00368 void BaseSoftRenderSurface::CreateNativePalette(Pentagram::Palette* palette)
00369 {
00370         for (int i = 0; i < 256; i++)
00371         {
00372                 sint32 r,g,b;
00373 
00374                 // Normal palette
00375                 palette->native_untransformed[i] = PACK_RGB8(palette->palette[i*3+0],
00376                                                                                                         palette->palette[i*3+1],
00377                                                                                                         palette->palette[i*3+2]);
00378 
00379                 r = palette->matrix[0] * palette->palette[i*3+0] +
00380                         palette->matrix[1] * palette->palette[i*3+1] +
00381                         palette->matrix[2] * palette->palette[i*3+2] +
00382                         palette->matrix[3] * 255;
00383                 if (r < 0) r = 0;
00384                 if (r > 0x7F800) r = 0x7F800;
00385 
00386                 g = palette->matrix[4] * palette->palette[i*3+0] +
00387                         palette->matrix[5] * palette->palette[i*3+1] +
00388                         palette->matrix[6] * palette->palette[i*3+2] +
00389                         palette->matrix[7] * 255;
00390                 if (g < 0) g = 0;
00391                 if (g > 0x7F800) g = 0x7F800;
00392 
00393                 b = palette->matrix[8] * palette->palette[i*3+0] +
00394                         palette->matrix[9] * palette->palette[i*3+1] +
00395                         palette->matrix[10] * palette->palette[i*3+2] +
00396                         palette->matrix[11] * 255;
00397                 if (b < 0) b = 0;
00398                 if (b > 0x7F800) b = 0x7F800;
00399 
00400                 // Transformed normal palette
00401                 // FIXME - Wont work on non SDL SRS Implementations
00402                 palette->native[i] = PACK_RGB8(static_cast<uint8>(r>>11),
00403                                                                                 static_cast<uint8>(g>>11),
00404                                                                                 static_cast<uint8>(b>>11));
00405 
00406                 // Transformed XFORM palette (Uses the TEX32 format)
00407                 if (TEX32_A(palette->xform_untransformed[i]))
00408                 {
00409                         r = palette->matrix[0] * TEX32_R(palette->xform_untransformed[i]) +
00410                                 palette->matrix[1] * TEX32_G(palette->xform_untransformed[i]) +
00411                                 palette->matrix[2] * TEX32_B(palette->xform_untransformed[i]) +
00412                                 palette->matrix[3] * 255;
00413                         if (r < 0) r = 0;
00414                         if (r > 0x7F800) r = 0x7F800;
00415 
00416                         g = palette->matrix[4] * TEX32_R(palette->xform_untransformed[i]) +
00417                                 palette->matrix[5] * TEX32_G(palette->xform_untransformed[i]) +
00418                                 palette->matrix[6] * TEX32_B(palette->xform_untransformed[i]) +
00419                                 palette->matrix[7] * 255;
00420                         if (g < 0) g = 0;
00421                         if (g > 0x7F800) g = 0x7F800;
00422 
00423                         b = palette->matrix[8] * TEX32_R(palette->xform_untransformed[i]) +
00424                                 palette->matrix[9] * TEX32_G(palette->xform_untransformed[i]) +
00425                                 palette->matrix[10] * TEX32_B(palette->xform_untransformed[i]) +
00426                                 palette->matrix[11] * 255;
00427                         if (b < 0) b = 0;
00428                         if (b > 0x7F800) b = 0x7F800;
00429 
00430                         palette->xform[i] = TEX32_PACK_RGBA(static_cast<uint8>(r>>11),
00431                                                                                                 static_cast<uint8>(g>>11),
00432                                                                                                 static_cast<uint8>(b>>11),
00433                                                                 TEX32_A(palette->xform_untransformed[i]));
00434                 }
00435                 else
00436                         palette->xform[i] = 0;
00437         }
00438 }
00439 
00440 //
00441 // void BaseSoftRenderSurface::GetSurfaceDims(Rect &r)
00442 //
00443 // Desc: Get the Surface Dimentions (and logical origin)
00444 // r: Rect object to fill
00445 //
00446 void BaseSoftRenderSurface::GetSurfaceDims(Rect &r) const
00447 {
00448         r.Set(ox, oy, width, height);
00449 }
00450 
00451 //
00452 // void BaseSoftRenderSurface::SetOrigin(sint32 x, sint32 y)
00453 //
00454 // Desc: Set the Phyiscal Pixel to be the logical origin
00455 //
00456 void BaseSoftRenderSurface::SetOrigin(sint32 x, sint32 y)
00457 {
00458         // Adjust the clipping window
00459         clip_window.MoveRel(ox-x, oy-y);
00460 
00461         // Set the origin
00462         ox = x;
00463         oy = y;
00464 
00465         // The new pointers
00466         SetPixelsPointer();
00467 }
00468 
00469 //
00470 // void BaseSoftRenderSurface::GetOrigin(sint32 &x, sint32 &y)
00471 //
00472 // Desc: Get the Phyiscal Pixel that is the logical origin
00473 //
00474 void BaseSoftRenderSurface::GetOrigin(sint32 &x, sint32 &y) const
00475 {
00476         // Set the origin
00477         x = ox;
00478         y = oy;
00479 }
00480 
00481 //
00482 // void BaseSoftRenderSurface::GetClippingRect(Rect &r)
00483 //
00484 // Desc: Get the Clipping Rectangle
00485 // r: Rect object to fill
00486 //
00487 void BaseSoftRenderSurface::GetClippingRect(Rect &r) const
00488 {
00489         r = clip_window;
00490 }
00491 
00492 //
00493 // void BaseSoftRenderSurface::GetClippingRect(Rect &r)
00494 //
00495 // Desc: Set the Clipping Rectangle
00496 // r: Rect object that contains new Clipping Rectangle
00497 //
00498 void BaseSoftRenderSurface::SetClippingRect(const Rect &r)
00499 {
00500         // What we need to do is to clip the clipping rect to the phyiscal screen
00501         clip_window = r;
00502         clip_window.Intersect(-ox,-oy, width, height);
00503 }
00504 
00505 //
00506 // sint16 BaseSoftRenderSurface::CheckClipped(Rect &r)
00507 //
00508 // Desc: Check for a clipped rectangle
00509 // Returns: -1 if off screen, 
00510 //           0 if not clipped, 
00511 //           1 if clipped
00512 //
00513 sint16 BaseSoftRenderSurface::CheckClipped(const Rect &c) const 
00514 {
00515         Rect r = c;
00516         r.Intersect(clip_window);
00517 
00518         // Clipped away to the void
00519         if (!r.IsValid()) return -1;
00520         else if (r == c) return 0;
00521         else return 1;
00522 }
00523 
00524 //
00525 // void BaseSoftRenderSurface::SetFlipped(bool flipped)
00526 //
00527 // Desc: Flip the surface
00528 //
00529 void BaseSoftRenderSurface::SetFlipped(bool wantFlipped)
00530 {
00531         // Flipping is not terrible complex
00532         // But is a bit of a pain to set up
00533 
00534         // First we check to see if we are currently flipped
00535         if (wantFlipped == flipped) return;
00536 
00537         flipped = wantFlipped;
00538 
00539         // What we 'need' to do is negate the pitches, and flip the clipping window
00540         // We keep the 'origin' in the same position relative to the clipping window
00541 
00542         oy -= clip_window.y;
00543         clip_window.y = height - (clip_window.y + clip_window.h);
00544         oy += clip_window.y;
00545 
00546         pitch = -pitch;
00547         zpitch = -zpitch;
00548 
00549         SetPixelsPointer();
00550 
00551 }
00552 
00553 //
00554 // bool BaseSoftRenderSurface::IsFlipped() const
00555 //
00556 // Desc: Has the render surface been flipped?
00557 //
00558 bool BaseSoftRenderSurface::IsFlipped() const
00559 {
00560         return flipped;
00561 }
00562 

Generated on Fri Jul 27 22:27:09 2007 for pentagram by  doxygen 1.4.7