source: trunk/src/opengl/glut/glut_cmap.c

Last change on this file was 2689, checked in by jeroen, 26 years ago

* empty log message *

File size: 12.1 KB
Line 
1/* $Id: glut_cmap.c,v 1.2 2000-02-09 08:46:08 jeroen Exp $ */
2/* Copyright (c) Mark J. Kilgard, 1994, 1996, 1997. */
3
4/* This program is freely distributable without licensing fees
5 and is provided without guarantee or warrantee expressed or
6 implied. This program is -not- in the public domain. */
7
8#include <stdlib.h>
9#include <string.h>
10#include <assert.h>
11#if !defined(_WIN32) && !defined(__WIN32OS2__)
12#include <X11/Xlib.h>
13#include <X11/Xutil.h>
14#include <X11/Xatom.h> /* for XA_RGB_DEFAULT_MAP atom */
15#if defined(__vms)
16#include <Xmu/StdCmap.h> /* for XmuLookupStandardColormap */
17#else
18#include <X11/Xmu/StdCmap.h> /* for XmuLookupStandardColormap */
19#endif
20#endif
21
22/* SGI optimization introduced in IRIX 6.3 to avoid X server
23 round trips for interning common X atoms. */
24#if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS)
25#include <X11/SGIFastAtom.h>
26#else
27#define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
28#endif
29
30#ifdef __WIN32OS2__
31#include "pfddefs.h"
32#endif
33#include "glutint.h"
34#include "layerutil.h"
35
36GLUTcolormap *__glutColormapList = NULL;
37
38GLUTcolormap *
39__glutAssociateNewColormap(XVisualInfo * vis)
40{
41 GLUTcolormap *cmap;
42 int transparentPixel, i;
43 unsigned long pixels[255];
44
45 cmap = (GLUTcolormap *) malloc(sizeof(GLUTcolormap));
46 if (!cmap)
47 __glutFatalError("out of memory.");
48#if defined(_WIN32) || defined(__WIN32OS2__)
49 pixels[0] = 0; /* avoid compilation warnings on win32 */
50 cmap->visual = 0;
51 cmap->size = 256; /* always assume 256 on Win32 */
52#else
53 cmap->visual = vis->visual;
54 cmap->size = vis->visual->map_entries;
55#endif
56 cmap->refcnt = 1;
57 cmap->cells = (GLUTcolorcell *)
58 malloc(sizeof(GLUTcolorcell) * cmap->size);
59 if (!cmap->cells)
60 __glutFatalError("out of memory.");
61 /* make all color cell entries be invalid */
62 for (i = cmap->size - 1; i >= 0; i--) {
63 cmap->cells[i].component[GLUT_RED] = -1.0;
64 cmap->cells[i].component[GLUT_GREEN] = -1.0;
65 cmap->cells[i].component[GLUT_BLUE] = -1.0;
66 }
67 transparentPixel = __glutGetTransparentPixel(__glutDisplay, vis);
68 if (transparentPixel == -1 || transparentPixel >= cmap->size) {
69
70 /* If there is no transparent pixel or if the transparent
71 pixel is outside the range of valid colormap cells (HP
72 can implement their overlays this smart way since their
73 transparent pixel is 255), we can AllocAll the colormap.
74 See note below. */
75
76 cmap->cmap = XCreateColormap(__glutDisplay,
77 __glutRoot, cmap->visual, AllocAll);
78 } else {
79
80 /* On machines where zero (or some other value in the range
81 of 0 through map_entries-1), BadAlloc may be generated
82 when an AllocAll overlay colormap is allocated since the
83 transparent pixel precludes all the cells in the colormap
84 being allocated (the transparent pixel is pre-allocated).
85 So in this case, use XAllocColorCells to allocate
86 map_entries-1 pixels (that is, all but the transparent
87 pixel. */
88
89#if defined(_WIN32) || defined(__WIN32OS2__)
90 cmap->cmap = XCreateColormap(__glutDisplay,
91 __glutRoot, 0, AllocNone);
92#else
93 cmap->cmap = XCreateColormap(__glutDisplay,
94 __glutRoot, vis->visual, AllocNone);
95 XAllocColorCells(__glutDisplay, cmap->cmap, False, 0, 0,
96 pixels, cmap->size - 1);
97#endif
98 }
99 cmap->next = __glutColormapList;
100 __glutColormapList = cmap;
101 return cmap;
102}
103
104static GLUTcolormap *
105associateColormap(XVisualInfo * vis)
106{
107#if !defined(_WIN32) && !defined(__WIN32OS2__)
108 GLUTcolormap *cmap = __glutColormapList;
109
110 while (cmap != NULL) {
111 /* Play safe: compare visual IDs, not Visual*'s. */
112 if (cmap->visual->visualid == vis->visual->visualid) {
113 /* Already have created colormap for the visual. */
114 cmap->refcnt++;
115 return cmap;
116 }
117 cmap = cmap->next;
118 }
119#endif
120 return __glutAssociateNewColormap(vis);
121}
122
123void
124__glutSetupColormap(XVisualInfo * vi, GLUTcolormap ** colormap, Colormap * cmap)
125{
126#if defined(_WIN32) || defined(__WIN32OS2__)
127 if (vi->dwFlags & PFD_NEED_PALETTE || vi->iPixelType == PFD_TYPE_COLORINDEX) {
128 *colormap = associateColormap(vi);
129 *cmap = (*colormap)->cmap;
130 } else {
131 *colormap = NULL;
132 *cmap = 0;
133 }
134#else
135 Status status;
136 XStandardColormap *standardCmaps;
137 int i, numCmaps;
138 static Atom hpColorRecoveryAtom = -1;
139 int isRGB, visualClass, rc;
140
141#if defined(__cplusplus) || defined(c_plusplus)
142 visualClass = vi->c_class;
143#else
144 visualClass = vi->class;
145#endif
146 switch (visualClass) {
147 case PseudoColor:
148 /* Mesa might return a PseudoColor visual for RGB mode. */
149 rc = glXGetConfig(__glutDisplay, vi, GLX_RGBA, &isRGB);
150 if (rc == 0 && isRGB) {
151 /* Must be Mesa. */
152 *colormap = NULL;
153 if (MaxCmapsOfScreen(DefaultScreenOfDisplay(__glutDisplay)) == 1
154 && vi->visual == DefaultVisual(__glutDisplay, __glutScreen)) {
155 char *privateCmap = getenv("MESA_PRIVATE_CMAP");
156
157 if (privateCmap) {
158 /* User doesn't want to share colormaps. */
159 *cmap = XCreateColormap(__glutDisplay, __glutRoot,
160 vi->visual, AllocNone);
161 } else {
162 /* Share the root colormap. */
163 *cmap = DefaultColormap(__glutDisplay, __glutScreen);
164 }
165 } else {
166 /* Get our own PseudoColor colormap. */
167 *cmap = XCreateColormap(__glutDisplay, __glutRoot,
168 vi->visual, AllocNone);
169 }
170 } else {
171 /* CI mode, real GLX never returns a PseudoColor visual
172 for RGB mode. */
173 *colormap = associateColormap(vi);
174 *cmap = (*colormap)->cmap;
175 }
176 break;
177 case TrueColor:
178 case DirectColor:
179 *colormap = NULL; /* NULL if RGBA */
180
181 /* Hewlett-Packard supports a feature called "HP Color
182 Recovery". Mesa has code to use HP Color Recovery. For
183 Mesa to use this feature, the atom
184 _HP_RGB_SMOOTH_MAP_LIST must be defined on the root
185 window AND the colormap obtainable by XGetRGBColormaps
186 for that atom must be set on the window. If that
187 colormap is not set, the output will look stripy. */
188
189 if (hpColorRecoveryAtom == -1) {
190 char *xvendor;
191
192#define VENDOR_HP "Hewlett-Packard"
193
194 /* Only makes sense to make XInternAtom round-trip if we
195 know that we are connected to an HP X server. */
196 xvendor = ServerVendor(__glutDisplay);
197 if (!strncmp(xvendor, VENDOR_HP, sizeof(VENDOR_HP) - 1)) {
198 hpColorRecoveryAtom = XInternAtom(__glutDisplay, "_HP_RGB_SMOOTH_MAP_LIST", True);
199 } else {
200 hpColorRecoveryAtom = None;
201 }
202 }
203 if (hpColorRecoveryAtom != None) {
204 status = XGetRGBColormaps(__glutDisplay, __glutRoot,
205 &standardCmaps, &numCmaps, hpColorRecoveryAtom);
206 if (status == 1) {
207 for (i = 0; i < numCmaps; i++) {
208 if (standardCmaps[i].visualid == vi->visualid) {
209 *cmap = standardCmaps[i].colormap;
210 XFree(standardCmaps);
211 return;
212 }
213 }
214 XFree(standardCmaps);
215 }
216 }
217#ifndef SOLARIS_2_4_BUG
218 /* Solaris 2.4 and 2.5 have a bug in their
219 XmuLookupStandardColormap implementations. Please
220 compile your Solaris 2.4 or 2.5 version of GLUT with
221 -DSOLARIS_2_4_BUG to work around this bug. The symptom
222 of the bug is that programs will get a BadMatch error
223 from X_CreateWindow when creating a GLUT window because
224 Solaris 2.4 and 2.5 create a corrupted RGB_DEFAULT_MAP
225 property. Note that this workaround prevents Colormap
226 sharing between applications, perhaps leading
227 unnecessary colormap installations or colormap flashing.
228 Sun fixed this bug in Solaris 2.6. */
229 status = XmuLookupStandardColormap(__glutDisplay,
230 vi->screen, vi->visualid, vi->depth, XA_RGB_DEFAULT_MAP,
231 /* replace */ False, /* retain */ True);
232 if (status == 1) {
233 status = XGetRGBColormaps(__glutDisplay, __glutRoot,
234 &standardCmaps, &numCmaps, XA_RGB_DEFAULT_MAP);
235 if (status == 1) {
236 for (i = 0; i < numCmaps; i++) {
237 if (standardCmaps[i].visualid == vi->visualid) {
238 *cmap = standardCmaps[i].colormap;
239 XFree(standardCmaps);
240 return;
241 }
242 }
243 XFree(standardCmaps);
244 }
245 }
246#endif
247 /* If no standard colormap but TrueColor, just make a
248 private one. */
249 /* XXX Should do a better job of internal sharing for
250 privately allocated TrueColor colormaps. */
251 /* XXX DirectColor probably needs ramps hand initialized! */
252 *cmap = XCreateColormap(__glutDisplay, __glutRoot,
253 vi->visual, AllocNone);
254 break;
255 case StaticColor:
256 case StaticGray:
257 case GrayScale:
258 /* Mesa supports these visuals */
259 *colormap = NULL;
260 *cmap = XCreateColormap(__glutDisplay, __glutRoot,
261 vi->visual, AllocNone);
262 break;
263 default:
264 __glutFatalError(
265 "could not allocate colormap for visual type: %d.",
266 visualClass);
267 }
268 return;
269#endif
270}
271
272#if !defined(_WIN32) && !defined(__WIN32OS2__)
273static int
274findColormaps(GLUTwindow * window,
275 Window * winlist, Colormap * cmaplist, int num, int max)
276{
277 GLUTwindow *child;
278 int i;
279
280 /* Do not allow more entries that maximum number of
281 colormaps! */
282 if (num >= max)
283 return num;
284 /* Is cmap for this window already on the list? */
285 for (i = 0; i < num; i++) {
286 if (cmaplist[i] == window->cmap)
287 goto normalColormapAlreadyListed;
288 }
289 /* Not found on the list; add colormap and window. */
290 winlist[num] = window->win;
291 cmaplist[num] = window->cmap;
292 num++;
293
294normalColormapAlreadyListed:
295
296 /* Repeat above but for the overlay colormap if there one. */
297 if (window->overlay) {
298 if (num >= max)
299 return num;
300 for (i = 0; i < num; i++) {
301 if (cmaplist[i] == window->overlay->cmap)
302 goto overlayColormapAlreadyListed;
303 }
304 winlist[num] = window->overlay->win;
305 cmaplist[num] = window->overlay->cmap;
306 num++;
307 }
308overlayColormapAlreadyListed:
309
310 /* Recursively search children. */
311 child = window->children;
312 while (child) {
313 num = findColormaps(child, winlist, cmaplist, num, max);
314 child = child->siblings;
315 }
316 return num;
317}
318
319void
320__glutEstablishColormapsProperty(GLUTwindow * window)
321{
322 /* this routine is strictly X. Win32 doesn't need to do
323 anything of this sort (but has to do other wacky stuff
324 later). */
325 static Atom wmColormapWindows = None;
326 Window *winlist;
327 Colormap *cmaplist;
328 Status status;
329 int maxcmaps, num;
330
331 assert(!window->parent);
332 maxcmaps = MaxCmapsOfScreen(ScreenOfDisplay(__glutDisplay,
333 __glutScreen));
334 /* For portability reasons we don't use alloca for winlist
335 and cmaplist, but we could. */
336 winlist = (Window *) malloc(maxcmaps * sizeof(Window));
337 cmaplist = (Colormap *) malloc(maxcmaps * sizeof(Colormap));
338 num = findColormaps(window, winlist, cmaplist, 0, maxcmaps);
339 if (num < 2) {
340 /* Property no longer needed; remove it. */
341 wmColormapWindows = XSGIFastInternAtom(__glutDisplay,
342 "WM_COLORMAP_WINDOWS", SGI_XA_WM_COLORMAP_WINDOWS, False);
343 if (wmColormapWindows == None) {
344 __glutWarning("Could not intern X atom for WM_COLORMAP_WINDOWS.");
345 return;
346 }
347 XDeleteProperty(__glutDisplay, window->win, wmColormapWindows);
348 } else {
349 status = XSetWMColormapWindows(__glutDisplay, window->win,
350 winlist, num);
351 /* XSetWMColormapWindows should always work unless the
352 WM_COLORMAP_WINDOWS property cannot be intern'ed. We
353 check to be safe. */
354 if (status == False)
355 __glutFatalError("XSetWMColormapWindows returned False.");
356 }
357 /* For portability reasons we don't use alloca for winlist
358 and cmaplist, but we could. */
359 free(winlist);
360 free(cmaplist);
361}
362
363GLUTwindow *
364__glutToplevelOf(GLUTwindow * window)
365{
366 while (window->parent) {
367 window = window->parent;
368 }
369 return window;
370}
371#endif
372
373void
374__glutFreeColormap(GLUTcolormap * cmap)
375{
376 GLUTcolormap *cur, **prev;
377
378 cmap->refcnt--;
379 if (cmap->refcnt == 0) {
380 /* remove from colormap list */
381 cur = __glutColormapList;
382 prev = &__glutColormapList;
383 while (cur) {
384 if (cur == cmap) {
385 *prev = cmap->next;
386 break;
387 }
388 prev = &(cur->next);
389 cur = cur->next;
390 }
391 /* actually free colormap */
392 XFreeColormap(__glutDisplay, cmap->cmap);
393 free(cmap->cells);
394 free(cmap);
395 }
396}
397
Note: See TracBrowser for help on using the repository browser.