diff options
-rw-r--r-- | src/video/SDL_RLEaccel.c | 1 | ||||
-rw-r--r-- | src/video/SDL_blit.c | 10 | ||||
-rw-r--r-- | src/video/SDL_blit.h | 58 | ||||
-rw-r--r-- | src/video/SDL_blit_slow.c | 139 | ||||
-rw-r--r-- | src/video/SDL_blit_slow.h | 26 | ||||
-rw-r--r-- | src/video/SDL_surface.c | 27 |
6 files changed, 227 insertions, 34 deletions
diff --git a/src/video/SDL_RLEaccel.c b/src/video/SDL_RLEaccel.c index 88827fbf8f..e8a7a5fa1e 100644 --- a/src/video/SDL_RLEaccel.c +++ b/src/video/SDL_RLEaccel.c @@ -1819,6 +1819,7 @@ SDL_RLESurface(SDL_Surface * surface) /* Pass on combinations not supported */ if ((flags & SDL_COPY_MODULATE_COLOR) || + ((flags & SDL_COPY_MODULATE_ALPHA) && surface->format->Amask) || (flags & (SDL_COPY_ADD | SDL_COPY_MOD)) || (flags & SDL_COPY_NEAREST)) { return -1; diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c index 7bb0729a82..3eb348a434 100644 --- a/src/video/SDL_blit.c +++ b/src/video/SDL_blit.c @@ -26,6 +26,7 @@ #include "SDL_blit.h" #include "SDL_blit_auto.h" #include "SDL_blit_copy.h" +#include "SDL_blit_slow.h" #include "SDL_RLEaccel_c.h" #include "SDL_pixels_c.h" @@ -269,6 +270,15 @@ SDL_CalculateBlit(SDL_Surface * surface) SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags, SDL_GeneratedBlitFuncTable); } +#ifndef TEST_SLOW_BLIT + if (blit == NULL) +#endif + { + if (surface->format->BytesPerPixel > 1 + && dst->format->BytesPerPixel > 1) { + blit = SDL_Blit_Slow; + } + } map->data = blit; /* Make sure we have a blit function */ diff --git a/src/video/SDL_blit.h b/src/video/SDL_blit.h index b5c0920e43..3e0caa9423 100644 --- a/src/video/SDL_blit.h +++ b/src/video/SDL_blit.h @@ -165,7 +165,7 @@ do { \ \ case 3: { \ Uint8 *B = (Uint8 *)(buf); \ - if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ Pixel = B[0] + (B[1] << 8) + (B[2] << 16); \ } else { \ Pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \ @@ -178,38 +178,42 @@ do { \ break; \ \ default: \ - Pixel = 0; /* appease gcc */ \ + Pixel; /* stop gcc complaints */ \ break; \ } \ -} while(0) +} while (0) #define DISEMBLE_RGB(buf, bpp, fmt, Pixel, r, g, b) \ do { \ switch (bpp) { \ case 2: \ Pixel = *((Uint16 *)(buf)); \ + RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \ break; \ \ - case 3: { \ - Uint8 *B = (Uint8 *)buf; \ - if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ - Pixel = B[0] + (B[1] << 8) + (B[2] << 16); \ + case 3: { \ + if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + r = *((buf)+fmt->Rshift/8); \ + g = *((buf)+fmt->Gshift/8); \ + b = *((buf)+fmt->Bshift/8); \ } else { \ - Pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \ + r = *((buf)+2-fmt->Rshift/8); \ + g = *((buf)+2-fmt->Gshift/8); \ + b = *((buf)+2-fmt->Bshift/8); \ } \ } \ break; \ \ case 4: \ Pixel = *((Uint32 *)(buf)); \ + RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \ break; \ \ - default: \ - Pixel = 0; /* prevent gcc from complaining */ \ + default: \ + Pixel; /* stop gcc complaints */ \ break; \ } \ - RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \ -} while(0) +} while (0) /* Assemble R-G-B values into a specified pixel format and store them */ #define PIXEL_FROM_RGB(Pixel, fmt, r, g, b) \ @@ -242,7 +246,7 @@ do { \ break; \ \ case 3: { \ - if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ *((buf)+fmt->Rshift/8) = r; \ *((buf)+fmt->Gshift/8) = g; \ *((buf)+fmt->Bshift/8) = b; \ @@ -277,7 +281,7 @@ do { \ break; \ \ case 3: { \ - if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ *((buf)+fmt->Rshift/8) = r; \ *((buf)+fmt->Gshift/8) = g; \ *((buf)+fmt->Bshift/8) = b; \ @@ -342,29 +346,33 @@ do { \ switch (bpp) { \ case 2: \ Pixel = *((Uint16 *)(buf)); \ + RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \ break; \ \ - case 3: {/* FIXME: broken code (no alpha) */ \ - Uint8 *b = (Uint8 *)buf; \ - if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ - Pixel = b[0] + (b[1] << 8) + (b[2] << 16); \ + case 3: { \ + if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + r = *((buf)+fmt->Rshift/8); \ + g = *((buf)+fmt->Gshift/8); \ + b = *((buf)+fmt->Bshift/8); \ } else { \ - Pixel = (b[0] << 16) + (b[1] << 8) + b[2]; \ + r = *((buf)+2-fmt->Rshift/8); \ + g = *((buf)+2-fmt->Gshift/8); \ + b = *((buf)+2-fmt->Bshift/8); \ } \ + a = 0xFF; \ } \ break; \ \ case 4: \ Pixel = *((Uint32 *)(buf)); \ + RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \ break; \ \ default: \ - Pixel = 0; /* stop gcc complaints */ \ + Pixel; /* stop gcc complaints */ \ break; \ } \ - RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \ - Pixel &= ~fmt->Amask; \ -} while(0) +} while (0) /* FIXME: this isn't correct, especially for Alpha (maximum != 255) */ #define PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a) \ @@ -385,8 +393,8 @@ do { \ } \ break; \ \ - case 3: { /* FIXME: broken code (no alpha) */ \ - if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + case 3: { \ + if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ *((buf)+fmt->Rshift/8) = r; \ *((buf)+fmt->Gshift/8) = g; \ *((buf)+fmt->Bshift/8) = b; \ diff --git a/src/video/SDL_blit_slow.c b/src/video/SDL_blit_slow.c index 33affc5b3d..74319ec1a6 100644 --- a/src/video/SDL_blit_slow.c +++ b/src/video/SDL_blit_slow.c @@ -27,5 +27,144 @@ /* The ONE TRUE BLITTER * This puppy has to handle all the unoptimized cases - yes, it's slow. */ +void +SDL_Blit_Slow(SDL_BlitInfo * info) +{ + const int flags = info->flags; + const Uint32 modulateR = info->r; + const Uint32 modulateG = info->g; + const Uint32 modulateB = info->b; + const Uint32 modulateA = info->a; + Uint32 srcpixel; + Uint32 srcR, srcG, srcB, srcA; + Uint32 dstpixel; + Uint32 dstR, dstG, dstB, dstA; + int srcy, srcx; + int posy, posx; + int incy, incx; + SDL_PixelFormat *src_fmt = info->src_fmt; + SDL_PixelFormat *dst_fmt = info->dst_fmt; + int srcbpp = src_fmt->BytesPerPixel; + int dstbpp = dst_fmt->BytesPerPixel; + + srcy = 0; + posy = 0; + incy = (info->src_h << 16) / info->dst_h; + incx = (info->src_w << 16) / info->dst_w; + + while (info->dst_h--) { + Uint8 *src; + Uint8 *dst = (Uint8 *) info->dst; + int n = info->dst_w; + srcx = -1; + posx = 0x10000L; + while (posy >= 0x10000L) { + ++srcy; + posy -= 0x10000L; + } + while (n--) { + if (posx >= 0x10000L) { + while (posx >= 0x10000L) { + ++srcx; + posx -= 0x10000L; + } + src = + (info->src + (srcy * info->src_pitch) + (srcx * srcbpp)); + } + if (src_fmt->Amask) { + DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG, + srcB, srcA); + } else { + DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG, + srcB); + srcA = 0xFF; + } + if (flags & SDL_COPY_COLORKEY) { + /* srcpixel isn't set for 24 bpp */ + if (srcbpp == 24) { + srcpixel = (srcR << src_fmt->Rshift) | + (srcG << src_fmt->Gshift) | (srcB << src_fmt->Bshift); + } + if (srcpixel == info->colorkey) { + posx += incx; + dst += dstbpp; + continue; + } + } + if (dst_fmt->Amask) { + DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, + dstB, dstA); + } else { + DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, + dstB); + dstA = 0xFF; + } + + if (flags & SDL_COPY_MODULATE_COLOR) { + srcR = (srcR * modulateR) / 255; + srcG = (srcG * modulateG) / 255; + srcB = (srcB * modulateB) / 255; + } + if (flags & SDL_COPY_MODULATE_ALPHA) { + srcA = (srcA * modulateA) / 255; + } + if (flags & (SDL_COPY_BLEND | SDL_COPY_ADD)) { + /* This goes away if we ever use premultiplied alpha */ + if (srcA < 255) { + srcR = (srcR * srcA) / 255; + srcG = (srcG * srcA) / 255; + srcB = (srcB * srcA) / 255; + } + } + switch (flags & + (SDL_COPY_MASK | SDL_COPY_BLEND | SDL_COPY_ADD | + SDL_COPY_MOD)) { + case 0: + dstR = srcR; + dstG = srcG; + dstB = srcB; + dstA = srcA; + break; + case SDL_COPY_MASK: + if (srcA) { + dstR = srcR; + dstG = srcG; + dstB = srcB; + } + break; + case SDL_COPY_BLEND: + dstR = srcR + ((255 - srcA) * dstR) / 255; + dstG = srcG + ((255 - srcA) * dstG) / 255; + dstB = srcB + ((255 - srcA) * dstB) / 255; + break; + case SDL_COPY_ADD: + dstR = srcR + dstR; + if (dstR > 255) + dstR = 255; + dstG = srcG + dstG; + if (dstG > 255) + dstG = 255; + dstB = srcB + dstB; + if (dstB > 255) + dstB = 255; + break; + case SDL_COPY_MOD: + dstR = (srcR * dstR) / 255; + dstG = (srcG * dstG) / 255; + dstB = (srcB * dstB) / 255; + break; + } + if (dst_fmt->Amask) { + ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA); + } else { + ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB); + } + posx += incx; + dst += dstbpp; + } + posy += incy; + info->dst += info->dst_pitch; + } +} /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_blit_slow.h b/src/video/SDL_blit_slow.h new file mode 100644 index 0000000000..14bfd3b368 --- /dev/null +++ b/src/video/SDL_blit_slow.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +extern void SDL_Blit_Slow(SDL_BlitInfo * info); + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 902223b3e3..09a6903933 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -336,6 +336,7 @@ SDL_ConvertColorkeyToAlpha(SDL_Surface * surface) SDL_UnlockSurface(surface); SDL_SetColorKey(surface, 0, 0); + SDL_SetSurfaceBlendMode(surface, SDL_TEXTUREBLENDMODE_BLEND); } int @@ -808,7 +809,16 @@ SDL_ConvertSurface(SDL_Surface * surface, SDL_PixelFormat * format, SDL_LowerBlit(surface, &bounds, convert, &bounds); /* Clean up the original surface, and update converted surface */ - SDL_SetClipRect(convert, &surface->clip_rect); + convert->map->info.r = surface->map->info.r; + convert->map->info.g = surface->map->info.g; + convert->map->info.b = surface->map->info.b; + convert->map->info.a = surface->map->info.a; + convert->map->info.flags = + (copy_flags & + ~(SDL_COPY_COLORKEY | SDL_COPY_BLEND + | SDL_COPY_RLE_DESIRED | SDL_COPY_RLE_COLORKEY | + SDL_COPY_RLE_ALPHAKEY)); + surface->map->info.flags = copy_flags; if (copy_flags & SDL_COPY_COLORKEY) { Uint8 keyR, keyG, keyB, keyA; @@ -816,21 +826,20 @@ SDL_ConvertSurface(SDL_Surface * surface, SDL_PixelFormat * format, &keyG, &keyB, &keyA); SDL_SetColorKey(convert, 1, SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA)); + /* This is needed when converting for 3D texture upload */ SDL_ConvertColorkeyToAlpha(convert); } - convert->map->info.r = surface->map->info.r; - convert->map->info.g = surface->map->info.g; - convert->map->info.b = surface->map->info.b; - convert->map->info.a = surface->map->info.a; - convert->map->info.flags = copy_flags; - surface->map->info.flags = copy_flags; + SDL_SetClipRect(convert, &surface->clip_rect); /* Enable alpha blending by default if the new surface has an * alpha channel or alpha modulation */ - if (format->Amask || (copy_flags & SDL_COPY_MODULATE_ALPHA)) { + if ((surface->format->Amask && format->Amask) || + (copy_flags & SDL_COPY_MODULATE_ALPHA)) { SDL_SetSurfaceBlendMode(convert, SDL_TEXTUREBLENDMODE_BLEND); } - SDL_SetSurfaceRLE(convert, (flags & SDL_RLEACCEL)); + if ((copy_flags & SDL_COPY_RLE_DESIRED) || (flags & SDL_RLEACCEL)) { + SDL_SetSurfaceRLE(convert, SDL_RLEACCEL); + } /* We're ready to go! */ return (convert); |