~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/glut/os2/glut_cmap.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
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
 
#ifdef __VMS
9
 
//EK#include <GL/vms_x_fix.h>
10
 
#endif
11
 
 
12
 
#include <stdlib.h>
13
 
#include <string.h>
14
 
#include <stdio.h>  /* SunOS multithreaded assert() needs <stdio.h>.  Lame. */
15
 
#include <assert.h>
16
 
#if !defined(_WIN32) && !defined(__OS2__)
17
 
 #include <X11/Xlib.h>
18
 
 #include <X11/Xutil.h>
19
 
 #include <X11/Xatom.h>  /* for XA_RGB_DEFAULT_MAP atom */
20
 
 #if defined(__vms)
21
 
   #include <Xmu/StdCmap.h>  /* for XmuLookupStandardColormap */
22
 
 #else
23
 
   #include <X11/Xmu/StdCmap.h>  /* for XmuLookupStandardColormap */
24
 
 #endif
25
 
#endif
26
 
 
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>
31
 
#else
32
 
#define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
33
 
#endif
34
 
 
35
 
#include "glutint.h"
36
 
#include "layerutil.h"
37
 
 
38
 
GLUTcolormap *__glutColormapList = NULL;
39
 
 
40
 
GLUTcolormap *
41
 
__glutAssociateNewColormap(XVisualInfo * vis)
42
 
{
43
 
  GLUTcolormap *cmap;
44
 
  int transparentPixel, i;
45
 
  unsigned long pixels[255];
46
 
 
47
 
  cmap = (GLUTcolormap *) malloc(sizeof(GLUTcolormap));
48
 
  if (!cmap)
49
 
    __glutFatalError("out of memory.");
50
 
#if defined(_WIN32)  || defined(__OS2__)
51
 
  pixels[0] = 0;        /* avoid compilation warnings on win32 */
52
 
  cmap->visual = 0;
53
 
  cmap->size = 256;     /* always assume 256 on Win32 */
54
 
#else
55
 
  cmap->visual = vis->visual;
56
 
  cmap->size = vis->visual->map_entries;
57
 
#endif
58
 
  cmap->refcnt = 1;
59
 
  cmap->cells = (GLUTcolorcell *)
60
 
    malloc(sizeof(GLUTcolorcell) * cmap->size);
61
 
  if (!cmap->cells)
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;
68
 
  }
69
 
  transparentPixel = __glutGetTransparentPixel(__glutDisplay, vis);
70
 
  if (transparentPixel == -1 || transparentPixel >= cmap->size) {
71
 
 
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.
76
 
       See note below.  */
77
 
 
78
 
    cmap->cmap = XCreateColormap(__glutDisplay,
79
 
      __glutRoot, cmap->visual, AllocAll);
80
 
  } else {
81
 
 
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
89
 
       pixel.  */
90
 
 
91
 
#if defined(_WIN32)  || defined(__OS2__)
92
 
    cmap->cmap = XCreateColormap(__glutDisplay,
93
 
      __glutRoot, 0, AllocNone);
94
 
#else
95
 
    cmap->cmap = XCreateColormap(__glutDisplay,
96
 
      __glutRoot, vis->visual, AllocNone);
97
 
    XAllocColorCells(__glutDisplay, cmap->cmap, False, 0, 0,
98
 
      pixels, cmap->size - 1);
99
 
#endif
100
 
  }
101
 
  cmap->next = __glutColormapList;
102
 
  __glutColormapList = cmap;
103
 
  return cmap;
104
 
}
105
 
 
106
 
static GLUTcolormap *
107
 
associateColormap(XVisualInfo * vis)
108
 
{
109
 
#if !defined(_WIN32)  && !defined(__OS2__)
110
 
  GLUTcolormap *cmap = __glutColormapList;
111
 
 
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. */
116
 
      cmap->refcnt++;
117
 
      return cmap;
118
 
    }
119
 
    cmap = cmap->next;
120
 
  }
121
 
#endif
122
 
  return __glutAssociateNewColormap(vis);
123
 
}
124
 
 
125
 
void
126
 
__glutSetupColormap(XVisualInfo * vi, GLUTcolormap ** colormap, Colormap * cmap)
127
 
{
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;
132
 
  } else {
133
 
    *colormap = NULL;
134
 
    *cmap = 0;
135
 
  }
136
 
#else
137
 
  Status status;
138
 
  XStandardColormap *standardCmaps;
139
 
  int i, numCmaps;
140
 
  static Atom hpColorRecoveryAtom = -1;
141
 
  int isRGB, visualClass, rc;
142
 
 
143
 
#if defined(__cplusplus) || defined(c_plusplus)
144
 
  visualClass = vi->c_class;
145
 
#else
146
 
  visualClass = vi->class;
147
 
#endif
148
 
  switch (visualClass) {
149
 
  case PseudoColor:
150
 
    /* Mesa might return a PseudoColor visual for RGB mode. */
151
 
    rc = glXGetConfig(__glutDisplay, vi, GLX_RGBA, &isRGB);
152
 
    if (rc == 0 && isRGB) {
153
 
      /* Must be Mesa. */
154
 
      *colormap = NULL;
155
 
      if (MaxCmapsOfScreen(DefaultScreenOfDisplay(__glutDisplay)) == 1
156
 
        && vi->visual == DefaultVisual(__glutDisplay, __glutScreen)) {
157
 
        char *privateCmap = getenv("MESA_PRIVATE_CMAP");
158
 
 
159
 
        if (privateCmap) {
160
 
          /* User doesn't want to share colormaps. */
161
 
          *cmap = XCreateColormap(__glutDisplay, __glutRoot,
162
 
            vi->visual, AllocNone);
163
 
        } else {
164
 
          /* Share the root colormap. */
165
 
          *cmap = DefaultColormap(__glutDisplay, __glutScreen);
166
 
        }
167
 
      } else {
168
 
        /* Get our own PseudoColor colormap. */
169
 
        *cmap = XCreateColormap(__glutDisplay, __glutRoot,
170
 
          vi->visual, AllocNone);
171
 
      }
172
 
    } else {
173
 
      /* CI mode, real GLX never returns a PseudoColor visual
174
 
         for RGB mode. */
175
 
      *colormap = associateColormap(vi);
176
 
      *cmap = (*colormap)->cmap;
177
 
    }
178
 
    break;
179
 
  case TrueColor:
180
 
  case DirectColor:
181
 
    *colormap = NULL;   /* NULL if RGBA */
182
 
 
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. */
190
 
 
191
 
    if (hpColorRecoveryAtom == -1) {
192
 
      char *xvendor;
193
 
 
194
 
#define VENDOR_HP "Hewlett-Packard"
195
 
 
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);
201
 
      } else {
202
 
        hpColorRecoveryAtom = None;
203
 
      }
204
 
    }
205
 
    if (hpColorRecoveryAtom != None) {
206
 
      status = XGetRGBColormaps(__glutDisplay, __glutRoot,
207
 
        &standardCmaps, &numCmaps, hpColorRecoveryAtom);
208
 
      if (status == 1) {
209
 
        for (i = 0; i < numCmaps; i++) {
210
 
          if (standardCmaps[i].visualid == vi->visualid) {
211
 
            *cmap = standardCmaps[i].colormap;
212
 
            XFree(standardCmaps);
213
 
            return;
214
 
          }
215
 
        }
216
 
        XFree(standardCmaps);
217
 
      }
218
 
    }
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);
234
 
    if (status == 1) {
235
 
      status = XGetRGBColormaps(__glutDisplay, __glutRoot,
236
 
        &standardCmaps, &numCmaps, XA_RGB_DEFAULT_MAP);
237
 
      if (status == 1) {
238
 
        for (i = 0; i < numCmaps; i++) {
239
 
          if (standardCmaps[i].visualid == vi->visualid) {
240
 
            *cmap = standardCmaps[i].colormap;
241
 
            XFree(standardCmaps);
242
 
            return;
243
 
          }
244
 
        }
245
 
        XFree(standardCmaps);
246
 
      }
247
 
    }
248
 
#endif
249
 
    /* If no standard colormap but TrueColor, just make a
250
 
       private one. */
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);
256
 
    break;
257
 
  case StaticColor:
258
 
  case StaticGray:
259
 
  case GrayScale:
260
 
    /* Mesa supports these visuals */
261
 
    *colormap = NULL;
262
 
    *cmap = XCreateColormap(__glutDisplay, __glutRoot,
263
 
      vi->visual, AllocNone);
264
 
    break;
265
 
  default:
266
 
    __glutFatalError(
267
 
      "could not allocate colormap for visual type: %d.",
268
 
      visualClass);
269
 
  }
270
 
  return;
271
 
#endif
272
 
}
273
 
 
274
 
#if !defined(_WIN32)  && !defined(__OS2__)
275
 
static int
276
 
findColormaps(GLUTwindow * window,
277
 
  Window * winlist, Colormap * cmaplist, int num, int max)
278
 
{
279
 
  GLUTwindow *child;
280
 
  int i;
281
 
 
282
 
  /* Do not allow more entries that maximum number of
283
 
     colormaps! */
284
 
  if (num >= max)
285
 
    return num;
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;
290
 
  }
291
 
  /* Not found on the list; add colormap and window. */
292
 
  winlist[num] = window->win;
293
 
  cmaplist[num] = window->cmap;
294
 
  num++;
295
 
 
296
 
normalColormapAlreadyListed:
297
 
 
298
 
  /* Repeat above but for the overlay colormap if there one. */
299
 
  if (window->overlay) {
300
 
    if (num >= max)
301
 
      return num;
302
 
    for (i = 0; i < num; i++) {
303
 
      if (cmaplist[i] == window->overlay->cmap)
304
 
        goto overlayColormapAlreadyListed;
305
 
    }
306
 
    winlist[num] = window->overlay->win;
307
 
    cmaplist[num] = window->overlay->cmap;
308
 
    num++;
309
 
  }
310
 
overlayColormapAlreadyListed:
311
 
 
312
 
  /* Recursively search children. */
313
 
  child = window->children;
314
 
  while (child) {
315
 
    num = findColormaps(child, winlist, cmaplist, num, max);
316
 
    child = child->siblings;
317
 
  }
318
 
  return num;
319
 
}
320
 
 
321
 
void
322
 
__glutEstablishColormapsProperty(GLUTwindow * window)
323
 
{
324
 
  /* this routine is strictly X.  Win32 doesn't need to do
325
 
     anything of this sort (but has to do other wacky stuff
326
 
     later). */
327
 
  static Atom wmColormapWindows = None;
328
 
  Window *winlist;
329
 
  Colormap *cmaplist;
330
 
  Status status;
331
 
  int maxcmaps, num;
332
 
 
333
 
  assert(!window->parent);
334
 
  maxcmaps = MaxCmapsOfScreen(ScreenOfDisplay(__glutDisplay,
335
 
      __glutScreen));
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);
341
 
  if (num < 2) {
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.");
347
 
      return;
348
 
    }
349
 
    XDeleteProperty(__glutDisplay, window->win, wmColormapWindows);
350
 
  } else {
351
 
    status = XSetWMColormapWindows(__glutDisplay, window->win,
352
 
      winlist, num);
353
 
    /* XSetWMColormapWindows should always work unless the
354
 
       WM_COLORMAP_WINDOWS property cannot be intern'ed.  We
355
 
       check to be safe. */
356
 
    if (status == False)
357
 
      __glutFatalError("XSetWMColormapWindows returned False.");
358
 
  }
359
 
  /* For portability reasons we don't use alloca for winlist
360
 
     and cmaplist, but we could. */
361
 
  free(winlist);
362
 
  free(cmaplist);
363
 
}
364
 
 
365
 
GLUTwindow *
366
 
__glutToplevelOf(GLUTwindow * window)
367
 
{
368
 
  while (window->parent) {
369
 
    window = window->parent;
370
 
  }
371
 
  return window;
372
 
}
373
 
#endif
374
 
 
375
 
void
376
 
__glutFreeColormap(GLUTcolormap * cmap)
377
 
{
378
 
  GLUTcolormap *cur, **prev;
379
 
 
380
 
  cmap->refcnt--;
381
 
  if (cmap->refcnt == 0) {
382
 
    /* remove from colormap list */
383
 
    cur = __glutColormapList;
384
 
    prev = &__glutColormapList;
385
 
    while (cur) {
386
 
      if (cur == cmap) {
387
 
        *prev = cmap->next;
388
 
        break;
389
 
      }
390
 
      prev = &(cur->next);
391
 
      cur = cur->next;
392
 
    }
393
 
    /* actually free colormap */
394
 
    XFreeColormap(__glutDisplay, cmap->cmap);
395
 
    free(cmap->cells);
396
 
    free(cmap);
397
 
  }
398
 
}
399