glxext.c revision 42ea25cb4ecae09b5cc011a95d42ba7f0645dde3
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 "glxclient.h"
42#include <X11/extensions/Xext.h>
43#include <X11/extensions/extutil.h>
44#include <X11/extensions/dri2proto.h>
45#include "glxextensions.h"
46#include "glcontextmodes.h"
47
48#ifdef USE_XCB
49#include <X11/Xlib-xcb.h>
50#include <xcb/xcb.h>
51#include <xcb/glx.h>
52#endif
53
54
55#ifdef DEBUG
56void __glXDumpDrawBuffer(__GLXcontext * ctx);
57#endif
58
59/*
60** You can set this cell to 1 to force the gl drawing stuff to be
61** one command per packet
62*/
63_X_HIDDEN int __glXDebug = 0;
64
65/* Extension required boiler plate */
66
67static char *__glXExtensionName = GLX_EXTENSION_NAME;
68XExtensionInfo *__glXExtensionInfo = NULL;
69
70static /* const */ char *error_list[] = {
71   "GLXBadContext",
72   "GLXBadContextState",
73   "GLXBadDrawable",
74   "GLXBadPixmap",
75   "GLXBadContextTag",
76   "GLXBadCurrentWindow",
77   "GLXBadRenderRequest",
78   "GLXBadLargeRequest",
79   "GLXUnsupportedPrivateRequest",
80   "GLXBadFBConfig",
81   "GLXBadPbuffer",
82   "GLXBadCurrentDrawable",
83   "GLXBadWindow",
84};
85
86static int
87__glXCloseDisplay(Display * dpy, XExtCodes * codes)
88{
89   GLXContext gc;
90
91   gc = __glXGetCurrentContext();
92   if (dpy == gc->currentDpy) {
93      __glXSetCurrentContextNull();
94      __glXFreeContext(gc);
95   }
96
97   return XextRemoveDisplay(__glXExtensionInfo, dpy);
98}
99
100
101static
102XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
103                           __GLX_NUMBER_ERRORS, error_list)
104static Bool
105__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire);
106static Status
107__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire);
108
109static /* const */ XExtensionHooks __glXExtensionHooks = {
110  NULL,                   /* create_gc */
111  NULL,                   /* copy_gc */
112  NULL,                   /* flush_gc */
113  NULL,                   /* free_gc */
114  NULL,                   /* create_font */
115  NULL,                   /* free_font */
116  __glXCloseDisplay,      /* close_display */
117  __glXWireToEvent,       /* wire_to_event */
118  __glXEventToWire,       /* event_to_wire */
119  NULL,                   /* error */
120  __glXErrorString,       /* error_string */
121};
122
123XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
124                           __glXExtensionName, &__glXExtensionHooks,
125                           __GLX_NUMBER_EVENTS, NULL)
126
127/*
128 * GLX events are a bit funky.  We don't stuff the X event code into
129 * our user exposed (via XNextEvent) structure.  Instead we use the GLX
130 * private event code namespace (and hope it doesn't conflict).  Clients
131 * have to know that bit 15 in the event type field means they're getting
132 * a GLX event, and then handle the various sub-event types there, rather
133 * than simply checking the event code and handling it directly.
134 */
135
136static Bool
137__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
138{
139   XExtDisplayInfo *info = __glXFindDisplay(dpy);
140
141   XextCheckExtension(dpy, info, __glXExtensionName, False);
142
143   switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
144   case GLX_PbufferClobber:
145   {
146      GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event;
147      xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire;
148      aevent->event_type = awire->type;
149      aevent->serial = awire->sequenceNumber;
150      aevent->event_type = awire->event_type;
151      aevent->draw_type = awire->draw_type;
152      aevent->drawable = awire->drawable;
153      aevent->buffer_mask = awire->buffer_mask;
154      aevent->aux_buffer = awire->aux_buffer;
155      aevent->x = awire->x;
156      aevent->y = awire->y;
157      aevent->width = awire->width;
158      aevent->height = awire->height;
159      aevent->count = awire->count;
160      return True;
161   }
162   /* No easy symbol to test for this, as GLX_BufferSwapComplete is
163    * defined in the local glx.h header, but the
164    * xGLXBufferSwapComplete typedef is only available in new versions
165    * of the external glxproto.h header, which doesn't have any
166    * testable versioning define.
167    *
168    * I'll use the related DRI2 define, in the hope that we won't
169    * receive these events unless we know how to ask for them:
170    */
171#ifdef X_DRI2SwapBuffers
172   case GLX_BufferSwapComplete:
173   {
174      GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
175      xGLXBufferSwapComplete *awire = (xGLXBufferSwapComplete *)wire;
176      aevent->event_type = awire->event_type;
177      aevent->drawable = awire->drawable;
178      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
179      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
180      aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
181      return True;
182   }
183#endif
184   default:
185      /* client doesn't support server event */
186      break;
187   }
188
189   return False;
190}
191
192/* We don't actually support this.  It doesn't make sense for clients to
193 * send each other GLX events.
194 */
195static Status
196__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
197{
198   XExtDisplayInfo *info = __glXFindDisplay(dpy);
199
200   XextCheckExtension(dpy, info, __glXExtensionName, False);
201
202   switch (event->type) {
203   case GLX_DAMAGED:
204      break;
205   case GLX_SAVED:
206      break;
207   case GLX_EXCHANGE_COMPLETE_INTEL:
208      break;
209   case GLX_COPY_COMPLETE_INTEL:
210      break;
211   case GLX_FLIP_COMPLETE_INTEL:
212      break;
213   default:
214      /* client doesn't support server event */
215      break;
216   }
217
218   return Success;
219}
220
221/************************************************************************/
222/*
223** Free the per screen configs data as well as the array of
224** __glXScreenConfigs.
225*/
226static void
227FreeScreenConfigs(__GLXdisplayPrivate * priv)
228{
229   __GLXscreenConfigs *psc;
230   GLint i, screens;
231
232   /* Free screen configuration information */
233   psc = priv->screenConfigs;
234   screens = ScreenCount(priv->dpy);
235   for (i = 0; i < screens; i++, psc++) {
236      if (psc->configs) {
237         _gl_context_modes_destroy(psc->configs);
238         if (psc->effectiveGLXexts)
239            Xfree(psc->effectiveGLXexts);
240         psc->configs = NULL;   /* NOTE: just for paranoia */
241      }
242      if (psc->visuals) {
243         _gl_context_modes_destroy(psc->visuals);
244         psc->visuals = NULL;   /* NOTE: just for paranoia */
245      }
246      Xfree((char *) psc->serverGLXexts);
247
248#ifdef GLX_DIRECT_RENDERING
249      if (psc->driver_configs) {
250         unsigned int j;
251         for (j = 0; psc->driver_configs[j]; j++)
252            free((__DRIconfig *) psc->driver_configs[j]);
253         free(psc->driver_configs);
254         psc->driver_configs = NULL;
255      }
256      if (psc->driScreen) {
257         psc->driScreen->destroyScreen(psc);
258         __glxHashDestroy(psc->drawHash);
259         XFree(psc->driScreen);
260         psc->driScreen = NULL;
261      }
262#endif
263   }
264   XFree((char *) priv->screenConfigs);
265   priv->screenConfigs = NULL;
266}
267
268/*
269** Release the private memory referred to in a display private
270** structure.  The caller will free the extension structure.
271*/
272static int
273__glXFreeDisplayPrivate(XExtData * extension)
274{
275   __GLXdisplayPrivate *priv;
276
277   priv = (__GLXdisplayPrivate *) extension->private_data;
278   FreeScreenConfigs(priv);
279   if (priv->serverGLXvendor) {
280      Xfree((char *) priv->serverGLXvendor);
281      priv->serverGLXvendor = 0x0;      /* to protect against double free's */
282   }
283   if (priv->serverGLXversion) {
284      Xfree((char *) priv->serverGLXversion);
285      priv->serverGLXversion = 0x0;     /* to protect against double free's */
286   }
287
288#ifdef GLX_DIRECT_RENDERING
289   /* Free the direct rendering per display data */
290   if (priv->driswDisplay)
291      (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
292   priv->driswDisplay = NULL;
293
294   if (priv->driDisplay)
295      (*priv->driDisplay->destroyDisplay) (priv->driDisplay);
296   priv->driDisplay = NULL;
297
298   if (priv->dri2Display)
299      (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
300   priv->dri2Display = NULL;
301#endif
302
303   Xfree((char *) priv);
304   return 0;
305}
306
307/************************************************************************/
308
309/*
310** Query the version of the GLX extension.  This procedure works even if
311** the client extension is not completely set up.
312*/
313static Bool
314QueryVersion(Display * dpy, int opcode, int *major, int *minor)
315{
316#ifdef USE_XCB
317   xcb_connection_t *c = XGetXCBConnection(dpy);
318   xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c,
319                                                                      xcb_glx_query_version
320                                                                      (c,
321                                                                       GLX_MAJOR_VERSION,
322                                                                       GLX_MINOR_VERSION),
323                                                                      NULL);
324
325   if (reply->major_version != GLX_MAJOR_VERSION) {
326      free(reply);
327      return GL_FALSE;
328   }
329   *major = reply->major_version;
330   *minor = min(reply->minor_version, GLX_MINOR_VERSION);
331   free(reply);
332   return GL_TRUE;
333#else
334   xGLXQueryVersionReq *req;
335   xGLXQueryVersionReply reply;
336
337   /* Send the glXQueryVersion request */
338   LockDisplay(dpy);
339   GetReq(GLXQueryVersion, req);
340   req->reqType = opcode;
341   req->glxCode = X_GLXQueryVersion;
342   req->majorVersion = GLX_MAJOR_VERSION;
343   req->minorVersion = GLX_MINOR_VERSION;
344   _XReply(dpy, (xReply *) & reply, 0, False);
345   UnlockDisplay(dpy);
346   SyncHandle();
347
348   if (reply.majorVersion != GLX_MAJOR_VERSION) {
349      /*
350       ** The server does not support the same major release as this
351       ** client.
352       */
353      return GL_FALSE;
354   }
355   *major = reply.majorVersion;
356   *minor = min(reply.minorVersion, GLX_MINOR_VERSION);
357   return GL_TRUE;
358#endif /* USE_XCB */
359}
360
361
362_X_HIDDEN void
363__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count,
364                                    const INT32 * bp, Bool tagged_only,
365                                    Bool fbconfig_style_tags)
366{
367   int i;
368
369   if (!tagged_only) {
370      /* Copy in the first set of properties */
371      config->visualID = *bp++;
372
373      config->visualType = _gl_convert_from_x_visual_type(*bp++);
374
375      config->rgbMode = *bp++;
376
377      config->redBits = *bp++;
378      config->greenBits = *bp++;
379      config->blueBits = *bp++;
380      config->alphaBits = *bp++;
381      config->accumRedBits = *bp++;
382      config->accumGreenBits = *bp++;
383      config->accumBlueBits = *bp++;
384      config->accumAlphaBits = *bp++;
385
386      config->doubleBufferMode = *bp++;
387      config->stereoMode = *bp++;
388
389      config->rgbBits = *bp++;
390      config->depthBits = *bp++;
391      config->stencilBits = *bp++;
392      config->numAuxBuffers = *bp++;
393      config->level = *bp++;
394
395      count -= __GLX_MIN_CONFIG_PROPS;
396   }
397
398   /*
399    ** Additional properties may be in a list at the end
400    ** of the reply.  They are in pairs of property type
401    ** and property value.
402    */
403
404#define FETCH_OR_SET(tag) \
405    config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
406
407   for (i = 0; i < count; i += 2) {
408      switch (*bp++) {
409      case GLX_RGBA:
410         FETCH_OR_SET(rgbMode);
411         break;
412      case GLX_BUFFER_SIZE:
413         config->rgbBits = *bp++;
414         break;
415      case GLX_LEVEL:
416         config->level = *bp++;
417         break;
418      case GLX_DOUBLEBUFFER:
419         FETCH_OR_SET(doubleBufferMode);
420         break;
421      case GLX_STEREO:
422         FETCH_OR_SET(stereoMode);
423         break;
424      case GLX_AUX_BUFFERS:
425         config->numAuxBuffers = *bp++;
426         break;
427      case GLX_RED_SIZE:
428         config->redBits = *bp++;
429         break;
430      case GLX_GREEN_SIZE:
431         config->greenBits = *bp++;
432         break;
433      case GLX_BLUE_SIZE:
434         config->blueBits = *bp++;
435         break;
436      case GLX_ALPHA_SIZE:
437         config->alphaBits = *bp++;
438         break;
439      case GLX_DEPTH_SIZE:
440         config->depthBits = *bp++;
441         break;
442      case GLX_STENCIL_SIZE:
443         config->stencilBits = *bp++;
444         break;
445      case GLX_ACCUM_RED_SIZE:
446         config->accumRedBits = *bp++;
447         break;
448      case GLX_ACCUM_GREEN_SIZE:
449         config->accumGreenBits = *bp++;
450         break;
451      case GLX_ACCUM_BLUE_SIZE:
452         config->accumBlueBits = *bp++;
453         break;
454      case GLX_ACCUM_ALPHA_SIZE:
455         config->accumAlphaBits = *bp++;
456         break;
457      case GLX_VISUAL_CAVEAT_EXT:
458         config->visualRating = *bp++;
459         break;
460      case GLX_X_VISUAL_TYPE:
461         config->visualType = *bp++;
462         break;
463      case GLX_TRANSPARENT_TYPE:
464         config->transparentPixel = *bp++;
465         break;
466      case GLX_TRANSPARENT_INDEX_VALUE:
467         config->transparentIndex = *bp++;
468         break;
469      case GLX_TRANSPARENT_RED_VALUE:
470         config->transparentRed = *bp++;
471         break;
472      case GLX_TRANSPARENT_GREEN_VALUE:
473         config->transparentGreen = *bp++;
474         break;
475      case GLX_TRANSPARENT_BLUE_VALUE:
476         config->transparentBlue = *bp++;
477         break;
478      case GLX_TRANSPARENT_ALPHA_VALUE:
479         config->transparentAlpha = *bp++;
480         break;
481      case GLX_VISUAL_ID:
482         config->visualID = *bp++;
483         break;
484      case GLX_DRAWABLE_TYPE:
485         config->drawableType = *bp++;
486         break;
487      case GLX_RENDER_TYPE:
488         config->renderType = *bp++;
489         break;
490      case GLX_X_RENDERABLE:
491         config->xRenderable = *bp++;
492         break;
493      case GLX_FBCONFIG_ID:
494         config->fbconfigID = *bp++;
495         break;
496      case GLX_MAX_PBUFFER_WIDTH:
497         config->maxPbufferWidth = *bp++;
498         break;
499      case GLX_MAX_PBUFFER_HEIGHT:
500         config->maxPbufferHeight = *bp++;
501         break;
502      case GLX_MAX_PBUFFER_PIXELS:
503         config->maxPbufferPixels = *bp++;
504         break;
505      case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
506         config->optimalPbufferWidth = *bp++;
507         break;
508      case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
509         config->optimalPbufferHeight = *bp++;
510         break;
511      case GLX_VISUAL_SELECT_GROUP_SGIX:
512         config->visualSelectGroup = *bp++;
513         break;
514      case GLX_SWAP_METHOD_OML:
515         config->swapMethod = *bp++;
516         break;
517      case GLX_SAMPLE_BUFFERS_SGIS:
518         config->sampleBuffers = *bp++;
519         break;
520      case GLX_SAMPLES_SGIS:
521         config->samples = *bp++;
522         break;
523      case GLX_BIND_TO_TEXTURE_RGB_EXT:
524         config->bindToTextureRgb = *bp++;
525         break;
526      case GLX_BIND_TO_TEXTURE_RGBA_EXT:
527         config->bindToTextureRgba = *bp++;
528         break;
529      case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
530         config->bindToMipmapTexture = *bp++;
531         break;
532      case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
533         config->bindToTextureTargets = *bp++;
534         break;
535      case GLX_Y_INVERTED_EXT:
536         config->yInverted = *bp++;
537         break;
538      case None:
539         i = count;
540         break;
541      default:
542         break;
543      }
544   }
545
546   config->renderType =
547      (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
548
549   config->haveAccumBuffer = ((config->accumRedBits +
550                               config->accumGreenBits +
551                               config->accumBlueBits +
552                               config->accumAlphaBits) > 0);
553   config->haveDepthBuffer = (config->depthBits > 0);
554   config->haveStencilBuffer = (config->stencilBits > 0);
555}
556
557static __GLcontextModes *
558createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
559                            int screen, GLboolean tagged_only)
560{
561   INT32 buf[__GLX_TOTAL_CONFIG], *props;
562   unsigned prop_size;
563   __GLcontextModes *modes, *m;
564   int i;
565
566   if (nprops == 0)
567      return NULL;
568
569   /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
570
571   /* Check number of properties */
572   if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
573      return NULL;
574
575   /* Allocate memory for our config structure */
576   modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes));
577   if (!modes)
578      return NULL;
579
580   prop_size = nprops * __GLX_SIZE_INT32;
581   if (prop_size <= sizeof(buf))
582      props = buf;
583   else
584      props = Xmalloc(prop_size);
585
586   /* Read each config structure and convert it into our format */
587   m = modes;
588   for (i = 0; i < nvisuals; i++) {
589      _XRead(dpy, (char *) props, prop_size);
590      /* Older X servers don't send this so we default it here. */
591      m->drawableType = GLX_WINDOW_BIT;
592      __glXInitializeVisualConfigFromTags(m, nprops, props,
593                                          tagged_only, GL_TRUE);
594      m->screen = screen;
595      m = m->next;
596   }
597
598   if (props != buf)
599      Xfree(props);
600
601   return modes;
602}
603
604static GLboolean
605getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
606{
607   xGLXGetVisualConfigsReq *req;
608   __GLXscreenConfigs *psc;
609   xGLXGetVisualConfigsReply reply;
610
611   LockDisplay(dpy);
612
613   psc = priv->screenConfigs + screen;
614   psc->visuals = NULL;
615   GetReq(GLXGetVisualConfigs, req);
616   req->reqType = priv->majorOpcode;
617   req->glxCode = X_GLXGetVisualConfigs;
618   req->screen = screen;
619
620   if (!_XReply(dpy, (xReply *) & reply, 0, False))
621      goto out;
622
623   psc->visuals = createConfigsFromProperties(dpy,
624                                              reply.numVisuals,
625                                              reply.numProps,
626                                              screen, GL_FALSE);
627
628 out:
629   UnlockDisplay(dpy);
630   return psc->visuals != NULL;
631}
632
633static GLboolean
634getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
635{
636   xGLXGetFBConfigsReq *fb_req;
637   xGLXGetFBConfigsSGIXReq *sgi_req;
638   xGLXVendorPrivateWithReplyReq *vpreq;
639   xGLXGetFBConfigsReply reply;
640   __GLXscreenConfigs *psc;
641
642   psc = priv->screenConfigs + screen;
643   psc->serverGLXexts =
644      __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
645
646   LockDisplay(dpy);
647
648   psc->configs = NULL;
649   if (atof(priv->serverGLXversion) >= 1.3) {
650      GetReq(GLXGetFBConfigs, fb_req);
651      fb_req->reqType = priv->majorOpcode;
652      fb_req->glxCode = X_GLXGetFBConfigs;
653      fb_req->screen = screen;
654   }
655   else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
656      GetReqExtra(GLXVendorPrivateWithReply,
657                  sz_xGLXGetFBConfigsSGIXReq +
658                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
659      sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
660      sgi_req->reqType = priv->majorOpcode;
661      sgi_req->glxCode = X_GLXVendorPrivateWithReply;
662      sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
663      sgi_req->screen = screen;
664   }
665   else
666      goto out;
667
668   if (!_XReply(dpy, (xReply *) & reply, 0, False))
669      goto out;
670
671   psc->configs = createConfigsFromProperties(dpy,
672                                              reply.numFBConfigs,
673                                              reply.numAttribs * 2,
674                                              screen, GL_TRUE);
675
676 out:
677   UnlockDisplay(dpy);
678   return psc->configs != NULL;
679}
680
681/*
682** Allocate the memory for the per screen configs for each screen.
683** If that works then fetch the per screen configs data.
684*/
685static Bool
686AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
687{
688   __GLXscreenConfigs *psc;
689   GLint i, screens;
690
691   /*
692    ** First allocate memory for the array of per screen configs.
693    */
694   screens = ScreenCount(dpy);
695   psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs));
696   if (!psc) {
697      return GL_FALSE;
698   }
699   memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
700   priv->screenConfigs = psc;
701
702   priv->serverGLXversion =
703      __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
704   if (priv->serverGLXversion == NULL) {
705      FreeScreenConfigs(priv);
706      return GL_FALSE;
707   }
708
709   for (i = 0; i < screens; i++, psc++) {
710      getVisualConfigs(dpy, priv, i);
711      getFBConfigs(dpy, priv, i);
712
713#ifdef GLX_DIRECT_RENDERING
714      psc->scr = i;
715      psc->dpy = dpy;
716      psc->drawHash = __glxHashCreate();
717      if (psc->drawHash == NULL)
718         continue;
719
720      /* Initialize per screen dynamic client GLX extensions */
721      psc->ext_list_first_time = GL_TRUE;
722
723      if (priv->dri2Display)
724         psc->driScreen = (*priv->dri2Display->createScreen) (psc, i, priv);
725
726      if (psc->driScreen == NULL && priv->driDisplay)
727         psc->driScreen = (*priv->driDisplay->createScreen) (psc, i, priv);
728
729      if (psc->driScreen == NULL && priv->driswDisplay)
730         psc->driScreen = (*priv->driswDisplay->createScreen) (psc, i, priv);
731
732      if (psc->driScreen == NULL) {
733         __glxHashDestroy(psc->drawHash);
734         psc->drawHash = NULL;
735      }
736#endif
737   }
738   SyncHandle();
739   return GL_TRUE;
740}
741
742/*
743** Initialize the client side extension code.
744*/
745_X_HIDDEN __GLXdisplayPrivate *
746__glXInitialize(Display * dpy)
747{
748   XExtDisplayInfo *info = __glXFindDisplay(dpy);
749   XExtData **privList, *private, *found;
750   __GLXdisplayPrivate *dpyPriv;
751   XEDataObject dataObj;
752   int major, minor;
753#ifdef GLX_DIRECT_RENDERING
754   Bool glx_direct, glx_accel;
755#endif
756
757   /* The one and only long long lock */
758   __glXLock();
759
760   if (!XextHasExtension(info)) {
761      /* No GLX extension supported by this server. Oh well. */
762      __glXUnlock();
763      XMissingExtension(dpy, __glXExtensionName);
764      return 0;
765   }
766
767   /* See if a display private already exists.  If so, return it */
768   dataObj.display = dpy;
769   privList = XEHeadOfExtensionList(dataObj);
770   found = XFindOnExtensionList(privList, info->codes->extension);
771   if (found) {
772      __glXUnlock();
773      return (__GLXdisplayPrivate *) found->private_data;
774   }
775
776   /* See if the versions are compatible */
777   if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) {
778      /* The client and server do not agree on versions.  Punt. */
779      __glXUnlock();
780      return 0;
781   }
782
783   /*
784    ** Allocate memory for all the pieces needed for this buffer.
785    */
786   private = (XExtData *) Xmalloc(sizeof(XExtData));
787   if (!private) {
788      __glXUnlock();
789      return 0;
790   }
791   dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate));
792   if (!dpyPriv) {
793      __glXUnlock();
794      Xfree((char *) private);
795      return 0;
796   }
797
798   /*
799    ** Init the display private and then read in the screen config
800    ** structures from the server.
801    */
802   dpyPriv->majorOpcode = info->codes->major_opcode;
803   dpyPriv->majorVersion = major;
804   dpyPriv->minorVersion = minor;
805   dpyPriv->dpy = dpy;
806
807   dpyPriv->serverGLXvendor = 0x0;
808   dpyPriv->serverGLXversion = 0x0;
809
810#ifdef GLX_DIRECT_RENDERING
811   glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL);
812   glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
813
814   /*
815    ** Initialize the direct rendering per display data and functions.
816    ** Note: This _must_ be done before calling any other DRI routines
817    ** (e.g., those called in AllocAndFetchScreenConfigs).
818    */
819   if (glx_direct && glx_accel) {
820      dpyPriv->dri2Display = dri2CreateDisplay(dpy);
821      dpyPriv->driDisplay = driCreateDisplay(dpy);
822   }
823   if (glx_direct)
824      dpyPriv->driswDisplay = driswCreateDisplay(dpy);
825#endif
826
827   if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
828      __glXUnlock();
829      Xfree((char *) dpyPriv);
830      Xfree((char *) private);
831      return 0;
832   }
833
834   /*
835    ** Fill in the private structure.  This is the actual structure that
836    ** hangs off of the Display structure.  Our private structure is
837    ** referred to by this structure.  Got that?
838    */
839   private->number = info->codes->extension;
840   private->next = 0;
841   private->free_private = __glXFreeDisplayPrivate;
842   private->private_data = (char *) dpyPriv;
843   XAddToExtensionList(privList, private);
844
845   if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1) {
846      __glXClientInfo(dpy, dpyPriv->majorOpcode);
847   }
848   __glXUnlock();
849
850   return dpyPriv;
851}
852
853/*
854** Setup for sending a GLX command on dpy.  Make sure the extension is
855** initialized.  Try to avoid calling __glXInitialize as its kinda slow.
856*/
857_X_HIDDEN CARD8
858__glXSetupForCommand(Display * dpy)
859{
860   GLXContext gc;
861   __GLXdisplayPrivate *priv;
862
863   /* If this thread has a current context, flush its rendering commands */
864   gc = __glXGetCurrentContext();
865   if (gc->currentDpy) {
866      /* Flush rendering buffer of the current context, if any */
867      (void) __glXFlushRenderBuffer(gc, gc->pc);
868
869      if (gc->currentDpy == dpy) {
870         /* Use opcode from gc because its right */
871         return gc->majorOpcode;
872      }
873      else {
874         /*
875          ** Have to get info about argument dpy because it might be to
876          ** a different server
877          */
878      }
879   }
880
881   /* Forced to lookup extension via the slow initialize route */
882   priv = __glXInitialize(dpy);
883   if (!priv) {
884      return 0;
885   }
886   return priv->majorOpcode;
887}
888
889/**
890 * Flush the drawing command transport buffer.
891 *
892 * \param ctx  Context whose transport buffer is to be flushed.
893 * \param pc   Pointer to first unused buffer location.
894 *
895 * \todo
896 * Modify this function to use \c ctx->pc instead of the explicit
897 * \c pc parameter.
898 */
899_X_HIDDEN GLubyte *
900__glXFlushRenderBuffer(__GLXcontext * ctx, GLubyte * pc)
901{
902   Display *const dpy = ctx->currentDpy;
903#ifdef USE_XCB
904   xcb_connection_t *c = XGetXCBConnection(dpy);
905#else
906   xGLXRenderReq *req;
907#endif /* USE_XCB */
908   const GLint size = pc - ctx->buf;
909
910   if ((dpy != NULL) && (size > 0)) {
911#ifdef USE_XCB
912      xcb_glx_render(c, ctx->currentContextTag, size,
913                     (const uint8_t *) ctx->buf);
914#else
915      /* Send the entire buffer as an X request */
916      LockDisplay(dpy);
917      GetReq(GLXRender, req);
918      req->reqType = ctx->majorOpcode;
919      req->glxCode = X_GLXRender;
920      req->contextTag = ctx->currentContextTag;
921      req->length += (size + 3) >> 2;
922      _XSend(dpy, (char *) ctx->buf, size);
923      UnlockDisplay(dpy);
924      SyncHandle();
925#endif
926   }
927
928   /* Reset pointer and return it */
929   ctx->pc = ctx->buf;
930   return ctx->pc;
931}
932
933
934/**
935 * Send a portion of a GLXRenderLarge command to the server.  The advantage of
936 * this function over \c __glXSendLargeCommand is that callers can use the
937 * data buffer in the GLX context and may be able to avoid allocating an
938 * extra buffer.  The disadvantage is the clients will have to do more
939 * GLX protocol work (i.e., calculating \c totalRequests, etc.).
940 *
941 * \sa __glXSendLargeCommand
942 *
943 * \param gc             GLX context
944 * \param requestNumber  Which part of the whole command is this?  The first
945 *                       request is 1.
946 * \param totalRequests  How many requests will there be?
947 * \param data           Command data.
948 * \param dataLen        Size, in bytes, of the command data.
949 */
950_X_HIDDEN void
951__glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber,
952                    GLint totalRequests, const GLvoid * data, GLint dataLen)
953{
954   Display *dpy = gc->currentDpy;
955#ifdef USE_XCB
956   xcb_connection_t *c = XGetXCBConnection(dpy);
957   xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
958                        totalRequests, dataLen, data);
959#else
960   xGLXRenderLargeReq *req;
961
962   if (requestNumber == 1) {
963      LockDisplay(dpy);
964   }
965
966   GetReq(GLXRenderLarge, req);
967   req->reqType = gc->majorOpcode;
968   req->glxCode = X_GLXRenderLarge;
969   req->contextTag = gc->currentContextTag;
970   req->length += (dataLen + 3) >> 2;
971   req->requestNumber = requestNumber;
972   req->requestTotal = totalRequests;
973   req->dataBytes = dataLen;
974   Data(dpy, data, dataLen);
975
976   if (requestNumber == totalRequests) {
977      UnlockDisplay(dpy);
978      SyncHandle();
979   }
980#endif /* USE_XCB */
981}
982
983
984/**
985 * Send a command that is too large for the GLXRender protocol request.
986 *
987 * Send a large command, one that is too large for some reason to
988 * send using the GLXRender protocol request.  One reason to send
989 * a large command is to avoid copying the data.
990 *
991 * \param ctx        GLX context
992 * \param header     Header data.
993 * \param headerLen  Size, in bytes, of the header data.  It is assumed that
994 *                   the header data will always be small enough to fit in
995 *                   a single X protocol packet.
996 * \param data       Command data.
997 * \param dataLen    Size, in bytes, of the command data.
998 */
999_X_HIDDEN void
1000__glXSendLargeCommand(__GLXcontext * ctx,
1001                      const GLvoid * header, GLint headerLen,
1002                      const GLvoid * data, GLint dataLen)
1003{
1004   GLint maxSize;
1005   GLint totalRequests, requestNumber;
1006
1007   /*
1008    ** Calculate the maximum amount of data can be stuffed into a single
1009    ** packet.  sz_xGLXRenderReq is added because bufSize is the maximum
1010    ** packet size minus sz_xGLXRenderReq.
1011    */
1012   maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
1013   totalRequests = 1 + (dataLen / maxSize);
1014   if (dataLen % maxSize)
1015      totalRequests++;
1016
1017   /*
1018    ** Send all of the command, except the large array, as one request.
1019    */
1020   assert(headerLen <= maxSize);
1021   __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
1022
1023   /*
1024    ** Send enough requests until the whole array is sent.
1025    */
1026   for (requestNumber = 2; requestNumber <= (totalRequests - 1);
1027        requestNumber++) {
1028      __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
1029      data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
1030      dataLen -= maxSize;
1031      assert(dataLen > 0);
1032   }
1033
1034   assert(dataLen <= maxSize);
1035   __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
1036}
1037
1038/************************************************************************/
1039
1040#ifdef DEBUG
1041_X_HIDDEN void
1042__glXDumpDrawBuffer(__GLXcontext * ctx)
1043{
1044   GLubyte *p = ctx->buf;
1045   GLubyte *end = ctx->pc;
1046   GLushort opcode, length;
1047
1048   while (p < end) {
1049      /* Fetch opcode */
1050      opcode = *((GLushort *) p);
1051      length = *((GLushort *) (p + 2));
1052      printf("%2x: %5d: ", opcode, length);
1053      length -= 4;
1054      p += 4;
1055      while (length > 0) {
1056         printf("%08x ", *((unsigned *) p));
1057         p += 4;
1058         length -= 4;
1059      }
1060      printf("\n");
1061   }
1062}
1063#endif
1064