diff src/video/SDL_surface.c @ 2266:e61ad15a205f

More work in progress integrating SDL_Surface and the new SDL_Texture API
author Sam Lantinga <slouken@libsdl.org>
date Sat, 18 Aug 2007 01:44:21 +0000
parents 202ddfd1cfb1
children c785543d1843
line wrap: on
line diff
--- 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! */