More work in progress integrating SDL_Surface and the new SDL_Texture API
authorSam Lantinga <slouken@libsdl.org>
Sat, 18 Aug 2007 01:44:21 +0000
changeset 2266 e61ad15a205f
parent 2265 265bb136af92
child 2267 c785543d1843
More work in progress integrating SDL_Surface and the new SDL_Texture API
include/SDL_compat.h
include/SDL_video.h
src/SDL_compat.c
src/video/SDL_RLEaccel.c
src/video/SDL_blit.c
src/video/SDL_blit.h
src/video/SDL_surface.c
src/video/SDL_video.c
--- a/include/SDL_compat.h	Fri Aug 17 06:58:20 2007 +0000
+++ b/include/SDL_compat.h	Sat Aug 18 01:44:21 2007 +0000
@@ -37,6 +37,8 @@
 #endif
 
 #define SDL_SWSURFACE       0x00000000  /* Not used */
+//#define SDL_SRCALPHA        0x00010000
+//#define SDL_SRCCOLORKEY     0x00020000
 #define SDL_ANYFORMAT       0x00100000
 #define SDL_HWPALETTE       0x00200000
 #define SDL_DOUBLEBUF       0x00400000
@@ -146,6 +148,8 @@
 extern DECLSPEC void SDLCALL SDL_UpdateRect(SDL_Surface * screen, Sint32 x,
                                             Sint32 y, Uint32 w, Uint32 h);
 extern DECLSPEC int SDLCALL SDL_Flip(SDL_Surface * screen);
+extern DECLSPEC int SDLCALL SDL_SetAlpha(SDL_Surface * surface, Uint32 flag,
+                                         Uint8 alpha);
 extern DECLSPEC SDL_Surface *SDLCALL SDL_DisplayFormat(SDL_Surface * surface);
 extern DECLSPEC SDL_Surface *SDLCALL SDL_DisplayFormatAlpha(SDL_Surface *
                                                             surface);
--- a/include/SDL_video.h	Fri Aug 17 06:58:20 2007 +0000
+++ b/include/SDL_video.h	Sat Aug 18 01:44:21 2007 +0000
@@ -265,10 +265,7 @@
 /* These are the currently supported flags for the SDL_surface */
 /* Used internally (read-only) */
 #define SDL_PREALLOC        0x00000001  /* Surface uses preallocated memory */
-#define SDL_SRCALPHA        0x00000004  /* Blit uses source alpha blending */
-#define SDL_SRCCOLORKEY     0x00000008  /* Blit uses a source color key */
-#define SDL_RLEACCELOK      0x00000010  /* Private flag */
-#define SDL_RLEACCEL        0x00000020  /* Surface is RLE encoded */
+#define SDL_RLEACCEL        0x00000001  /* Surface is RLE encoded */
 
 /* Evaluates to true if the surface needs to be locked before access */
 #define SDL_MUSTLOCK(S)	(((S)->flags & SDL_RLEACCEL) != 0)
@@ -1401,34 +1398,157 @@
 		SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1)
 
 /*
- * Sets the color key (transparent pixel) in a blittable surface.
- * If 'flag' is SDL_SRCCOLORKEY (optionally OR'd with SDL_RLEACCEL), 
- * 'key' will be the transparent pixel in the source image of a blit.
- * SDL_RLEACCEL requests RLE acceleration for the surface if present,
- * and removes RLE acceleration if absent.
- * If 'flag' is 0, this function clears any current color key.
- * This function returns 0, or -1 if there was an error.
+ * \fn int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag)
+ *
+ * \brief Sets the RLE acceleration hint for a surface.
+ *
+ * \return 0 on success, or -1 if the surface is not valid
+ *
+ * \note If RLE is enabled, colorkey and alpha blending blits are much faster,
+ *       but the surface must be locked before directly accessing the pixels.
  */
-extern DECLSPEC int SDLCALL SDL_SetColorKey
-    (SDL_Surface * surface, Uint32 flag, Uint32 key);
+extern DECLSPEC int SDLCALL SDL_SetSurfaceRLE(SDL_Surface *surface, int flag);
 
 /*
- * This function sets the alpha value for the entire surface, as opposed to
- * using the alpha component of each pixel. This value measures the range
- * of transparency of the surface, 0 being completely transparent to 255
- * being completely opaque. An 'alpha' value of 255 causes blits to be
- * opaque, the source pixels copied to the destination (the default). Note
- * that per-surface alpha can be combined with colorkey transparency.
+ * \fn int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key)
+ *
+ * \brief Sets the color key (transparent pixel) in a blittable surface.
+ *
+ * \param surface The surface to update
+ * \param flag Non-zero to enable colorkey and 0 to disable colorkey 
+ * \param key The transparent pixel in the native surface format
+ *
+ * \return 0 on success, or -1 if the surface is not valid
+ */
+extern DECLSPEC int SDLCALL SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
+
+/**
+ * \fn int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b)
+ *
+ * \brief Set an additional color value used in blit operations
+ *
+ * \param surface The surface to update
+ * \param r The red source color value multiplied into blit operations
+ * \param g The green source color value multiplied into blit operations
+ * \param b The blue source color value multiplied into blit operations
+ *
+ * \return 0 on success, or -1 if the surface is not valid
+ *
+ * \sa SDL_GetSurfaceColorMod()
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface,
+                                                   Uint8 r, Uint8 g, Uint8 b);
+
+
+/**
+ * \fn int SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 *r, Uint8 *g, Uint8 *b)
+ *
+ * \brief Get the additional color value used in blit operations
+ *
+ * \param surface The surface to query
+ * \param r A pointer filled in with the source red color value
+ * \param g A pointer filled in with the source green color value
+ * \param b A pointer filled in with the source blue color value
+ *
+ * \return 0 on success, or -1 if the surface is not valid
+ *
+ * \sa SDL_SetSurfaceColorMod()
+ */
+extern DECLSPEC int SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface,
+                                                   Uint8 * r, Uint8 * g,
+                                                   Uint8 * b);
+
+/**
+ * \fn int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha)
+ *
+ * \brief Set an additional alpha value used in blit operations
+ *
+ * \param surface The surface to update
+ * \param alpha The source alpha value multiplied into blit operations.
+ *
+ * \return 0 on success, or -1 if the surface is not valid
+ *
+ * \sa SDL_GetSurfaceAlphaMod()
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface *surface,
+                                                   Uint8 alpha);
+
+/**
+ * \fn int SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 *alpha)
+ *
+ * \brief Get the additional alpha value used in blit operations
  *
- * If 'flag' is 0, alpha blending is disabled for the surface.
- * If 'flag' is SDL_SRCALPHA, alpha blending is enabled for the surface.
- * OR:ing the flag with SDL_RLEACCEL requests RLE acceleration for the
- * surface; if SDL_RLEACCEL is not specified, the RLE accel will be removed.
+ * \param surface The surface to query
+ * \param alpha A pointer filled in with the source alpha value
+ *
+ * \return 0 on success, or -1 if the surface is not valid
+ *
+ * \sa SDL_SetSurfaceAlphaMod()
+ */
+extern DECLSPEC int SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface,
+                                                   Uint8 * alpha);
+
+/**
+ * \fn int SDL_SetSurfaceBlendMode(SDL_Surface *surface, int blendMode)
+ *
+ * \brief Set the blend mode used for blit operations
+ *
+ * \param surface The surface to update
+ * \param blendMode SDL_TextureBlendMode to use for blit blending
+ *
+ * \return 0 on success, or -1 if the parameters are not valid
+ *
+ * \sa SDL_GetSurfaceBlendMode()
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface *surface,
+                                                    int blendMode);
+
+/**
+ * \fn int SDL_GetSurfaceBlendMode(SDL_Surface *surface, int *blendMode)
+ *
+ * \brief Get the blend mode used for blit operations
+ *
+ * \param surface The surface to query
+ * \param blendMode A pointer filled in with the current blend mode
+ *
+ * \return 0 on success, or -1 if the surface is not valid
  *
- * The 'alpha' parameter is ignored for surfaces that have an alpha channel.
+ * \sa SDL_SetSurfaceBlendMode()
  */
-extern DECLSPEC int SDLCALL SDL_SetAlpha(SDL_Surface * surface, Uint32 flag,
-                                         Uint8 alpha);
+extern DECLSPEC int SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface,
+                                                    int *blendMode);
+
+/**
+ * \fn int SDL_SetSurfaceScaleMode(SDL_Surface *surface, int scaleMode)
+ *
+ * \brief Set the scale mode used for blit operations
+ *
+ * \param surface The surface to update
+ * \param scaleMode SDL_TextureScaleMode to use for blit scaling
+ *
+ * \return 0 on success, or -1 if the surface is not valid or the scale mode is not supported
+ *
+ * \note If the scale mode is not supported, the closest supported mode is chosen.  Currently only SDL_TEXTURESCALEMODE_FAST is supported on surfaces.
+ *
+ * \sa SDL_GetSurfaceScaleMode()
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceScaleMode(SDL_Surface *surface,
+                                                    int scaleMode);
+
+/**
+ * \fn int SDL_GetSurfaceScaleMode(SDL_Surface *surface, int *scaleMode)
+ *
+ * \brief Get the scale mode used for blit operations
+ *
+ * \param surface The surface to query
+ * \param scaleMode A pointer filled in with the current scale mode
+ *
+ * \return 0 on success, or -1 if the surface is not valid
+ *
+ * \sa SDL_SetSurfaceScaleMode()
+ */
+extern DECLSPEC int SDLCALL SDL_GetSurfaceScaleMode(SDL_Surface *surface,
+                                                    int *scaleMode);
 
 /*
  * Sets the clipping rectangle for the destination surface in a blit.
--- a/src/SDL_compat.c	Fri Aug 17 06:58:20 2007 +0000
+++ b/src/SDL_compat.c	Sat Aug 18 01:44:21 2007 +0000
@@ -589,6 +589,22 @@
     return SDL_PublicSurface;
 }
 
+int
+SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value)
+{
+    if (flag & SDL_RLEACCEL) {
+        SDL_SetSurfaceRLE(surface, 1);
+    }
+    if (flag) {
+        SDL_SetSurfaceAlphaMod(surface, value);
+        SDL_SetSurfaceBlendMode(surface, SDL_TEXTUREBLENDMODE_BLEND);
+    } else {
+        SDL_SetSurfaceAlphaMod(surface, 0xFF);
+        SDL_SetSurfaceBlendMode(surface, SDL_TEXTUREBLENDMODE_NONE);
+    }
+    return 0;
+}
+
 SDL_Surface *
 SDL_DisplayFormat(SDL_Surface * surface)
 {
@@ -600,15 +616,7 @@
     }
 
     /* Set the flags appropriate for copying to display surface */
-    flags = SDL_SWSURFACE;
-#ifdef AUTORLE_DISPLAYFORMAT
-    flags |= (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA));
-    flags |= SDL_RLEACCELOK;
-#else
-    flags |=
-        surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_RLEACCELOK);
-#endif
-    return SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags);
+    return SDL_ConvertSurface(surface, SDL_PublicSurface->format, SDL_RLEACCELOK);
 }
 
 SDL_Surface *
@@ -658,8 +666,7 @@
         break;
     }
     format = SDL_AllocFormat(32, rmask, gmask, bmask, amask);
-    flags = surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
-    converted = SDL_ConvertSurface(surface, format, flags);
+    converted = SDL_ConvertSurface(surface, format, SDL_RLEACCELOK);
     SDL_FreeFormat(format);
     return converted;
 }
--- a/src/video/SDL_RLEaccel.c	Fri Aug 17 06:58:20 2007 +0000
+++ b/src/video/SDL_RLEaccel.c	Sat Aug 18 01:44:21 2007 +0000
@@ -905,8 +905,7 @@
         }
     }
 
-    alpha = (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA
-        ? src->map->info.a : 255;
+    alpha = src->map->info.a;
     /* if left or right edge clipping needed, call clip blit */
     if (srcrect->x || srcrect->w != src->w) {
         RLEClipBlit(w, srcbuf, dst, dstbuf, srcrect, alpha);
@@ -1803,7 +1802,7 @@
 int
 SDL_RLESurface(SDL_Surface * surface)
 {
-    int retcode;
+    int flags;
 
     /* Clear any previous RLE conversion */
     if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
@@ -1812,35 +1811,45 @@
 
     /* We don't support RLE encoding of bitmaps */
     if (surface->format->BitsPerPixel < 8) {
-        return (-1);
+        return -1;
     }
 
-    /* Lock the surface if it's in hardware */
-    if (SDL_MUSTLOCK(surface)) {
-        if (SDL_LockSurface(surface) < 0) {
-            return (-1);
-        }
+    /* Make sure the pixels are available */
+    if (!surface->pixels) {
+        return -1;
+    }
+
+    /* If we don't have colorkey or blending, nothing to do... */
+    flags = surface->map->info.flags;
+    if(!(flags & (SDL_COPY_COLORKEY|SDL_COPY_BLEND))) {
+        return -1;
     }
 
-    /* Encode */
-    if ((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
-        retcode = RLEColorkeySurface(surface);
-    } else {
-        if ((surface->flags & SDL_SRCALPHA) == SDL_SRCALPHA
-            && surface->format->Amask != 0)
-            retcode = RLEAlphaSurface(surface);
-        else
-            retcode = -1;       /* no RLE for per-surface alpha sans ckey */
+    /* Pass on combinations not supported */
+    if ((flags & SDL_COPY_MODULATE_COLOR) ||
+        (flags & (SDL_COPY_ADD|SDL_COPY_MOD)) ||
+        (flags & SDL_COPY_NEAREST)) {
+        return -1;
     }
 
-    /* Unlock the surface if it's in hardware */
-    if (SDL_MUSTLOCK(surface)) {
-        SDL_UnlockSurface(surface);
+    /* Encode and set up the blit */
+    if (!surface->format->Amask || !(flags & SDL_COPY_BLEND)) {
+        if (!surface->map->identity) {
+            return -1;
+        }
+        if (RLEColorkeySurface(surface) < 0) {
+            return -1;
+        }
+        surface->map->blit = SDL_RLEBlit;
+        surface->map->info.flags |= SDL_COPY_RLE_COLORKEY;
+    } else {
+        if (RLEAlphaSurface(surface) < 0) {
+            return -1;
+        }
+        surface->map->blit = SDL_RLEAlphaBlit;
+        surface->map->info.flags |= SDL_COPY_RLE_ALPHAKEY;
     }
 
-    if (retcode < 0)
-        return -1;
-
     /* The surface is now accelerated */
     surface->flags |= SDL_RLEACCEL;
 
@@ -1931,13 +1940,12 @@
 void
 SDL_UnRLESurface(SDL_Surface * surface, int recode)
 {
-    if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
+    if (surface->flags & SDL_RLEACCEL) {
         surface->flags &= ~SDL_RLEACCEL;
 
         if (recode && !(surface->flags & SDL_PREALLOC)) {
-            if ((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
+            if (surface->map->info.flags & SDL_COPY_RLE_COLORKEY) {
                 SDL_Rect full;
-                unsigned alpha_flag;
 
                 /* re-create the original surface */
                 surface->pixels = SDL_malloc(surface->h * surface->pitch);
@@ -1954,10 +1962,7 @@
                 full.x = full.y = 0;
                 full.w = surface->w;
                 full.h = surface->h;
-                alpha_flag = surface->flags & SDL_SRCALPHA;
-                surface->flags &= ~SDL_SRCALPHA;        /* opaque blit */
                 SDL_RLEBlit(surface, &full, surface, &full);
-                surface->flags |= alpha_flag;
             } else {
                 if (!UnRLEAlpha(surface)) {
                     /* Oh crap... */
@@ -1966,8 +1971,9 @@
                 }
             }
         }
+        surface->map->info.flags &= (SDL_COPY_RLE_COLORKEY|SDL_COPY_RLE_ALPHAKEY);
 
-        if (surface->map && surface->map->data) {
+        if (surface->map->data) {
             SDL_free(surface->map->data);
             surface->map->data = NULL;
         }
--- a/src/video/SDL_blit.c	Fri Aug 17 06:58:20 2007 +0000
+++ b/src/video/SDL_blit.c	Sat Aug 18 01:44:21 2007 +0000
@@ -206,7 +206,8 @@
 SDL_CalculateBlit(SDL_Surface * surface)
 {
     SDL_BlitFunc blit = NULL;
-    SDL_Surface *dst = surface->map->dst;
+    SDL_BlitMap *map = surface->map;
+    SDL_Surface *dst = map->dst;
     Uint32 src_format;
     Uint32 dst_format;
 
@@ -214,67 +215,48 @@
     if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
         SDL_UnRLESurface(surface, 1);
     }
-    surface->map->blit = NULL;
-    surface->map->info.src_fmt = surface->format;
-    surface->map->info.src_pitch = surface->pitch;
-    surface->map->info.dst_fmt = dst->format;
-    surface->map->info.dst_pitch = dst->pitch;
+    map->blit = SDL_SoftBlit;
+    map->info.src_fmt = surface->format;
+    map->info.src_pitch = surface->pitch;
+    map->info.dst_fmt = dst->format;
+    map->info.dst_pitch = dst->pitch;
 
+    /* See if we can do RLE acceleration */
+    if (surface->flags & SDL_RLEACCELOK) {
+        if (SDL_RLESurface(surface) == 0) {
+            return 0;
+        }
+    }
+
+    /* Choose a standard blit function */
     src_format = SDL_MasksToPixelFormatEnum(surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask);
     dst_format = SDL_MasksToPixelFormatEnum(dst->format->BitsPerPixel, dst->format->Rmask, dst->format->Gmask, dst->format->Bmask, dst->format->Amask);
 
-    /* Check for special "identity" case -- copy blit */
-    if (surface->map->identity && !surface->map->info.flags) {
+    if (map->identity && !map->info.flags) {
         /* Handle overlapping blits on the same surface */
         if (surface == dst) {
             blit = SDL_BlitCopyOverlap;
         } else {
             blit = SDL_BlitCopy;
         }
+    } else if (surface->format->BitsPerPixel < 8) {
+        blit = SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags, SDL_BlitFuncTable0);
+    } else if (surface->format->BytesPerPixel == 1) {
+        blit = SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags, SDL_BlitFuncTable1);
     } else {
-        if (surface->format->BitsPerPixel < 8) {
-            blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_BlitFuncTable0);
-        } else {
-            switch (surface->format->BytesPerPixel) {
-            case 1:
-                blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_BlitFuncTable1);
-                break;
-            case 2:
-            case 3:
-            case 4:
-                blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_BlitFuncTableN);
-                break;
-            }
-        }
+        blit = SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags, SDL_BlitFuncTableN);
     }
     if (blit == NULL) {
-        blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_GeneratedBlitFuncTable);
+        blit = SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags, SDL_GeneratedBlitFuncTable);
     }
 
     /* Make sure we have a blit function */
     if (blit == NULL) {
-        SDL_InvalidateMap(surface->map);
+        SDL_InvalidateMap(map);
         SDL_SetError("Blit combination not supported");
         return (-1);
     }
 
-    /* Choose software blitting function */
-    if ((surface->flags & SDL_RLEACCELOK) && !(surface->map->flags & () {
-        if (surface->map->identity && (surface->map->flags & SDL_COPY_COLORKEY)
-            && (blit_index == 1
-                || (blit_index == 3 && !surface->format->Amask))) {
-            if (SDL_RLESurface(surface) == 0)
-                surface->map->blit = SDL_RLEBlit;
-        } else if (blit_index == 2 && surface->format->Amask) {
-            if (SDL_RLESurface(surface) == 0)
-                surface->map->blit = SDL_RLEAlphaBlit;
-        }
-    }
-
-    if (surface->map->blit == NULL) {
-        surface->map->blit = SDL_SoftBlit;
-        surface->map->data = blit;
-    }
     return (0);
 }
 
--- a/src/video/SDL_blit.h	Fri Aug 17 06:58:20 2007 +0000
+++ b/src/video/SDL_blit.h	Sat Aug 18 01:44:21 2007 +0000
@@ -41,23 +41,26 @@
 #include "SDL_endian.h"
 
 /* SDL blit copy flags */
-#define SDL_COPY_MODULATE_COLOR     0x0001
-#define SDL_COPY_MODULATE_ALPHA     0x0002
-#define SDL_COPY_MASK               0x0010
-#define SDL_COPY_BLEND              0x0020
-#define SDL_COPY_ADD                0x0040
-#define SDL_COPY_MOD                0x0080
-#define SDL_COPY_COLORKEY           0x0100
-#define SDL_COPY_NEAREST            0x0200
+#define SDL_COPY_MODULATE_COLOR     0x00000001
+#define SDL_COPY_MODULATE_ALPHA     0x00000002
+#define SDL_COPY_MASK               0x00000010
+#define SDL_COPY_BLEND              0x00000020
+#define SDL_COPY_ADD                0x00000040
+#define SDL_COPY_MOD                0x00000080
+#define SDL_COPY_COLORKEY           0x00000100
+#define SDL_COPY_NEAREST            0x00000200
+#define SDL_COPY_RLE_DESIRED        0x00001000
+#define SDL_COPY_RLE_COLORKEY       0x00002000
+#define SDL_COPY_RLE_ALPHAKEY       0x00004000
 
 /* SDL blit CPU flags */
-#define SDL_CPU_ANY                 0x0000
-#define SDL_CPU_MMX                 0x0001
-#define SDL_CPU_3DNOW               0x0002
-#define SDL_CPU_SSE                 0x0004
-#define SDL_CPU_SSE2                0x0008
-#define SDL_CPU_ALTIVEC_PREFETCH    0x0010
-#define SDL_CPU_ALTIVEC_NOPREFETCH  0x0020
+#define SDL_CPU_ANY                 0x00000000
+#define SDL_CPU_MMX                 0x00000001
+#define SDL_CPU_3DNOW               0x00000002
+#define SDL_CPU_SSE                 0x00000004
+#define SDL_CPU_SSE2                0x00000008
+#define SDL_CPU_ALTIVEC_PREFETCH    0x00000010
+#define SDL_CPU_ALTIVEC_NOPREFETCH  0x00000020
 
 typedef struct {
     Uint8 *src;
--- a/src/video/SDL_surface.c	Fri Aug 17 06:58:20 2007 +0000
+++ b/src/video/SDL_surface.c	Sat Aug 18 01:44:21 2007 +0000
@@ -212,153 +212,251 @@
     return 0;
 }
 
-/*
- * Set the color key in a blittable surface
- */
-int
-SDL_SetColorKey(SDL_Surface * surface, Uint32 flag, Uint32 key)
+int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag)
 {
-    /* Sanity check the flag as it gets passed in */
-    if (flag & SDL_SRCCOLORKEY) {
-        if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) {
-            flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
-        } else {
-            flag = SDL_SRCCOLORKEY;
-        }
-    } else {
-        flag = 0;
-    }
+    Uint32 flags;
 
-    /* Optimize away operations that don't change anything */
-    if ((flag == (surface->flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK))) &&
-        (key == surface->map->ckey)) {
-        return (0);
-    }
-
-    /* UnRLE surfaces before we change the colorkey */
-    if (surface->flags & SDL_RLEACCEL) {
-        SDL_UnRLESurface(surface, 1);
+    if (!surface) {
+        return -1;
     }
 
     if (flag) {
-        surface->flags |= SDL_SRCCOLORKEY;
-        surface->map->ckey = key;
-        if (flag & SDL_RLEACCELOK) {
-            surface->flags |= SDL_RLEACCELOK;
-        } else {
-            surface->flags &= ~SDL_RLEACCELOK;
-        }
+        surface->flags |= SDL_RLEACCELOK;
     } else {
-        surface->flags &= ~(SDL_SRCCOLORKEY | SDL_RLEACCELOK);
-        surface->map->ckey = 0;
+        surface->flags &= ~SDL_RLEACCELOK;
     }
-    SDL_InvalidateMap(surface->map);
-    return (0);
+    if (surface->flags != flags) {
+        SDL_InvalidateMap(surface->map);
+    }
+    return 0;
 }
 
-/* This function sets the alpha channel of a surface */
-int
-SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value)
+int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key)
 {
-    Uint32 oldflags = surface->flags;
-    Uint32 oldalpha = (surface->map->cmod >> 24);
+    int flags;
 
-    /* Sanity check the flag as it gets passed in */
-    if (flag & SDL_SRCALPHA) {
-        if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) {
-            flag = (SDL_SRCALPHA | SDL_RLEACCELOK);
-        } else {
-            flag = SDL_SRCALPHA;
-        }
-    } else {
-        flag = 0;
+    if (!surface) {
+        return -1;
+    }
+
+    if (flag & SDL_RLEACCEL) {
+        SDL_SetSurfaceRLE(surface, 1);
     }
 
-    /* Optimize away operations that don't change anything */
-    if ((flag == (surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK))) &&
-        (!flag || value == oldalpha)) {
-        return (0);
+    flags = surface->map->info.flags;
+    if (flag) {
+        surface->map->info.flags |= SDL_COPY_COLORKEY;
+        surface->map->info.colorkey = key;
+    } else {
+        surface->map->info.flags &= ~SDL_COPY_COLORKEY;
+    }
+    if (surface->map->info.flags != flags) {
+        SDL_InvalidateMap(surface->map);
+    }
+    return 0;
+}
+
+int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b)
+{
+    int flags;
+
+    if (!surface) {
+        return -1;
     }
 
-    if (!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL))
-        SDL_UnRLESurface(surface, 1);
+    surface->map->info.r = r;
+    surface->map->info.g = g;
+    surface->map->info.b = b;
 
-    if (flag) {
-        surface->flags |= SDL_SRCALPHA;
-        surface->map->cmod &= 0x00FFFFFF;
-        surface->map->cmod |= ((Uint32) value << 24);
-        if (flag & SDL_RLEACCELOK) {
-            surface->flags |= SDL_RLEACCELOK;
-        } else {
-            surface->flags &= ~SDL_RLEACCELOK;
-        }
+    flags = surface->map->info.flags;
+    if (r != 0xFF || g != 0xFF || b != 0xFF) {
+        surface->map->info.flags |= SDL_COPY_MODULATE_COLOR;
     } else {
-        surface->flags &= ~SDL_SRCALPHA;
-        surface->map->cmod |= 0xFF000000;
+        surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR;
     }
-    /*
-     * The representation for software surfaces is independent of
-     * per-surface alpha, so no need to invalidate the blit mapping
-     * if just the alpha value was changed. (If either is 255, we still
-     * need to invalidate.)
-     */
-    if (oldflags != surface->flags
-        || (((oldalpha + 1) ^ (value + 1)) & 0x100)) {
+    if (surface->map->info.flags != flags) {
         SDL_InvalidateMap(surface->map);
     }
-    return (0);
+    return 0;
 }
 
-int
-SDL_SetAlphaChannel(SDL_Surface * surface, Uint8 value)
+
+int SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 * r, Uint8 * g, Uint8 * b)
 {
-    int row, col;
-    int offset;
-    Uint8 *buf;
-
-    if ((surface->format->Amask != 0xFF000000) &&
-        (surface->format->Amask != 0x000000FF)) {
-        SDL_SetError("Unsupported surface alpha mask format");
+    if (!surface) {
         return -1;
     }
-#if SDL_BYTEORDER == SDL_LIL_ENDIAN
-    if (surface->format->Amask == 0xFF000000) {
-        offset = 3;
-    } else {
-        offset = 0;
+
+    if (r) {
+        *r = surface->map->info.r;
+    }
+    if (g) {
+        *g = surface->map->info.g;
+    }
+    if (b) {
+        *b = surface->map->info.b;
     }
-#else
-    if (surface->format->Amask == 0xFF000000) {
-        offset = 0;
-    } else {
-        offset = 3;
+    return 0;
+}
+
+int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha)
+{
+    int flags;
+
+    if (!surface) {
+        return -1;
     }
-#endif /* Byte ordering */
 
-    /* Quickly set the alpha channel of an RGBA or ARGB surface */
-    if (SDL_MUSTLOCK(surface)) {
-        if (SDL_LockSurface(surface) < 0) {
-            return -1;
-        }
+    surface->map->info.a = alpha;
+
+    flags = surface->map->info.flags;
+    if (alpha != 0xFF) {
+        surface->map->info.flags |= SDL_COPY_MODULATE_ALPHA;
+    } else {
+        surface->map->info.flags &= ~SDL_COPY_MODULATE_ALPHA;
+    }
+    if (surface->map->info.flags != flags) {
+        SDL_InvalidateMap(surface->map);
     }
-    row = surface->h;
-    while (row--) {
-        col = surface->w;
-        buf = (Uint8 *) surface->pixels + row * surface->pitch + offset;
-        while (col--) {
-            *buf = value;
-            buf += 4;
-        }
+    return 0;
+}
+
+int SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 * alpha)
+{
+    if (!surface) {
+        return -1;
     }
-    if (SDL_MUSTLOCK(surface)) {
-        SDL_UnlockSurface(surface);
+
+    if (alpha) {
+        *alpha = surface->map->info.a;
     }
     return 0;
 }
 
-/*
- * Set the clipping rectangle for a blittable surface
- */
+int SDL_SetSurfaceBlendMode(SDL_Surface *surface, int blendMode)
+{
+    int flags, status;
+
+    if (!surface) {
+        return -1;
+    }
+
+    status = 0;
+    flags = surface->map->info.flags;
+    surface->map->info.flags &= ~(SDL_COPY_MASK|SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD);
+    switch (blendMode) {
+    case SDL_TEXTUREBLENDMODE_NONE:
+        break;
+    case SDL_TEXTUREBLENDMODE_MASK:
+        surface->map->info.flags |= SDL_COPY_MASK;
+        break;
+    case SDL_TEXTUREBLENDMODE_BLEND:
+        surface->map->info.flags |= SDL_COPY_BLEND;
+        break;
+    case SDL_TEXTUREBLENDMODE_ADD:
+        surface->map->info.flags |= SDL_COPY_ADD;
+        break;
+    case SDL_TEXTUREBLENDMODE_MOD:
+        surface->map->info.flags |= SDL_COPY_MOD;
+        break;
+    default:
+        SDL_Unsupported();
+        status = -1;
+        break;
+    }
+
+    if (surface->map->info.flags != flags) {
+        SDL_InvalidateMap(surface->map);
+    }
+    return status;
+}
+
+int SDL_GetSurfaceBlendMode(SDL_Surface *surface, int *blendMode)
+{
+    if (!surface) {
+        return -1;
+    }
+
+    if (!blendMode) {
+        return 0;
+    }
+
+    switch(surface->map->info.flags & (SDL_COPY_MASK|SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) {
+    case SDL_COPY_MASK:
+        *blendMode = SDL_TEXTUREBLENDMODE_MASK:
+        break;
+    case SDL_COPY_BLEND:
+        *blendMode = SDL_TEXTUREBLENDMODE_BLEND:
+        break;
+    case SDL_COPY_ADD:
+        *blendMode = SDL_TEXTUREBLENDMODE_ADD:
+        break;
+    case SDL_COPY_MOD:
+        *blendMode = SDL_TEXTUREBLENDMODE_MOD:
+        break;
+    default:
+        *blendMode = SDL_TEXTUREBLENDMODE_NONE:
+        break;
+    }
+    return 0;
+}
+
+int SDL_SetSurfaceScaleMode(SDL_Surface *surface, int scaleMode)
+{
+    int flags, status;
+
+    if (!surface) {
+        return -1;
+    }
+
+    status = 0;
+    flags = surface->map->info.flags;
+    surface->map->info.flags &= ~(SDL_COPY_NEAREST);
+    switch (scaleMode) {
+    case SDL_TEXTURESCALEMODE_NONE:
+        break;
+    case SDL_TEXTURESCALEMODE_FAST:
+        surface->map->info.flags |= SDL_COPY_NEAREST;
+        break;
+    case SDL_TEXTURESCALEMODE_SLOW:
+    case SDL_TEXTURESCALEMODE_BEST:
+        SDL_Unsupported();
+        surface->map->info.flags |= SDL_COPY_NEAREST;
+        status = -1;
+        break;
+    default:
+        SDL_Unsupported();
+        status = -1;
+        break;
+    }
+
+    if (surface->map->info.flags != flags) {
+        SDL_InvalidateMap(surface->map);
+    }
+    return status;
+}
+
+int SDL_GetSurfaceScaleMode(SDL_Surface *surface, int *scaleMode)
+{
+    if (!surface) {
+        return -1;
+    }
+
+    if (!scaleMode) {
+        return 0;
+    }
+
+    switch(surface->map->info.flags & (SDL_COPY_LINEAR)) {
+    case SDL_COPY_LINEAR:
+        *scaleMode = SDL_TEXTURESCALEMODE_FAST:
+        break;
+    default:
+        *scaleMode = SDL_TEXTURESCALEMODE_NONE:
+        break;
+    }
+    return 0;
+}
+
 SDL_bool
 SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect)
 {
@@ -557,9 +655,7 @@
                    SDL_PixelFormat * format, Uint32 flags)
 {
     SDL_Surface *convert;
-    Uint32 colorkey = 0;
-    Uint8 alpha = 0;
-    Uint32 surface_flags;
+    Uint32 copy_flags;
     SDL_Rect bounds;
 
     /* Check for empty destination palette! (results in empty image) */
@@ -578,8 +674,7 @@
     }
 
     /* Create a new surface with the desired format */
-    convert = SDL_CreateRGBSurface(flags,
-                                   surface->w, surface->h,
+    convert = SDL_CreateRGBSurface(0, surface->w, surface->h,
                                    format->BitsPerPixel, format->Rmask,
                                    format->Gmask, format->Bmask,
                                    format->Amask);
@@ -595,26 +690,9 @@
         convert->format->palette->ncolors = format->palette->ncolors;
     }
 
-    /* Save the original surface color key and alpha */
-    surface_flags = surface->flags;
-    if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
-        /* Convert colourkeyed surfaces to RGBA if requested */
-        if ((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY && format->Amask) {
-            surface_flags &= ~SDL_SRCCOLORKEY;
-        } else {
-            colorkey = surface->map->ckey;
-            SDL_SetColorKey(surface, 0, 0);
-        }
-    }
-    if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
-        /* Copy over the alpha channel to RGBA if requested */
-        if (format->Amask) {
-            surface->flags &= ~SDL_SRCALPHA;
-        } else {
-            alpha = (Uint8) (surface->map->cmod >> 24);
-            SDL_SetAlpha(surface, 0, 0);
-        }
-    }
+    /* Save the original copy flags */
+    copy_flags = surface->map->info.flags;
+    surface->map->info.flags = 0;
 
     /* Copy over the image data */
     bounds.x = 0;
@@ -624,30 +702,25 @@
     SDL_LowerBlit(surface, &bounds, convert, &bounds);
 
     /* Clean up the original surface, and update converted surface */
-    if (convert != NULL) {
-        SDL_SetClipRect(convert, &surface->clip_rect);
-    }
-    if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
-        Uint32 cflags = surface_flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
-        if (convert != NULL) {
-            Uint8 keyR, keyG, keyB;
+    SDL_SetClipRect(convert, &surface->clip_rect);
+    if (copy_flags & SDL_COPY_COLORKEY) {
+        Uint8 keyR, keyG, keyB, keyA;
 
-            SDL_GetRGB(colorkey, surface->format, &keyR, &keyG, &keyB);
-            SDL_SetColorKey(convert, cflags | (flags & SDL_RLEACCELOK),
-                            SDL_MapRGB(convert->format, keyR, keyG, keyB));
-        }
-        SDL_SetColorKey(surface, cflags, colorkey);
+        SDL_GetRGBA(colorkey, surface->format, &keyR, &keyG, &keyB, &keyA);
+        SDL_SetColorKey(convert, 1,
+                        SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA));
     }
-    if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
-        Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
-        if (convert != NULL) {
-            SDL_SetAlpha(convert, aflags | (flags & SDL_RLEACCELOK), alpha);
-        }
-        if (format->Amask) {
-            surface->flags |= SDL_SRCALPHA;
-        } else {
-            SDL_SetAlpha(surface, aflags, alpha);
-        }
+    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;
+
+    /* 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)) {
+        SDL_SetSurfaceBlendMode(convert, SDL_TEXTUREBLENDMODE_BLEND);
     }
 
     /* We're ready to go! */
--- a/src/video/SDL_video.c	Fri Aug 17 06:58:20 2007 +0000
+++ b/src/video/SDL_video.c	Sat Aug 18 01:44:21 2007 +0000
@@ -1535,8 +1535,7 @@
 SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface)
 {
     SDL_TextureID textureID;
-    Uint32 surface_flags = surface->flags;
-    SDL_PixelFormat *fmt = surface->format;
+    SDL_PixelFormat *fmt;
     int bpp;
     Uint32 Rmask, Gmask, Bmask, Amask;
 
@@ -1544,6 +1543,7 @@
         SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
         return 0;
     }
+    fmt = surface->format;
 
     if (format) {
         if (!SDL_PixelFormatEnumToMasks
@@ -1552,7 +1552,7 @@
             return 0;
         }
     } else {
-        if (fmt->Amask || !(surface_flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA))) {
+        if (surface->format->Amask || !(flags & (SDL_COPY_COLORKEY|SDL_COPY_MASK|SDL_COPY_BLEND))) {
             bpp = fmt->BitsPerPixel;
             Rmask = fmt->Rmask;
             Gmask = fmt->Gmask;
@@ -1595,92 +1595,38 @@
                               surface->pitch);
         }
     } else {
-        Uint32 cmod;
-        SDL_Rect bounds;
-        SDL_Surface dst;
+        SDL_PixelFormat *dst_fmt;
+        SDL_Surface *dst = NULL;
 
         /* Set up a destination surface for the texture update */
-        SDL_zero(dst);
-        dst.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
-        if (!dst.format) {
-            SDL_DestroyTexture(textureID);
-            return 0;
-        }
-        dst.w = surface->w;
-        dst.h = surface->h;
-        dst.pitch = SDL_CalculatePitch(&dst);
-        dst.pixels = SDL_malloc(dst.h * dst.pitch);
-        if (!dst.pixels) {
-            SDL_DestroyTexture(textureID);
-            SDL_FreeFormat(dst.format);
-            SDL_OutOfMemory();
-            return 0;
-        }
-
-        /* Copy the palette if any */
-        if (SDL_ISPIXELFORMAT_INDEXED(format)) {
-            if (fmt->palette) {
-                SDL_SetTexturePalette(textureID, fmt->palette->colors, 0,
-                                      fmt->palette->ncolors);
-                SDL_SetSurfacePalette(&dst, fmt->palette);
-            } else {
-                dst.format->palette =
-                    SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format)));
-                if (!dst.format->palette) {
-                    SDL_DestroyTexture(textureID);
-                    SDL_FreeFormat(dst.format);
-                    return 0;
+        dst_fmt = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
+        if (dst_fmt) {
+            if (SDL_ISPIXELFORMAT_INDEXED(format)) {
+                dst_fmt->palette = SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format)));
+                if (dst_fmt->palette) {
+                    if (fmt->palette) {
+fixme
+                    } else {
+                        SDL_DitherColors(dst_fmt->palette->colors, SDL_BITSPERPIXEL(format));
+                    }
                 }
-                SDL_DitherColors(dst.format->palette->colors,
-                                 SDL_BITSPERPIXEL(format));
+                if (fmt->palette) {
+                    dst_fmt->palette = fmt->palette;
+                } else {
+                }
             }
-        }
 
-        /* Make the texture transparent if the surface has colorkey */
-        if (surface_flags & SDL_SRCCOLORKEY) {
-            int row;
-            int length = dst.w * dst.format->BytesPerPixel;
-            Uint8 *p = (Uint8 *) dst.pixels;
-            for (row = 0; row < dst.h; ++row) {
-                SDL_memset(p, 0, length);
-                p += dst.pitch;
+            cvt = SDL_ConvertSurface(surface, fmt, 0);
+            if (cvt) {
+                SDL_UpdateTexture(textureID, NULL, cvt->pixels, cvt->pitch);
+                SDL_FreeSurface(cvt);
             }
-        }
-
-        /* Copy over the alpha channel */
-        cmod = surface->map->cmod;
-        if (surface_flags & SDL_SRCALPHA) {
-            if (fmt->Amask) {
-                surface->flags &= ~SDL_SRCALPHA;
-            } else {
-                /* FIXME: Need to make sure the texture has an alpha channel
-                 *        and copy 'alpha' into the texture alpha channel.
-                 */
-                SDL_SetAlpha(surface, 0, 0);
-            }
+            SDL_FreeFormat(fmt);
         }
-
-        /* Copy over the image data */
-        bounds.x = 0;
-        bounds.y = 0;
-        bounds.w = surface->w;
-        bounds.h = surface->h;
-        SDL_LowerBlit(surface, &bounds, &dst, &bounds);
+    }
 
-        /* Clean up the original surface */
-        if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
-            Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
-            if (fmt->Amask) {
-                surface->flags |= SDL_SRCALPHA;
-            } else {
-                SDL_SetAlpha(surface, aflags, (cmod >> 24));
-            }
-        }
-
-        /* Update the texture */
-        SDL_UpdateTexture(textureID, NULL, dst.pixels, dst.pitch);
-        SDL_free(dst.pixels);
-        SDL_FreeFormat(dst.format);
+    if (SDL_ISPIXELFORMAT_INDEXED(format) && fmt->palette) {
+        SDL_SetTexturePalette(textureID, fmt->palette->colors, 0, fmt->palette->ncolors);
     }
 
     return textureID;