From 5742dd7bfaf2fa8ffdb812bbc150826554959c98 Mon Sep 17 00:00:00 2001 From: Tim Goya Date: Wed, 22 Aug 2007 21:17:27 +0000 Subject: [PATCH] Improved SDL_Surface optimizer to handle images that have fairly constant alpha and to pick a color key from knowing what colors are already in the image. Use RLE acceleration and do proper locking. SVN-Revision: 5154 --- src/video/gl_renderer.cpp | 8 ++ src/video/gl_texture.cpp | 8 ++ src/video/sdl_lightmap.cpp | 34 ++++- src/video/sdl_renderer.cpp | 71 +++++++--- src/video/sdl_texture.cpp | 326 ++++++++++++++++++++++++--------------------- 5 files changed, 279 insertions(+), 168 deletions(-) diff --git a/src/video/gl_renderer.cpp b/src/video/gl_renderer.cpp index 9fa6b0310..6fb64803c 100644 --- a/src/video/gl_renderer.cpp +++ b/src/video/gl_renderer.cpp @@ -298,8 +298,16 @@ namespace GL // copy array line-by-line for (int i = 0; i < SCREEN_HEIGHT; i++) { char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1)); + if(SDL_MUSTLOCK(shot_surf)) + { + SDL_LockSurface(shot_surf); + } char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch; memcpy(dst, src, 3 * SCREEN_WIDTH); + if(SDL_MUSTLOCK(shot_surf)) + { + SDL_UnlockSurface(shot_surf); + } } // free array diff --git a/src/video/gl_texture.cpp b/src/video/gl_texture.cpp index e9d72d0ab..413d0ce24 100644 --- a/src/video/gl_texture.cpp +++ b/src/video/gl_texture.cpp @@ -111,9 +111,17 @@ namespace GL glBindTexture(GL_TEXTURE_2D, handle); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, convert->pitch/convert->format->BytesPerPixel); + if(SDL_MUSTLOCK(convert)) + { + SDL_LockSurface(convert); + } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_width, texture_height, 0, sdl_format, GL_UNSIGNED_BYTE, convert->pixels); + if(SDL_MUSTLOCK(convert)) + { + SDL_UnlockSurface(convert); + } assert_gl("creating texture"); diff --git a/src/video/sdl_lightmap.cpp b/src/video/sdl_lightmap.cpp index 040189cdd..d8bdcde7c 100644 --- a/src/video/sdl_lightmap.cpp +++ b/src/video/sdl_lightmap.cpp @@ -112,6 +112,10 @@ namespace SDL if(LIGHTMAP_DIV == 1) { int bpp = screen->format->BytesPerPixel; + if(SDL_MUSTLOCK(screen)) + { + SDL_LockSurface(screen); + } Uint8 *pixel = (Uint8 *) screen->pixels; int loc = 0; for(int y = 0;y < height;y++) { @@ -174,10 +178,18 @@ namespace SDL } pixel += screen->pitch - width * bpp; } + if(SDL_MUSTLOCK(screen)) + { + SDL_UnlockSurface(screen); + } } else { int bpp = screen->format->BytesPerPixel; + if(SDL_MUSTLOCK(screen)) + { + SDL_LockSurface(screen); + } Uint8 *div_pixel = (Uint8 *) screen->pixels; int loc = 0; for(int y = 0;y < height;y++) { @@ -281,6 +293,10 @@ namespace SDL } div_pixel += (screen->pitch - width * bpp) * LIGHTMAP_DIV; } + if(SDL_MUSTLOCK(screen)) + { + SDL_UnlockSurface(screen); + } } } @@ -293,6 +309,10 @@ namespace SDL int blit_width = src_rect->w / LIGHTMAP_DIV; int blit_height = src_rect->h / LIGHTMAP_DIV; int bpp = src->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } Uint8 *pixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp; int loc = dsty * width + dstx; for(int y = 0;y < blit_height;y++) { @@ -351,12 +371,20 @@ namespace SDL pixel += (src->pitch - blit_width * bpp) * LIGHTMAP_DIV; loc += width - blit_width; } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } } /*void Lightmap::light_blit(SDL_Surface *src, SDL_Rect *src_rect, int dstx, int dsty) { int bpp = src->format->BytesPerPixel; - Uint8 *pixel = (Uint8 *) src->pixels + src_rect->y * src->pitch + src_rect->x * bpp; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + Uint8 *pixel = (Uint8 *) src->pixels + src_rect->y * src->pitch + src_rect->x * bpp; int loc = dsty * width + dstx; for(int y = 0;y < src_rect->h;y++) { for(int x = 0;x < src_rect->w;x++, pixel += bpp, loc++) { @@ -414,6 +442,10 @@ namespace SDL pixel += src->pitch - src_rect->w * bpp; loc += width - src_rect->w; } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } }*/ void diff --git a/src/video/sdl_renderer.cpp b/src/video/sdl_renderer.cpp index 6e8797c6a..fecf7ea73 100644 --- a/src/video/sdl_renderer.cpp +++ b/src/video/sdl_renderer.cpp @@ -52,6 +52,14 @@ namespace int alpha = (int) (alpha_factor * 256); 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); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; @@ -106,6 +114,14 @@ namespace } } } + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } return dst; } } @@ -212,11 +228,11 @@ namespace SDL { if(alpha == 255) { - SDL_SetAlpha(transform, 0, 0); + SDL_SetAlpha(transform, SDL_RLEACCEL, 0); } else { - SDL_SetAlpha(transform, SDL_SRCALPHA, alpha); + SDL_SetAlpha(transform, SDL_SRCALPHA | SDL_RLEACCEL, alpha); } } /*else @@ -275,26 +291,45 @@ namespace SDL dst_rect.y = (int) request.pos.y * numerator / denominator; Uint8 alpha = 0; - if(!(transform->flags & SDL_SRCALPHA)) - { - alpha = 255; - SDL_SetAlpha(transform, SDL_SRCALPHA, (Uint8) (request.alpha * 255)); - } - else if(!transform->format->Amask) + if(request.alpha != 1.0) { - alpha = transform->format->alpha; - SDL_SetAlpha(transform, SDL_SRCALPHA, (Uint8) (request.alpha * alpha)); + if(!transform->format->Amask) + { + if(transform->flags & SDL_SRCALPHA) + { + alpha = transform->format->alpha; + } + else + { + alpha = 255; + } + SDL_SetAlpha(transform, SDL_SRCALPHA, (Uint8) (request.alpha * alpha)); + } + /*else + { + transform = apply_alpha(transform, request.alpha); + }*/ } SDL_BlitSurface(transform, &src_rect, screen, &dst_rect); - if(alpha == 255) - { - SDL_SetAlpha(transform, 0, 0); - } - else if(!transform->format->Amask) + if(request.alpha != 1.0) { - SDL_SetAlpha(transform, SDL_SRCALPHA, alpha); + if(!transform->format->Amask) + { + if(alpha == 255) + { + SDL_SetAlpha(transform, SDL_RLEACCEL, 0); + } + else + { + SDL_SetAlpha(transform, SDL_SRCALPHA | SDL_RLEACCEL, alpha); + } + } + /*else + { + SDL_FreeSurface(transform); + }*/ } } @@ -326,7 +361,7 @@ namespace SDL SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); SDL_FillRect(temp, 0, color); - SDL_SetAlpha(temp, SDL_SRCALPHA, a); + SDL_SetAlpha(temp, SDL_SRCALPHA | SDL_RLEACCEL, a); SDL_BlitSurface(temp, 0, screen, &rect); SDL_FreeSurface(temp); } @@ -364,7 +399,7 @@ namespace SDL SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); SDL_FillRect(temp, 0, color); - SDL_SetAlpha(temp, SDL_SRCALPHA, a); + SDL_SetAlpha(temp, SDL_SRCALPHA | SDL_RLEACCEL, a); SDL_BlitSurface(temp, 0, screen, &rect); SDL_FreeSurface(temp); } diff --git a/src/video/sdl_texture.cpp b/src/video/sdl_texture.cpp index 56eeb1179..a536ad3b4 100644 --- a/src/video/sdl_texture.cpp +++ b/src/video/sdl_texture.cpp @@ -44,6 +44,14 @@ namespace { 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); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { Uint8 *srcpixel = (Uint8 *) src->pixels + (y * denominator / numerator) * src->pitch + (x * denominator / numerator) * bpp; @@ -60,15 +68,23 @@ namespace } } } + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } if(!src->format->Amask) { if(src->flags & SDL_SRCALPHA) { - SDL_SetAlpha(dst, SDL_SRCALPHA, src->format->alpha); + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); } if(src->flags & SDL_SRCCOLORKEY) { - SDL_SetColorKey(dst, SDL_SRCCOLORKEY, src->format->colorkey); + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); } } return dst; @@ -134,6 +150,14 @@ namespace { 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); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { int srcx = x * denominator / numerator; @@ -175,146 +199,23 @@ namespace } } } - if(!src->format->Amask) + if(SDL_MUSTLOCK(dst)) { - if(src->flags & SDL_SRCALPHA) - { - SDL_SetAlpha(dst, SDL_SRCALPHA, src->format->alpha); - } - if(src->flags & SDL_SRCCOLORKEY) - { - SDL_SetColorKey(dst, SDL_SRCCOLORKEY, src->format->colorkey); - } + SDL_UnlockSurface(dst); } - return dst; - } - } -#endif - - // FIXME: Horizontal and vertical line problem -#ifdef BRESENHAM - void accumulate(SDL_Surface *src, int srcx, int srcy, int color[4], int weight) - { - if(srcx < 0 || srcy < 0 || weight == 0) { - return; - } - int bpp = src->format->BytesPerPixel; - Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp; - Uint32 mapped = 0; - switch(bpp) { - case 1: - mapped = *srcpixel; - break; - case 2: - mapped = *(Uint16 *)srcpixel; - break; - case 3: -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - mapped |= srcpixel[0] << 16; - mapped |= srcpixel[1] << 8; - mapped |= srcpixel[2] << 0; -#else - mapped |= srcpixel[0] << 0; - mapped |= srcpixel[1] << 8; - mapped |= srcpixel[2] << 16; -#endif - break; - case 4: - mapped = *(Uint32 *)srcpixel; - break; - } - Uint8 red, green, blue, alpha; - SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); - color[0] += red * weight; - color[1] += green * weight; - color[2] += blue * weight; - color[3] += alpha * weight; - } - - void accumulate_line(SDL_Surface *src, int srcy, int line[][4], int linesize, int weight, int numerator, int denominator) - { - int intpart = denominator / numerator; - int fractpart = denominator % numerator; - for(int x = 0, xe = 0, srcx = 0;x < linesize;x++) { - accumulate(src, srcx, srcy, line[x], (numerator - xe) * weight); - srcx++; - for(int i = 0;i < intpart - 1;i++) { - accumulate(src, srcx, srcy, line[x], numerator * weight); - srcx++; - } - xe += fractpart; - if(xe >= numerator) { - xe -= numerator; - srcx++; - } - accumulate(src, srcx, srcy, line[x], xe * weight); - } - } - - SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator) - { - if(numerator == denominator) - { - src->refcount++; - return src; - } - else - { - 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); - int bpp = dst->format->BytesPerPixel; - int intpart = denominator / numerator; - int fractpart = denominator % numerator; - for(int y = 0, ye = 0, srcy = 0;y < dst->h;y++) { - int line[dst->w][4]; - memset(line, 0, sizeof(int) * dst->w * 4); - accumulate_line(src, srcy, line, dst->w, numerator - ye, numerator, denominator); - srcy++; - for(int i = 0;i < intpart - 1;i++) { - accumulate_line(src, srcy, line, dst->w, numerator, numerator, denominator); - srcy++; - } - ye += fractpart; - if(ye >= numerator) { - ye -= numerator; - srcy++; - } - accumulate_line(src, srcy, line, dst->w, ye, numerator, denominator); - for(int x = 0;x < dst->w;x++) { - Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp; - Uint32 mapped = SDL_MapRGBA(dst->format, line[x][0] / (denominator * denominator), line[x][1] / (denominator * denominator), line[x][2] / (denominator * denominator), line[x][3] / (denominator * denominator)); - switch(bpp) { - case 1: - *dstpixel = mapped; - break; - case 2: - *(Uint16 *)dstpixel = mapped; - break; - case 3: -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - dstpixel[0] = (mapped >> 16) & 0xff; - dstpixel[1] = (mapped >> 8) & 0xff; - dstpixel[2] = (mapped >> 0) & 0xff; -#else - dstpixel[0] = (mapped >> 0) & 0xff; - dstpixel[1] = (mapped >> 8) & 0xff; - dstpixel[2] = (mapped >> 16) & 0xff; -#endif - break; - case 4: - *(Uint32 *)dstpixel = mapped; - break; - } - } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); } if(!src->format->Amask) { if(src->flags & SDL_SRCALPHA) { - SDL_SetAlpha(dst, SDL_SRCALPHA, src->format->alpha); + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); } if(src->flags & SDL_SRCCOLORKEY) { - SDL_SetColorKey(dst, SDL_SRCCOLORKEY, src->format->colorkey); + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); } } return dst; @@ -326,6 +227,14 @@ namespace { 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); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; @@ -342,15 +251,23 @@ namespace } } } + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } if(!src->format->Amask) { if(src->flags & SDL_SRCALPHA) { - SDL_SetAlpha(dst, SDL_SRCALPHA, src->format->alpha); + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); } if(src->flags & SDL_SRCCOLORKEY) { - SDL_SetColorKey(dst, SDL_SRCCOLORKEY, src->format->colorkey); + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); } } return dst; @@ -360,6 +277,14 @@ namespace { 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); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; @@ -376,15 +301,23 @@ namespace } } } + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } if(!src->format->Amask) { if(src->flags & SDL_SRCALPHA) { - SDL_SetAlpha(dst, SDL_SRCALPHA, src->format->alpha); + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); } if(src->flags & SDL_SRCCOLORKEY) { - SDL_SetColorKey(dst, SDL_SRCCOLORKEY, src->format->colorkey); + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); } } return dst; @@ -399,6 +332,14 @@ namespace int blue = (int) (color.blue * 256); 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); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; @@ -456,15 +397,23 @@ namespace } } } + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } if(!src->format->Amask) { if(src->flags & SDL_SRCALPHA) { - SDL_SetAlpha(dst, SDL_SRCALPHA, src->format->alpha); + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); } if(src->flags & SDL_SRCCOLORKEY) { - SDL_SetColorKey(dst, SDL_SRCCOLORKEY, src->format->colorkey); + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); } } return dst; @@ -478,12 +427,18 @@ namespace } else { - int opaque = 0; int transparent = 0; + int opaque = 0; int semitransparent = 0; - std::set colors; + int alphasum = 0; + bool colors[(1 << 12)]; + memset(colors, 0, (1 << 12) * sizeof(bool)); int bpp = src->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } for(int y = 0;y < src->h;y++) { for(int x = 0;x < src->w;x++) { Uint8 *pixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; @@ -512,30 +467,91 @@ namespace } Uint8 red, green, blue, alpha; SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); - if(alpha < 32) + if(alpha < 16) { transparent++; } - else if (alpha > 224) + else if (alpha > 240) { opaque++; + alphasum += alpha; } else { semitransparent++; + alphasum += alpha; } - colors.insert(((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0) >> 4)); + colors[((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0) >> 4)] = true; } } - if(semitransparent > ((opaque + transparent + semitransparent) / 8)) + int avgalpha = (opaque + semitransparent) ? alphasum / (opaque + semitransparent) : 0; + int alphavariance = 0; + for(int y = 0;y < src->h;y++) { + for(int x = 0;x < src->w;x++) { + Uint8 *pixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; + Uint32 mapped = 0; + switch(bpp) { + case 1: + mapped = *pixel; + break; + case 2: + mapped = *(Uint16 *)pixel; + break; + case 3: +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + mapped |= pixel[0] << 16; + mapped |= pixel[1] << 8; + mapped |= pixel[2] << 0; +#else + mapped |= pixel[0] << 0; + mapped |= pixel[1] << 8; + mapped |= pixel[2] << 16; +#endif + break; + case 4: + mapped = *(Uint32 *)pixel; + break; + } + Uint8 red, green, blue, alpha; + SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); + if(alpha >= 16) + { + alphavariance += (alpha - avgalpha) * (alpha - avgalpha); + } + } + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } + alphavariance /= (opaque + semitransparent) ? (opaque + semitransparent) : 1; + if(semitransparent > ((transparent + opaque + semitransparent) / 8) && alphavariance > 16) + { + return SDL_DisplayFormatAlpha(src); + } + int keycolor = -1; + for(int i = 0;i < (1 << 12);i++) + { + if(!colors[i]) + { + keycolor = i; + } + } + if(keycolor == -1) { - // FIXME: try to approximate textures that have a fairly constant alpha return SDL_DisplayFormatAlpha(src); } - // FIXME: pick a color key by examining "colors" SDL_Surface *dst = SDL_CreateRGBSurface(src->flags & ~(SDL_SRCALPHA), src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, 0); bpp = dst->format->BytesPerPixel; - Uint32 key = SDL_MapRGB(dst->format, 0xff, 0x00, 0xff); + Uint32 key = SDL_MapRGB(dst->format, (((keycolor & 0xf00) >> 4) | 0xf), ((keycolor & 0xf0) | 0xf), (((keycolor & 0xf) << 4) | 0xf)); + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; @@ -565,7 +581,7 @@ namespace } Uint8 red, green, blue, alpha; SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); - if(alpha < 64) + if(alpha < (avgalpha / 4)) { mapped = key; } @@ -597,7 +613,19 @@ namespace } } } - SDL_SetColorKey(dst, SDL_SRCCOLORKEY, key); + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } + if(avgalpha < 240) + { + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, avgalpha); + } + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, key); SDL_Surface *convert = SDL_DisplayFormat(dst); SDL_FreeSurface(dst); return convert; -- 2.11.0