src/video/x11/SDL_x11gamma.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Dec 2009 08:11:06 +0000
changeset 3565 f43c8f688f77
parent 3500 4b594623401b
child 3697 f7b03b6838cb
permissions -rw-r--r--
Fixed bug #906

Added better error reporting for OpenGL context creation failing.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 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     /* The size of *all* SDL gamma ramps */
    27 #define SDL_GammaRampSize (3 * 256 * sizeof(Uint16))
    28 
    29 static int numCmaps = 0;
    30 
    31 typedef struct
    32 {
    33     Display *display;
    34     int scrNum;
    35     Colormap colormap;
    36     Visual visual;
    37     Uint16 *ramp;
    38 } cmapTableEntry;
    39 
    40 cmapTableEntry *cmapTable = NULL;
    41 
    42 /* To reduce the overhead as much as possible lets do as little as
    43    possible. When we do have to create a colormap keep track of it and
    44    reuse it. We're going to do this for both DirectColor and
    45    PseudoColor colormaps. */
    46 
    47 Colormap
    48 X11_LookupColormap(Display * display, int scrNum, VisualID vid)
    49 {
    50     int i;
    51 
    52     for (i = 0; i < numCmaps; i++) {
    53         if (cmapTable[i].display == display &&
    54             cmapTable[i].scrNum == scrNum &&
    55             cmapTable[i].visual.visualid == vid) {
    56             return cmapTable[i].colormap;
    57         }
    58     }
    59 
    60     return 0;
    61 }
    62 
    63 
    64 void
    65 X11_TrackColormap(Display * display, int scrNum, Colormap colormap,
    66                   Visual * visual, XColor * ramp)
    67 {
    68     int i;
    69     Uint16 *newramp;
    70     int ncolors;
    71 
    72     /* search the table to find out if we already have this one. We
    73        only want one entry for each display, screen number, visualid,
    74        and colormap combination */
    75     for (i = 0; i < numCmaps; i++) {
    76         if (cmapTable[i].display == display &&
    77             cmapTable[i].scrNum == scrNum &&
    78             cmapTable[i].visual.visualid == visual->visualid &&
    79             cmapTable[i].colormap == colormap) {
    80             return;
    81         }
    82     }
    83 
    84     /* increase the table by one entry. If the table is NULL create the
    85        first entrty */
    86     cmapTable =
    87         SDL_realloc(cmapTable, (numCmaps + 1) * sizeof(cmapTableEntry));
    88     if (NULL == cmapTable) {
    89         SDL_SetError("Out of memory in X11_TrackColormap()");
    90         return;
    91     }
    92 
    93     cmapTable[numCmaps].display = display;
    94     cmapTable[numCmaps].scrNum = scrNum;
    95     cmapTable[numCmaps].colormap = colormap;
    96     SDL_memcpy(&cmapTable[numCmaps].visual, visual, sizeof(Visual));
    97     cmapTable[numCmaps].ramp = NULL;
    98 
    99     if (ramp != NULL) {
   100         newramp = SDL_malloc(SDL_GammaRampSize);
   101         if (NULL == newramp) {
   102             SDL_SetError("Out of memory in X11_TrackColormap()");
   103             return;
   104         }
   105         SDL_memset(newramp, 0, SDL_GammaRampSize);
   106         cmapTable[numCmaps].ramp = newramp;
   107 
   108         ncolors = cmapTable[numCmaps].visual.map_entries;
   109 
   110         for (i = 0; i < ncolors; i++) {
   111             newramp[(0 * 256) + i] = ramp[i].red;
   112             newramp[(1 * 256) + i] = ramp[i].green;
   113             newramp[(2 * 256) + i] = ramp[i].blue;
   114         }
   115     }
   116 
   117     numCmaps++;
   118 }
   119 
   120 /* The problem is that you have to have at least one DirectColor
   121    colormap before you can set the gamma ramps or read the gamma
   122    ramps. If the application has created a DirectColor window then the
   123    cmapTable will have at least one colormap in it and everything is
   124    cool. If not, then we just fail  */
   125 
   126 int
   127 X11_SetDisplayGammaRamp(_THIS, SDL_VideoDisplay * sdl_display, Uint16 * ramp)
   128 {
   129     Visual *visual;
   130     Display *display;
   131     Colormap colormap;
   132     XColor *colorcells;
   133     int ncolors;
   134     int rmask, gmask, bmask;
   135     int rshift, gshift, bshift;
   136     int i;
   137     int j;
   138 
   139     for (j = 0; j < numCmaps; j++) {
   140         if (cmapTable[j].visual.class == DirectColor) {
   141             display = cmapTable[j].display;
   142             colormap = cmapTable[j].colormap;
   143             ncolors = cmapTable[j].visual.map_entries;
   144             visual = &cmapTable[j].visual;
   145 
   146             colorcells = SDL_malloc(ncolors * sizeof(XColor));
   147             if (NULL == colorcells) {
   148                 SDL_SetError("out of memory in X11_SetDisplayGammaRamp");
   149                 return -1;
   150             }
   151             /* remember the new ramp */
   152             if (cmapTable[j].ramp == NULL) {
   153                 Uint16 *newramp = SDL_malloc(SDL_GammaRampSize);
   154                 if (NULL == newramp) {
   155                     SDL_SetError("Out of memory in X11_TrackColormap()");
   156                     return -1;
   157                 }
   158                 cmapTable[j].ramp = newramp;
   159             }
   160             SDL_memcpy(cmapTable[j].ramp, ramp, SDL_GammaRampSize);
   161 
   162             rshift = 0;
   163             rmask = visual->red_mask;
   164             while (0 == (rmask & 1)) {
   165                 rshift++;
   166                 rmask >>= 1;
   167             }
   168 
   169 /*             printf("rmask = %4x rshift = %4d\n", rmask, rshift); */
   170 
   171             gshift = 0;
   172             gmask = visual->green_mask;
   173             while (0 == (gmask & 1)) {
   174                 gshift++;
   175                 gmask >>= 1;
   176             }
   177 
   178 /*             printf("gmask = %4x gshift = %4d\n", gmask, gshift); */
   179 
   180             bshift = 0;
   181             bmask = visual->blue_mask;
   182             while (0 == (bmask & 1)) {
   183                 bshift++;
   184                 bmask >>= 1;
   185             }
   186 
   187 /*             printf("bmask = %4x bshift = %4d\n", bmask, bshift); */
   188 
   189             /* build the color table pixel values */
   190             for (i = 0; i < ncolors; i++) {
   191                 Uint32 rbits = (rmask * i) / (ncolors - 1);
   192                 Uint32 gbits = (gmask * i) / (ncolors - 1);
   193                 Uint32 bbits = (bmask * i) / (ncolors - 1);
   194 
   195                 Uint32 pix =
   196                     (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
   197 
   198                 colorcells[i].pixel = pix;
   199 
   200                 colorcells[i].flags = DoRed | DoGreen | DoBlue;
   201 
   202                 colorcells[i].red = ramp[(0 * 256) + i];
   203                 colorcells[i].green = ramp[(1 * 256) + i];
   204                 colorcells[i].blue = ramp[(2 * 256) + i];
   205             }
   206 
   207             XStoreColors(display, colormap, colorcells, ncolors);
   208             XFlush(display);
   209             SDL_free(colorcells);
   210         }
   211     }
   212 
   213     return 0;
   214 }
   215 
   216 int
   217 X11_GetDisplayGammaRamp(_THIS, SDL_VideoDisplay * display, Uint16 * ramp)
   218 {
   219     int i;
   220 
   221     /* find the first DirectColor colormap and use it to get the gamma
   222        ramp */
   223 
   224     for (i = 0; i < numCmaps; i++) {
   225         if (cmapTable[i].visual.class == DirectColor) {
   226             SDL_memcpy(ramp, cmapTable[i].ramp, SDL_GammaRampSize);
   227             return 0;
   228         }
   229     }
   230 
   231     return -1;
   232 }