src/video/x11/SDL_x11gamma.c
author Bob Pendleton <bob@pendleton.com>
Thu, 26 Jul 2007 17:58:17 +0000
changeset 2216 82a133b784c9
parent 2214 e7164a4dac62
child 2221 1d75c38e1e5c
permissions -rw-r--r--
changed to use SDL_realloc()
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 #include "../SDL_sysvideo.h"
    24 #include "SDL_x11video.h"
    25 
    26 static int numCmaps = 0;
    27 
    28 typedef struct
    29 {
    30     Display *display;
    31     int scrNum;
    32     Colormap colormap;
    33     XStandardColormap cmap;
    34     Visual visual;
    35 } cmapTableEntry;
    36 
    37 cmapTableEntry *cmapTable = NULL;
    38 
    39 /* To reduce the overhead as much as possible lets do as little as
    40    possible. When we do have to create a colormap keep track of it and
    41    reuse it. We're going to do this for both DirectColor and
    42    PseudoColor colormaps. */
    43 
    44 Colormap
    45 X11_LookupColormap(Display * display, int scrNum, VisualID vid)
    46 {
    47     int i;
    48 
    49     for (i = 0; i < numCmaps; i++) {
    50         if (cmapTable[i].display == display &&
    51             cmapTable[i].scrNum == scrNum &&
    52             cmapTable[i].cmap.visualid == vid) {
    53             return cmapTable[i].cmap.colormap;
    54         }
    55     }
    56 
    57     return 0;
    58 }
    59 
    60 
    61 void
    62 X11_TrackColormap(Display * display, int scrNum, Colormap colormap,
    63                   XStandardColormap * cmap, Visual * visual)
    64 {
    65     int i;
    66 
    67     /* search the table to find out if we already have this one. We
    68        only want one entry for each display, screen number, visualid,
    69        and colormap combination */
    70     for (i = 0; i < numCmaps; i++) {
    71         if (cmapTable[i].display == display &&
    72             cmapTable[i].scrNum == scrNum &&
    73             cmapTable[i].cmap.visualid == cmap->visualid &&
    74             cmapTable[i].cmap.colormap == colormap) {
    75             return;
    76         }
    77     }
    78 
    79     /* increase the table by one entry. If the table is NULL create the
    80        first entrty */
    81     cmapTable = SDL_realloc(cmapTable, (numCmaps + 1) * sizeof(cmapTableEntry));
    82     if (NULL == cmapTable) {
    83         SDL_SetError("Out of memory in X11_TrackColormap()");
    84         return;
    85     }
    86 
    87     cmapTable[numCmaps].display = display;
    88     cmapTable[numCmaps].scrNum = scrNum;
    89     cmapTable[numCmaps].colormap = colormap;
    90     SDL_memcpy(&cmapTable[numCmaps].cmap, cmap, sizeof(XStandardColormap));
    91     SDL_memcpy(&cmapTable[numCmaps].visual, visual, sizeof(Visual));
    92 
    93     numCmaps++;
    94 }
    95 
    96 /* The problem is that you have to have at least one DirectColor
    97    colormap before you can set the gamma ramps or read the gamma
    98    ramps. If the application has created a DirectColor window then the
    99    cmapTable will have at least one colormap in it and everything is
   100    cool. If not, then we just fail  */
   101 
   102 int
   103 X11_SetDisplayGammaRamp(_THIS, Uint16 * ramp)
   104 {
   105     Display *display;
   106     Colormap colormap;
   107     XColor *colorcells;
   108     int ncolors;
   109     int i;
   110     int j;
   111 
   112     int rmax, gmax, bmax;
   113     int rmul, gmul, bmul;
   114 
   115     for (j = 0; j < numCmaps; j++) {
   116         if (cmapTable[j].visual.class == DirectColor) {
   117             display = cmapTable[j].display;
   118             colormap = cmapTable[j].colormap;
   119             ncolors = cmapTable[j].visual.map_entries;
   120 
   121             colorcells = SDL_malloc(ncolors * sizeof(XColor));
   122             if (NULL == colorcells) {
   123                 SDL_SetError("out of memory in X11_SetDisplayGammaRamp");
   124                 return -1;
   125             }
   126 
   127             rmax = cmapTable[j].cmap.red_max + 1;
   128             gmax = cmapTable[j].cmap.blue_max + 1;
   129             bmax = cmapTable[j].cmap.green_max + 1;
   130 
   131             rmul = cmapTable[j].cmap.red_mult;
   132             gmul = cmapTable[j].cmap.blue_mult;
   133             bmul = cmapTable[j].cmap.green_mult;
   134 
   135             /* build the color table pixel values */
   136             for (i = 0; i < ncolors; i++) {
   137                 Uint32 red = (rmax * i) / ncolors;
   138                 Uint32 green = (gmax * i) / ncolors;
   139                 Uint32 blue = (bmax * i) / ncolors;
   140 
   141                 colorcells[i].pixel =
   142                     (red * rmul) | (green * gmul) | (blue * bmul);
   143                 colorcells[i].flags = DoRed | DoGreen | DoBlue;
   144 
   145                 colorcells[i].red = ramp[(0 * 256) + i];
   146                 colorcells[i].green = ramp[(1 * 256) + i];
   147                 colorcells[i].blue = ramp[(2 * 256) + i];
   148             }
   149 
   150             XStoreColors(display, colormap, colorcells, ncolors);
   151             XFlush(display);
   152             SDL_free(colorcells);
   153         }
   154     }
   155 
   156     return 0;
   157 }
   158 
   159 int
   160 X11_GetDisplayGammaRamp(_THIS, Uint16 * ramp)
   161 {
   162     Display *display;
   163     Colormap colormap;
   164     XColor *colorcells;
   165     int ncolors;
   166     int dc;
   167     int i;
   168 
   169     int rmax, gmax, bmax;
   170     int rmul, gmul, bmul;
   171 
   172     /* find the first DirectColor colormap and use it to get the gamma
   173        ramp */
   174 
   175     dc = -1;
   176     for (i = 0; i < numCmaps; i++) {
   177         if (cmapTable[i].visual.class == DirectColor) {
   178             dc = i;
   179             break;
   180         }
   181     }
   182 
   183     if (dc < 0) {
   184         return -1;
   185     }
   186 
   187     /* there is at least one DirectColor colormap in the cmapTable,
   188        let's just get the entries from that colormap */
   189 
   190     display = cmapTable[dc].display;
   191     colormap = cmapTable[dc].colormap;
   192     ncolors = cmapTable[dc].visual.map_entries;
   193     colorcells = SDL_malloc(ncolors * sizeof(XColor));
   194     if (NULL == colorcells) {
   195         SDL_SetError("out of memory in X11_GetDisplayGammaRamp");
   196         return -1;
   197     }
   198 
   199     rmax = cmapTable[dc].cmap.red_max + 1;
   200     gmax = cmapTable[dc].cmap.blue_max + 1;
   201     bmax = cmapTable[dc].cmap.green_max + 1;
   202 
   203     rmul = cmapTable[dc].cmap.red_mult;
   204     gmul = cmapTable[dc].cmap.blue_mult;
   205     bmul = cmapTable[dc].cmap.green_mult;
   206 
   207     /* build the color table pixel values */
   208     for (i = 0; i < ncolors; i++) {
   209         Uint32 red = (rmax * i) / ncolors;
   210         Uint32 green = (gmax * i) / ncolors;
   211         Uint32 blue = (bmax * i) / ncolors;
   212 
   213         colorcells[i].pixel = (red * rmul) | (green * gmul) | (blue * bmul);
   214     }
   215 
   216     XQueryColors(display, colormap, colorcells, ncolors);
   217 
   218     /* prepare the values to be returned. Note that SDL assumes that
   219        gamma ramps are always 3 * 256 entries long with the red entries
   220        in the first 256 elements, the green in the second 256 elements
   221        and the blue in the last 256 elements */
   222 
   223     for (i = 0; i < ncolors; i++) {
   224         ramp[(0 * 256) + i] = colorcells[i].red;
   225         ramp[(1 * 256) + i] = colorcells[i].green;
   226         ramp[(2 * 256) + i] = colorcells[i].blue;
   227     }
   228 
   229     SDL_free(colorcells);
   230     return 0;
   231 }