glxext.c revision ad7d36e91933a49ce3f6ed2c14ae585a8a84fdf5
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         /* Ignore the unrecognized tag's value */
543         bp++;
544         break;
545      }
546   }
547
548   config->renderType =
549      (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
550
551   config->haveAccumBuffer = ((config->accumRedBits +
552                               config->accumGreenBits +
553                               config->accumBlueBits +
554                               config->accumAlphaBits) > 0);
555   config->haveDepthBuffer = (config->depthBits > 0);
556   config->haveStencilBuffer = (config->stencilBits > 0);
557}
558
559static __GLcontextModes *
560createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
561                            int screen, GLboolean tagged_only)
562{
563   INT32 buf[__GLX_TOTAL_CONFIG], *props;
564   unsigned prop_size;
565   __GLcontextModes *modes, *m;
566   int i;
567
568   if (nprops == 0)
569      return NULL;
570
571   /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
572
573   /* Check number of properties */
574   if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
575      return NULL;
576
577   /* Allocate memory for our config structure */
578   modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes));
579   if (!modes)
580      return NULL;
581
582   prop_size = nprops * __GLX_SIZE_INT32;
583   if (prop_size <= sizeof(buf))
584      props = buf;
585   else
586      props = Xmalloc(prop_size);
587
588   /* Read each config structure and convert it into our format */
589   m = modes;
590   for (i = 0; i < nvisuals; i++) {
591      _XRead(dpy, (char *) props, prop_size);
592      /* Older X servers don't send this so we default it here. */
593      m->drawableType = GLX_WINDOW_BIT;
594      __glXInitializeVisualConfigFromTags(m, nprops, props,
595                                          tagged_only, GL_TRUE);
596      m->screen = screen;
597      m = m->next;
598   }
599
600   if (props != buf)
601      Xfree(props);
602
603   return modes;
604}
605
606static GLboolean
607getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
608{
609   xGLXGetVisualConfigsReq *req;
610   __GLXscreenConfigs *psc;
611   xGLXGetVisualConfigsReply reply;
612
613   LockDisplay(dpy);
614
615   psc = priv->screenConfigs + screen;
616   psc->visuals = NULL;
617   GetReq(GLXGetVisualConfigs, req);
618   req->reqType = priv->majorOpcode;
619   req->glxCode = X_GLXGetVisualConfigs;
620   req->screen = screen;
621
622   if (!_XReply(dpy, (xReply *) & reply, 0, False))
623      goto out;
624
625   psc->visuals = createConfigsFromProperties(dpy,
626                                              reply.numVisuals,
627                                              reply.numProps,
628                                              screen, GL_FALSE);
629
630 out:
631   UnlockDisplay(dpy);
632   return psc->visuals != NULL;
633}
634
635static GLboolean
636getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
637{
638   xGLXGetFBConfigsReq *fb_req;
639   xGLXGetFBConfigsSGIXReq *sgi_req;
640   xGLXVendorPrivateWithReplyReq *vpreq;
641   xGLXGetFBConfigsReply reply;
642   __GLXscreenConfigs *psc;
643
644   psc = priv->screenConfigs + screen;
645   psc->serverGLXexts =
646      __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
647
648   LockDisplay(dpy);
649
650   psc->configs = NULL;
651   if (atof(priv->serverGLXversion) >= 1.3) {
652      GetReq(GLXGetFBConfigs, fb_req);
653      fb_req->reqType = priv->majorOpcode;
654      fb_req->glxCode = X_GLXGetFBConfigs;
655      fb_req->screen = screen;
656   }
657   else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
658      GetReqExtra(GLXVendorPrivateWithReply,
659                  sz_xGLXGetFBConfigsSGIXReq +
660                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
661      sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
662      sgi_req->reqType = priv->majorOpcode;
663      sgi_req->glxCode = X_GLXVendorPrivateWithReply;
664      sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
665      sgi_req->screen = screen;
666   }
667   else
668      goto out;
669
670   if (!_XReply(dpy, (xReply *) & reply, 0, False))
671      goto out;
672
673   psc->configs = createConfigsFromProperties(dpy,
674                                              reply.numFBConfigs,
675                                              reply.numAttribs * 2,
676                                              screen, GL_TRUE);
677
678 out:
679   UnlockDisplay(dpy);
680   return psc->configs != NULL;
681}
682
683/*
684** Allocate the memory for the per screen configs for each screen.
685** If that works then fetch the per screen configs data.
686*/
687static Bool
688AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
689{
690   __GLXscreenConfigs *psc;
691   GLint i, screens;
692
693   /*
694    ** First allocate memory for the array of per screen configs.
695    */
696   screens = ScreenCount(dpy);
697   psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs));
698   if (!psc) {
699      return GL_FALSE;
700   }
701   memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
702   priv->screenConfigs = psc;
703
704   priv->serverGLXversion =
705      __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
706   if (priv->serverGLXversion == NULL) {
707      FreeScreenConfigs(priv);
708      return GL_FALSE;
709   }
710
711   for (i = 0; i < screens; i++, psc++) {
712      getVisualConfigs(dpy, priv, i);
713      getFBConfigs(dpy, priv, i);
714
715#ifdef GLX_DIRECT_RENDERING
716      psc->scr = i;
717      psc->dpy = dpy;
718      psc->drawHash = __glxHashCreate();
719      if (psc->drawHash == NULL)
720         continue;
721
722      /* Initialize per screen dynamic client GLX extensions */
723      psc->ext_list_first_time = GL_TRUE;
724
725      if (priv->dri2Display)
726         psc->driScreen = (*priv->dri2Display->createScreen) (psc, i, priv);
727
728      if (psc->driScreen == NULL && priv->driDisplay)
729         psc->driScreen = (*priv->driDisplay->createScreen) (psc, i, priv);
730
731      if (psc->driScreen == NULL && priv->driswDisplay)
732         psc->driScreen = (*priv->driswDisplay->createScreen) (psc, i, priv);
733
734      if (psc->driScreen == NULL) {
735         __glxHashDestroy(psc->drawHash);
736         psc->drawHash = NULL;
737      }
738#endif
739   }
740   SyncHandle();
741   return GL_TRUE;
742}
743
744/*
745** Initialize the client side extension code.
746*/
747_X_HIDDEN __GLXdisplayPrivate *
748__glXInitialize(Display * dpy)
749{
750   XExtDisplayInfo *info = __glXFindDisplay(dpy);
751   XExtData **privList, *private, *found;
752   __GLXdisplayPrivate *dpyPriv;
753   XEDataObject dataObj;
754   int major, minor;
755#ifdef GLX_DIRECT_RENDERING
756   Bool glx_direct, glx_accel;
757#endif
758
759   /* The one and only long long lock */
760   __glXLock();
761
762   if (!XextHasExtension(info)) {
763      /* No GLX extension supported by this server. Oh well. */
764      __glXUnlock();
765      XMissingExtension(dpy, __glXExtensionName);
766      return 0;
767   }
768
769   /* See if a display private already exists.  If so, return it */
770   dataObj.display = dpy;
771   privList = XEHeadOfExtensionList(dataObj);
772   found = XFindOnExtensionList(privList, info->codes->extension);
773   if (found) {
774      __glXUnlock();
775      return (__GLXdisplayPrivate *) found->private_data;
776   }
777
778   /* See if the versions are compatible */
779   if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) {
780      /* The client and server do not agree on versions.  Punt. */
781      __glXUnlock();
782      return 0;
783   }
784
785   /*
786    ** Allocate memory for all the pieces needed for this buffer.
787    */
788   private = (XExtData *) Xmalloc(sizeof(XExtData));
789   if (!private) {
790      __glXUnlock();
791      return 0;
792   }
793   dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate));
794   if (!dpyPriv) {
795      __glXUnlock();
796      Xfree((char *) private);
797      return 0;
798   }
799
800   /*
801    ** Init the display private and then read in the screen config
802    ** structures from the server.
803    */
804   dpyPriv->majorOpcode = info->codes->major_opcode;
805   dpyPriv->majorVersion = major;
806   dpyPriv->minorVersion = minor;
807   dpyPriv->dpy = dpy;
808
809   dpyPriv->serverGLXvendor = 0x0;
810   dpyPriv->serverGLXversion = 0x0;
811
812#ifdef GLX_DIRECT_RENDERING
813   glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL);
814   glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
815
816   /*
817    ** Initialize the direct rendering per display data and functions.
818    ** Note: This _must_ be done before calling any other DRI routines
819    ** (e.g., those called in AllocAndFetchScreenConfigs).
820    */
821   if (glx_direct && glx_accel) {
822      dpyPriv->dri2Display = dri2CreateDisplay(dpy);
823      dpyPriv->driDisplay = driCreateDisplay(dpy);
824   }
825   if (glx_direct)
826      dpyPriv->driswDisplay = driswCreateDisplay(dpy);
827#endif
828
829   if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
830      __glXUnlock();
831      Xfree((char *) dpyPriv);
832      Xfree((char *) private);
833      return 0;
834   }
835
836   /*
837    ** Fill in the private structure.  This is the actual structure that
838    ** hangs off of the Display structure.  Our private structure is
839    ** referred to by this structure.  Got that?
840    */
841   private->number = info->codes->extension;
842   private->next = 0;
843   private->free_private = __glXFreeDisplayPrivate;
844   private->private_data = (char *) dpyPriv;
845   XAddToExtensionList(privList, private);
846
847   if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1) {
848      __glXClientInfo(dpy, dpyPriv->majorOpcode);
849   }
850   __glXUnlock();
851
852   return dpyPriv;
853}
854
855/*
856** Setup for sending a GLX command on dpy.  Make sure the extension is
857** initialized.  Try to avoid calling __glXInitialize as its kinda slow.
858*/
859_X_HIDDEN CARD8
860__glXSetupForCommand(Display * dpy)
861{
862   GLXContext gc;
863   __GLXdisplayPrivate *priv;
864
865   /* If this thread has a current context, flush its rendering commands */
866   gc = __glXGetCurrentContext();
867   if (gc->currentDpy) {
868      /* Flush rendering buffer of the current context, if any */
869      (void) __glXFlushRenderBuffer(gc, gc->pc);
870
871      if (gc->currentDpy == dpy) {
872         /* Use opcode from gc because its right */
873         return gc->majorOpcode;
874      }
875      else {
876         /*
877          ** Have to get info about argument dpy because it might be to
878          ** a different server
879          */
880      }
881   }
882
883   /* Forced to lookup extension via the slow initialize route */
884   priv = __glXInitialize(dpy);
885   if (!priv) {
886      return 0;
887   }
888   return priv->majorOpcode;
889}
890
891/**
892 * Flush the drawing command transport buffer.
893 *
894 * \param ctx  Context whose transport buffer is to be flushed.
895 * \param pc   Pointer to first unused buffer location.
896 *
897 * \todo
898 * Modify this function to use \c ctx->pc instead of the explicit
899 * \c pc parameter.
900 */
901_X_HIDDEN GLubyte *
902__glXFlushRenderBuffer(__GLXcontext * ctx, GLubyte * pc)
903{
904   Display *const dpy = ctx->currentDpy;
905#ifdef USE_XCB
906   xcb_connection_t *c = XGetXCBConnection(dpy);
907#else
908   xGLXRenderReq *req;
909#endif /* USE_XCB */
910   const GLint size = pc - ctx->buf;
911
912   if ((dpy != NULL) && (size > 0)) {
913#ifdef USE_XCB
914      xcb_glx_render(c, ctx->currentContextTag, size,
915                     (const uint8_t *) ctx->buf);
916#else
917      /* Send the entire buffer as an X request */
918      LockDisplay(dpy);
919      GetReq(GLXRender, req);
920      req->reqType = ctx->majorOpcode;
921      req->glxCode = X_GLXRender;
922      req->contextTag = ctx->currentContextTag;
923      req->length += (size + 3) >> 2;
924      _XSend(dpy, (char *) ctx->buf, size);
925      UnlockDisplay(dpy);
926      SyncHandle();
927#endif
928   }
929
930   /* Reset pointer and return it */
931   ctx->pc = ctx->buf;
932   return ctx->pc;
933}
934
935
936/**
937 * Send a portion of a GLXRenderLarge command to the server.  The advantage of
938 * this function over \c __glXSendLargeCommand is that callers can use the
939 * data buffer in the GLX context and may be able to avoid allocating an
940 * extra buffer.  The disadvantage is the clients will have to do more
941 * GLX protocol work (i.e., calculating \c totalRequests, etc.).
942 *
943 * \sa __glXSendLargeCommand
944 *
945 * \param gc             GLX context
946 * \param requestNumber  Which part of the whole command is this?  The first
947 *                       request is 1.
948 * \param totalRequests  How many requests will there be?
949 * \param data           Command data.
950 * \param dataLen        Size, in bytes, of the command data.
951 */
952_X_HIDDEN void
953__glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber,
954                    GLint totalRequests, const GLvoid * data, GLint dataLen)
955{
956   Display *dpy = gc->currentDpy;
957#ifdef USE_XCB
958   xcb_connection_t *c = XGetXCBConnection(dpy);
959   xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
960                        totalRequests, dataLen, data);
961#else
962   xGLXRenderLargeReq *req;
963
964   if (requestNumber == 1) {
965      LockDisplay(dpy);
966   }
967
968   GetReq(GLXRenderLarge, req);
969   req->reqType = gc->majorOpcode;
970   req->glxCode = X_GLXRenderLarge;
971   req->contextTag = gc->currentContextTag;
972   req->length += (dataLen + 3) >> 2;
973   req->requestNumber = requestNumber;
974   req->requestTotal = totalRequests;
975   req->dataBytes = dataLen;
976   Data(dpy, data, dataLen);
977
978   if (requestNumber == totalRequests) {
979      UnlockDisplay(dpy);
980      SyncHandle();
981   }
982#endif /* USE_XCB */
983}
984
985
986/**
987 * Send a command that is too large for the GLXRender protocol request.
988 *
989 * Send a large command, one that is too large for some reason to
990 * send using the GLXRender protocol request.  One reason to send
991 * a large command is to avoid copying the data.
992 *
993 * \param ctx        GLX context
994 * \param header     Header data.
995 * \param headerLen  Size, in bytes, of the header data.  It is assumed that
996 *                   the header data will always be small enough to fit in
997 *                   a single X protocol packet.
998 * \param data       Command data.
999 * \param dataLen    Size, in bytes, of the command data.
1000 */
1001_X_HIDDEN void
1002__glXSendLargeCommand(__GLXcontext * ctx,
1003                      const GLvoid * header, GLint headerLen,
1004                      const GLvoid * data, GLint dataLen)
1005{
1006   GLint maxSize;
1007   GLint totalRequests, requestNumber;
1008
1009   /*
1010    ** Calculate the maximum amount of data can be stuffed into a single
1011    ** packet.  sz_xGLXRenderReq is added because bufSize is the maximum
1012    ** packet size minus sz_xGLXRenderReq.
1013    */
1014   maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
1015   totalRequests = 1 + (dataLen / maxSize);
1016   if (dataLen % maxSize)
1017      totalRequests++;
1018
1019   /*
1020    ** Send all of the command, except the large array, as one request.
1021    */
1022   assert(headerLen <= maxSize);
1023   __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
1024
1025   /*
1026    ** Send enough requests until the whole array is sent.
1027    */
1028   for (requestNumber = 2; requestNumber <= (totalRequests - 1);
1029        requestNumber++) {
1030      __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
1031      data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
1032      dataLen -= maxSize;
1033      assert(dataLen > 0);
1034   }
1035
1036   assert(dataLen <= maxSize);
1037   __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
1038}
1039
1040/************************************************************************/
1041
1042#ifdef DEBUG
1043_X_HIDDEN void
1044__glXDumpDrawBuffer(__GLXcontext * ctx)
1045{
1046   GLubyte *p = ctx->buf;
1047   GLubyte *end = ctx->pc;
1048   GLushort opcode, length;
1049
1050   while (p < end) {
1051      /* Fetch opcode */
1052      opcode = *((GLushort *) p);
1053      length = *((GLushort *) (p + 2));
1054      printf("%2x: %5d: ", opcode, length);
1055      length -= 4;
1056      p += 4;
1057      while (length > 0) {
1058         printf("%08x ", *((unsigned *) p));
1059         p += 4;
1060         length -= 4;
1061      }
1062      printf("\n");
1063   }
1064}
1065#endif
1066