2 /* Copyright (c) Mark J. Kilgard, 1994, 1996, 1997. */
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. */
9 #include <GL/vms_x_fix.h>
14 #include <stdio.h> /* SunOS multithreaded assert() needs <stdio.h>. Lame. */
18 #include <X11/Xutil.h>
19 #include <X11/Xatom.h> /* for XA_RGB_DEFAULT_MAP atom */
21 #include <Xmu/StdCmap.h> /* for XmuLookupStandardColormap */
23 #include <X11/Xmu/StdCmap.h> /* for XmuLookupStandardColormap */
27 /* SGI optimization introduced in IRIX 6.3 to avoid X server
28 round trips for interning common X atoms. */
29 #if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS)
30 #include <X11/SGIFastAtom.h>
32 #define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
36 #include "layerutil.h"
38 GLUTcolormap
*__glutColormapList
= NULL
;
41 __glutAssociateNewColormap(XVisualInfo
* vis
)
44 int transparentPixel
, i
;
45 unsigned long pixels
[255];
47 cmap
= (GLUTcolormap
*) malloc(sizeof(GLUTcolormap
));
49 __glutFatalError("out of memory.");
51 pixels
[0] = 0; /* avoid compilation warnings on win32 */
53 cmap
->size
= 256; /* always assume 256 on Win32 */
55 cmap
->visual
= vis
->visual
;
56 cmap
->size
= vis
->visual
->map_entries
;
59 cmap
->cells
= (GLUTcolorcell
*)
60 malloc(sizeof(GLUTcolorcell
) * cmap
->size
);
62 __glutFatalError("out of memory.");
63 /* make all color cell entries be invalid */
64 for (i
= cmap
->size
- 1; i
>= 0; i
--) {
65 cmap
->cells
[i
].component
[GLUT_RED
] = -1.0;
66 cmap
->cells
[i
].component
[GLUT_GREEN
] = -1.0;
67 cmap
->cells
[i
].component
[GLUT_BLUE
] = -1.0;
69 transparentPixel
= __glutGetTransparentPixel(__glutDisplay
, vis
);
70 if (transparentPixel
== -1 || transparentPixel
>= cmap
->size
) {
72 /* If there is no transparent pixel or if the transparent
73 pixel is outside the range of valid colormap cells (HP
74 can implement their overlays this smart way since their
75 transparent pixel is 255), we can AllocAll the colormap.
78 cmap
->cmap
= XCreateColormap(__glutDisplay
,
79 __glutRoot
, cmap
->visual
, AllocAll
);
82 /* On machines where zero (or some other value in the range
83 of 0 through map_entries-1), BadAlloc may be generated
84 when an AllocAll overlay colormap is allocated since the
85 transparent pixel precludes all the cells in the colormap
86 being allocated (the transparent pixel is pre-allocated).
87 So in this case, use XAllocColorCells to allocate
88 map_entries-1 pixels (that is, all but the transparent
92 cmap
->cmap
= XCreateColormap(__glutDisplay
,
93 __glutRoot
, 0, AllocNone
);
95 cmap
->cmap
= XCreateColormap(__glutDisplay
,
96 __glutRoot
, vis
->visual
, AllocNone
);
97 XAllocColorCells(__glutDisplay
, cmap
->cmap
, False
, 0, 0,
98 pixels
, cmap
->size
- 1);
101 cmap
->next
= __glutColormapList
;
102 __glutColormapList
= cmap
;
106 static GLUTcolormap
*
107 associateColormap(XVisualInfo
* vis
)
110 GLUTcolormap
*cmap
= __glutColormapList
;
112 while (cmap
!= NULL
) {
113 /* Play safe: compare visual IDs, not Visual*'s. */
114 if (cmap
->visual
->visualid
== vis
->visual
->visualid
) {
115 /* Already have created colormap for the visual. */
122 return __glutAssociateNewColormap(vis
);
126 __glutSetupColormap(XVisualInfo
* vi
, GLUTcolormap
** colormap
, Colormap
* cmap
)
129 if (vi
->dwFlags
& PFD_NEED_PALETTE
|| vi
->iPixelType
== PFD_TYPE_COLORINDEX
) {
130 *colormap
= associateColormap(vi
);
131 *cmap
= (*colormap
)->cmap
;
138 XStandardColormap
*standardCmaps
;
140 static Atom hpColorRecoveryAtom
= -1;
141 int isRGB
, visualClass
, rc
;
143 #if defined(__cplusplus) || defined(c_plusplus)
144 visualClass
= vi
->c_class
;
146 visualClass
= vi
->class;
148 switch (visualClass
) {
150 /* Mesa might return a PseudoColor visual for RGB mode. */
151 rc
= glXGetConfig(__glutDisplay
, vi
, GLX_RGBA
, &isRGB
);
152 if (rc
== 0 && isRGB
) {
155 if (MaxCmapsOfScreen(DefaultScreenOfDisplay(__glutDisplay
)) == 1
156 && vi
->visual
== DefaultVisual(__glutDisplay
, __glutScreen
)) {
157 char *privateCmap
= getenv("MESA_PRIVATE_CMAP");
160 /* User doesn't want to share colormaps. */
161 *cmap
= XCreateColormap(__glutDisplay
, __glutRoot
,
162 vi
->visual
, AllocNone
);
164 /* Share the root colormap. */
165 *cmap
= DefaultColormap(__glutDisplay
, __glutScreen
);
168 /* Get our own PseudoColor colormap. */
169 *cmap
= XCreateColormap(__glutDisplay
, __glutRoot
,
170 vi
->visual
, AllocNone
);
173 /* CI mode, real GLX never returns a PseudoColor visual
175 *colormap
= associateColormap(vi
);
176 *cmap
= (*colormap
)->cmap
;
180 *colormap
= NULL
; /* NULL if RGBA */
182 /* Hewlett-Packard supports a feature called "HP Color
183 Recovery". Mesa has code to use HP Color Recovery. For
184 Mesa to use this feature, the atom
185 _HP_RGB_SMOOTH_MAP_LIST must be defined on the root
186 window AND the colormap obtainable by XGetRGBColormaps
187 for that atom must be set on the window. If that
188 colormap is not set, the output will look stripy. */
190 if (hpColorRecoveryAtom
== -1) {
193 #define VENDOR_HP "Hewlett-Packard"
195 /* Only makes sense to make XInternAtom round-trip if we
196 know that we are connected to an HP X server. */
197 xvendor
= ServerVendor(__glutDisplay
);
198 if (!strncmp(xvendor
, VENDOR_HP
, sizeof(VENDOR_HP
) - 1)) {
199 hpColorRecoveryAtom
= XInternAtom(__glutDisplay
, "_HP_RGB_SMOOTH_MAP_LIST", True
);
201 hpColorRecoveryAtom
= None
;
204 if (hpColorRecoveryAtom
!= None
) {
205 status
= XGetRGBColormaps(__glutDisplay
, __glutRoot
,
206 &standardCmaps
, &numCmaps
, hpColorRecoveryAtom
);
208 for (i
= 0; i
< numCmaps
; i
++) {
209 if (standardCmaps
[i
].visualid
== vi
->visualid
) {
210 *cmap
= standardCmaps
[i
].colormap
;
211 XFree(standardCmaps
);
215 XFree(standardCmaps
);
218 #ifndef SOLARIS_2_4_BUG
219 /* Solaris 2.4 and 2.5 have a bug in their
220 XmuLookupStandardColormap implementations. Please
221 compile your Solaris 2.4 or 2.5 version of GLUT with
222 -DSOLARIS_2_4_BUG to work around this bug. The symptom
223 of the bug is that programs will get a BadMatch error
224 from X_CreateWindow when creating a GLUT window because
225 Solaris 2.4 and 2.5 create a corrupted RGB_DEFAULT_MAP
226 property. Note that this workaround prevents Colormap
227 sharing between applications, perhaps leading
228 unnecessary colormap installations or colormap flashing.
229 Sun fixed this bug in Solaris 2.6. */
230 status
= XmuLookupStandardColormap(__glutDisplay
,
231 vi
->screen
, vi
->visualid
, vi
->depth
, XA_RGB_DEFAULT_MAP
,
232 /* replace */ False
, /* retain */ True
);
234 status
= XGetRGBColormaps(__glutDisplay
, __glutRoot
,
235 &standardCmaps
, &numCmaps
, XA_RGB_DEFAULT_MAP
);
237 for (i
= 0; i
< numCmaps
; i
++) {
238 if (standardCmaps
[i
].visualid
== vi
->visualid
) {
239 *cmap
= standardCmaps
[i
].colormap
;
240 XFree(standardCmaps
);
244 XFree(standardCmaps
);
248 /* If no standard colormap but TrueColor, just make a
250 /* XXX Should do a better job of internal sharing for
251 privately allocated TrueColor colormaps. */
252 *cmap
= XCreateColormap(__glutDisplay
, __glutRoot
,
253 vi
->visual
, AllocNone
);
256 *colormap
= NULL
; /* NULL if RGBA */
257 *cmap
= XCreateColormap(__glutDisplay
, __glutRoot
,
258 vi
->visual
, AllocAll
);
259 if (vi
->depth
== 24) {
260 /* init the red, green, blue maps to linear ramps */
263 for (i
= 0; i
< 256; i
++) {
264 xc
[i
].pixel
= (i
<< 16) | (i
<< 8) | i
;
265 xc
[i
].red
= (i
<< 8) | i
;
266 xc
[i
].green
= (i
<< 8) | i
;
267 xc
[i
].blue
= (i
<< 8) | i
;
268 xc
[i
].flags
= DoRed
| DoGreen
| DoBlue
;
270 XStoreColors(__glutDisplay
, *cmap
, xc
, 256);
273 fprintf(stderr
, "GLUT Error: DirectColor visuals other than 24-bits "
274 "not fully supported.\n");
280 /* Mesa supports these visuals */
282 *cmap
= XCreateColormap(__glutDisplay
, __glutRoot
,
283 vi
->visual
, AllocNone
);
287 "could not allocate colormap for visual type: %d.",
296 findColormaps(GLUTwindow
* window
,
297 Window
* winlist
, Colormap
* cmaplist
, int num
, int max
)
302 /* Do not allow more entries that maximum number of
306 /* Is cmap for this window already on the list? */
307 for (i
= 0; i
< num
; i
++) {
308 if (cmaplist
[i
] == window
->cmap
)
309 goto normalColormapAlreadyListed
;
311 /* Not found on the list; add colormap and window. */
312 winlist
[num
] = window
->win
;
313 cmaplist
[num
] = window
->cmap
;
316 normalColormapAlreadyListed
:
318 /* Repeat above but for the overlay colormap if there one. */
319 if (window
->overlay
) {
322 for (i
= 0; i
< num
; i
++) {
323 if (cmaplist
[i
] == window
->overlay
->cmap
)
324 goto overlayColormapAlreadyListed
;
326 winlist
[num
] = window
->overlay
->win
;
327 cmaplist
[num
] = window
->overlay
->cmap
;
330 overlayColormapAlreadyListed
:
332 /* Recursively search children. */
333 child
= window
->children
;
335 num
= findColormaps(child
, winlist
, cmaplist
, num
, max
);
336 child
= child
->siblings
;
342 __glutEstablishColormapsProperty(GLUTwindow
* window
)
344 /* this routine is strictly X. Win32 doesn't need to do
345 anything of this sort (but has to do other wacky stuff
347 static Atom wmColormapWindows
= None
;
351 int maxcmaps
, num
, i
;
353 assert(!window
->parent
);
354 maxcmaps
= MaxCmapsOfScreen(ScreenOfDisplay(__glutDisplay
,
356 /* For portability reasons we don't use alloca for winlist
357 and cmaplist, but we could. */
358 winlist
= (Window
*) malloc(maxcmaps
* sizeof(Window
));
359 cmaplist
= (Colormap
*) malloc(maxcmaps
* sizeof(Colormap
));
360 for (i
= 0; i
< maxcmaps
; i
++) {
363 num
= findColormaps(window
, winlist
, cmaplist
, 0, maxcmaps
);
365 /* Property no longer needed; remove it. */
366 wmColormapWindows
= XSGIFastInternAtom(__glutDisplay
,
367 "WM_COLORMAP_WINDOWS", SGI_XA_WM_COLORMAP_WINDOWS
, False
);
368 if (wmColormapWindows
== None
) {
369 __glutWarning("Could not intern X atom for WM_COLORMAP_WINDOWS.");
372 XDeleteProperty(__glutDisplay
, window
->win
, wmColormapWindows
);
374 status
= XSetWMColormapWindows(__glutDisplay
, window
->win
,
376 /* XSetWMColormapWindows should always work unless the
377 WM_COLORMAP_WINDOWS property cannot be intern'ed. We
380 __glutFatalError("XSetWMColormapWindows returned False.");
382 /* For portability reasons we don't use alloca for winlist
383 and cmaplist, but we could. */
389 __glutToplevelOf(GLUTwindow
* window
)
391 while (window
->parent
) {
392 window
= window
->parent
;
399 __glutFreeColormap(GLUTcolormap
* cmap
)
401 GLUTcolormap
*cur
, **prev
;
404 if (cmap
->refcnt
== 0) {
405 /* remove from colormap list */
406 cur
= __glutColormapList
;
407 prev
= &__glutColormapList
;
416 /* actually free colormap */
417 XFreeColormap(__glutDisplay
, cmap
->cmap
);