comparison src/video/Xext/XmuStdCmap/CrCmap.c @ 2185:2032348afed1

This code adds support for DirectColor visuals to SDL 1.3. The support uses part of the Xmu library. To ensure that the library is available and to keep people form having to install yet another library I have added the essential parts of Xmu in src/video/extensions/XmuStdCmap and an include file in src/video/extensions. The support makes use of standard X11 mechanisms to create color maps and make sure that an application uses the same color map for each window/visual combination. This should make it possible for gamma support to be implemented based on a single color map per application. Hurm... it looks like "make indent" modified a few extra files. Those are getting committed too.
author Bob Pendleton <bob@pendleton.com>
date Thu, 12 Jul 2007 20:00:50 +0000
parents
children
comparison
equal deleted inserted replaced
2184:8f8516e79a13 2185:2032348afed1
1 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
2
3 /*
4
5 Copyright 1989, 1998 The Open Group
6
7 Permission to use, copy, modify, distribute, and sell this software and its
8 documentation for any purpose is hereby granted without fee, provided that
9 the above copyright notice appear in all copies and that both that
10 copyright notice and this permission notice appear in supporting
11 documentation.
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23 Except as contained in this notice, the name of The Open Group shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from The Open Group.
26
27 */
28 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.6 2001/01/17 19:42:53 dawes Exp $ */
29
30 /*
31 * Author: Donna Converse, MIT X Consortium
32 */
33
34 /*
35 * CreateCmap.c - given a standard colormap description, make the map.
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <X11/Xlib.h>
44 #include <X11/Xutil.h>
45 #include "../extensions/StdCmap.h"
46
47 /*
48 * Prototypes
49 */
50 /* allocate entire map Read Only */
51 static int ROmap(Display *, Colormap, unsigned long[], int, int);
52
53 /* allocate a cell, prefer Read Only */
54 static Status ROorRWcell(Display *, Colormap, unsigned long[], int,
55 XColor *, unsigned long);
56
57 /* allocate a cell Read Write */
58 static Status RWcell(Display *, Colormap, XColor *, XColor *,
59 unsigned long *);
60
61 /* for quicksort */
62 static int compare(_Xconst void *, _Xconst void *);
63
64 /* find contiguous sequence of cells */
65 static Status contiguous(unsigned long[], int, int, unsigned long, int *,
66 int *);
67
68 /* frees resources before quitting */
69 static void free_cells(Display *, Colormap, unsigned long[], int, int);
70
71 /* create a map in a RO visual type */
72 static Status readonly_map(Display *, XVisualInfo *, XStandardColormap *);
73
74 /* create a map in a RW visual type */
75 static Status readwrite_map(Display *, XVisualInfo *, XStandardColormap *);
76
77 #define lowbit(x) ((x) & (~(x) + 1))
78 #define TRUEMATCH(mult,max,mask) \
79 (colormap->max * colormap->mult <= vinfo->mask && \
80 lowbit(vinfo->mask) == colormap->mult)
81
82 /*
83 * To create any one colormap which is described by an XStandardColormap
84 * structure, use XmuCreateColormap().
85 *
86 * Return 0 on failure, non-zero on success.
87 * Resources created by this function are not made permanent.
88 * No argument error checking is provided. Use at your own risk.
89 *
90 * All colormaps are created with read only allocations, with the exception
91 * of read only allocations of colors in the default map or otherwise
92 * which fail to return the expected pixel value, and these are individually
93 * defined as read/write allocations. This is done so that all the cells
94 * defined in the default map are contiguous, for use in image processing.
95 * This typically happens with White and Black in the default map.
96 *
97 * Colormaps of static visuals are considered to be successfully created if
98 * the map of the static visual matches the definition given in the
99 * standard colormap structure.
100 */
101
102 Status
103 XmuCreateColormap(Display * dpy, XStandardColormap * colormap)
104 /* dpy - specifies the connection under which the map is created
105 * colormap - specifies the map to be created, and returns, particularly
106 * if the map is created as a subset of the default colormap
107 * of the screen, the base_pixel of the map.
108 */
109 {
110 XVisualInfo vinfo_template; /* template visual information */
111 XVisualInfo *vinfo; /* matching visual information */
112 XVisualInfo *vpointer; /* for freeing the entire list */
113 long vinfo_mask; /* specifies the visual mask value */
114 int n; /* number of matching visuals */
115 int status;
116
117 vinfo_template.visualid = colormap->visualid;
118 vinfo_mask = VisualIDMask;
119 if ((vinfo =
120 XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
121 return 0;
122
123 /* A visual id may be valid on multiple screens. Also, there may
124 * be multiple visuals with identical visual ids at different depths.
125 * If the colormap is the Default Colormap, use the Default Visual.
126 * Otherwise, arbitrarily, use the deepest visual.
127 */
128 vpointer = vinfo;
129 if (n > 1) {
130 register int i;
131 register int screen_number;
132 Bool def_cmap;
133
134 def_cmap = False;
135 for (screen_number = ScreenCount(dpy); --screen_number >= 0;)
136 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
137 def_cmap = True;
138 break;
139 }
140
141 if (def_cmap) {
142 for (i = 0; i < n; i++, vinfo++) {
143 if (vinfo->visual == DefaultVisual(dpy, screen_number))
144 break;
145 }
146 } else {
147 int maxdepth = 0;
148 XVisualInfo *v = NULL;
149
150 for (i = 0; i < n; i++, vinfo++)
151 if (vinfo->depth > maxdepth) {
152 maxdepth = vinfo->depth;
153 v = vinfo;
154 }
155 vinfo = v;
156 }
157 }
158
159 if (vinfo->class == PseudoColor || vinfo->class == DirectColor ||
160 vinfo->class == GrayScale)
161 status = readwrite_map(dpy, vinfo, colormap);
162 else if (vinfo->class == TrueColor)
163 status = TRUEMATCH(red_mult, red_max, red_mask) &&
164 TRUEMATCH(green_mult, green_max, green_mask) &&
165 TRUEMATCH(blue_mult, blue_max, blue_mask);
166 else
167 status = readonly_map(dpy, vinfo, colormap);
168
169 XFree((char *) vpointer);
170 return status;
171 }
172
173 /****************************************************************************/
174 static Status
175 readwrite_map(Display * dpy, XVisualInfo * vinfo,
176 XStandardColormap * colormap)
177 {
178 register unsigned long i, n; /* index counters */
179 unsigned long ncolors; /* number of colors to be defined */
180 int npixels; /* number of pixels allocated R/W */
181 int first_index; /* first index of pixels to use */
182 int remainder; /* first index of remainder */
183 XColor color; /* the definition of a color */
184 unsigned long *pixels; /* array of colormap pixels */
185 unsigned long delta;
186
187
188 /* Determine ncolors, the number of colors to be defined.
189 * Insure that 1 < ncolors <= the colormap size.
190 */
191 if (vinfo->class == DirectColor) {
192 ncolors = colormap->red_max;
193 if (colormap->green_max > ncolors)
194 ncolors = colormap->green_max;
195 if (colormap->blue_max > ncolors)
196 ncolors = colormap->blue_max;
197 ncolors++;
198 delta = lowbit(vinfo->red_mask) +
199 lowbit(vinfo->green_mask) + lowbit(vinfo->blue_mask);
200 } else {
201 ncolors = colormap->red_max * colormap->red_mult +
202 colormap->green_max * colormap->green_mult +
203 colormap->blue_max * colormap->blue_mult + 1;
204 delta = 1;
205 }
206 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size)
207 return 0;
208
209 /* Allocate Read/Write as much of the colormap as we can possibly get.
210 * Then insure that the pixels we were allocated are given in
211 * monotonically increasing order, using a quicksort. Next, insure
212 * that our allocation includes a subset of contiguous pixels at least
213 * as long as the number of colors to be defined. Now we know that
214 * these conditions are met:
215 * 1) There are no free cells in the colormap.
216 * 2) We have a contiguous sequence of pixels, monotonically
217 * increasing, of length >= the number of colors requested.
218 *
219 * One cell at a time, we will free, compute the next color value,
220 * then allocate read only. This takes a long time.
221 * This is done to insure that cells are allocated read only in the
222 * contiguous order which we prefer. If the server has a choice of
223 * cells to grant to an allocation request, the server may give us any
224 * cell, so that is why we do these slow gymnastics.
225 */
226
227 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
228 sizeof(unsigned long))) == NULL)
229 return 0;
230
231 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
232 vinfo->colormap_size, ncolors)) == 0) {
233 free((char *) pixels);
234 return 0;
235 }
236
237 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
238
239 if (!contiguous
240 (pixels, npixels, ncolors, delta, &first_index, &remainder)) {
241 /* can't find enough contiguous cells, give up */
242 XFreeColors(dpy, colormap->colormap, pixels, npixels,
243 (unsigned long) 0);
244 free((char *) pixels);
245 return 0;
246 }
247 colormap->base_pixel = pixels[first_index];
248
249 /* construct a gray map */
250 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
251 colormap->blue_mult == 1)
252 for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) {
253 color.pixel = n;
254 color.blue = color.green = color.red =
255 (unsigned short) ((i * 65535) / (colormap->red_max +
256 colormap->green_max +
257 colormap->blue_max));
258
259 if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
260 first_index + i))
261 return 0;
262 }
263
264 /* construct a red ramp map */
265 else if (colormap->green_max == 0 && colormap->blue_max == 0)
266 for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) {
267 color.pixel = n;
268 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
269 color.green = color.blue = 0;
270
271 if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
272 first_index + i))
273 return 0;
274 }
275
276 /* construct a green ramp map */
277 else if (colormap->red_max == 0 && colormap->blue_max == 0)
278 for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) {
279 color.pixel = n;
280 color.green =
281 (unsigned short) ((i * 65535) / colormap->green_max);
282 color.red = color.blue = 0;
283
284 if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
285 first_index + i))
286 return 0;
287 }
288
289 /* construct a blue ramp map */
290 else if (colormap->red_max == 0 && colormap->green_max == 0)
291 for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) {
292 color.pixel = n;
293 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
294 color.red = color.green = 0;
295
296 if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
297 first_index + i))
298 return 0;
299 }
300
301 /* construct a standard red green blue cube map */
302 else {
303 #define calc(max,mult) (((n / colormap->mult) % \
304 (colormap->max + 1)) * 65535) / colormap->max
305
306 for (n = 0, i = 0; i < ncolors; i++, n += delta) {
307 color.pixel = n + colormap->base_pixel;
308 color.red = calc(red_max, red_mult);
309 color.green = calc(green_max, green_mult);
310 color.blue = calc(blue_max, blue_mult);
311 if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
312 first_index + i))
313 return 0;
314 }
315 #undef calc
316 }
317 /* We have a read-only map defined. Now free unused cells,
318 * first those occuring before the contiguous sequence begins,
319 * then any following the contiguous sequence.
320 */
321
322 if (first_index)
323 XFreeColors(dpy, colormap->colormap, pixels, first_index,
324 (unsigned long) 0);
325 if (remainder)
326 XFreeColors(dpy, colormap->colormap,
327 &(pixels[first_index + ncolors]), remainder,
328 (unsigned long) 0);
329
330 free((char *) pixels);
331 return 1;
332 }
333
334
335 /****************************************************************************/
336 static int
337 ROmap(Display * dpy, Colormap cmap, unsigned long pixels[], int m, int n)
338 /*
339 * dpy - the X server connection
340 * cmap - specifies colormap ID
341 * pixels - returns pixel allocations
342 * m - specifies colormap size
343 * n - specifies number of colors
344 */
345 {
346 register int p;
347
348 /* first try to allocate the entire colormap */
349 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
350 (unsigned) 0, pixels, (unsigned) m))
351 return m;
352
353 /* Allocate all available cells in the colormap, using a binary
354 * algorithm to discover how many cells we can allocate in the colormap.
355 */
356 m--;
357 while (n <= m) {
358 p = n + ((m - n + 1) / 2);
359 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
360 (unsigned) 0, pixels, (unsigned) p)) {
361 if (p == m)
362 return p;
363 else {
364 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
365 n = p;
366 }
367 } else
368 m = p - 1;
369 }
370 return 0;
371 }
372
373
374 /****************************************************************************/
375 static Status
376 contiguous(unsigned long pixels[], int npixels, int ncolors,
377 unsigned long delta, int *first, int *rem)
378 /* pixels - specifies allocated pixels
379 * npixels - specifies count of alloc'd pixels
380 * ncolors - specifies needed sequence length
381 * delta - between pixels
382 * first - returns first index of sequence
383 * rem - returns first index after sequence, or 0, if none follow
384 */
385 {
386 register int i = 1; /* walking index into the pixel array */
387 register int count = 1; /* length of sequence discovered so far */
388
389 *first = 0;
390 if (npixels == ncolors) {
391 *rem = 0;
392 return 1;
393 }
394 *rem = npixels - 1;
395 while (count < ncolors && ncolors - count <= *rem) {
396 if (pixels[i - 1] + delta == pixels[i])
397 count++;
398 else {
399 count = 1;
400 *first = i;
401 }
402 i++;
403 (*rem)--;
404 }
405 if (count != ncolors)
406 return 0;
407 return 1;
408 }
409
410
411 /****************************************************************************/
412 static Status
413 ROorRWcell(Display * dpy, Colormap cmap, unsigned long pixels[],
414 int npixels, XColor * color, unsigned long p)
415 {
416 unsigned long pixel;
417 XColor request;
418
419 /* Free the read/write allocation of one cell in the colormap.
420 * Request a read only allocation of one cell in the colormap.
421 * If the read only allocation cannot be granted, give up, because
422 * there must be no free cells in the colormap.
423 * If the read only allocation is granted, but gives us a cell which
424 * is not the one that we just freed, it is probably the case that
425 * we are trying allocate White or Black or some other color which
426 * already has a read-only allocation in the map. So we try to
427 * allocate the previously freed cell with a read/write allocation,
428 * because we want contiguous cells for image processing algorithms.
429 */
430
431 pixel = color->pixel;
432 request.red = color->red;
433 request.green = color->green;
434 request.blue = color->blue;
435
436 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
437 if (!XAllocColor(dpy, cmap, color)
438 || (color->pixel != pixel &&
439 (!RWcell(dpy, cmap, color, &request, &pixel)))) {
440 free_cells(dpy, cmap, pixels, npixels, (int) p);
441 return 0;
442 }
443 return 1;
444 }
445
446
447 /****************************************************************************/
448 static void
449 free_cells(Display * dpy, Colormap cmap, unsigned long pixels[],
450 int npixels, int p)
451 /*
452 * pixels - to be freed
453 * npixels - original number allocated
454 */
455 {
456 /* One of the npixels allocated has already been freed.
457 * p is the index of the freed pixel.
458 * First free the pixels preceeding p, and there are p of them;
459 * then free the pixels following p, there are npixels - p - 1 of them.
460 */
461 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
462 XFreeColors(dpy, cmap, &(pixels[p + 1]), npixels - p - 1,
463 (unsigned long) 0);
464 free((char *) pixels);
465 }
466
467
468 /****************************************************************************/
469 static Status
470 RWcell(Display * dpy, Colormap cmap, XColor * color, XColor * request,
471 unsigned long *pixel)
472 {
473 unsigned long n = *pixel;
474
475 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long) 0);
476 if (!XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
477 (unsigned) 0, pixel, (unsigned) 1))
478 return 0;
479 if (*pixel != n) {
480 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
481 return 0;
482 }
483 color->pixel = *pixel;
484 color->flags = DoRed | DoGreen | DoBlue;
485 color->red = request->red;
486 color->green = request->green;
487 color->blue = request->blue;
488 XStoreColors(dpy, cmap, color, 1);
489 return 1;
490 }
491
492
493 /****************************************************************************/
494 static int
495 compare(_Xconst void *e1, _Xconst void *e2)
496 {
497 return ((int) (*(long *) e1 - *(long *) e2));
498 }
499
500
501 /****************************************************************************/
502 static Status
503 readonly_map(Display * dpy, XVisualInfo * vinfo, XStandardColormap * colormap)
504 {
505 int i, last_pixel;
506 XColor color;
507
508 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
509 (colormap->blue_max + 1) + colormap->base_pixel - 1;
510
511 for (i = colormap->base_pixel; i <= last_pixel; i++) {
512
513 color.pixel = (unsigned long) i;
514 color.red = (unsigned short)
515 (((i / colormap->red_mult) * 65535) / colormap->red_max);
516
517 if (vinfo->class == StaticColor) {
518 color.green = (unsigned short)
519 ((((i / colormap->green_mult) % (colormap->green_max + 1)) *
520 65535) / colormap->green_max);
521 color.blue = (unsigned short)
522 (((i % colormap->green_mult) * 65535) / colormap->blue_max);
523 } else /* vinfo->class == GrayScale, old style allocation XXX */
524 color.green = color.blue = color.red;
525
526 XAllocColor(dpy, colormap->colormap, &color);
527 if (color.pixel != (unsigned long) i)
528 return 0;
529 }
530 return 1;
531 }