Changes to hopefully handle the creation of a colormap for 8 bit PseudoColor visuals in X11
authorBob Pendleton <bob@pendleton.com>
Thu, 15 Jan 2009 21:35:42 +0000
changeset 3044 b36579172f27
parent 3043 9a20287aaed1
child 3045 9acb9f0f7f0d
Changes to hopefully handle the creation of a colormap for 8 bit PseudoColor visuals in X11
src/video/x11/SDL_x11gamma.c
src/video/x11/SDL_x11render.c
src/video/x11/SDL_x11window.c
--- a/src/video/x11/SDL_x11gamma.c	Wed Jan 14 15:03:44 2009 +0000
+++ b/src/video/x11/SDL_x11gamma.c	Thu Jan 15 21:35:42 2009 +0000
@@ -23,6 +23,9 @@
 #include "../SDL_sysvideo.h"
 #include "SDL_x11video.h"
 
+    /* The size of *all* SDL gamma ramps */
+#define SDL_GammaRampSize (3 * 256 * sizeof(Uint16))
+
 static int numCmaps = 0;
 
 typedef struct
@@ -93,20 +96,22 @@
     SDL_memcpy(&cmapTable[numCmaps].visual, visual, sizeof(Visual));
     cmapTable[numCmaps].ramp = NULL;
 
-    newramp = SDL_malloc(3 * 256 * sizeof(Uint16));     /* The size of *all* SDL gamma ramps */
-    if (NULL == newramp) {
+    if (ramp != NULL) {
+      newramp = SDL_malloc(SDL_GammaRampSize);
+      if (NULL == newramp) {
         SDL_SetError("Out of memory in X11_TrackColormap()");
         return;
-    }
-    SDL_memset(newramp, 0, sizeof(*newramp));
-    cmapTable[numCmaps].ramp = newramp;
+      }
+      SDL_memset(newramp, 0, SDL_GammaRampSize);
+      cmapTable[numCmaps].ramp = newramp;
 
-    ncolors = cmapTable[numCmaps].visual.map_entries;
+      ncolors = cmapTable[numCmaps].visual.map_entries;
 
-    for (i = 0; i < ncolors; i++) {
+      for (i = 0; i < ncolors; i++) {
         newramp[(0 * 256) + i] = ramp[i].red;
         newramp[(1 * 256) + i] = ramp[i].green;
         newramp[(2 * 256) + i] = ramp[i].blue;
+      }
     }
 
     numCmaps++;
@@ -144,7 +149,15 @@
                 return -1;
             }
             /* remember the new ramp */
-            SDL_memcpy(cmapTable[j].ramp, ramp, sizeof(*cmapTable[j].ramp));
+	    if (cmapTable[j].ramp == NULL) {
+	      Uint16 * newramp = SDL_malloc(SDL_GammaRampSize);
+	      if (NULL == newramp) {
+		SDL_SetError("Out of memory in X11_TrackColormap()");
+		return -1;
+	      }
+	      cmapTable[j].ramp = newramp;
+	    }
+            SDL_memcpy(cmapTable[j].ramp, ramp, SDL_GammaRampSize);
 
             rshift = 0;
             rmask = visual->red_mask;
@@ -210,7 +223,7 @@
 
     for (i = 0; i < numCmaps; i++) {
         if (cmapTable[i].visual.class == DirectColor) {
-            SDL_memcpy(ramp, cmapTable[i].ramp, sizeof(*cmapTable[i].ramp));
+            SDL_memcpy(ramp, cmapTable[i].ramp, SDL_GammaRampSize);
             return 0;
         }
     }
--- a/src/video/x11/SDL_x11render.c	Wed Jan 14 15:03:44 2009 +0000
+++ b/src/video/x11/SDL_x11render.c	Thu Jan 15 21:35:42 2009 +0000
@@ -413,7 +413,7 @@
                           texture->h, renderdata->depth);
         if (data->pixmap == None) {
             X11_DestroyTexture(renderer, texture);
-            SDL_SetError("XCteatePixmap() failed");
+            SDL_SetError("XCreatePixmap() failed");
             return -1;
         }
 
--- a/src/video/x11/SDL_x11window.c	Wed Jan 14 15:03:44 2009 +0000
+++ b/src/video/x11/SDL_x11window.c	Thu Jan 15 21:35:42 2009 +0000
@@ -214,91 +214,115 @@
     xattr.border_pixel = 0;
 
     if (visual->class == PseudoColor) {
-/*         printf("asking for PseudoColor\n"); */
-        int nmaps;
+        printf("asking for PseudoColor\n");
+
+        Status status;
         XStandardColormap cmap;
-        XStandardColormap *stdmaps;
         XColor *colorcells;
         Colormap colormap;
-        Bool found = False;
-        int i;
-        int ncolors;
-        int rmax, gmax, bmax;
-        int rmul, gmul, bmul;
+	Sint32 pix;
+        Sint32 ncolors;
+        Sint32 nbits;
+        Sint32 rmax, gmax, bmax;
+	Sint32 rwidth, gwidth, bwidth;
+        Sint32 rmask, gmask, bmask;
+        Sint32 rshift, gshift, bshift;
+	Sint32 r, g, b;
 
+        /* Is the colormap we need already registered in SDL? */
         if (colormap =
-            X11_LookupColormap(data->display, displaydata->screen,
-                               visual->visualid)) {
+            X11_LookupColormap(data->display,
+                               displaydata->screen, visual->visualid)) {
             xattr.colormap = colormap;
+/*             printf("found existing colormap\n"); */
         } else {
-            /* check to see if the colormap we need already exists */
-            if (0 != XGetRGBColormaps(data->display,
-                                      RootWindow(data->display,
-                                                 displaydata->screen),
-                                      &stdmaps, &nmaps, XA_RGB_BEST_MAP)) {
-                for (i = 0; i < nmaps; i++) {
-                    if (stdmaps[i].visualid == visual->visualid) {
-                        SDL_memcpy(&cmap, &stdmaps[i],
-                                   sizeof(XStandardColormap));
-                        found = True;
-                        break;
-                    }
-                }
-                XFree(stdmaps);
+            /* The colormap is not known to SDL so we will create it */
+            colormap = XCreateColormap(data->display,
+                                       RootWindow(data->display,
+                                                  displaydata->screen),
+                                       visual, AllocAll);
+/*             printf("colormap = %x\n", colormap); */
+
+            /* If we can't create a colormap, then we must die */
+            if (!colormap) {
+                SDL_SetError
+                    ("Couldn't create window: Could not create writable colormap");
+                return -1;
             }
 
-            /* it doesn't exist, so create it */
-            if (!found) {
-                int max = visual->map_entries - 1;
-                stdmaps =
-                    XmuStandardColormap(data->display, displaydata->screen,
-                                        visual->visualid, depth,
-                                        XA_RGB_BEST_MAP, None, max, max, max);
-                if (NULL == stdmaps || stdmaps->visualid != visual->visualid) {
-                    SDL_SetError
-                        ("Couldn't create window:XA_RGB_BEST_MAP not found and could not be created");
-                    return -1;
-                }
-                SDL_memcpy(&cmap, stdmaps, sizeof(XStandardColormap));
-                XFree(stdmaps);
-            }
-
-            /* OK, we have the best color map, now copy it for use by the
-               program */
+            /* OK, we got a colormap, now fill it in as best as we can */
 
             colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
             if (NULL == colorcells) {
                 SDL_SetError("out of memory in X11_CreateWindow");
                 return -1;
             }
+
             ncolors = visual->map_entries;
-            rmax = cmap.red_max + 1;
-            gmax = cmap.blue_max + 1;
-            bmax = cmap.green_max + 1;
+	    nbits = visual->bits_per_rgb;
+
+/* 	    printf("ncolors = %d nbits = %d\n", ncolors, nbits); */
+
+	    /* what if ncolors != (1 << nbits)? That can happen on a
+	       true PseudoColor display.  I'm assuming that we will
+	       always have ncolors == (1 << nbits)*/
+
+	    /* I'm making a lot of assumptions here. */
+	    
+	    /* Compute the width of each field. If there is one extra
+	       bit, give it to green. If there are two extra bits give
+	       them to red and greed.  We can get extra bits when the
+	       number of bits per pixel is not a multiple of 3. For
+	       example when we have 16 bits per pixel and need a 5/6/5
+	       layout for the RGB fields */
 
-            rmul = cmap.red_mult;
-            gmul = cmap.blue_mult;
-            bmul = cmap.green_mult;
+	    rwidth = (nbits / 3) + (((nbits % 3) == 2) ? 1 : 0);
+	    gwidth = (nbits / 3) + (((nbits % 3) >= 1) ? 1 : 0);
+	    bwidth = (nbits / 3);
+
+            rshift = gwidth + bwidth;
+            gshift = bwidth;
+            bshift = 0;
+
+            rmax = 1 << rwidth;
+            gmax = 1 << gwidth;
+            bmax = 1 << bwidth;
+
+            rmask = rmax - 1;
+            gmask = gmax - 1;
+            bmask = bmax - 1;
+
+/*             printf("red   mask = %4x shift = %4d width = %d\n", rmask, rshift, rwidth); */
+/*             printf("green mask = %4x shift = %4d width = %d\n", gmask, gshift, gwidth); */
+/*             printf("blue  mask = %4x shift = %4d width = %d\n", bmask, bshift, bwidth); */
 
             /* build the color table pixel values */
-            for (i = 0; i < ncolors; i++) {
-                Uint32 red = (rmax * i) / ncolors;
-                Uint32 green = (gmax * i) / ncolors;
-                Uint32 blue = (bmax * i) / ncolors;
+	    pix = 0;
+	    for (r = 0; r < rmax; r++) {
+	      for (g = 0; g < gmax; g++) {
+		for (b = 0; b < bmax; b++) {
+		  colorcells[pix].pixel = (r << rshift) | (g << gshift) | (b << bshift);
+		  colorcells[pix].red   = (0xffff * r) / rmask;
+		  colorcells[pix].green = (0xffff * g) / gmask;
+		  colorcells[pix].blue  = (0xffff * b) / bmask;
+/* 		  printf("%4x:%4x [%4x %4x %4x]\n",  */
+/* 			 pix,  */
+/* 			 colorcells[pix].pixel, */
+/* 			 colorcells[pix].red, */
+/* 			 colorcells[pix].green, */
+/* 			 colorcells[pix].blue); */
+		  pix++;
+		}
+	      }
+	    }
 
-                colorcells[i].pixel =
-                    (red * rmul) | (green * gmul) | (blue * bmul);
-            }
-            XQueryColors(data->display, cmap.colormap, colorcells, ncolors);
-            colormap = XCreateColormap(data->display,
-                                       RootWindow(data->display,
-                                                  displaydata->screen),
-                                       visual, AllocAll);
-            XStoreColors(data->display, colormap, colorcells, ncolors);
+/*             status = */
+/*                 XStoreColors(data->display, colormap, colorcells, ncolors); */
 
             xattr.colormap = colormap;
-            X11_TrackColormap(data->display, displaydata->screen, colormap,
-                              visual, colorcells);
+            X11_TrackColormap(data->display, displaydata->screen,
+                              colormap, visual, NULL);
+
             SDL_free(colorcells);
         }
     } else if (visual->class == DirectColor) {
@@ -329,7 +353,7 @@
             /* If we can't create a colormap, then we must die */
             if (!colormap) {
                 SDL_SetError
-                    ("Couldn't create window: Could not create wriatable colormap");
+                    ("Couldn't create window: Could not create writable colormap");
                 return -1;
             }
 
@@ -393,7 +417,6 @@
 
                 colorcells[i].flags = DoRed | DoGreen | DoBlue;
 /* 		printf("%2d:%4x [%4x %4x %4x]\n", i, pix, red, green, blue); */
-
             }
 
             status =