summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video/SDL_RLEaccel.c1
-rw-r--r--src/video/SDL_blit.c10
-rw-r--r--src/video/SDL_blit.h58
-rw-r--r--src/video/SDL_blit_slow.c139
-rw-r--r--src/video/SDL_blit_slow.h26
-rw-r--r--src/video/SDL_surface.c27
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);