00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00033
00035
00036
00037
00038
00039
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
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
00080 if (!mask) return;
00081
00082
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
00106 if (zero < last) return;
00107
00108
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
00119
00120
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
00183
00184
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
00206
00207
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
00237
00238
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
00258
00259
00260
00261
00262 ECode BaseSoftRenderSurface::BeginPainting()
00263 {
00264 if (!lock_count) {
00265
00266 if (sdl_surf) {
00267
00268
00269 if (SDL_MUSTLOCK(sdl_surf))
00270 {
00271
00272 if (SDL_LockSurface(sdl_surf)!=0) {
00273 pixels = pixels00 = 0;
00274
00275 perr << "Error: SDL Surface Lock Failed!" << std::endl;
00276 return GR_SOFT_ERROR_SDL_LOCK_FAILED;
00277 }
00278 }
00279
00280
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
00296 perr << "Error: Surface Locked with NULL BaseSoftRenderSurface::pixels pointer!" << std::endl;
00297 return GR_SOFT_ERROR_LOCKED_NULL_PIXELS;
00298 }
00299
00300
00301 SetPixelsPointer();
00302
00303
00304 return P_NO_ERROR;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314 ECode BaseSoftRenderSurface::EndPainting()
00315 {
00316
00317 if (!lock_count)
00318 {
00319
00320 perr << "Error: BeginPainting()/EndPainting() Mismatch!" << std::endl;
00321 return GR_SOFT_ERROR_BEGIN_END_MISMATCH;
00322 }
00323
00324
00325 --lock_count;
00326
00327 if (!lock_count) {
00328 if (sdl_surf) {
00329
00330 if (SDL_MUSTLOCK(sdl_surf)) SDL_UnlockSurface(sdl_surf);
00331
00332
00333 pixels=pixels00=0;
00334
00335
00336 SDL_Flip (sdl_surf);
00337 }
00338 else {
00339 ECode ret = GenericUnlock();
00340 if (ret.failed()) return ret;
00341 }
00342 }
00343
00344
00345 return P_NO_ERROR;
00346 }
00347
00348
00349
00350
00351
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
00365
00366
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
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
00401
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
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
00442
00443
00444
00445
00446 void BaseSoftRenderSurface::GetSurfaceDims(Rect &r) const
00447 {
00448 r.Set(ox, oy, width, height);
00449 }
00450
00451
00452
00453
00454
00455
00456 void BaseSoftRenderSurface::SetOrigin(sint32 x, sint32 y)
00457 {
00458
00459 clip_window.MoveRel(ox-x, oy-y);
00460
00461
00462 ox = x;
00463 oy = y;
00464
00465
00466 SetPixelsPointer();
00467 }
00468
00469
00470
00471
00472
00473
00474 void BaseSoftRenderSurface::GetOrigin(sint32 &x, sint32 &y) const
00475 {
00476
00477 x = ox;
00478 y = oy;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 void BaseSoftRenderSurface::GetClippingRect(Rect &r) const
00488 {
00489 r = clip_window;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498 void BaseSoftRenderSurface::SetClippingRect(const Rect &r)
00499 {
00500
00501 clip_window = r;
00502 clip_window.Intersect(-ox,-oy, width, height);
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 sint16 BaseSoftRenderSurface::CheckClipped(const Rect &c) const
00514 {
00515 Rect r = c;
00516 r.Intersect(clip_window);
00517
00518
00519 if (!r.IsValid()) return -1;
00520 else if (r == c) return 0;
00521 else return 1;
00522 }
00523
00524
00525
00526
00527
00528
00529 void BaseSoftRenderSurface::SetFlipped(bool wantFlipped)
00530 {
00531
00532
00533
00534
00535 if (wantFlipped == flipped) return;
00536
00537 flipped = wantFlipped;
00538
00539
00540
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
00555
00556
00557
00558 bool BaseSoftRenderSurface::IsFlipped() const
00559 {
00560 return flipped;
00561 }
00562