1
2/* Copyright (c) Mark J. Kilgard, 1993, 1994. */
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/* Based on XLayerUtil.c: Revision: 1.5 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include "layerutil.h"
13
14/* SGI optimization introduced in IRIX 6.3 to avoid X server
15   round trips for interning common X atoms. */
16#if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS)
17#include <X11/SGIFastAtom.h>
18#else
19#define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
20#endif
21
22static Bool layersRead = False;
23static OverlayInfo **overlayInfoPerScreen;
24static unsigned long *numOverlaysPerScreen;
25
26static void
27findServerOverlayVisualsInfo(Display * dpy)
28{
29  static Atom overlayVisualsAtom;
30  Atom actualType;
31  Status status;
32  unsigned long sizeData, bytesLeft;
33  Window root;
34  int actualFormat, numScreens, i;
35
36  if (layersRead == False) {
37    overlayVisualsAtom = XSGIFastInternAtom(dpy,
38      "SERVER_OVERLAY_VISUALS", SGI_XA_SERVER_OVERLAY_VISUALS, True);
39    if (overlayVisualsAtom != None) {
40      numScreens = ScreenCount(dpy);
41      overlayInfoPerScreen = (OverlayInfo **)
42        malloc(numScreens * sizeof(OverlayInfo *));
43      numOverlaysPerScreen = (unsigned long *)
44        malloc(numScreens * sizeof(unsigned long));
45      if (overlayInfoPerScreen != NULL &&
46        numOverlaysPerScreen != NULL) {
47        for (i = 0; i < numScreens; i++) {
48          root = RootWindow(dpy, i);
49          status = XGetWindowProperty(dpy, root,
50            overlayVisualsAtom, 0L, (long) 10000, False,
51            overlayVisualsAtom, &actualType, &actualFormat,
52            &sizeData, &bytesLeft,
53            (unsigned char **) &overlayInfoPerScreen[i]);
54          if (status != Success ||
55            actualType != overlayVisualsAtom ||
56            actualFormat != 32 || sizeData < 4)
57            numOverlaysPerScreen[i] = 0;
58          else
59            /* Four 32-bit quantities per
60               SERVER_OVERLAY_VISUALS entry. */
61            numOverlaysPerScreen[i] = sizeData / 4;
62        }
63        layersRead = True;
64      } else {
65        if (overlayInfoPerScreen != NULL)
66          free(overlayInfoPerScreen);
67        if (numOverlaysPerScreen != NULL)
68          free(numOverlaysPerScreen);
69      }
70    }
71  }
72}
73
74int
75__glutGetTransparentPixel(Display * dpy, XVisualInfo * vinfo)
76{
77  int i, screen = vinfo->screen;
78  OverlayInfo *overlayInfo;
79
80  findServerOverlayVisualsInfo(dpy);
81  if (layersRead) {
82    for (i = 0; i < numOverlaysPerScreen[screen]; i++) {
83      overlayInfo = &overlayInfoPerScreen[screen][i];
84      if (vinfo->visualid == overlayInfo->overlay_visual) {
85        if (overlayInfo->transparent_type == TransparentPixel) {
86          return (int) overlayInfo->value;
87        } else {
88          return -1;
89        }
90      }
91    }
92  }
93  return -1;
94}
95
96XLayerVisualInfo *
97__glutXGetLayerVisualInfo(Display * dpy, long lvinfo_mask,
98  XLayerVisualInfo * lvinfo_template, int *nitems_return)
99{
100  XVisualInfo *vinfo;
101  XLayerVisualInfo *layerInfo;
102  int numVisuals, count, i, j;
103
104  vinfo = XGetVisualInfo(dpy, lvinfo_mask & VisualAllMask,
105    &lvinfo_template->vinfo, nitems_return);
106  if (vinfo == NULL)
107    return NULL;
108  numVisuals = *nitems_return;
109  findServerOverlayVisualsInfo(dpy);
110  layerInfo = (XLayerVisualInfo *)
111    malloc(numVisuals * sizeof(XLayerVisualInfo));
112  if (layerInfo == NULL) {
113    XFree(vinfo);
114    return NULL;
115  }
116  count = 0;
117  for (i = 0; i < numVisuals; i++) {
118    XVisualInfo *pVinfo = &vinfo[i];
119    int screen = pVinfo->screen;
120    OverlayInfo *overlayInfo = NULL;
121
122    overlayInfo = NULL;
123    if (layersRead) {
124      for (j = 0; j < numOverlaysPerScreen[screen]; j++)
125        if (pVinfo->visualid ==
126          overlayInfoPerScreen[screen][j].overlay_visual) {
127          overlayInfo = &overlayInfoPerScreen[screen][j];
128          break;
129        }
130    }
131    if (lvinfo_mask & VisualLayerMask) {
132      if (overlayInfo == NULL) {
133        if (lvinfo_template->layer != 0)
134          continue;
135      } else if (lvinfo_template->layer != overlayInfo->layer)
136        continue;
137    }
138    if (lvinfo_mask & VisualTransparentType) {
139      if (overlayInfo == NULL) {
140        if (lvinfo_template->type != None)
141          continue;
142      } else if (lvinfo_template->type !=
143        overlayInfo->transparent_type)
144        continue;
145    }
146    if (lvinfo_mask & VisualTransparentValue) {
147      if (overlayInfo == NULL)
148        /* Non-overlay visuals have no sense of
149           TransparentValue. */
150        continue;
151      else if (lvinfo_template->value != overlayInfo->value)
152        continue;
153    }
154    layerInfo[count].vinfo = *pVinfo;
155    if (overlayInfo == NULL) {
156      layerInfo[count].layer = 0;
157      layerInfo[count].type = None;
158      layerInfo[count].value = 0;  /* meaningless */
159    } else {
160      layerInfo[count].layer = overlayInfo->layer;
161      layerInfo[count].type = overlayInfo->transparent_type;
162      layerInfo[count].value = overlayInfo->value;
163    }
164    count++;
165  }
166  XFree(vinfo);
167  *nitems_return = count;
168  if (count == 0) {
169    XFree(layerInfo);
170    return NULL;
171  } else
172    return layerInfo;
173}
174
175#if 0                   /* Unused by GLUT. */
176Status
177__glutXMatchLayerVisualInfo(Display * dpy, int screen,
178  int depth, int visualClass, int layer,
179  XLayerVisualInfo * lvinfo_return)
180{
181  XLayerVisualInfo *lvinfo;
182  XLayerVisualInfo lvinfoTemplate;
183  int nitems;
184
185  lvinfoTemplate.vinfo.screen = screen;
186  lvinfoTemplate.vinfo.depth = depth;
187#if defined(__cplusplus) || defined(c_plusplus)
188  lvinfoTemplate.vinfo.c_class = visualClass;
189#else
190  lvinfoTemplate.vinfo.class = visualClass;
191#endif
192  lvinfoTemplate.layer = layer;
193  lvinfo = __glutXGetLayerVisualInfo(dpy,
194    VisualScreenMask | VisualDepthMask |
195    VisualClassMask | VisualLayerMask,
196    &lvinfoTemplate, &nitems);
197  if (lvinfo != NULL && nitems > 0) {
198    *lvinfo_return = *lvinfo;
199    return 1;
200  } else
201    return 0;
202}
203#endif
204