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