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