1/*
2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
29 */
30
31/**
32 * \file glxext.c
33 * GLX protocol interface boot-strap code.
34 *
35 * Direct rendering support added by Precision Insight, Inc.
36 *
37 * \author Kevin E. Martin <kevin@precisioninsight.com>
38 */
39
40#include <assert.h>
41#include <stdbool.h>
42
43#include "glxclient.h"
44#include <X11/extensions/Xext.h>
45#include <X11/extensions/extutil.h>
46#ifdef GLX_USE_APPLEGL
47#include "apple/apple_glx.h"
48#include "apple/apple_visual.h"
49#endif
50#include "glxextensions.h"
51
52#include "util/debug.h"
53
54#include <X11/Xlib-xcb.h>
55#include <xcb/xcb.h>
56#include <xcb/glx.h>
57
58
59#ifdef DEBUG
60void __glXDumpDrawBuffer(struct glx_context * ctx);
61#endif
62
63/*
64** You can set this cell to 1 to force the gl drawing stuff to be
65** one command per packet
66*/
67_X_HIDDEN int __glXDebug = 0;
68
69/* Extension required boiler plate */
70
71static const char __glXExtensionName[] = GLX_EXTENSION_NAME;
72  static struct glx_display *glx_displays;
73
74static /* const */ char *error_list[] = {
75   "GLXBadContext",
76   "GLXBadContextState",
77   "GLXBadDrawable",
78   "GLXBadPixmap",
79   "GLXBadContextTag",
80   "GLXBadCurrentWindow",
81   "GLXBadRenderRequest",
82   "GLXBadLargeRequest",
83   "GLXUnsupportedPrivateRequest",
84   "GLXBadFBConfig",
85   "GLXBadPbuffer",
86   "GLXBadCurrentDrawable",
87   "GLXBadWindow",
88   "GLXBadProfileARB",
89};
90
91#ifdef GLX_USE_APPLEGL
92static char *__glXErrorString(Display *dpy, int code, XExtCodes *codes,
93                              char *buf, int n);
94#endif
95
96static
97XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
98                           __GLX_NUMBER_ERRORS, error_list)
99
100/*
101 * GLX events are a bit funky.  We don't stuff the X event code into
102 * our user exposed (via XNextEvent) structure.  Instead we use the GLX
103 * private event code namespace (and hope it doesn't conflict).  Clients
104 * have to know that bit 15 in the event type field means they're getting
105 * a GLX event, and then handle the various sub-event types there, rather
106 * than simply checking the event code and handling it directly.
107 */
108
109static Bool
110__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
111{
112     struct glx_display *glx_dpy = __glXInitialize(dpy);
113
114   if (glx_dpy == NULL)
115      return False;
116
117   switch ((wire->u.u.type & 0x7f) - glx_dpy->codes->first_event) {
118   case GLX_PbufferClobber:
119   {
120      GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event;
121      xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire;
122      aevent->event_type = awire->type;
123      aevent->serial = awire->sequenceNumber;
124      aevent->event_type = awire->event_type;
125      aevent->draw_type = awire->draw_type;
126      aevent->drawable = awire->drawable;
127      aevent->buffer_mask = awire->buffer_mask;
128      aevent->aux_buffer = awire->aux_buffer;
129      aevent->x = awire->x;
130      aevent->y = awire->y;
131      aevent->width = awire->width;
132      aevent->height = awire->height;
133      aevent->count = awire->count;
134      return True;
135   }
136   case GLX_BufferSwapComplete:
137   {
138      GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
139      xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire;
140      struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable);
141
142      if (!glxDraw)
143	 return False;
144
145      aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
146      aevent->send_event = (awire->type & 0x80) != 0;
147      aevent->display = dpy;
148      aevent->event_type = awire->event_type;
149      aevent->drawable = glxDraw->xDrawable;
150      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
151      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
152
153      /* Handle 32-Bit wire sbc wraparound in both directions to cope with out
154       * of sequence 64-Bit sbc's
155       */
156      if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000))
157         glxDraw->eventSbcWrap += 0x100000000;
158      if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000))
159         glxDraw->eventSbcWrap -= 0x100000000;
160      glxDraw->lastEventSbc = awire->sbc;
161      aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
162      return True;
163   }
164   default:
165      /* client doesn't support server event */
166      break;
167   }
168
169   return False;
170}
171
172/* We don't actually support this.  It doesn't make sense for clients to
173 * send each other GLX events.
174 */
175static Status
176__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
177{
178     struct glx_display *glx_dpy = __glXInitialize(dpy);
179
180   if (glx_dpy == NULL)
181      return False;
182
183   switch (event->type) {
184   case GLX_DAMAGED:
185      break;
186   case GLX_SAVED:
187      break;
188   case GLX_EXCHANGE_COMPLETE_INTEL:
189      break;
190   case GLX_COPY_COMPLETE_INTEL:
191      break;
192   case GLX_FLIP_COMPLETE_INTEL:
193      break;
194   default:
195      /* client doesn't support server event */
196      break;
197   }
198
199   return Success;
200}
201
202/************************************************************************/
203/*
204** Free the per screen configs data as well as the array of
205** __glXScreenConfigs.
206*/
207static void
208FreeScreenConfigs(struct glx_display * priv)
209{
210   struct glx_screen *psc;
211   GLint i, screens;
212
213   /* Free screen configuration information */
214   screens = ScreenCount(priv->dpy);
215   for (i = 0; i < screens; i++) {
216      psc = priv->screens[i];
217      if (!psc)
218         continue;
219      glx_screen_cleanup(psc);
220
221#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
222      if (psc->driScreen) {
223         psc->driScreen->destroyScreen(psc);
224      } else {
225	 free(psc);
226      }
227#else
228      free(psc);
229#endif
230   }
231   free((char *) priv->screens);
232   priv->screens = NULL;
233}
234
235static void
236glx_display_free(struct glx_display *priv)
237{
238   struct glx_context *gc;
239
240   gc = __glXGetCurrentContext();
241   if (priv->dpy == gc->currentDpy) {
242      gc->vtable->destroy(gc);
243      __glXSetCurrentContextNull();
244   }
245
246   FreeScreenConfigs(priv);
247   free((char *) priv->serverGLXvendor);
248   free((char *) priv->serverGLXversion);
249
250   __glxHashDestroy(priv->glXDrawHash);
251
252#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
253   __glxHashDestroy(priv->drawHash);
254
255   /* Free the direct rendering per display data */
256   if (priv->driswDisplay)
257      (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
258   priv->driswDisplay = NULL;
259
260#if defined (GLX_USE_DRM)
261   if (priv->driDisplay)
262      (*priv->driDisplay->destroyDisplay) (priv->driDisplay);
263   priv->driDisplay = NULL;
264
265   if (priv->dri2Display)
266      (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
267   priv->dri2Display = NULL;
268
269   if (priv->dri3Display)
270      (*priv->dri3Display->destroyDisplay) (priv->dri3Display);
271   priv->dri3Display = NULL;
272#endif /* GLX_USE_DRM */
273
274#if defined(GLX_USE_WINDOWSGL)
275   if (priv->windowsdriDisplay)
276      (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay);
277   priv->windowsdriDisplay = NULL;
278#endif /* GLX_USE_WINDOWSGL */
279
280#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
281
282   free((char *) priv);
283}
284
285static int
286__glXCloseDisplay(Display * dpy, XExtCodes * codes)
287{
288   struct glx_display *priv, **prev;
289
290   _XLockMutex(_Xglobal_lock);
291   prev = &glx_displays;
292   for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
293      if (priv->dpy == dpy) {
294         *prev = priv->next;
295	 break;
296      }
297   }
298   _XUnlockMutex(_Xglobal_lock);
299
300   if (priv != NULL)
301      glx_display_free(priv);
302
303   return 1;
304}
305
306/*
307** Query the version of the GLX extension.  This procedure works even if
308** the client extension is not completely set up.
309*/
310static Bool
311QueryVersion(Display * dpy, int opcode, int *major, int *minor)
312{
313   xcb_connection_t *c = XGetXCBConnection(dpy);
314   xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c,
315                                                                      xcb_glx_query_version
316                                                                      (c,
317                                                                       GLX_MAJOR_VERSION,
318                                                                       GLX_MINOR_VERSION),
319                                                                      NULL);
320
321   if (!reply)
322     return GL_FALSE;
323
324   if (reply->major_version != GLX_MAJOR_VERSION) {
325      free(reply);
326      return GL_FALSE;
327   }
328   *major = reply->major_version;
329   *minor = min(reply->minor_version, GLX_MINOR_VERSION);
330   free(reply);
331   return GL_TRUE;
332}
333
334/*
335 * We don't want to enable this GLX_OML_swap_method in glxext.h,
336 * because we can't support it.  The X server writes it out though,
337 * so we should handle it somehow, to avoid false warnings.
338 */
339enum {
340    IGNORE_GLX_SWAP_METHOD_OML = 0x8060
341};
342
343
344static GLint
345convert_from_x_visual_type(int visualType)
346{
347   static const int glx_visual_types[] = {
348      [StaticGray]  = GLX_STATIC_GRAY,
349      [GrayScale]   = GLX_GRAY_SCALE,
350      [StaticColor] = GLX_STATIC_COLOR,
351      [PseudoColor] = GLX_PSEUDO_COLOR,
352      [TrueColor]   = GLX_TRUE_COLOR,
353      [DirectColor] = GLX_DIRECT_COLOR,
354   };
355
356   if (visualType < ARRAY_SIZE(glx_visual_types))
357      return glx_visual_types[visualType];
358
359   return GLX_NONE;
360}
361
362/*
363 * getVisualConfigs uses the !tagged_only path.
364 * getFBConfigs uses the tagged_only path.
365 */
366_X_HIDDEN void
367__glXInitializeVisualConfigFromTags(struct glx_config * config, int count,
368                                    const INT32 * bp, Bool tagged_only,
369                                    Bool fbconfig_style_tags)
370{
371   int i;
372   GLint renderType = 0;
373
374   if (!tagged_only) {
375      /* Copy in the first set of properties */
376      config->visualID = *bp++;
377
378      config->visualType = convert_from_x_visual_type(*bp++);
379
380      config->rgbMode = *bp++;
381
382      config->redBits = *bp++;
383      config->greenBits = *bp++;
384      config->blueBits = *bp++;
385      config->alphaBits = *bp++;
386      config->accumRedBits = *bp++;
387      config->accumGreenBits = *bp++;
388      config->accumBlueBits = *bp++;
389      config->accumAlphaBits = *bp++;
390
391      config->doubleBufferMode = *bp++;
392      config->stereoMode = *bp++;
393
394      config->rgbBits = *bp++;
395      config->depthBits = *bp++;
396      config->stencilBits = *bp++;
397      config->numAuxBuffers = *bp++;
398      config->level = *bp++;
399
400#ifdef GLX_USE_APPLEGL
401       /* AppleSGLX supports pixmap and pbuffers with all config. */
402       config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
403       /* Unfortunately this can create an ABI compatibility problem. */
404       count -= 18;
405#else
406      count -= __GLX_MIN_CONFIG_PROPS;
407#endif
408   }
409
410   /*
411    ** Additional properties may be in a list at the end
412    ** of the reply.  They are in pairs of property type
413    ** and property value.
414    */
415
416#define FETCH_OR_SET(tag) \
417    config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
418
419   for (i = 0; i < count; i += 2) {
420      long int tag = *bp++;
421
422      switch (tag) {
423      case GLX_RGBA:
424         FETCH_OR_SET(rgbMode);
425         break;
426      case GLX_BUFFER_SIZE:
427         config->rgbBits = *bp++;
428         break;
429      case GLX_LEVEL:
430         config->level = *bp++;
431         break;
432      case GLX_DOUBLEBUFFER:
433         FETCH_OR_SET(doubleBufferMode);
434         break;
435      case GLX_STEREO:
436         FETCH_OR_SET(stereoMode);
437         break;
438      case GLX_AUX_BUFFERS:
439         config->numAuxBuffers = *bp++;
440         break;
441      case GLX_RED_SIZE:
442         config->redBits = *bp++;
443         break;
444      case GLX_GREEN_SIZE:
445         config->greenBits = *bp++;
446         break;
447      case GLX_BLUE_SIZE:
448         config->blueBits = *bp++;
449         break;
450      case GLX_ALPHA_SIZE:
451         config->alphaBits = *bp++;
452         break;
453      case GLX_DEPTH_SIZE:
454         config->depthBits = *bp++;
455         break;
456      case GLX_STENCIL_SIZE:
457         config->stencilBits = *bp++;
458         break;
459      case GLX_ACCUM_RED_SIZE:
460         config->accumRedBits = *bp++;
461         break;
462      case GLX_ACCUM_GREEN_SIZE:
463         config->accumGreenBits = *bp++;
464         break;
465      case GLX_ACCUM_BLUE_SIZE:
466         config->accumBlueBits = *bp++;
467         break;
468      case GLX_ACCUM_ALPHA_SIZE:
469         config->accumAlphaBits = *bp++;
470         break;
471      case GLX_VISUAL_CAVEAT_EXT:
472         config->visualRating = *bp++;
473         break;
474      case GLX_X_VISUAL_TYPE:
475         config->visualType = *bp++;
476         break;
477      case GLX_TRANSPARENT_TYPE:
478         config->transparentPixel = *bp++;
479         break;
480      case GLX_TRANSPARENT_INDEX_VALUE:
481         config->transparentIndex = *bp++;
482         break;
483      case GLX_TRANSPARENT_RED_VALUE:
484         config->transparentRed = *bp++;
485         break;
486      case GLX_TRANSPARENT_GREEN_VALUE:
487         config->transparentGreen = *bp++;
488         break;
489      case GLX_TRANSPARENT_BLUE_VALUE:
490         config->transparentBlue = *bp++;
491         break;
492      case GLX_TRANSPARENT_ALPHA_VALUE:
493         config->transparentAlpha = *bp++;
494         break;
495      case GLX_VISUAL_ID:
496         config->visualID = *bp++;
497         break;
498      case GLX_DRAWABLE_TYPE:
499         config->drawableType = *bp++;
500#ifdef GLX_USE_APPLEGL
501         /* AppleSGLX supports pixmap and pbuffers with all config. */
502         config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
503#endif
504         break;
505      case GLX_RENDER_TYPE: /* fbconfig render type bits */
506         renderType = *bp++;
507         break;
508      case GLX_X_RENDERABLE:
509         config->xRenderable = *bp++;
510         break;
511      case GLX_FBCONFIG_ID:
512         config->fbconfigID = *bp++;
513         break;
514      case GLX_MAX_PBUFFER_WIDTH:
515         config->maxPbufferWidth = *bp++;
516         break;
517      case GLX_MAX_PBUFFER_HEIGHT:
518         config->maxPbufferHeight = *bp++;
519         break;
520      case GLX_MAX_PBUFFER_PIXELS:
521         config->maxPbufferPixels = *bp++;
522         break;
523#ifndef GLX_USE_APPLEGL
524      case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
525         config->optimalPbufferWidth = *bp++;
526         break;
527      case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
528         config->optimalPbufferHeight = *bp++;
529         break;
530      case GLX_VISUAL_SELECT_GROUP_SGIX:
531         config->visualSelectGroup = *bp++;
532         break;
533      case GLX_SWAP_METHOD_OML:
534         if (*bp == GLX_SWAP_UNDEFINED_OML ||
535             *bp == GLX_SWAP_COPY_OML ||
536             *bp == GLX_SWAP_EXCHANGE_OML) {
537            config->swapMethod = *bp++;
538         } else {
539            /* X servers with old HW drivers may return any value here, so
540             * assume GLX_SWAP_METHOD_UNDEFINED.
541             */
542            config->swapMethod = GLX_SWAP_UNDEFINED_OML;
543            bp++;
544         }
545         break;
546#endif
547      case GLX_SAMPLE_BUFFERS_SGIS:
548         config->sampleBuffers = *bp++;
549         break;
550      case GLX_SAMPLES_SGIS:
551         config->samples = *bp++;
552         break;
553#ifdef GLX_USE_APPLEGL
554      case IGNORE_GLX_SWAP_METHOD_OML:
555         /* We ignore this tag.  See the comment above this function. */
556         ++bp;
557         break;
558#else
559      case GLX_BIND_TO_TEXTURE_RGB_EXT:
560         config->bindToTextureRgb = *bp++;
561         break;
562      case GLX_BIND_TO_TEXTURE_RGBA_EXT:
563         config->bindToTextureRgba = *bp++;
564         break;
565      case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
566         config->bindToMipmapTexture = *bp++;
567         break;
568      case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
569         config->bindToTextureTargets = *bp++;
570         break;
571      case GLX_Y_INVERTED_EXT:
572         config->yInverted = *bp++;
573         break;
574#endif
575      case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
576         config->sRGBCapable = *bp++;
577         break;
578
579      case GLX_USE_GL:
580         if (fbconfig_style_tags)
581            bp++;
582         break;
583      case None:
584         i = count;
585         break;
586      default:
587         if(env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) {
588             long int tagvalue = *bp++;
589             fprintf(stderr, "WARNING: unknown GLX tag from server: "
590                     "tag 0x%lx value 0x%lx\n", tag, tagvalue);
591         } else {
592             /* Ignore the unrecognized tag's value */
593             bp++;
594         }
595         break;
596      }
597   }
598
599   if (renderType != 0 && renderType != GLX_DONT_CARE) {
600      config->renderType = renderType;
601      config->floatMode = (renderType &
602         (GLX_RGBA_FLOAT_BIT_ARB|GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT)) != 0;
603   } else {
604      /* If there wasn't GLX_RENDER_TYPE property, set it based on
605       * config->rgbMode.  The only way to communicate that the config is
606       * floating-point is via GLX_RENDER_TYPE, so this cannot be a float
607       * config.
608       */
609      config->renderType =
610         (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
611   }
612
613   /* The GLX_ARB_fbconfig_float spec says:
614    *
615    *     "Note that floating point rendering is only supported for
616    *     GLXPbuffer drawables."
617    */
618   if (config->floatMode)
619      config->drawableType &= GLX_PBUFFER_BIT;
620}
621
622static struct glx_config *
623createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
624                            int screen, GLboolean tagged_only)
625{
626   INT32 buf[__GLX_TOTAL_CONFIG], *props;
627   unsigned prop_size;
628   struct glx_config *modes, *m;
629   int i;
630
631   if (nprops == 0)
632      return NULL;
633
634   /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
635
636   /* Check number of properties */
637   if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
638      return NULL;
639
640   /* Allocate memory for our config structure */
641   modes = glx_config_create_list(nvisuals);
642   if (!modes)
643      return NULL;
644
645   prop_size = nprops * __GLX_SIZE_INT32;
646   if (prop_size <= sizeof(buf))
647      props = buf;
648   else
649      props = malloc(prop_size);
650
651   /* Read each config structure and convert it into our format */
652   m = modes;
653   for (i = 0; i < nvisuals; i++) {
654      _XRead(dpy, (char *) props, prop_size);
655#ifdef GLX_USE_APPLEGL
656       /* Older X servers don't send this so we default it here. */
657      m->drawableType = GLX_WINDOW_BIT;
658#else
659      /*
660       * The XQuartz 2.3.2.1 X server doesn't set this properly, so
661       * set the proper bits here.
662       * AppleSGLX supports windows, pixmaps, and pbuffers with all config.
663       */
664      m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
665#endif
666      /* Older X servers don't send this so we default it here. */
667      m->sRGBCapable = GL_FALSE;
668       __glXInitializeVisualConfigFromTags(m, nprops, props,
669                                          tagged_only, GL_TRUE);
670      m->screen = screen;
671      m = m->next;
672   }
673
674   if (props != buf)
675      free(props);
676
677   return modes;
678}
679
680static GLboolean
681getVisualConfigs(struct glx_screen *psc,
682		  struct glx_display *priv, int screen)
683{
684   xGLXGetVisualConfigsReq *req;
685   xGLXGetVisualConfigsReply reply;
686   Display *dpy = priv->dpy;
687
688   LockDisplay(dpy);
689
690   psc->visuals = NULL;
691   GetReq(GLXGetVisualConfigs, req);
692   req->reqType = priv->majorOpcode;
693   req->glxCode = X_GLXGetVisualConfigs;
694   req->screen = screen;
695
696   if (!_XReply(dpy, (xReply *) & reply, 0, False))
697      goto out;
698
699   psc->visuals = createConfigsFromProperties(dpy,
700                                              reply.numVisuals,
701                                              reply.numProps,
702                                              screen, GL_FALSE);
703
704 out:
705   UnlockDisplay(dpy);
706   return psc->visuals != NULL;
707}
708
709static GLboolean
710 getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen)
711{
712   xGLXGetFBConfigsReq *fb_req;
713   xGLXGetFBConfigsSGIXReq *sgi_req;
714   xGLXVendorPrivateWithReplyReq *vpreq;
715   xGLXGetFBConfigsReply reply;
716   Display *dpy = priv->dpy;
717
718   psc->serverGLXexts =
719      __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
720
721   if (psc->serverGLXexts == NULL) {
722      return GL_FALSE;
723   }
724
725   LockDisplay(dpy);
726
727   psc->configs = NULL;
728   if (atof(priv->serverGLXversion) >= 1.3) {
729      GetReq(GLXGetFBConfigs, fb_req);
730      fb_req->reqType = priv->majorOpcode;
731      fb_req->glxCode = X_GLXGetFBConfigs;
732      fb_req->screen = screen;
733   }
734   else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
735      GetReqExtra(GLXVendorPrivateWithReply,
736                  sz_xGLXGetFBConfigsSGIXReq -
737                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
738      sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
739      sgi_req->reqType = priv->majorOpcode;
740      sgi_req->glxCode = X_GLXVendorPrivateWithReply;
741      sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
742      sgi_req->screen = screen;
743   }
744   else
745      goto out;
746
747   if (!_XReply(dpy, (xReply *) & reply, 0, False))
748      goto out;
749
750   psc->configs = createConfigsFromProperties(dpy,
751                                              reply.numFBConfigs,
752                                              reply.numAttribs * 2,
753                                              screen, GL_TRUE);
754
755 out:
756   UnlockDisplay(dpy);
757   return psc->configs != NULL;
758}
759
760_X_HIDDEN Bool
761glx_screen_init(struct glx_screen *psc,
762		 int screen, struct glx_display * priv)
763{
764   /* Initialize per screen dynamic client GLX extensions */
765   psc->ext_list_first_time = GL_TRUE;
766   psc->scr = screen;
767   psc->dpy = priv->dpy;
768   psc->display = priv;
769
770   if (!getVisualConfigs(psc, priv, screen))
771      return GL_FALSE;
772
773   if (!getFBConfigs(psc, priv, screen))
774      return GL_FALSE;
775
776   return GL_TRUE;
777}
778
779_X_HIDDEN void
780glx_screen_cleanup(struct glx_screen *psc)
781{
782   if (psc->configs) {
783      glx_config_destroy_list(psc->configs);
784      free(psc->effectiveGLXexts);
785      psc->configs = NULL;   /* NOTE: just for paranoia */
786   }
787   if (psc->visuals) {
788      glx_config_destroy_list(psc->visuals);
789      psc->visuals = NULL;   /* NOTE: just for paranoia */
790   }
791   free((char *) psc->serverGLXexts);
792}
793
794/*
795** Allocate the memory for the per screen configs for each screen.
796** If that works then fetch the per screen configs data.
797*/
798static Bool
799AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
800{
801   struct glx_screen *psc;
802   GLint i, screens;
803
804   /*
805    ** First allocate memory for the array of per screen configs.
806    */
807   screens = ScreenCount(dpy);
808   priv->screens = calloc(screens, sizeof *priv->screens);
809   if (!priv->screens)
810      return GL_FALSE;
811
812   priv->serverGLXversion =
813      __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
814   if (priv->serverGLXversion == NULL) {
815      FreeScreenConfigs(priv);
816      return GL_FALSE;
817   }
818
819   for (i = 0; i < screens; i++, psc++) {
820      psc = NULL;
821#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
822#if defined(GLX_USE_DRM)
823#if defined(HAVE_DRI3)
824      if (priv->dri3Display)
825         psc = (*priv->dri3Display->createScreen) (i, priv);
826#endif /* HAVE_DRI3 */
827      if (psc == NULL && priv->dri2Display)
828	 psc = (*priv->dri2Display->createScreen) (i, priv);
829      if (psc == NULL && priv->driDisplay)
830	 psc = (*priv->driDisplay->createScreen) (i, priv);
831#endif /* GLX_USE_DRM */
832
833#ifdef GLX_USE_WINDOWSGL
834      if (psc == NULL && priv->windowsdriDisplay)
835	 psc = (*priv->windowsdriDisplay->createScreen) (i, priv);
836#endif
837
838      if (psc == NULL && priv->driswDisplay)
839	 psc = (*priv->driswDisplay->createScreen) (i, priv);
840#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
841
842#if defined(GLX_USE_APPLEGL)
843      if (psc == NULL)
844         psc = applegl_create_screen(i, priv);
845#else
846      if (psc == NULL)
847	 psc = indirect_create_screen(i, priv);
848#endif
849      priv->screens[i] = psc;
850   }
851   SyncHandle();
852   return GL_TRUE;
853}
854
855/*
856** Initialize the client side extension code.
857*/
858 _X_HIDDEN struct glx_display *
859__glXInitialize(Display * dpy)
860{
861   struct glx_display *dpyPriv, *d;
862#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
863   Bool glx_direct, glx_accel;
864#endif
865   int i;
866
867   _XLockMutex(_Xglobal_lock);
868
869   for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) {
870      if (dpyPriv->dpy == dpy) {
871	 _XUnlockMutex(_Xglobal_lock);
872	 return dpyPriv;
873      }
874   }
875
876   /* Drop the lock while we create the display private. */
877   _XUnlockMutex(_Xglobal_lock);
878
879   dpyPriv = calloc(1, sizeof *dpyPriv);
880   if (!dpyPriv)
881      return NULL;
882
883   dpyPriv->codes = XInitExtension(dpy, __glXExtensionName);
884   if (!dpyPriv->codes) {
885      free(dpyPriv);
886      return NULL;
887   }
888
889   dpyPriv->dpy = dpy;
890   dpyPriv->majorOpcode = dpyPriv->codes->major_opcode;
891   dpyPriv->serverGLXvendor = 0x0;
892   dpyPriv->serverGLXversion = 0x0;
893
894   /* See if the versions are compatible.  This GLX implementation does not
895    * work with servers that only support GLX 1.0.
896    */
897   if (!QueryVersion(dpy, dpyPriv->majorOpcode,
898		     &dpyPriv->majorVersion, &dpyPriv->minorVersion)
899       || (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion < 1)) {
900      free(dpyPriv);
901      return NULL;
902   }
903
904   for (i = 0; i < __GLX_NUMBER_EVENTS; i++) {
905      XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent);
906      XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire);
907   }
908
909   XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay);
910   XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString);
911
912   dpyPriv->glXDrawHash = __glxHashCreate();
913
914#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
915   glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false);
916   glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
917
918   dpyPriv->drawHash = __glxHashCreate();
919
920   /*
921    ** Initialize the direct rendering per display data and functions.
922    ** Note: This _must_ be done before calling any other DRI routines
923    ** (e.g., those called in AllocAndFetchScreenConfigs).
924    */
925#if defined(GLX_USE_DRM)
926   if (glx_direct && glx_accel) {
927#if defined(HAVE_DRI3)
928      if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false))
929         dpyPriv->dri3Display = dri3_create_display(dpy);
930#endif /* HAVE_DRI3 */
931      dpyPriv->dri2Display = dri2CreateDisplay(dpy);
932      dpyPriv->driDisplay = driCreateDisplay(dpy);
933   }
934#endif /* GLX_USE_DRM */
935   if (glx_direct)
936      dpyPriv->driswDisplay = driswCreateDisplay(dpy);
937#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
938
939#ifdef GLX_USE_APPLEGL
940   if (!applegl_create_display(dpyPriv)) {
941      free(dpyPriv);
942      return NULL;
943   }
944#endif
945
946#ifdef GLX_USE_WINDOWSGL
947   if (glx_direct && glx_accel)
948      dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy);
949#endif
950
951   if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
952      free(dpyPriv);
953      return NULL;
954   }
955
956   __glX_send_client_info(dpyPriv);
957
958   /* Grab the lock again and add the dispay private, unless somebody
959    * beat us to initializing on this display in the meantime. */
960   _XLockMutex(_Xglobal_lock);
961
962   for (d = glx_displays; d; d = d->next) {
963      if (d->dpy == dpy) {
964	 _XUnlockMutex(_Xglobal_lock);
965	 glx_display_free(dpyPriv);
966	 return d;
967      }
968   }
969
970   dpyPriv->next = glx_displays;
971   glx_displays = dpyPriv;
972
973   _XUnlockMutex(_Xglobal_lock);
974
975   return dpyPriv;
976}
977
978/*
979** Setup for sending a GLX command on dpy.  Make sure the extension is
980** initialized.  Try to avoid calling __glXInitialize as its kinda slow.
981*/
982_X_HIDDEN CARD8
983__glXSetupForCommand(Display * dpy)
984{
985    struct glx_context *gc;
986    struct glx_display *priv;
987
988   /* If this thread has a current context, flush its rendering commands */
989   gc = __glXGetCurrentContext();
990   if (gc->currentDpy) {
991      /* Flush rendering buffer of the current context, if any */
992      (void) __glXFlushRenderBuffer(gc, gc->pc);
993
994      if (gc->currentDpy == dpy) {
995         /* Use opcode from gc because its right */
996         return gc->majorOpcode;
997      }
998      else {
999         /*
1000          ** Have to get info about argument dpy because it might be to
1001          ** a different server
1002          */
1003      }
1004   }
1005
1006   /* Forced to lookup extension via the slow initialize route */
1007   priv = __glXInitialize(dpy);
1008   if (!priv) {
1009      return 0;
1010   }
1011   return priv->majorOpcode;
1012}
1013
1014/**
1015 * Flush the drawing command transport buffer.
1016 *
1017 * \param ctx  Context whose transport buffer is to be flushed.
1018 * \param pc   Pointer to first unused buffer location.
1019 *
1020 * \todo
1021 * Modify this function to use \c ctx->pc instead of the explicit
1022 * \c pc parameter.
1023 */
1024_X_HIDDEN GLubyte *
1025__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc)
1026{
1027   Display *const dpy = ctx->currentDpy;
1028   xcb_connection_t *c = XGetXCBConnection(dpy);
1029   const GLint size = pc - ctx->buf;
1030
1031   if ((dpy != NULL) && (size > 0)) {
1032      xcb_glx_render(c, ctx->currentContextTag, size,
1033                     (const uint8_t *) ctx->buf);
1034   }
1035
1036   /* Reset pointer and return it */
1037   ctx->pc = ctx->buf;
1038   return ctx->pc;
1039}
1040
1041
1042/**
1043 * Send a portion of a GLXRenderLarge command to the server.  The advantage of
1044 * this function over \c __glXSendLargeCommand is that callers can use the
1045 * data buffer in the GLX context and may be able to avoid allocating an
1046 * extra buffer.  The disadvantage is the clients will have to do more
1047 * GLX protocol work (i.e., calculating \c totalRequests, etc.).
1048 *
1049 * \sa __glXSendLargeCommand
1050 *
1051 * \param gc             GLX context
1052 * \param requestNumber  Which part of the whole command is this?  The first
1053 *                       request is 1.
1054 * \param totalRequests  How many requests will there be?
1055 * \param data           Command data.
1056 * \param dataLen        Size, in bytes, of the command data.
1057 */
1058_X_HIDDEN void
1059__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber,
1060                    GLint totalRequests, const GLvoid * data, GLint dataLen)
1061{
1062   Display *dpy = gc->currentDpy;
1063   xcb_connection_t *c = XGetXCBConnection(dpy);
1064   xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
1065                        totalRequests, dataLen, data);
1066}
1067
1068
1069/**
1070 * Send a command that is too large for the GLXRender protocol request.
1071 *
1072 * Send a large command, one that is too large for some reason to
1073 * send using the GLXRender protocol request.  One reason to send
1074 * a large command is to avoid copying the data.
1075 *
1076 * \param ctx        GLX context
1077 * \param header     Header data.
1078 * \param headerLen  Size, in bytes, of the header data.  It is assumed that
1079 *                   the header data will always be small enough to fit in
1080 *                   a single X protocol packet.
1081 * \param data       Command data.
1082 * \param dataLen    Size, in bytes, of the command data.
1083 */
1084_X_HIDDEN void
1085__glXSendLargeCommand(struct glx_context * ctx,
1086                      const GLvoid * header, GLint headerLen,
1087                      const GLvoid * data, GLint dataLen)
1088{
1089   GLint maxSize;
1090   GLint totalRequests, requestNumber;
1091
1092   /*
1093    ** Calculate the maximum amount of data can be stuffed into a single
1094    ** packet.  sz_xGLXRenderReq is added because bufSize is the maximum
1095    ** packet size minus sz_xGLXRenderReq.
1096    */
1097   maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
1098   totalRequests = 1 + (dataLen / maxSize);
1099   if (dataLen % maxSize)
1100      totalRequests++;
1101
1102   /*
1103    ** Send all of the command, except the large array, as one request.
1104    */
1105   assert(headerLen <= maxSize);
1106   __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
1107
1108   /*
1109    ** Send enough requests until the whole array is sent.
1110    */
1111   for (requestNumber = 2; requestNumber <= (totalRequests - 1);
1112        requestNumber++) {
1113      __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
1114      data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
1115      dataLen -= maxSize;
1116      assert(dataLen > 0);
1117   }
1118
1119   assert(dataLen <= maxSize);
1120   __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
1121}
1122
1123/************************************************************************/
1124
1125#ifdef DEBUG
1126_X_HIDDEN void
1127__glXDumpDrawBuffer(struct glx_context * ctx)
1128{
1129   GLubyte *p = ctx->buf;
1130   GLubyte *end = ctx->pc;
1131   GLushort opcode, length;
1132
1133   while (p < end) {
1134      /* Fetch opcode */
1135      opcode = *((GLushort *) p);
1136      length = *((GLushort *) (p + 2));
1137      printf("%2x: %5d: ", opcode, length);
1138      length -= 4;
1139      p += 4;
1140      while (length > 0) {
1141         printf("%08x ", *((unsigned *) p));
1142         p += 4;
1143         length -= 4;
1144      }
1145      printf("\n");
1146   }
1147}
1148#endif
1149