src/video/x11/SDL_x11gamma.c
author Bob Pendleton <bob@pendleton.com>
Wed, 25 Jul 2007 21:22:55 +0000
changeset 2214 e7164a4dac62
parent 2213 59a667370c57
child 2216 82a133b784c9
permissions -rw-r--r--
Added gamma table support to X11. Also now supports DirectColor visuals.
     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     cmapTableEntry *newTable = NULL;
    67 
    68     /* search the table to find out if we already have this one. We
    69        only want one entry for each display, screen number, visualid,
    70        and colormap combination */
    71     for (i = 0; i < numCmaps; i++) {
    72         if (cmapTable[i].display == display &&
    73             cmapTable[i].scrNum == scrNum &&
    74             cmapTable[i].cmap.visualid == cmap->visualid &&
    75             cmapTable[i].cmap.colormap == colormap) {
    76             return;
    77         }
    78     }
    79 
    80     /* increase the table by one entry. If the table is NULL create the
    81        first entrty */
    82     newTable = SDL_malloc((numCmaps + 1) * sizeof(cmapTableEntry));
    83     if (NULL == newTable) {
    84         SDL_SetError("Out of memory in X11_TrackColormap()");
    85         return;
    86     }
    87 
    88     if (NULL != cmapTable) {
    89         SDL_memcpy(newTable, cmapTable, numCmaps * sizeof(cmapTableEntry));
    90         SDL_free(cmapTable);
    91     }
    92     cmapTable = newTable;
    93 
    94     cmapTable[numCmaps].display = display;
    95     cmapTable[numCmaps].scrNum = scrNum;
    96     cmapTable[numCmaps].colormap = colormap;
    97     SDL_memcpy(&cmapTable[numCmaps].cmap, cmap, sizeof(XStandardColormap));
    98     SDL_memcpy(&cmapTable[numCmaps].visual, visual, sizeof(Visual));
    99 
   100     numCmaps++;
   101 }
   102 
   103 /* The problem is that you have to have at least one DirectColor
   104    colormap before you can set the gamma ramps or read the gamma
   105    ramps. If the application has created a DirectColor window then the
   106    cmapTable will have at least one colormap in it and everything is
   107    cool. If not, then we just fail  */
   108 
   109 int
   110 X11_SetDisplayGammaRamp(_THIS, Uint16 * ramp)
   111 {
   112     Display *display;
   113     Colormap colormap;
   114     XColor *colorcells;
   115     int ncolors;
   116     int i;
   117     int j;
   118 
   119     int rmax, gmax, bmax;
   120     int rmul, gmul, bmul;
   121 
   122     for (j = 0; j < numCmaps; j++) {
   123         if (cmapTable[j].visual.class == DirectColor) {
   124             display = cmapTable[j].display;
   125             colormap = cmapTable[j].colormap;
   126             ncolors = cmapTable[j].visual.map_entries;
   127 
   128             colorcells = SDL_malloc(ncolors * sizeof(XColor));
   129             if (NULL == colorcells) {
   130                 SDL_SetError("out of memory in X11_SetDisplayGammaRamp");
   131                 return -1;
   132             }
   133 
   134             rmax = cmapTable[j].cmap.red_max + 1;
   135             gmax = cmapTable[j].cmap.blue_max + 1;
   136             bmax = cmapTable[j].cmap.green_max + 1;
   137 
   138             rmul = cmapTable[j].cmap.red_mult;
   139             gmul = cmapTable[j].cmap.blue_mult;
   140             bmul = cmapTable[j].cmap.green_mult;
   141 
   142             /* build the color table pixel values */
   143             for (i = 0; i < ncolors; i++) {
   144                 Uint32 red = (rmax * i) / ncolors;
   145                 Uint32 green = (gmax * i) / ncolors;
   146                 Uint32 blue = (bmax * i) / ncolors;
   147 
   148                 colorcells[i].pixel =
   149                     (red * rmul) | (green * gmul) | (blue * bmul);
   150                 colorcells[i].flags = DoRed | DoGreen | DoBlue;
   151 
   152                 colorcells[i].red = ramp[(0 * 256) + i];
   153                 colorcells[i].green = ramp[(1 * 256) + i];
   154                 colorcells[i].blue = ramp[(2 * 256) + i];
   155             }
   156 
   157             XStoreColors(display, colormap, colorcells, ncolors);
   158             XFlush(display);
   159             SDL_free(colorcells);
   160         }
   161     }
   162 
   163     return 0;
   164 }
   165 
   166 int
   167 X11_GetDisplayGammaRamp(_THIS, Uint16 * ramp)
   168 {
   169     Display *display;
   170     Colormap colormap;
   171     XColor *colorcells;
   172     int ncolors;
   173     int dc;
   174     int i;
   175 
   176     int rmax, gmax, bmax;
   177     int rmul, gmul, bmul;
   178 
   179     /* find the first DirectColor colormap and use it to get the gamma
   180        ramp */
   181 
   182     dc = -1;
   183     for (i = 0; i < numCmaps; i++) {
   184         if (cmapTable[i].visual.class == DirectColor) {
   185             dc = i;
   186             break;
   187         }
   188     }
   189 
   190     if (dc < 0) {
   191         return -1;
   192     }
   193 
   194     /* there is at least one DirectColor colormap in the cmapTable,
   195        let's just get the entries from that colormap */
   196 
   197     display = cmapTable[dc].display;
   198     colormap = cmapTable[dc].colormap;
   199     ncolors = cmapTable[dc].visual.map_entries;
   200     colorcells = SDL_malloc(ncolors * sizeof(XColor));
   201     if (NULL == colorcells) {
   202         SDL_SetError("out of memory in X11_GetDisplayGammaRamp");
   203         return -1;
   204     }
   205 
   206     rmax = cmapTable[dc].cmap.red_max + 1;
   207     gmax = cmapTable[dc].cmap.blue_max + 1;
   208     bmax = cmapTable[dc].cmap.green_max + 1;
   209 
   210     rmul = cmapTable[dc].cmap.red_mult;
   211     gmul = cmapTable[dc].cmap.blue_mult;
   212     bmul = cmapTable[dc].cmap.green_mult;
   213 
   214     /* build the color table pixel values */
   215     for (i = 0; i < ncolors; i++) {
   216         Uint32 red = (rmax * i) / ncolors;
   217         Uint32 green = (gmax * i) / ncolors;
   218         Uint32 blue = (bmax * i) / ncolors;
   219 
   220         colorcells[i].pixel = (red * rmul) | (green * gmul) | (blue * bmul);
   221     }
   222 
   223     XQueryColors(display, colormap, colorcells, ncolors);
   224 
   225     /* prepare the values to be returned. Note that SDL assumes that
   226        gamma ramps are always 3 * 256 entries long with the red entries
   227        in the first 256 elements, the green in the second 256 elements
   228        and the blue in the last 256 elements */
   229 
   230     for (i = 0; i < ncolors; i++) {
   231         ramp[(0 * 256) + i] = colorcells[i].red;
   232         ramp[(1 * 256) + i] = colorcells[i].green;
   233         ramp[(2 * 256) + i] = colorcells[i].blue;
   234     }
   235 
   236     SDL_free(colorcells);
   237     return 0;
   238 }