glxext.c revision 7ec681f3
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>
427ec681f3Smrg#include <stdarg.h>
4301e04c3fSmrg
44cdc920a0Smrg#include "glxclient.h"
45cdc920a0Smrg#include <X11/extensions/Xext.h>
46cdc920a0Smrg#include <X11/extensions/extutil.h>
47cdc920a0Smrg#ifdef GLX_USE_APPLEGL
48af69d88dSmrg#include "apple/apple_glx.h"
49af69d88dSmrg#include "apple/apple_visual.h"
50cdc920a0Smrg#endif
51cdc920a0Smrg#include "glxextensions.h"
52cdc920a0Smrg
5301e04c3fSmrg#include "util/debug.h"
547ec681f3Smrg#ifndef GLX_USE_APPLEGL
557ec681f3Smrg#include "dri_common.h"
567ec681f3Smrg#endif
5701e04c3fSmrg
58cdc920a0Smrg#include <X11/Xlib-xcb.h>
59cdc920a0Smrg#include <xcb/xcb.h>
60cdc920a0Smrg#include <xcb/glx.h>
61cdc920a0Smrg
627ec681f3Smrg#define __GLX_MIN_CONFIG_PROPS	18
637ec681f3Smrg#define __GLX_EXT_CONFIG_PROPS	32
64cdc920a0Smrg
657ec681f3Smrg/*
667ec681f3Smrg** Since we send all non-core visual properties as token, value pairs,
677ec681f3Smrg** we require 2 words across the wire. In order to maintain backwards
687ec681f3Smrg** compatibility, we need to send the total number of words that the
697ec681f3Smrg** VisualConfigs are sent back in so old libraries can simply "ignore"
707ec681f3Smrg** the new properties.
717ec681f3Smrg*/
727ec681f3Smrg#define __GLX_TOTAL_CONFIG \
737ec681f3Smrg   (__GLX_MIN_CONFIG_PROPS + 2 * __GLX_EXT_CONFIG_PROPS)
747ec681f3Smrg
757ec681f3Smrg_X_HIDDEN void
767ec681f3Smrgglx_message(int level, const char *f, ...)
777ec681f3Smrg{
787ec681f3Smrg   va_list args;
797ec681f3Smrg   int threshold = _LOADER_WARNING;
807ec681f3Smrg   const char *libgl_debug;
817ec681f3Smrg
827ec681f3Smrg   libgl_debug = getenv("LIBGL_DEBUG");
837ec681f3Smrg   if (libgl_debug) {
847ec681f3Smrg      if (strstr(libgl_debug, "quiet"))
857ec681f3Smrg         threshold = _LOADER_FATAL;
867ec681f3Smrg      else if (strstr(libgl_debug, "verbose"))
877ec681f3Smrg         threshold = _LOADER_DEBUG;
887ec681f3Smrg   }
897ec681f3Smrg
907ec681f3Smrg   /* Note that the _LOADER_* levels are lower numbers for more severe. */
917ec681f3Smrg   if (level <= threshold) {
927ec681f3Smrg      fprintf(stderr, "libGL%s: ", level <= _LOADER_WARNING ? " error" : "");
937ec681f3Smrg      va_start(args, f);
947ec681f3Smrg      vfprintf(stderr, f, args);
957ec681f3Smrg      va_end(args);
967ec681f3Smrg   }
977ec681f3Smrg}
98cdc920a0Smrg
99cdc920a0Smrg/*
100cdc920a0Smrg** You can set this cell to 1 to force the gl drawing stuff to be
101cdc920a0Smrg** one command per packet
102cdc920a0Smrg*/
103cdc920a0Smrg_X_HIDDEN int __glXDebug = 0;
104cdc920a0Smrg
105cdc920a0Smrg/* Extension required boiler plate */
106cdc920a0Smrg
1073464ebd5Sriastradhstatic const char __glXExtensionName[] = GLX_EXTENSION_NAME;
1087ec681f3Smrgstatic struct glx_display *glx_displays;
109cdc920a0Smrg
110cdc920a0Smrgstatic /* const */ char *error_list[] = {
111cdc920a0Smrg   "GLXBadContext",
112cdc920a0Smrg   "GLXBadContextState",
113cdc920a0Smrg   "GLXBadDrawable",
114cdc920a0Smrg   "GLXBadPixmap",
115cdc920a0Smrg   "GLXBadContextTag",
116cdc920a0Smrg   "GLXBadCurrentWindow",
117cdc920a0Smrg   "GLXBadRenderRequest",
118cdc920a0Smrg   "GLXBadLargeRequest",
119cdc920a0Smrg   "GLXUnsupportedPrivateRequest",
120cdc920a0Smrg   "GLXBadFBConfig",
121cdc920a0Smrg   "GLXBadPbuffer",
122cdc920a0Smrg   "GLXBadCurrentDrawable",
123cdc920a0Smrg   "GLXBadWindow",
124af69d88dSmrg   "GLXBadProfileARB",
125cdc920a0Smrg};
126cdc920a0Smrg
127cdc920a0Smrg#ifdef GLX_USE_APPLEGL
128cdc920a0Smrgstatic char *__glXErrorString(Display *dpy, int code, XExtCodes *codes,
129cdc920a0Smrg                              char *buf, int n);
130cdc920a0Smrg#endif
131cdc920a0Smrg
132cdc920a0Smrgstatic
133cdc920a0SmrgXEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
134cdc920a0Smrg                           __GLX_NUMBER_ERRORS, error_list)
135cdc920a0Smrg
136cdc920a0Smrg/*
137cdc920a0Smrg * GLX events are a bit funky.  We don't stuff the X event code into
138cdc920a0Smrg * our user exposed (via XNextEvent) structure.  Instead we use the GLX
139cdc920a0Smrg * private event code namespace (and hope it doesn't conflict).  Clients
140cdc920a0Smrg * have to know that bit 15 in the event type field means they're getting
141cdc920a0Smrg * a GLX event, and then handle the various sub-event types there, rather
142cdc920a0Smrg * than simply checking the event code and handling it directly.
143cdc920a0Smrg */
144cdc920a0Smrg
145cdc920a0Smrgstatic Bool
146cdc920a0Smrg__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
147cdc920a0Smrg{
1483464ebd5Sriastradh     struct glx_display *glx_dpy = __glXInitialize(dpy);
149cdc920a0Smrg
1503464ebd5Sriastradh   if (glx_dpy == NULL)
1513464ebd5Sriastradh      return False;
152cdc920a0Smrg
1537ec681f3Smrg   switch ((wire->u.u.type & 0x7f) - glx_dpy->codes.first_event) {
154cdc920a0Smrg   case GLX_PbufferClobber:
155cdc920a0Smrg   {
156cdc920a0Smrg      GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event;
157cdc920a0Smrg      xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire;
158cdc920a0Smrg      aevent->event_type = awire->type;
159cdc920a0Smrg      aevent->serial = awire->sequenceNumber;
160cdc920a0Smrg      aevent->event_type = awire->event_type;
161cdc920a0Smrg      aevent->draw_type = awire->draw_type;
162cdc920a0Smrg      aevent->drawable = awire->drawable;
163cdc920a0Smrg      aevent->buffer_mask = awire->buffer_mask;
164cdc920a0Smrg      aevent->aux_buffer = awire->aux_buffer;
165cdc920a0Smrg      aevent->x = awire->x;
166cdc920a0Smrg      aevent->y = awire->y;
167cdc920a0Smrg      aevent->width = awire->width;
168cdc920a0Smrg      aevent->height = awire->height;
169cdc920a0Smrg      aevent->count = awire->count;
170cdc920a0Smrg      return True;
171cdc920a0Smrg   }
172cdc920a0Smrg   case GLX_BufferSwapComplete:
173cdc920a0Smrg   {
174cdc920a0Smrg      GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
175af69d88dSmrg      xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire;
176af69d88dSmrg      struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable);
177af69d88dSmrg
178af69d88dSmrg      if (!glxDraw)
179af69d88dSmrg	 return False;
180af69d88dSmrg
18101e04c3fSmrg      aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
18201e04c3fSmrg      aevent->send_event = (awire->type & 0x80) != 0;
18301e04c3fSmrg      aevent->display = dpy;
184cdc920a0Smrg      aevent->event_type = awire->event_type;
185af69d88dSmrg      aevent->drawable = glxDraw->xDrawable;
186cdc920a0Smrg      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
187cdc920a0Smrg      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
188af69d88dSmrg
18901e04c3fSmrg      /* Handle 32-Bit wire sbc wraparound in both directions to cope with out
19001e04c3fSmrg       * of sequence 64-Bit sbc's
19101e04c3fSmrg       */
19201e04c3fSmrg      if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000))
19301e04c3fSmrg         glxDraw->eventSbcWrap += 0x100000000;
19401e04c3fSmrg      if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000))
19501e04c3fSmrg         glxDraw->eventSbcWrap -= 0x100000000;
196af69d88dSmrg      glxDraw->lastEventSbc = awire->sbc;
197af69d88dSmrg      aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
198cdc920a0Smrg      return True;
199cdc920a0Smrg   }
200cdc920a0Smrg   default:
201cdc920a0Smrg      /* client doesn't support server event */
202cdc920a0Smrg      break;
203cdc920a0Smrg   }
204cdc920a0Smrg
205cdc920a0Smrg   return False;
206cdc920a0Smrg}
207cdc920a0Smrg
208cdc920a0Smrg/* We don't actually support this.  It doesn't make sense for clients to
209cdc920a0Smrg * send each other GLX events.
210cdc920a0Smrg */
211cdc920a0Smrgstatic Status
212cdc920a0Smrg__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
213cdc920a0Smrg{
2143464ebd5Sriastradh     struct glx_display *glx_dpy = __glXInitialize(dpy);
215cdc920a0Smrg
2163464ebd5Sriastradh   if (glx_dpy == NULL)
2173464ebd5Sriastradh      return False;
218cdc920a0Smrg
219cdc920a0Smrg   switch (event->type) {
220cdc920a0Smrg   case GLX_DAMAGED:
221cdc920a0Smrg      break;
222cdc920a0Smrg   case GLX_SAVED:
223cdc920a0Smrg      break;
224cdc920a0Smrg   case GLX_EXCHANGE_COMPLETE_INTEL:
225cdc920a0Smrg      break;
226cdc920a0Smrg   case GLX_COPY_COMPLETE_INTEL:
227cdc920a0Smrg      break;
228cdc920a0Smrg   case GLX_FLIP_COMPLETE_INTEL:
229cdc920a0Smrg      break;
230cdc920a0Smrg   default:
231cdc920a0Smrg      /* client doesn't support server event */
232cdc920a0Smrg      break;
233cdc920a0Smrg   }
234cdc920a0Smrg
235cdc920a0Smrg   return Success;
236cdc920a0Smrg}
237cdc920a0Smrg
238cdc920a0Smrg/************************************************************************/
239cdc920a0Smrg/*
240cdc920a0Smrg** Free the per screen configs data as well as the array of
241cdc920a0Smrg** __glXScreenConfigs.
242cdc920a0Smrg*/
243cdc920a0Smrgstatic void
2443464ebd5SriastradhFreeScreenConfigs(struct glx_display * priv)
245cdc920a0Smrg{
2463464ebd5Sriastradh   struct glx_screen *psc;
247cdc920a0Smrg   GLint i, screens;
248cdc920a0Smrg
249cdc920a0Smrg   /* Free screen configuration information */
250cdc920a0Smrg   screens = ScreenCount(priv->dpy);
2513464ebd5Sriastradh   for (i = 0; i < screens; i++) {
2523464ebd5Sriastradh      psc = priv->screens[i];
2539f464c52Smaya      if (!psc)
2549f464c52Smaya         continue;
2553464ebd5Sriastradh      glx_screen_cleanup(psc);
256cdc920a0Smrg
257cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
258cdc920a0Smrg      if (psc->driScreen) {
259cdc920a0Smrg         psc->driScreen->destroyScreen(psc);
2603464ebd5Sriastradh      } else {
261af69d88dSmrg	 free(psc);
262cdc920a0Smrg      }
2633464ebd5Sriastradh#else
264af69d88dSmrg      free(psc);
265cdc920a0Smrg#endif
266cdc920a0Smrg   }
267af69d88dSmrg   free((char *) priv->screens);
2683464ebd5Sriastradh   priv->screens = NULL;
269cdc920a0Smrg}
270cdc920a0Smrg
2713464ebd5Sriastradhstatic void
2723464ebd5Sriastradhglx_display_free(struct glx_display *priv)
273cdc920a0Smrg{
2743464ebd5Sriastradh   struct glx_context *gc;
2753464ebd5Sriastradh
2763464ebd5Sriastradh   gc = __glXGetCurrentContext();
2773464ebd5Sriastradh   if (priv->dpy == gc->currentDpy) {
2783464ebd5Sriastradh      gc->vtable->destroy(gc);
2793464ebd5Sriastradh      __glXSetCurrentContextNull();
2803464ebd5Sriastradh   }
281cdc920a0Smrg
282cdc920a0Smrg   FreeScreenConfigs(priv);
283af69d88dSmrg
284af69d88dSmrg   __glxHashDestroy(priv->glXDrawHash);
285cdc920a0Smrg
286cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
2873464ebd5Sriastradh   __glxHashDestroy(priv->drawHash);
2883464ebd5Sriastradh
289cdc920a0Smrg   /* Free the direct rendering per display data */
290cdc920a0Smrg   if (priv->driswDisplay)
291cdc920a0Smrg      (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
292cdc920a0Smrg   priv->driswDisplay = NULL;
293cdc920a0Smrg
294af69d88dSmrg#if defined (GLX_USE_DRM)
295cdc920a0Smrg   if (priv->dri2Display)
296cdc920a0Smrg      (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
297cdc920a0Smrg   priv->dri2Display = NULL;
298cdc920a0Smrg
299af69d88dSmrg   if (priv->dri3Display)
300af69d88dSmrg      (*priv->dri3Display->destroyDisplay) (priv->dri3Display);
301af69d88dSmrg   priv->dri3Display = NULL;
302af69d88dSmrg#endif /* GLX_USE_DRM */
30301e04c3fSmrg
30401e04c3fSmrg#if defined(GLX_USE_WINDOWSGL)
30501e04c3fSmrg   if (priv->windowsdriDisplay)
30601e04c3fSmrg      (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay);
30701e04c3fSmrg   priv->windowsdriDisplay = NULL;
30801e04c3fSmrg#endif /* GLX_USE_WINDOWSGL */
30901e04c3fSmrg
310af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
311af69d88dSmrg
312af69d88dSmrg   free((char *) priv);
313cdc920a0Smrg}
314cdc920a0Smrg
3153464ebd5Sriastradhstatic int
3163464ebd5Sriastradh__glXCloseDisplay(Display * dpy, XExtCodes * codes)
3173464ebd5Sriastradh{
3183464ebd5Sriastradh   struct glx_display *priv, **prev;
3193464ebd5Sriastradh
3203464ebd5Sriastradh   _XLockMutex(_Xglobal_lock);
3213464ebd5Sriastradh   prev = &glx_displays;
3223464ebd5Sriastradh   for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
3233464ebd5Sriastradh      if (priv->dpy == dpy) {
3243464ebd5Sriastradh         *prev = priv->next;
3253464ebd5Sriastradh	 break;
3263464ebd5Sriastradh      }
3273464ebd5Sriastradh   }
3283464ebd5Sriastradh   _XUnlockMutex(_Xglobal_lock);
3293464ebd5Sriastradh
330af69d88dSmrg   if (priv != NULL)
331af69d88dSmrg      glx_display_free(priv);
3323464ebd5Sriastradh
3333464ebd5Sriastradh   return 1;
3343464ebd5Sriastradh}
335cdc920a0Smrg
336cdc920a0Smrg/*
337cdc920a0Smrg** Query the version of the GLX extension.  This procedure works even if
338cdc920a0Smrg** the client extension is not completely set up.
339cdc920a0Smrg*/
340cdc920a0Smrgstatic Bool
341cdc920a0SmrgQueryVersion(Display * dpy, int opcode, int *major, int *minor)
342cdc920a0Smrg{
343cdc920a0Smrg   xcb_connection_t *c = XGetXCBConnection(dpy);
344cdc920a0Smrg   xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c,
345cdc920a0Smrg                                                                      xcb_glx_query_version
346cdc920a0Smrg                                                                      (c,
347cdc920a0Smrg                                                                       GLX_MAJOR_VERSION,
348cdc920a0Smrg                                                                       GLX_MINOR_VERSION),
349cdc920a0Smrg                                                                      NULL);
350cdc920a0Smrg
351af69d88dSmrg   if (!reply)
352af69d88dSmrg     return GL_FALSE;
353af69d88dSmrg
354cdc920a0Smrg   if (reply->major_version != GLX_MAJOR_VERSION) {
355cdc920a0Smrg      free(reply);
356cdc920a0Smrg      return GL_FALSE;
357cdc920a0Smrg   }
358cdc920a0Smrg   *major = reply->major_version;
359cdc920a0Smrg   *minor = min(reply->minor_version, GLX_MINOR_VERSION);
360cdc920a0Smrg   free(reply);
361cdc920a0Smrg   return GL_TRUE;
362cdc920a0Smrg}
363cdc920a0Smrg
364cdc920a0Smrg/*
365cdc920a0Smrg * We don't want to enable this GLX_OML_swap_method in glxext.h,
366cdc920a0Smrg * because we can't support it.  The X server writes it out though,
367cdc920a0Smrg * so we should handle it somehow, to avoid false warnings.
368cdc920a0Smrg */
369cdc920a0Smrgenum {
370cdc920a0Smrg    IGNORE_GLX_SWAP_METHOD_OML = 0x8060
371cdc920a0Smrg};
372cdc920a0Smrg
373cdc920a0Smrg
3743464ebd5Sriastradhstatic GLint
3753464ebd5Sriastradhconvert_from_x_visual_type(int visualType)
3763464ebd5Sriastradh{
3773464ebd5Sriastradh   static const int glx_visual_types[] = {
37801e04c3fSmrg      [StaticGray]  = GLX_STATIC_GRAY,
37901e04c3fSmrg      [GrayScale]   = GLX_GRAY_SCALE,
38001e04c3fSmrg      [StaticColor] = GLX_STATIC_COLOR,
38101e04c3fSmrg      [PseudoColor] = GLX_PSEUDO_COLOR,
38201e04c3fSmrg      [TrueColor]   = GLX_TRUE_COLOR,
38301e04c3fSmrg      [DirectColor] = GLX_DIRECT_COLOR,
3843464ebd5Sriastradh   };
3853464ebd5Sriastradh
3863464ebd5Sriastradh   if (visualType < ARRAY_SIZE(glx_visual_types))
3873464ebd5Sriastradh      return glx_visual_types[visualType];
3883464ebd5Sriastradh
3893464ebd5Sriastradh   return GLX_NONE;
3903464ebd5Sriastradh}
3913464ebd5Sriastradh
392cdc920a0Smrg/*
393cdc920a0Smrg * getVisualConfigs uses the !tagged_only path.
394cdc920a0Smrg * getFBConfigs uses the tagged_only path.
395cdc920a0Smrg */
396cdc920a0Smrg_X_HIDDEN void
3973464ebd5Sriastradh__glXInitializeVisualConfigFromTags(struct glx_config * config, int count,
398cdc920a0Smrg                                    const INT32 * bp, Bool tagged_only,
399cdc920a0Smrg                                    Bool fbconfig_style_tags)
400cdc920a0Smrg{
401cdc920a0Smrg   int i;
402cdc920a0Smrg
403cdc920a0Smrg   if (!tagged_only) {
404cdc920a0Smrg      /* Copy in the first set of properties */
405cdc920a0Smrg      config->visualID = *bp++;
406cdc920a0Smrg
4073464ebd5Sriastradh      config->visualType = convert_from_x_visual_type(*bp++);
408cdc920a0Smrg
4097ec681f3Smrg      config->renderType = *bp++ ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
410cdc920a0Smrg
411cdc920a0Smrg      config->redBits = *bp++;
412cdc920a0Smrg      config->greenBits = *bp++;
413cdc920a0Smrg      config->blueBits = *bp++;
414cdc920a0Smrg      config->alphaBits = *bp++;
415cdc920a0Smrg      config->accumRedBits = *bp++;
416cdc920a0Smrg      config->accumGreenBits = *bp++;
417cdc920a0Smrg      config->accumBlueBits = *bp++;
418cdc920a0Smrg      config->accumAlphaBits = *bp++;
419cdc920a0Smrg
420cdc920a0Smrg      config->doubleBufferMode = *bp++;
421cdc920a0Smrg      config->stereoMode = *bp++;
422cdc920a0Smrg
423cdc920a0Smrg      config->rgbBits = *bp++;
424cdc920a0Smrg      config->depthBits = *bp++;
425cdc920a0Smrg      config->stencilBits = *bp++;
426cdc920a0Smrg      config->numAuxBuffers = *bp++;
427cdc920a0Smrg      config->level = *bp++;
428cdc920a0Smrg
429cdc920a0Smrg#ifdef GLX_USE_APPLEGL
430cdc920a0Smrg       /* AppleSGLX supports pixmap and pbuffers with all config. */
431cdc920a0Smrg       config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
432cdc920a0Smrg       /* Unfortunately this can create an ABI compatibility problem. */
433cdc920a0Smrg       count -= 18;
434cdc920a0Smrg#else
435cdc920a0Smrg      count -= __GLX_MIN_CONFIG_PROPS;
436cdc920a0Smrg#endif
437cdc920a0Smrg   }
438cdc920a0Smrg
439cdc920a0Smrg   /*
440cdc920a0Smrg    ** Additional properties may be in a list at the end
441cdc920a0Smrg    ** of the reply.  They are in pairs of property type
442cdc920a0Smrg    ** and property value.
443cdc920a0Smrg    */
444cdc920a0Smrg
445cdc920a0Smrg#define FETCH_OR_SET(tag) \
446cdc920a0Smrg    config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
447cdc920a0Smrg
448cdc920a0Smrg   for (i = 0; i < count; i += 2) {
449cdc920a0Smrg      long int tag = *bp++;
450cdc920a0Smrg
451cdc920a0Smrg      switch (tag) {
452cdc920a0Smrg      case GLX_RGBA:
4537ec681f3Smrg         if (fbconfig_style_tags)
4547ec681f3Smrg            config->renderType = *bp++ ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
4557ec681f3Smrg         else
4567ec681f3Smrg            config->renderType = GLX_RGBA_BIT;
457cdc920a0Smrg         break;
458cdc920a0Smrg      case GLX_BUFFER_SIZE:
459cdc920a0Smrg         config->rgbBits = *bp++;
460cdc920a0Smrg         break;
461cdc920a0Smrg      case GLX_LEVEL:
462cdc920a0Smrg         config->level = *bp++;
463cdc920a0Smrg         break;
464cdc920a0Smrg      case GLX_DOUBLEBUFFER:
465cdc920a0Smrg         FETCH_OR_SET(doubleBufferMode);
466cdc920a0Smrg         break;
467cdc920a0Smrg      case GLX_STEREO:
468cdc920a0Smrg         FETCH_OR_SET(stereoMode);
469cdc920a0Smrg         break;
470cdc920a0Smrg      case GLX_AUX_BUFFERS:
471cdc920a0Smrg         config->numAuxBuffers = *bp++;
472cdc920a0Smrg         break;
473cdc920a0Smrg      case GLX_RED_SIZE:
474cdc920a0Smrg         config->redBits = *bp++;
475cdc920a0Smrg         break;
476cdc920a0Smrg      case GLX_GREEN_SIZE:
477cdc920a0Smrg         config->greenBits = *bp++;
478cdc920a0Smrg         break;
479cdc920a0Smrg      case GLX_BLUE_SIZE:
480cdc920a0Smrg         config->blueBits = *bp++;
481cdc920a0Smrg         break;
482cdc920a0Smrg      case GLX_ALPHA_SIZE:
483cdc920a0Smrg         config->alphaBits = *bp++;
484cdc920a0Smrg         break;
485cdc920a0Smrg      case GLX_DEPTH_SIZE:
486cdc920a0Smrg         config->depthBits = *bp++;
487cdc920a0Smrg         break;
488cdc920a0Smrg      case GLX_STENCIL_SIZE:
489cdc920a0Smrg         config->stencilBits = *bp++;
490cdc920a0Smrg         break;
491cdc920a0Smrg      case GLX_ACCUM_RED_SIZE:
492cdc920a0Smrg         config->accumRedBits = *bp++;
493cdc920a0Smrg         break;
494cdc920a0Smrg      case GLX_ACCUM_GREEN_SIZE:
495cdc920a0Smrg         config->accumGreenBits = *bp++;
496cdc920a0Smrg         break;
497cdc920a0Smrg      case GLX_ACCUM_BLUE_SIZE:
498cdc920a0Smrg         config->accumBlueBits = *bp++;
499cdc920a0Smrg         break;
500cdc920a0Smrg      case GLX_ACCUM_ALPHA_SIZE:
501cdc920a0Smrg         config->accumAlphaBits = *bp++;
502cdc920a0Smrg         break;
503cdc920a0Smrg      case GLX_VISUAL_CAVEAT_EXT:
504cdc920a0Smrg         config->visualRating = *bp++;
505cdc920a0Smrg         break;
506cdc920a0Smrg      case GLX_X_VISUAL_TYPE:
507cdc920a0Smrg         config->visualType = *bp++;
508cdc920a0Smrg         break;
509cdc920a0Smrg      case GLX_TRANSPARENT_TYPE:
510cdc920a0Smrg         config->transparentPixel = *bp++;
511cdc920a0Smrg         break;
512cdc920a0Smrg      case GLX_TRANSPARENT_INDEX_VALUE:
513cdc920a0Smrg         config->transparentIndex = *bp++;
514cdc920a0Smrg         break;
515cdc920a0Smrg      case GLX_TRANSPARENT_RED_VALUE:
516cdc920a0Smrg         config->transparentRed = *bp++;
517cdc920a0Smrg         break;
518cdc920a0Smrg      case GLX_TRANSPARENT_GREEN_VALUE:
519cdc920a0Smrg         config->transparentGreen = *bp++;
520cdc920a0Smrg         break;
521cdc920a0Smrg      case GLX_TRANSPARENT_BLUE_VALUE:
522cdc920a0Smrg         config->transparentBlue = *bp++;
523cdc920a0Smrg         break;
524cdc920a0Smrg      case GLX_TRANSPARENT_ALPHA_VALUE:
525cdc920a0Smrg         config->transparentAlpha = *bp++;
526cdc920a0Smrg         break;
527cdc920a0Smrg      case GLX_VISUAL_ID:
528cdc920a0Smrg         config->visualID = *bp++;
529cdc920a0Smrg         break;
530cdc920a0Smrg      case GLX_DRAWABLE_TYPE:
531cdc920a0Smrg         config->drawableType = *bp++;
532cdc920a0Smrg#ifdef GLX_USE_APPLEGL
533cdc920a0Smrg         /* AppleSGLX supports pixmap and pbuffers with all config. */
534cdc920a0Smrg         config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
535cdc920a0Smrg#endif
536cdc920a0Smrg         break;
537af69d88dSmrg      case GLX_RENDER_TYPE: /* fbconfig render type bits */
5387ec681f3Smrg         config->renderType = *bp++;
539cdc920a0Smrg         break;
540cdc920a0Smrg      case GLX_X_RENDERABLE:
541cdc920a0Smrg         config->xRenderable = *bp++;
542cdc920a0Smrg         break;
543cdc920a0Smrg      case GLX_FBCONFIG_ID:
544cdc920a0Smrg         config->fbconfigID = *bp++;
545cdc920a0Smrg         break;
546cdc920a0Smrg      case GLX_MAX_PBUFFER_WIDTH:
547cdc920a0Smrg         config->maxPbufferWidth = *bp++;
548cdc920a0Smrg         break;
549cdc920a0Smrg      case GLX_MAX_PBUFFER_HEIGHT:
550cdc920a0Smrg         config->maxPbufferHeight = *bp++;
551cdc920a0Smrg         break;
552cdc920a0Smrg      case GLX_MAX_PBUFFER_PIXELS:
553cdc920a0Smrg         config->maxPbufferPixels = *bp++;
554cdc920a0Smrg         break;
555cdc920a0Smrg#ifndef GLX_USE_APPLEGL
556cdc920a0Smrg      case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
557cdc920a0Smrg         config->optimalPbufferWidth = *bp++;
558cdc920a0Smrg         break;
559cdc920a0Smrg      case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
560cdc920a0Smrg         config->optimalPbufferHeight = *bp++;
561cdc920a0Smrg         break;
562cdc920a0Smrg      case GLX_VISUAL_SELECT_GROUP_SGIX:
563cdc920a0Smrg         config->visualSelectGroup = *bp++;
564cdc920a0Smrg         break;
565cdc920a0Smrg      case GLX_SWAP_METHOD_OML:
56601e04c3fSmrg         if (*bp == GLX_SWAP_UNDEFINED_OML ||
56701e04c3fSmrg             *bp == GLX_SWAP_COPY_OML ||
56801e04c3fSmrg             *bp == GLX_SWAP_EXCHANGE_OML) {
56901e04c3fSmrg            config->swapMethod = *bp++;
57001e04c3fSmrg         } else {
57101e04c3fSmrg            /* X servers with old HW drivers may return any value here, so
57201e04c3fSmrg             * assume GLX_SWAP_METHOD_UNDEFINED.
57301e04c3fSmrg             */
57401e04c3fSmrg            config->swapMethod = GLX_SWAP_UNDEFINED_OML;
57501e04c3fSmrg            bp++;
57601e04c3fSmrg         }
577cdc920a0Smrg         break;
578cdc920a0Smrg#endif
579cdc920a0Smrg      case GLX_SAMPLE_BUFFERS_SGIS:
580cdc920a0Smrg         config->sampleBuffers = *bp++;
581cdc920a0Smrg         break;
582cdc920a0Smrg      case GLX_SAMPLES_SGIS:
583cdc920a0Smrg         config->samples = *bp++;
584cdc920a0Smrg         break;
585cdc920a0Smrg#ifdef GLX_USE_APPLEGL
586cdc920a0Smrg      case IGNORE_GLX_SWAP_METHOD_OML:
587cdc920a0Smrg         /* We ignore this tag.  See the comment above this function. */
588cdc920a0Smrg         ++bp;
589cdc920a0Smrg         break;
590cdc920a0Smrg#else
591cdc920a0Smrg      case GLX_BIND_TO_TEXTURE_RGB_EXT:
592cdc920a0Smrg         config->bindToTextureRgb = *bp++;
593cdc920a0Smrg         break;
594cdc920a0Smrg      case GLX_BIND_TO_TEXTURE_RGBA_EXT:
595cdc920a0Smrg         config->bindToTextureRgba = *bp++;
596cdc920a0Smrg         break;
597cdc920a0Smrg      case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
598cdc920a0Smrg         config->bindToMipmapTexture = *bp++;
599cdc920a0Smrg         break;
600cdc920a0Smrg      case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
601cdc920a0Smrg         config->bindToTextureTargets = *bp++;
602cdc920a0Smrg         break;
603cdc920a0Smrg      case GLX_Y_INVERTED_EXT:
604cdc920a0Smrg         config->yInverted = *bp++;
605cdc920a0Smrg         break;
606cdc920a0Smrg#endif
6073464ebd5Sriastradh      case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
6083464ebd5Sriastradh         config->sRGBCapable = *bp++;
6093464ebd5Sriastradh         break;
6103464ebd5Sriastradh
611cdc920a0Smrg      case GLX_USE_GL:
612cdc920a0Smrg         if (fbconfig_style_tags)
613cdc920a0Smrg            bp++;
614cdc920a0Smrg         break;
615cdc920a0Smrg      case None:
616cdc920a0Smrg         i = count;
617cdc920a0Smrg         break;
6187ec681f3Smrg      default: {
6197ec681f3Smrg            long int tagvalue = *bp++;
6207ec681f3Smrg            DebugMessageF("WARNING: unknown fbconfig attribute from server: "
6217ec681f3Smrg                          "tag 0x%lx value 0x%lx\n", tag, tagvalue);
6227ec681f3Smrg            break;
623cdc920a0Smrg         }
624cdc920a0Smrg      }
625cdc920a0Smrg   }
626cdc920a0Smrg}
627cdc920a0Smrg
6283464ebd5Sriastradhstatic struct glx_config *
629cdc920a0SmrgcreateConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
630cdc920a0Smrg                            int screen, GLboolean tagged_only)
631cdc920a0Smrg{
632cdc920a0Smrg   INT32 buf[__GLX_TOTAL_CONFIG], *props;
633cdc920a0Smrg   unsigned prop_size;
6343464ebd5Sriastradh   struct glx_config *modes, *m;
635cdc920a0Smrg   int i;
636cdc920a0Smrg
637cdc920a0Smrg   if (nprops == 0)
638cdc920a0Smrg      return NULL;
639cdc920a0Smrg
640cdc920a0Smrg   /* Check number of properties */
6417ec681f3Smrg   if (nprops < __GLX_MIN_CONFIG_PROPS)
642cdc920a0Smrg      return NULL;
643cdc920a0Smrg
644cdc920a0Smrg   /* Allocate memory for our config structure */
6453464ebd5Sriastradh   modes = glx_config_create_list(nvisuals);
646cdc920a0Smrg   if (!modes)
647cdc920a0Smrg      return NULL;
648cdc920a0Smrg
649cdc920a0Smrg   prop_size = nprops * __GLX_SIZE_INT32;
650cdc920a0Smrg   if (prop_size <= sizeof(buf))
651cdc920a0Smrg      props = buf;
652cdc920a0Smrg   else
653af69d88dSmrg      props = malloc(prop_size);
654cdc920a0Smrg
655cdc920a0Smrg   /* Read each config structure and convert it into our format */
656cdc920a0Smrg   m = modes;
657cdc920a0Smrg   for (i = 0; i < nvisuals; i++) {
658cdc920a0Smrg      _XRead(dpy, (char *) props, prop_size);
659cdc920a0Smrg#ifdef GLX_USE_APPLEGL
660cdc920a0Smrg       /* Older X servers don't send this so we default it here. */
661cdc920a0Smrg      m->drawableType = GLX_WINDOW_BIT;
662cdc920a0Smrg#else
663cdc920a0Smrg      /*
664cdc920a0Smrg       * The XQuartz 2.3.2.1 X server doesn't set this properly, so
665cdc920a0Smrg       * set the proper bits here.
666cdc920a0Smrg       * AppleSGLX supports windows, pixmaps, and pbuffers with all config.
667cdc920a0Smrg       */
668cdc920a0Smrg      m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
669cdc920a0Smrg#endif
670cdc920a0Smrg       __glXInitializeVisualConfigFromTags(m, nprops, props,
671cdc920a0Smrg                                          tagged_only, GL_TRUE);
672cdc920a0Smrg      m->screen = screen;
673cdc920a0Smrg      m = m->next;
674cdc920a0Smrg   }
675cdc920a0Smrg
676cdc920a0Smrg   if (props != buf)
677af69d88dSmrg      free(props);
678cdc920a0Smrg
679cdc920a0Smrg   return modes;
680cdc920a0Smrg}
681cdc920a0Smrg
682cdc920a0Smrgstatic GLboolean
6833464ebd5SriastradhgetVisualConfigs(struct glx_screen *psc,
6843464ebd5Sriastradh		  struct glx_display *priv, int screen)
685cdc920a0Smrg{
686cdc920a0Smrg   xGLXGetVisualConfigsReq *req;
687cdc920a0Smrg   xGLXGetVisualConfigsReply reply;
6883464ebd5Sriastradh   Display *dpy = priv->dpy;
689cdc920a0Smrg
690cdc920a0Smrg   LockDisplay(dpy);
691cdc920a0Smrg
692cdc920a0Smrg   psc->visuals = NULL;
693cdc920a0Smrg   GetReq(GLXGetVisualConfigs, req);
6947ec681f3Smrg   req->reqType = priv->codes.major_opcode;
695cdc920a0Smrg   req->glxCode = X_GLXGetVisualConfigs;
696cdc920a0Smrg   req->screen = screen;
697cdc920a0Smrg
698cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & reply, 0, False))
699cdc920a0Smrg      goto out;
700cdc920a0Smrg
701cdc920a0Smrg   psc->visuals = createConfigsFromProperties(dpy,
702cdc920a0Smrg                                              reply.numVisuals,
703cdc920a0Smrg                                              reply.numProps,
704cdc920a0Smrg                                              screen, GL_FALSE);
705cdc920a0Smrg
706cdc920a0Smrg out:
707cdc920a0Smrg   UnlockDisplay(dpy);
708cdc920a0Smrg   return psc->visuals != NULL;
709cdc920a0Smrg}
710cdc920a0Smrg
711cdc920a0Smrgstatic GLboolean
7127ec681f3SmrggetFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen)
713cdc920a0Smrg{
714cdc920a0Smrg   xGLXGetFBConfigsReq *fb_req;
715cdc920a0Smrg   xGLXGetFBConfigsSGIXReq *sgi_req;
716cdc920a0Smrg   xGLXVendorPrivateWithReplyReq *vpreq;
717cdc920a0Smrg   xGLXGetFBConfigsReply reply;
7183464ebd5Sriastradh   Display *dpy = priv->dpy;
719cdc920a0Smrg
7207ec681f3Smrg   psc->serverGLXexts = __glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
721cdc920a0Smrg
722af69d88dSmrg   if (psc->serverGLXexts == NULL) {
723af69d88dSmrg      return GL_FALSE;
724af69d88dSmrg   }
725af69d88dSmrg
726cdc920a0Smrg   LockDisplay(dpy);
727cdc920a0Smrg
728cdc920a0Smrg   psc->configs = NULL;
7297ec681f3Smrg   if (priv->minorVersion >= 3) {
730cdc920a0Smrg      GetReq(GLXGetFBConfigs, fb_req);
7317ec681f3Smrg      fb_req->reqType = priv->codes.major_opcode;
732cdc920a0Smrg      fb_req->glxCode = X_GLXGetFBConfigs;
733cdc920a0Smrg      fb_req->screen = screen;
734cdc920a0Smrg   }
735cdc920a0Smrg   else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
736cdc920a0Smrg      GetReqExtra(GLXVendorPrivateWithReply,
7373464ebd5Sriastradh                  sz_xGLXGetFBConfigsSGIXReq -
738cdc920a0Smrg                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
739cdc920a0Smrg      sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
7407ec681f3Smrg      sgi_req->reqType = priv->codes.major_opcode;
741cdc920a0Smrg      sgi_req->glxCode = X_GLXVendorPrivateWithReply;
742cdc920a0Smrg      sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
743cdc920a0Smrg      sgi_req->screen = screen;
744cdc920a0Smrg   }
745cdc920a0Smrg   else
746cdc920a0Smrg      goto out;
747cdc920a0Smrg
748cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & reply, 0, False))
749cdc920a0Smrg      goto out;
750cdc920a0Smrg
751cdc920a0Smrg   psc->configs = createConfigsFromProperties(dpy,
752cdc920a0Smrg                                              reply.numFBConfigs,
753cdc920a0Smrg                                              reply.numAttribs * 2,
754cdc920a0Smrg                                              screen, GL_TRUE);
755cdc920a0Smrg
756cdc920a0Smrg out:
757cdc920a0Smrg   UnlockDisplay(dpy);
758cdc920a0Smrg   return psc->configs != NULL;
759cdc920a0Smrg}
760cdc920a0Smrg
7613464ebd5Sriastradh_X_HIDDEN Bool
7623464ebd5Sriastradhglx_screen_init(struct glx_screen *psc,
7633464ebd5Sriastradh		 int screen, struct glx_display * priv)
7643464ebd5Sriastradh{
7653464ebd5Sriastradh   /* Initialize per screen dynamic client GLX extensions */
7663464ebd5Sriastradh   psc->ext_list_first_time = GL_TRUE;
7673464ebd5Sriastradh   psc->scr = screen;
7683464ebd5Sriastradh   psc->dpy = priv->dpy;
7693464ebd5Sriastradh   psc->display = priv;
7703464ebd5Sriastradh
77101e04c3fSmrg   if (!getVisualConfigs(psc, priv, screen))
77201e04c3fSmrg      return GL_FALSE;
77301e04c3fSmrg
77401e04c3fSmrg   if (!getFBConfigs(psc, priv, screen))
77501e04c3fSmrg      return GL_FALSE;
7763464ebd5Sriastradh
7773464ebd5Sriastradh   return GL_TRUE;
7783464ebd5Sriastradh}
7793464ebd5Sriastradh
7803464ebd5Sriastradh_X_HIDDEN void
7813464ebd5Sriastradhglx_screen_cleanup(struct glx_screen *psc)
7823464ebd5Sriastradh{
7833464ebd5Sriastradh   if (psc->configs) {
7843464ebd5Sriastradh      glx_config_destroy_list(psc->configs);
785af69d88dSmrg      free(psc->effectiveGLXexts);
7863464ebd5Sriastradh      psc->configs = NULL;   /* NOTE: just for paranoia */
7873464ebd5Sriastradh   }
7883464ebd5Sriastradh   if (psc->visuals) {
7893464ebd5Sriastradh      glx_config_destroy_list(psc->visuals);
7903464ebd5Sriastradh      psc->visuals = NULL;   /* NOTE: just for paranoia */
7913464ebd5Sriastradh   }
792af69d88dSmrg   free((char *) psc->serverGLXexts);
7937ec681f3Smrg   free((char *) psc->serverGLXvendor);
7947ec681f3Smrg   free((char *) psc->serverGLXversion);
7953464ebd5Sriastradh}
7963464ebd5Sriastradh
797cdc920a0Smrg/*
798cdc920a0Smrg** Allocate the memory for the per screen configs for each screen.
799cdc920a0Smrg** If that works then fetch the per screen configs data.
800cdc920a0Smrg*/
801cdc920a0Smrgstatic Bool
8023464ebd5SriastradhAllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
803cdc920a0Smrg{
8043464ebd5Sriastradh   struct glx_screen *psc;
805cdc920a0Smrg   GLint i, screens;
806cdc920a0Smrg
807cdc920a0Smrg   /*
808cdc920a0Smrg    ** First allocate memory for the array of per screen configs.
809cdc920a0Smrg    */
810cdc920a0Smrg   screens = ScreenCount(dpy);
8119f464c52Smaya   priv->screens = calloc(screens, sizeof *priv->screens);
8123464ebd5Sriastradh   if (!priv->screens)
813cdc920a0Smrg      return GL_FALSE;
814cdc920a0Smrg
815cdc920a0Smrg   for (i = 0; i < screens; i++, psc++) {
8163464ebd5Sriastradh      psc = NULL;
817cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
818af69d88dSmrg#if defined(GLX_USE_DRM)
819af69d88dSmrg#if defined(HAVE_DRI3)
820af69d88dSmrg      if (priv->dri3Display)
821af69d88dSmrg         psc = (*priv->dri3Display->createScreen) (i, priv);
822af69d88dSmrg#endif /* HAVE_DRI3 */
823af69d88dSmrg      if (psc == NULL && priv->dri2Display)
8243464ebd5Sriastradh	 psc = (*priv->dri2Display->createScreen) (i, priv);
825af69d88dSmrg#endif /* GLX_USE_DRM */
82601e04c3fSmrg
82701e04c3fSmrg#ifdef GLX_USE_WINDOWSGL
82801e04c3fSmrg      if (psc == NULL && priv->windowsdriDisplay)
82901e04c3fSmrg	 psc = (*priv->windowsdriDisplay->createScreen) (i, priv);
83001e04c3fSmrg#endif
83101e04c3fSmrg
8323464ebd5Sriastradh      if (psc == NULL && priv->driswDisplay)
8333464ebd5Sriastradh	 psc = (*priv->driswDisplay->createScreen) (i, priv);
834af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
835af69d88dSmrg
8363464ebd5Sriastradh#if defined(GLX_USE_APPLEGL)
8373464ebd5Sriastradh      if (psc == NULL)
8383464ebd5Sriastradh         psc = applegl_create_screen(i, priv);
8393464ebd5Sriastradh#else
8403464ebd5Sriastradh      if (psc == NULL)
8413464ebd5Sriastradh	 psc = indirect_create_screen(i, priv);
8423464ebd5Sriastradh#endif
8433464ebd5Sriastradh      priv->screens[i] = psc;
844cdc920a0Smrg   }
845cdc920a0Smrg   SyncHandle();
846cdc920a0Smrg   return GL_TRUE;
847cdc920a0Smrg}
848cdc920a0Smrg
849cdc920a0Smrg/*
850cdc920a0Smrg** Initialize the client side extension code.
851cdc920a0Smrg*/
8523464ebd5Sriastradh _X_HIDDEN struct glx_display *
853cdc920a0Smrg__glXInitialize(Display * dpy)
854cdc920a0Smrg{
8557ec681f3Smrg   XExtCodes *codes;
8563464ebd5Sriastradh   struct glx_display *dpyPriv, *d;
857cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
858cdc920a0Smrg   Bool glx_direct, glx_accel;
859cdc920a0Smrg#endif
8607ec681f3Smrg   int i, majorVersion = 0;
861cdc920a0Smrg
8623464ebd5Sriastradh   _XLockMutex(_Xglobal_lock);
863cdc920a0Smrg
8643464ebd5Sriastradh   for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) {
8653464ebd5Sriastradh      if (dpyPriv->dpy == dpy) {
8663464ebd5Sriastradh	 _XUnlockMutex(_Xglobal_lock);
8673464ebd5Sriastradh	 return dpyPriv;
8683464ebd5Sriastradh      }
869cdc920a0Smrg   }
870cdc920a0Smrg
8713464ebd5Sriastradh   /* Drop the lock while we create the display private. */
8723464ebd5Sriastradh   _XUnlockMutex(_Xglobal_lock);
873cdc920a0Smrg
874af69d88dSmrg   dpyPriv = calloc(1, sizeof *dpyPriv);
8753464ebd5Sriastradh   if (!dpyPriv)
8763464ebd5Sriastradh      return NULL;
877cdc920a0Smrg
8787ec681f3Smrg   codes = XInitExtension(dpy, __glXExtensionName);
8797ec681f3Smrg   if (!codes) {
880af69d88dSmrg      free(dpyPriv);
8813464ebd5Sriastradh      return NULL;
882cdc920a0Smrg   }
883cdc920a0Smrg
8847ec681f3Smrg   dpyPriv->codes = *codes;
885cdc920a0Smrg   dpyPriv->dpy = dpy;
886cdc920a0Smrg
8877ec681f3Smrg   /* This GLX implementation requires X_GLXQueryExtensionsString
8887ec681f3Smrg    * and X_GLXQueryServerString, which are new in GLX 1.1.
889af69d88dSmrg    */
8907ec681f3Smrg   if (!QueryVersion(dpy, dpyPriv->codes.major_opcode,
8917ec681f3Smrg		     &majorVersion, &dpyPriv->minorVersion)
8927ec681f3Smrg       || (majorVersion != 1)
8937ec681f3Smrg       || (majorVersion == 1 && dpyPriv->minorVersion < 1)) {
894af69d88dSmrg      free(dpyPriv);
8953464ebd5Sriastradh      return NULL;
8963464ebd5Sriastradh   }
8973464ebd5Sriastradh
8983464ebd5Sriastradh   for (i = 0; i < __GLX_NUMBER_EVENTS; i++) {
8997ec681f3Smrg      XESetWireToEvent(dpy, dpyPriv->codes.first_event + i, __glXWireToEvent);
9007ec681f3Smrg      XESetEventToWire(dpy, dpyPriv->codes.first_event + i, __glXEventToWire);
9013464ebd5Sriastradh   }
9023464ebd5Sriastradh
9037ec681f3Smrg   XESetCloseDisplay(dpy, dpyPriv->codes.extension, __glXCloseDisplay);
9047ec681f3Smrg   XESetErrorString (dpy, dpyPriv->codes.extension, __glXErrorString);
9053464ebd5Sriastradh
906af69d88dSmrg   dpyPriv->glXDrawHash = __glxHashCreate();
907af69d88dSmrg
908cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
90901e04c3fSmrg   glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false);
91001e04c3fSmrg   glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
911cdc920a0Smrg
9123464ebd5Sriastradh   dpyPriv->drawHash = __glxHashCreate();
9133464ebd5Sriastradh
9147ec681f3Smrg#ifndef GLX_USE_APPLEGL
9157ec681f3Smrg   /* Set the logger before the *CreateDisplay functions. */
9167ec681f3Smrg   loader_set_logger(glx_message);
9177ec681f3Smrg#endif
9187ec681f3Smrg
919cdc920a0Smrg   /*
920cdc920a0Smrg    ** Initialize the direct rendering per display data and functions.
921cdc920a0Smrg    ** Note: This _must_ be done before calling any other DRI routines
922cdc920a0Smrg    ** (e.g., those called in AllocAndFetchScreenConfigs).
923cdc920a0Smrg    */
924af69d88dSmrg#if defined(GLX_USE_DRM)
925cdc920a0Smrg   if (glx_direct && glx_accel) {
926af69d88dSmrg#if defined(HAVE_DRI3)
92701e04c3fSmrg      if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false))
928af69d88dSmrg         dpyPriv->dri3Display = dri3_create_display(dpy);
929af69d88dSmrg#endif /* HAVE_DRI3 */
9307ec681f3Smrg      if (!env_var_as_boolean("LIBGL_DRI2_DISABLE", false))
9317ec681f3Smrg         dpyPriv->dri2Display = dri2CreateDisplay(dpy);
932cdc920a0Smrg   }
933af69d88dSmrg#endif /* GLX_USE_DRM */
934cdc920a0Smrg   if (glx_direct)
935cdc920a0Smrg      dpyPriv->driswDisplay = driswCreateDisplay(dpy);
936af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
9373464ebd5Sriastradh
938cdc920a0Smrg#ifdef GLX_USE_APPLEGL
9393464ebd5Sriastradh   if (!applegl_create_display(dpyPriv)) {
940af69d88dSmrg      free(dpyPriv);
9413464ebd5Sriastradh      return NULL;
9423464ebd5Sriastradh   }
943cdc920a0Smrg#endif
94401e04c3fSmrg
94501e04c3fSmrg#ifdef GLX_USE_WINDOWSGL
94601e04c3fSmrg   if (glx_direct && glx_accel)
94701e04c3fSmrg      dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy);
94801e04c3fSmrg#endif
94901e04c3fSmrg
9503464ebd5Sriastradh   if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
951af69d88dSmrg      free(dpyPriv);
9523464ebd5Sriastradh      return NULL;
953cdc920a0Smrg   }
954cdc920a0Smrg
955af69d88dSmrg   __glX_send_client_info(dpyPriv);
9563464ebd5Sriastradh
9573464ebd5Sriastradh   /* Grab the lock again and add the dispay private, unless somebody
9583464ebd5Sriastradh    * beat us to initializing on this display in the meantime. */
9593464ebd5Sriastradh   _XLockMutex(_Xglobal_lock);
9603464ebd5Sriastradh
9613464ebd5Sriastradh   for (d = glx_displays; d; d = d->next) {
9623464ebd5Sriastradh      if (d->dpy == dpy) {
9633464ebd5Sriastradh	 _XUnlockMutex(_Xglobal_lock);
9643464ebd5Sriastradh	 glx_display_free(dpyPriv);
9653464ebd5Sriastradh	 return d;
9663464ebd5Sriastradh      }
967cdc920a0Smrg   }
9683464ebd5Sriastradh
9693464ebd5Sriastradh   dpyPriv->next = glx_displays;
9703464ebd5Sriastradh   glx_displays = dpyPriv;
9713464ebd5Sriastradh
972af69d88dSmrg   _XUnlockMutex(_Xglobal_lock);
973cdc920a0Smrg
974cdc920a0Smrg   return dpyPriv;
975cdc920a0Smrg}
976cdc920a0Smrg
977cdc920a0Smrg/*
978cdc920a0Smrg** Setup for sending a GLX command on dpy.  Make sure the extension is
979cdc920a0Smrg** initialized.  Try to avoid calling __glXInitialize as its kinda slow.
980cdc920a0Smrg*/
981cdc920a0Smrg_X_HIDDEN CARD8
982cdc920a0Smrg__glXSetupForCommand(Display * dpy)
983cdc920a0Smrg{
9843464ebd5Sriastradh    struct glx_context *gc;
9853464ebd5Sriastradh    struct glx_display *priv;
986cdc920a0Smrg
987cdc920a0Smrg   /* If this thread has a current context, flush its rendering commands */
988cdc920a0Smrg   gc = __glXGetCurrentContext();
989cdc920a0Smrg   if (gc->currentDpy) {
990cdc920a0Smrg      /* Flush rendering buffer of the current context, if any */
991cdc920a0Smrg      (void) __glXFlushRenderBuffer(gc, gc->pc);
992cdc920a0Smrg
993cdc920a0Smrg      if (gc->currentDpy == dpy) {
994cdc920a0Smrg         /* Use opcode from gc because its right */
995cdc920a0Smrg         return gc->majorOpcode;
996cdc920a0Smrg      }
997cdc920a0Smrg      else {
998cdc920a0Smrg         /*
999cdc920a0Smrg          ** Have to get info about argument dpy because it might be to
1000cdc920a0Smrg          ** a different server
1001cdc920a0Smrg          */
1002cdc920a0Smrg      }
1003cdc920a0Smrg   }
1004cdc920a0Smrg
1005cdc920a0Smrg   /* Forced to lookup extension via the slow initialize route */
1006cdc920a0Smrg   priv = __glXInitialize(dpy);
1007cdc920a0Smrg   if (!priv) {
1008cdc920a0Smrg      return 0;
1009cdc920a0Smrg   }
10107ec681f3Smrg   return priv->codes.major_opcode;
1011cdc920a0Smrg}
1012cdc920a0Smrg
1013cdc920a0Smrg/**
1014cdc920a0Smrg * Flush the drawing command transport buffer.
1015cdc920a0Smrg *
1016cdc920a0Smrg * \param ctx  Context whose transport buffer is to be flushed.
1017cdc920a0Smrg * \param pc   Pointer to first unused buffer location.
1018cdc920a0Smrg *
1019cdc920a0Smrg * \todo
1020cdc920a0Smrg * Modify this function to use \c ctx->pc instead of the explicit
1021cdc920a0Smrg * \c pc parameter.
1022cdc920a0Smrg */
1023cdc920a0Smrg_X_HIDDEN GLubyte *
10243464ebd5Sriastradh__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc)
1025cdc920a0Smrg{
1026cdc920a0Smrg   Display *const dpy = ctx->currentDpy;
1027cdc920a0Smrg   xcb_connection_t *c = XGetXCBConnection(dpy);
1028cdc920a0Smrg   const GLint size = pc - ctx->buf;
1029cdc920a0Smrg
1030cdc920a0Smrg   if ((dpy != NULL) && (size > 0)) {
1031cdc920a0Smrg      xcb_glx_render(c, ctx->currentContextTag, size,
1032cdc920a0Smrg                     (const uint8_t *) ctx->buf);
1033cdc920a0Smrg   }
1034cdc920a0Smrg
1035cdc920a0Smrg   /* Reset pointer and return it */
1036cdc920a0Smrg   ctx->pc = ctx->buf;
1037cdc920a0Smrg   return ctx->pc;
1038cdc920a0Smrg}
1039cdc920a0Smrg
1040cdc920a0Smrg
1041cdc920a0Smrg/**
1042cdc920a0Smrg * Send a portion of a GLXRenderLarge command to the server.  The advantage of
1043cdc920a0Smrg * this function over \c __glXSendLargeCommand is that callers can use the
1044cdc920a0Smrg * data buffer in the GLX context and may be able to avoid allocating an
1045cdc920a0Smrg * extra buffer.  The disadvantage is the clients will have to do more
1046cdc920a0Smrg * GLX protocol work (i.e., calculating \c totalRequests, etc.).
1047cdc920a0Smrg *
1048cdc920a0Smrg * \sa __glXSendLargeCommand
1049cdc920a0Smrg *
1050cdc920a0Smrg * \param gc             GLX context
1051cdc920a0Smrg * \param requestNumber  Which part of the whole command is this?  The first
1052cdc920a0Smrg *                       request is 1.
1053cdc920a0Smrg * \param totalRequests  How many requests will there be?
1054cdc920a0Smrg * \param data           Command data.
1055cdc920a0Smrg * \param dataLen        Size, in bytes, of the command data.
1056cdc920a0Smrg */
1057cdc920a0Smrg_X_HIDDEN void
10583464ebd5Sriastradh__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber,
1059cdc920a0Smrg                    GLint totalRequests, const GLvoid * data, GLint dataLen)
1060cdc920a0Smrg{
1061cdc920a0Smrg   Display *dpy = gc->currentDpy;
1062cdc920a0Smrg   xcb_connection_t *c = XGetXCBConnection(dpy);
1063cdc920a0Smrg   xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
1064cdc920a0Smrg                        totalRequests, dataLen, data);
1065cdc920a0Smrg}
1066cdc920a0Smrg
1067cdc920a0Smrg
1068cdc920a0Smrg/**
1069cdc920a0Smrg * Send a command that is too large for the GLXRender protocol request.
1070cdc920a0Smrg *
1071cdc920a0Smrg * Send a large command, one that is too large for some reason to
1072cdc920a0Smrg * send using the GLXRender protocol request.  One reason to send
1073cdc920a0Smrg * a large command is to avoid copying the data.
1074cdc920a0Smrg *
1075cdc920a0Smrg * \param ctx        GLX context
1076cdc920a0Smrg * \param header     Header data.
1077cdc920a0Smrg * \param headerLen  Size, in bytes, of the header data.  It is assumed that
1078cdc920a0Smrg *                   the header data will always be small enough to fit in
1079cdc920a0Smrg *                   a single X protocol packet.
1080cdc920a0Smrg * \param data       Command data.
1081cdc920a0Smrg * \param dataLen    Size, in bytes, of the command data.
1082cdc920a0Smrg */
1083cdc920a0Smrg_X_HIDDEN void
10843464ebd5Sriastradh__glXSendLargeCommand(struct glx_context * ctx,
1085cdc920a0Smrg                      const GLvoid * header, GLint headerLen,
1086cdc920a0Smrg                      const GLvoid * data, GLint dataLen)
1087cdc920a0Smrg{
1088cdc920a0Smrg   GLint maxSize;
1089cdc920a0Smrg   GLint totalRequests, requestNumber;
1090cdc920a0Smrg
1091cdc920a0Smrg   /*
1092cdc920a0Smrg    ** Calculate the maximum amount of data can be stuffed into a single
1093cdc920a0Smrg    ** packet.  sz_xGLXRenderReq is added because bufSize is the maximum
1094cdc920a0Smrg    ** packet size minus sz_xGLXRenderReq.
1095cdc920a0Smrg    */
1096cdc920a0Smrg   maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
1097cdc920a0Smrg   totalRequests = 1 + (dataLen / maxSize);
1098cdc920a0Smrg   if (dataLen % maxSize)
1099cdc920a0Smrg      totalRequests++;
1100cdc920a0Smrg
1101cdc920a0Smrg   /*
1102cdc920a0Smrg    ** Send all of the command, except the large array, as one request.
1103cdc920a0Smrg    */
1104cdc920a0Smrg   assert(headerLen <= maxSize);
1105cdc920a0Smrg   __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
1106cdc920a0Smrg
1107cdc920a0Smrg   /*
1108cdc920a0Smrg    ** Send enough requests until the whole array is sent.
1109cdc920a0Smrg    */
1110cdc920a0Smrg   for (requestNumber = 2; requestNumber <= (totalRequests - 1);
1111cdc920a0Smrg        requestNumber++) {
1112cdc920a0Smrg      __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
1113cdc920a0Smrg      data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
1114cdc920a0Smrg      dataLen -= maxSize;
1115cdc920a0Smrg      assert(dataLen > 0);
1116cdc920a0Smrg   }
1117cdc920a0Smrg
1118cdc920a0Smrg   assert(dataLen <= maxSize);
1119cdc920a0Smrg   __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
1120cdc920a0Smrg}
1121