From 8d65a9ca37a46d44aad69f6be3be9cce3a1168cf Mon Sep 17 00:00:00 2001 From: Bob Pendleton Date: Thu, 15 Jan 2009 21:35:42 +0000 Subject: [PATCH] Changes to hopefully handle the creation of a colormap for 8 bit PseudoColor visuals in X11 --- src/video/x11/SDL_x11gamma.c | 31 +++++-- src/video/x11/SDL_x11render.c | 2 +- src/video/x11/SDL_x11window.c | 153 +++++++++++++++++++--------------- 3 files changed, 111 insertions(+), 75 deletions(-) diff --git a/src/video/x11/SDL_x11gamma.c b/src/video/x11/SDL_x11gamma.c index 0401ceaac..d8cecb41b 100644 --- a/src/video/x11/SDL_x11gamma.c +++ b/src/video/x11/SDL_x11gamma.c @@ -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 @@ X11_TrackColormap(Display * display, int scrNum, Colormap colormap, 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 @@ X11_SetDisplayGammaRamp(_THIS, Uint16 * ramp) 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 @@ X11_GetDisplayGammaRamp(_THIS, Uint16 * ramp) 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; } } diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index e51248c70..e932ffe7e 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -413,7 +413,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) texture->h, renderdata->depth); if (data->pixmap == None) { X11_DestroyTexture(renderer, texture); - SDL_SetError("XCteatePixmap() failed"); + SDL_SetError("XCreatePixmap() failed"); return -1; } diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index c3cdab5a9..8b0df084a 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -214,91 +214,115 @@ X11_CreateWindow(_THIS, SDL_Window * window) 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); */ - /* 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); + /* 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; } - /* 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; - rmul = cmap.red_mult; - gmul = cmap.blue_mult; - bmul = cmap.green_mult; +/* printf("ncolors = %d nbits = %d\n", ncolors, nbits); */ - /* 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; + /* what if ncolors != (1 << nbits)? That can happen on a + true PseudoColor display. I'm assuming that we will + always have ncolors == (1 << nbits)*/ - 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); + /* 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 */ + + 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 */ + 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++; + } + } + } + +/* 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 @@ X11_CreateWindow(_THIS, SDL_Window * window) /* 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 @@ X11_CreateWindow(_THIS, SDL_Window * window) colorcells[i].flags = DoRed | DoGreen | DoBlue; /* printf("%2d:%4x [%4x %4x %4x]\n", i, pix, red, green, blue); */ - } status =