1848b8605Smrg/*
2848b8605Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3848b8605Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4848b8605Smrg *
5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6848b8605Smrg * copy of this software and associated documentation files (the "Software"),
7848b8605Smrg * to deal in the Software without restriction, including without limitation
8848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
10848b8605Smrg * Software is furnished to do so, subject to the following conditions:
11848b8605Smrg *
12848b8605Smrg * The above copyright notice including the dates of first publication and
13848b8605Smrg * either this permission notice or a reference to
14848b8605Smrg * http://oss.sgi.com/projects/FreeB/
15848b8605Smrg * shall be included in all copies or substantial portions of the Software.
16848b8605Smrg *
17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20848b8605Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21848b8605Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22848b8605Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23848b8605Smrg * SOFTWARE.
24848b8605Smrg *
25848b8605Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc.
26848b8605Smrg * shall not be used in advertising or otherwise to promote the sale, use or
27848b8605Smrg * other dealings in this Software without prior written authorization from
28848b8605Smrg * Silicon Graphics, Inc.
29848b8605Smrg */
30848b8605Smrg
31848b8605Smrg/**
32848b8605Smrg * \file glxext.c
33848b8605Smrg * GLX protocol interface boot-strap code.
34848b8605Smrg *
35848b8605Smrg * Direct rendering support added by Precision Insight, Inc.
36848b8605Smrg *
37848b8605Smrg * \author Kevin E. Martin <kevin@precisioninsight.com>
38848b8605Smrg */
39848b8605Smrg
40848b8605Smrg#include <assert.h>
41b8e80941Smrg#include <stdbool.h>
42b8e80941Smrg
43848b8605Smrg#include "glxclient.h"
44848b8605Smrg#include <X11/extensions/Xext.h>
45848b8605Smrg#include <X11/extensions/extutil.h>
46848b8605Smrg#ifdef GLX_USE_APPLEGL
47848b8605Smrg#include "apple/apple_glx.h"
48848b8605Smrg#include "apple/apple_visual.h"
49848b8605Smrg#endif
50848b8605Smrg#include "glxextensions.h"
51848b8605Smrg
52b8e80941Smrg#include "util/debug.h"
53b8e80941Smrg
54848b8605Smrg#include <X11/Xlib-xcb.h>
55848b8605Smrg#include <xcb/xcb.h>
56848b8605Smrg#include <xcb/glx.h>
57848b8605Smrg
58848b8605Smrg
59848b8605Smrg#ifdef DEBUG
60848b8605Smrgvoid __glXDumpDrawBuffer(struct glx_context * ctx);
61848b8605Smrg#endif
62848b8605Smrg
63848b8605Smrg/*
64848b8605Smrg** You can set this cell to 1 to force the gl drawing stuff to be
65848b8605Smrg** one command per packet
66848b8605Smrg*/
67848b8605Smrg_X_HIDDEN int __glXDebug = 0;
68848b8605Smrg
69848b8605Smrg/* Extension required boiler plate */
70848b8605Smrg
71848b8605Smrgstatic const char __glXExtensionName[] = GLX_EXTENSION_NAME;
72848b8605Smrg  static struct glx_display *glx_displays;
73848b8605Smrg
74848b8605Smrgstatic /* const */ char *error_list[] = {
75848b8605Smrg   "GLXBadContext",
76848b8605Smrg   "GLXBadContextState",
77848b8605Smrg   "GLXBadDrawable",
78848b8605Smrg   "GLXBadPixmap",
79848b8605Smrg   "GLXBadContextTag",
80848b8605Smrg   "GLXBadCurrentWindow",
81848b8605Smrg   "GLXBadRenderRequest",
82848b8605Smrg   "GLXBadLargeRequest",
83848b8605Smrg   "GLXUnsupportedPrivateRequest",
84848b8605Smrg   "GLXBadFBConfig",
85848b8605Smrg   "GLXBadPbuffer",
86848b8605Smrg   "GLXBadCurrentDrawable",
87848b8605Smrg   "GLXBadWindow",
88848b8605Smrg   "GLXBadProfileARB",
89848b8605Smrg};
90848b8605Smrg
91848b8605Smrg#ifdef GLX_USE_APPLEGL
92848b8605Smrgstatic char *__glXErrorString(Display *dpy, int code, XExtCodes *codes,
93848b8605Smrg                              char *buf, int n);
94848b8605Smrg#endif
95848b8605Smrg
96848b8605Smrgstatic
97848b8605SmrgXEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
98848b8605Smrg                           __GLX_NUMBER_ERRORS, error_list)
99848b8605Smrg
100848b8605Smrg/*
101848b8605Smrg * GLX events are a bit funky.  We don't stuff the X event code into
102848b8605Smrg * our user exposed (via XNextEvent) structure.  Instead we use the GLX
103848b8605Smrg * private event code namespace (and hope it doesn't conflict).  Clients
104848b8605Smrg * have to know that bit 15 in the event type field means they're getting
105848b8605Smrg * a GLX event, and then handle the various sub-event types there, rather
106848b8605Smrg * than simply checking the event code and handling it directly.
107848b8605Smrg */
108848b8605Smrg
109848b8605Smrgstatic Bool
110848b8605Smrg__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
111848b8605Smrg{
112848b8605Smrg     struct glx_display *glx_dpy = __glXInitialize(dpy);
113848b8605Smrg
114848b8605Smrg   if (glx_dpy == NULL)
115848b8605Smrg      return False;
116848b8605Smrg
117848b8605Smrg   switch ((wire->u.u.type & 0x7f) - glx_dpy->codes->first_event) {
118848b8605Smrg   case GLX_PbufferClobber:
119848b8605Smrg   {
120848b8605Smrg      GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event;
121848b8605Smrg      xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire;
122848b8605Smrg      aevent->event_type = awire->type;
123848b8605Smrg      aevent->serial = awire->sequenceNumber;
124848b8605Smrg      aevent->event_type = awire->event_type;
125848b8605Smrg      aevent->draw_type = awire->draw_type;
126848b8605Smrg      aevent->drawable = awire->drawable;
127848b8605Smrg      aevent->buffer_mask = awire->buffer_mask;
128848b8605Smrg      aevent->aux_buffer = awire->aux_buffer;
129848b8605Smrg      aevent->x = awire->x;
130848b8605Smrg      aevent->y = awire->y;
131848b8605Smrg      aevent->width = awire->width;
132848b8605Smrg      aevent->height = awire->height;
133848b8605Smrg      aevent->count = awire->count;
134848b8605Smrg      return True;
135848b8605Smrg   }
136848b8605Smrg   case GLX_BufferSwapComplete:
137848b8605Smrg   {
138848b8605Smrg      GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
139848b8605Smrg      xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire;
140848b8605Smrg      struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable);
141848b8605Smrg
142848b8605Smrg      if (!glxDraw)
143848b8605Smrg	 return False;
144848b8605Smrg
145b8e80941Smrg      aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
146b8e80941Smrg      aevent->send_event = (awire->type & 0x80) != 0;
147b8e80941Smrg      aevent->display = dpy;
148848b8605Smrg      aevent->event_type = awire->event_type;
149848b8605Smrg      aevent->drawable = glxDraw->xDrawable;
150848b8605Smrg      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
151848b8605Smrg      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
152848b8605Smrg
153b8e80941Smrg      /* Handle 32-Bit wire sbc wraparound in both directions to cope with out
154b8e80941Smrg       * of sequence 64-Bit sbc's
155b8e80941Smrg       */
156b8e80941Smrg      if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000))
157b8e80941Smrg         glxDraw->eventSbcWrap += 0x100000000;
158b8e80941Smrg      if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000))
159b8e80941Smrg         glxDraw->eventSbcWrap -= 0x100000000;
160848b8605Smrg      glxDraw->lastEventSbc = awire->sbc;
161848b8605Smrg      aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
162848b8605Smrg      return True;
163848b8605Smrg   }
164848b8605Smrg   default:
165848b8605Smrg      /* client doesn't support server event */
166848b8605Smrg      break;
167848b8605Smrg   }
168848b8605Smrg
169848b8605Smrg   return False;
170848b8605Smrg}
171848b8605Smrg
172848b8605Smrg/* We don't actually support this.  It doesn't make sense for clients to
173848b8605Smrg * send each other GLX events.
174848b8605Smrg */
175848b8605Smrgstatic Status
176848b8605Smrg__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
177848b8605Smrg{
178848b8605Smrg     struct glx_display *glx_dpy = __glXInitialize(dpy);
179848b8605Smrg
180848b8605Smrg   if (glx_dpy == NULL)
181848b8605Smrg      return False;
182848b8605Smrg
183848b8605Smrg   switch (event->type) {
184848b8605Smrg   case GLX_DAMAGED:
185848b8605Smrg      break;
186848b8605Smrg   case GLX_SAVED:
187848b8605Smrg      break;
188848b8605Smrg   case GLX_EXCHANGE_COMPLETE_INTEL:
189848b8605Smrg      break;
190848b8605Smrg   case GLX_COPY_COMPLETE_INTEL:
191848b8605Smrg      break;
192848b8605Smrg   case GLX_FLIP_COMPLETE_INTEL:
193848b8605Smrg      break;
194848b8605Smrg   default:
195848b8605Smrg      /* client doesn't support server event */
196848b8605Smrg      break;
197848b8605Smrg   }
198848b8605Smrg
199848b8605Smrg   return Success;
200848b8605Smrg}
201848b8605Smrg
202848b8605Smrg/************************************************************************/
203848b8605Smrg/*
204848b8605Smrg** Free the per screen configs data as well as the array of
205848b8605Smrg** __glXScreenConfigs.
206848b8605Smrg*/
207848b8605Smrgstatic void
208848b8605SmrgFreeScreenConfigs(struct glx_display * priv)
209848b8605Smrg{
210848b8605Smrg   struct glx_screen *psc;
211848b8605Smrg   GLint i, screens;
212848b8605Smrg
213848b8605Smrg   /* Free screen configuration information */
214848b8605Smrg   screens = ScreenCount(priv->dpy);
215848b8605Smrg   for (i = 0; i < screens; i++) {
216848b8605Smrg      psc = priv->screens[i];
217b8e80941Smrg      if (!psc)
218b8e80941Smrg         continue;
219848b8605Smrg      glx_screen_cleanup(psc);
220848b8605Smrg
221848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
222848b8605Smrg      if (psc->driScreen) {
223848b8605Smrg         psc->driScreen->destroyScreen(psc);
224848b8605Smrg      } else {
225848b8605Smrg	 free(psc);
226848b8605Smrg      }
227848b8605Smrg#else
228848b8605Smrg      free(psc);
229848b8605Smrg#endif
230848b8605Smrg   }
231848b8605Smrg   free((char *) priv->screens);
232848b8605Smrg   priv->screens = NULL;
233848b8605Smrg}
234848b8605Smrg
235848b8605Smrgstatic void
236848b8605Smrgglx_display_free(struct glx_display *priv)
237848b8605Smrg{
238848b8605Smrg   struct glx_context *gc;
239848b8605Smrg
240848b8605Smrg   gc = __glXGetCurrentContext();
241848b8605Smrg   if (priv->dpy == gc->currentDpy) {
242848b8605Smrg      gc->vtable->destroy(gc);
243848b8605Smrg      __glXSetCurrentContextNull();
244848b8605Smrg   }
245848b8605Smrg
246848b8605Smrg   FreeScreenConfigs(priv);
247848b8605Smrg   free((char *) priv->serverGLXvendor);
248848b8605Smrg   free((char *) priv->serverGLXversion);
249848b8605Smrg
250848b8605Smrg   __glxHashDestroy(priv->glXDrawHash);
251848b8605Smrg
252848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
253848b8605Smrg   __glxHashDestroy(priv->drawHash);
254848b8605Smrg
255848b8605Smrg   /* Free the direct rendering per display data */
256848b8605Smrg   if (priv->driswDisplay)
257848b8605Smrg      (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
258848b8605Smrg   priv->driswDisplay = NULL;
259848b8605Smrg
260848b8605Smrg#if defined (GLX_USE_DRM)
261848b8605Smrg   if (priv->driDisplay)
262848b8605Smrg      (*priv->driDisplay->destroyDisplay) (priv->driDisplay);
263848b8605Smrg   priv->driDisplay = NULL;
264848b8605Smrg
265848b8605Smrg   if (priv->dri2Display)
266848b8605Smrg      (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
267848b8605Smrg   priv->dri2Display = NULL;
268848b8605Smrg
269848b8605Smrg   if (priv->dri3Display)
270848b8605Smrg      (*priv->dri3Display->destroyDisplay) (priv->dri3Display);
271848b8605Smrg   priv->dri3Display = NULL;
272848b8605Smrg#endif /* GLX_USE_DRM */
273b8e80941Smrg
274b8e80941Smrg#if defined(GLX_USE_WINDOWSGL)
275b8e80941Smrg   if (priv->windowsdriDisplay)
276b8e80941Smrg      (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay);
277b8e80941Smrg   priv->windowsdriDisplay = NULL;
278b8e80941Smrg#endif /* GLX_USE_WINDOWSGL */
279b8e80941Smrg
280848b8605Smrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
281848b8605Smrg
282848b8605Smrg   free((char *) priv);
283848b8605Smrg}
284848b8605Smrg
285848b8605Smrgstatic int
286848b8605Smrg__glXCloseDisplay(Display * dpy, XExtCodes * codes)
287848b8605Smrg{
288848b8605Smrg   struct glx_display *priv, **prev;
289848b8605Smrg
290848b8605Smrg   _XLockMutex(_Xglobal_lock);
291848b8605Smrg   prev = &glx_displays;
292848b8605Smrg   for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
293848b8605Smrg      if (priv->dpy == dpy) {
294848b8605Smrg         *prev = priv->next;
295848b8605Smrg	 break;
296848b8605Smrg      }
297848b8605Smrg   }
298848b8605Smrg   _XUnlockMutex(_Xglobal_lock);
299848b8605Smrg
300848b8605Smrg   if (priv != NULL)
301848b8605Smrg      glx_display_free(priv);
302848b8605Smrg
303848b8605Smrg   return 1;
304848b8605Smrg}
305848b8605Smrg
306848b8605Smrg/*
307848b8605Smrg** Query the version of the GLX extension.  This procedure works even if
308848b8605Smrg** the client extension is not completely set up.
309848b8605Smrg*/
310848b8605Smrgstatic Bool
311848b8605SmrgQueryVersion(Display * dpy, int opcode, int *major, int *minor)
312848b8605Smrg{
313848b8605Smrg   xcb_connection_t *c = XGetXCBConnection(dpy);
314848b8605Smrg   xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c,
315848b8605Smrg                                                                      xcb_glx_query_version
316848b8605Smrg                                                                      (c,
317848b8605Smrg                                                                       GLX_MAJOR_VERSION,
318848b8605Smrg                                                                       GLX_MINOR_VERSION),
319848b8605Smrg                                                                      NULL);
320848b8605Smrg
321848b8605Smrg   if (!reply)
322848b8605Smrg     return GL_FALSE;
323848b8605Smrg
324848b8605Smrg   if (reply->major_version != GLX_MAJOR_VERSION) {
325848b8605Smrg      free(reply);
326848b8605Smrg      return GL_FALSE;
327848b8605Smrg   }
328848b8605Smrg   *major = reply->major_version;
329848b8605Smrg   *minor = min(reply->minor_version, GLX_MINOR_VERSION);
330848b8605Smrg   free(reply);
331848b8605Smrg   return GL_TRUE;
332848b8605Smrg}
333848b8605Smrg
334848b8605Smrg/*
335848b8605Smrg * We don't want to enable this GLX_OML_swap_method in glxext.h,
336848b8605Smrg * because we can't support it.  The X server writes it out though,
337848b8605Smrg * so we should handle it somehow, to avoid false warnings.
338848b8605Smrg */
339848b8605Smrgenum {
340848b8605Smrg    IGNORE_GLX_SWAP_METHOD_OML = 0x8060
341848b8605Smrg};
342848b8605Smrg
343848b8605Smrg
344848b8605Smrgstatic GLint
345848b8605Smrgconvert_from_x_visual_type(int visualType)
346848b8605Smrg{
347848b8605Smrg   static const int glx_visual_types[] = {
348b8e80941Smrg      [StaticGray]  = GLX_STATIC_GRAY,
349b8e80941Smrg      [GrayScale]   = GLX_GRAY_SCALE,
350b8e80941Smrg      [StaticColor] = GLX_STATIC_COLOR,
351b8e80941Smrg      [PseudoColor] = GLX_PSEUDO_COLOR,
352b8e80941Smrg      [TrueColor]   = GLX_TRUE_COLOR,
353b8e80941Smrg      [DirectColor] = GLX_DIRECT_COLOR,
354848b8605Smrg   };
355848b8605Smrg
356848b8605Smrg   if (visualType < ARRAY_SIZE(glx_visual_types))
357848b8605Smrg      return glx_visual_types[visualType];
358848b8605Smrg
359848b8605Smrg   return GLX_NONE;
360848b8605Smrg}
361848b8605Smrg
362848b8605Smrg/*
363848b8605Smrg * getVisualConfigs uses the !tagged_only path.
364848b8605Smrg * getFBConfigs uses the tagged_only path.
365848b8605Smrg */
366848b8605Smrg_X_HIDDEN void
367848b8605Smrg__glXInitializeVisualConfigFromTags(struct glx_config * config, int count,
368848b8605Smrg                                    const INT32 * bp, Bool tagged_only,
369848b8605Smrg                                    Bool fbconfig_style_tags)
370848b8605Smrg{
371848b8605Smrg   int i;
372848b8605Smrg   GLint renderType = 0;
373848b8605Smrg
374848b8605Smrg   if (!tagged_only) {
375848b8605Smrg      /* Copy in the first set of properties */
376848b8605Smrg      config->visualID = *bp++;
377848b8605Smrg
378848b8605Smrg      config->visualType = convert_from_x_visual_type(*bp++);
379848b8605Smrg
380848b8605Smrg      config->rgbMode = *bp++;
381848b8605Smrg
382848b8605Smrg      config->redBits = *bp++;
383848b8605Smrg      config->greenBits = *bp++;
384848b8605Smrg      config->blueBits = *bp++;
385848b8605Smrg      config->alphaBits = *bp++;
386848b8605Smrg      config->accumRedBits = *bp++;
387848b8605Smrg      config->accumGreenBits = *bp++;
388848b8605Smrg      config->accumBlueBits = *bp++;
389848b8605Smrg      config->accumAlphaBits = *bp++;
390848b8605Smrg
391848b8605Smrg      config->doubleBufferMode = *bp++;
392848b8605Smrg      config->stereoMode = *bp++;
393848b8605Smrg
394848b8605Smrg      config->rgbBits = *bp++;
395848b8605Smrg      config->depthBits = *bp++;
396848b8605Smrg      config->stencilBits = *bp++;
397848b8605Smrg      config->numAuxBuffers = *bp++;
398848b8605Smrg      config->level = *bp++;
399848b8605Smrg
400848b8605Smrg#ifdef GLX_USE_APPLEGL
401848b8605Smrg       /* AppleSGLX supports pixmap and pbuffers with all config. */
402848b8605Smrg       config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
403848b8605Smrg       /* Unfortunately this can create an ABI compatibility problem. */
404848b8605Smrg       count -= 18;
405848b8605Smrg#else
406848b8605Smrg      count -= __GLX_MIN_CONFIG_PROPS;
407848b8605Smrg#endif
408848b8605Smrg   }
409848b8605Smrg
410848b8605Smrg   /*
411848b8605Smrg    ** Additional properties may be in a list at the end
412848b8605Smrg    ** of the reply.  They are in pairs of property type
413848b8605Smrg    ** and property value.
414848b8605Smrg    */
415848b8605Smrg
416848b8605Smrg#define FETCH_OR_SET(tag) \
417848b8605Smrg    config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
418848b8605Smrg
419848b8605Smrg   for (i = 0; i < count; i += 2) {
420848b8605Smrg      long int tag = *bp++;
421848b8605Smrg
422848b8605Smrg      switch (tag) {
423848b8605Smrg      case GLX_RGBA:
424848b8605Smrg         FETCH_OR_SET(rgbMode);
425848b8605Smrg         break;
426848b8605Smrg      case GLX_BUFFER_SIZE:
427848b8605Smrg         config->rgbBits = *bp++;
428848b8605Smrg         break;
429848b8605Smrg      case GLX_LEVEL:
430848b8605Smrg         config->level = *bp++;
431848b8605Smrg         break;
432848b8605Smrg      case GLX_DOUBLEBUFFER:
433848b8605Smrg         FETCH_OR_SET(doubleBufferMode);
434848b8605Smrg         break;
435848b8605Smrg      case GLX_STEREO:
436848b8605Smrg         FETCH_OR_SET(stereoMode);
437848b8605Smrg         break;
438848b8605Smrg      case GLX_AUX_BUFFERS:
439848b8605Smrg         config->numAuxBuffers = *bp++;
440848b8605Smrg         break;
441848b8605Smrg      case GLX_RED_SIZE:
442848b8605Smrg         config->redBits = *bp++;
443848b8605Smrg         break;
444848b8605Smrg      case GLX_GREEN_SIZE:
445848b8605Smrg         config->greenBits = *bp++;
446848b8605Smrg         break;
447848b8605Smrg      case GLX_BLUE_SIZE:
448848b8605Smrg         config->blueBits = *bp++;
449848b8605Smrg         break;
450848b8605Smrg      case GLX_ALPHA_SIZE:
451848b8605Smrg         config->alphaBits = *bp++;
452848b8605Smrg         break;
453848b8605Smrg      case GLX_DEPTH_SIZE:
454848b8605Smrg         config->depthBits = *bp++;
455848b8605Smrg         break;
456848b8605Smrg      case GLX_STENCIL_SIZE:
457848b8605Smrg         config->stencilBits = *bp++;
458848b8605Smrg         break;
459848b8605Smrg      case GLX_ACCUM_RED_SIZE:
460848b8605Smrg         config->accumRedBits = *bp++;
461848b8605Smrg         break;
462848b8605Smrg      case GLX_ACCUM_GREEN_SIZE:
463848b8605Smrg         config->accumGreenBits = *bp++;
464848b8605Smrg         break;
465848b8605Smrg      case GLX_ACCUM_BLUE_SIZE:
466848b8605Smrg         config->accumBlueBits = *bp++;
467848b8605Smrg         break;
468848b8605Smrg      case GLX_ACCUM_ALPHA_SIZE:
469848b8605Smrg         config->accumAlphaBits = *bp++;
470848b8605Smrg         break;
471848b8605Smrg      case GLX_VISUAL_CAVEAT_EXT:
472848b8605Smrg         config->visualRating = *bp++;
473848b8605Smrg         break;
474848b8605Smrg      case GLX_X_VISUAL_TYPE:
475848b8605Smrg         config->visualType = *bp++;
476848b8605Smrg         break;
477848b8605Smrg      case GLX_TRANSPARENT_TYPE:
478848b8605Smrg         config->transparentPixel = *bp++;
479848b8605Smrg         break;
480848b8605Smrg      case GLX_TRANSPARENT_INDEX_VALUE:
481848b8605Smrg         config->transparentIndex = *bp++;
482848b8605Smrg         break;
483848b8605Smrg      case GLX_TRANSPARENT_RED_VALUE:
484848b8605Smrg         config->transparentRed = *bp++;
485848b8605Smrg         break;
486848b8605Smrg      case GLX_TRANSPARENT_GREEN_VALUE:
487848b8605Smrg         config->transparentGreen = *bp++;
488848b8605Smrg         break;
489848b8605Smrg      case GLX_TRANSPARENT_BLUE_VALUE:
490848b8605Smrg         config->transparentBlue = *bp++;
491848b8605Smrg         break;
492848b8605Smrg      case GLX_TRANSPARENT_ALPHA_VALUE:
493848b8605Smrg         config->transparentAlpha = *bp++;
494848b8605Smrg         break;
495848b8605Smrg      case GLX_VISUAL_ID:
496848b8605Smrg         config->visualID = *bp++;
497848b8605Smrg         break;
498848b8605Smrg      case GLX_DRAWABLE_TYPE:
499848b8605Smrg         config->drawableType = *bp++;
500848b8605Smrg#ifdef GLX_USE_APPLEGL
501848b8605Smrg         /* AppleSGLX supports pixmap and pbuffers with all config. */
502848b8605Smrg         config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
503848b8605Smrg#endif
504848b8605Smrg         break;
505848b8605Smrg      case GLX_RENDER_TYPE: /* fbconfig render type bits */
506848b8605Smrg         renderType = *bp++;
507848b8605Smrg         break;
508848b8605Smrg      case GLX_X_RENDERABLE:
509848b8605Smrg         config->xRenderable = *bp++;
510848b8605Smrg         break;
511848b8605Smrg      case GLX_FBCONFIG_ID:
512848b8605Smrg         config->fbconfigID = *bp++;
513848b8605Smrg         break;
514848b8605Smrg      case GLX_MAX_PBUFFER_WIDTH:
515848b8605Smrg         config->maxPbufferWidth = *bp++;
516848b8605Smrg         break;
517848b8605Smrg      case GLX_MAX_PBUFFER_HEIGHT:
518848b8605Smrg         config->maxPbufferHeight = *bp++;
519848b8605Smrg         break;
520848b8605Smrg      case GLX_MAX_PBUFFER_PIXELS:
521848b8605Smrg         config->maxPbufferPixels = *bp++;
522848b8605Smrg         break;
523848b8605Smrg#ifndef GLX_USE_APPLEGL
524848b8605Smrg      case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
525848b8605Smrg         config->optimalPbufferWidth = *bp++;
526848b8605Smrg         break;
527848b8605Smrg      case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
528848b8605Smrg         config->optimalPbufferHeight = *bp++;
529848b8605Smrg         break;
530848b8605Smrg      case GLX_VISUAL_SELECT_GROUP_SGIX:
531848b8605Smrg         config->visualSelectGroup = *bp++;
532848b8605Smrg         break;
533848b8605Smrg      case GLX_SWAP_METHOD_OML:
534b8e80941Smrg         if (*bp == GLX_SWAP_UNDEFINED_OML ||
535b8e80941Smrg             *bp == GLX_SWAP_COPY_OML ||
536b8e80941Smrg             *bp == GLX_SWAP_EXCHANGE_OML) {
537b8e80941Smrg            config->swapMethod = *bp++;
538b8e80941Smrg         } else {
539b8e80941Smrg            /* X servers with old HW drivers may return any value here, so
540b8e80941Smrg             * assume GLX_SWAP_METHOD_UNDEFINED.
541b8e80941Smrg             */
542b8e80941Smrg            config->swapMethod = GLX_SWAP_UNDEFINED_OML;
543b8e80941Smrg            bp++;
544b8e80941Smrg         }
545848b8605Smrg         break;
546848b8605Smrg#endif
547848b8605Smrg      case GLX_SAMPLE_BUFFERS_SGIS:
548848b8605Smrg         config->sampleBuffers = *bp++;
549848b8605Smrg         break;
550848b8605Smrg      case GLX_SAMPLES_SGIS:
551848b8605Smrg         config->samples = *bp++;
552848b8605Smrg         break;
553848b8605Smrg#ifdef GLX_USE_APPLEGL
554848b8605Smrg      case IGNORE_GLX_SWAP_METHOD_OML:
555848b8605Smrg         /* We ignore this tag.  See the comment above this function. */
556848b8605Smrg         ++bp;
557848b8605Smrg         break;
558848b8605Smrg#else
559848b8605Smrg      case GLX_BIND_TO_TEXTURE_RGB_EXT:
560848b8605Smrg         config->bindToTextureRgb = *bp++;
561848b8605Smrg         break;
562848b8605Smrg      case GLX_BIND_TO_TEXTURE_RGBA_EXT:
563848b8605Smrg         config->bindToTextureRgba = *bp++;
564848b8605Smrg         break;
565848b8605Smrg      case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
566848b8605Smrg         config->bindToMipmapTexture = *bp++;
567848b8605Smrg         break;
568848b8605Smrg      case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
569848b8605Smrg         config->bindToTextureTargets = *bp++;
570848b8605Smrg         break;
571848b8605Smrg      case GLX_Y_INVERTED_EXT:
572848b8605Smrg         config->yInverted = *bp++;
573848b8605Smrg         break;
574848b8605Smrg#endif
575848b8605Smrg      case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
576848b8605Smrg         config->sRGBCapable = *bp++;
577848b8605Smrg         break;
578848b8605Smrg
579848b8605Smrg      case GLX_USE_GL:
580848b8605Smrg         if (fbconfig_style_tags)
581848b8605Smrg            bp++;
582848b8605Smrg         break;
583848b8605Smrg      case None:
584848b8605Smrg         i = count;
585848b8605Smrg         break;
586848b8605Smrg      default:
587b8e80941Smrg         if(env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) {
588848b8605Smrg             long int tagvalue = *bp++;
589848b8605Smrg             fprintf(stderr, "WARNING: unknown GLX tag from server: "
590848b8605Smrg                     "tag 0x%lx value 0x%lx\n", tag, tagvalue);
591848b8605Smrg         } else {
592848b8605Smrg             /* Ignore the unrecognized tag's value */
593848b8605Smrg             bp++;
594848b8605Smrg         }
595848b8605Smrg         break;
596848b8605Smrg      }
597848b8605Smrg   }
598848b8605Smrg
599848b8605Smrg   if (renderType != 0 && renderType != GLX_DONT_CARE) {
600848b8605Smrg      config->renderType = renderType;
601848b8605Smrg      config->floatMode = (renderType &
602848b8605Smrg         (GLX_RGBA_FLOAT_BIT_ARB|GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT)) != 0;
603848b8605Smrg   } else {
604848b8605Smrg      /* If there wasn't GLX_RENDER_TYPE property, set it based on
605848b8605Smrg       * config->rgbMode.  The only way to communicate that the config is
606848b8605Smrg       * floating-point is via GLX_RENDER_TYPE, so this cannot be a float
607848b8605Smrg       * config.
608848b8605Smrg       */
609848b8605Smrg      config->renderType =
610848b8605Smrg         (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
611848b8605Smrg   }
612848b8605Smrg
613848b8605Smrg   /* The GLX_ARB_fbconfig_float spec says:
614848b8605Smrg    *
615848b8605Smrg    *     "Note that floating point rendering is only supported for
616848b8605Smrg    *     GLXPbuffer drawables."
617848b8605Smrg    */
618848b8605Smrg   if (config->floatMode)
619b8e80941Smrg      config->drawableType &= GLX_PBUFFER_BIT;
620848b8605Smrg}
621848b8605Smrg
622848b8605Smrgstatic struct glx_config *
623848b8605SmrgcreateConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
624848b8605Smrg                            int screen, GLboolean tagged_only)
625848b8605Smrg{
626848b8605Smrg   INT32 buf[__GLX_TOTAL_CONFIG], *props;
627848b8605Smrg   unsigned prop_size;
628848b8605Smrg   struct glx_config *modes, *m;
629848b8605Smrg   int i;
630848b8605Smrg
631848b8605Smrg   if (nprops == 0)
632848b8605Smrg      return NULL;
633848b8605Smrg
634848b8605Smrg   /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
635848b8605Smrg
636848b8605Smrg   /* Check number of properties */
637848b8605Smrg   if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
638848b8605Smrg      return NULL;
639848b8605Smrg
640848b8605Smrg   /* Allocate memory for our config structure */
641848b8605Smrg   modes = glx_config_create_list(nvisuals);
642848b8605Smrg   if (!modes)
643848b8605Smrg      return NULL;
644848b8605Smrg
645848b8605Smrg   prop_size = nprops * __GLX_SIZE_INT32;
646848b8605Smrg   if (prop_size <= sizeof(buf))
647848b8605Smrg      props = buf;
648848b8605Smrg   else
649848b8605Smrg      props = malloc(prop_size);
650848b8605Smrg
651848b8605Smrg   /* Read each config structure and convert it into our format */
652848b8605Smrg   m = modes;
653848b8605Smrg   for (i = 0; i < nvisuals; i++) {
654848b8605Smrg      _XRead(dpy, (char *) props, prop_size);
655848b8605Smrg#ifdef GLX_USE_APPLEGL
656848b8605Smrg       /* Older X servers don't send this so we default it here. */
657848b8605Smrg      m->drawableType = GLX_WINDOW_BIT;
658848b8605Smrg#else
659848b8605Smrg      /*
660848b8605Smrg       * The XQuartz 2.3.2.1 X server doesn't set this properly, so
661848b8605Smrg       * set the proper bits here.
662848b8605Smrg       * AppleSGLX supports windows, pixmaps, and pbuffers with all config.
663848b8605Smrg       */
664848b8605Smrg      m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
665848b8605Smrg#endif
666b8e80941Smrg      /* Older X servers don't send this so we default it here. */
667b8e80941Smrg      m->sRGBCapable = GL_FALSE;
668848b8605Smrg       __glXInitializeVisualConfigFromTags(m, nprops, props,
669848b8605Smrg                                          tagged_only, GL_TRUE);
670848b8605Smrg      m->screen = screen;
671848b8605Smrg      m = m->next;
672848b8605Smrg   }
673848b8605Smrg
674848b8605Smrg   if (props != buf)
675848b8605Smrg      free(props);
676848b8605Smrg
677848b8605Smrg   return modes;
678848b8605Smrg}
679848b8605Smrg
680848b8605Smrgstatic GLboolean
681848b8605SmrggetVisualConfigs(struct glx_screen *psc,
682848b8605Smrg		  struct glx_display *priv, int screen)
683848b8605Smrg{
684848b8605Smrg   xGLXGetVisualConfigsReq *req;
685848b8605Smrg   xGLXGetVisualConfigsReply reply;
686848b8605Smrg   Display *dpy = priv->dpy;
687848b8605Smrg
688848b8605Smrg   LockDisplay(dpy);
689848b8605Smrg
690848b8605Smrg   psc->visuals = NULL;
691848b8605Smrg   GetReq(GLXGetVisualConfigs, req);
692848b8605Smrg   req->reqType = priv->majorOpcode;
693848b8605Smrg   req->glxCode = X_GLXGetVisualConfigs;
694848b8605Smrg   req->screen = screen;
695848b8605Smrg
696848b8605Smrg   if (!_XReply(dpy, (xReply *) & reply, 0, False))
697848b8605Smrg      goto out;
698848b8605Smrg
699848b8605Smrg   psc->visuals = createConfigsFromProperties(dpy,
700848b8605Smrg                                              reply.numVisuals,
701848b8605Smrg                                              reply.numProps,
702848b8605Smrg                                              screen, GL_FALSE);
703848b8605Smrg
704848b8605Smrg out:
705848b8605Smrg   UnlockDisplay(dpy);
706848b8605Smrg   return psc->visuals != NULL;
707848b8605Smrg}
708848b8605Smrg
709848b8605Smrgstatic GLboolean
710848b8605Smrg getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen)
711848b8605Smrg{
712848b8605Smrg   xGLXGetFBConfigsReq *fb_req;
713848b8605Smrg   xGLXGetFBConfigsSGIXReq *sgi_req;
714848b8605Smrg   xGLXVendorPrivateWithReplyReq *vpreq;
715848b8605Smrg   xGLXGetFBConfigsReply reply;
716848b8605Smrg   Display *dpy = priv->dpy;
717848b8605Smrg
718848b8605Smrg   psc->serverGLXexts =
719848b8605Smrg      __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
720848b8605Smrg
721848b8605Smrg   if (psc->serverGLXexts == NULL) {
722848b8605Smrg      return GL_FALSE;
723848b8605Smrg   }
724848b8605Smrg
725848b8605Smrg   LockDisplay(dpy);
726848b8605Smrg
727848b8605Smrg   psc->configs = NULL;
728848b8605Smrg   if (atof(priv->serverGLXversion) >= 1.3) {
729848b8605Smrg      GetReq(GLXGetFBConfigs, fb_req);
730848b8605Smrg      fb_req->reqType = priv->majorOpcode;
731848b8605Smrg      fb_req->glxCode = X_GLXGetFBConfigs;
732848b8605Smrg      fb_req->screen = screen;
733848b8605Smrg   }
734848b8605Smrg   else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
735848b8605Smrg      GetReqExtra(GLXVendorPrivateWithReply,
736848b8605Smrg                  sz_xGLXGetFBConfigsSGIXReq -
737848b8605Smrg                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
738848b8605Smrg      sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
739848b8605Smrg      sgi_req->reqType = priv->majorOpcode;
740848b8605Smrg      sgi_req->glxCode = X_GLXVendorPrivateWithReply;
741848b8605Smrg      sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
742848b8605Smrg      sgi_req->screen = screen;
743848b8605Smrg   }
744848b8605Smrg   else
745848b8605Smrg      goto out;
746848b8605Smrg
747848b8605Smrg   if (!_XReply(dpy, (xReply *) & reply, 0, False))
748848b8605Smrg      goto out;
749848b8605Smrg
750848b8605Smrg   psc->configs = createConfigsFromProperties(dpy,
751848b8605Smrg                                              reply.numFBConfigs,
752848b8605Smrg                                              reply.numAttribs * 2,
753848b8605Smrg                                              screen, GL_TRUE);
754848b8605Smrg
755848b8605Smrg out:
756848b8605Smrg   UnlockDisplay(dpy);
757848b8605Smrg   return psc->configs != NULL;
758848b8605Smrg}
759848b8605Smrg
760848b8605Smrg_X_HIDDEN Bool
761848b8605Smrgglx_screen_init(struct glx_screen *psc,
762848b8605Smrg		 int screen, struct glx_display * priv)
763848b8605Smrg{
764848b8605Smrg   /* Initialize per screen dynamic client GLX extensions */
765848b8605Smrg   psc->ext_list_first_time = GL_TRUE;
766848b8605Smrg   psc->scr = screen;
767848b8605Smrg   psc->dpy = priv->dpy;
768848b8605Smrg   psc->display = priv;
769848b8605Smrg
770b8e80941Smrg   if (!getVisualConfigs(psc, priv, screen))
771b8e80941Smrg      return GL_FALSE;
772b8e80941Smrg
773b8e80941Smrg   if (!getFBConfigs(psc, priv, screen))
774b8e80941Smrg      return GL_FALSE;
775848b8605Smrg
776848b8605Smrg   return GL_TRUE;
777848b8605Smrg}
778848b8605Smrg
779848b8605Smrg_X_HIDDEN void
780848b8605Smrgglx_screen_cleanup(struct glx_screen *psc)
781848b8605Smrg{
782848b8605Smrg   if (psc->configs) {
783848b8605Smrg      glx_config_destroy_list(psc->configs);
784848b8605Smrg      free(psc->effectiveGLXexts);
785848b8605Smrg      psc->configs = NULL;   /* NOTE: just for paranoia */
786848b8605Smrg   }
787848b8605Smrg   if (psc->visuals) {
788848b8605Smrg      glx_config_destroy_list(psc->visuals);
789848b8605Smrg      psc->visuals = NULL;   /* NOTE: just for paranoia */
790848b8605Smrg   }
791848b8605Smrg   free((char *) psc->serverGLXexts);
792848b8605Smrg}
793848b8605Smrg
794848b8605Smrg/*
795848b8605Smrg** Allocate the memory for the per screen configs for each screen.
796848b8605Smrg** If that works then fetch the per screen configs data.
797848b8605Smrg*/
798848b8605Smrgstatic Bool
799848b8605SmrgAllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
800848b8605Smrg{
801848b8605Smrg   struct glx_screen *psc;
802848b8605Smrg   GLint i, screens;
803848b8605Smrg
804848b8605Smrg   /*
805848b8605Smrg    ** First allocate memory for the array of per screen configs.
806848b8605Smrg    */
807848b8605Smrg   screens = ScreenCount(dpy);
808b8e80941Smrg   priv->screens = calloc(screens, sizeof *priv->screens);
809848b8605Smrg   if (!priv->screens)
810848b8605Smrg      return GL_FALSE;
811848b8605Smrg
812848b8605Smrg   priv->serverGLXversion =
813848b8605Smrg      __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
814848b8605Smrg   if (priv->serverGLXversion == NULL) {
815848b8605Smrg      FreeScreenConfigs(priv);
816848b8605Smrg      return GL_FALSE;
817848b8605Smrg   }
818848b8605Smrg
819848b8605Smrg   for (i = 0; i < screens; i++, psc++) {
820848b8605Smrg      psc = NULL;
821848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
822848b8605Smrg#if defined(GLX_USE_DRM)
823848b8605Smrg#if defined(HAVE_DRI3)
824848b8605Smrg      if (priv->dri3Display)
825848b8605Smrg         psc = (*priv->dri3Display->createScreen) (i, priv);
826848b8605Smrg#endif /* HAVE_DRI3 */
827848b8605Smrg      if (psc == NULL && priv->dri2Display)
828848b8605Smrg	 psc = (*priv->dri2Display->createScreen) (i, priv);
829848b8605Smrg      if (psc == NULL && priv->driDisplay)
830848b8605Smrg	 psc = (*priv->driDisplay->createScreen) (i, priv);
831848b8605Smrg#endif /* GLX_USE_DRM */
832b8e80941Smrg
833b8e80941Smrg#ifdef GLX_USE_WINDOWSGL
834b8e80941Smrg      if (psc == NULL && priv->windowsdriDisplay)
835b8e80941Smrg	 psc = (*priv->windowsdriDisplay->createScreen) (i, priv);
836b8e80941Smrg#endif
837b8e80941Smrg
838848b8605Smrg      if (psc == NULL && priv->driswDisplay)
839848b8605Smrg	 psc = (*priv->driswDisplay->createScreen) (i, priv);
840848b8605Smrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
841848b8605Smrg
842848b8605Smrg#if defined(GLX_USE_APPLEGL)
843848b8605Smrg      if (psc == NULL)
844848b8605Smrg         psc = applegl_create_screen(i, priv);
845848b8605Smrg#else
846848b8605Smrg      if (psc == NULL)
847848b8605Smrg	 psc = indirect_create_screen(i, priv);
848848b8605Smrg#endif
849848b8605Smrg      priv->screens[i] = psc;
850848b8605Smrg   }
851848b8605Smrg   SyncHandle();
852848b8605Smrg   return GL_TRUE;
853848b8605Smrg}
854848b8605Smrg
855848b8605Smrg/*
856848b8605Smrg** Initialize the client side extension code.
857848b8605Smrg*/
858848b8605Smrg _X_HIDDEN struct glx_display *
859848b8605Smrg__glXInitialize(Display * dpy)
860848b8605Smrg{
861848b8605Smrg   struct glx_display *dpyPriv, *d;
862848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
863848b8605Smrg   Bool glx_direct, glx_accel;
864848b8605Smrg#endif
865848b8605Smrg   int i;
866848b8605Smrg
867848b8605Smrg   _XLockMutex(_Xglobal_lock);
868848b8605Smrg
869848b8605Smrg   for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) {
870848b8605Smrg      if (dpyPriv->dpy == dpy) {
871848b8605Smrg	 _XUnlockMutex(_Xglobal_lock);
872848b8605Smrg	 return dpyPriv;
873848b8605Smrg      }
874848b8605Smrg   }
875848b8605Smrg
876848b8605Smrg   /* Drop the lock while we create the display private. */
877848b8605Smrg   _XUnlockMutex(_Xglobal_lock);
878848b8605Smrg
879848b8605Smrg   dpyPriv = calloc(1, sizeof *dpyPriv);
880848b8605Smrg   if (!dpyPriv)
881848b8605Smrg      return NULL;
882848b8605Smrg
883848b8605Smrg   dpyPriv->codes = XInitExtension(dpy, __glXExtensionName);
884848b8605Smrg   if (!dpyPriv->codes) {
885848b8605Smrg      free(dpyPriv);
886848b8605Smrg      return NULL;
887848b8605Smrg   }
888848b8605Smrg
889848b8605Smrg   dpyPriv->dpy = dpy;
890848b8605Smrg   dpyPriv->majorOpcode = dpyPriv->codes->major_opcode;
891848b8605Smrg   dpyPriv->serverGLXvendor = 0x0;
892848b8605Smrg   dpyPriv->serverGLXversion = 0x0;
893848b8605Smrg
894848b8605Smrg   /* See if the versions are compatible.  This GLX implementation does not
895848b8605Smrg    * work with servers that only support GLX 1.0.
896848b8605Smrg    */
897848b8605Smrg   if (!QueryVersion(dpy, dpyPriv->majorOpcode,
898848b8605Smrg		     &dpyPriv->majorVersion, &dpyPriv->minorVersion)
899848b8605Smrg       || (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion < 1)) {
900848b8605Smrg      free(dpyPriv);
901848b8605Smrg      return NULL;
902848b8605Smrg   }
903848b8605Smrg
904848b8605Smrg   for (i = 0; i < __GLX_NUMBER_EVENTS; i++) {
905848b8605Smrg      XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent);
906848b8605Smrg      XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire);
907848b8605Smrg   }
908848b8605Smrg
909848b8605Smrg   XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay);
910848b8605Smrg   XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString);
911848b8605Smrg
912848b8605Smrg   dpyPriv->glXDrawHash = __glxHashCreate();
913848b8605Smrg
914848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
915b8e80941Smrg   glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false);
916b8e80941Smrg   glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
917848b8605Smrg
918848b8605Smrg   dpyPriv->drawHash = __glxHashCreate();
919848b8605Smrg
920848b8605Smrg   /*
921848b8605Smrg    ** Initialize the direct rendering per display data and functions.
922848b8605Smrg    ** Note: This _must_ be done before calling any other DRI routines
923848b8605Smrg    ** (e.g., those called in AllocAndFetchScreenConfigs).
924848b8605Smrg    */
925848b8605Smrg#if defined(GLX_USE_DRM)
926848b8605Smrg   if (glx_direct && glx_accel) {
927848b8605Smrg#if defined(HAVE_DRI3)
928b8e80941Smrg      if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false))
929848b8605Smrg         dpyPriv->dri3Display = dri3_create_display(dpy);
930848b8605Smrg#endif /* HAVE_DRI3 */
931848b8605Smrg      dpyPriv->dri2Display = dri2CreateDisplay(dpy);
932848b8605Smrg      dpyPriv->driDisplay = driCreateDisplay(dpy);
933848b8605Smrg   }
934848b8605Smrg#endif /* GLX_USE_DRM */
935848b8605Smrg   if (glx_direct)
936848b8605Smrg      dpyPriv->driswDisplay = driswCreateDisplay(dpy);
937848b8605Smrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
938848b8605Smrg
939848b8605Smrg#ifdef GLX_USE_APPLEGL
940848b8605Smrg   if (!applegl_create_display(dpyPriv)) {
941848b8605Smrg      free(dpyPriv);
942848b8605Smrg      return NULL;
943848b8605Smrg   }
944848b8605Smrg#endif
945b8e80941Smrg
946b8e80941Smrg#ifdef GLX_USE_WINDOWSGL
947b8e80941Smrg   if (glx_direct && glx_accel)
948b8e80941Smrg      dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy);
949b8e80941Smrg#endif
950b8e80941Smrg
951848b8605Smrg   if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
952848b8605Smrg      free(dpyPriv);
953848b8605Smrg      return NULL;
954848b8605Smrg   }
955848b8605Smrg
956848b8605Smrg   __glX_send_client_info(dpyPriv);
957848b8605Smrg
958848b8605Smrg   /* Grab the lock again and add the dispay private, unless somebody
959848b8605Smrg    * beat us to initializing on this display in the meantime. */
960848b8605Smrg   _XLockMutex(_Xglobal_lock);
961848b8605Smrg
962848b8605Smrg   for (d = glx_displays; d; d = d->next) {
963848b8605Smrg      if (d->dpy == dpy) {
964848b8605Smrg	 _XUnlockMutex(_Xglobal_lock);
965848b8605Smrg	 glx_display_free(dpyPriv);
966848b8605Smrg	 return d;
967848b8605Smrg      }
968848b8605Smrg   }
969848b8605Smrg
970848b8605Smrg   dpyPriv->next = glx_displays;
971848b8605Smrg   glx_displays = dpyPriv;
972848b8605Smrg
973848b8605Smrg   _XUnlockMutex(_Xglobal_lock);
974848b8605Smrg
975848b8605Smrg   return dpyPriv;
976848b8605Smrg}
977848b8605Smrg
978848b8605Smrg/*
979848b8605Smrg** Setup for sending a GLX command on dpy.  Make sure the extension is
980848b8605Smrg** initialized.  Try to avoid calling __glXInitialize as its kinda slow.
981848b8605Smrg*/
982848b8605Smrg_X_HIDDEN CARD8
983848b8605Smrg__glXSetupForCommand(Display * dpy)
984848b8605Smrg{
985848b8605Smrg    struct glx_context *gc;
986848b8605Smrg    struct glx_display *priv;
987848b8605Smrg
988848b8605Smrg   /* If this thread has a current context, flush its rendering commands */
989848b8605Smrg   gc = __glXGetCurrentContext();
990848b8605Smrg   if (gc->currentDpy) {
991848b8605Smrg      /* Flush rendering buffer of the current context, if any */
992848b8605Smrg      (void) __glXFlushRenderBuffer(gc, gc->pc);
993848b8605Smrg
994848b8605Smrg      if (gc->currentDpy == dpy) {
995848b8605Smrg         /* Use opcode from gc because its right */
996848b8605Smrg         return gc->majorOpcode;
997848b8605Smrg      }
998848b8605Smrg      else {
999848b8605Smrg         /*
1000848b8605Smrg          ** Have to get info about argument dpy because it might be to
1001848b8605Smrg          ** a different server
1002848b8605Smrg          */
1003848b8605Smrg      }
1004848b8605Smrg   }
1005848b8605Smrg
1006848b8605Smrg   /* Forced to lookup extension via the slow initialize route */
1007848b8605Smrg   priv = __glXInitialize(dpy);
1008848b8605Smrg   if (!priv) {
1009848b8605Smrg      return 0;
1010848b8605Smrg   }
1011848b8605Smrg   return priv->majorOpcode;
1012848b8605Smrg}
1013848b8605Smrg
1014848b8605Smrg/**
1015848b8605Smrg * Flush the drawing command transport buffer.
1016848b8605Smrg *
1017848b8605Smrg * \param ctx  Context whose transport buffer is to be flushed.
1018848b8605Smrg * \param pc   Pointer to first unused buffer location.
1019848b8605Smrg *
1020848b8605Smrg * \todo
1021848b8605Smrg * Modify this function to use \c ctx->pc instead of the explicit
1022848b8605Smrg * \c pc parameter.
1023848b8605Smrg */
1024848b8605Smrg_X_HIDDEN GLubyte *
1025848b8605Smrg__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc)
1026848b8605Smrg{
1027848b8605Smrg   Display *const dpy = ctx->currentDpy;
1028848b8605Smrg   xcb_connection_t *c = XGetXCBConnection(dpy);
1029848b8605Smrg   const GLint size = pc - ctx->buf;
1030848b8605Smrg
1031848b8605Smrg   if ((dpy != NULL) && (size > 0)) {
1032848b8605Smrg      xcb_glx_render(c, ctx->currentContextTag, size,
1033848b8605Smrg                     (const uint8_t *) ctx->buf);
1034848b8605Smrg   }
1035848b8605Smrg
1036848b8605Smrg   /* Reset pointer and return it */
1037848b8605Smrg   ctx->pc = ctx->buf;
1038848b8605Smrg   return ctx->pc;
1039848b8605Smrg}
1040848b8605Smrg
1041848b8605Smrg
1042848b8605Smrg/**
1043848b8605Smrg * Send a portion of a GLXRenderLarge command to the server.  The advantage of
1044848b8605Smrg * this function over \c __glXSendLargeCommand is that callers can use the
1045848b8605Smrg * data buffer in the GLX context and may be able to avoid allocating an
1046848b8605Smrg * extra buffer.  The disadvantage is the clients will have to do more
1047848b8605Smrg * GLX protocol work (i.e., calculating \c totalRequests, etc.).
1048848b8605Smrg *
1049848b8605Smrg * \sa __glXSendLargeCommand
1050848b8605Smrg *
1051848b8605Smrg * \param gc             GLX context
1052848b8605Smrg * \param requestNumber  Which part of the whole command is this?  The first
1053848b8605Smrg *                       request is 1.
1054848b8605Smrg * \param totalRequests  How many requests will there be?
1055848b8605Smrg * \param data           Command data.
1056848b8605Smrg * \param dataLen        Size, in bytes, of the command data.
1057848b8605Smrg */
1058848b8605Smrg_X_HIDDEN void
1059848b8605Smrg__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber,
1060848b8605Smrg                    GLint totalRequests, const GLvoid * data, GLint dataLen)
1061848b8605Smrg{
1062848b8605Smrg   Display *dpy = gc->currentDpy;
1063848b8605Smrg   xcb_connection_t *c = XGetXCBConnection(dpy);
1064848b8605Smrg   xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
1065848b8605Smrg                        totalRequests, dataLen, data);
1066848b8605Smrg}
1067848b8605Smrg
1068848b8605Smrg
1069848b8605Smrg/**
1070848b8605Smrg * Send a command that is too large for the GLXRender protocol request.
1071848b8605Smrg *
1072848b8605Smrg * Send a large command, one that is too large for some reason to
1073848b8605Smrg * send using the GLXRender protocol request.  One reason to send
1074848b8605Smrg * a large command is to avoid copying the data.
1075848b8605Smrg *
1076848b8605Smrg * \param ctx        GLX context
1077848b8605Smrg * \param header     Header data.
1078848b8605Smrg * \param headerLen  Size, in bytes, of the header data.  It is assumed that
1079848b8605Smrg *                   the header data will always be small enough to fit in
1080848b8605Smrg *                   a single X protocol packet.
1081848b8605Smrg * \param data       Command data.
1082848b8605Smrg * \param dataLen    Size, in bytes, of the command data.
1083848b8605Smrg */
1084848b8605Smrg_X_HIDDEN void
1085848b8605Smrg__glXSendLargeCommand(struct glx_context * ctx,
1086848b8605Smrg                      const GLvoid * header, GLint headerLen,
1087848b8605Smrg                      const GLvoid * data, GLint dataLen)
1088848b8605Smrg{
1089848b8605Smrg   GLint maxSize;
1090848b8605Smrg   GLint totalRequests, requestNumber;
1091848b8605Smrg
1092848b8605Smrg   /*
1093848b8605Smrg    ** Calculate the maximum amount of data can be stuffed into a single
1094848b8605Smrg    ** packet.  sz_xGLXRenderReq is added because bufSize is the maximum
1095848b8605Smrg    ** packet size minus sz_xGLXRenderReq.
1096848b8605Smrg    */
1097848b8605Smrg   maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
1098848b8605Smrg   totalRequests = 1 + (dataLen / maxSize);
1099848b8605Smrg   if (dataLen % maxSize)
1100848b8605Smrg      totalRequests++;
1101848b8605Smrg
1102848b8605Smrg   /*
1103848b8605Smrg    ** Send all of the command, except the large array, as one request.
1104848b8605Smrg    */
1105848b8605Smrg   assert(headerLen <= maxSize);
1106848b8605Smrg   __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
1107848b8605Smrg
1108848b8605Smrg   /*
1109848b8605Smrg    ** Send enough requests until the whole array is sent.
1110848b8605Smrg    */
1111848b8605Smrg   for (requestNumber = 2; requestNumber <= (totalRequests - 1);
1112848b8605Smrg        requestNumber++) {
1113848b8605Smrg      __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
1114848b8605Smrg      data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
1115848b8605Smrg      dataLen -= maxSize;
1116848b8605Smrg      assert(dataLen > 0);
1117848b8605Smrg   }
1118848b8605Smrg
1119848b8605Smrg   assert(dataLen <= maxSize);
1120848b8605Smrg   __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
1121848b8605Smrg}
1122848b8605Smrg
1123848b8605Smrg/************************************************************************/
1124848b8605Smrg
1125848b8605Smrg#ifdef DEBUG
1126848b8605Smrg_X_HIDDEN void
1127848b8605Smrg__glXDumpDrawBuffer(struct glx_context * ctx)
1128848b8605Smrg{
1129848b8605Smrg   GLubyte *p = ctx->buf;
1130848b8605Smrg   GLubyte *end = ctx->pc;
1131848b8605Smrg   GLushort opcode, length;
1132848b8605Smrg
1133848b8605Smrg   while (p < end) {
1134848b8605Smrg      /* Fetch opcode */
1135848b8605Smrg      opcode = *((GLushort *) p);
1136848b8605Smrg      length = *((GLushort *) (p + 2));
1137848b8605Smrg      printf("%2x: %5d: ", opcode, length);
1138848b8605Smrg      length -= 4;
1139848b8605Smrg      p += 4;
1140848b8605Smrg      while (length > 0) {
1141848b8605Smrg         printf("%08x ", *((unsigned *) p));
1142848b8605Smrg         p += 4;
1143848b8605Smrg         length -= 4;
1144848b8605Smrg      }
1145848b8605Smrg      printf("\n");
1146848b8605Smrg   }
1147848b8605Smrg}
1148848b8605Smrg#endif
1149