#include <config.h>
#include "supertux/gameconfig.hpp"
#include "supertux/globals.hpp"
#include "video/color.hpp"
#include "video/sdl/sdl_texture.hpp"
#include "util/log.hpp"
#include "math/random_generator.hpp"
#include <assert.h>
#include <SDL.h>
Go to the source code of this file.
Defines | |
#define | BILINEAR |
Functions | |
static Uint32 | get_pixel_mapping (SDL_Surface *src, void *pixel) |
static Uint32 | get_random_color (SDL_Surface *src) |
static bool | color_is_used (SDL_Surface *src, Uint32 color) |
static Uint32 | get_unused_color (SDL_Surface *src) |
void | getpixel (SDL_Surface *src, int srcx, int srcy, Uint8 color[4]) |
void | merge (Uint8 color[4], Uint8 color0[4], Uint8 color1[4], int rem, int total) |
SDL_Surface * | scale (SDL_Surface *src, int numerator, int denominator) |
SDL_Surface * | horz_flip (SDL_Surface *src) |
SDL_Surface * | vert_flip (SDL_Surface *src) |
SDL_Surface * | colorize (SDL_Surface *src, const Color &color) |
SDL_Surface * | optimize (SDL_Surface *src) |
Optimizes a SDL_Surface surface and returns it in the "display format". |
#define BILINEAR |
Definition at line 31 of file sdl_texture.cpp.
static bool @525::color_is_used | ( | SDL_Surface * | src, | |
Uint32 | color | |||
) | [static] |
Definition at line 99 of file sdl_texture.cpp.
References get_pixel_mapping().
Referenced by get_unused_color().
00100 { 00101 if(SDL_MUSTLOCK(src)) 00102 SDL_LockSurface(src); 00103 00104 for(int y = 0; y < src->h; y++) { 00105 for(int x = 0; x < src->w; x++) { 00106 Uint8 *pixel = (Uint8 *) src->pixels 00107 + (y * src->pitch) + (x * src->format->BytesPerPixel); 00108 Uint32 mapped = get_pixel_mapping (src, pixel); 00109 00110 if (color == mapped) 00111 return (true); 00112 } 00113 } 00114 00115 return (false); 00116 } /* bool color_is_used */
SDL_Surface* @525::colorize | ( | SDL_Surface * | src, | |
const Color & | color | |||
) | [static] |
Definition at line 399 of file sdl_texture.cpp.
References Color::blue, Color::green, and Color::red.
Referenced by SDLTexture::get_transform().
00400 { 00401 // FIXME: This is really slow 00402 assert(color.red != 1.0 || color.green != 1.0 || color.blue != 1.0); 00403 int red = (int) (color.red * 256); 00404 int green = (int) (color.green * 256); 00405 int blue = (int) (color.blue * 256); 00406 SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); 00407 int bpp = dst->format->BytesPerPixel; 00408 if(SDL_MUSTLOCK(src)) 00409 { 00410 SDL_LockSurface(src); 00411 } 00412 if(SDL_MUSTLOCK(dst)) 00413 { 00414 SDL_LockSurface(dst); 00415 } 00416 for(int y = 0;y < dst->h;y++) { 00417 for(int x = 0;x < dst->w;x++) { 00418 Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; 00419 Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp; 00420 Uint32 mapped = 0; 00421 switch(bpp) { 00422 case 1: 00423 mapped = *srcpixel; 00424 break; 00425 case 2: 00426 mapped = *(Uint16 *)srcpixel; 00427 break; 00428 case 3: 00429 #if SDL_BYTEORDER == SDL_BIG_ENDIAN 00430 mapped |= srcpixel[0] << 16; 00431 mapped |= srcpixel[1] << 8; 00432 mapped |= srcpixel[2] << 0; 00433 #else 00434 mapped |= srcpixel[0] << 0; 00435 mapped |= srcpixel[1] << 8; 00436 mapped |= srcpixel[2] << 16; 00437 #endif 00438 break; 00439 case 4: 00440 mapped = *(Uint32 *)srcpixel; 00441 break; 00442 } 00443 if(src->format->Amask || !(src->flags & SDL_SRCCOLORKEY) || mapped != src->format->colorkey) 00444 { 00445 Uint8 r, g, b, a; 00446 SDL_GetRGBA(mapped, src->format, &r, &g, &b, &a); 00447 mapped = SDL_MapRGBA(dst->format, (r * red) >> 8, (g * green) >> 8, (b * blue) >> 8, a); 00448 } 00449 switch(bpp) { 00450 case 1: 00451 *dstpixel = mapped; 00452 break; 00453 case 2: 00454 *(Uint16 *)dstpixel = mapped; 00455 break; 00456 case 3: 00457 #if SDL_BYTEORDER == SDL_BIG_ENDIAN 00458 dstpixel[0] = (mapped >> 16) & 0xff; 00459 dstpixel[1] = (mapped >> 8) & 0xff; 00460 dstpixel[2] = (mapped >> 0) & 0xff; 00461 #else 00462 dstpixel[0] = (mapped >> 0) & 0xff; 00463 dstpixel[1] = (mapped >> 8) & 0xff; 00464 dstpixel[2] = (mapped >> 16) & 0xff; 00465 #endif 00466 break; 00467 case 4: 00468 *(Uint32 *)dstpixel = mapped; 00469 break; 00470 } 00471 } 00472 } 00473 if(SDL_MUSTLOCK(dst)) 00474 { 00475 SDL_UnlockSurface(dst); 00476 } 00477 if(SDL_MUSTLOCK(src)) 00478 { 00479 SDL_UnlockSurface(src); 00480 } 00481 if(!src->format->Amask) 00482 { 00483 if(src->flags & SDL_SRCALPHA) 00484 { 00485 SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); 00486 } 00487 if(src->flags & SDL_SRCCOLORKEY) 00488 { 00489 SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); 00490 } 00491 } 00492 return dst; 00493 }
static Uint32 @525::get_pixel_mapping | ( | SDL_Surface * | src, | |
void * | pixel | |||
) | [static] |
Definition at line 33 of file sdl_texture.cpp.
References log_warning.
Referenced by color_is_used(), getpixel(), and optimize().
00034 { 00035 Uint32 mapped = 0; 00036 00037 switch (src->format->BytesPerPixel) 00038 { 00039 case 1: 00040 mapped = *((Uint8 *) pixel); 00041 break; 00042 case 2: 00043 mapped = *((Uint16 *) pixel); 00044 break; 00045 case 3: 00046 { 00047 Uint8 *tmp = (Uint8 *) pixel; 00048 #if SDL_BYTEORDER == SDL_BIG_ENDIAN 00049 mapped |= tmp[0] << 16; 00050 mapped |= tmp[1] << 8; 00051 mapped |= tmp[2] << 0; 00052 #else 00053 mapped |= tmp[0] << 0; 00054 mapped |= tmp[1] << 8; 00055 mapped |= tmp[2] << 16; 00056 #endif 00057 break; 00058 } 00059 case 4: 00060 mapped = *((Uint32 *) pixel); 00061 break; 00062 00063 default: 00064 log_warning << "Unknown BytesPerPixel value: " 00065 << src->format->BytesPerPixel << std::endl; 00066 mapped = 0; 00067 } /* switch (bpp) */ 00068 00069 return (mapped); 00070 } /* Uint32 get_pixel_mapping */
static Uint32 @525::get_random_color | ( | SDL_Surface * | src | ) | [static] |
Definition at line 72 of file sdl_texture.cpp.
References graphicsRandom, and RandomGenerator::rand().
Referenced by get_unused_color().
00073 { 00074 Uint32 r; 00075 00076 r = (Uint32) graphicsRandom.rand (); 00077 /* rand() returns 31bit random numbers. So call it twice to get full 32 bit. */ 00078 r <<= 1; 00079 r |= (Uint32) graphicsRandom.rand (); 00080 00081 switch (src->format->BytesPerPixel) 00082 { 00083 case 1: 00084 r &= 0x000000ff; 00085 break; 00086 00087 case 2: 00088 r &= 0x0000ffff; 00089 break; 00090 00091 case 3: 00092 r &= 0x0000ffff; 00093 break; 00094 } 00095 00096 return (r); 00097 } /* Uint32 get_random_color */
static Uint32 @525::get_unused_color | ( | SDL_Surface * | src | ) | [static] |
Definition at line 118 of file sdl_texture.cpp.
References color_is_used(), and get_random_color().
Referenced by optimize().
00119 { 00120 Uint32 random_color; 00121 00122 do 00123 { 00124 random_color = get_random_color (src); 00125 } while (color_is_used (src, random_color)); 00126 00127 return (random_color); 00128 } /* Uint32 get_unused_color */
void @525::getpixel | ( | SDL_Surface * | src, | |
int | srcx, | |||
int | srcy, | |||
Uint8 | color[4] | |||
) | [static] |
Definition at line 191 of file sdl_texture.cpp.
References get_pixel_mapping().
Referenced by scale().
00192 { 00193 int bpp = src->format->BytesPerPixel; 00194 if(srcx == src->w) 00195 { 00196 srcx--; 00197 } 00198 if(srcy == src->h) 00199 { 00200 srcy--; 00201 } 00202 Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp; 00203 Uint32 mapped = get_pixel_mapping (src, srcpixel); 00204 SDL_GetRGBA(mapped, src->format, &color[0], &color[1], &color[2], &color[3]); 00205 }
SDL_Surface* @525::horz_flip | ( | SDL_Surface * | src | ) | [static] |
Definition at line 299 of file sdl_texture.cpp.
Referenced by SDLTexture::get_transform().
00300 { 00301 SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); 00302 int bpp = dst->format->BytesPerPixel; 00303 if(SDL_MUSTLOCK(src)) 00304 { 00305 SDL_LockSurface(src); 00306 } 00307 if(SDL_MUSTLOCK(dst)) 00308 { 00309 SDL_LockSurface(dst); 00310 } 00311 for(int y = 0;y < dst->h;y++) { 00312 for(int x = 0;x < dst->w;x++) { 00313 Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; 00314 Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + (dst->w - x - 1) * bpp; 00315 switch(bpp) { 00316 case 4: 00317 dstpixel[3] = srcpixel[3]; 00318 case 3: 00319 dstpixel[2] = srcpixel[2]; 00320 case 2: 00321 dstpixel[1] = srcpixel[1]; 00322 case 1: 00323 dstpixel[0] = srcpixel[0]; 00324 } 00325 } 00326 } 00327 if(SDL_MUSTLOCK(dst)) 00328 { 00329 SDL_UnlockSurface(dst); 00330 } 00331 if(SDL_MUSTLOCK(src)) 00332 { 00333 SDL_UnlockSurface(src); 00334 } 00335 if(!src->format->Amask) 00336 { 00337 if(src->flags & SDL_SRCALPHA) 00338 { 00339 SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); 00340 } 00341 if(src->flags & SDL_SRCCOLORKEY) 00342 { 00343 SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); 00344 } 00345 } 00346 return dst; 00347 }
void @525::merge | ( | Uint8 | color[4], | |
Uint8 | color0[4], | |||
Uint8 | color1[4], | |||
int | rem, | |||
int | total | |||
) | [static] |
Definition at line 207 of file sdl_texture.cpp.
Referenced by SDLLightmap::do_draw(), and scale().
00208 { 00209 color[0] = (color0[0] * (total - rem) + color1[0] * rem) / total; 00210 color[1] = (color0[1] * (total - rem) + color1[1] * rem) / total; 00211 color[2] = (color0[2] * (total - rem) + color1[2] * rem) / total; 00212 color[3] = (color0[3] * (total - rem) + color1[3] * rem) / total; 00213 }
SDL_Surface* @525::optimize | ( | SDL_Surface * | src | ) | [static] |
Optimizes a SDL_Surface surface and returns it in the "display format".
If the surface does not have an alpha channel, simply calls "SDL_DisplayFormat". If the surface has an alpha channel, examines all the pixels. If in fact semi-transparent pixels are found, calls "SDL_DisplayFormatAlpha". If only fully transparent and fully opaque pixels are found, converts the surface to a 1-bit alpha surface with "SDL_SetColorKey".
Definition at line 502 of file sdl_texture.cpp.
References TinyGetText::convert(), get_pixel_mapping(), and get_unused_color().
Referenced by SDLTexture::SDLTexture().
00503 { 00504 bool have_transparent = false; 00505 bool have_semi_trans = false; 00506 bool have_opaque = false; 00507 00508 if(!src->format->Amask) 00509 return SDL_DisplayFormat(src); 00510 00511 if(SDL_MUSTLOCK(src)) 00512 SDL_LockSurface(src); 00513 00514 /* Iterate over all the pixels and record which ones we found. */ 00515 for(int y = 0; y < src->h; y++) { 00516 for(int x = 0; x < src->w; x++) { 00517 Uint8 *pixel = (Uint8 *) src->pixels 00518 + (y * src->pitch) + (x * src->format->BytesPerPixel); 00519 Uint32 mapped = get_pixel_mapping (src, pixel); 00520 Uint8 red, green, blue, alpha; 00521 SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); 00522 00523 if (alpha < 16) 00524 have_transparent = true; 00525 else if (alpha > 240) 00526 have_opaque = true; 00527 else 00528 have_semi_trans = true; 00529 } /* for (x) */ 00530 } /* for (y) */ 00531 00532 if(SDL_MUSTLOCK(src)) 00533 SDL_UnlockSurface(src); 00534 00535 if (have_semi_trans) 00536 return SDL_DisplayFormatAlpha(src); 00537 00538 if (!have_transparent /* && !have_semi_trans */) 00539 return SDL_DisplayFormat(src); 00540 00541 /* The surface is totally transparent. We shouldn't return a surface at all, 00542 * but since the calling code can't cope with that, use the alpha channel in 00543 * this case. */ 00544 if (!have_opaque /* && !have_semi_trans */) 00545 return SDL_DisplayFormatAlpha(src); 00546 00547 /* If we get here, the surface has fully transparent pixels and fully opaque 00548 * pixels, but no semi-transparent pixels. We can therefore use a one bit 00549 * transparency, which is pretty fast to draw. This code path is a bit bulky 00550 * and rarely used (~25 surfaces when starting the game and entering a 00551 * level), so it could be removed for readabilities sake. -octo */ 00552 00553 /* Create a new surface without alpha channel */ 00554 SDL_Surface *dst = SDL_CreateRGBSurface(src->flags & ~(SDL_SRCALPHA), 00555 src->w, src->h, src->format->BitsPerPixel, 00556 src->format->Rmask, src->format->Gmask, src->format->Bmask, /* Amask = */ 0); 00557 /* Get a color that's not in the source surface. It is used to mark 00558 * transparent pixels. There's a possible race condition: Maybe we should 00559 * lock the surface before calling this function and add a "bool have_lock" 00560 * argument to "get_unused_color"? -octo */ 00561 Uint32 color_key = get_unused_color (src); 00562 00563 if(SDL_MUSTLOCK(src)) 00564 SDL_LockSurface(src); 00565 if(SDL_MUSTLOCK(dst)) 00566 SDL_LockSurface(dst); 00567 00568 /* Copy all the pixels to the new surface */ 00569 for(int y = 0; y < src->h; y++) { 00570 for(int x = 0; x < src->w; x++) { 00571 Uint8 *src_pixel = (Uint8 *) src->pixels 00572 + (y * src->pitch) + (x * src->format->BytesPerPixel); 00573 Uint8 *dst_pixel = (Uint8 *) dst->pixels 00574 + (y * dst->pitch) + (x * dst->format->BytesPerPixel); 00575 Uint32 mapped = get_pixel_mapping (src, src_pixel); 00576 Uint8 red, green, blue, alpha; 00577 SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); 00578 00579 /* "alpha" should either be smaller than 16 or greater than 240. We 00580 * unlocked the surface in between though, so use 128 to play it save, 00581 * i.e. don't leave any unspecified code paths. */ 00582 if (alpha < 128) 00583 mapped = color_key; 00584 00585 switch (dst->format->BytesPerPixel) 00586 { 00587 case 1: 00588 *dst_pixel = (Uint8) mapped; 00589 break; 00590 00591 case 2: 00592 *((Uint16 *) dst_pixel) = (Uint16) mapped; 00593 break; 00594 00595 case 3: 00596 #if SDL_BYTEORDER == SDL_BIG_ENDIAN 00597 dst_pixel[0] = (mapped >> 16) & 0xff; 00598 dst_pixel[1] = (mapped >> 8) & 0xff; 00599 dst_pixel[2] = (mapped >> 0) & 0xff; 00600 #else 00601 dst_pixel[0] = (mapped >> 0) & 0xff; 00602 dst_pixel[1] = (mapped >> 8) & 0xff; 00603 dst_pixel[2] = (mapped >> 16) & 0xff; 00604 #endif 00605 break; 00606 00607 case 4: 00608 *((Uint32 *) dst_pixel) = mapped; 00609 } /* switch (dst->format->BytesPerPixel) */ 00610 } /* for (x) */ 00611 } /* for (y) */ 00612 00613 if(SDL_MUSTLOCK(src)) 00614 SDL_UnlockSurface(src); 00615 if(SDL_MUSTLOCK(dst)) 00616 SDL_UnlockSurface(dst); 00617 00618 /* Tell SDL that the "color_key" color is supposed to be transparent. */ 00619 SDL_SetColorKey (dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, color_key); 00620 SDL_Surface *convert = SDL_DisplayFormat(dst); 00621 SDL_FreeSurface(dst); 00622 return convert; 00623 } /* SDL_Surface *optimize */
SDL_Surface* @525::scale | ( | SDL_Surface * | src, | |
int | numerator, | |||
int | denominator | |||
) | [static] |
Definition at line 215 of file sdl_texture.cpp.
References getpixel(), and merge().
Referenced by GLRenderer::apply_config(), and SDLTexture::SDLTexture().
00216 { 00217 if(numerator == denominator) 00218 { 00219 src->refcount++; 00220 return src; 00221 } 00222 else 00223 { 00224 SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); 00225 int bpp = dst->format->BytesPerPixel; 00226 if(SDL_MUSTLOCK(src)) 00227 { 00228 SDL_LockSurface(src); 00229 } 00230 if(SDL_MUSTLOCK(dst)) 00231 { 00232 SDL_LockSurface(dst); 00233 } 00234 for(int y = 0;y < dst->h;y++) { 00235 for(int x = 0;x < dst->w;x++) { 00236 int srcx = x * denominator / numerator; 00237 int srcy = y * denominator / numerator; 00238 Uint8 color00[4], color01[4], color10[4], color11[4]; 00239 getpixel(src, srcx, srcy, color00); 00240 getpixel(src, srcx + 1, srcy, color01); 00241 getpixel(src, srcx, srcy + 1, color10); 00242 getpixel(src, srcx + 1, srcy + 1, color11); 00243 Uint8 color0[4], color1[4], color[4]; 00244 int remx = x * denominator % numerator; 00245 merge(color0, color00, color01, remx, numerator); 00246 merge(color1, color10, color11, remx, numerator); 00247 int remy = y * denominator % numerator; 00248 merge(color, color0, color1, remy, numerator); 00249 Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp; 00250 Uint32 mapped = SDL_MapRGBA(dst->format, color[0], color[1], color[2], color[3]); 00251 switch(bpp) { 00252 case 1: 00253 *dstpixel = mapped; 00254 break; 00255 case 2: 00256 *(Uint16 *)dstpixel = mapped; 00257 break; 00258 case 3: 00259 #if SDL_BYTEORDER == SDL_BIG_ENDIAN 00260 dstpixel[0] = (mapped >> 16) & 0xff; 00261 dstpixel[1] = (mapped >> 8) & 0xff; 00262 dstpixel[2] = (mapped >> 0) & 0xff; 00263 #else 00264 dstpixel[0] = (mapped >> 0) & 0xff; 00265 dstpixel[1] = (mapped >> 8) & 0xff; 00266 dstpixel[2] = (mapped >> 16) & 0xff; 00267 #endif 00268 break; 00269 case 4: 00270 *(Uint32 *)dstpixel = mapped; 00271 break; 00272 } 00273 } 00274 } 00275 if(SDL_MUSTLOCK(dst)) 00276 { 00277 SDL_UnlockSurface(dst); 00278 } 00279 if(SDL_MUSTLOCK(src)) 00280 { 00281 SDL_UnlockSurface(src); 00282 } 00283 if(!src->format->Amask) 00284 { 00285 if(src->flags & SDL_SRCALPHA) 00286 { 00287 SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); 00288 } 00289 if(src->flags & SDL_SRCCOLORKEY) 00290 { 00291 SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); 00292 } 00293 } 00294 return dst; 00295 } 00296 }
SDL_Surface* @525::vert_flip | ( | SDL_Surface * | src | ) | [static] |
Definition at line 349 of file sdl_texture.cpp.
Referenced by SDLTexture::get_transform().
00350 { 00351 SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); 00352 int bpp = dst->format->BytesPerPixel; 00353 if(SDL_MUSTLOCK(src)) 00354 { 00355 SDL_LockSurface(src); 00356 } 00357 if(SDL_MUSTLOCK(dst)) 00358 { 00359 SDL_LockSurface(dst); 00360 } 00361 for(int y = 0;y < dst->h;y++) { 00362 for(int x = 0;x < dst->w;x++) { 00363 Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; 00364 Uint8 *dstpixel = (Uint8 *) dst->pixels + (dst->h - y - 1) * dst->pitch + x * bpp; 00365 switch(bpp) { 00366 case 4: 00367 dstpixel[3] = srcpixel[3]; 00368 case 3: 00369 dstpixel[2] = srcpixel[2]; 00370 case 2: 00371 dstpixel[1] = srcpixel[1]; 00372 case 1: 00373 dstpixel[0] = srcpixel[0]; 00374 } 00375 } 00376 } 00377 if(SDL_MUSTLOCK(dst)) 00378 { 00379 SDL_UnlockSurface(dst); 00380 } 00381 if(SDL_MUSTLOCK(src)) 00382 { 00383 SDL_UnlockSurface(src); 00384 } 00385 if(!src->format->Amask) 00386 { 00387 if(src->flags & SDL_SRCALPHA) 00388 { 00389 SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); 00390 } 00391 if(src->flags & SDL_SRCCOLORKEY) 00392 { 00393 SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); 00394 } 00395 } 00396 return dst; 00397 }