src/video/sdl/sdl_texture.cpp File Reference

#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_Surfacescale (SDL_Surface *src, int numerator, int denominator)
SDL_Surfacehorz_flip (SDL_Surface *src)
SDL_Surfacevert_flip (SDL_Surface *src)
SDL_Surfacecolorize (SDL_Surface *src, const Color &color)
SDL_Surfaceoptimize (SDL_Surface *src)
 Optimizes a SDL_Surface surface and returns it in the "display format".


Define Documentation

#define BILINEAR

Definition at line 31 of file sdl_texture.cpp.


Function Documentation

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 }


Generated on Mon Jun 9 03:38:27 2014 for SuperTux by  doxygen 1.5.1