src/video/x11/SDL_x11gamma.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 01 Sep 2008 16:04:20 +0000
changeset 2738 79c1bd651f04
parent 2221 1d75c38e1e5c
child 2859 99210400e8b9
permissions -rw-r--r--
Fixed a bunch of compile warnings on Mac OS X
     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 =
    82         SDL_realloc(cmapTable, (numCmaps + 1) * sizeof(cmapTableEntry));
    83     if (NULL == cmapTable) {
    84         SDL_SetError("Out of memory in X11_TrackColormap()");
    85         return;
    86     }
    87 
    88     cmapTable[numCmaps].display = display;
    89     cmapTable[numCmaps].scrNum = scrNum;
    90     cmapTable[numCmaps].colormap = colormap;
    91     SDL_memcpy(&cmapTable[numCmaps].cmap, cmap, sizeof(XStandardColormap));
    92     SDL_memcpy(&cmapTable[numCmaps].visual, visual, sizeof(Visual));
    93 
    94     numCmaps++;
    95 }
    96 
    97 /* The problem is that you have to have at least one DirectColor
    98    colormap before you can set the gamma ramps or read the gamma
    99    ramps. If the application has created a DirectColor window then the
   100    cmapTable will have at least one colormap in it and everything is
   101    cool. If not, then we just fail  */
   102 
   103 int
   104 X11_SetDisplayGammaRamp(_THIS, Uint16 * ramp)
   105 {
   106     Display *display;
   107     Colormap colormap;
   108     XColor *colorcells;
   109     int ncolors;
   110     int i;
   111     int j;
   112 
   113     int rmax, gmax, bmax;
   114     int rmul, gmul, bmul;
   115 
   116     for (j = 0; j < numCmaps; j++) {
   117         if (cmapTable[j].visual.class == DirectColor) {
   118             display = cmapTable[j].display;
   119             colormap = cmapTable[j].colormap;
   120             ncolors = cmapTable[j].visual.map_entries;
   121 
   122             colorcells = SDL_malloc(ncolors * sizeof(XColor));
   123             if (NULL == colorcells) {
   124                 SDL_SetError("out of memory in X11_SetDisplayGammaRamp");
   125                 return -1;
   126             }
   127 
   128             rmax = cmapTable[j].cmap.red_max + 1;
   129             gmax = cmapTable[j].cmap.blue_max + 1;
   130             bmax = cmapTable[j].cmap.green_max + 1;
   131 
   132             rmul = cmapTable[j].cmap.red_mult;
   133             gmul = cmapTable[j].cmap.blue_mult;
   134             bmul = cmapTable[j].cmap.green_mult;
   135 
   136             /* build the color table pixel values */
   137             for (i = 0; i < ncolors; i++) {
   138                 Uint32 red = (rmax * i) / ncolors;
   139                 Uint32 green = (gmax * i) / ncolors;
   140                 Uint32 blue = (bmax * i) / ncolors;
   141 
   142                 colorcells[i].pixel =
   143                     (red * rmul) | (green * gmul) | (blue * bmul);
   144                 colorcells[i].flags = DoRed | DoGreen | DoBlue;
   145 
   146                 colorcells[i].red = ramp[(0 * 256) + i];
   147                 colorcells[i].green = ramp[(1 * 256) + i];
   148                 colorcells[i].blue = ramp[(2 * 256) + i];
   149             }
   150 
   151             XStoreColors(display, colormap, colorcells, ncolors);
   152             XFlush(display);
   153             SDL_free(colorcells);
   154         }
   155     }
   156 
   157     return 0;
   158 }
   159 
   160 int
   161 X11_GetDisplayGammaRamp(_THIS, Uint16 * ramp)
   162 {
   163     Display *display;
   164     Colormap colormap;
   165     XColor *colorcells;
   166     int ncolors;
   167     int dc;
   168     int i;
   169 
   170     int rmax, gmax, bmax;
   171     int rmul, gmul, bmul;
   172 
   173     /* find the first DirectColor colormap and use it to get the gamma
   174        ramp */
   175 
   176     dc = -1;
   177     for (i = 0; i < numCmaps; i++) {
   178         if (cmapTable[i].visual.class == DirectColor) {
   179             dc = i;
   180             break;
   181         }
   182     }
   183 
   184     if (dc < 0) {
   185         return -1;
   186     }
   187 
   188     /* there is at least one DirectColor colormap in the cmapTable,
   189        let's just get the entries from that colormap */
   190 
   191     display = cmapTable[dc].display;
   192     colormap = cmapTable[dc].colormap;
   193     ncolors = cmapTable[dc].visual.map_entries;
   194     colorcells = SDL_malloc(ncolors * sizeof(XColor));
   195     if (NULL == colorcells) {
   196         SDL_SetError("out of memory in X11_GetDisplayGammaRamp");
   197         return -1;
   198     }
   199 
   200     rmax = cmapTable[dc].cmap.red_max + 1;
   201     gmax = cmapTable[dc].cmap.blue_max + 1;
   202     bmax = cmapTable[dc].cmap.green_max + 1;
   203 
   204     rmul = cmapTable[dc].cmap.red_mult;
   205     gmul = cmapTable[dc].cmap.blue_mult;
   206     bmul = cmapTable[dc].cmap.green_mult;
   207 
   208     /* build the color table pixel values */
   209     for (i = 0; i < ncolors; i++) {
   210         Uint32 red = (rmax * i) / ncolors;
   211         Uint32 green = (gmax * i) / ncolors;
   212         Uint32 blue = (bmax * i) / ncolors;
   213 
   214         colorcells[i].pixel = (red * rmul) | (green * gmul) | (blue * bmul);
   215     }
   216 
   217     XQueryColors(display, colormap, colorcells, ncolors);
   218 
   219     /* prepare the values to be returned. Note that SDL assumes that
   220        gamma ramps are always 3 * 256 entries long with the red entries
   221        in the first 256 elements, the green in the second 256 elements
   222        and the blue in the last 256 elements */
   223 
   224     for (i = 0; i < ncolors; i++) {
   225         ramp[(0 * 256) + i] = colorcells[i].red;
   226         ramp[(1 * 256) + i] = colorcells[i].green;
   227         ramp[(2 * 256) + i] = colorcells[i].blue;
   228     }
   229 
   230     SDL_free(colorcells);
   231     return 0;
   232 }