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 //EK#include <GL/vms_x_fix.h>
14 #include <stdio.h> /* SunOS multithreaded assert() needs <stdio.h>. Lame. */
16 #if !defined(_WIN32) && !defined(__OS2__)
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.");
50 #if defined(_WIN32) || defined(__OS2__)
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
91 #if defined(_WIN32) || defined(__OS2__)
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
)
109 #if !defined(_WIN32) && !defined(__OS2__)
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
)
128 #if defined(_WIN32) || defined(__OS2__)
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
;
181 *colormap
= NULL
; /* NULL if RGBA */
183 /* Hewlett-Packard supports a feature called "HP Color
184 Recovery". Mesa has code to use HP Color Recovery. For
185 Mesa to use this feature, the atom
186 _HP_RGB_SMOOTH_MAP_LIST must be defined on the root
187 window AND the colormap obtainable by XGetRGBColormaps
188 for that atom must be set on the window. If that
189 colormap is not set, the output will look stripy. */
191 if (hpColorRecoveryAtom
== -1) {
194 #define VENDOR_HP "Hewlett-Packard"
196 /* Only makes sense to make XInternAtom round-trip if we
197 know that we are connected to an HP X server. */
198 xvendor
= ServerVendor(__glutDisplay
);
199 if (!strncmp(xvendor
, VENDOR_HP
, sizeof(VENDOR_HP
) - 1)) {
200 hpColorRecoveryAtom
= XInternAtom(__glutDisplay
, "_HP_RGB_SMOOTH_MAP_LIST", True
);
202 hpColorRecoveryAtom
= None
;
205 if (hpColorRecoveryAtom
!= None
) {
206 status
= XGetRGBColormaps(__glutDisplay
, __glutRoot
,
207 &standardCmaps
, &numCmaps
, hpColorRecoveryAtom
);
209 for (i
= 0; i
< numCmaps
; i
++) {
210 if (standardCmaps
[i
].visualid
== vi
->visualid
) {
211 *cmap
= standardCmaps
[i
].colormap
;
212 XFree(standardCmaps
);
216 XFree(standardCmaps
);
219 #ifndef SOLARIS_2_4_BUG
220 /* Solaris 2.4 and 2.5 have a bug in their
221 XmuLookupStandardColormap implementations. Please
222 compile your Solaris 2.4 or 2.5 version of GLUT with
223 -DSOLARIS_2_4_BUG to work around this bug. The symptom
224 of the bug is that programs will get a BadMatch error
225 from X_CreateWindow when creating a GLUT window because
226 Solaris 2.4 and 2.5 create a corrupted RGB_DEFAULT_MAP
227 property. Note that this workaround prevents Colormap
228 sharing between applications, perhaps leading
229 unnecessary colormap installations or colormap flashing.
230 Sun fixed this bug in Solaris 2.6. */
231 status
= XmuLookupStandardColormap(__glutDisplay
,
232 vi
->screen
, vi
->visualid
, vi
->depth
, XA_RGB_DEFAULT_MAP
,
233 /* replace */ False
, /* retain */ True
);
235 status
= XGetRGBColormaps(__glutDisplay
, __glutRoot
,
236 &standardCmaps
, &numCmaps
, XA_RGB_DEFAULT_MAP
);
238 for (i
= 0; i
< numCmaps
; i
++) {
239 if (standardCmaps
[i
].visualid
== vi
->visualid
) {
240 *cmap
= standardCmaps
[i
].colormap
;
241 XFree(standardCmaps
);
245 XFree(standardCmaps
);
249 /* If no standard colormap but TrueColor, just make a
251 /* XXX Should do a better job of internal sharing for
252 privately allocated TrueColor colormaps. */
253 /* XXX DirectColor probably needs ramps hand initialized! */
254 *cmap
= XCreateColormap(__glutDisplay
, __glutRoot
,
255 vi
->visual
, AllocNone
);
260 /* Mesa supports these visuals */
262 *cmap
= XCreateColormap(__glutDisplay
, __glutRoot
,
263 vi
->visual
, AllocNone
);
267 "could not allocate colormap for visual type: %d.",
274 #if !defined(_WIN32) && !defined(__OS2__)
276 findColormaps(GLUTwindow
* window
,
277 Window
* winlist
, Colormap
* cmaplist
, int num
, int max
)
282 /* Do not allow more entries that maximum number of
286 /* Is cmap for this window already on the list? */
287 for (i
= 0; i
< num
; i
++) {
288 if (cmaplist
[i
] == window
->cmap
)
289 goto normalColormapAlreadyListed
;
291 /* Not found on the list; add colormap and window. */
292 winlist
[num
] = window
->win
;
293 cmaplist
[num
] = window
->cmap
;
296 normalColormapAlreadyListed
:
298 /* Repeat above but for the overlay colormap if there one. */
299 if (window
->overlay
) {
302 for (i
= 0; i
< num
; i
++) {
303 if (cmaplist
[i
] == window
->overlay
->cmap
)
304 goto overlayColormapAlreadyListed
;
306 winlist
[num
] = window
->overlay
->win
;
307 cmaplist
[num
] = window
->overlay
->cmap
;
310 overlayColormapAlreadyListed
:
312 /* Recursively search children. */
313 child
= window
->children
;
315 num
= findColormaps(child
, winlist
, cmaplist
, num
, max
);
316 child
= child
->siblings
;
322 __glutEstablishColormapsProperty(GLUTwindow
* window
)
324 /* this routine is strictly X. Win32 doesn't need to do
325 anything of this sort (but has to do other wacky stuff
327 static Atom wmColormapWindows
= None
;
333 assert(!window
->parent
);
334 maxcmaps
= MaxCmapsOfScreen(ScreenOfDisplay(__glutDisplay
,
336 /* For portability reasons we don't use alloca for winlist
337 and cmaplist, but we could. */
338 winlist
= (Window
*) malloc(maxcmaps
* sizeof(Window
));
339 cmaplist
= (Colormap
*) malloc(maxcmaps
* sizeof(Colormap
));
340 num
= findColormaps(window
, winlist
, cmaplist
, 0, maxcmaps
);
342 /* Property no longer needed; remove it. */
343 wmColormapWindows
= XSGIFastInternAtom(__glutDisplay
,
344 "WM_COLORMAP_WINDOWS", SGI_XA_WM_COLORMAP_WINDOWS
, False
);
345 if (wmColormapWindows
== None
) {
346 __glutWarning("Could not intern X atom for WM_COLORMAP_WINDOWS.");
349 XDeleteProperty(__glutDisplay
, window
->win
, wmColormapWindows
);
351 status
= XSetWMColormapWindows(__glutDisplay
, window
->win
,
353 /* XSetWMColormapWindows should always work unless the
354 WM_COLORMAP_WINDOWS property cannot be intern'ed. We
357 __glutFatalError("XSetWMColormapWindows returned False.");
359 /* For portability reasons we don't use alloca for winlist
360 and cmaplist, but we could. */
366 __glutToplevelOf(GLUTwindow
* window
)
368 while (window
->parent
) {
369 window
= window
->parent
;
376 __glutFreeColormap(GLUTcolormap
* cmap
)
378 GLUTcolormap
*cur
, **prev
;
381 if (cmap
->refcnt
== 0) {
382 /* remove from colormap list */
383 cur
= __glutColormapList
;
384 prev
= &__glutColormapList
;
393 /* actually free colormap */
394 XFreeColormap(__glutDisplay
, cmap
->cmap
);