Added gamma table support to X11. Also now supports DirectColor visuals.
authorBob Pendleton <bob@pendleton.com>
Wed, 25 Jul 2007 21:22:55 +0000
changeset 2214e7164a4dac62
parent 2213 59a667370c57
child 2215 23a2cb765052
Added gamma table support to X11. Also now supports DirectColor visuals.
src/video/x11/SDL_x11gamma.c
src/video/x11/SDL_x11gamma.h
src/video/x11/SDL_x11window.c
     1.1 --- a/src/video/x11/SDL_x11gamma.c	Tue Jul 24 18:46:45 2007 +0000
     1.2 +++ b/src/video/x11/SDL_x11gamma.c	Wed Jul 25 21:22:55 2007 +0000
     1.3 @@ -29,32 +29,50 @@
     1.4  {
     1.5      Display *display;
     1.6      int scrNum;
     1.7 +    Colormap colormap;
     1.8      XStandardColormap cmap;
     1.9      Visual visual;
    1.10  } cmapTableEntry;
    1.11  
    1.12  cmapTableEntry *cmapTable = NULL;
    1.13  
    1.14 +/* To reduce the overhead as much as possible lets do as little as
    1.15 +   possible. When we do have to create a colormap keep track of it and
    1.16 +   reuse it. We're going to do this for both DirectColor and
    1.17 +   PseudoColor colormaps. */
    1.18 +
    1.19 +Colormap
    1.20 +X11_LookupColormap(Display * display, int scrNum, VisualID vid)
    1.21 +{
    1.22 +    int i;
    1.23 +
    1.24 +    for (i = 0; i < numCmaps; i++) {
    1.25 +        if (cmapTable[i].display == display &&
    1.26 +            cmapTable[i].scrNum == scrNum &&
    1.27 +            cmapTable[i].cmap.visualid == vid) {
    1.28 +            return cmapTable[i].cmap.colormap;
    1.29 +        }
    1.30 +    }
    1.31 +
    1.32 +    return 0;
    1.33 +}
    1.34 +
    1.35 +
    1.36  void
    1.37 -X11_TrackColormap(Display * display, int scrNum,
    1.38 +X11_TrackColormap(Display * display, int scrNum, Colormap colormap,
    1.39                    XStandardColormap * cmap, Visual * visual)
    1.40  {
    1.41      int i;
    1.42      cmapTableEntry *newTable = NULL;
    1.43  
    1.44 -    /* only tracking DirectColor colormaps because they're the only ones
    1.45 -       with gamma ramps */
    1.46 -    if (DirectColor != visual->class) {
    1.47 -        return;
    1.48 -    }
    1.49 -
    1.50 -    /* search the table to find out if we already have this one. We only
    1.51 -       want one entry for each display, screen number, visualid
    1.52 -       combination */
    1.53 +    /* search the table to find out if we already have this one. We
    1.54 +       only want one entry for each display, screen number, visualid,
    1.55 +       and colormap combination */
    1.56      for (i = 0; i < numCmaps; i++) {
    1.57          if (cmapTable[i].display == display &&
    1.58              cmapTable[i].scrNum == scrNum &&
    1.59 -            cmapTable[i].cmap.visualid == cmap->visualid) {
    1.60 +            cmapTable[i].cmap.visualid == cmap->visualid &&
    1.61 +            cmapTable[i].cmap.colormap == colormap) {
    1.62              return;
    1.63          }
    1.64      }
    1.65 @@ -75,20 +93,146 @@
    1.66  
    1.67      cmapTable[numCmaps].display = display;
    1.68      cmapTable[numCmaps].scrNum = scrNum;
    1.69 +    cmapTable[numCmaps].colormap = colormap;
    1.70      SDL_memcpy(&cmapTable[numCmaps].cmap, cmap, sizeof(XStandardColormap));
    1.71      SDL_memcpy(&cmapTable[numCmaps].visual, visual, sizeof(Visual));
    1.72  
    1.73      numCmaps++;
    1.74  }
    1.75  
    1.76 +/* The problem is that you have to have at least one DirectColor
    1.77 +   colormap before you can set the gamma ramps or read the gamma
    1.78 +   ramps. If the application has created a DirectColor window then the
    1.79 +   cmapTable will have at least one colormap in it and everything is
    1.80 +   cool. If not, then we just fail  */
    1.81 +
    1.82  int
    1.83  X11_SetDisplayGammaRamp(_THIS, Uint16 * ramp)
    1.84  {
    1.85 -    return -1;
    1.86 +    Display *display;
    1.87 +    Colormap colormap;
    1.88 +    XColor *colorcells;
    1.89 +    int ncolors;
    1.90 +    int i;
    1.91 +    int j;
    1.92 +
    1.93 +    int rmax, gmax, bmax;
    1.94 +    int rmul, gmul, bmul;
    1.95 +
    1.96 +    for (j = 0; j < numCmaps; j++) {
    1.97 +        if (cmapTable[j].visual.class == DirectColor) {
    1.98 +            display = cmapTable[j].display;
    1.99 +            colormap = cmapTable[j].colormap;
   1.100 +            ncolors = cmapTable[j].visual.map_entries;
   1.101 +
   1.102 +            colorcells = SDL_malloc(ncolors * sizeof(XColor));
   1.103 +            if (NULL == colorcells) {
   1.104 +                SDL_SetError("out of memory in X11_SetDisplayGammaRamp");
   1.105 +                return -1;
   1.106 +            }
   1.107 +
   1.108 +            rmax = cmapTable[j].cmap.red_max + 1;
   1.109 +            gmax = cmapTable[j].cmap.blue_max + 1;
   1.110 +            bmax = cmapTable[j].cmap.green_max + 1;
   1.111 +
   1.112 +            rmul = cmapTable[j].cmap.red_mult;
   1.113 +            gmul = cmapTable[j].cmap.blue_mult;
   1.114 +            bmul = cmapTable[j].cmap.green_mult;
   1.115 +
   1.116 +            /* build the color table pixel values */
   1.117 +            for (i = 0; i < ncolors; i++) {
   1.118 +                Uint32 red = (rmax * i) / ncolors;
   1.119 +                Uint32 green = (gmax * i) / ncolors;
   1.120 +                Uint32 blue = (bmax * i) / ncolors;
   1.121 +
   1.122 +                colorcells[i].pixel =
   1.123 +                    (red * rmul) | (green * gmul) | (blue * bmul);
   1.124 +                colorcells[i].flags = DoRed | DoGreen | DoBlue;
   1.125 +
   1.126 +                colorcells[i].red = ramp[(0 * 256) + i];
   1.127 +                colorcells[i].green = ramp[(1 * 256) + i];
   1.128 +                colorcells[i].blue = ramp[(2 * 256) + i];
   1.129 +            }
   1.130 +
   1.131 +            XStoreColors(display, colormap, colorcells, ncolors);
   1.132 +            XFlush(display);
   1.133 +            SDL_free(colorcells);
   1.134 +        }
   1.135 +    }
   1.136 +
   1.137 +    return 0;
   1.138  }
   1.139  
   1.140  int
   1.141  X11_GetDisplayGammaRamp(_THIS, Uint16 * ramp)
   1.142  {
   1.143 -    return -1;
   1.144 +    Display *display;
   1.145 +    Colormap colormap;
   1.146 +    XColor *colorcells;
   1.147 +    int ncolors;
   1.148 +    int dc;
   1.149 +    int i;
   1.150 +
   1.151 +    int rmax, gmax, bmax;
   1.152 +    int rmul, gmul, bmul;
   1.153 +
   1.154 +    /* find the first DirectColor colormap and use it to get the gamma
   1.155 +       ramp */
   1.156 +
   1.157 +    dc = -1;
   1.158 +    for (i = 0; i < numCmaps; i++) {
   1.159 +        if (cmapTable[i].visual.class == DirectColor) {
   1.160 +            dc = i;
   1.161 +            break;
   1.162 +        }
   1.163 +    }
   1.164 +
   1.165 +    if (dc < 0) {
   1.166 +        return -1;
   1.167 +    }
   1.168 +
   1.169 +    /* there is at least one DirectColor colormap in the cmapTable,
   1.170 +       let's just get the entries from that colormap */
   1.171 +
   1.172 +    display = cmapTable[dc].display;
   1.173 +    colormap = cmapTable[dc].colormap;
   1.174 +    ncolors = cmapTable[dc].visual.map_entries;
   1.175 +    colorcells = SDL_malloc(ncolors * sizeof(XColor));
   1.176 +    if (NULL == colorcells) {
   1.177 +        SDL_SetError("out of memory in X11_GetDisplayGammaRamp");
   1.178 +        return -1;
   1.179 +    }
   1.180 +
   1.181 +    rmax = cmapTable[dc].cmap.red_max + 1;
   1.182 +    gmax = cmapTable[dc].cmap.blue_max + 1;
   1.183 +    bmax = cmapTable[dc].cmap.green_max + 1;
   1.184 +
   1.185 +    rmul = cmapTable[dc].cmap.red_mult;
   1.186 +    gmul = cmapTable[dc].cmap.blue_mult;
   1.187 +    bmul = cmapTable[dc].cmap.green_mult;
   1.188 +
   1.189 +    /* build the color table pixel values */
   1.190 +    for (i = 0; i < ncolors; i++) {
   1.191 +        Uint32 red = (rmax * i) / ncolors;
   1.192 +        Uint32 green = (gmax * i) / ncolors;
   1.193 +        Uint32 blue = (bmax * i) / ncolors;
   1.194 +
   1.195 +        colorcells[i].pixel = (red * rmul) | (green * gmul) | (blue * bmul);
   1.196 +    }
   1.197 +
   1.198 +    XQueryColors(display, colormap, colorcells, ncolors);
   1.199 +
   1.200 +    /* prepare the values to be returned. Note that SDL assumes that
   1.201 +       gamma ramps are always 3 * 256 entries long with the red entries
   1.202 +       in the first 256 elements, the green in the second 256 elements
   1.203 +       and the blue in the last 256 elements */
   1.204 +
   1.205 +    for (i = 0; i < ncolors; i++) {
   1.206 +        ramp[(0 * 256) + i] = colorcells[i].red;
   1.207 +        ramp[(1 * 256) + i] = colorcells[i].green;
   1.208 +        ramp[(2 * 256) + i] = colorcells[i].blue;
   1.209 +    }
   1.210 +
   1.211 +    SDL_free(colorcells);
   1.212 +    return 0;
   1.213  }
     2.1 --- a/src/video/x11/SDL_x11gamma.h	Tue Jul 24 18:46:45 2007 +0000
     2.2 +++ b/src/video/x11/SDL_x11gamma.h	Wed Jul 25 21:22:55 2007 +0000
     2.3 @@ -24,8 +24,11 @@
     2.4  #ifndef _SDL_x11gamma_h
     2.5  #define _SDL_x11gamma_h
     2.6  
     2.7 +extern Colormap X11_LookupColormap(Display * display, int scrNum,
     2.8 +                                   VisualID vid);
     2.9  extern void X11_TrackColormap(Display * display, int scrNum,
    2.10 -                              XStandardColormap * cmap, Visual * visual);
    2.11 +                              Colormap colormap, XStandardColormap * cmap,
    2.12 +                              Visual * visual);
    2.13  
    2.14  extern int X11_SetDisplayGammaRamp(_THIS, Uint16 * ramp);
    2.15  extern int X11_GetDisplayGammaRamp(_THIS, Uint16 * ramp);
     3.1 --- a/src/video/x11/SDL_x11window.c	Tue Jul 24 18:46:45 2007 +0000
     3.2 +++ b/src/video/x11/SDL_x11window.c	Wed Jul 25 21:22:55 2007 +0000
     3.3 @@ -181,46 +181,92 @@
     3.4      }
     3.5      xattr.background_pixel = 0;
     3.6      xattr.border_pixel = 0;
     3.7 +
     3.8      if (visual->class == DirectColor || visual->class == PseudoColor) {
     3.9          int nmaps;
    3.10 +        XStandardColormap cmap;
    3.11          XStandardColormap *stdmaps;
    3.12 +        XColor *colorcells;
    3.13 +        Colormap colormap;
    3.14          Bool found = False;
    3.15 +        int i;
    3.16 +        int ncolors;
    3.17 +        int rmax, gmax, bmax;
    3.18 +        int rmul, gmul, bmul;
    3.19  
    3.20 -        /* check to see if the colormap we need already exists */
    3.21 -        if (0 != XGetRGBColormaps(data->display,
    3.22 -                                  RootWindow(data->display,
    3.23 -                                             displaydata->screen), &stdmaps,
    3.24 -                                  &nmaps, XA_RGB_BEST_MAP)) {
    3.25 -            int i;
    3.26 -            for (i = 0; i < nmaps; i++) {
    3.27 -                if (stdmaps[i].visualid == visual->visualid) {
    3.28 -                    xattr.colormap = stdmaps[i].colormap;
    3.29 -                    X11_TrackColormap(data->display, displaydata->screen,
    3.30 -                                      &stdmaps[i], visual);
    3.31 -                    found = True;
    3.32 -                    break;
    3.33 +        if (colormap =
    3.34 +            X11_LookupColormap(data->display, displaydata->screen,
    3.35 +                               visual->visualid)) {
    3.36 +            xattr.colormap = colormap;
    3.37 +        } else {
    3.38 +            /* check to see if the colormap we need already exists */
    3.39 +            if (0 != XGetRGBColormaps(data->display,
    3.40 +                                      RootWindow(data->display,
    3.41 +                                                 displaydata->screen),
    3.42 +                                      &stdmaps, &nmaps, XA_RGB_BEST_MAP)) {
    3.43 +                for (i = 0; i < nmaps; i++) {
    3.44 +                    if (stdmaps[i].visualid == visual->visualid) {
    3.45 +                        SDL_memcpy(&cmap, &stdmaps[i],
    3.46 +                                   sizeof(XStandardColormap));
    3.47 +                        found = True;
    3.48 +                        break;
    3.49 +                    }
    3.50                  }
    3.51 +                XFree(stdmaps);
    3.52              }
    3.53 -            XFree(stdmaps);
    3.54 -        }
    3.55  
    3.56 -        /* it doesn't exist, so create it */
    3.57 -        if (!found) {
    3.58 -            int max = visual->map_entries - 1;
    3.59 -            XStandardColormap *cmap =
    3.60 -                XmuStandardColormap(data->display, displaydata->screen,
    3.61 -                                    visual->visualid, depth,
    3.62 -                                    XA_RGB_BEST_MAP, None,
    3.63 -                                    max, max, max);
    3.64 -            if (NULL != cmap && cmap->visualid == visual->visualid) {
    3.65 -                xattr.colormap = cmap->colormap;
    3.66 -                X11_TrackColormap(data->display, displaydata->screen, cmap,
    3.67 -                                  visual);
    3.68 -            } else {
    3.69 -                SDL_SetError
    3.70 -                    ("Couldn't create window:XA_RGB_BEST_MAP not found");
    3.71 +            /* it doesn't exist, so create it */
    3.72 +            if (!found) {
    3.73 +                int max = visual->map_entries - 1;
    3.74 +                stdmaps =
    3.75 +                    XmuStandardColormap(data->display, displaydata->screen,
    3.76 +                                        visual->visualid, depth,
    3.77 +                                        XA_RGB_BEST_MAP, None, max, max, max);
    3.78 +                if (NULL == stdmaps || stdmaps->visualid != visual->visualid) {
    3.79 +                    SDL_SetError
    3.80 +                        ("Couldn't create window:XA_RGB_BEST_MAP not found and could not be created");
    3.81 +                    return -1;
    3.82 +                }
    3.83 +                SDL_memcpy(&cmap, stdmaps, sizeof(XStandardColormap));
    3.84 +            }
    3.85 +
    3.86 +            /* OK, we have the best color map, now copy it for use by the
    3.87 +               program */
    3.88 +
    3.89 +            colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
    3.90 +            if (NULL == colorcells) {
    3.91 +                SDL_SetError("out of memory in X11_CreateWindow");
    3.92                  return -1;
    3.93              }
    3.94 +            ncolors = visual->map_entries;
    3.95 +            rmax = cmap.red_max + 1;
    3.96 +            gmax = cmap.blue_max + 1;
    3.97 +            bmax = cmap.green_max + 1;
    3.98 +
    3.99 +            rmul = cmap.red_mult;
   3.100 +            gmul = cmap.blue_mult;
   3.101 +            bmul = cmap.green_mult;
   3.102 +
   3.103 +            /* build the color table pixel values */
   3.104 +            for (i = 0; i < ncolors; i++) {
   3.105 +                Uint32 red = (rmax * i) / ncolors;
   3.106 +                Uint32 green = (gmax * i) / ncolors;
   3.107 +                Uint32 blue = (bmax * i) / ncolors;
   3.108 +
   3.109 +                colorcells[i].pixel =
   3.110 +                    (red * rmul) | (green * gmul) | (blue * bmul);
   3.111 +            }
   3.112 +            XQueryColors(data->display, cmap.colormap, colorcells, ncolors);
   3.113 +            colormap = XCreateColormap(data->display,
   3.114 +                                       RootWindow(data->display,
   3.115 +                                                  displaydata->screen),
   3.116 +                                       visual, AllocAll);
   3.117 +            XStoreColors(data->display, colormap, colorcells, ncolors);
   3.118 +            SDL_free(colorcells);
   3.119 +
   3.120 +            xattr.colormap = colormap;
   3.121 +            X11_TrackColormap(data->display, displaydata->screen, colormap,
   3.122 +                              &cmap, visual);
   3.123          }
   3.124      } else {
   3.125          xattr.colormap =