diff src/video/SDL_surface.c @ 1683:396a35389351 SDL-1.3

Finished palettized display handling. Added support for surface palette sharing.
author Sam Lantinga <slouken@libsdl.org>
date Sat, 17 Jun 2006 06:45:14 +0000
parents 7ae8018b2e5d
children a1ebb17f9c52
line wrap: on
line diff
--- a/src/video/SDL_surface.c	Fri Jun 16 06:00:31 2006 +0000
+++ b/src/video/SDL_surface.c	Sat Jun 17 06:45:14 2006 +0000
@@ -47,20 +47,21 @@
     /* Next time I write a library like SDL, I'll use int for size. :) */
     if (width >= 16384 || height >= 65536) {
         SDL_SetError("Width or height is too large");
-        return (NULL);
+        return NULL;
     }
 
     /* Allocate the surface */
     surface = (SDL_Surface *) SDL_malloc(sizeof(*surface));
     if (surface == NULL) {
         SDL_OutOfMemory();
-        return (NULL);
+        return NULL;
     }
-    surface->flags = 0;
+    SDL_zerop(surface);
+
     surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
-    if (surface->format == NULL) {
-        SDL_free(surface);
-        return (NULL);
+    if (!surface->format) {
+        SDL_FreeSurface(surface);
+        return NULL;
     }
     if (Amask) {
         surface->flags |= SDL_SRCALPHA;
@@ -68,16 +69,69 @@
     surface->w = width;
     surface->h = height;
     surface->pitch = SDL_CalculatePitch(surface);
-    surface->pixels = NULL;
-    surface->locked = 0;
-    surface->map = NULL;
     SDL_SetClipRect(surface, NULL);
-    SDL_FormatChanged(surface);
+
+    if (surface->format->BitsPerPixel <= 8) {
+        SDL_Palette *palette =
+            SDL_AllocPalette((1 << surface->format->BitsPerPixel));
+        if (!palette) {
+            SDL_FreeSurface(surface);
+            return NULL;
+        }
+        if (Rmask || Bmask || Gmask) {
+            const SDL_PixelFormat *format = surface->format;
+
+            /* create palette according to masks */
+            int i;
+            int Rm = 0, Gm = 0, Bm = 0;
+            int Rw = 0, Gw = 0, Bw = 0;
+
+            if (Rmask) {
+                Rw = 8 - format->Rloss;
+                for (i = format->Rloss; i > 0; i -= Rw)
+                    Rm |= 1 << i;
+            }
+            if (Gmask) {
+                Gw = 8 - format->Gloss;
+                for (i = format->Gloss; i > 0; i -= Gw)
+                    Gm |= 1 << i;
+            }
+            if (Bmask) {
+                Bw = 8 - format->Bloss;
+                for (i = format->Bloss; i > 0; i -= Bw)
+                    Bm |= 1 << i;
+            }
+            for (i = 0; i < palette->ncolors; ++i) {
+                int r, g, b;
+                r = (i & Rmask) >> format->Rshift;
+                r = (r << format->Rloss) | ((r * Rm) >> Rw);
+                palette->colors[i].r = r;
+
+                g = (i & Gmask) >> format->Gshift;
+                g = (g << format->Gloss) | ((g * Gm) >> Gw);
+                palette->colors[i].g = g;
+
+                b = (i & Bmask) >> format->Bshift;
+                b = (b << format->Bloss) | ((b * Bm) >> Bw);
+                palette->colors[i].b = b;
+            }
+        } else if (palette->ncolors == 2) {
+            /* Create a black and white bitmap palette */
+            palette->colors[0].r = 0xFF;
+            palette->colors[0].g = 0xFF;
+            palette->colors[0].b = 0xFF;
+            palette->colors[1].r = 0x00;
+            palette->colors[1].g = 0x00;
+            palette->colors[1].b = 0x00;
+        }
+        SDL_SetSurfacePalette(surface, palette);
+        SDL_FreePalette(palette);
+    }
 
     /* Get the pixels */
     if (surface->w && surface->h) {
         surface->pixels = SDL_malloc(surface->h * surface->pitch);
-        if (surface->pixels == NULL) {
+        if (!surface->pixels) {
             SDL_FreeSurface(surface);
             SDL_OutOfMemory();
             return NULL;
@@ -88,17 +142,18 @@
 
     /* Allocate an empty mapping */
     surface->map = SDL_AllocBlitMap();
-    if (surface->map == NULL) {
+    if (!surface->map) {
         SDL_FreeSurface(surface);
-        return (NULL);
+        return NULL;
     }
+    SDL_FormatChanged(surface);
 
     /* The surface is ready to go */
     surface->refcount = 1;
 #ifdef CHECK_LEAKS
     ++surfaces_allocated;
 #endif
-    return (surface);
+    return surface;
 }
 
 /*
@@ -157,47 +212,64 @@
             surface->flags |= SDL_HWSURFACE;
             surface->w = w;
             surface->h = h;
-            surface->lock_data = (void *) textureID;
             SDL_SetClipRect(surface, NULL);
         }
     }
+    if (surface) {
+        surface->textureID = textureID;
+    }
 
     return surface;
 }
 
-/*
- * Set the palette in a blittable surface
- */
-int
-SDL_SetColors(SDL_Surface * surface, const SDL_Color * colors, int firstcolor,
-              int ncolors)
+static int
+SDL_SurfacePaletteChanged(void *userdata, SDL_Palette * palette)
 {
-    SDL_Palette *pal;
-    int gotall;
-    int palsize;
+    SDL_Surface *surface = (SDL_Surface *) userdata;
 
-    /* Verify the parameters */
-    pal = surface->format->palette;
-    if (!pal) {
-        return 0;               /* not a palettized surface */
-    }
-    gotall = 1;
-    palsize = 1 << surface->format->BitsPerPixel;
-    if (ncolors > (palsize - firstcolor)) {
-        ncolors = (palsize - firstcolor);
-        gotall = 0;
-    }
-
-    if (colors != (pal->colors + firstcolor)) {
-        SDL_memcpy(pal->colors + firstcolor, colors,
-                   ncolors * sizeof(*colors));
+    if (surface->textureID) {
+        if (SDL_SetTexturePalette
+            (surface->textureID, palette->colors, 0, palette->ncolors) < 0) {
+            SDL_GetTexturePalette(surface->textureID, palette->colors, 0,
+                                  palette->ncolors);
+            return -1;
+        }
     }
     SDL_FormatChanged(surface);
 
-    if (surface->flags & (SDL_SHADOW_SURFACE | SDL_SCREEN_SURFACE)) {
-        gotall &= SDL_SetScreenColors(surface, colors, firstcolor, ncolors);
+    return 0;
+}
+
+int
+SDL_SetSurfacePalette(SDL_Surface * surface, SDL_Palette * palette)
+{
+    if (!surface || !surface->format) {
+        SDL_SetError("SDL_SetSurfacePalette() passed a NULL surface");
+        return -1;
+    }
+
+    if (palette && palette->ncolors != (1 << surface->format->BitsPerPixel)) {
+        SDL_SetError
+            ("SDL_SetSurfacePalette() passed a palette that doesn't match the surface format");
+        return -1;
     }
-    return gotall;
+
+    if (surface->format->palette == palette) {
+        return 0;
+    }
+
+    if (surface->format->palette) {
+        SDL_DelPaletteWatch(surface->format->palette,
+                            SDL_SurfacePaletteChanged, surface);
+    }
+
+    surface->format->palette = palette;
+
+    if (surface->format->palette) {
+        SDL_AddPaletteWatch(surface->format->palette,
+                            SDL_SurfacePaletteChanged, surface);
+    }
+    return 0;
 }
 
 /*
@@ -729,8 +801,8 @@
         /* Perform the lock */
         if (surface->flags & SDL_HWSURFACE) {
             if (SDL_LockTexture
-                ((SDL_TextureID) surface->lock_data, NULL, 1,
-                 &surface->pixels, &surface->pitch) < 0) {
+                (surface->textureID, NULL, 1, &surface->pixels,
+                 &surface->pitch) < 0) {
                 return (-1);
             }
         }
@@ -760,13 +832,13 @@
 
     /* Unlock hardware or accelerated surfaces */
     if (surface->flags & SDL_HWSURFACE) {
-        SDL_UnlockTexture((SDL_TextureID) surface->lock_data);
-    } else {
-        /* Update RLE encoded surface with new data */
-        if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
-            surface->flags &= ~SDL_RLEACCEL;    /* stop lying */
-            SDL_RLESurface(surface);
-        }
+        SDL_UnlockTexture(surface->textureID);
+    }
+
+    /* Update RLE encoded surface with new data */
+    if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
+        surface->flags &= ~SDL_RLEACCEL;        /* stop lying */
+        SDL_RLESurface(surface);
     }
 }
 
@@ -894,6 +966,7 @@
         SDL_UnRLESurface(surface, 0);
     }
     if (surface->format) {
+        SDL_SetSurfacePalette(surface, NULL);
         SDL_FreeFormat(surface->format);
         surface->format = NULL;
     }
@@ -902,8 +975,8 @@
         surface->map = NULL;
     }
     /* Should we destroy the texture too?
-       if (surface->flags & SDL_HWSURFACE) {
-       SDL_DestroyTexture((SDL_TextureID)surface->lock_data);
+       if (surface->textureID) {
+       SDL_DestroyTexture(surface->textureID);
        }
      */
     if (surface->pixels && ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC)) {