Finished palettized display handling. SDL-1.3
authorSam Lantinga <slouken@libsdl.org>
Sat, 17 Jun 2006 06:45:14 +0000
branchSDL-1.3
changeset 1683 396a35389351
parent 1682 7ae8018b2e5d
child 1684 c4aa1a2f48f1
Finished palettized display handling. Added support for surface palette sharing.
include/SDL_compat.h
include/SDL_pixels.h
include/SDL_video.h
src/SDL_compat.c
src/video/SDL_RLEaccel.c
src/video/SDL_bmp.c
src/video/SDL_pixels.c
src/video/SDL_pixels_c.h
src/video/SDL_renderer_sw.c
src/video/SDL_surface.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/dummy/SDL_nullrender.c
--- a/include/SDL_compat.h	Fri Jun 16 06:00:31 2006 +0000
+++ b/include/SDL_compat.h	Sat Jun 17 06:45:14 2006 +0000
@@ -148,9 +148,9 @@
 extern DECLSPEC int SDLCALL SDL_SetPalette(SDL_Surface * surface, int flags,
                                            const SDL_Color * colors,
                                            int firstcolor, int ncolors);
-extern DECLSPEC int SDLCALL SDL_SetScreenColors(SDL_Surface * screen,
-                                                const SDL_Color * colors,
-                                                int firstcolor, int ncolors);
+extern DECLSPEC int SDLCALL SDL_SetColors(SDL_Surface * surface,
+                                          const SDL_Color * colors,
+                                          int firstcolor, int ncolors);
 extern DECLSPEC int SDLCALL SDL_GetWMInfo(SDL_SysWMinfo * info);
 extern DECLSPEC Uint8 SDLCALL SDL_GetAppState(void);
 extern DECLSPEC void SDLCALL SDL_WarpMouse(Uint16 x, Uint16 y);
--- a/include/SDL_pixels.h	Fri Jun 16 06:00:31 2006 +0000
+++ b/include/SDL_pixels.h	Sat Jun 17 06:45:14 2006 +0000
@@ -195,11 +195,24 @@
 } SDL_Color;
 #define SDL_Colour SDL_Color
 
-typedef struct SDL_Palette
+typedef struct SDL_Palette SDL_Palette;
+typedef int (*SDL_PaletteChangedFunc) (void *userdata, SDL_Palette * palette);
+
+typedef struct SDL_PaletteWatch
+{
+    SDL_PaletteChangedFunc callback;
+    void *userdata;
+    struct SDL_PaletteWatch *next;
+} SDL_PaletteWatch;
+
+struct SDL_Palette
 {
     int ncolors;
     SDL_Color *colors;
-} SDL_Palette;
+
+    int refcount;
+    SDL_PaletteWatch *watch;
+};
 
 /* Everything in the pixel format structure is read-only */
 typedef struct SDL_PixelFormat
@@ -226,23 +239,96 @@
     Uint8 alpha;
 } SDL_PixelFormat;
 
-/*
- * Convert one of the enumerated formats above to a bpp and RGBA masks.
- * Returns SDL_TRUE, or SDL_FALSE if the conversion wasn't possible.
+/**
+ * \fn SDL_bool SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask, Uint32 * Gmask, Uint32 * Bmask, Uint32 * Amask)
+ *
+ * \brief Convert one of the enumerated pixel formats to a bpp and RGBA masks.
+ *
+ * \return SDL_TRUE, or SDL_FALSE if the conversion wasn't possible.
+ *
+ * \sa SDL_MasksToPixelFormatEnum()
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_PixelFormatEnumToMasks(Uint32 format,
+                                                            int *bpp,
+                                                            Uint32 * Rmask,
+                                                            Uint32 * Gmask,
+                                                            Uint32 * Bmask,
+                                                            Uint32 * Amask);
+
+/**
+ * \fn Uint32 SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
+ *
+ * \brief Convert a bpp and RGBA masks to an enumerated pixel format.
+ *
+ * \return The pixel format, or SDL_PixelFormat_Unknown if the conversion wasn't possible.
+ *
+ * \sa SDL_PixelFormatEnumToMasks()
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_MasksToPixelFormatEnum(int bpp,
+                                                          Uint32 Rmask,
+                                                          Uint32 Gmask,
+                                                          Uint32 Bmask,
+                                                          Uint32 Amask);
+
+/**
+ * \fn SDL_Palette *SDL_AllocPalette(int ncolors)
+ *
+ * \brief Create a palette structure with the specified number of color entries.
+ *
+ * \return A new palette, or NULL if there wasn't enough memory
+ *
+ * \note The palette entries are initialized to white.
+ *
+ * \sa SDL_FreePalette()
  */
-extern DECLSPEC SDL_bool SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp,
-                                                    Uint32 * Rmask,
-                                                    Uint32 * Gmask,
-                                                    Uint32 * Bmask,
-                                                    Uint32 * Amask);
+extern DECLSPEC SDL_Palette *SDLCALL SDL_AllocPalette(int ncolors);
+
+/**
+ * \fn int SDL_AddPaletteWatch(SDL_Palette *palette, SDL_PaletteChangedFunc callback, void *userdata)
+ *
+ * \brief Add a callback function which is called when the palette changes.
+ *
+ * \sa SDL_DelPaletteWatch()
+ */
+extern DECLSPEC int SDLCALL SDL_AddPaletteWatch(SDL_Palette * palette,
+                                                SDL_PaletteChangedFunc
+                                                callback, void *userdata);
+
+/**
+ * \fn void SDL_DelPaletteWatch(SDL_Palette *palette, SDL_PaletteChangedFunc callback, void *userdata)
+ *
+ * \brief Remove a callback function previously added with SDL_AddPaletteWatch()
+ *
+ * \sa SDL_AddPaletteWatch()
+ */
+extern DECLSPEC void SDLCALL SDL_DelPaletteWatch(SDL_Palette * palette,
+                                                 SDL_PaletteChangedFunc
+                                                 callback, void *userdata);
 
-/*
- * Convert a bpp and RGBA masks to one of the enumerated formats above.
- * Returns SDL_PixelFormat_Unknown if the conversion wasn't possible.
+/**
+ * \fn int SDL_SetPaletteColors(SDL_Palette *palette, const SDL_Colors *colors, int firstcolor, int numcolors)
+ *
+ * \brief Set a range of colors in a palette.
+ *
+ * \param palette The palette to modify
+ * \param colors An array of colors to copy into the palette
+ * \param firstcolor The index of the first palette entry to modify
+ * \param ncolors The number of entries to modify
+ *
+ * \return 0 on success, or -1 if not all of the colors could be set
  */
-extern DECLSPEC Uint32 SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask,
-                                                  Uint32 Gmask, Uint32 Bmask,
-                                                  Uint32 Amask);
+extern DECLSPEC int SDLCALL SDL_SetPaletteColors(SDL_Palette * palette,
+                                                 const SDL_Color * colors,
+                                                 int firstcolor, int ncolors);
+
+/**
+ * \fn void SDL_FreePalette(SDL_Palette *palette)
+ *
+ * \brief Free a palette created with SDL_AllocPalette()
+ *
+ * \sa SDL_AllocPalette()
+ */
+extern DECLSPEC void SDLCALL SDL_FreePalette(SDL_Palette * palette);
 
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
--- a/include/SDL_video.h	Fri Jun 16 06:00:31 2006 +0000
+++ b/include/SDL_video.h	Sat Jun 17 06:45:14 2006 +0000
@@ -252,6 +252,9 @@
     int pitch;                  /* Read-only */
     void *pixels;               /* Read-write */
 
+    /* texture associated with the surface, if any */
+    SDL_TextureID textureID;
+
     /* information needed for surfaces requiring locks */
     int locked;
     void *lock_data;
@@ -1067,25 +1070,6 @@
                                              Uint16 * blue);
 
 /*
- * Sets a portion of the colormap for the given 8-bit surface.  If 'surface'
- * is not a palettized surface, this function does nothing, returning 0.
- * If all of the colors were set as passed to SDL_SetColors(), it will
- * return 1.  If not all the color entries were set exactly as given,
- * it will return 0, and you should look at the surface palette to
- * determine the actual color palette.
- *
- * When 'surface' is the surface associated with the current display, the
- * display colormap will be updated with the requested colors.  If 
- * SDL_HWPALETTE was set in SDL_SetVideoMode() flags, SDL_SetColors()
- * will always return 1, and the palette is guaranteed to be set the way
- * you desire, even if the window colormap has to be warped or run under
- * emulation.
- */
-extern DECLSPEC int SDLCALL SDL_SetColors(SDL_Surface * surface,
-                                          const SDL_Color * colors,
-                                          int firstcolor, int ncolors);
-
-/*
  * Maps an RGB triple to an opaque pixel value for a given pixel format
  */
 extern DECLSPEC Uint32 SDLCALL SDL_MapRGB
@@ -1138,6 +1122,18 @@
 SDL_CreateRGBSurfaceFromTexture(SDL_TextureID textureID);
 extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface);
 
+/**
+ * \fn int SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette)
+ *
+ * \brief Set the palette used by a surface.
+ *
+ * \return 0, or -1 if the surface format doesn't use a palette.
+ *
+ * \note A single palette can be shared with many surfaces.
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfacePalette(SDL_Surface * surface,
+                                                  SDL_Palette * palette);
+
 /*
  * SDL_LockSurface() sets up a surface for directly accessing the pixels.
  * Between calls to SDL_LockSurface()/SDL_UnlockSurface(), you can write
--- a/src/SDL_compat.c	Fri Jun 16 06:00:31 2006 +0000
+++ b/src/SDL_compat.c	Sat Jun 17 06:45:14 2006 +0000
@@ -204,7 +204,25 @@
             break;
         }
     }
-    return orig_eventfilter(event);
+    if (orig_eventfilter) {
+        return orig_eventfilter(event);
+    } else {
+        return 1;
+    }
+}
+
+static int
+SDL_VideoPaletteChanged(void *userdata, SDL_Palette * palette)
+{
+    if (userdata == SDL_ShadowSurface) {
+        /* If the shadow palette changed, make the changes visible */
+        if (!SDL_VideoSurface->format->palette) {
+            SDL_UpdateRect(SDL_ShadowSurface, 0, 0, 0, 0);
+        }
+    }
+    if (userdata == SDL_VideoSurface) {
+        return SDL_SetDisplayPalette(palette->colors, 0, palette->ncolors);
+    }
 }
 
 SDL_Surface *
@@ -233,7 +251,9 @@
         SDL_ShadowSurface = NULL;
     }
     if (SDL_VideoSurface) {
-        SDL_FreeSurface(SDL_ShadowSurface);
+        SDL_DelPaletteWatch(SDL_VideoSurface->format->palette,
+                            SDL_VideoPaletteChanged, NULL);
+        SDL_FreeSurface(SDL_VideoSurface);
         SDL_VideoSurface = NULL;
     }
     SDL_DestroyWindow(SDL_VideoWindow);
@@ -380,11 +400,11 @@
         SDL_VideoSurface->flags |= SDL_HWPALETTE;
         SDL_DitherColors(SDL_VideoSurface->format->palette->colors,
                          SDL_VideoSurface->format->BitsPerPixel);
-        SDL_SetTexturePalette(SDL_VideoTexture,
-                              SDL_VideoSurface->format->palette->colors, 0,
-                              SDL_VideoSurface->format->palette->ncolors);
-        SDL_SetDisplayPalette(SDL_VideoSurface->format->palette->colors, 0,
-                              SDL_VideoSurface->format->palette->ncolors);
+        SDL_AddPaletteWatch(SDL_VideoSurface->format->palette,
+                            SDL_VideoPaletteChanged, NULL);
+        SDL_SetPaletteColors(SDL_VideoSurface->format->palette,
+                             SDL_VideoSurface->format->palette->colors, 0,
+                             SDL_VideoSurface->format->palette->ncolors);
     }
 
     /* Create a shadow surface if necessary */
@@ -415,8 +435,13 @@
         /* 8-bit SDL_ShadowSurface surfaces report that they have exclusive palette */
         if (SDL_ShadowSurface->format->palette) {
             SDL_ShadowSurface->flags |= SDL_HWPALETTE;
-            SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
-                             SDL_ShadowSurface->format->BitsPerPixel);
+            if (SDL_VideoSurface->format->palette) {
+                SDL_SetSurfacePalette(SDL_ShadowSurface,
+                                      SDL_VideoSurface->format->palette);
+            } else {
+                SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
+                                 SDL_ShadowSurface->format->BitsPerPixel);
+            }
         }
     }
     SDL_PublicSurface =
@@ -656,55 +681,15 @@
 }
 
 int
-SDL_SetScreenColors(SDL_Surface * screen, const SDL_Color * colors,
-                    int firstcolor, int ncolors)
+SDL_SetColors(SDL_Surface * surface, const SDL_Color * colors, int firstcolor,
+              int ncolors)
 {
-    SDL_Palette *pal;
-    int gotall;
-    int palsize;
-
-    /* Verify the parameters */
-    pal = screen->format->palette;
-    if (!pal) {
-        return 0;               /* not a palettized surface */
-    }
-    gotall = 1;
-    palsize = 1 << screen->format->BitsPerPixel;
-    if (ncolors > (palsize - firstcolor)) {
-        ncolors = (palsize - firstcolor);
-        gotall = 0;
+    if (SDL_SetPaletteColors
+        (surface->format->palette, colors, firstcolor, ncolors) == 0) {
+        return 1;
+    } else {
+        return 0;
     }
-
-    if (screen == SDL_ShadowSurface) {
-        SDL_Palette *vidpal;
-
-        vidpal = SDL_VideoSurface->format->palette;
-        if (vidpal && vidpal->ncolors == pal->ncolors) {
-            /* This is a shadow surface, and the physical
-             * framebuffer is also indexed. Propagate the
-             * changes to its logical palette so that
-             * updates are always identity blits
-             */
-            SDL_memcpy(vidpal->colors + firstcolor, colors,
-                       ncolors * sizeof(*colors));
-        }
-        if (SDL_VideoSurface->flags & SDL_HWPALETTE) {
-            /* Set the physical palette */
-            screen = SDL_VideoSurface;
-        } else {
-            SDL_UpdateRect(screen, 0, 0, 0, 0);
-        }
-    }
-
-    if (screen == SDL_VideoSurface) {
-        SDL_SetTexturePalette(SDL_VideoTexture,
-                              SDL_VideoSurface->format->palette->colors, 0,
-                              SDL_VideoSurface->format->palette->ncolors);
-        SDL_SetDisplayPalette(SDL_VideoSurface->format->palette->colors, 0,
-                              SDL_VideoSurface->format->palette->ncolors);
-    }
-
-    return gotall;
 }
 
 int
--- a/src/video/SDL_RLEaccel.c	Fri Jun 16 06:00:31 2006 +0000
+++ b/src/video/SDL_RLEaccel.c	Sat Jun 17 06:45:14 2006 +0000
@@ -1618,8 +1618,7 @@
 #undef ADD_TRANSL_COUNTS
 
     /* Now that we have it encoded, release the original pixels */
-    if ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC
-        && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) {
+    if (!(surface->flags & SDL_PREALLOC) && !(surface->flags & SDL_HWSURFACE)) {
         SDL_free(surface->pixels);
         surface->pixels = NULL;
     }
@@ -1784,8 +1783,7 @@
 #undef ADD_COUNTS
 
     /* Now that we have it encoded, release the original pixels */
-    if ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC
-        && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) {
+    if (!(surface->flags & SDL_PREALLOC) && !(surface->flags & SDL_HWSURFACE)) {
         SDL_free(surface->pixels);
         surface->pixels = NULL;
     }
@@ -1936,8 +1934,8 @@
     if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
         surface->flags &= ~SDL_RLEACCEL;
 
-        if (recode && (surface->flags & SDL_PREALLOC) != SDL_PREALLOC
-            && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) {
+        if (recode && !(surface->flags & SDL_PREALLOC)
+            && !(surface->flags & SDL_HWSURFACE)) {
             if ((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
                 SDL_Rect full;
                 unsigned alpha_flag;
--- a/src/video/SDL_bmp.c	Fri Jun 16 06:00:31 2006 +0000
+++ b/src/video/SDL_bmp.c	Sat Jun 17 06:45:14 2006 +0000
@@ -222,7 +222,7 @@
                 SDL_RWread(src, &palette->colors[i].b, 1, 1);
                 SDL_RWread(src, &palette->colors[i].g, 1, 1);
                 SDL_RWread(src, &palette->colors[i].r, 1, 1);
-                palette->colors[i].unused = 0;
+                palette->colors[i].unused = SDL_ALPHA_OPAQUE;
             }
         } else {
             for (i = 0; i < (int) biClrUsed; ++i) {
--- a/src/video/SDL_pixels.c	Fri Jun 16 06:00:31 2006 +0000
+++ b/src/video/SDL_pixels.c	Sat Jun 17 06:45:14 2006 +0000
@@ -215,6 +215,126 @@
     return SDL_PixelFormat_Unknown;
 }
 
+
+SDL_Palette *
+SDL_AllocPalette(int ncolors)
+{
+    SDL_Palette *palette;
+
+    palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
+    if (!palette) {
+        SDL_OutOfMemory();
+        return NULL;
+    }
+    palette->colors =
+        (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
+    if (!palette->colors) {
+        SDL_free(palette);
+        return NULL;
+    }
+    palette->ncolors = ncolors;
+    palette->watch = NULL;
+    palette->refcount = 1;
+
+    SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
+
+    return palette;
+}
+
+int
+SDL_AddPaletteWatch(SDL_Palette * palette, SDL_PaletteChangedFunc callback,
+                    void *userdata)
+{
+    SDL_PaletteWatch *watch;
+
+    if (!palette) {
+        return -1;
+    }
+
+    watch = (SDL_PaletteWatch *) SDL_malloc(sizeof(*watch));
+    if (!watch) {
+        SDL_OutOfMemory();
+        return -1;
+    }
+
+    watch->callback = callback;
+    watch->userdata = userdata;
+    watch->next = palette->watch;
+    palette->watch = watch;
+    ++palette->refcount;
+    return 0;
+}
+
+void
+SDL_DelPaletteWatch(SDL_Palette * palette, SDL_PaletteChangedFunc callback,
+                    void *userdata)
+{
+    SDL_PaletteWatch *prev, *watch;
+
+    if (!palette) {
+        return;
+    }
+
+    for (prev = NULL, watch = palette->watch; watch;
+         prev = watch, watch = watch->next) {
+        if (watch->callback == callback && watch->userdata == userdata) {
+            if (prev) {
+                prev->next = watch->next;
+            } else {
+                palette->watch = watch->next;
+            }
+            SDL_free(watch);
+            SDL_FreePalette(palette);
+            return;
+        }
+    }
+}
+
+int
+SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
+                     int firstcolor, int ncolors)
+{
+    SDL_PaletteWatch *watch;
+    int status = 0;
+
+    /* Verify the parameters */
+    if (!palette) {
+        return -1;
+    }
+    if (ncolors > (palette->ncolors - firstcolor)) {
+        ncolors = (palette->ncolors - firstcolor);
+        status = -1;
+    }
+
+    if (colors != (palette->colors + firstcolor)) {
+        SDL_memcpy(palette->colors + firstcolor, colors,
+                   ncolors * sizeof(*colors));
+    }
+
+    for (watch = palette->watch; watch; watch = watch->next) {
+        if (watch->callback(watch->userdata, palette) < 0) {
+            status = -1;
+        }
+    }
+
+    return status;
+}
+
+void
+SDL_FreePalette(SDL_Palette * palette)
+{
+    if (!palette) {
+        return;
+    }
+    if (--palette->refcount > 0) {
+        return;
+    }
+    if (palette->colors) {
+        SDL_free(palette->colors);
+    }
+    SDL_free(palette);
+}
+
 /*
  * Allocate a pixel format structure and fill it according to the given info.
  */
@@ -238,7 +358,6 @@
     format->BitsPerPixel = bpp;
     format->BytesPerPixel = (bpp + 7) / 8;
     if (Rmask || Bmask || Gmask) {      /* Packed pixels with custom mask */
-        format->palette = NULL;
         format->Rshift = 0;
         format->Rloss = 8;
         if (Rmask) {
@@ -303,121 +422,11 @@
         format->Bmask = 0;
         format->Amask = 0;
     }
-    if (bpp <= 8) {             /* Palettized mode */
-        int ncolors = 1 << bpp;
-#ifdef DEBUG_PALETTE
-        fprintf(stderr, "bpp=%d ncolors=%d\n", bpp, ncolors);
-#endif
-        format->palette = (SDL_Palette *) SDL_malloc(sizeof(SDL_Palette));
-        if (format->palette == NULL) {
-            SDL_FreeFormat(format);
-            SDL_OutOfMemory();
-            return (NULL);
-        }
-        (format->palette)->ncolors = ncolors;
-        (format->palette)->colors = (SDL_Color *) SDL_malloc((format->
-                                                              palette)->
-                                                             ncolors *
-                                                             sizeof
-                                                             (SDL_Color));
-        if ((format->palette)->colors == NULL) {
-            SDL_FreeFormat(format);
-            SDL_OutOfMemory();
-            return (NULL);
-        }
-        if (Rmask || Bmask || Gmask) {
-            /* create palette according to masks */
-            int i;
-            int Rm = 0, Gm = 0, Bm = 0;
-            int Rw = 0, Gw = 0, Bw = 0;
-#ifdef ENABLE_PALETTE_ALPHA
-            int Am = 0, Aw = 0;
-#endif
-            if (Rmask) {
-                Rw = 8 - format->Rloss;
-                for (i = format->Rloss; i > 0; i -= Rw)
-                    Rm |= 1 << i;
-            }
-#ifdef DEBUG_PALETTE
-            fprintf(stderr, "Rw=%d Rm=0x%02X\n", Rw, Rm);
-#endif
-            if (Gmask) {
-                Gw = 8 - format->Gloss;
-                for (i = format->Gloss; i > 0; i -= Gw)
-                    Gm |= 1 << i;
-            }
-#ifdef DEBUG_PALETTE
-            fprintf(stderr, "Gw=%d Gm=0x%02X\n", Gw, Gm);
-#endif
-            if (Bmask) {
-                Bw = 8 - format->Bloss;
-                for (i = format->Bloss; i > 0; i -= Bw)
-                    Bm |= 1 << i;
-            }
-#ifdef DEBUG_PALETTE
-            fprintf(stderr, "Bw=%d Bm=0x%02X\n", Bw, Bm);
-#endif
-#ifdef ENABLE_PALETTE_ALPHA
-            if (Amask) {
-                Aw = 8 - format->Aloss;
-                for (i = format->Aloss; i > 0; i -= Aw)
-                    Am |= 1 << i;
-            }
-# ifdef DEBUG_PALETTE
-            fprintf(stderr, "Aw=%d Am=0x%02X\n", Aw, Am);
-# endif
-#endif
-            for (i = 0; i < ncolors; ++i) {
-                int r, g, b;
-                r = (i & Rmask) >> format->Rshift;
-                r = (r << format->Rloss) | ((r * Rm) >> Rw);
-                format->palette->colors[i].r = r;
+    format->palette = NULL;
 
-                g = (i & Gmask) >> format->Gshift;
-                g = (g << format->Gloss) | ((g * Gm) >> Gw);
-                format->palette->colors[i].g = g;
-
-                b = (i & Bmask) >> format->Bshift;
-                b = (b << format->Bloss) | ((b * Bm) >> Bw);
-                format->palette->colors[i].b = b;
-
-#ifdef ENABLE_PALETTE_ALPHA
-                a = (i & Amask) >> format->Ashift;
-                a = (a << format->Aloss) | ((a * Am) >> Aw);
-                format->palette->colors[i].unused = a;
-#else
-                format->palette->colors[i].unused = SDL_ALPHA_OPAQUE;
-#endif
-            }
-        } else if (ncolors == 2) {
-            /* Create a black and white bitmap palette */
-            format->palette->colors[0].r = 0xFF;
-            format->palette->colors[0].g = 0xFF;
-            format->palette->colors[0].b = 0xFF;
-            format->palette->colors[1].r = 0x00;
-            format->palette->colors[1].g = 0x00;
-            format->palette->colors[1].b = 0x00;
-        } else {
-            /* Create an empty palette */
-            SDL_memset((format->palette)->colors, 0xFF,
-                       (format->palette)->ncolors * sizeof(SDL_Color));
-        }
-    }
     return (format);
 }
 
-SDL_PixelFormat *
-SDL_ReallocFormat(SDL_Surface * surface, int bpp,
-                  Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
-{
-    if (surface->format) {
-        SDL_FreeFormat(surface->format);
-        SDL_FormatChanged(surface);
-    }
-    surface->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
-    return surface->format;
-}
-
 /*
  * Change any previous mappings from/to the new surface format
  */
@@ -439,15 +448,10 @@
 void
 SDL_FreeFormat(SDL_PixelFormat * format)
 {
-    if (format) {
-        if (format->palette) {
-            if (format->palette->colors) {
-                SDL_free(format->palette->colors);
-            }
-            SDL_free(format->palette);
-        }
-        SDL_free(format);
+    if (!format) {
+        return;
     }
+    SDL_free(format);
 }
 
 /*
@@ -695,10 +699,6 @@
     SDL_Color colors[256];
     SDL_Palette *pal = dst->palette;
 
-    /* SDL_DitherColors does not initialize the 'unused' component of colors,
-       but Map1to1 compares it against pal, so we should initialize it. */
-    SDL_memset(colors, 0xFF, sizeof(colors));
-
     dithered.ncolors = 256;
     SDL_DitherColors(colors, 8);
     dithered.colors = colors;
@@ -768,14 +768,8 @@
         switch (dstfmt->BytesPerPixel) {
         case 1:
             /* Palette --> Palette */
-            /* If both SDL_HWSURFACE, assume have same palette */
-            if (((src->flags & SDL_HWSURFACE) == SDL_HWSURFACE) &&
-                ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE)) {
-                map->identity = 1;
-            } else {
-                map->table = Map1to1(srcfmt->palette,
-                                     dstfmt->palette, &map->identity);
-            }
+            map->table =
+                Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
             if (!map->identity) {
                 if (map->table == NULL) {
                     return (-1);
--- a/src/video/SDL_pixels_c.h	Fri Jun 16 06:00:31 2006 +0000
+++ b/src/video/SDL_pixels_c.h	Sat Jun 17 06:45:14 2006 +0000
@@ -29,9 +29,6 @@
 extern SDL_PixelFormat *SDL_AllocFormat(int bpp,
                                         Uint32 Rmask, Uint32 Gmask,
                                         Uint32 Bmask, Uint32 Amask);
-extern SDL_PixelFormat *SDL_ReallocFormat(SDL_Surface * surface, int bpp,
-                                          Uint32 Rmask, Uint32 Gmask,
-                                          Uint32 Bmask, Uint32 Amask);
 extern void SDL_FormatChanged(SDL_Surface * surface);
 extern void SDL_FreeFormat(SDL_PixelFormat * format);
 
--- a/src/video/SDL_renderer_sw.c	Fri Jun 16 06:00:31 2006 +0000
+++ b/src/video/SDL_renderer_sw.c	Sat Jun 17 06:45:14 2006 +0000
@@ -178,6 +178,7 @@
             SDL_SW_DestroyRenderer(renderer);
             return NULL;
         }
+        SDL_SetSurfacePalette(data->screens[i], window->display->palette);
     }
     data->current_screen = 0;
     data->target = data->screens[0];
@@ -248,8 +249,8 @@
 {
     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
 
-    SDL_SetColors(surface, colors, firstcolor, ncolors);
-    return 0;
+    return SDL_SetPaletteColors(surface->format->palette, colors, firstcolor,
+                                ncolors);
 }
 
 static int
@@ -314,7 +315,12 @@
 SDL_SW_SelectRenderTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
     SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata;
-    data->target = (SDL_Surface *) texture->driverdata;
+
+    if (texture) {
+        data->target = (SDL_Surface *) texture->driverdata;
+    } else {
+        data->target = data->screens[data->current_screen];
+    }
 }
 
 static void
--- 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)) {
--- a/src/video/SDL_sysvideo.h	Fri Jun 16 06:00:31 2006 +0000
+++ b/src/video/SDL_sysvideo.h	Sat Jun 17 06:45:14 2006 +0000
@@ -146,7 +146,7 @@
     SDL_DisplayMode *display_modes;
     SDL_DisplayMode desktop_mode;
     SDL_DisplayMode current_mode;
-    SDL_Palette palette;
+    SDL_Palette *palette;
 
     int num_render_drivers;
     SDL_RenderDriver *render_drivers;
--- a/src/video/SDL_video.c	Fri Jun 16 06:00:31 2006 +0000
+++ b/src/video/SDL_video.c	Sat Jun 17 06:45:14 2006 +0000
@@ -517,7 +517,7 @@
 {
     SDL_VideoDisplay *display;
     SDL_DisplayMode display_mode;
-    int i;
+    int i, ncolors;
 
     if (!_this) {
         SDL_SetError("Video subsystem has not been initialized");
@@ -560,26 +560,24 @@
         return 0;
     }
 
+    /* Set up a palette, if necessary */
     if (SDL_ISPIXELFORMAT_INDEXED(display_mode.format)) {
-        display->palette.ncolors =
-            (1 << SDL_BITSPERPIXEL(display_mode.format));
-        display->palette.colors =
-            (SDL_Color *) SDL_realloc(display->palette.colors,
-                                      display->palette.ncolors *
-                                      sizeof(*display->palette.colors));
-        if (!display->palette.colors) {
-            SDL_OutOfMemory();
-            return -1;
+        ncolors = (1 << SDL_BITSPERPIXEL(display_mode.format));
+    } else {
+        ncolors = 0;
+    }
+    if ((!ncolors && display->palette) || (ncolors && !display->palette)
+        || (ncolors != display->palette->ncolors)) {
+        if (display->palette) {
+            SDL_FreePalette(display->palette);
+            display->palette = NULL;
         }
-        SDL_memset(display->palette.colors, 0xff,
-                   display->palette.ncolors *
-                   sizeof(*display->palette.colors));
-    } else {
-        if (display->palette.colors) {
-            SDL_free(display->palette.colors);
+        if (ncolors) {
+            display->palette = SDL_AllocPalette(ncolors);
+            if (!display->palette) {
+                return -1;
+            }
         }
-        display->palette.colors = NULL;
-        display->palette.ncolors = 0;
     }
 
     return _this->SetDisplayMode(_this, &display_mode);
@@ -589,31 +587,27 @@
 SDL_SetDisplayPalette(const SDL_Color * colors, int firstcolor, int ncolors)
 {
     SDL_Palette *palette;
+    int status = 0;
 
     if (!_this) {
         SDL_SetError("Video subsystem has not been initialized");
         return -1;
     }
-
-    palette = &SDL_CurrentDisplay.palette;
-    if (!palette->ncolors) {
+    if (!SDL_CurrentDisplay.palette) {
         SDL_SetError("Display mode does not have a palette");
         return -1;
     }
 
-    if (firstcolor < 0 || (firstcolor + ncolors) > palette->ncolors) {
-        SDL_SetError("Palette indices are out of range");
-        return -1;
-    }
-
-    SDL_memcpy(&palette->colors[firstcolor], colors,
-               ncolors * sizeof(*colors));
+    status =
+        SDL_SetPaletteColors(SDL_CurrentDisplay.palette, colors, firstcolor,
+                             ncolors);
 
     if (_this->SetDisplayPalette) {
-        return _this->SetDisplayPalette(_this, palette);
-    } else {
-        return 0;
+        if (_this->SetDisplayPalette(_this, palette) < 0) {
+            status = -1;
+        }
     }
+    return status;
 }
 
 int
@@ -626,7 +620,7 @@
         return -1;
     }
 
-    palette = &SDL_CurrentDisplay.palette;
+    palette = SDL_CurrentDisplay.palette;
     if (!palette->ncolors) {
         SDL_SetError("Display mode does not have a palette");
         return -1;
@@ -1717,10 +1711,9 @@
             SDL_free(display->windows);
             display->windows = NULL;
         }
-        if (display->palette.colors) {
-            SDL_free(display->palette.colors);
-            display->palette.colors = NULL;
-            display->palette.ncolors = 0;
+        if (display->palette) {
+            SDL_FreePalette(display->palette);
+            display->palette = NULL;
         }
     }
     _this->VideoQuit(_this);
--- a/src/video/dummy/SDL_nullrender.c	Fri Jun 16 06:00:31 2006 +0000
+++ b/src/video/dummy/SDL_nullrender.c	Sat Jun 17 06:45:14 2006 +0000
@@ -106,16 +106,7 @@
         SDL_DUMMY_DestroyRenderer(renderer);
         return NULL;
     }
-
-    /* If the display has a palette, use it for the window surfaces */
-    if (window->display->palette.ncolors) {
-        SDL_PixelFormat *format = data->surface->format;
-        if (format->palette->colors) {
-            SDL_free(format->palette->colors);
-        }
-        SDL_free(format->palette);
-        format->palette = &window->display->palette;
-    }
+    SDL_SetSurfacePalette(data->surface, window->display->palette);
 
     return renderer;
 }
@@ -178,8 +169,8 @@
 
     if (SDL_getenv("SDL_VIDEO_DUMMY_SAVE_FRAMES")) {
         char file[128];
-        SDL_snprintf(file, sizeof(file), "SDL_frame-%8.8d.bmp",
-                     ++frame_number);
+        SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp",
+                     renderer->window->id, ++frame_number);
         SDL_SaveBMP(surface, file);
     }
 }