glxext.c revision 01e04c3f
1cdc920a0Smrg/*
2cdc920a0Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3cdc920a0Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4cdc920a0Smrg *
5cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6cdc920a0Smrg * copy of this software and associated documentation files (the "Software"),
7cdc920a0Smrg * to deal in the Software without restriction, including without limitation
8cdc920a0Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9cdc920a0Smrg * and/or sell copies of the Software, and to permit persons to whom the
10cdc920a0Smrg * Software is furnished to do so, subject to the following conditions:
11cdc920a0Smrg *
12cdc920a0Smrg * The above copyright notice including the dates of first publication and
13cdc920a0Smrg * either this permission notice or a reference to
14cdc920a0Smrg * http://oss.sgi.com/projects/FreeB/
15cdc920a0Smrg * shall be included in all copies or substantial portions of the Software.
16cdc920a0Smrg *
17cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18cdc920a0Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19cdc920a0Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20cdc920a0Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21cdc920a0Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22cdc920a0Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23cdc920a0Smrg * SOFTWARE.
24cdc920a0Smrg *
25cdc920a0Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc.
26cdc920a0Smrg * shall not be used in advertising or otherwise to promote the sale, use or
27cdc920a0Smrg * other dealings in this Software without prior written authorization from
28cdc920a0Smrg * Silicon Graphics, Inc.
29cdc920a0Smrg */
30cdc920a0Smrg
31cdc920a0Smrg/**
32cdc920a0Smrg * \file glxext.c
33cdc920a0Smrg * GLX protocol interface boot-strap code.
34cdc920a0Smrg *
35cdc920a0Smrg * Direct rendering support added by Precision Insight, Inc.
36cdc920a0Smrg *
37cdc920a0Smrg * \author Kevin E. Martin <kevin@precisioninsight.com>
38cdc920a0Smrg */
39cdc920a0Smrg
40cdc920a0Smrg#include <assert.h>
4101e04c3fSmrg#include <stdbool.h>
4201e04c3fSmrg
43cdc920a0Smrg#include "glxclient.h"
44cdc920a0Smrg#include <X11/extensions/Xext.h>
45cdc920a0Smrg#include <X11/extensions/extutil.h>
46cdc920a0Smrg#ifdef GLX_USE_APPLEGL
47af69d88dSmrg#include "apple/apple_glx.h"
48af69d88dSmrg#include "apple/apple_visual.h"
49cdc920a0Smrg#endif
50cdc920a0Smrg#include "glxextensions.h"
51cdc920a0Smrg
5201e04c3fSmrg#include "util/debug.h"
5301e04c3fSmrg
54cdc920a0Smrg#include <X11/Xlib-xcb.h>
55cdc920a0Smrg#include <xcb/xcb.h>
56cdc920a0Smrg#include <xcb/glx.h>
57cdc920a0Smrg
58cdc920a0Smrg
59cdc920a0Smrg#ifdef DEBUG
603464ebd5Sriastradhvoid __glXDumpDrawBuffer(struct glx_context * ctx);
61cdc920a0Smrg#endif
62cdc920a0Smrg
63cdc920a0Smrg/*
64cdc920a0Smrg** You can set this cell to 1 to force the gl drawing stuff to be
65cdc920a0Smrg** one command per packet
66cdc920a0Smrg*/
67cdc920a0Smrg_X_HIDDEN int __glXDebug = 0;
68cdc920a0Smrg
69cdc920a0Smrg/* Extension required boiler plate */
70cdc920a0Smrg
713464ebd5Sriastradhstatic const char __glXExtensionName[] = GLX_EXTENSION_NAME;
723464ebd5Sriastradh  static struct glx_display *glx_displays;
73cdc920a0Smrg
74cdc920a0Smrgstatic /* const */ char *error_list[] = {
75cdc920a0Smrg   "GLXBadContext",
76cdc920a0Smrg   "GLXBadContextState",
77cdc920a0Smrg   "GLXBadDrawable",
78cdc920a0Smrg   "GLXBadPixmap",
79cdc920a0Smrg   "GLXBadContextTag",
80cdc920a0Smrg   "GLXBadCurrentWindow",
81cdc920a0Smrg   "GLXBadRenderRequest",
82cdc920a0Smrg   "GLXBadLargeRequest",
83cdc920a0Smrg   "GLXUnsupportedPrivateRequest",
84cdc920a0Smrg   "GLXBadFBConfig",
85cdc920a0Smrg   "GLXBadPbuffer",
86cdc920a0Smrg   "GLXBadCurrentDrawable",
87cdc920a0Smrg   "GLXBadWindow",
88af69d88dSmrg   "GLXBadProfileARB",
89cdc920a0Smrg};
90cdc920a0Smrg
91cdc920a0Smrg#ifdef GLX_USE_APPLEGL
92cdc920a0Smrgstatic char *__glXErrorString(Display *dpy, int code, XExtCodes *codes,
93cdc920a0Smrg                              char *buf, int n);
94cdc920a0Smrg#endif
95cdc920a0Smrg
96cdc920a0Smrgstatic
97cdc920a0SmrgXEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
98cdc920a0Smrg                           __GLX_NUMBER_ERRORS, error_list)
99cdc920a0Smrg
100cdc920a0Smrg/*
101cdc920a0Smrg * GLX events are a bit funky.  We don't stuff the X event code into
102cdc920a0Smrg * our user exposed (via XNextEvent) structure.  Instead we use the GLX
103cdc920a0Smrg * private event code namespace (and hope it doesn't conflict).  Clients
104cdc920a0Smrg * have to know that bit 15 in the event type field means they're getting
105cdc920a0Smrg * a GLX event, and then handle the various sub-event types there, rather
106cdc920a0Smrg * than simply checking the event code and handling it directly.
107cdc920a0Smrg */
108cdc920a0Smrg
109cdc920a0Smrgstatic Bool
110cdc920a0Smrg__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
111cdc920a0Smrg{
1123464ebd5Sriastradh     struct glx_display *glx_dpy = __glXInitialize(dpy);
113cdc920a0Smrg
1143464ebd5Sriastradh   if (glx_dpy == NULL)
1153464ebd5Sriastradh      return False;
116cdc920a0Smrg
1173464ebd5Sriastradh   switch ((wire->u.u.type & 0x7f) - glx_dpy->codes->first_event) {
118cdc920a0Smrg   case GLX_PbufferClobber:
119cdc920a0Smrg   {
120cdc920a0Smrg      GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event;
121cdc920a0Smrg      xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire;
122cdc920a0Smrg      aevent->event_type = awire->type;
123cdc920a0Smrg      aevent->serial = awire->sequenceNumber;
124cdc920a0Smrg      aevent->event_type = awire->event_type;
125cdc920a0Smrg      aevent->draw_type = awire->draw_type;
126cdc920a0Smrg      aevent->drawable = awire->drawable;
127cdc920a0Smrg      aevent->buffer_mask = awire->buffer_mask;
128cdc920a0Smrg      aevent->aux_buffer = awire->aux_buffer;
129cdc920a0Smrg      aevent->x = awire->x;
130cdc920a0Smrg      aevent->y = awire->y;
131cdc920a0Smrg      aevent->width = awire->width;
132cdc920a0Smrg      aevent->height = awire->height;
133cdc920a0Smrg      aevent->count = awire->count;
134cdc920a0Smrg      return True;
135cdc920a0Smrg   }
136cdc920a0Smrg   case GLX_BufferSwapComplete:
137cdc920a0Smrg   {
138cdc920a0Smrg      GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
139af69d88dSmrg      xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire;
140af69d88dSmrg      struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable);
141af69d88dSmrg
142af69d88dSmrg      if (!glxDraw)
143af69d88dSmrg	 return False;
144af69d88dSmrg
14501e04c3fSmrg      aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
14601e04c3fSmrg      aevent->send_event = (awire->type & 0x80) != 0;
14701e04c3fSmrg      aevent->display = dpy;
148cdc920a0Smrg      aevent->event_type = awire->event_type;
149af69d88dSmrg      aevent->drawable = glxDraw->xDrawable;
150cdc920a0Smrg      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
151cdc920a0Smrg      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
152af69d88dSmrg
15301e04c3fSmrg      /* Handle 32-Bit wire sbc wraparound in both directions to cope with out
15401e04c3fSmrg       * of sequence 64-Bit sbc's
15501e04c3fSmrg       */
15601e04c3fSmrg      if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000))
15701e04c3fSmrg         glxDraw->eventSbcWrap += 0x100000000;
15801e04c3fSmrg      if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000))
15901e04c3fSmrg         glxDraw->eventSbcWrap -= 0x100000000;
160af69d88dSmrg      glxDraw->lastEventSbc = awire->sbc;
161af69d88dSmrg      aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
162cdc920a0Smrg      return True;
163cdc920a0Smrg   }
164cdc920a0Smrg   default:
165cdc920a0Smrg      /* client doesn't support server event */
166cdc920a0Smrg      break;
167cdc920a0Smrg   }
168cdc920a0Smrg
169cdc920a0Smrg   return False;
170cdc920a0Smrg}
171cdc920a0Smrg
172cdc920a0Smrg/* We don't actually support this.  It doesn't make sense for clients to
173cdc920a0Smrg * send each other GLX events.
174cdc920a0Smrg */
175cdc920a0Smrgstatic Status
176cdc920a0Smrg__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
177cdc920a0Smrg{
1783464ebd5Sriastradh     struct glx_display *glx_dpy = __glXInitialize(dpy);
179cdc920a0Smrg
1803464ebd5Sriastradh   if (glx_dpy == NULL)
1813464ebd5Sriastradh      return False;
182cdc920a0Smrg
183cdc920a0Smrg   switch (event->type) {
184cdc920a0Smrg   case GLX_DAMAGED:
185cdc920a0Smrg      break;
186cdc920a0Smrg   case GLX_SAVED:
187cdc920a0Smrg      break;
188cdc920a0Smrg   case GLX_EXCHANGE_COMPLETE_INTEL:
189cdc920a0Smrg      break;
190cdc920a0Smrg   case GLX_COPY_COMPLETE_INTEL:
191cdc920a0Smrg      break;
192cdc920a0Smrg   case GLX_FLIP_COMPLETE_INTEL:
193cdc920a0Smrg      break;
194cdc920a0Smrg   default:
195cdc920a0Smrg      /* client doesn't support server event */
196cdc920a0Smrg      break;
197cdc920a0Smrg   }
198cdc920a0Smrg
199cdc920a0Smrg   return Success;
200cdc920a0Smrg}
201cdc920a0Smrg
202cdc920a0Smrg/************************************************************************/
203cdc920a0Smrg/*
204cdc920a0Smrg** Free the per screen configs data as well as the array of
205cdc920a0Smrg** __glXScreenConfigs.
206cdc920a0Smrg*/
207cdc920a0Smrgstatic void
2083464ebd5SriastradhFreeScreenConfigs(struct glx_display * priv)
209cdc920a0Smrg{
2103464ebd5Sriastradh   struct glx_screen *psc;
211cdc920a0Smrg   GLint i, screens;
212cdc920a0Smrg
213cdc920a0Smrg   /* Free screen configuration information */
214cdc920a0Smrg   screens = ScreenCount(priv->dpy);
2153464ebd5Sriastradh   for (i = 0; i < screens; i++) {
2163464ebd5Sriastradh      psc = priv->screens[i];
2173464ebd5Sriastradh      glx_screen_cleanup(psc);
218cdc920a0Smrg
219cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
220cdc920a0Smrg      if (psc->driScreen) {
221cdc920a0Smrg         psc->driScreen->destroyScreen(psc);
2223464ebd5Sriastradh      } else {
223af69d88dSmrg	 free(psc);
224cdc920a0Smrg      }
2253464ebd5Sriastradh#else
226af69d88dSmrg      free(psc);
227cdc920a0Smrg#endif
228cdc920a0Smrg   }
229af69d88dSmrg   free((char *) priv->screens);
2303464ebd5Sriastradh   priv->screens = NULL;
231cdc920a0Smrg}
232cdc920a0Smrg
2333464ebd5Sriastradhstatic void
2343464ebd5Sriastradhglx_display_free(struct glx_display *priv)
235cdc920a0Smrg{
2363464ebd5Sriastradh   struct glx_context *gc;
2373464ebd5Sriastradh
2383464ebd5Sriastradh   gc = __glXGetCurrentContext();
2393464ebd5Sriastradh   if (priv->dpy == gc->currentDpy) {
2403464ebd5Sriastradh      gc->vtable->destroy(gc);
2413464ebd5Sriastradh      __glXSetCurrentContextNull();
2423464ebd5Sriastradh   }
243cdc920a0Smrg
244cdc920a0Smrg   FreeScreenConfigs(priv);
245af69d88dSmrg   free((char *) priv->serverGLXvendor);
246af69d88dSmrg   free((char *) priv->serverGLXversion);
247af69d88dSmrg
248af69d88dSmrg   __glxHashDestroy(priv->glXDrawHash);
249cdc920a0Smrg
250cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
2513464ebd5Sriastradh   __glxHashDestroy(priv->drawHash);
2523464ebd5Sriastradh
253cdc920a0Smrg   /* Free the direct rendering per display data */
254cdc920a0Smrg   if (priv->driswDisplay)
255cdc920a0Smrg      (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
256cdc920a0Smrg   priv->driswDisplay = NULL;
257cdc920a0Smrg
258af69d88dSmrg#if defined (GLX_USE_DRM)
259cdc920a0Smrg   if (priv->driDisplay)
260cdc920a0Smrg      (*priv->driDisplay->destroyDisplay) (priv->driDisplay);
261cdc920a0Smrg   priv->driDisplay = NULL;
262cdc920a0Smrg
263cdc920a0Smrg   if (priv->dri2Display)
264cdc920a0Smrg      (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
265cdc920a0Smrg   priv->dri2Display = NULL;
266cdc920a0Smrg
267af69d88dSmrg   if (priv->dri3Display)
268af69d88dSmrg      (*priv->dri3Display->destroyDisplay) (priv->dri3Display);
269af69d88dSmrg   priv->dri3Display = NULL;
270af69d88dSmrg#endif /* GLX_USE_DRM */
27101e04c3fSmrg
27201e04c3fSmrg#if defined(GLX_USE_WINDOWSGL)
27301e04c3fSmrg   if (priv->windowsdriDisplay)
27401e04c3fSmrg      (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay);
27501e04c3fSmrg   priv->windowsdriDisplay = NULL;
27601e04c3fSmrg#endif /* GLX_USE_WINDOWSGL */
27701e04c3fSmrg
278af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
279af69d88dSmrg
280af69d88dSmrg   free((char *) priv);
281cdc920a0Smrg}
282cdc920a0Smrg
2833464ebd5Sriastradhstatic int
2843464ebd5Sriastradh__glXCloseDisplay(Display * dpy, XExtCodes * codes)
2853464ebd5Sriastradh{
2863464ebd5Sriastradh   struct glx_display *priv, **prev;
2873464ebd5Sriastradh
2883464ebd5Sriastradh   _XLockMutex(_Xglobal_lock);
2893464ebd5Sriastradh   prev = &glx_displays;
2903464ebd5Sriastradh   for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
2913464ebd5Sriastradh      if (priv->dpy == dpy) {
2923464ebd5Sriastradh         *prev = priv->next;
2933464ebd5Sriastradh	 break;
2943464ebd5Sriastradh      }
2953464ebd5Sriastradh   }
2963464ebd5Sriastradh   _XUnlockMutex(_Xglobal_lock);
2973464ebd5Sriastradh
298af69d88dSmrg   if (priv != NULL)
299af69d88dSmrg      glx_display_free(priv);
3003464ebd5Sriastradh
3013464ebd5Sriastradh   return 1;
3023464ebd5Sriastradh}
303cdc920a0Smrg
304cdc920a0Smrg/*
305cdc920a0Smrg** Query the version of the GLX extension.  This procedure works even if
306cdc920a0Smrg** the client extension is not completely set up.
307cdc920a0Smrg*/
308cdc920a0Smrgstatic Bool
309cdc920a0SmrgQueryVersion(Display * dpy, int opcode, int *major, int *minor)
310cdc920a0Smrg{
311cdc920a0Smrg   xcb_connection_t *c = XGetXCBConnection(dpy);
312cdc920a0Smrg   xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c,
313cdc920a0Smrg                                                                      xcb_glx_query_version
314cdc920a0Smrg                                                                      (c,
315cdc920a0Smrg                                                                       GLX_MAJOR_VERSION,
316cdc920a0Smrg                                                                       GLX_MINOR_VERSION),
317cdc920a0Smrg                                                                      NULL);
318cdc920a0Smrg
319af69d88dSmrg   if (!reply)
320af69d88dSmrg     return GL_FALSE;
321af69d88dSmrg
322cdc920a0Smrg   if (reply->major_version != GLX_MAJOR_VERSION) {
323cdc920a0Smrg      free(reply);
324cdc920a0Smrg      return GL_FALSE;
325cdc920a0Smrg   }
326cdc920a0Smrg   *major = reply->major_version;
327cdc920a0Smrg   *minor = min(reply->minor_version, GLX_MINOR_VERSION);
328cdc920a0Smrg   free(reply);
329cdc920a0Smrg   return GL_TRUE;
330cdc920a0Smrg}
331cdc920a0Smrg
332cdc920a0Smrg/*
333cdc920a0Smrg * We don't want to enable this GLX_OML_swap_method in glxext.h,
334cdc920a0Smrg * because we can't support it.  The X server writes it out though,
335cdc920a0Smrg * so we should handle it somehow, to avoid false warnings.
336cdc920a0Smrg */
337cdc920a0Smrgenum {
338cdc920a0Smrg    IGNORE_GLX_SWAP_METHOD_OML = 0x8060
339cdc920a0Smrg};
340cdc920a0Smrg
341cdc920a0Smrg
3423464ebd5Sriastradhstatic GLint
3433464ebd5Sriastradhconvert_from_x_visual_type(int visualType)
3443464ebd5Sriastradh{
3453464ebd5Sriastradh   static const int glx_visual_types[] = {
34601e04c3fSmrg      [StaticGray]  = GLX_STATIC_GRAY,
34701e04c3fSmrg      [GrayScale]   = GLX_GRAY_SCALE,
34801e04c3fSmrg      [StaticColor] = GLX_STATIC_COLOR,
34901e04c3fSmrg      [PseudoColor] = GLX_PSEUDO_COLOR,
35001e04c3fSmrg      [TrueColor]   = GLX_TRUE_COLOR,
35101e04c3fSmrg      [DirectColor] = GLX_DIRECT_COLOR,
3523464ebd5Sriastradh   };
3533464ebd5Sriastradh
3543464ebd5Sriastradh   if (visualType < ARRAY_SIZE(glx_visual_types))
3553464ebd5Sriastradh      return glx_visual_types[visualType];
3563464ebd5Sriastradh
3573464ebd5Sriastradh   return GLX_NONE;
3583464ebd5Sriastradh}
3593464ebd5Sriastradh
360cdc920a0Smrg/*
361cdc920a0Smrg * getVisualConfigs uses the !tagged_only path.
362cdc920a0Smrg * getFBConfigs uses the tagged_only path.
363cdc920a0Smrg */
364cdc920a0Smrg_X_HIDDEN void
3653464ebd5Sriastradh__glXInitializeVisualConfigFromTags(struct glx_config * config, int count,
366cdc920a0Smrg                                    const INT32 * bp, Bool tagged_only,
367cdc920a0Smrg                                    Bool fbconfig_style_tags)
368cdc920a0Smrg{
369cdc920a0Smrg   int i;
370af69d88dSmrg   GLint renderType = 0;
371cdc920a0Smrg
372cdc920a0Smrg   if (!tagged_only) {
373cdc920a0Smrg      /* Copy in the first set of properties */
374cdc920a0Smrg      config->visualID = *bp++;
375cdc920a0Smrg
3763464ebd5Sriastradh      config->visualType = convert_from_x_visual_type(*bp++);
377cdc920a0Smrg
378cdc920a0Smrg      config->rgbMode = *bp++;
379cdc920a0Smrg
380cdc920a0Smrg      config->redBits = *bp++;
381cdc920a0Smrg      config->greenBits = *bp++;
382cdc920a0Smrg      config->blueBits = *bp++;
383cdc920a0Smrg      config->alphaBits = *bp++;
384cdc920a0Smrg      config->accumRedBits = *bp++;
385cdc920a0Smrg      config->accumGreenBits = *bp++;
386cdc920a0Smrg      config->accumBlueBits = *bp++;
387cdc920a0Smrg      config->accumAlphaBits = *bp++;
388cdc920a0Smrg
389cdc920a0Smrg      config->doubleBufferMode = *bp++;
390cdc920a0Smrg      config->stereoMode = *bp++;
391cdc920a0Smrg
392cdc920a0Smrg      config->rgbBits = *bp++;
393cdc920a0Smrg      config->depthBits = *bp++;
394cdc920a0Smrg      config->stencilBits = *bp++;
395cdc920a0Smrg      config->numAuxBuffers = *bp++;
396cdc920a0Smrg      config->level = *bp++;
397cdc920a0Smrg
398cdc920a0Smrg#ifdef GLX_USE_APPLEGL
399cdc920a0Smrg       /* AppleSGLX supports pixmap and pbuffers with all config. */
400cdc920a0Smrg       config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
401cdc920a0Smrg       /* Unfortunately this can create an ABI compatibility problem. */
402cdc920a0Smrg       count -= 18;
403cdc920a0Smrg#else
404cdc920a0Smrg      count -= __GLX_MIN_CONFIG_PROPS;
405cdc920a0Smrg#endif
406cdc920a0Smrg   }
407cdc920a0Smrg
408cdc920a0Smrg   /*
409cdc920a0Smrg    ** Additional properties may be in a list at the end
410cdc920a0Smrg    ** of the reply.  They are in pairs of property type
411cdc920a0Smrg    ** and property value.
412cdc920a0Smrg    */
413cdc920a0Smrg
414cdc920a0Smrg#define FETCH_OR_SET(tag) \
415cdc920a0Smrg    config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
416cdc920a0Smrg
417cdc920a0Smrg   for (i = 0; i < count; i += 2) {
418cdc920a0Smrg      long int tag = *bp++;
419cdc920a0Smrg
420cdc920a0Smrg      switch (tag) {
421cdc920a0Smrg      case GLX_RGBA:
422cdc920a0Smrg         FETCH_OR_SET(rgbMode);
423cdc920a0Smrg         break;
424cdc920a0Smrg      case GLX_BUFFER_SIZE:
425cdc920a0Smrg         config->rgbBits = *bp++;
426cdc920a0Smrg         break;
427cdc920a0Smrg      case GLX_LEVEL:
428cdc920a0Smrg         config->level = *bp++;
429cdc920a0Smrg         break;
430cdc920a0Smrg      case GLX_DOUBLEBUFFER:
431cdc920a0Smrg         FETCH_OR_SET(doubleBufferMode);
432cdc920a0Smrg         break;
433cdc920a0Smrg      case GLX_STEREO:
434cdc920a0Smrg         FETCH_OR_SET(stereoMode);
435cdc920a0Smrg         break;
436cdc920a0Smrg      case GLX_AUX_BUFFERS:
437cdc920a0Smrg         config->numAuxBuffers = *bp++;
438cdc920a0Smrg         break;
439cdc920a0Smrg      case GLX_RED_SIZE:
440cdc920a0Smrg         config->redBits = *bp++;
441cdc920a0Smrg         break;
442cdc920a0Smrg      case GLX_GREEN_SIZE:
443cdc920a0Smrg         config->greenBits = *bp++;
444cdc920a0Smrg         break;
445cdc920a0Smrg      case GLX_BLUE_SIZE:
446cdc920a0Smrg         config->blueBits = *bp++;
447cdc920a0Smrg         break;
448cdc920a0Smrg      case GLX_ALPHA_SIZE:
449cdc920a0Smrg         config->alphaBits = *bp++;
450cdc920a0Smrg         break;
451cdc920a0Smrg      case GLX_DEPTH_SIZE:
452cdc920a0Smrg         config->depthBits = *bp++;
453cdc920a0Smrg         break;
454cdc920a0Smrg      case GLX_STENCIL_SIZE:
455cdc920a0Smrg         config->stencilBits = *bp++;
456cdc920a0Smrg         break;
457cdc920a0Smrg      case GLX_ACCUM_RED_SIZE:
458cdc920a0Smrg         config->accumRedBits = *bp++;
459cdc920a0Smrg         break;
460cdc920a0Smrg      case GLX_ACCUM_GREEN_SIZE:
461cdc920a0Smrg         config->accumGreenBits = *bp++;
462cdc920a0Smrg         break;
463cdc920a0Smrg      case GLX_ACCUM_BLUE_SIZE:
464cdc920a0Smrg         config->accumBlueBits = *bp++;
465cdc920a0Smrg         break;
466cdc920a0Smrg      case GLX_ACCUM_ALPHA_SIZE:
467cdc920a0Smrg         config->accumAlphaBits = *bp++;
468cdc920a0Smrg         break;
469cdc920a0Smrg      case GLX_VISUAL_CAVEAT_EXT:
470cdc920a0Smrg         config->visualRating = *bp++;
471cdc920a0Smrg         break;
472cdc920a0Smrg      case GLX_X_VISUAL_TYPE:
473cdc920a0Smrg         config->visualType = *bp++;
474cdc920a0Smrg         break;
475cdc920a0Smrg      case GLX_TRANSPARENT_TYPE:
476cdc920a0Smrg         config->transparentPixel = *bp++;
477cdc920a0Smrg         break;
478cdc920a0Smrg      case GLX_TRANSPARENT_INDEX_VALUE:
479cdc920a0Smrg         config->transparentIndex = *bp++;
480cdc920a0Smrg         break;
481cdc920a0Smrg      case GLX_TRANSPARENT_RED_VALUE:
482cdc920a0Smrg         config->transparentRed = *bp++;
483cdc920a0Smrg         break;
484cdc920a0Smrg      case GLX_TRANSPARENT_GREEN_VALUE:
485cdc920a0Smrg         config->transparentGreen = *bp++;
486cdc920a0Smrg         break;
487cdc920a0Smrg      case GLX_TRANSPARENT_BLUE_VALUE:
488cdc920a0Smrg         config->transparentBlue = *bp++;
489cdc920a0Smrg         break;
490cdc920a0Smrg      case GLX_TRANSPARENT_ALPHA_VALUE:
491cdc920a0Smrg         config->transparentAlpha = *bp++;
492cdc920a0Smrg         break;
493cdc920a0Smrg      case GLX_VISUAL_ID:
494cdc920a0Smrg         config->visualID = *bp++;
495cdc920a0Smrg         break;
496cdc920a0Smrg      case GLX_DRAWABLE_TYPE:
497cdc920a0Smrg         config->drawableType = *bp++;
498cdc920a0Smrg#ifdef GLX_USE_APPLEGL
499cdc920a0Smrg         /* AppleSGLX supports pixmap and pbuffers with all config. */
500cdc920a0Smrg         config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
501cdc920a0Smrg#endif
502cdc920a0Smrg         break;
503af69d88dSmrg      case GLX_RENDER_TYPE: /* fbconfig render type bits */
504af69d88dSmrg         renderType = *bp++;
505cdc920a0Smrg         break;
506cdc920a0Smrg      case GLX_X_RENDERABLE:
507cdc920a0Smrg         config->xRenderable = *bp++;
508cdc920a0Smrg         break;
509cdc920a0Smrg      case GLX_FBCONFIG_ID:
510cdc920a0Smrg         config->fbconfigID = *bp++;
511cdc920a0Smrg         break;
512cdc920a0Smrg      case GLX_MAX_PBUFFER_WIDTH:
513cdc920a0Smrg         config->maxPbufferWidth = *bp++;
514cdc920a0Smrg         break;
515cdc920a0Smrg      case GLX_MAX_PBUFFER_HEIGHT:
516cdc920a0Smrg         config->maxPbufferHeight = *bp++;
517cdc920a0Smrg         break;
518cdc920a0Smrg      case GLX_MAX_PBUFFER_PIXELS:
519cdc920a0Smrg         config->maxPbufferPixels = *bp++;
520cdc920a0Smrg         break;
521cdc920a0Smrg#ifndef GLX_USE_APPLEGL
522cdc920a0Smrg      case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
523cdc920a0Smrg         config->optimalPbufferWidth = *bp++;
524cdc920a0Smrg         break;
525cdc920a0Smrg      case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
526cdc920a0Smrg         config->optimalPbufferHeight = *bp++;
527cdc920a0Smrg         break;
528cdc920a0Smrg      case GLX_VISUAL_SELECT_GROUP_SGIX:
529cdc920a0Smrg         config->visualSelectGroup = *bp++;
530cdc920a0Smrg         break;
531cdc920a0Smrg      case GLX_SWAP_METHOD_OML:
53201e04c3fSmrg         if (*bp == GLX_SWAP_UNDEFINED_OML ||
53301e04c3fSmrg             *bp == GLX_SWAP_COPY_OML ||
53401e04c3fSmrg             *bp == GLX_SWAP_EXCHANGE_OML) {
53501e04c3fSmrg            config->swapMethod = *bp++;
53601e04c3fSmrg         } else {
53701e04c3fSmrg            /* X servers with old HW drivers may return any value here, so
53801e04c3fSmrg             * assume GLX_SWAP_METHOD_UNDEFINED.
53901e04c3fSmrg             */
54001e04c3fSmrg            config->swapMethod = GLX_SWAP_UNDEFINED_OML;
54101e04c3fSmrg            bp++;
54201e04c3fSmrg         }
543cdc920a0Smrg         break;
544cdc920a0Smrg#endif
545cdc920a0Smrg      case GLX_SAMPLE_BUFFERS_SGIS:
546cdc920a0Smrg         config->sampleBuffers = *bp++;
547cdc920a0Smrg         break;
548cdc920a0Smrg      case GLX_SAMPLES_SGIS:
549cdc920a0Smrg         config->samples = *bp++;
550cdc920a0Smrg         break;
551cdc920a0Smrg#ifdef GLX_USE_APPLEGL
552cdc920a0Smrg      case IGNORE_GLX_SWAP_METHOD_OML:
553cdc920a0Smrg         /* We ignore this tag.  See the comment above this function. */
554cdc920a0Smrg         ++bp;
555cdc920a0Smrg         break;
556cdc920a0Smrg#else
557cdc920a0Smrg      case GLX_BIND_TO_TEXTURE_RGB_EXT:
558cdc920a0Smrg         config->bindToTextureRgb = *bp++;
559cdc920a0Smrg         break;
560cdc920a0Smrg      case GLX_BIND_TO_TEXTURE_RGBA_EXT:
561cdc920a0Smrg         config->bindToTextureRgba = *bp++;
562cdc920a0Smrg         break;
563cdc920a0Smrg      case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
564cdc920a0Smrg         config->bindToMipmapTexture = *bp++;
565cdc920a0Smrg         break;
566cdc920a0Smrg      case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
567cdc920a0Smrg         config->bindToTextureTargets = *bp++;
568cdc920a0Smrg         break;
569cdc920a0Smrg      case GLX_Y_INVERTED_EXT:
570cdc920a0Smrg         config->yInverted = *bp++;
571cdc920a0Smrg         break;
572cdc920a0Smrg#endif
5733464ebd5Sriastradh      case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
5743464ebd5Sriastradh         config->sRGBCapable = *bp++;
5753464ebd5Sriastradh         break;
5763464ebd5Sriastradh
577cdc920a0Smrg      case GLX_USE_GL:
578cdc920a0Smrg         if (fbconfig_style_tags)
579cdc920a0Smrg            bp++;
580cdc920a0Smrg         break;
581cdc920a0Smrg      case None:
582cdc920a0Smrg         i = count;
583cdc920a0Smrg         break;
584cdc920a0Smrg      default:
58501e04c3fSmrg         if(env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) {
586cdc920a0Smrg             long int tagvalue = *bp++;
587cdc920a0Smrg             fprintf(stderr, "WARNING: unknown GLX tag from server: "
588cdc920a0Smrg                     "tag 0x%lx value 0x%lx\n", tag, tagvalue);
589cdc920a0Smrg         } else {
590cdc920a0Smrg             /* Ignore the unrecognized tag's value */
591cdc920a0Smrg             bp++;
592cdc920a0Smrg         }
5933464ebd5Sriastradh         break;
594cdc920a0Smrg      }
595cdc920a0Smrg   }
596cdc920a0Smrg
597af69d88dSmrg   if (renderType != 0 && renderType != GLX_DONT_CARE) {
598af69d88dSmrg      config->renderType = renderType;
599af69d88dSmrg      config->floatMode = (renderType &
600af69d88dSmrg         (GLX_RGBA_FLOAT_BIT_ARB|GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT)) != 0;
601af69d88dSmrg   } else {
602af69d88dSmrg      /* If there wasn't GLX_RENDER_TYPE property, set it based on
603af69d88dSmrg       * config->rgbMode.  The only way to communicate that the config is
604af69d88dSmrg       * floating-point is via GLX_RENDER_TYPE, so this cannot be a float
605af69d88dSmrg       * config.
606af69d88dSmrg       */
607af69d88dSmrg      config->renderType =
608af69d88dSmrg         (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
609af69d88dSmrg   }
610af69d88dSmrg
611af69d88dSmrg   /* The GLX_ARB_fbconfig_float spec says:
612af69d88dSmrg    *
613af69d88dSmrg    *     "Note that floating point rendering is only supported for
614af69d88dSmrg    *     GLXPbuffer drawables."
615af69d88dSmrg    */
616af69d88dSmrg   if (config->floatMode)
61701e04c3fSmrg      config->drawableType &= GLX_PBUFFER_BIT;
618cdc920a0Smrg}
619cdc920a0Smrg
6203464ebd5Sriastradhstatic struct glx_config *
621cdc920a0SmrgcreateConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
622cdc920a0Smrg                            int screen, GLboolean tagged_only)
623cdc920a0Smrg{
624cdc920a0Smrg   INT32 buf[__GLX_TOTAL_CONFIG], *props;
625cdc920a0Smrg   unsigned prop_size;
6263464ebd5Sriastradh   struct glx_config *modes, *m;
627cdc920a0Smrg   int i;
628cdc920a0Smrg
629cdc920a0Smrg   if (nprops == 0)
630cdc920a0Smrg      return NULL;
631cdc920a0Smrg
632cdc920a0Smrg   /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
633cdc920a0Smrg
634cdc920a0Smrg   /* Check number of properties */
635cdc920a0Smrg   if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
636cdc920a0Smrg      return NULL;
637cdc920a0Smrg
638cdc920a0Smrg   /* Allocate memory for our config structure */
6393464ebd5Sriastradh   modes = glx_config_create_list(nvisuals);
640cdc920a0Smrg   if (!modes)
641cdc920a0Smrg      return NULL;
642cdc920a0Smrg
643cdc920a0Smrg   prop_size = nprops * __GLX_SIZE_INT32;
644cdc920a0Smrg   if (prop_size <= sizeof(buf))
645cdc920a0Smrg      props = buf;
646cdc920a0Smrg   else
647af69d88dSmrg      props = malloc(prop_size);
648cdc920a0Smrg
649cdc920a0Smrg   /* Read each config structure and convert it into our format */
650cdc920a0Smrg   m = modes;
651cdc920a0Smrg   for (i = 0; i < nvisuals; i++) {
652cdc920a0Smrg      _XRead(dpy, (char *) props, prop_size);
653cdc920a0Smrg#ifdef GLX_USE_APPLEGL
654cdc920a0Smrg       /* Older X servers don't send this so we default it here. */
655cdc920a0Smrg      m->drawableType = GLX_WINDOW_BIT;
656cdc920a0Smrg#else
657cdc920a0Smrg      /*
658cdc920a0Smrg       * The XQuartz 2.3.2.1 X server doesn't set this properly, so
659cdc920a0Smrg       * set the proper bits here.
660cdc920a0Smrg       * AppleSGLX supports windows, pixmaps, and pbuffers with all config.
661cdc920a0Smrg       */
662cdc920a0Smrg      m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
663cdc920a0Smrg#endif
66401e04c3fSmrg      /* Older X servers don't send this so we default it here. */
66501e04c3fSmrg      m->sRGBCapable = GL_FALSE;
666cdc920a0Smrg       __glXInitializeVisualConfigFromTags(m, nprops, props,
667cdc920a0Smrg                                          tagged_only, GL_TRUE);
668cdc920a0Smrg      m->screen = screen;
669cdc920a0Smrg      m = m->next;
670cdc920a0Smrg   }
671cdc920a0Smrg
672cdc920a0Smrg   if (props != buf)
673af69d88dSmrg      free(props);
674cdc920a0Smrg
675cdc920a0Smrg   return modes;
676cdc920a0Smrg}
677cdc920a0Smrg
678cdc920a0Smrgstatic GLboolean
6793464ebd5SriastradhgetVisualConfigs(struct glx_screen *psc,
6803464ebd5Sriastradh		  struct glx_display *priv, int screen)
681cdc920a0Smrg{
682cdc920a0Smrg   xGLXGetVisualConfigsReq *req;
683cdc920a0Smrg   xGLXGetVisualConfigsReply reply;
6843464ebd5Sriastradh   Display *dpy = priv->dpy;
685cdc920a0Smrg
686cdc920a0Smrg   LockDisplay(dpy);
687cdc920a0Smrg
688cdc920a0Smrg   psc->visuals = NULL;
689cdc920a0Smrg   GetReq(GLXGetVisualConfigs, req);
690cdc920a0Smrg   req->reqType = priv->majorOpcode;
691cdc920a0Smrg   req->glxCode = X_GLXGetVisualConfigs;
692cdc920a0Smrg   req->screen = screen;
693cdc920a0Smrg
694cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & reply, 0, False))
695cdc920a0Smrg      goto out;
696cdc920a0Smrg
697cdc920a0Smrg   psc->visuals = createConfigsFromProperties(dpy,
698cdc920a0Smrg                                              reply.numVisuals,
699cdc920a0Smrg                                              reply.numProps,
700cdc920a0Smrg                                              screen, GL_FALSE);
701cdc920a0Smrg
702cdc920a0Smrg out:
703cdc920a0Smrg   UnlockDisplay(dpy);
704cdc920a0Smrg   return psc->visuals != NULL;
705cdc920a0Smrg}
706cdc920a0Smrg
707cdc920a0Smrgstatic GLboolean
7083464ebd5Sriastradh getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen)
709cdc920a0Smrg{
710cdc920a0Smrg   xGLXGetFBConfigsReq *fb_req;
711cdc920a0Smrg   xGLXGetFBConfigsSGIXReq *sgi_req;
712cdc920a0Smrg   xGLXVendorPrivateWithReplyReq *vpreq;
713cdc920a0Smrg   xGLXGetFBConfigsReply reply;
7143464ebd5Sriastradh   Display *dpy = priv->dpy;
715cdc920a0Smrg
716cdc920a0Smrg   psc->serverGLXexts =
717cdc920a0Smrg      __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
718cdc920a0Smrg
719af69d88dSmrg   if (psc->serverGLXexts == NULL) {
720af69d88dSmrg      return GL_FALSE;
721af69d88dSmrg   }
722af69d88dSmrg
723cdc920a0Smrg   LockDisplay(dpy);
724cdc920a0Smrg
725cdc920a0Smrg   psc->configs = NULL;
726cdc920a0Smrg   if (atof(priv->serverGLXversion) >= 1.3) {
727cdc920a0Smrg      GetReq(GLXGetFBConfigs, fb_req);
728cdc920a0Smrg      fb_req->reqType = priv->majorOpcode;
729cdc920a0Smrg      fb_req->glxCode = X_GLXGetFBConfigs;
730cdc920a0Smrg      fb_req->screen = screen;
731cdc920a0Smrg   }
732cdc920a0Smrg   else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
733cdc920a0Smrg      GetReqExtra(GLXVendorPrivateWithReply,
7343464ebd5Sriastradh                  sz_xGLXGetFBConfigsSGIXReq -
735cdc920a0Smrg                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
736cdc920a0Smrg      sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
737cdc920a0Smrg      sgi_req->reqType = priv->majorOpcode;
738cdc920a0Smrg      sgi_req->glxCode = X_GLXVendorPrivateWithReply;
739cdc920a0Smrg      sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
740cdc920a0Smrg      sgi_req->screen = screen;
741cdc920a0Smrg   }
742cdc920a0Smrg   else
743cdc920a0Smrg      goto out;
744cdc920a0Smrg
745cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & reply, 0, False))
746cdc920a0Smrg      goto out;
747cdc920a0Smrg
748cdc920a0Smrg   psc->configs = createConfigsFromProperties(dpy,
749cdc920a0Smrg                                              reply.numFBConfigs,
750cdc920a0Smrg                                              reply.numAttribs * 2,
751cdc920a0Smrg                                              screen, GL_TRUE);
752cdc920a0Smrg
753cdc920a0Smrg out:
754cdc920a0Smrg   UnlockDisplay(dpy);
755cdc920a0Smrg   return psc->configs != NULL;
756cdc920a0Smrg}
757cdc920a0Smrg
7583464ebd5Sriastradh_X_HIDDEN Bool
7593464ebd5Sriastradhglx_screen_init(struct glx_screen *psc,
7603464ebd5Sriastradh		 int screen, struct glx_display * priv)
7613464ebd5Sriastradh{
7623464ebd5Sriastradh   /* Initialize per screen dynamic client GLX extensions */
7633464ebd5Sriastradh   psc->ext_list_first_time = GL_TRUE;
7643464ebd5Sriastradh   psc->scr = screen;
7653464ebd5Sriastradh   psc->dpy = priv->dpy;
7663464ebd5Sriastradh   psc->display = priv;
7673464ebd5Sriastradh
76801e04c3fSmrg   if (!getVisualConfigs(psc, priv, screen))
76901e04c3fSmrg      return GL_FALSE;
77001e04c3fSmrg
77101e04c3fSmrg   if (!getFBConfigs(psc, priv, screen))
77201e04c3fSmrg      return GL_FALSE;
7733464ebd5Sriastradh
7743464ebd5Sriastradh   return GL_TRUE;
7753464ebd5Sriastradh}
7763464ebd5Sriastradh
7773464ebd5Sriastradh_X_HIDDEN void
7783464ebd5Sriastradhglx_screen_cleanup(struct glx_screen *psc)
7793464ebd5Sriastradh{
7803464ebd5Sriastradh   if (psc->configs) {
7813464ebd5Sriastradh      glx_config_destroy_list(psc->configs);
782af69d88dSmrg      free(psc->effectiveGLXexts);
7833464ebd5Sriastradh      psc->configs = NULL;   /* NOTE: just for paranoia */
7843464ebd5Sriastradh   }
7853464ebd5Sriastradh   if (psc->visuals) {
7863464ebd5Sriastradh      glx_config_destroy_list(psc->visuals);
7873464ebd5Sriastradh      psc->visuals = NULL;   /* NOTE: just for paranoia */
7883464ebd5Sriastradh   }
789af69d88dSmrg   free((char *) psc->serverGLXexts);
7903464ebd5Sriastradh}
7913464ebd5Sriastradh
792cdc920a0Smrg/*
793cdc920a0Smrg** Allocate the memory for the per screen configs for each screen.
794cdc920a0Smrg** If that works then fetch the per screen configs data.
795cdc920a0Smrg*/
796cdc920a0Smrgstatic Bool
7973464ebd5SriastradhAllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
798cdc920a0Smrg{
7993464ebd5Sriastradh   struct glx_screen *psc;
800cdc920a0Smrg   GLint i, screens;
801cdc920a0Smrg
802cdc920a0Smrg   /*
803cdc920a0Smrg    ** First allocate memory for the array of per screen configs.
804cdc920a0Smrg    */
805cdc920a0Smrg   screens = ScreenCount(dpy);
806af69d88dSmrg   priv->screens = malloc(screens * sizeof *priv->screens);
8073464ebd5Sriastradh   if (!priv->screens)
808cdc920a0Smrg      return GL_FALSE;
809cdc920a0Smrg
810cdc920a0Smrg   priv->serverGLXversion =
811cdc920a0Smrg      __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
812cdc920a0Smrg   if (priv->serverGLXversion == NULL) {
813cdc920a0Smrg      FreeScreenConfigs(priv);
814cdc920a0Smrg      return GL_FALSE;
815cdc920a0Smrg   }
816cdc920a0Smrg
817cdc920a0Smrg   for (i = 0; i < screens; i++, psc++) {
8183464ebd5Sriastradh      psc = NULL;
819cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
820af69d88dSmrg#if defined(GLX_USE_DRM)
821af69d88dSmrg#if defined(HAVE_DRI3)
822af69d88dSmrg      if (priv->dri3Display)
823af69d88dSmrg         psc = (*priv->dri3Display->createScreen) (i, priv);
824af69d88dSmrg#endif /* HAVE_DRI3 */
825af69d88dSmrg      if (psc == NULL && priv->dri2Display)
8263464ebd5Sriastradh	 psc = (*priv->dri2Display->createScreen) (i, priv);
8273464ebd5Sriastradh      if (psc == NULL && priv->driDisplay)
8283464ebd5Sriastradh	 psc = (*priv->driDisplay->createScreen) (i, priv);
829af69d88dSmrg#endif /* GLX_USE_DRM */
83001e04c3fSmrg
83101e04c3fSmrg#ifdef GLX_USE_WINDOWSGL
83201e04c3fSmrg      if (psc == NULL && priv->windowsdriDisplay)
83301e04c3fSmrg	 psc = (*priv->windowsdriDisplay->createScreen) (i, priv);
83401e04c3fSmrg#endif
83501e04c3fSmrg
8363464ebd5Sriastradh      if (psc == NULL && priv->driswDisplay)
8373464ebd5Sriastradh	 psc = (*priv->driswDisplay->createScreen) (i, priv);
838af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
839af69d88dSmrg
8403464ebd5Sriastradh#if defined(GLX_USE_APPLEGL)
8413464ebd5Sriastradh      if (psc == NULL)
8423464ebd5Sriastradh         psc = applegl_create_screen(i, priv);
8433464ebd5Sriastradh#else
8443464ebd5Sriastradh      if (psc == NULL)
8453464ebd5Sriastradh	 psc = indirect_create_screen(i, priv);
8463464ebd5Sriastradh#endif
8473464ebd5Sriastradh      priv->screens[i] = psc;
848cdc920a0Smrg   }
849cdc920a0Smrg   SyncHandle();
850cdc920a0Smrg   return GL_TRUE;
851cdc920a0Smrg}
852cdc920a0Smrg
853cdc920a0Smrg/*
854cdc920a0Smrg** Initialize the client side extension code.
855cdc920a0Smrg*/
8563464ebd5Sriastradh _X_HIDDEN struct glx_display *
857cdc920a0Smrg__glXInitialize(Display * dpy)
858cdc920a0Smrg{
8593464ebd5Sriastradh   struct glx_display *dpyPriv, *d;
860cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
861cdc920a0Smrg   Bool glx_direct, glx_accel;
862cdc920a0Smrg#endif
8633464ebd5Sriastradh   int i;
864cdc920a0Smrg
8653464ebd5Sriastradh   _XLockMutex(_Xglobal_lock);
866cdc920a0Smrg
8673464ebd5Sriastradh   for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) {
8683464ebd5Sriastradh      if (dpyPriv->dpy == dpy) {
8693464ebd5Sriastradh	 _XUnlockMutex(_Xglobal_lock);
8703464ebd5Sriastradh	 return dpyPriv;
8713464ebd5Sriastradh      }
872cdc920a0Smrg   }
873cdc920a0Smrg
8743464ebd5Sriastradh   /* Drop the lock while we create the display private. */
8753464ebd5Sriastradh   _XUnlockMutex(_Xglobal_lock);
876cdc920a0Smrg
877af69d88dSmrg   dpyPriv = calloc(1, sizeof *dpyPriv);
8783464ebd5Sriastradh   if (!dpyPriv)
8793464ebd5Sriastradh      return NULL;
880cdc920a0Smrg
8813464ebd5Sriastradh   dpyPriv->codes = XInitExtension(dpy, __glXExtensionName);
8823464ebd5Sriastradh   if (!dpyPriv->codes) {
883af69d88dSmrg      free(dpyPriv);
8843464ebd5Sriastradh      return NULL;
885cdc920a0Smrg   }
886cdc920a0Smrg
887cdc920a0Smrg   dpyPriv->dpy = dpy;
8883464ebd5Sriastradh   dpyPriv->majorOpcode = dpyPriv->codes->major_opcode;
889cdc920a0Smrg   dpyPriv->serverGLXvendor = 0x0;
890cdc920a0Smrg   dpyPriv->serverGLXversion = 0x0;
891cdc920a0Smrg
892af69d88dSmrg   /* See if the versions are compatible.  This GLX implementation does not
893af69d88dSmrg    * work with servers that only support GLX 1.0.
894af69d88dSmrg    */
8953464ebd5Sriastradh   if (!QueryVersion(dpy, dpyPriv->majorOpcode,
896af69d88dSmrg		     &dpyPriv->majorVersion, &dpyPriv->minorVersion)
897af69d88dSmrg       || (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion < 1)) {
898af69d88dSmrg      free(dpyPriv);
8993464ebd5Sriastradh      return NULL;
9003464ebd5Sriastradh   }
9013464ebd5Sriastradh
9023464ebd5Sriastradh   for (i = 0; i < __GLX_NUMBER_EVENTS; i++) {
9033464ebd5Sriastradh      XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent);
9043464ebd5Sriastradh      XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire);
9053464ebd5Sriastradh   }
9063464ebd5Sriastradh
9073464ebd5Sriastradh   XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay);
9083464ebd5Sriastradh   XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString);
9093464ebd5Sriastradh
910af69d88dSmrg   dpyPriv->glXDrawHash = __glxHashCreate();
911af69d88dSmrg
912cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
91301e04c3fSmrg   glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false);
91401e04c3fSmrg   glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
915cdc920a0Smrg
9163464ebd5Sriastradh   dpyPriv->drawHash = __glxHashCreate();
9173464ebd5Sriastradh
918cdc920a0Smrg   /*
919cdc920a0Smrg    ** Initialize the direct rendering per display data and functions.
920cdc920a0Smrg    ** Note: This _must_ be done before calling any other DRI routines
921cdc920a0Smrg    ** (e.g., those called in AllocAndFetchScreenConfigs).
922cdc920a0Smrg    */
923af69d88dSmrg#if defined(GLX_USE_DRM)
924cdc920a0Smrg   if (glx_direct && glx_accel) {
925af69d88dSmrg#if defined(HAVE_DRI3)
92601e04c3fSmrg      if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false))
927af69d88dSmrg         dpyPriv->dri3Display = dri3_create_display(dpy);
928af69d88dSmrg#endif /* HAVE_DRI3 */
929cdc920a0Smrg      dpyPriv->dri2Display = dri2CreateDisplay(dpy);
930cdc920a0Smrg      dpyPriv->driDisplay = driCreateDisplay(dpy);
931cdc920a0Smrg   }
932af69d88dSmrg#endif /* GLX_USE_DRM */
933cdc920a0Smrg   if (glx_direct)
934cdc920a0Smrg      dpyPriv->driswDisplay = driswCreateDisplay(dpy);
935af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
9363464ebd5Sriastradh
937cdc920a0Smrg#ifdef GLX_USE_APPLEGL
9383464ebd5Sriastradh   if (!applegl_create_display(dpyPriv)) {
939af69d88dSmrg      free(dpyPriv);
9403464ebd5Sriastradh      return NULL;
9413464ebd5Sriastradh   }
942cdc920a0Smrg#endif
94301e04c3fSmrg
94401e04c3fSmrg#ifdef GLX_USE_WINDOWSGL
94501e04c3fSmrg   if (glx_direct && glx_accel)
94601e04c3fSmrg      dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy);
94701e04c3fSmrg#endif
94801e04c3fSmrg
9493464ebd5Sriastradh   if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
950af69d88dSmrg      free(dpyPriv);
9513464ebd5Sriastradh      return NULL;
952cdc920a0Smrg   }
953cdc920a0Smrg
954af69d88dSmrg   __glX_send_client_info(dpyPriv);
9553464ebd5Sriastradh
9563464ebd5Sriastradh   /* Grab the lock again and add the dispay private, unless somebody
9573464ebd5Sriastradh    * beat us to initializing on this display in the meantime. */
9583464ebd5Sriastradh   _XLockMutex(_Xglobal_lock);
9593464ebd5Sriastradh
9603464ebd5Sriastradh   for (d = glx_displays; d; d = d->next) {
9613464ebd5Sriastradh      if (d->dpy == dpy) {
9623464ebd5Sriastradh	 _XUnlockMutex(_Xglobal_lock);
9633464ebd5Sriastradh	 glx_display_free(dpyPriv);
9643464ebd5Sriastradh	 return d;
9653464ebd5Sriastradh      }
966cdc920a0Smrg   }
9673464ebd5Sriastradh
9683464ebd5Sriastradh   dpyPriv->next = glx_displays;
9693464ebd5Sriastradh   glx_displays = dpyPriv;
9703464ebd5Sriastradh
971af69d88dSmrg   _XUnlockMutex(_Xglobal_lock);
972cdc920a0Smrg
973cdc920a0Smrg   return dpyPriv;
974cdc920a0Smrg}
975cdc920a0Smrg
976cdc920a0Smrg/*
977cdc920a0Smrg** Setup for sending a GLX command on dpy.  Make sure the extension is
978cdc920a0Smrg** initialized.  Try to avoid calling __glXInitialize as its kinda slow.
979cdc920a0Smrg*/
980cdc920a0Smrg_X_HIDDEN CARD8
981cdc920a0Smrg__glXSetupForCommand(Display * dpy)
982cdc920a0Smrg{
9833464ebd5Sriastradh    struct glx_context *gc;
9843464ebd5Sriastradh    struct glx_display *priv;
985cdc920a0Smrg
986cdc920a0Smrg   /* If this thread has a current context, flush its rendering commands */
987cdc920a0Smrg   gc = __glXGetCurrentContext();
988cdc920a0Smrg   if (gc->currentDpy) {
989cdc920a0Smrg      /* Flush rendering buffer of the current context, if any */
990cdc920a0Smrg      (void) __glXFlushRenderBuffer(gc, gc->pc);
991cdc920a0Smrg
992cdc920a0Smrg      if (gc->currentDpy == dpy) {
993cdc920a0Smrg         /* Use opcode from gc because its right */
994cdc920a0Smrg         return gc->majorOpcode;
995cdc920a0Smrg      }
996cdc920a0Smrg      else {
997cdc920a0Smrg         /*
998cdc920a0Smrg          ** Have to get info about argument dpy because it might be to
999cdc920a0Smrg          ** a different server
1000cdc920a0Smrg          */
1001cdc920a0Smrg      }
1002cdc920a0Smrg   }
1003cdc920a0Smrg
1004cdc920a0Smrg   /* Forced to lookup extension via the slow initialize route */
1005cdc920a0Smrg   priv = __glXInitialize(dpy);
1006cdc920a0Smrg   if (!priv) {
1007cdc920a0Smrg      return 0;
1008cdc920a0Smrg   }
1009cdc920a0Smrg   return priv->majorOpcode;
1010cdc920a0Smrg}
1011cdc920a0Smrg
1012cdc920a0Smrg/**
1013cdc920a0Smrg * Flush the drawing command transport buffer.
1014cdc920a0Smrg *
1015cdc920a0Smrg * \param ctx  Context whose transport buffer is to be flushed.
1016cdc920a0Smrg * \param pc   Pointer to first unused buffer location.
1017cdc920a0Smrg *
1018cdc920a0Smrg * \todo
1019cdc920a0Smrg * Modify this function to use \c ctx->pc instead of the explicit
1020cdc920a0Smrg * \c pc parameter.
1021cdc920a0Smrg */
1022cdc920a0Smrg_X_HIDDEN GLubyte *
10233464ebd5Sriastradh__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc)
1024cdc920a0Smrg{
1025cdc920a0Smrg   Display *const dpy = ctx->currentDpy;
1026cdc920a0Smrg   xcb_connection_t *c = XGetXCBConnection(dpy);
1027cdc920a0Smrg   const GLint size = pc - ctx->buf;
1028cdc920a0Smrg
1029cdc920a0Smrg   if ((dpy != NULL) && (size > 0)) {
1030cdc920a0Smrg      xcb_glx_render(c, ctx->currentContextTag, size,
1031cdc920a0Smrg                     (const uint8_t *) ctx->buf);
1032cdc920a0Smrg   }
1033cdc920a0Smrg
1034cdc920a0Smrg   /* Reset pointer and return it */
1035cdc920a0Smrg   ctx->pc = ctx->buf;
1036cdc920a0Smrg   return ctx->pc;
1037cdc920a0Smrg}
1038cdc920a0Smrg
1039cdc920a0Smrg
1040cdc920a0Smrg/**
1041cdc920a0Smrg * Send a portion of a GLXRenderLarge command to the server.  The advantage of
1042cdc920a0Smrg * this function over \c __glXSendLargeCommand is that callers can use the
1043cdc920a0Smrg * data buffer in the GLX context and may be able to avoid allocating an
1044cdc920a0Smrg * extra buffer.  The disadvantage is the clients will have to do more
1045cdc920a0Smrg * GLX protocol work (i.e., calculating \c totalRequests, etc.).
1046cdc920a0Smrg *
1047cdc920a0Smrg * \sa __glXSendLargeCommand
1048cdc920a0Smrg *
1049cdc920a0Smrg * \param gc             GLX context
1050cdc920a0Smrg * \param requestNumber  Which part of the whole command is this?  The first
1051cdc920a0Smrg *                       request is 1.
1052cdc920a0Smrg * \param totalRequests  How many requests will there be?
1053cdc920a0Smrg * \param data           Command data.
1054cdc920a0Smrg * \param dataLen        Size, in bytes, of the command data.
1055cdc920a0Smrg */
1056cdc920a0Smrg_X_HIDDEN void
10573464ebd5Sriastradh__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber,
1058cdc920a0Smrg                    GLint totalRequests, const GLvoid * data, GLint dataLen)
1059cdc920a0Smrg{
1060cdc920a0Smrg   Display *dpy = gc->currentDpy;
1061cdc920a0Smrg   xcb_connection_t *c = XGetXCBConnection(dpy);
1062cdc920a0Smrg   xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
1063cdc920a0Smrg                        totalRequests, dataLen, data);
1064cdc920a0Smrg}
1065cdc920a0Smrg
1066cdc920a0Smrg
1067cdc920a0Smrg/**
1068cdc920a0Smrg * Send a command that is too large for the GLXRender protocol request.
1069cdc920a0Smrg *
1070cdc920a0Smrg * Send a large command, one that is too large for some reason to
1071cdc920a0Smrg * send using the GLXRender protocol request.  One reason to send
1072cdc920a0Smrg * a large command is to avoid copying the data.
1073cdc920a0Smrg *
1074cdc920a0Smrg * \param ctx        GLX context
1075cdc920a0Smrg * \param header     Header data.
1076cdc920a0Smrg * \param headerLen  Size, in bytes, of the header data.  It is assumed that
1077cdc920a0Smrg *                   the header data will always be small enough to fit in
1078cdc920a0Smrg *                   a single X protocol packet.
1079cdc920a0Smrg * \param data       Command data.
1080cdc920a0Smrg * \param dataLen    Size, in bytes, of the command data.
1081cdc920a0Smrg */
1082cdc920a0Smrg_X_HIDDEN void
10833464ebd5Sriastradh__glXSendLargeCommand(struct glx_context * ctx,
1084cdc920a0Smrg                      const GLvoid * header, GLint headerLen,
1085cdc920a0Smrg                      const GLvoid * data, GLint dataLen)
1086cdc920a0Smrg{
1087cdc920a0Smrg   GLint maxSize;
1088cdc920a0Smrg   GLint totalRequests, requestNumber;
1089cdc920a0Smrg
1090cdc920a0Smrg   /*
1091cdc920a0Smrg    ** Calculate the maximum amount of data can be stuffed into a single
1092cdc920a0Smrg    ** packet.  sz_xGLXRenderReq is added because bufSize is the maximum
1093cdc920a0Smrg    ** packet size minus sz_xGLXRenderReq.
1094cdc920a0Smrg    */
1095cdc920a0Smrg   maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
1096cdc920a0Smrg   totalRequests = 1 + (dataLen / maxSize);
1097cdc920a0Smrg   if (dataLen % maxSize)
1098cdc920a0Smrg      totalRequests++;
1099cdc920a0Smrg
1100cdc920a0Smrg   /*
1101cdc920a0Smrg    ** Send all of the command, except the large array, as one request.
1102cdc920a0Smrg    */
1103cdc920a0Smrg   assert(headerLen <= maxSize);
1104cdc920a0Smrg   __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
1105cdc920a0Smrg
1106cdc920a0Smrg   /*
1107cdc920a0Smrg    ** Send enough requests until the whole array is sent.
1108cdc920a0Smrg    */
1109cdc920a0Smrg   for (requestNumber = 2; requestNumber <= (totalRequests - 1);
1110cdc920a0Smrg        requestNumber++) {
1111cdc920a0Smrg      __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
1112cdc920a0Smrg      data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
1113cdc920a0Smrg      dataLen -= maxSize;
1114cdc920a0Smrg      assert(dataLen > 0);
1115cdc920a0Smrg   }
1116cdc920a0Smrg
1117cdc920a0Smrg   assert(dataLen <= maxSize);
1118cdc920a0Smrg   __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
1119cdc920a0Smrg}
1120cdc920a0Smrg
1121cdc920a0Smrg/************************************************************************/
1122cdc920a0Smrg
1123cdc920a0Smrg#ifdef DEBUG
1124cdc920a0Smrg_X_HIDDEN void
11253464ebd5Sriastradh__glXDumpDrawBuffer(struct glx_context * ctx)
1126cdc920a0Smrg{
1127cdc920a0Smrg   GLubyte *p = ctx->buf;
1128cdc920a0Smrg   GLubyte *end = ctx->pc;
1129cdc920a0Smrg   GLushort opcode, length;
1130cdc920a0Smrg
1131cdc920a0Smrg   while (p < end) {
1132cdc920a0Smrg      /* Fetch opcode */
1133cdc920a0Smrg      opcode = *((GLushort *) p);
1134cdc920a0Smrg      length = *((GLushort *) (p + 2));
1135cdc920a0Smrg      printf("%2x: %5d: ", opcode, length);
1136cdc920a0Smrg      length -= 4;
1137cdc920a0Smrg      p += 4;
1138cdc920a0Smrg      while (length > 0) {
1139cdc920a0Smrg         printf("%08x ", *((unsigned *) p));
1140cdc920a0Smrg         p += 4;
1141cdc920a0Smrg         length -= 4;
1142cdc920a0Smrg      }
1143cdc920a0Smrg      printf("\n");
1144cdc920a0Smrg   }
1145cdc920a0Smrg}
1146cdc920a0Smrg#endif
1147