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 |
}
|