glxcmds.c revision a18702f067d060ca9d56e9fcd5d2cd1a5093177f
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 glxcmds.c
33 * Client-side GLX interface.
34 */
35
36#include "glxclient.h"
37#include "glapi.h"
38#include "glxextensions.h"
39#include "glcontextmodes.h"
40
41#ifdef GLX_DIRECT_RENDERING
42#ifdef GLX_USE_APPLEGL
43#include "apple_glx_context.h"
44#include "apple_glx.h"
45#include "glx_error.h"
46#define GC_IS_DIRECT(gc) ((gc)->isDirect)
47#else
48#include <sys/time.h>
49#include <X11/extensions/xf86vmode.h>
50#include "xf86dri.h"
51#define GC_IS_DIRECT(gc) ((gc)->driContext != NULL)
52#endif
53#else
54#define GC_IS_DIRECT(gc) (0)
55#endif
56
57#if defined(USE_XCB)
58#include <X11/Xlib-xcb.h>
59#include <xcb/xcb.h>
60#include <xcb/glx.h>
61#endif
62
63static const char __glXGLXClientVendorName[] = "Mesa Project and SGI";
64static const char __glXGLXClientVersion[] = "1.4";
65
66
67/****************************************************************************/
68
69#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
70
71static Bool windowExistsFlag;
72static int
73windowExistsErrorHandler(Display * dpy, XErrorEvent * xerr)
74{
75   (void) dpy;
76
77   if (xerr->error_code == BadWindow) {
78      windowExistsFlag = GL_FALSE;
79   }
80   return 0;
81}
82
83/**
84 * Find drawables in the local hash that have been destroyed on the
85 * server.
86 *
87 * \param dpy    Display to destroy drawables for
88 * \param screen Screen number to destroy drawables for
89 */
90static void
91GarbageCollectDRIDrawables(Display * dpy, __GLXscreenConfigs * sc)
92{
93   XID draw;
94   __GLXDRIdrawable *pdraw;
95   XWindowAttributes xwa;
96   int (*oldXErrorHandler) (Display *, XErrorEvent *);
97
98   /* Set no-op error handler so Xlib doesn't bail out if the windows
99    * has alreay been destroyed on the server. */
100   XSync(dpy, GL_FALSE);
101   oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
102
103   if (__glxHashFirst(sc->drawHash, &draw, (void *) &pdraw) == 1) {
104      do {
105         windowExistsFlag = GL_TRUE;
106         XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
107         if (!windowExistsFlag) {
108            /* Destroy the local drawable data, if the drawable no
109               longer exists in the Xserver */
110            (*pdraw->destroyDrawable) (pdraw);
111            __glxHashDelete(sc->drawHash, draw);
112         }
113      } while (__glxHashNext(sc->drawHash, &draw, (void *) &pdraw) == 1);
114   }
115
116   XSync(dpy, GL_FALSE);
117   XSetErrorHandler(oldXErrorHandler);
118}
119
120/**
121 * Get the __DRIdrawable for the drawable associated with a GLXContext
122 *
123 * \param dpy       The display associated with \c drawable.
124 * \param drawable  GLXDrawable whose __DRIdrawable part is to be retrieved.
125 * \param scrn_num  If non-NULL, the drawables screen is stored there
126 * \returns  A pointer to the context's __DRIdrawable on success, or NULL if
127 *           the drawable is not associated with a direct-rendering context.
128 */
129_X_HIDDEN __GLXDRIdrawable *
130GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable, int *const scrn_num)
131{
132   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
133   __GLXDRIdrawable *pdraw;
134   const unsigned screen_count = ScreenCount(dpy);
135   unsigned i;
136   __GLXscreenConfigs *psc;
137
138   if (priv == NULL)
139      return NULL;
140
141   for (i = 0; i < screen_count; i++) {
142      psc = &priv->screenConfigs[i];
143      if (psc->drawHash == NULL)
144         continue;
145
146      if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) {
147         if (scrn_num != NULL)
148            *scrn_num = i;
149         return pdraw;
150      }
151   }
152
153   return NULL;
154}
155
156#endif
157
158
159/**
160 * Get the GLX per-screen data structure associated with a GLX context.
161 *
162 * \param dpy   Display for which the GLX per-screen information is to be
163 *              retrieved.
164 * \param scrn  Screen on \c dpy for which the GLX per-screen information is
165 *              to be retrieved.
166 * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
167 *          specify a valid GLX screen, or NULL otherwise.
168 *
169 * \todo Should this function validate that \c scrn is within the screen
170 *       number range for \c dpy?
171 */
172
173static __GLXscreenConfigs *
174GetGLXScreenConfigs(Display * dpy, int scrn)
175{
176   __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
177
178   return (priv
179           && priv->screenConfigs !=
180           NULL) ? &priv->screenConfigs[scrn] : NULL;
181}
182
183
184static int
185GetGLXPrivScreenConfig(Display * dpy, int scrn, __GLXdisplayPrivate ** ppriv,
186                       __GLXscreenConfigs ** ppsc)
187{
188   /* Initialize the extension, if needed .  This has the added value
189    * of initializing/allocating the display private
190    */
191
192   if (dpy == NULL) {
193      return GLX_NO_EXTENSION;
194   }
195
196   *ppriv = __glXInitialize(dpy);
197   if (*ppriv == NULL) {
198      return GLX_NO_EXTENSION;
199   }
200
201   /* Check screen number to see if its valid */
202   if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
203      return GLX_BAD_SCREEN;
204   }
205
206   /* Check to see if the GL is supported on this screen */
207   *ppsc = &((*ppriv)->screenConfigs[scrn]);
208   if ((*ppsc)->configs == NULL) {
209      /* No support for GL on this screen regardless of visual */
210      return GLX_BAD_VISUAL;
211   }
212
213   return Success;
214}
215
216
217/**
218 * Determine if a \c GLXFBConfig supplied by the application is valid.
219 *
220 * \param dpy     Application supplied \c Display pointer.
221 * \param config  Application supplied \c GLXFBConfig.
222 *
223 * \returns If the \c GLXFBConfig is valid, the a pointer to the matching
224 *          \c __GLcontextModes structure is returned.  Otherwise, \c NULL
225 *          is returned.
226 */
227static __GLcontextModes *
228ValidateGLXFBConfig(Display * dpy, GLXFBConfig config)
229{
230   __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
231   const unsigned num_screens = ScreenCount(dpy);
232   unsigned i;
233   const __GLcontextModes *modes;
234
235
236   if (priv != NULL) {
237      for (i = 0; i < num_screens; i++) {
238         for (modes = priv->screenConfigs[i].configs; modes != NULL;
239              modes = modes->next) {
240            if (modes == (__GLcontextModes *) config) {
241               return (__GLcontextModes *) config;
242            }
243         }
244      }
245   }
246
247   return NULL;
248}
249
250
251/**
252 * \todo It should be possible to move the allocate of \c client_state_private
253 * later in the function for direct-rendering contexts.  Direct-rendering
254 * contexts don't need to track client state, so they don't need that memory
255 * at all.
256 *
257 * \todo Eliminate \c __glXInitVertexArrayState.  Replace it with a new
258 * function called \c __glXAllocateClientState that allocates the memory and
259 * does all the initialization (including the pixel pack / unpack).
260 */
261static GLXContext
262AllocateGLXContext(Display * dpy)
263{
264   GLXContext gc;
265   int bufSize;
266   CARD8 opcode;
267   __GLXattribute *state;
268
269   if (!dpy)
270      return NULL;
271
272   opcode = __glXSetupForCommand(dpy);
273   if (!opcode) {
274      return NULL;
275   }
276
277   /* Allocate our context record */
278   gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec));
279   if (!gc) {
280      /* Out of memory */
281      return NULL;
282   }
283   memset(gc, 0, sizeof(struct __GLXcontextRec));
284
285   state = Xmalloc(sizeof(struct __GLXattributeRec));
286   if (state == NULL) {
287      /* Out of memory */
288      Xfree(gc);
289      return NULL;
290   }
291   gc->client_state_private = state;
292   memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec));
293   state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
294
295   /*
296    ** Create a temporary buffer to hold GLX rendering commands.  The size
297    ** of the buffer is selected so that the maximum number of GLX rendering
298    ** commands can fit in a single X packet and still have room in the X
299    ** packet for the GLXRenderReq header.
300    */
301
302   bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;
303   gc->buf = (GLubyte *) Xmalloc(bufSize);
304   if (!gc->buf) {
305      Xfree(gc->client_state_private);
306      Xfree(gc);
307      return NULL;
308   }
309   gc->bufSize = bufSize;
310
311   /* Fill in the new context */
312   gc->renderMode = GL_RENDER;
313
314   state->storePack.alignment = 4;
315   state->storeUnpack.alignment = 4;
316
317   gc->attributes.stackPointer = &gc->attributes.stack[0];
318
319   /*
320    ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
321    ** Other code uses the fastImageUnpack bit, but it is never set
322    ** to GL_TRUE.
323    */
324   gc->fastImageUnpack = GL_FALSE;
325   gc->fillImage = __glFillImage;
326   gc->pc = gc->buf;
327   gc->bufEnd = gc->buf + bufSize;
328   gc->isDirect = GL_FALSE;
329   if (__glXDebug) {
330      /*
331       ** Set limit register so that there will be one command per packet
332       */
333      gc->limit = gc->buf;
334   }
335   else {
336      gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
337   }
338   gc->createDpy = dpy;
339   gc->majorOpcode = opcode;
340
341   /*
342    ** Constrain the maximum drawing command size allowed to be
343    ** transfered using the X_GLXRender protocol request.  First
344    ** constrain by a software limit, then constrain by the protocl
345    ** limit.
346    */
347   if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
348      bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
349   }
350   if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
351      bufSize = __GLX_MAX_RENDER_CMD_SIZE;
352   }
353   gc->maxSmallRenderCommandSize = bufSize;
354
355#ifdef GLX_USE_APPLEGL
356   gc->driContext = NULL;
357   gc->do_destroy = False;
358#endif
359
360   return gc;
361}
362
363
364/**
365 * Create a new context.  Exactly one of \c vis and \c fbconfig should be
366 * non-NULL.
367 *
368 * \param use_glx_1_3  For FBConfigs, should GLX 1.3 protocol or
369 *                     SGIX_fbconfig protocol be used?
370 * \param renderType   For FBConfigs, what is the rendering type?
371 */
372
373static GLXContext
374CreateContext(Display * dpy, int generic_id,
375              const __GLcontextModes * const fbconfig,
376              GLXContext shareList,
377              Bool allowDirect,
378	      unsigned code, int renderType, int screen)
379{
380   GLXContext gc;
381#ifdef GLX_DIRECT_RENDERING
382#ifdef GLX_USE_APPLEGL
383   int errorcode;
384   bool x11error;
385#else
386   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
387#endif
388#endif
389
390   if (dpy == NULL)
391      return NULL;
392
393   if (generic_id == None)
394      return NULL;
395
396   gc = AllocateGLXContext(dpy);
397   if (!gc)
398      return NULL;
399
400#ifndef GLX_USE_APPLEGL  /* TODO: darwin indirect */
401#ifdef GLX_DIRECT_RENDERING
402   if (allowDirect && psc->driScreen) {
403      gc->driContext = psc->driScreen->createContext(psc, fbconfig, gc,
404						     shareList, renderType);
405      if (gc->driContext != NULL) {
406	 gc->screen = screen;
407	 gc->psc = psc;
408	 gc->mode = fbconfig;
409	 gc->isDirect = GL_TRUE;
410      }
411   }
412#endif
413
414   LockDisplay(dpy);
415   switch (code) {
416   case X_GLXCreateContext: {
417      xGLXCreateContextReq *req;
418
419      /* Send the glXCreateContext request */
420      GetReq(GLXCreateContext, req);
421      req->reqType = gc->majorOpcode;
422      req->glxCode = X_GLXCreateContext;
423      req->context = gc->xid = XAllocID(dpy);
424      req->visual = generic_id;
425      req->screen = screen;
426      req->shareList = shareList ? shareList->xid : None;
427      req->isDirect = GC_IS_DIRECT(gc);
428      break;
429   }
430
431   case X_GLXCreateNewContext: {
432      xGLXCreateNewContextReq *req;
433
434      /* Send the glXCreateNewContext request */
435      GetReq(GLXCreateNewContext, req);
436      req->reqType = gc->majorOpcode;
437      req->glxCode = X_GLXCreateNewContext;
438      req->context = gc->xid = XAllocID(dpy);
439      req->fbconfig = generic_id;
440      req->screen = screen;
441      req->renderType = renderType;
442      req->shareList = shareList ? shareList->xid : None;
443      req->isDirect = GC_IS_DIRECT(gc);
444      break;
445   }
446
447   case X_GLXvop_CreateContextWithConfigSGIX: {
448      xGLXVendorPrivateWithReplyReq *vpreq;
449      xGLXCreateContextWithConfigSGIXReq *req;
450
451      /* Send the glXCreateNewContext request */
452      GetReqExtra(GLXVendorPrivateWithReply,
453		  sz_xGLXCreateContextWithConfigSGIXReq -
454		  sz_xGLXVendorPrivateWithReplyReq, vpreq);
455      req = (xGLXCreateContextWithConfigSGIXReq *) vpreq;
456      req->reqType = gc->majorOpcode;
457      req->glxCode = X_GLXVendorPrivateWithReply;
458      req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
459      req->context = gc->xid = XAllocID(dpy);
460      req->fbconfig = generic_id;
461      req->screen = screen;
462      req->renderType = renderType;
463      req->shareList = shareList ? shareList->xid : None;
464      req->isDirect = GC_IS_DIRECT(gc);
465      break;
466   }
467
468   default:
469      /* What to do here?  This case is the sign of an internal error.  It
470       * should never be reachable.
471       */
472      break;
473   }
474
475   UnlockDisplay(dpy);
476   SyncHandle();
477#endif
478
479   gc->imported = GL_FALSE;
480   gc->renderType = renderType;
481
482   /* TODO: darwin: Integrate with above to do indirect */
483#ifdef GLX_USE_APPLEGL
484   if(apple_glx_create_context(&gc->driContext, dpy, screen, fbconfig,
485                               shareList ? shareList->driContext : NULL,
486                               &errorcode, &x11error)) {
487      __glXSendError(dpy, errorcode, 0, X_GLXCreateContext, x11error);
488      __glXFreeContext(gc);
489      return NULL;
490   }
491
492   gc->currentContextTag = -1;
493   gc->mode = fbconfig;
494   gc->isDirect = allowDirect;
495#endif
496
497   return gc;
498}
499
500PUBLIC GLXContext
501glXCreateContext(Display * dpy, XVisualInfo * vis,
502                 GLXContext shareList, Bool allowDirect)
503{
504   const __GLcontextModes *mode = NULL;
505   int renderType = 0;
506
507#if defined(GLX_DIRECT_RENDERING) || defined(GLX_USE_APPLEGL)
508   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, vis->screen);
509
510   mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
511   if (mode == NULL) {
512      xError error;
513
514      error.errorCode = BadValue;
515      error.resourceID = vis->visualid;
516      error.sequenceNumber = dpy->request;
517      error.type = X_Error;
518      error.majorCode = __glXSetupForCommand(dpy);
519      error.minorCode = X_GLXCreateContext;
520      _XError(dpy, &error);
521      return None;
522   }
523
524   renderType = mode->rgbMode ? GLX_RGBA_TYPE : GLX_COLOR_INDEX_TYPE;
525#endif
526
527   return CreateContext(dpy, vis->visualid, mode, shareList, allowDirect,
528                        X_GLXCreateContext, renderType, vis->screen);
529}
530
531_X_HIDDEN void
532__glXFreeContext(__GLXcontext * gc)
533{
534   if (gc->vendor)
535      XFree((char *) gc->vendor);
536   if (gc->renderer)
537      XFree((char *) gc->renderer);
538   if (gc->version)
539      XFree((char *) gc->version);
540   if (gc->extensions)
541      XFree((char *) gc->extensions);
542   __glFreeAttributeState(gc);
543   XFree((char *) gc->buf);
544   Xfree((char *) gc->client_state_private);
545   XFree((char *) gc);
546
547}
548
549/*
550** Destroy the named context
551*/
552static void
553DestroyContext(Display * dpy, GLXContext gc)
554{
555#ifndef GLX_USE_APPLEGL /* TODO: darwin: indirect */
556   xGLXDestroyContextReq *req;
557   GLXContextID xid;
558   CARD8 opcode;
559   GLboolean imported;
560
561   opcode = __glXSetupForCommand(dpy);
562   if (!opcode || !gc) {
563      return;
564   }
565
566   __glXLock();
567   xid = gc->xid;
568   imported = gc->imported;
569   gc->xid = None;
570
571   if (gc->currentDpy) {
572      /* This context is bound to some thread.  According to the man page,
573       * we should not actually delete the context until it's unbound.
574       * Note that we set gc->xid = None above.  In MakeContextCurrent()
575       * we check for that and delete the context there.
576       */
577      __glXUnlock();
578      return;
579   }
580
581#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
582   /* Destroy the direct rendering context */
583   if (gc->driContext) {
584      (*gc->driContext->destroyContext) (gc->driContext, gc->psc, dpy);
585      gc->driContext = NULL;
586      GarbageCollectDRIDrawables(dpy, gc->psc);
587   }
588#endif
589
590   __glXFreeVertexArrayState(gc);
591#else
592   __glXLock();
593#endif /* GLX_USE_APPLEGL */
594
595   if (gc->currentDpy) {
596#ifdef GLX_USE_APPLEGL
597      /*
598       * Set the Bool that indicates that we should destroy this GLX context
599       * when the context is no longer current.
600       */
601      gc->do_destroy = True;
602#endif
603      /* Have to free later cuz it's in use now */
604      __glXUnlock();
605   }
606   else {
607      /* Destroy the handle if not current to anybody */
608      __glXUnlock();
609#ifdef GLX_USE_APPLEGL
610      if(gc->driContext)
611         apple_glx_destroy_context(&gc->driContext, dpy);
612#endif
613      __glXFreeContext(gc);
614   }
615#ifndef GLX_USE_APPLEGL
616   if (!imported) {
617      /*
618       ** This dpy also created the server side part of the context.
619       ** Send the glXDestroyContext request.
620       */
621      LockDisplay(dpy);
622      GetReq(GLXDestroyContext, req);
623      req->reqType = opcode;
624      req->glxCode = X_GLXDestroyContext;
625      req->context = xid;
626      UnlockDisplay(dpy);
627      SyncHandle();
628   }
629#endif
630}
631
632PUBLIC void
633glXDestroyContext(Display * dpy, GLXContext gc)
634{
635   DestroyContext(dpy, gc);
636}
637
638/*
639** Return the major and minor version #s for the GLX extension
640*/
641PUBLIC Bool
642glXQueryVersion(Display * dpy, int *major, int *minor)
643{
644   __GLXdisplayPrivate *priv;
645
646   /* Init the extension.  This fetches the major and minor version. */
647   priv = __glXInitialize(dpy);
648   if (!priv)
649      return GL_FALSE;
650
651   if (major)
652      *major = priv->majorVersion;
653   if (minor)
654      *minor = priv->minorVersion;
655   return GL_TRUE;
656}
657
658/*
659** Query the existance of the GLX extension
660*/
661PUBLIC Bool
662glXQueryExtension(Display * dpy, int *errorBase, int *eventBase)
663{
664   int major_op, erb, evb;
665   Bool rv;
666
667   rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
668   if (rv) {
669      if (errorBase)
670         *errorBase = erb;
671      if (eventBase)
672         *eventBase = evb;
673   }
674   return rv;
675}
676
677/*
678** Put a barrier in the token stream that forces the GL to finish its
679** work before X can proceed.
680*/
681PUBLIC void
682glXWaitGL(void)
683{
684#ifndef GLX_USE_APPLEGL
685   xGLXWaitGLReq *req;
686#endif
687   GLXContext gc = __glXGetCurrentContext();
688   Display *dpy = gc->currentDpy;
689
690   if (!dpy)
691      return;
692
693   /* Flush any pending commands out */
694   __glXFlushRenderBuffer(gc, gc->pc);
695#ifdef GLX_USE_APPLEGL
696   glFinish();
697#else
698#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
699   if (gc->driContext) {
700      int screen;
701      __GLXDRIdrawable *pdraw =
702         GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen);
703
704      if (pdraw != NULL) {
705         __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
706         glFlush();
707         if (psc->driScreen->waitGL != NULL)
708            (*psc->driScreen->waitGL) (pdraw);
709      }
710      return;
711   }
712#endif
713
714   /* Send the glXWaitGL request */
715   LockDisplay(dpy);
716   GetReq(GLXWaitGL, req);
717   req->reqType = gc->majorOpcode;
718   req->glxCode = X_GLXWaitGL;
719   req->contextTag = gc->currentContextTag;
720   UnlockDisplay(dpy);
721   SyncHandle();
722#endif /* GLX_USE_APPLEGL */
723}
724
725/*
726** Put a barrier in the token stream that forces X to finish its
727** work before GL can proceed.
728*/
729PUBLIC void
730glXWaitX(void)
731{
732#ifndef GLX_USE_APPLEGL
733   xGLXWaitXReq *req;
734#endif
735   GLXContext gc = __glXGetCurrentContext();
736   Display *dpy = gc->currentDpy;
737
738   if (!dpy)
739      return;
740
741   /* Flush any pending commands out */
742   __glXFlushRenderBuffer(gc, gc->pc);
743
744#ifdef GLX_USE_APPLEGL
745   apple_glx_waitx(dpy, gc->driContext);
746#else
747#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
748   if (gc->driContext) {
749      int screen;
750      __GLXDRIdrawable *pdraw =
751         GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen);
752
753      if (pdraw != NULL) {
754         __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
755         if (psc->driScreen->waitX != NULL)
756            (*psc->driScreen->waitX) (pdraw);
757      }
758      else
759         XSync(dpy, False);
760      return;
761   }
762#endif
763
764   /*
765    ** Send the glXWaitX request.
766    */
767   LockDisplay(dpy);
768   GetReq(GLXWaitX, req);
769   req->reqType = gc->majorOpcode;
770   req->glxCode = X_GLXWaitX;
771   req->contextTag = gc->currentContextTag;
772   UnlockDisplay(dpy);
773   SyncHandle();
774#endif /* GLX_USE_APPLEGL */
775}
776
777PUBLIC void
778glXUseXFont(Font font, int first, int count, int listBase)
779{
780#ifndef GLX_USE_APPLEGL
781   xGLXUseXFontReq *req;
782#endif
783   GLXContext gc = __glXGetCurrentContext();
784   Display *dpy = gc->currentDpy;
785
786   if (!dpy)
787      return;
788
789   /* Flush any pending commands out */
790   (void) __glXFlushRenderBuffer(gc, gc->pc);
791#ifdef GLX_USE_APPLEGL
792   DRI_glXUseXFont(font, first, count, listBase);
793#else
794#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
795   if (gc->driContext) {
796      DRI_glXUseXFont(font, first, count, listBase);
797      return;
798   }
799#endif
800
801   /* Send the glXUseFont request */
802   LockDisplay(dpy);
803   GetReq(GLXUseXFont, req);
804   req->reqType = gc->majorOpcode;
805   req->glxCode = X_GLXUseXFont;
806   req->contextTag = gc->currentContextTag;
807   req->font = font;
808   req->first = first;
809   req->count = count;
810   req->listBase = listBase;
811   UnlockDisplay(dpy);
812   SyncHandle();
813#endif /* GLX_USE_APPLEGL */
814}
815
816/************************************************************************/
817
818/*
819** Copy the source context to the destination context using the
820** attribute "mask".
821*/
822PUBLIC void
823glXCopyContext(Display * dpy, GLXContext source,
824               GLXContext dest, unsigned long mask)
825{
826#ifdef GLX_USE_APPLEGL
827   GLXContext gc = __glXGetCurrentContext();
828   int errorcode;
829   bool x11error;
830
831   if(apple_glx_copy_context(gc->driContext, source->driContext, dest->driContext,
832                             mask, &errorcode, &x11error)) {
833      __glXSendError(dpy, errorcode, 0, X_GLXCopyContext, x11error);
834   }
835
836#else
837   xGLXCopyContextReq *req;
838   GLXContext gc = __glXGetCurrentContext();
839   GLXContextTag tag;
840   CARD8 opcode;
841
842   opcode = __glXSetupForCommand(dpy);
843   if (!opcode) {
844      return;
845   }
846
847#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
848   if (gc->driContext) {
849      /* NOT_DONE: This does not work yet */
850   }
851#endif
852
853   /*
854    ** If the source is the current context, send its tag so that the context
855    ** can be flushed before the copy.
856    */
857   if (source == gc && dpy == gc->currentDpy) {
858      tag = gc->currentContextTag;
859   }
860   else {
861      tag = 0;
862   }
863
864   /* Send the glXCopyContext request */
865   LockDisplay(dpy);
866   GetReq(GLXCopyContext, req);
867   req->reqType = opcode;
868   req->glxCode = X_GLXCopyContext;
869   req->source = source ? source->xid : None;
870   req->dest = dest ? dest->xid : None;
871   req->mask = mask;
872   req->contextTag = tag;
873   UnlockDisplay(dpy);
874   SyncHandle();
875#endif /* GLX_USE_APPLEGL */
876}
877
878
879/**
880 * Determine if a context uses direct rendering.
881 *
882 * \param dpy        Display where the context was created.
883 * \param contextID  ID of the context to be tested.
884 *
885 * \returns \c GL_TRUE if the context is direct rendering or not.
886 */
887static Bool
888__glXIsDirect(Display * dpy, GLXContextID contextID)
889{
890#if !defined(USE_XCB)
891   xGLXIsDirectReq *req;
892   xGLXIsDirectReply reply;
893#endif
894   CARD8 opcode;
895
896   opcode = __glXSetupForCommand(dpy);
897   if (!opcode) {
898      return GL_FALSE;
899   }
900
901#ifdef USE_XCB
902   xcb_connection_t *c = XGetXCBConnection(dpy);
903   xcb_glx_is_direct_reply_t *reply = xcb_glx_is_direct_reply(c,
904                                                              xcb_glx_is_direct
905                                                              (c, contextID),
906                                                              NULL);
907
908   const Bool is_direct = reply->is_direct ? True : False;
909   free(reply);
910
911   return is_direct;
912#else
913   /* Send the glXIsDirect request */
914   LockDisplay(dpy);
915   GetReq(GLXIsDirect, req);
916   req->reqType = opcode;
917   req->glxCode = X_GLXIsDirect;
918   req->context = contextID;
919   _XReply(dpy, (xReply *) & reply, 0, False);
920   UnlockDisplay(dpy);
921   SyncHandle();
922
923   return reply.isDirect;
924#endif /* USE_XCB */
925}
926
927/**
928 * \todo
929 * Shouldn't this function \b always return \c GL_FALSE when
930 * \c GLX_DIRECT_RENDERING is not defined?  Do we really need to bother with
931 * the GLX protocol here at all?
932 */
933PUBLIC Bool
934glXIsDirect(Display * dpy, GLXContext gc)
935{
936   if (!gc) {
937      return GL_FALSE;
938   }
939   else if (GC_IS_DIRECT(gc)) {
940      return GL_TRUE;
941   }
942#ifdef GLX_USE_APPLEGL  /* TODO: indirect on darwin */
943      return GL_FALSE;
944#else
945   return __glXIsDirect(dpy, gc->xid);
946#endif
947}
948
949PUBLIC GLXPixmap
950glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
951{
952#ifdef GLX_USE_APPLEGL
953   int screen = vis->screen;
954   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
955   const __GLcontextModes *modes;
956
957   modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
958
959   if(apple_glx_pixmap_create(dpy, vis->screen, pixmap, modes))
960      return None;
961
962   return pixmap;
963#else
964   xGLXCreateGLXPixmapReq *req;
965   GLXPixmap xid;
966   CARD8 opcode;
967
968   opcode = __glXSetupForCommand(dpy);
969   if (!opcode) {
970      return None;
971   }
972
973   /* Send the glXCreateGLXPixmap request */
974   LockDisplay(dpy);
975   GetReq(GLXCreateGLXPixmap, req);
976   req->reqType = opcode;
977   req->glxCode = X_GLXCreateGLXPixmap;
978   req->screen = vis->screen;
979   req->visual = vis->visualid;
980   req->pixmap = pixmap;
981   req->glxpixmap = xid = XAllocID(dpy);
982   UnlockDisplay(dpy);
983   SyncHandle();
984
985#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
986   do {
987      /* FIXME: Maybe delay __DRIdrawable creation until the drawable
988       * is actually bound to a context... */
989
990      __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
991      __GLXDRIdrawable *pdraw;
992      __GLXscreenConfigs *psc;
993      __GLcontextModes *modes;
994
995      psc = &priv->screenConfigs[vis->screen];
996      if (psc->driScreen == NULL)
997         break;
998      modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
999      pdraw = psc->driScreen->createDrawable(psc, pixmap, req->glxpixmap, modes);
1000      if (pdraw == NULL) {
1001         fprintf(stderr, "failed to create pixmap\n");
1002         break;
1003      }
1004
1005      if (__glxHashInsert(psc->drawHash, req->glxpixmap, pdraw)) {
1006         (*pdraw->destroyDrawable) (pdraw);
1007         return None;           /* FIXME: Check what we're supposed to do here... */
1008      }
1009   } while (0);
1010#endif
1011
1012   return xid;
1013#endif
1014}
1015
1016/*
1017** Destroy the named pixmap
1018*/
1019PUBLIC void
1020glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
1021{
1022#ifdef GLX_USE_APPLEGL
1023   if(apple_glx_pixmap_destroy(dpy, glxpixmap))
1024      __glXSendError(dpy, GLXBadPixmap, glxpixmap, X_GLXDestroyPixmap, false);
1025#else
1026   xGLXDestroyGLXPixmapReq *req;
1027   CARD8 opcode;
1028
1029   opcode = __glXSetupForCommand(dpy);
1030   if (!opcode) {
1031      return;
1032   }
1033
1034   /* Send the glXDestroyGLXPixmap request */
1035   LockDisplay(dpy);
1036   GetReq(GLXDestroyGLXPixmap, req);
1037   req->reqType = opcode;
1038   req->glxCode = X_GLXDestroyGLXPixmap;
1039   req->glxpixmap = glxpixmap;
1040   UnlockDisplay(dpy);
1041   SyncHandle();
1042
1043#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
1044   {
1045      int screen;
1046      __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
1047      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap, &screen);
1048      __GLXscreenConfigs *psc = &priv->screenConfigs[screen];
1049
1050      if (pdraw != NULL) {
1051         (*pdraw->destroyDrawable) (pdraw);
1052         __glxHashDelete(psc->drawHash, glxpixmap);
1053      }
1054   }
1055#endif
1056#endif /* GLX_USE_APPLEGL */
1057}
1058
1059PUBLIC void
1060glXSwapBuffers(Display * dpy, GLXDrawable drawable)
1061{
1062#ifdef GLX_USE_APPLEGL
1063   GLXContext gc = glXGetCurrentContext();
1064   if(gc && apple_glx_is_current_drawable(dpy, gc->driContext, drawable)) {
1065      apple_glx_swap_buffers(gc->driContext);
1066   } else {
1067      __glXSendError(dpy, GLXBadCurrentWindow, 0, X_GLXSwapBuffers, false);
1068   }
1069#else
1070   GLXContext gc;
1071   GLXContextTag tag;
1072   CARD8 opcode;
1073#ifdef USE_XCB
1074   xcb_connection_t *c;
1075#else
1076   xGLXSwapBuffersReq *req;
1077#endif
1078
1079#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
1080   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
1081
1082   if (pdraw != NULL) {
1083      glFlush();
1084      (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0);
1085      return;
1086   }
1087#endif
1088
1089   opcode = __glXSetupForCommand(dpy);
1090   if (!opcode) {
1091      return;
1092   }
1093
1094   /*
1095    ** The calling thread may or may not have a current context.  If it
1096    ** does, send the context tag so the server can do a flush.
1097    */
1098   gc = __glXGetCurrentContext();
1099   if ((gc != NULL) && (dpy == gc->currentDpy) &&
1100       ((drawable == gc->currentDrawable)
1101        || (drawable == gc->currentReadable))) {
1102      tag = gc->currentContextTag;
1103   }
1104   else {
1105      tag = 0;
1106   }
1107
1108#ifdef USE_XCB
1109   c = XGetXCBConnection(dpy);
1110   xcb_glx_swap_buffers(c, tag, drawable);
1111   xcb_flush(c);
1112#else
1113   /* Send the glXSwapBuffers request */
1114   LockDisplay(dpy);
1115   GetReq(GLXSwapBuffers, req);
1116   req->reqType = opcode;
1117   req->glxCode = X_GLXSwapBuffers;
1118   req->drawable = drawable;
1119   req->contextTag = tag;
1120   UnlockDisplay(dpy);
1121   SyncHandle();
1122   XFlush(dpy);
1123#endif /* USE_XCB */
1124#endif /* GLX_USE_APPLEGL */
1125}
1126
1127
1128/*
1129** Return configuration information for the given display, screen and
1130** visual combination.
1131*/
1132PUBLIC int
1133glXGetConfig(Display * dpy, XVisualInfo * vis, int attribute,
1134             int *value_return)
1135{
1136   __GLXdisplayPrivate *priv;
1137   __GLXscreenConfigs *psc;
1138   __GLcontextModes *modes;
1139   int status;
1140
1141   status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc);
1142   if (status == Success) {
1143      modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
1144
1145      /* Lookup attribute after first finding a match on the visual */
1146      if (modes != NULL) {
1147         return _gl_get_context_mode_data(modes, attribute, value_return);
1148      }
1149
1150      status = GLX_BAD_VISUAL;
1151   }
1152
1153   /*
1154    ** If we can't find the config for this visual, this visual is not
1155    ** supported by the OpenGL implementation on the server.
1156    */
1157   if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) {
1158      *value_return = GL_FALSE;
1159      status = Success;
1160   }
1161
1162   return status;
1163}
1164
1165/************************************************************************/
1166
1167static void
1168init_fbconfig_for_chooser(__GLcontextModes * config,
1169                          GLboolean fbconfig_style_tags)
1170{
1171   memset(config, 0, sizeof(__GLcontextModes));
1172   config->visualID = (XID) GLX_DONT_CARE;
1173   config->visualType = GLX_DONT_CARE;
1174
1175   /* glXChooseFBConfig specifies different defaults for these two than
1176    * glXChooseVisual.
1177    */
1178   if (fbconfig_style_tags) {
1179      config->rgbMode = GL_TRUE;
1180      config->doubleBufferMode = GLX_DONT_CARE;
1181   }
1182
1183   config->visualRating = GLX_DONT_CARE;
1184   config->transparentPixel = GLX_NONE;
1185   config->transparentRed = GLX_DONT_CARE;
1186   config->transparentGreen = GLX_DONT_CARE;
1187   config->transparentBlue = GLX_DONT_CARE;
1188   config->transparentAlpha = GLX_DONT_CARE;
1189   config->transparentIndex = GLX_DONT_CARE;
1190
1191   config->drawableType = GLX_WINDOW_BIT;
1192   config->renderType =
1193      (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
1194   config->xRenderable = GLX_DONT_CARE;
1195   config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE);
1196
1197   config->swapMethod = GLX_DONT_CARE;
1198}
1199
1200#define MATCH_DONT_CARE( param )        \
1201  do {                                  \
1202    if ( ((int) a-> param != (int) GLX_DONT_CARE)   \
1203         && (a-> param != b-> param) ) {        \
1204      return False;                             \
1205    }                                           \
1206  } while ( 0 )
1207
1208#define MATCH_MINIMUM( param )                  \
1209  do {                                          \
1210    if ( ((int) a-> param != (int) GLX_DONT_CARE)	\
1211         && (a-> param > b-> param) ) {         \
1212      return False;                             \
1213    }                                           \
1214  } while ( 0 )
1215
1216#define MATCH_EXACT( param )                    \
1217  do {                                          \
1218    if ( a-> param != b-> param) {              \
1219      return False;                             \
1220    }                                           \
1221  } while ( 0 )
1222
1223/* Test that all bits from a are contained in b */
1224#define MATCH_MASK(param)			\
1225  do {						\
1226    if ((a->param & ~b->param) != 0)		\
1227      return False;				\
1228  } while (0);
1229
1230/**
1231 * Determine if two GLXFBConfigs are compatible.
1232 *
1233 * \param a  Application specified config to test.
1234 * \param b  Server specified config to test against \c a.
1235 */
1236static Bool
1237fbconfigs_compatible(const __GLcontextModes * const a,
1238                     const __GLcontextModes * const b)
1239{
1240   MATCH_DONT_CARE(doubleBufferMode);
1241   MATCH_DONT_CARE(visualType);
1242   MATCH_DONT_CARE(visualRating);
1243   MATCH_DONT_CARE(xRenderable);
1244   MATCH_DONT_CARE(fbconfigID);
1245   MATCH_DONT_CARE(swapMethod);
1246
1247   MATCH_MINIMUM(rgbBits);
1248   MATCH_MINIMUM(numAuxBuffers);
1249   MATCH_MINIMUM(redBits);
1250   MATCH_MINIMUM(greenBits);
1251   MATCH_MINIMUM(blueBits);
1252   MATCH_MINIMUM(alphaBits);
1253   MATCH_MINIMUM(depthBits);
1254   MATCH_MINIMUM(stencilBits);
1255   MATCH_MINIMUM(accumRedBits);
1256   MATCH_MINIMUM(accumGreenBits);
1257   MATCH_MINIMUM(accumBlueBits);
1258   MATCH_MINIMUM(accumAlphaBits);
1259   MATCH_MINIMUM(sampleBuffers);
1260   MATCH_MINIMUM(maxPbufferWidth);
1261   MATCH_MINIMUM(maxPbufferHeight);
1262   MATCH_MINIMUM(maxPbufferPixels);
1263   MATCH_MINIMUM(samples);
1264
1265   MATCH_DONT_CARE(stereoMode);
1266   MATCH_EXACT(level);
1267
1268   MATCH_MASK(drawableType);
1269   MATCH_MASK(renderType);
1270
1271   /* There is a bug in a few of the XFree86 DDX drivers.  They contain
1272    * visuals with a "transparent type" of 0 when they really mean GLX_NONE.
1273    * Technically speaking, it is a bug in the DDX driver, but there is
1274    * enough of an installed base to work around the problem here.  In any
1275    * case, 0 is not a valid value of the transparent type, so we'll treat 0
1276    * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
1277    * 0 from the server to be a match to maintain backward compatibility with
1278    * the (broken) drivers.
1279    */
1280
1281   if (a->transparentPixel != (int) GLX_DONT_CARE && a->transparentPixel != 0) {
1282      if (a->transparentPixel == GLX_NONE) {
1283         if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0)
1284            return False;
1285      }
1286      else {
1287         MATCH_EXACT(transparentPixel);
1288      }
1289
1290      switch (a->transparentPixel) {
1291      case GLX_TRANSPARENT_RGB:
1292         MATCH_DONT_CARE(transparentRed);
1293         MATCH_DONT_CARE(transparentGreen);
1294         MATCH_DONT_CARE(transparentBlue);
1295         MATCH_DONT_CARE(transparentAlpha);
1296         break;
1297
1298      case GLX_TRANSPARENT_INDEX:
1299         MATCH_DONT_CARE(transparentIndex);
1300         break;
1301
1302      default:
1303         break;
1304      }
1305   }
1306
1307   return True;
1308}
1309
1310
1311/* There's some trickly language in the GLX spec about how this is supposed
1312 * to work.  Basically, if a given component size is either not specified
1313 * or the requested size is zero, it is supposed to act like PERFER_SMALLER.
1314 * Well, that's really hard to do with the code as-is.  This behavior is
1315 * closer to correct, but still not technically right.
1316 */
1317#define PREFER_LARGER_OR_ZERO(comp)             \
1318  do {                                          \
1319    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
1320      if ( ((*a)-> comp) == 0 ) {               \
1321        return -1;                              \
1322      }                                         \
1323      else if ( ((*b)-> comp) == 0 ) {          \
1324        return 1;                               \
1325      }                                         \
1326      else {                                    \
1327        return ((*b)-> comp) - ((*a)-> comp) ;  \
1328      }                                         \
1329    }                                           \
1330  } while( 0 )
1331
1332#define PREFER_LARGER(comp)                     \
1333  do {                                          \
1334    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
1335      return ((*b)-> comp) - ((*a)-> comp) ;    \
1336    }                                           \
1337  } while( 0 )
1338
1339#define PREFER_SMALLER(comp)                    \
1340  do {                                          \
1341    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
1342      return ((*a)-> comp) - ((*b)-> comp) ;    \
1343    }                                           \
1344  } while( 0 )
1345
1346/**
1347 * Compare two GLXFBConfigs.  This function is intended to be used as the
1348 * compare function passed in to qsort.
1349 *
1350 * \returns If \c a is a "better" config, according to the specification of
1351 *          SGIX_fbconfig, a number less than zero is returned.  If \c b is
1352 *          better, then a number greater than zero is return.  If both are
1353 *          equal, zero is returned.
1354 * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1355 */
1356static int
1357fbconfig_compare(const __GLcontextModes * const *const a,
1358                 const __GLcontextModes * const *const b)
1359{
1360   /* The order of these comparisons must NOT change.  It is defined by
1361    * the GLX 1.3 spec and ARB_multisample.
1362    */
1363
1364   PREFER_SMALLER(visualSelectGroup);
1365
1366   /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
1367    * GLX_NON_CONFORMANT_CONFIG.  It just so happens that this is the
1368    * numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
1369    */
1370   PREFER_SMALLER(visualRating);
1371
1372   /* This isn't quite right.  It is supposed to compare the sum of the
1373    * components the user specifically set minimums for.
1374    */
1375   PREFER_LARGER_OR_ZERO(redBits);
1376   PREFER_LARGER_OR_ZERO(greenBits);
1377   PREFER_LARGER_OR_ZERO(blueBits);
1378   PREFER_LARGER_OR_ZERO(alphaBits);
1379
1380   PREFER_SMALLER(rgbBits);
1381
1382   if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) {
1383      /* Prefer single-buffer.
1384       */
1385      return (!(*a)->doubleBufferMode) ? -1 : 1;
1386   }
1387
1388   PREFER_SMALLER(numAuxBuffers);
1389
1390   PREFER_LARGER_OR_ZERO(depthBits);
1391   PREFER_SMALLER(stencilBits);
1392
1393   /* This isn't quite right.  It is supposed to compare the sum of the
1394    * components the user specifically set minimums for.
1395    */
1396   PREFER_LARGER_OR_ZERO(accumRedBits);
1397   PREFER_LARGER_OR_ZERO(accumGreenBits);
1398   PREFER_LARGER_OR_ZERO(accumBlueBits);
1399   PREFER_LARGER_OR_ZERO(accumAlphaBits);
1400
1401   PREFER_SMALLER(visualType);
1402
1403   /* None of the multisample specs say where this comparison should happen,
1404    * so I put it near the end.
1405    */
1406   PREFER_SMALLER(sampleBuffers);
1407   PREFER_SMALLER(samples);
1408
1409   /* None of the pbuffer or fbconfig specs say that this comparison needs
1410    * to happen at all, but it seems like it should.
1411    */
1412   PREFER_LARGER(maxPbufferWidth);
1413   PREFER_LARGER(maxPbufferHeight);
1414   PREFER_LARGER(maxPbufferPixels);
1415
1416   return 0;
1417}
1418
1419
1420/**
1421 * Selects and sorts a subset of the supplied configs based on the attributes.
1422 * This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig,
1423 * and \c glXChooseFBConfigSGIX.
1424 *
1425 * \param configs   Array of pointers to possible configs.  The elements of
1426 *                  this array that do not meet the criteria will be set to
1427 *                  NULL.  The remaining elements will be sorted according to
1428 *                  the various visual / FBConfig selection rules.
1429 * \param num_configs  Number of elements in the \c configs array.
1430 * \param attribList   Attributes used select from \c configs.  This array is
1431 *                     terminated by a \c None tag.  The array can either take
1432 *                     the form expected by \c glXChooseVisual (where boolean
1433 *                     tags do not have a value) or by \c glXChooseFBConfig
1434 *                     (where every tag has a value).
1435 * \param fbconfig_style_tags  Selects whether \c attribList is in
1436 *                             \c glXChooseVisual style or
1437 *                             \c glXChooseFBConfig style.
1438 * \returns The number of valid elements left in \c configs.
1439 *
1440 * \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1441 */
1442static int
1443choose_visual(__GLcontextModes ** configs, int num_configs,
1444              const int *attribList, GLboolean fbconfig_style_tags)
1445{
1446   __GLcontextModes test_config;
1447   int base;
1448   int i;
1449
1450   /* This is a fairly direct implementation of the selection method
1451    * described by GLX_SGIX_fbconfig.  Start by culling out all the
1452    * configs that are not compatible with the selected parameter
1453    * list.
1454    */
1455
1456   init_fbconfig_for_chooser(&test_config, fbconfig_style_tags);
1457   __glXInitializeVisualConfigFromTags(&test_config, 512,
1458                                       (const INT32 *) attribList,
1459                                       GL_TRUE, fbconfig_style_tags);
1460
1461   base = 0;
1462   for (i = 0; i < num_configs; i++) {
1463      if (fbconfigs_compatible(&test_config, configs[i])) {
1464         configs[base] = configs[i];
1465         base++;
1466      }
1467   }
1468
1469   if (base == 0) {
1470      return 0;
1471   }
1472
1473   if (base < num_configs) {
1474      (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base));
1475   }
1476
1477   /* After the incompatible configs are removed, the resulting
1478    * list is sorted according to the rules set out in the various
1479    * specifications.
1480    */
1481
1482   qsort(configs, base, sizeof(__GLcontextModes *),
1483         (int (*)(const void *, const void *)) fbconfig_compare);
1484   return base;
1485}
1486
1487
1488
1489
1490/*
1491** Return the visual that best matches the template.  Return None if no
1492** visual matches the template.
1493*/
1494PUBLIC XVisualInfo *
1495glXChooseVisual(Display * dpy, int screen, int *attribList)
1496{
1497   XVisualInfo *visualList = NULL;
1498   __GLXdisplayPrivate *priv;
1499   __GLXscreenConfigs *psc;
1500   __GLcontextModes test_config;
1501   __GLcontextModes *modes;
1502   const __GLcontextModes *best_config = NULL;
1503
1504   /*
1505    ** Get a list of all visuals, return if list is empty
1506    */
1507   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1508      return None;
1509   }
1510
1511
1512   /*
1513    ** Build a template from the defaults and the attribute list
1514    ** Free visual list and return if an unexpected token is encountered
1515    */
1516   init_fbconfig_for_chooser(&test_config, GL_FALSE);
1517   __glXInitializeVisualConfigFromTags(&test_config, 512,
1518                                       (const INT32 *) attribList,
1519                                       GL_TRUE, GL_FALSE);
1520
1521   /*
1522    ** Eliminate visuals that don't meet minimum requirements
1523    ** Compute a score for those that do
1524    ** Remember which visual, if any, got the highest score
1525    ** If no visual is acceptable, return None
1526    ** Otherwise, create an XVisualInfo list with just the selected X visual
1527    ** and return this.
1528    */
1529   for (modes = psc->visuals; modes != NULL; modes = modes->next) {
1530      if (fbconfigs_compatible(&test_config, modes)
1531          && ((best_config == NULL)
1532              ||
1533              (fbconfig_compare
1534               ((const __GLcontextModes * const *const) &modes,
1535                &best_config) < 0))) {
1536         XVisualInfo visualTemplate;
1537         XVisualInfo *newList;
1538         int i;
1539
1540         visualTemplate.screen = screen;
1541         visualTemplate.visualid = modes->visualID;
1542         newList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
1543                                  &visualTemplate, &i);
1544
1545         if (newList) {
1546            Xfree(visualList);
1547            visualList = newList;
1548            best_config = modes;
1549         }
1550      }
1551   }
1552
1553#ifdef GLX_USE_APPLEGL
1554   if(visualList && getenv("LIBGL_DUMP_VISUALID")) {
1555      printf("visualid 0x%lx\n", visualList[0].visualid);
1556   }
1557#endif
1558
1559   return visualList;
1560}
1561
1562
1563PUBLIC const char *
1564glXQueryExtensionsString(Display * dpy, int screen)
1565{
1566   __GLXscreenConfigs *psc;
1567   __GLXdisplayPrivate *priv;
1568
1569   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1570      return NULL;
1571   }
1572
1573   if (!psc->effectiveGLXexts) {
1574      if (!psc->serverGLXexts) {
1575         psc->serverGLXexts =
1576            __glXQueryServerString(dpy, priv->majorOpcode, screen,
1577                                   GLX_EXTENSIONS);
1578      }
1579
1580      __glXCalculateUsableExtensions(psc,
1581#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
1582                                     (psc->driScreen != NULL),
1583#else
1584                                     GL_FALSE,
1585#endif
1586                                     priv->minorVersion);
1587   }
1588
1589   return psc->effectiveGLXexts;
1590}
1591
1592PUBLIC const char *
1593glXGetClientString(Display * dpy, int name)
1594{
1595   (void) dpy;
1596
1597   switch (name) {
1598   case GLX_VENDOR:
1599      return (__glXGLXClientVendorName);
1600   case GLX_VERSION:
1601      return (__glXGLXClientVersion);
1602   case GLX_EXTENSIONS:
1603      return (__glXGetClientExtensions());
1604   default:
1605      return NULL;
1606   }
1607}
1608
1609PUBLIC const char *
1610glXQueryServerString(Display * dpy, int screen, int name)
1611{
1612   __GLXscreenConfigs *psc;
1613   __GLXdisplayPrivate *priv;
1614   const char **str;
1615
1616
1617   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1618      return NULL;
1619   }
1620
1621   switch (name) {
1622   case GLX_VENDOR:
1623      str = &priv->serverGLXvendor;
1624      break;
1625   case GLX_VERSION:
1626      str = &priv->serverGLXversion;
1627      break;
1628   case GLX_EXTENSIONS:
1629      str = &psc->serverGLXexts;
1630      break;
1631   default:
1632      return NULL;
1633   }
1634
1635   if (*str == NULL) {
1636      *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name);
1637   }
1638
1639   return *str;
1640}
1641
1642void
1643__glXClientInfo(Display * dpy, int opcode)
1644{
1645   char *ext_str = __glXGetClientGLExtensionString();
1646   int size = strlen(ext_str) + 1;
1647
1648#ifdef USE_XCB
1649   xcb_connection_t *c = XGetXCBConnection(dpy);
1650   xcb_glx_client_info(c,
1651                       GLX_MAJOR_VERSION, GLX_MINOR_VERSION, size, ext_str);
1652#else
1653   xGLXClientInfoReq *req;
1654
1655   /* Send the glXClientInfo request */
1656   LockDisplay(dpy);
1657   GetReq(GLXClientInfo, req);
1658   req->reqType = opcode;
1659   req->glxCode = X_GLXClientInfo;
1660   req->major = GLX_MAJOR_VERSION;
1661   req->minor = GLX_MINOR_VERSION;
1662
1663   req->length += (size + 3) >> 2;
1664   req->numbytes = size;
1665   Data(dpy, ext_str, size);
1666
1667   UnlockDisplay(dpy);
1668   SyncHandle();
1669#endif /* USE_XCB */
1670
1671   Xfree(ext_str);
1672}
1673
1674
1675/*
1676** EXT_import_context
1677*/
1678
1679PUBLIC Display *
1680glXGetCurrentDisplay(void)
1681{
1682   GLXContext gc = __glXGetCurrentContext();
1683   if (NULL == gc)
1684      return NULL;
1685   return gc->currentDpy;
1686}
1687
1688PUBLIC
1689GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
1690          glXGetCurrentDisplay)
1691
1692#ifndef GLX_USE_APPLEGL
1693/**
1694 * Used internally by libGL to send \c xGLXQueryContextinfoExtReq requests
1695 * to the X-server.
1696 *
1697 * \param dpy  Display where \c ctx was created.
1698 * \param ctx  Context to query.
1699 * \returns  \c Success on success.  \c GLX_BAD_CONTEXT if \c ctx is invalid,
1700 *           or zero if the request failed due to internal problems (i.e.,
1701 *           unable to allocate temporary memory, etc.)
1702 *
1703 * \note
1704 * This function dynamically determines whether to use the EXT_import_context
1705 * version of the protocol or the GLX 1.3 version of the protocol.
1706 */
1707static int __glXQueryContextInfo(Display * dpy, GLXContext ctx)
1708{
1709   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1710   xGLXQueryContextReply reply;
1711   CARD8 opcode;
1712   GLuint numValues;
1713   int retval;
1714
1715   if (ctx == NULL) {
1716      return GLX_BAD_CONTEXT;
1717   }
1718   opcode = __glXSetupForCommand(dpy);
1719   if (!opcode) {
1720      return 0;
1721   }
1722
1723   /* Send the glXQueryContextInfoEXT request */
1724   LockDisplay(dpy);
1725
1726   if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
1727      xGLXQueryContextReq *req;
1728
1729      GetReq(GLXQueryContext, req);
1730
1731      req->reqType = opcode;
1732      req->glxCode = X_GLXQueryContext;
1733      req->context = (unsigned int) (ctx->xid);
1734   }
1735   else {
1736      xGLXVendorPrivateReq *vpreq;
1737      xGLXQueryContextInfoEXTReq *req;
1738
1739      GetReqExtra(GLXVendorPrivate,
1740                  sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
1741                  vpreq);
1742      req = (xGLXQueryContextInfoEXTReq *) vpreq;
1743      req->reqType = opcode;
1744      req->glxCode = X_GLXVendorPrivateWithReply;
1745      req->vendorCode = X_GLXvop_QueryContextInfoEXT;
1746      req->context = (unsigned int) (ctx->xid);
1747   }
1748
1749   _XReply(dpy, (xReply *) & reply, 0, False);
1750
1751   numValues = reply.n;
1752   if (numValues == 0)
1753      retval = Success;
1754   else if (numValues > __GLX_MAX_CONTEXT_PROPS)
1755      retval = 0;
1756   else {
1757      int *propList, *pProp;
1758      int nPropListBytes;
1759
1760      nPropListBytes = numValues << 3;
1761      propList = (int *) Xmalloc(nPropListBytes);
1762      if (NULL == propList) {
1763         retval = 0;
1764      }
1765      else {
1766	 unsigned i;
1767
1768         _XRead(dpy, (char *) propList, nPropListBytes);
1769         pProp = propList;
1770         for (i = 0; i < numValues; i++) {
1771            switch (*pProp++) {
1772            case GLX_SHARE_CONTEXT_EXT:
1773               ctx->share_xid = *pProp++;
1774               break;
1775            case GLX_VISUAL_ID_EXT:
1776               ctx->mode =
1777                  _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++);
1778               break;
1779            case GLX_SCREEN:
1780               ctx->screen = *pProp++;
1781               break;
1782            case GLX_FBCONFIG_ID:
1783               ctx->mode =
1784                  _gl_context_modes_find_fbconfig(ctx->psc->configs,
1785                                                  *pProp++);
1786               break;
1787            case GLX_RENDER_TYPE:
1788               ctx->renderType = *pProp++;
1789               break;
1790            default:
1791               pProp++;
1792               continue;
1793            }
1794         }
1795         Xfree((char *) propList);
1796         retval = Success;
1797      }
1798   }
1799   UnlockDisplay(dpy);
1800   SyncHandle();
1801   return retval;
1802}
1803
1804#endif
1805
1806PUBLIC int
1807glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int *value)
1808{
1809#ifndef GLX_USE_APPLEGL
1810   int retVal;
1811
1812   /* get the information from the server if we don't have it already */
1813#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
1814   if (!ctx->driContext && (ctx->mode == NULL)) {
1815#else
1816   if (ctx->mode == NULL) {
1817#endif
1818      retVal = __glXQueryContextInfo(dpy, ctx);
1819      if (Success != retVal)
1820         return retVal;
1821   }
1822#endif
1823
1824   switch (attribute) {
1825#ifndef GLX_USE_APPLEGL
1826      case GLX_SHARE_CONTEXT_EXT:
1827      *value = (int) (ctx->share_xid);
1828      break;
1829   case GLX_VISUAL_ID_EXT:
1830      *value = ctx->mode ? ctx->mode->visualID : None;
1831      break;
1832#endif
1833   case GLX_SCREEN:
1834      *value = (int) (ctx->screen);
1835      break;
1836   case GLX_FBCONFIG_ID:
1837      *value = ctx->mode ? ctx->mode->fbconfigID : None;
1838      break;
1839   case GLX_RENDER_TYPE:
1840      *value = (int) (ctx->renderType);
1841      break;
1842   default:
1843      return GLX_BAD_ATTRIBUTE;
1844   }
1845   return Success;
1846}
1847
1848PUBLIC
1849GLX_ALIAS(int, glXQueryContextInfoEXT,
1850          (Display * dpy, GLXContext ctx, int attribute, int *value),
1851          (dpy, ctx, attribute, value), glXQueryContext)
1852
1853PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx)
1854{
1855   return ctx->xid;
1856}
1857
1858PUBLIC GLXContext
1859glXImportContextEXT(Display * dpy, GLXContextID contextID)
1860{
1861#ifdef GLX_USE_APPLEGL
1862   return NULL;
1863#else
1864   GLXContext ctx;
1865
1866   if (contextID == None) {
1867      return NULL;
1868   }
1869   if (__glXIsDirect(dpy, contextID)) {
1870      return NULL;
1871   }
1872
1873   ctx = AllocateGLXContext(dpy);
1874   if (NULL != ctx) {
1875      ctx->xid = contextID;
1876      ctx->imported = GL_TRUE;
1877
1878      if (Success != __glXQueryContextInfo(dpy, ctx)) {
1879	 __glXFreeContext(ctx);
1880	 ctx = NULL;
1881      }
1882   }
1883   return ctx;
1884#endif
1885}
1886
1887PUBLIC void
1888glXFreeContextEXT(Display * dpy, GLXContext ctx)
1889{
1890   DestroyContext(dpy, ctx);
1891}
1892
1893
1894
1895/*
1896 * GLX 1.3 functions - these are just stubs for now!
1897 */
1898
1899PUBLIC GLXFBConfig *
1900glXChooseFBConfig(Display * dpy, int screen,
1901                  const int *attribList, int *nitems)
1902{
1903   __GLcontextModes **config_list;
1904   int list_size;
1905
1906
1907   config_list = (__GLcontextModes **)
1908      glXGetFBConfigs(dpy, screen, &list_size);
1909
1910   if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) {
1911      list_size = choose_visual(config_list, list_size, attribList, GL_TRUE);
1912      if (list_size == 0) {
1913         XFree(config_list);
1914         config_list = NULL;
1915      }
1916   }
1917
1918   *nitems = list_size;
1919   return (GLXFBConfig *) config_list;
1920}
1921
1922
1923PUBLIC GLXContext
1924glXCreateNewContext(Display * dpy, GLXFBConfig config,
1925                    int renderType, GLXContext shareList, Bool allowDirect)
1926{
1927   const __GLcontextModes *const fbconfig =
1928      (const __GLcontextModes *const) config;
1929
1930   return CreateContext(dpy, fbconfig->fbconfigID, fbconfig, shareList,
1931                        allowDirect, X_GLXCreateNewContext, renderType,
1932			fbconfig->screen);
1933}
1934
1935
1936PUBLIC GLXDrawable
1937glXGetCurrentReadDrawable(void)
1938{
1939   GLXContext gc = __glXGetCurrentContext();
1940   return gc->currentReadable;
1941}
1942
1943
1944PUBLIC GLXFBConfig *
1945glXGetFBConfigs(Display * dpy, int screen, int *nelements)
1946{
1947   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1948   __GLcontextModes **config = NULL;
1949   int i;
1950
1951   *nelements = 0;
1952   if (priv && (priv->screenConfigs != NULL)
1953       && (screen >= 0) && (screen <= ScreenCount(dpy))
1954       && (priv->screenConfigs[screen].configs != NULL)
1955       && (priv->screenConfigs[screen].configs->fbconfigID
1956	   != (int) GLX_DONT_CARE)) {
1957      unsigned num_configs = 0;
1958      __GLcontextModes *modes;
1959
1960
1961      for (modes = priv->screenConfigs[screen].configs; modes != NULL;
1962           modes = modes->next) {
1963         if (modes->fbconfigID != (int) GLX_DONT_CARE) {
1964            num_configs++;
1965         }
1966      }
1967
1968      config = (__GLcontextModes **) Xmalloc(sizeof(__GLcontextModes *)
1969                                             * num_configs);
1970      if (config != NULL) {
1971         *nelements = num_configs;
1972         i = 0;
1973         for (modes = priv->screenConfigs[screen].configs; modes != NULL;
1974              modes = modes->next) {
1975            if (modes->fbconfigID != (int) GLX_DONT_CARE) {
1976               config[i] = modes;
1977               i++;
1978            }
1979         }
1980      }
1981   }
1982   return (GLXFBConfig *) config;
1983}
1984
1985
1986PUBLIC int
1987glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config,
1988                     int attribute, int *value)
1989{
1990   __GLcontextModes *const modes = ValidateGLXFBConfig(dpy, config);
1991
1992   return (modes != NULL)
1993      ? _gl_get_context_mode_data(modes, attribute, value)
1994      : GLXBadFBConfig;
1995}
1996
1997
1998PUBLIC XVisualInfo *
1999glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config)
2000{
2001   XVisualInfo visualTemplate;
2002   __GLcontextModes *fbconfig = (__GLcontextModes *) config;
2003   int count;
2004
2005   /*
2006    ** Get a list of all visuals, return if list is empty
2007    */
2008   visualTemplate.visualid = fbconfig->visualID;
2009   return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count);
2010}
2011
2012#ifndef GLX_USE_APPLEGL
2013/*
2014** GLX_SGI_swap_control
2015*/
2016static int
2017__glXSwapIntervalSGI(int interval)
2018{
2019   xGLXVendorPrivateReq *req;
2020   GLXContext gc = __glXGetCurrentContext();
2021   __GLXscreenConfigs *psc;
2022   Display *dpy;
2023   CARD32 *interval_ptr;
2024   CARD8 opcode;
2025
2026   if (gc == NULL) {
2027      return GLX_BAD_CONTEXT;
2028   }
2029
2030   if (interval <= 0) {
2031      return GLX_BAD_VALUE;
2032   }
2033
2034#ifdef __DRI_SWAP_CONTROL
2035   if (gc->driContext) {
2036      __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
2037							    gc->screen );
2038      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
2039						  gc->currentDrawable,
2040						  NULL);
2041      if (psc->swapControl != NULL && pdraw != NULL) {
2042	 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
2043	 return 0;
2044      }
2045      else if (pdraw == NULL) {
2046	 return GLX_BAD_CONTEXT;
2047      }
2048   }
2049#endif
2050   psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
2051
2052#ifdef GLX_DIRECT_RENDERING
2053   if (gc->driContext && psc->driScreen && psc->driScreen->setSwapInterval) {
2054      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
2055						  gc->currentDrawable,
2056						  NULL);
2057      psc->driScreen->setSwapInterval(pdraw, interval);
2058      return 0;
2059   }
2060#endif
2061
2062   dpy = gc->currentDpy;
2063   opcode = __glXSetupForCommand(dpy);
2064   if (!opcode) {
2065      return 0;
2066   }
2067
2068   /* Send the glXSwapIntervalSGI request */
2069   LockDisplay(dpy);
2070   GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req);
2071   req->reqType = opcode;
2072   req->glxCode = X_GLXVendorPrivate;
2073   req->vendorCode = X_GLXvop_SwapIntervalSGI;
2074   req->contextTag = gc->currentContextTag;
2075
2076   interval_ptr = (CARD32 *) (req + 1);
2077   *interval_ptr = interval;
2078
2079   UnlockDisplay(dpy);
2080   SyncHandle();
2081   XFlush(dpy);
2082
2083   return 0;
2084}
2085
2086
2087/*
2088** GLX_MESA_swap_control
2089*/
2090static int
2091__glXSwapIntervalMESA(unsigned int interval)
2092{
2093   GLXContext gc = __glXGetCurrentContext();
2094
2095#ifdef __DRI_SWAP_CONTROL
2096   if (gc != NULL && gc->driContext) {
2097      __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
2098                                                          gc->screen);
2099
2100      if ((psc != NULL) && (psc->driScreen != NULL)) {
2101         __GLXDRIdrawable *pdraw =
2102            GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2103         if (psc->swapControl != NULL && pdraw != NULL) {
2104            psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
2105            return 0;
2106         }
2107      }
2108   }
2109#endif
2110
2111#ifdef GLX_DIRECT_RENDERING
2112   if (gc != NULL && gc->driContext) {
2113      __GLXscreenConfigs *psc;
2114
2115      psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
2116      if (psc->driScreen && psc->driScreen->setSwapInterval) {
2117         __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
2118						     gc->currentDrawable, NULL);
2119	 psc->driScreen->setSwapInterval(pdraw, interval);
2120	 return 0;
2121      }
2122   }
2123#endif
2124
2125   return GLX_BAD_CONTEXT;
2126}
2127
2128
2129static int
2130__glXGetSwapIntervalMESA(void)
2131{
2132#ifdef __DRI_SWAP_CONTROL
2133   GLXContext gc = __glXGetCurrentContext();
2134
2135   if (gc != NULL && gc->driContext) {
2136      __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
2137                                                          gc->screen);
2138
2139      if ((psc != NULL) && (psc->driScreen != NULL)) {
2140         __GLXDRIdrawable *pdraw =
2141            GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2142         if (psc->swapControl != NULL && pdraw != NULL) {
2143            return psc->swapControl->getSwapInterval(pdraw->driDrawable);
2144         }
2145      }
2146   }
2147#endif
2148
2149#ifdef GLX_DIRECT_RENDERING
2150   if (gc != NULL && gc->driContext) {
2151      __GLXscreenConfigs *psc;
2152
2153      psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
2154      if (psc->driScreen && psc->driScreen->getSwapInterval) {
2155         __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
2156						     gc->currentDrawable, NULL);
2157	 return psc->driScreen->getSwapInterval(pdraw);
2158      }
2159   }
2160#endif
2161
2162   return 0;
2163}
2164
2165
2166/*
2167** GLX_MESA_swap_frame_usage
2168*/
2169
2170static GLint
2171__glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
2172{
2173   int status = GLX_BAD_CONTEXT;
2174#ifdef __DRI_FRAME_TRACKING
2175   int screen = 0;
2176   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2177   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2178
2179   if (pdraw != NULL && psc->frameTracking != NULL)
2180      status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE);
2181#else
2182   (void) dpy;
2183   (void) drawable;
2184#endif
2185   return status;
2186}
2187
2188
2189static GLint
2190__glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
2191{
2192   int status = GLX_BAD_CONTEXT;
2193#ifdef __DRI_FRAME_TRACKING
2194   int screen = 0;
2195   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2196   __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen);
2197
2198   if (pdraw != NULL && psc->frameTracking != NULL)
2199      status = psc->frameTracking->frameTracking(pdraw->driDrawable,
2200                                                 GL_FALSE);
2201#else
2202   (void) dpy;
2203   (void) drawable;
2204#endif
2205   return status;
2206}
2207
2208
2209static GLint
2210__glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage)
2211{
2212   int status = GLX_BAD_CONTEXT;
2213#ifdef __DRI_FRAME_TRACKING
2214   int screen = 0;
2215   __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2216   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2217
2218   if (pdraw != NULL && psc->frameTracking != NULL) {
2219      int64_t sbc, missedFrames;
2220      float lastMissedUsage;
2221
2222      status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
2223                                                      &sbc,
2224                                                      &missedFrames,
2225                                                      &lastMissedUsage,
2226                                                      usage);
2227   }
2228#else
2229   (void) dpy;
2230   (void) drawable;
2231   (void) usage;
2232#endif
2233   return status;
2234}
2235
2236
2237static GLint
2238__glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable,
2239                            int64_t * sbc, int64_t * missedFrames,
2240                            GLfloat * lastMissedUsage)
2241{
2242   int status = GLX_BAD_CONTEXT;
2243#ifdef __DRI_FRAME_TRACKING
2244   int screen = 0;
2245   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2246   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2247
2248   if (pdraw != NULL && psc->frameTracking != NULL) {
2249      float usage;
2250
2251      status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
2252                                                      sbc, missedFrames,
2253                                                      lastMissedUsage,
2254                                                      &usage);
2255   }
2256#else
2257   (void) dpy;
2258   (void) drawable;
2259   (void) sbc;
2260   (void) missedFrames;
2261   (void) lastMissedUsage;
2262#endif
2263   return status;
2264}
2265
2266
2267/*
2268** GLX_SGI_video_sync
2269*/
2270static int
2271__glXGetVideoSyncSGI(unsigned int *count)
2272{
2273   int64_t ust, msc, sbc;
2274   int ret;
2275   GLXContext gc = __glXGetCurrentContext();
2276   __GLXscreenConfigs *psc;
2277#ifdef GLX_DIRECT_RENDERING
2278   __GLXDRIdrawable *pdraw;
2279#endif
2280
2281   if (!gc)
2282      return GLX_BAD_CONTEXT;
2283
2284#ifdef GLX_DIRECT_RENDERING
2285   if (!gc->driContext)
2286      return GLX_BAD_CONTEXT;
2287#endif
2288
2289   psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen);
2290#ifdef GLX_DIRECT_RENDERING
2291   pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2292#endif
2293
2294   /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
2295    * FIXME: there should be a GLX encoding for this call.  I can find no
2296    * FIXME: documentation for the GLX encoding.
2297    */
2298#ifdef __DRI_MEDIA_STREAM_COUNTER
2299   if ( psc->msc && psc->driScreen ) {
2300      ret = (*psc->msc->getDrawableMSC)(psc->__driScreen,
2301					pdraw->driDrawable, &msc);
2302      *count = (unsigned) msc;
2303
2304      return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
2305   }
2306#endif
2307
2308#ifdef GLX_DIRECT_RENDERING
2309   if (psc->driScreen && psc->driScreen->getDrawableMSC) {
2310      ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc);
2311      *count = (unsigned) msc;
2312      return (ret == True) ? 0 : GLX_BAD_CONTEXT;
2313   }
2314#endif
2315
2316   return GLX_BAD_CONTEXT;
2317}
2318
2319static int
2320__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
2321{
2322   GLXContext gc = __glXGetCurrentContext();
2323   __GLXscreenConfigs *psc;
2324#ifdef GLX_DIRECT_RENDERING
2325   __GLXDRIdrawable *pdraw;
2326#endif
2327   int64_t ust, msc, sbc;
2328   int ret;
2329
2330   if (divisor <= 0 || remainder < 0)
2331      return GLX_BAD_VALUE;
2332
2333   if (!gc)
2334      return GLX_BAD_CONTEXT;
2335
2336#ifdef GLX_DIRECT_RENDERING
2337   if (!gc->driContext)
2338      return GLX_BAD_CONTEXT;
2339#endif
2340
2341   psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
2342#ifdef GLX_DIRECT_RENDERING
2343   pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2344#endif
2345
2346#ifdef __DRI_MEDIA_STREAM_COUNTER
2347   if (psc->msc != NULL && psc->driScreen ) {
2348      ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0,
2349				    divisor, remainder, &msc, &sbc);
2350      *count = (unsigned) msc;
2351      return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
2352   }
2353#endif
2354
2355#ifdef GLX_DIRECT_RENDERING
2356   if (psc->driScreen && psc->driScreen->waitForMSC) {
2357      ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc,
2358				       &sbc);
2359      *count = (unsigned) msc;
2360      return (ret == True) ? 0 : GLX_BAD_CONTEXT;
2361   }
2362#endif
2363
2364   return GLX_BAD_CONTEXT;
2365}
2366
2367#endif /* GLX_USE_APPLEGL */
2368
2369/*
2370** GLX_SGIX_fbconfig
2371** Many of these functions are aliased to GLX 1.3 entry points in the
2372** GLX_functions table.
2373*/
2374
2375PUBLIC
2376GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
2377          (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value),
2378          (dpy, config, attribute, value), glXGetFBConfigAttrib)
2379
2380PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
2381                 (Display * dpy, int screen, int *attrib_list,
2382                  int *nelements), (dpy, screen, attrib_list, nelements),
2383                 glXChooseFBConfig)
2384
2385PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
2386                 (Display * dpy, GLXFBConfigSGIX config),
2387                 (dpy, config), glXGetVisualFromFBConfig)
2388
2389PUBLIC GLXPixmap
2390glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
2391                                 GLXFBConfigSGIX config,
2392                                 Pixmap pixmap)
2393{
2394#ifndef GLX_USE_APPLEGL
2395   xGLXVendorPrivateWithReplyReq *vpreq;
2396   xGLXCreateGLXPixmapWithConfigSGIXReq *req;
2397   GLXPixmap xid = None;
2398   CARD8 opcode;
2399   __GLXscreenConfigs *psc;
2400#endif
2401   const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
2402
2403
2404   if ((dpy == NULL) || (config == NULL)) {
2405      return None;
2406   }
2407#ifdef GLX_USE_APPLEGL
2408   if(apple_glx_pixmap_create(dpy, fbconfig->screen, pixmap, fbconfig))
2409      return None;
2410   return pixmap;
2411#else
2412
2413   psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
2414   if ((psc != NULL)
2415       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
2416      opcode = __glXSetupForCommand(dpy);
2417      if (!opcode) {
2418         return None;
2419      }
2420
2421      /* Send the glXCreateGLXPixmapWithConfigSGIX request */
2422      LockDisplay(dpy);
2423      GetReqExtra(GLXVendorPrivateWithReply,
2424                  sz_xGLXCreateGLXPixmapWithConfigSGIXReq -
2425                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
2426      req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq;
2427      req->reqType = opcode;
2428      req->glxCode = X_GLXVendorPrivateWithReply;
2429      req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
2430      req->screen = fbconfig->screen;
2431      req->fbconfig = fbconfig->fbconfigID;
2432      req->pixmap = pixmap;
2433      req->glxpixmap = xid = XAllocID(dpy);
2434      UnlockDisplay(dpy);
2435      SyncHandle();
2436   }
2437
2438   return xid;
2439#endif
2440}
2441
2442PUBLIC GLXContext
2443glXCreateContextWithConfigSGIX(Display * dpy,
2444                               GLXFBConfigSGIX config, int renderType,
2445                               GLXContext shareList, Bool allowDirect)
2446{
2447   GLXContext gc = NULL;
2448   const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
2449   __GLXscreenConfigs *psc;
2450
2451
2452   if ((dpy == NULL) || (config == NULL)) {
2453      return None;
2454   }
2455
2456   psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
2457   if ((psc != NULL)
2458       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
2459      gc = CreateContext(dpy, fbconfig->fbconfigID, fbconfig, shareList,
2460                         allowDirect,
2461			 X_GLXvop_CreateContextWithConfigSGIX, renderType,
2462			 fbconfig->screen);
2463   }
2464
2465   return gc;
2466}
2467
2468
2469PUBLIC GLXFBConfigSGIX
2470glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
2471{
2472   __GLXdisplayPrivate *priv;
2473   __GLXscreenConfigs *psc = NULL;
2474
2475   if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success)
2476       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
2477       && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) {
2478      return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs,
2479                                                             vis->visualid);
2480   }
2481
2482   return NULL;
2483}
2484
2485#ifndef GLX_USE_APPLEGL
2486/*
2487** GLX_SGIX_swap_group
2488*/
2489static void
2490__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable,
2491                       GLXDrawable member)
2492{
2493   (void) dpy;
2494   (void) drawable;
2495   (void) member;
2496}
2497
2498
2499/*
2500** GLX_SGIX_swap_barrier
2501*/
2502static void
2503__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier)
2504{
2505   (void) dpy;
2506   (void) drawable;
2507   (void) barrier;
2508}
2509
2510static Bool
2511__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max)
2512{
2513   (void) dpy;
2514   (void) screen;
2515   (void) max;
2516   return False;
2517}
2518
2519
2520/*
2521** GLX_OML_sync_control
2522*/
2523static Bool
2524__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
2525                      int64_t * ust, int64_t * msc, int64_t * sbc)
2526{
2527   __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
2528   int i, ret;
2529#ifdef GLX_DIRECT_RENDERING
2530   __GLXDRIdrawable *pdraw;
2531#endif
2532   __GLXscreenConfigs *psc;
2533
2534   if (!priv)
2535      return False;
2536
2537#ifdef GLX_DIRECT_RENDERING
2538   pdraw = GetGLXDRIDrawable(dpy, drawable, &i);
2539#endif
2540   psc = &priv->screenConfigs[i];
2541
2542#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER)
2543   if (pdraw && psc->sbc && psc->msc)
2544      return ( (pdraw && psc->sbc && psc->msc)
2545	       && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0)
2546	       && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0)
2547	       && (__glXGetUST(ust) == 0) );
2548#endif
2549
2550#ifdef GLX_DIRECT_RENDERING
2551   if (pdraw && psc && psc->driScreen && psc->driScreen->getDrawableMSC) {
2552      ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc);
2553      return ret;
2554   }
2555#endif
2556
2557   return False;
2558}
2559
2560#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
2561_X_HIDDEN GLboolean
2562__driGetMscRateOML(__DRIdrawable * draw,
2563                   int32_t * numerator, int32_t * denominator, void *private)
2564{
2565#ifdef XF86VIDMODE
2566   __GLXscreenConfigs *psc;
2567   XF86VidModeModeLine mode_line;
2568   int dot_clock;
2569   int i;
2570   __GLXDRIdrawable *glxDraw = private;
2571
2572   (void) draw;
2573
2574   psc = glxDraw->psc;
2575   if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
2576       XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) {
2577      unsigned n = dot_clock * 1000;
2578      unsigned d = mode_line.vtotal * mode_line.htotal;
2579
2580# define V_INTERLACE 0x010
2581# define V_DBLSCAN   0x020
2582
2583      if (mode_line.flags & V_INTERLACE)
2584         n *= 2;
2585      else if (mode_line.flags & V_DBLSCAN)
2586         d *= 2;
2587
2588      /* The OML_sync_control spec requires that if the refresh rate is a
2589       * whole number, that the returned numerator be equal to the refresh
2590       * rate and the denominator be 1.
2591       */
2592
2593      if (n % d == 0) {
2594         n /= d;
2595         d = 1;
2596      }
2597      else {
2598         static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
2599
2600         /* This is a poor man's way to reduce a fraction.  It's far from
2601          * perfect, but it will work well enough for this situation.
2602          */
2603
2604         for (i = 0; f[i] != 0; i++) {
2605            while (n % f[i] == 0 && d % f[i] == 0) {
2606               d /= f[i];
2607               n /= f[i];
2608            }
2609         }
2610      }
2611
2612      *numerator = n;
2613      *denominator = d;
2614
2615      return True;
2616   }
2617   else
2618      return False;
2619#else
2620   (void) draw;
2621   (void) numerator;
2622   (void) denominator;
2623   (void) private;
2624
2625   return False;
2626#endif
2627}
2628#endif
2629
2630/**
2631 * Determine the refresh rate of the specified drawable and display.
2632 *
2633 * \param dpy          Display whose refresh rate is to be determined.
2634 * \param drawable     Drawable whose refresh rate is to be determined.
2635 * \param numerator    Numerator of the refresh rate.
2636 * \param demoninator  Denominator of the refresh rate.
2637 * \return  If the refresh rate for the specified display and drawable could
2638 *          be calculated, True is returned.  Otherwise False is returned.
2639 *
2640 * \note This function is implemented entirely client-side.  A lot of other
2641 *       functionality is required to export GLX_OML_sync_control, so on
2642 *       XFree86 this function can be called for direct-rendering contexts
2643 *       when GLX_OML_sync_control appears in the client extension string.
2644 */
2645
2646_X_HIDDEN GLboolean
2647__glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
2648                   int32_t * numerator, int32_t * denominator)
2649{
2650#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE )
2651   __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL);
2652
2653   if (draw == NULL)
2654      return False;
2655
2656   return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw);
2657#else
2658   (void) dpy;
2659   (void) drawable;
2660   (void) numerator;
2661   (void) denominator;
2662#endif
2663   return False;
2664}
2665
2666
2667static int64_t
2668__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable,
2669                       int64_t target_msc, int64_t divisor, int64_t remainder)
2670{
2671   GLXContext gc = __glXGetCurrentContext();
2672   int screen;
2673#ifdef GLX_DIRECT_RENDERING
2674   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2675#endif
2676   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2677
2678   if (!gc) /* no GLX for this */
2679      return -1;
2680
2681#ifdef GLX_DIRECT_RENDERING
2682   if (!pdraw || !gc->driContext)
2683      return -1;
2684#endif
2685
2686   /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2687    * error", but it also says "It [glXSwapBuffersMscOML] will return a value
2688    * of -1 if the function failed because of errors detected in the input
2689    * parameters"
2690    */
2691   if (divisor < 0 || remainder < 0 || target_msc < 0)
2692      return -1;
2693   if (divisor > 0 && remainder >= divisor)
2694      return -1;
2695
2696   if (target_msc == 0 && divisor == 0 && remainder == 0)
2697      remainder = 1;
2698
2699#ifdef __DRI_SWAP_BUFFER_COUNTER
2700   if (psc->counters != NULL)
2701      return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc,
2702					 divisor, remainder);
2703#endif
2704
2705#ifdef GLX_DIRECT_RENDERING
2706   if (psc->driScreen && psc->driScreen->swapBuffers)
2707      return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor,
2708					    remainder);
2709#endif
2710
2711   return -1;
2712}
2713
2714
2715static Bool
2716__glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
2717                   int64_t target_msc, int64_t divisor,
2718                   int64_t remainder, int64_t * ust,
2719                   int64_t * msc, int64_t * sbc)
2720{
2721   int screen;
2722#ifdef GLX_DIRECT_RENDERING
2723   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2724#endif
2725   __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
2726   int ret;
2727
2728
2729   /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2730    * error", but the return type in the spec is Bool.
2731    */
2732   if (divisor < 0 || remainder < 0 || target_msc < 0)
2733      return False;
2734   if (divisor > 0 && remainder >= divisor)
2735      return False;
2736
2737#ifdef __DRI_MEDIA_STREAM_COUNTER
2738   if (pdraw != NULL && psc->msc != NULL) {
2739      ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc,
2740                                     divisor, remainder, msc, sbc);
2741
2742      /* __glXGetUST returns zero on success and non-zero on failure.
2743       * This function returns True on success and False on failure.
2744       */
2745      return ((ret == 0) && (__glXGetUST(ust) == 0));
2746   }
2747#endif
2748
2749#ifdef GLX_DIRECT_RENDERING
2750   if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) {
2751      ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder,
2752				       ust, msc, sbc);
2753      return ret;
2754   }
2755#endif
2756
2757   return False;
2758}
2759
2760
2761static Bool
2762__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
2763                   int64_t target_sbc, int64_t * ust,
2764                   int64_t * msc, int64_t * sbc)
2765{
2766   int screen;
2767#ifdef GLX_DIRECT_RENDERING
2768   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2769#endif
2770   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2771   int ret;
2772
2773   /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE
2774    * error", but the return type in the spec is Bool.
2775    */
2776   if (target_sbc < 0)
2777      return False;
2778#ifdef __DRI_SWAP_BUFFER_COUNTER
2779   if (pdraw != NULL && psc->sbc != NULL) {
2780      ret =
2781         (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc);
2782
2783      /* __glXGetUST returns zero on success and non-zero on failure.
2784       * This function returns True on success and False on failure.
2785       */
2786      return ((ret == 0) && (__glXGetUST(ust) == 0));
2787   }
2788#endif
2789
2790#ifdef GLX_DIRECT_RENDERING
2791   if (pdraw && psc->driScreen && psc->driScreen->waitForSBC) {
2792      ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc);
2793      return ret;
2794   }
2795#endif
2796
2797   return False;
2798}
2799
2800
2801/**
2802 * GLX_MESA_allocate_memory
2803 */
2804/*@{*/
2805
2806PUBLIC void *
2807glXAllocateMemoryMESA(Display * dpy, int scrn,
2808                      size_t size, float readFreq,
2809                      float writeFreq, float priority)
2810{
2811#ifdef __DRI_ALLOCATE
2812   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
2813
2814   if (psc && psc->allocate)
2815      return (*psc->allocate->allocateMemory) (psc->__driScreen, size,
2816                                               readFreq, writeFreq, priority);
2817
2818#else
2819   (void) dpy;
2820   (void) scrn;
2821   (void) size;
2822   (void) readFreq;
2823   (void) writeFreq;
2824   (void) priority;
2825#endif /* __DRI_ALLOCATE */
2826
2827   return NULL;
2828}
2829
2830
2831PUBLIC void
2832glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer)
2833{
2834#ifdef __DRI_ALLOCATE
2835   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
2836
2837   if (psc && psc->allocate)
2838      (*psc->allocate->freeMemory) (psc->__driScreen, pointer);
2839
2840#else
2841   (void) dpy;
2842   (void) scrn;
2843   (void) pointer;
2844#endif /* __DRI_ALLOCATE */
2845}
2846
2847
2848PUBLIC GLuint
2849glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer)
2850{
2851#ifdef __DRI_ALLOCATE
2852   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
2853
2854   if (psc && psc->allocate)
2855      return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer);
2856
2857#else
2858   (void) dpy;
2859   (void) scrn;
2860   (void) pointer;
2861#endif /* GLX_DIRECT_RENDERING */
2862
2863   return ~0L;
2864}
2865
2866/*@}*/
2867
2868
2869/**
2870 * Mesa extension stubs.  These will help reduce portability problems.
2871 */
2872/*@{*/
2873
2874/**
2875 * Release all buffers associated with the specified GLX drawable.
2876 *
2877 * \todo
2878 * This function was intended for stand-alone Mesa.  The issue there is that
2879 * the library doesn't get any notification when a window is closed.  In
2880 * DRI there is a similar but slightly different issue.  When GLX 1.3 is
2881 * supported, there are 3 different functions to destroy a drawable.  It
2882 * should be possible to create GLX protocol (or have it determine which
2883 * protocol to use based on the type of the drawable) to have one function
2884 * do the work of 3.  For the direct-rendering case, this function could
2885 * just call the driver's \c __DRIdrawableRec::destroyDrawable function.
2886 * This would reduce the frequency with which \c __driGarbageCollectDrawables
2887 * would need to be used.  This really should be done as part of the new DRI
2888 * interface work.
2889 *
2890 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt
2891 *     __driGarbageCollectDrawables
2892 *     glXDestroyGLXPixmap
2893 *     glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow
2894 *     glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX
2895 */
2896static Bool
2897__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d)
2898{
2899   (void) dpy;
2900   (void) d;
2901   return False;
2902}
2903
2904
2905PUBLIC GLXPixmap
2906glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual,
2907                       Pixmap pixmap, Colormap cmap)
2908{
2909   (void) dpy;
2910   (void) visual;
2911   (void) pixmap;
2912   (void) cmap;
2913   return 0;
2914}
2915
2916/*@}*/
2917
2918
2919/**
2920 * GLX_MESA_copy_sub_buffer
2921 */
2922#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
2923static void
2924__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable,
2925                       int x, int y, int width, int height)
2926{
2927   xGLXVendorPrivateReq *req;
2928   GLXContext gc;
2929   GLXContextTag tag;
2930   CARD32 *drawable_ptr;
2931   INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
2932   CARD8 opcode;
2933
2934#ifdef __DRI_COPY_SUB_BUFFER
2935   int screen;
2936   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2937   if (pdraw != NULL) {
2938      __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2939      if (psc->driScreen->copySubBuffer != NULL) {
2940         glFlush();
2941         (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height);
2942      }
2943
2944      return;
2945   }
2946#endif
2947
2948   opcode = __glXSetupForCommand(dpy);
2949   if (!opcode)
2950      return;
2951
2952   /*
2953    ** The calling thread may or may not have a current context.  If it
2954    ** does, send the context tag so the server can do a flush.
2955    */
2956   gc = __glXGetCurrentContext();
2957   if ((gc != NULL) && (dpy == gc->currentDpy) &&
2958       ((drawable == gc->currentDrawable) ||
2959        (drawable == gc->currentReadable))) {
2960      tag = gc->currentContextTag;
2961   }
2962   else {
2963      tag = 0;
2964   }
2965
2966   LockDisplay(dpy);
2967   GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req);
2968   req->reqType = opcode;
2969   req->glxCode = X_GLXVendorPrivate;
2970   req->vendorCode = X_GLXvop_CopySubBufferMESA;
2971   req->contextTag = tag;
2972
2973   drawable_ptr = (CARD32 *) (req + 1);
2974   x_ptr = (INT32 *) (drawable_ptr + 1);
2975   y_ptr = (INT32 *) (drawable_ptr + 2);
2976   w_ptr = (INT32 *) (drawable_ptr + 3);
2977   h_ptr = (INT32 *) (drawable_ptr + 4);
2978
2979   *drawable_ptr = drawable;
2980   *x_ptr = x;
2981   *y_ptr = y;
2982   *w_ptr = width;
2983   *h_ptr = height;
2984
2985   UnlockDisplay(dpy);
2986   SyncHandle();
2987}
2988
2989
2990/**
2991 * GLX_EXT_texture_from_pixmap
2992 */
2993/*@{*/
2994static void
2995__glXBindTexImageEXT(Display * dpy,
2996                     GLXDrawable drawable, int buffer, const int *attrib_list)
2997{
2998   xGLXVendorPrivateReq *req;
2999   GLXContext gc = __glXGetCurrentContext();
3000   CARD32 *drawable_ptr;
3001   INT32 *buffer_ptr;
3002   CARD32 *num_attrib_ptr;
3003   CARD32 *attrib_ptr;
3004   CARD8 opcode;
3005   unsigned int i;
3006
3007   if (gc == NULL)
3008      return;
3009
3010   i = 0;
3011   if (attrib_list) {
3012      while (attrib_list[i * 2] != None)
3013         i++;
3014   }
3015
3016#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
3017   if (gc->driContext) {
3018      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
3019
3020      if (pdraw != NULL) {
3021         if (pdraw->psc->texBuffer->base.version >= 2 &&
3022             pdraw->psc->texBuffer->setTexBuffer2 != NULL) {
3023            (*pdraw->psc->texBuffer->setTexBuffer2) (gc->__driContext,
3024                                                     pdraw->textureTarget,
3025                                                     pdraw->textureFormat,
3026                                                     pdraw->driDrawable);
3027         }
3028         else {
3029            (*pdraw->psc->texBuffer->setTexBuffer) (gc->__driContext,
3030                                                    pdraw->textureTarget,
3031                                                    pdraw->driDrawable);
3032         }
3033      }
3034      return;
3035   }
3036#endif
3037
3038   opcode = __glXSetupForCommand(dpy);
3039   if (!opcode)
3040      return;
3041
3042   LockDisplay(dpy);
3043   GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
3044   req->reqType = opcode;
3045   req->glxCode = X_GLXVendorPrivate;
3046   req->vendorCode = X_GLXvop_BindTexImageEXT;
3047   req->contextTag = gc->currentContextTag;
3048
3049   drawable_ptr = (CARD32 *) (req + 1);
3050   buffer_ptr = (INT32 *) (drawable_ptr + 1);
3051   num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
3052   attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
3053
3054   *drawable_ptr = drawable;
3055   *buffer_ptr = buffer;
3056   *num_attrib_ptr = (CARD32) i;
3057
3058   i = 0;
3059   if (attrib_list) {
3060      while (attrib_list[i * 2] != None) {
3061         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
3062         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
3063         i++;
3064      }
3065   }
3066
3067   UnlockDisplay(dpy);
3068   SyncHandle();
3069}
3070
3071static void
3072__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer)
3073{
3074   xGLXVendorPrivateReq *req;
3075   GLXContext gc = __glXGetCurrentContext();
3076   CARD32 *drawable_ptr;
3077   INT32 *buffer_ptr;
3078   CARD8 opcode;
3079
3080   if ((gc == NULL) || GC_IS_DIRECT(gc))
3081      return;
3082
3083   opcode = __glXSetupForCommand(dpy);
3084   if (!opcode)
3085      return;
3086
3087   LockDisplay(dpy);
3088   GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
3089   req->reqType = opcode;
3090   req->glxCode = X_GLXVendorPrivate;
3091   req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
3092   req->contextTag = gc->currentContextTag;
3093
3094   drawable_ptr = (CARD32 *) (req + 1);
3095   buffer_ptr = (INT32 *) (drawable_ptr + 1);
3096
3097   *drawable_ptr = drawable;
3098   *buffer_ptr = buffer;
3099
3100   UnlockDisplay(dpy);
3101   SyncHandle();
3102}
3103
3104/*@}*/
3105
3106#endif /* GLX_USE_APPLEGL */
3107
3108/**
3109 * \c strdup is actually not a standard ANSI C or POSIX routine.
3110 * Irix will not define it if ANSI mode is in effect.
3111 *
3112 * \sa strdup
3113 */
3114_X_HIDDEN char *
3115__glXstrdup(const char *str)
3116{
3117   char *copy;
3118   copy = (char *) Xmalloc(strlen(str) + 1);
3119   if (!copy)
3120      return NULL;
3121   strcpy(copy, str);
3122   return copy;
3123}
3124
3125/*
3126** glXGetProcAddress support
3127*/
3128
3129struct name_address_pair
3130{
3131   const char *Name;
3132   GLvoid *Address;
3133};
3134
3135#define GLX_FUNCTION(f) { # f, (GLvoid *) f }
3136#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f }
3137
3138static const struct name_address_pair GLX_functions[] = {
3139   /*** GLX_VERSION_1_0 ***/
3140   GLX_FUNCTION(glXChooseVisual),
3141   GLX_FUNCTION(glXCopyContext),
3142   GLX_FUNCTION(glXCreateContext),
3143   GLX_FUNCTION(glXCreateGLXPixmap),
3144   GLX_FUNCTION(glXDestroyContext),
3145   GLX_FUNCTION(glXDestroyGLXPixmap),
3146   GLX_FUNCTION(glXGetConfig),
3147   GLX_FUNCTION(glXGetCurrentContext),
3148   GLX_FUNCTION(glXGetCurrentDrawable),
3149   GLX_FUNCTION(glXIsDirect),
3150   GLX_FUNCTION(glXMakeCurrent),
3151   GLX_FUNCTION(glXQueryExtension),
3152   GLX_FUNCTION(glXQueryVersion),
3153   GLX_FUNCTION(glXSwapBuffers),
3154   GLX_FUNCTION(glXUseXFont),
3155   GLX_FUNCTION(glXWaitGL),
3156   GLX_FUNCTION(glXWaitX),
3157
3158   /*** GLX_VERSION_1_1 ***/
3159   GLX_FUNCTION(glXGetClientString),
3160   GLX_FUNCTION(glXQueryExtensionsString),
3161   GLX_FUNCTION(glXQueryServerString),
3162
3163   /*** GLX_VERSION_1_2 ***/
3164   GLX_FUNCTION(glXGetCurrentDisplay),
3165
3166   /*** GLX_VERSION_1_3 ***/
3167   GLX_FUNCTION(glXChooseFBConfig),
3168   GLX_FUNCTION(glXCreateNewContext),
3169   GLX_FUNCTION(glXCreatePbuffer),
3170   GLX_FUNCTION(glXCreatePixmap),
3171   GLX_FUNCTION(glXCreateWindow),
3172   GLX_FUNCTION(glXDestroyPbuffer),
3173   GLX_FUNCTION(glXDestroyPixmap),
3174   GLX_FUNCTION(glXDestroyWindow),
3175   GLX_FUNCTION(glXGetCurrentReadDrawable),
3176   GLX_FUNCTION(glXGetFBConfigAttrib),
3177   GLX_FUNCTION(glXGetFBConfigs),
3178   GLX_FUNCTION(glXGetSelectedEvent),
3179   GLX_FUNCTION(glXGetVisualFromFBConfig),
3180   GLX_FUNCTION(glXMakeContextCurrent),
3181   GLX_FUNCTION(glXQueryContext),
3182   GLX_FUNCTION(glXQueryDrawable),
3183   GLX_FUNCTION(glXSelectEvent),
3184
3185#ifndef GLX_USE_APPLEGL
3186   /*** GLX_SGI_swap_control ***/
3187   GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI),
3188
3189   /*** GLX_SGI_video_sync ***/
3190   GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI),
3191   GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI),
3192
3193   /*** GLX_SGI_make_current_read ***/
3194   GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent),
3195   GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable),
3196
3197   /*** GLX_EXT_import_context ***/
3198   GLX_FUNCTION(glXFreeContextEXT),
3199   GLX_FUNCTION(glXGetContextIDEXT),
3200   GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay),
3201   GLX_FUNCTION(glXImportContextEXT),
3202   GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext),
3203#endif
3204
3205   /*** GLX_SGIX_fbconfig ***/
3206   GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib),
3207   GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig),
3208   GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX),
3209   GLX_FUNCTION(glXCreateContextWithConfigSGIX),
3210   GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig),
3211   GLX_FUNCTION(glXGetFBConfigFromVisualSGIX),
3212
3213#ifndef GLX_USE_APPLEGL
3214   /*** GLX_SGIX_pbuffer ***/
3215   GLX_FUNCTION(glXCreateGLXPbufferSGIX),
3216   GLX_FUNCTION(glXDestroyGLXPbufferSGIX),
3217   GLX_FUNCTION(glXQueryGLXPbufferSGIX),
3218   GLX_FUNCTION(glXSelectEventSGIX),
3219   GLX_FUNCTION(glXGetSelectedEventSGIX),
3220
3221   /*** GLX_SGIX_swap_group ***/
3222   GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX),
3223
3224   /*** GLX_SGIX_swap_barrier ***/
3225   GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX),
3226   GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX),
3227
3228   /*** GLX_MESA_allocate_memory ***/
3229   GLX_FUNCTION(glXAllocateMemoryMESA),
3230   GLX_FUNCTION(glXFreeMemoryMESA),
3231   GLX_FUNCTION(glXGetMemoryOffsetMESA),
3232
3233   /*** GLX_MESA_copy_sub_buffer ***/
3234   GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA),
3235
3236   /*** GLX_MESA_pixmap_colormap ***/
3237   GLX_FUNCTION(glXCreateGLXPixmapMESA),
3238
3239   /*** GLX_MESA_release_buffers ***/
3240   GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA),
3241
3242   /*** GLX_MESA_swap_control ***/
3243   GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA),
3244   GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA),
3245
3246   /*** GLX_MESA_swap_frame_usage ***/
3247   GLX_FUNCTION2(glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA),
3248   GLX_FUNCTION2(glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA),
3249   GLX_FUNCTION2(glXGetFrameUsageMESA, __glXGetFrameUsageMESA),
3250   GLX_FUNCTION2(glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA),
3251#endif
3252
3253   /*** GLX_ARB_get_proc_address ***/
3254   GLX_FUNCTION(glXGetProcAddressARB),
3255
3256   /*** GLX 1.4 ***/
3257   GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB),
3258
3259#ifndef GLX_USE_APPLEGL
3260   /*** GLX_OML_sync_control ***/
3261   GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML),
3262   GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML),
3263   GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML),
3264   GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML),
3265   GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML),
3266
3267   /*** GLX_EXT_texture_from_pixmap ***/
3268   GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT),
3269   GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT),
3270#endif
3271
3272#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
3273   /*** DRI configuration ***/
3274   GLX_FUNCTION(glXGetScreenDriver),
3275   GLX_FUNCTION(glXGetDriverConfig),
3276#endif
3277
3278   {NULL, NULL}                 /* end of list */
3279};
3280
3281#ifndef GLX_USE_APPLEGL
3282static const GLvoid *
3283get_glx_proc_address(const char *funcName)
3284{
3285   GLuint i;
3286
3287   /* try static functions */
3288   for (i = 0; GLX_functions[i].Name; i++) {
3289      if (strcmp(GLX_functions[i].Name, funcName) == 0)
3290         return GLX_functions[i].Address;
3291   }
3292
3293   return NULL;
3294}
3295#endif
3296
3297/**
3298 * Get the address of a named GL function.  This is the pre-GLX 1.4 name for
3299 * \c glXGetProcAddress.
3300 *
3301 * \param procName  Name of a GL or GLX function.
3302 * \returns         A pointer to the named function
3303 *
3304 * \sa glXGetProcAddress
3305 */
3306PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
3307{
3308   typedef void (*gl_function) (void);
3309   gl_function f;
3310
3311
3312   /* Search the table of GLX and internal functions first.  If that
3313    * fails and the supplied name could be a valid core GL name, try
3314    * searching the core GL function table.  This check is done to prevent
3315    * DRI based drivers from searching the core GL function table for
3316    * internal API functions.
3317    */
3318#ifdef GLX_USE_APPLEGL
3319   f = (gl_function) apple_glx_get_proc_address(procName);
3320#else
3321   f = (gl_function) get_glx_proc_address((const char *) procName);
3322   if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
3323       && (procName[2] != 'X')) {
3324      f = (gl_function) _glapi_get_proc_address((const char *) procName);
3325   }
3326#endif
3327   return f;
3328}
3329
3330/**
3331 * Get the address of a named GL function.  This is the GLX 1.4 name for
3332 * \c glXGetProcAddressARB.
3333 *
3334 * \param procName  Name of a GL or GLX function.
3335 * \returns         A pointer to the named function
3336 *
3337 * \sa glXGetProcAddressARB
3338 */
3339PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void)
3340#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED)
3341   __attribute__ ((alias("glXGetProcAddressARB")));
3342#else
3343{
3344   return glXGetProcAddressARB(procName);
3345}
3346#endif /* __GNUC__ */
3347
3348
3349#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
3350/**
3351 * Get the unadjusted system time (UST).  Currently, the UST is measured in
3352 * microseconds since Epoc.  The actual resolution of the UST may vary from
3353 * system to system, and the units may vary from release to release.
3354 * Drivers should not call this function directly.  They should instead use
3355 * \c glXGetProcAddress to obtain a pointer to the function.
3356 *
3357 * \param ust Location to store the 64-bit UST
3358 * \returns Zero on success or a negative errno value on failure.
3359 *
3360 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
3361 *
3362 * \since Internal API version 20030317.
3363 */
3364_X_HIDDEN int
3365__glXGetUST(int64_t * ust)
3366{
3367   struct timeval tv;
3368
3369   if (ust == NULL) {
3370      return -EFAULT;
3371   }
3372
3373   if (gettimeofday(&tv, NULL) == 0) {
3374      ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
3375      return 0;
3376   }
3377   else {
3378      return -errno;
3379   }
3380}
3381#endif /* GLX_DIRECT_RENDERING */
3382