glxcmds.c revision f972115d33e391499e049b83a1559959f2ca9f72
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";
65static const struct glx_context_vtable glx_indirect_context_vtable;
66
67#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
68
69static Bool windowExistsFlag;
70static int
71windowExistsErrorHandler(Display * dpy, XErrorEvent * xerr)
72{
73   (void) dpy;
74
75   if (xerr->error_code == BadWindow) {
76      windowExistsFlag = GL_FALSE;
77   }
78   return 0;
79}
80
81/**
82 * Find drawables in the local hash that have been destroyed on the
83 * server.
84 *
85 * \param dpy    Display to destroy drawables for
86 * \param screen Screen number to destroy drawables for
87 */
88static void
89GarbageCollectDRIDrawables(Display * dpy, __GLXscreenConfigs * sc)
90{
91   XID draw;
92   __GLXDRIdrawable *pdraw;
93   XWindowAttributes xwa;
94   int (*oldXErrorHandler) (Display *, XErrorEvent *);
95
96   /* Set no-op error handler so Xlib doesn't bail out if the windows
97    * has alreay been destroyed on the server. */
98   XSync(dpy, GL_FALSE);
99   oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
100
101   if (__glxHashFirst(sc->drawHash, &draw, (void *) &pdraw) == 1) {
102      do {
103         windowExistsFlag = GL_TRUE;
104         XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
105         if (!windowExistsFlag) {
106            /* Destroy the local drawable data, if the drawable no
107               longer exists in the Xserver */
108            (*pdraw->destroyDrawable) (pdraw);
109            __glxHashDelete(sc->drawHash, draw);
110         }
111      } while (__glxHashNext(sc->drawHash, &draw, (void *) &pdraw) == 1);
112   }
113
114   XSync(dpy, GL_FALSE);
115   XSetErrorHandler(oldXErrorHandler);
116}
117
118/**
119 * Get the __DRIdrawable for the drawable associated with a GLXContext
120 *
121 * \param dpy       The display associated with \c drawable.
122 * \param drawable  GLXDrawable whose __DRIdrawable part is to be retrieved.
123 * \param scrn_num  If non-NULL, the drawables screen is stored there
124 * \returns  A pointer to the context's __DRIdrawable on success, or NULL if
125 *           the drawable is not associated with a direct-rendering context.
126 */
127_X_HIDDEN __GLXDRIdrawable *
128GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable, int *const scrn_num)
129{
130   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
131   __GLXDRIdrawable *pdraw;
132   const unsigned screen_count = ScreenCount(dpy);
133   unsigned i;
134   __GLXscreenConfigs *psc;
135
136   if (priv == NULL)
137      return NULL;
138
139   for (i = 0; i < screen_count; i++) {
140      psc = priv->screenConfigs[i];
141      if (psc->drawHash == NULL)
142         continue;
143
144      if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) {
145         if (scrn_num != NULL)
146            *scrn_num = i;
147         return pdraw;
148      }
149   }
150
151   return NULL;
152}
153
154#endif
155
156
157/**
158 * Get the GLX per-screen data structure associated with a GLX context.
159 *
160 * \param dpy   Display for which the GLX per-screen information is to be
161 *              retrieved.
162 * \param scrn  Screen on \c dpy for which the GLX per-screen information is
163 *              to be retrieved.
164 * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
165 *          specify a valid GLX screen, or NULL otherwise.
166 *
167 * \todo Should this function validate that \c scrn is within the screen
168 *       number range for \c dpy?
169 */
170
171static __GLXscreenConfigs *
172GetGLXScreenConfigs(Display * dpy, int scrn)
173{
174   __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
175
176   return (priv
177           && priv->screenConfigs !=
178           NULL) ? priv->screenConfigs[scrn] : NULL;
179}
180
181
182static int
183GetGLXPrivScreenConfig(Display * dpy, int scrn, __GLXdisplayPrivate ** ppriv,
184                       __GLXscreenConfigs ** ppsc)
185{
186   /* Initialize the extension, if needed .  This has the added value
187    * of initializing/allocating the display private
188    */
189
190   if (dpy == NULL) {
191      return GLX_NO_EXTENSION;
192   }
193
194   *ppriv = __glXInitialize(dpy);
195   if (*ppriv == NULL) {
196      return GLX_NO_EXTENSION;
197   }
198
199   /* Check screen number to see if its valid */
200   if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
201      return GLX_BAD_SCREEN;
202   }
203
204   /* Check to see if the GL is supported on this screen */
205   *ppsc = (*ppriv)->screenConfigs[scrn];
206   if ((*ppsc)->configs == NULL) {
207      /* No support for GL on this screen regardless of visual */
208      return GLX_BAD_VISUAL;
209   }
210
211   return Success;
212}
213
214
215/**
216 * Determine if a \c GLXFBConfig supplied by the application is valid.
217 *
218 * \param dpy     Application supplied \c Display pointer.
219 * \param config  Application supplied \c GLXFBConfig.
220 *
221 * \returns If the \c GLXFBConfig is valid, the a pointer to the matching
222 *          \c __GLcontextModes structure is returned.  Otherwise, \c NULL
223 *          is returned.
224 */
225static __GLcontextModes *
226ValidateGLXFBConfig(Display * dpy, GLXFBConfig config)
227{
228   __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
229   const unsigned num_screens = ScreenCount(dpy);
230   unsigned i;
231   const __GLcontextModes *modes;
232
233
234   if (priv != NULL) {
235      for (i = 0; i < num_screens; i++) {
236         for (modes = priv->screenConfigs[i]->configs; modes != NULL;
237              modes = modes->next) {
238            if (modes == (__GLcontextModes *) config) {
239               return (__GLcontextModes *) config;
240            }
241         }
242      }
243   }
244
245   return NULL;
246}
247
248
249/**
250 * \todo It should be possible to move the allocate of \c client_state_private
251 * later in the function for direct-rendering contexts.  Direct-rendering
252 * contexts don't need to track client state, so they don't need that memory
253 * at all.
254 *
255 * \todo Eliminate \c __glXInitVertexArrayState.  Replace it with a new
256 * function called \c __glXAllocateClientState that allocates the memory and
257 * does all the initialization (including the pixel pack / unpack).
258 */
259static GLXContext
260AllocateGLXContext(Display * dpy)
261{
262   GLXContext gc;
263   int bufSize;
264   CARD8 opcode;
265   __GLXattribute *state;
266
267   if (!dpy)
268      return NULL;
269
270   opcode = __glXSetupForCommand(dpy);
271   if (!opcode) {
272      return NULL;
273   }
274
275   /* Allocate our context record */
276   gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec));
277   if (!gc) {
278      /* Out of memory */
279      return NULL;
280   }
281   memset(gc, 0, sizeof(struct __GLXcontextRec));
282
283   state = Xmalloc(sizeof(struct __GLXattributeRec));
284   if (state == NULL) {
285      /* Out of memory */
286      Xfree(gc);
287      return NULL;
288   }
289   gc->client_state_private = state;
290   memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec));
291   state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
292
293   /*
294    ** Create a temporary buffer to hold GLX rendering commands.  The size
295    ** of the buffer is selected so that the maximum number of GLX rendering
296    ** commands can fit in a single X packet and still have room in the X
297    ** packet for the GLXRenderReq header.
298    */
299
300   bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;
301   gc->buf = (GLubyte *) Xmalloc(bufSize);
302   if (!gc->buf) {
303      Xfree(gc->client_state_private);
304      Xfree(gc);
305      return NULL;
306   }
307   gc->bufSize = bufSize;
308
309   /* Fill in the new context */
310   gc->renderMode = GL_RENDER;
311
312   state->storePack.alignment = 4;
313   state->storeUnpack.alignment = 4;
314
315   gc->attributes.stackPointer = &gc->attributes.stack[0];
316
317   /*
318    ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
319    ** Other code uses the fastImageUnpack bit, but it is never set
320    ** to GL_TRUE.
321    */
322   gc->fastImageUnpack = GL_FALSE;
323   gc->fillImage = __glFillImage;
324   gc->pc = gc->buf;
325   gc->bufEnd = gc->buf + bufSize;
326   gc->isDirect = GL_FALSE;
327   if (__glXDebug) {
328      /*
329       ** Set limit register so that there will be one command per packet
330       */
331      gc->limit = gc->buf;
332   }
333   else {
334      gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
335   }
336   gc->createDpy = dpy;
337   gc->majorOpcode = opcode;
338
339   /*
340    ** Constrain the maximum drawing command size allowed to be
341    ** transfered using the X_GLXRender protocol request.  First
342    ** constrain by a software limit, then constrain by the protocl
343    ** limit.
344    */
345   if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
346      bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
347   }
348   if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
349      bufSize = __GLX_MAX_RENDER_CMD_SIZE;
350   }
351   gc->maxSmallRenderCommandSize = bufSize;
352
353#ifdef GLX_USE_APPLEGL
354   gc->driContext = NULL;
355   gc->do_destroy = False;
356#endif
357
358   return gc;
359}
360
361
362/**
363 * Create a new context.  Exactly one of \c vis and \c fbconfig should be
364 * non-NULL.
365 *
366 * \param use_glx_1_3  For FBConfigs, should GLX 1.3 protocol or
367 *                     SGIX_fbconfig protocol be used?
368 * \param renderType   For FBConfigs, what is the rendering type?
369 */
370
371static GLXContext
372CreateContext(Display * dpy, int generic_id,
373              const __GLcontextModes * const fbconfig,
374              GLXContext shareList,
375              Bool allowDirect,
376	      unsigned code, int renderType, int screen)
377{
378   GLXContext gc;
379   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
380#if defined(GLX_DIRECT_RENDERING) && defined(GLX_USE_APPLEGL)
381   int errorcode;
382   bool x11error;
383#endif
384
385   if (dpy == NULL)
386      return NULL;
387
388   if (generic_id == None)
389      return NULL;
390
391   gc = AllocateGLXContext(dpy);
392   if (!gc)
393      return NULL;
394
395#ifndef GLX_USE_APPLEGL  /* TODO: darwin indirect */
396#ifdef GLX_DIRECT_RENDERING
397   if (allowDirect && psc->driScreen) {
398      gc->driContext = psc->driScreen->createContext(psc, fbconfig, gc,
399						     shareList, renderType);
400      if (gc->driContext != NULL) {
401	 gc->screen = screen;
402	 gc->psc = psc;
403	 gc->mode = fbconfig;
404	 gc->isDirect = GL_TRUE;
405      }
406   }
407#endif
408
409   if (gc->driContext != NULL)
410      gc->vtable = psc->direct_context_vtable;
411   else
412      gc->vtable = &glx_indirect_context_vtable;
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
1770	 /* Look up screen first so we can look up visuals/fbconfigs later */
1771         pProp = propList;
1772         for (i = 0; i < numValues; i++, pProp += 2)
1773	     if (pProp[0] == GLX_SCREEN) {
1774		 ctx->screen = pProp[1];
1775		 ctx->psc = GetGLXScreenConfigs(dpy, ctx->screen);
1776	     }
1777
1778         pProp = propList;
1779         for (i = 0; i < numValues; i++) {
1780            switch (*pProp++) {
1781            case GLX_SHARE_CONTEXT_EXT:
1782               ctx->share_xid = *pProp++;
1783               break;
1784            case GLX_VISUAL_ID_EXT:
1785               ctx->mode =
1786                  _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++);
1787               break;
1788            case GLX_FBCONFIG_ID:
1789               ctx->mode =
1790                  _gl_context_modes_find_fbconfig(ctx->psc->configs,
1791                                                  *pProp++);
1792               break;
1793            case GLX_RENDER_TYPE:
1794               ctx->renderType = *pProp++;
1795               break;
1796            case GLX_SCREEN:
1797            default:
1798               pProp++;
1799               continue;
1800            }
1801         }
1802         Xfree((char *) propList);
1803         retval = Success;
1804      }
1805   }
1806   UnlockDisplay(dpy);
1807   SyncHandle();
1808   return retval;
1809}
1810
1811#endif
1812
1813PUBLIC int
1814glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int *value)
1815{
1816#ifndef GLX_USE_APPLEGL
1817   int retVal;
1818
1819   /* get the information from the server if we don't have it already */
1820#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
1821   if (!ctx->driContext && (ctx->mode == NULL)) {
1822#else
1823   if (ctx->mode == NULL) {
1824#endif
1825      retVal = __glXQueryContextInfo(dpy, ctx);
1826      if (Success != retVal)
1827         return retVal;
1828   }
1829#endif
1830
1831   switch (attribute) {
1832#ifndef GLX_USE_APPLEGL
1833      case GLX_SHARE_CONTEXT_EXT:
1834      *value = (int) (ctx->share_xid);
1835      break;
1836   case GLX_VISUAL_ID_EXT:
1837      *value = ctx->mode ? ctx->mode->visualID : None;
1838      break;
1839#endif
1840   case GLX_SCREEN:
1841      *value = (int) (ctx->screen);
1842      break;
1843   case GLX_FBCONFIG_ID:
1844      *value = ctx->mode ? ctx->mode->fbconfigID : None;
1845      break;
1846   case GLX_RENDER_TYPE:
1847      *value = (int) (ctx->renderType);
1848      break;
1849   default:
1850      return GLX_BAD_ATTRIBUTE;
1851   }
1852   return Success;
1853}
1854
1855PUBLIC
1856GLX_ALIAS(int, glXQueryContextInfoEXT,
1857          (Display * dpy, GLXContext ctx, int attribute, int *value),
1858          (dpy, ctx, attribute, value), glXQueryContext)
1859
1860PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx)
1861{
1862   return ctx->xid;
1863}
1864
1865PUBLIC GLXContext
1866glXImportContextEXT(Display * dpy, GLXContextID contextID)
1867{
1868#ifdef GLX_USE_APPLEGL
1869   return NULL;
1870#else
1871   GLXContext ctx;
1872
1873   if (contextID == None) {
1874      return NULL;
1875   }
1876   if (__glXIsDirect(dpy, contextID)) {
1877      return NULL;
1878   }
1879
1880   ctx = AllocateGLXContext(dpy);
1881   if (NULL != ctx) {
1882      ctx->xid = contextID;
1883      ctx->imported = GL_TRUE;
1884
1885      if (Success != __glXQueryContextInfo(dpy, ctx)) {
1886	 __glXFreeContext(ctx);
1887	 ctx = NULL;
1888      }
1889   }
1890   return ctx;
1891#endif
1892}
1893
1894PUBLIC void
1895glXFreeContextEXT(Display * dpy, GLXContext ctx)
1896{
1897   DestroyContext(dpy, ctx);
1898}
1899
1900
1901
1902/*
1903 * GLX 1.3 functions - these are just stubs for now!
1904 */
1905
1906PUBLIC GLXFBConfig *
1907glXChooseFBConfig(Display * dpy, int screen,
1908                  const int *attribList, int *nitems)
1909{
1910   __GLcontextModes **config_list;
1911   int list_size;
1912
1913
1914   config_list = (__GLcontextModes **)
1915      glXGetFBConfigs(dpy, screen, &list_size);
1916
1917   if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) {
1918      list_size = choose_visual(config_list, list_size, attribList, GL_TRUE);
1919      if (list_size == 0) {
1920         XFree(config_list);
1921         config_list = NULL;
1922      }
1923   }
1924
1925   *nitems = list_size;
1926   return (GLXFBConfig *) config_list;
1927}
1928
1929
1930PUBLIC GLXContext
1931glXCreateNewContext(Display * dpy, GLXFBConfig config,
1932                    int renderType, GLXContext shareList, Bool allowDirect)
1933{
1934   const __GLcontextModes *const fbconfig =
1935      (const __GLcontextModes *const) config;
1936
1937   return CreateContext(dpy, fbconfig->fbconfigID, fbconfig, shareList,
1938                        allowDirect, X_GLXCreateNewContext, renderType,
1939			fbconfig->screen);
1940}
1941
1942
1943PUBLIC GLXDrawable
1944glXGetCurrentReadDrawable(void)
1945{
1946   GLXContext gc = __glXGetCurrentContext();
1947   return gc->currentReadable;
1948}
1949
1950
1951PUBLIC GLXFBConfig *
1952glXGetFBConfigs(Display * dpy, int screen, int *nelements)
1953{
1954   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1955   __GLcontextModes **config = NULL;
1956   int i;
1957
1958   *nelements = 0;
1959   if (priv && (priv->screenConfigs != NULL)
1960       && (screen >= 0) && (screen <= ScreenCount(dpy))
1961       && (priv->screenConfigs[screen]->configs != NULL)
1962       && (priv->screenConfigs[screen]->configs->fbconfigID
1963	   != (int) GLX_DONT_CARE)) {
1964      unsigned num_configs = 0;
1965      __GLcontextModes *modes;
1966
1967
1968      for (modes = priv->screenConfigs[screen]->configs; modes != NULL;
1969           modes = modes->next) {
1970         if (modes->fbconfigID != (int) GLX_DONT_CARE) {
1971            num_configs++;
1972         }
1973      }
1974
1975      config = (__GLcontextModes **) Xmalloc(sizeof(__GLcontextModes *)
1976                                             * num_configs);
1977      if (config != NULL) {
1978         *nelements = num_configs;
1979         i = 0;
1980         for (modes = priv->screenConfigs[screen]->configs; modes != NULL;
1981              modes = modes->next) {
1982            if (modes->fbconfigID != (int) GLX_DONT_CARE) {
1983               config[i] = modes;
1984               i++;
1985            }
1986         }
1987      }
1988   }
1989   return (GLXFBConfig *) config;
1990}
1991
1992
1993PUBLIC int
1994glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config,
1995                     int attribute, int *value)
1996{
1997   __GLcontextModes *const modes = ValidateGLXFBConfig(dpy, config);
1998
1999   return (modes != NULL)
2000      ? _gl_get_context_mode_data(modes, attribute, value)
2001      : GLXBadFBConfig;
2002}
2003
2004
2005PUBLIC XVisualInfo *
2006glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config)
2007{
2008   XVisualInfo visualTemplate;
2009   __GLcontextModes *fbconfig = (__GLcontextModes *) config;
2010   int count;
2011
2012   /*
2013    ** Get a list of all visuals, return if list is empty
2014    */
2015   visualTemplate.visualid = fbconfig->visualID;
2016   return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count);
2017}
2018
2019#ifndef GLX_USE_APPLEGL
2020/*
2021** GLX_SGI_swap_control
2022*/
2023static int
2024__glXSwapIntervalSGI(int interval)
2025{
2026   xGLXVendorPrivateReq *req;
2027   GLXContext gc = __glXGetCurrentContext();
2028   __GLXscreenConfigs *psc;
2029   Display *dpy;
2030   CARD32 *interval_ptr;
2031   CARD8 opcode;
2032
2033   if (gc == NULL) {
2034      return GLX_BAD_CONTEXT;
2035   }
2036
2037   if (interval <= 0) {
2038      return GLX_BAD_VALUE;
2039   }
2040
2041#ifdef __DRI_SWAP_CONTROL
2042   if (gc->driContext) {
2043      __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
2044							    gc->screen );
2045      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
2046						  gc->currentDrawable,
2047						  NULL);
2048      if (psc->swapControl != NULL && pdraw != NULL) {
2049	 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
2050	 return 0;
2051      }
2052      else if (pdraw == NULL) {
2053	 return GLX_BAD_CONTEXT;
2054      }
2055   }
2056#endif
2057   psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
2058
2059#ifdef GLX_DIRECT_RENDERING
2060   if (gc->driContext && psc->driScreen && psc->driScreen->setSwapInterval) {
2061      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
2062						  gc->currentDrawable,
2063						  NULL);
2064      psc->driScreen->setSwapInterval(pdraw, interval);
2065      return 0;
2066   }
2067#endif
2068
2069   dpy = gc->currentDpy;
2070   opcode = __glXSetupForCommand(dpy);
2071   if (!opcode) {
2072      return 0;
2073   }
2074
2075   /* Send the glXSwapIntervalSGI request */
2076   LockDisplay(dpy);
2077   GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req);
2078   req->reqType = opcode;
2079   req->glxCode = X_GLXVendorPrivate;
2080   req->vendorCode = X_GLXvop_SwapIntervalSGI;
2081   req->contextTag = gc->currentContextTag;
2082
2083   interval_ptr = (CARD32 *) (req + 1);
2084   *interval_ptr = interval;
2085
2086   UnlockDisplay(dpy);
2087   SyncHandle();
2088   XFlush(dpy);
2089
2090   return 0;
2091}
2092
2093
2094/*
2095** GLX_MESA_swap_control
2096*/
2097static int
2098__glXSwapIntervalMESA(unsigned int interval)
2099{
2100   GLXContext gc = __glXGetCurrentContext();
2101
2102#ifdef __DRI_SWAP_CONTROL
2103   if (gc != NULL && gc->driContext) {
2104      __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
2105                                                          gc->screen);
2106
2107      if ((psc != NULL) && (psc->driScreen != NULL)) {
2108         __GLXDRIdrawable *pdraw =
2109            GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2110         if (psc->swapControl != NULL && pdraw != NULL) {
2111            psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
2112            return 0;
2113         }
2114      }
2115   }
2116#endif
2117
2118#ifdef GLX_DIRECT_RENDERING
2119   if (gc != NULL && gc->driContext) {
2120      __GLXscreenConfigs *psc;
2121
2122      psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
2123      if (psc->driScreen && psc->driScreen->setSwapInterval) {
2124         __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
2125						     gc->currentDrawable, NULL);
2126	 psc->driScreen->setSwapInterval(pdraw, interval);
2127	 return 0;
2128      }
2129   }
2130#endif
2131
2132   return GLX_BAD_CONTEXT;
2133}
2134
2135
2136static int
2137__glXGetSwapIntervalMESA(void)
2138{
2139#ifdef __DRI_SWAP_CONTROL
2140   GLXContext gc = __glXGetCurrentContext();
2141
2142   if (gc != NULL && gc->driContext) {
2143      __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
2144                                                          gc->screen);
2145
2146      if ((psc != NULL) && (psc->driScreen != NULL)) {
2147         __GLXDRIdrawable *pdraw =
2148            GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2149         if (psc->swapControl != NULL && pdraw != NULL) {
2150            return psc->swapControl->getSwapInterval(pdraw->driDrawable);
2151         }
2152      }
2153   }
2154#endif
2155
2156#ifdef GLX_DIRECT_RENDERING
2157   if (gc != NULL && gc->driContext) {
2158      __GLXscreenConfigs *psc;
2159
2160      psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
2161      if (psc->driScreen && psc->driScreen->getSwapInterval) {
2162         __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
2163						     gc->currentDrawable, NULL);
2164	 return psc->driScreen->getSwapInterval(pdraw);
2165      }
2166   }
2167#endif
2168
2169   return 0;
2170}
2171
2172
2173/*
2174** GLX_MESA_swap_frame_usage
2175*/
2176
2177static GLint
2178__glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
2179{
2180   int status = GLX_BAD_CONTEXT;
2181#ifdef __DRI_FRAME_TRACKING
2182   int screen = 0;
2183   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2184   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2185
2186   if (pdraw != NULL && psc->frameTracking != NULL)
2187      status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE);
2188#else
2189   (void) dpy;
2190   (void) drawable;
2191#endif
2192   return status;
2193}
2194
2195
2196static GLint
2197__glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
2198{
2199   int status = GLX_BAD_CONTEXT;
2200#ifdef __DRI_FRAME_TRACKING
2201   int screen = 0;
2202   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2203   __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen);
2204
2205   if (pdraw != NULL && psc->frameTracking != NULL)
2206      status = psc->frameTracking->frameTracking(pdraw->driDrawable,
2207                                                 GL_FALSE);
2208#else
2209   (void) dpy;
2210   (void) drawable;
2211#endif
2212   return status;
2213}
2214
2215
2216static GLint
2217__glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage)
2218{
2219   int status = GLX_BAD_CONTEXT;
2220#ifdef __DRI_FRAME_TRACKING
2221   int screen = 0;
2222   __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2223   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2224
2225   if (pdraw != NULL && psc->frameTracking != NULL) {
2226      int64_t sbc, missedFrames;
2227      float lastMissedUsage;
2228
2229      status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
2230                                                      &sbc,
2231                                                      &missedFrames,
2232                                                      &lastMissedUsage,
2233                                                      usage);
2234   }
2235#else
2236   (void) dpy;
2237   (void) drawable;
2238   (void) usage;
2239#endif
2240   return status;
2241}
2242
2243
2244static GLint
2245__glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable,
2246                            int64_t * sbc, int64_t * missedFrames,
2247                            GLfloat * lastMissedUsage)
2248{
2249   int status = GLX_BAD_CONTEXT;
2250#ifdef __DRI_FRAME_TRACKING
2251   int screen = 0;
2252   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2253   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2254
2255   if (pdraw != NULL && psc->frameTracking != NULL) {
2256      float usage;
2257
2258      status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
2259                                                      sbc, missedFrames,
2260                                                      lastMissedUsage,
2261                                                      &usage);
2262   }
2263#else
2264   (void) dpy;
2265   (void) drawable;
2266   (void) sbc;
2267   (void) missedFrames;
2268   (void) lastMissedUsage;
2269#endif
2270   return status;
2271}
2272
2273
2274/*
2275** GLX_SGI_video_sync
2276*/
2277static int
2278__glXGetVideoSyncSGI(unsigned int *count)
2279{
2280   int64_t ust, msc, sbc;
2281   int ret;
2282   GLXContext gc = __glXGetCurrentContext();
2283   __GLXscreenConfigs *psc;
2284#ifdef GLX_DIRECT_RENDERING
2285   __GLXDRIdrawable *pdraw;
2286#endif
2287
2288   if (!gc)
2289      return GLX_BAD_CONTEXT;
2290
2291#ifdef GLX_DIRECT_RENDERING
2292   if (!gc->driContext)
2293      return GLX_BAD_CONTEXT;
2294#endif
2295
2296   psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen);
2297#ifdef GLX_DIRECT_RENDERING
2298   pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2299#endif
2300
2301   /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
2302    * FIXME: there should be a GLX encoding for this call.  I can find no
2303    * FIXME: documentation for the GLX encoding.
2304    */
2305#ifdef __DRI_MEDIA_STREAM_COUNTER
2306   if ( psc->msc && psc->driScreen ) {
2307      ret = (*psc->msc->getDrawableMSC)(psc->__driScreen,
2308					pdraw->driDrawable, &msc);
2309      *count = (unsigned) msc;
2310
2311      return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
2312   }
2313#endif
2314
2315#ifdef GLX_DIRECT_RENDERING
2316   if (psc->driScreen && psc->driScreen->getDrawableMSC) {
2317      ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc);
2318      *count = (unsigned) msc;
2319      return (ret == True) ? 0 : GLX_BAD_CONTEXT;
2320   }
2321#endif
2322
2323   return GLX_BAD_CONTEXT;
2324}
2325
2326static int
2327__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
2328{
2329   GLXContext gc = __glXGetCurrentContext();
2330   __GLXscreenConfigs *psc;
2331#ifdef GLX_DIRECT_RENDERING
2332   __GLXDRIdrawable *pdraw;
2333#endif
2334   int64_t ust, msc, sbc;
2335   int ret;
2336
2337   if (divisor <= 0 || remainder < 0)
2338      return GLX_BAD_VALUE;
2339
2340   if (!gc)
2341      return GLX_BAD_CONTEXT;
2342
2343#ifdef GLX_DIRECT_RENDERING
2344   if (!gc->driContext)
2345      return GLX_BAD_CONTEXT;
2346#endif
2347
2348   psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
2349#ifdef GLX_DIRECT_RENDERING
2350   pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2351#endif
2352
2353#ifdef __DRI_MEDIA_STREAM_COUNTER
2354   if (psc->msc != NULL && psc->driScreen ) {
2355      ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0,
2356				    divisor, remainder, &msc, &sbc);
2357      *count = (unsigned) msc;
2358      return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
2359   }
2360#endif
2361
2362#ifdef GLX_DIRECT_RENDERING
2363   if (psc->driScreen && psc->driScreen->waitForMSC) {
2364      ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc,
2365				       &sbc);
2366      *count = (unsigned) msc;
2367      return (ret == True) ? 0 : GLX_BAD_CONTEXT;
2368   }
2369#endif
2370
2371   return GLX_BAD_CONTEXT;
2372}
2373
2374#endif /* GLX_USE_APPLEGL */
2375
2376/*
2377** GLX_SGIX_fbconfig
2378** Many of these functions are aliased to GLX 1.3 entry points in the
2379** GLX_functions table.
2380*/
2381
2382PUBLIC
2383GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
2384          (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value),
2385          (dpy, config, attribute, value), glXGetFBConfigAttrib)
2386
2387PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
2388                 (Display * dpy, int screen, int *attrib_list,
2389                  int *nelements), (dpy, screen, attrib_list, nelements),
2390                 glXChooseFBConfig)
2391
2392PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
2393                 (Display * dpy, GLXFBConfigSGIX config),
2394                 (dpy, config), glXGetVisualFromFBConfig)
2395
2396PUBLIC GLXPixmap
2397glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
2398                                 GLXFBConfigSGIX config,
2399                                 Pixmap pixmap)
2400{
2401#ifndef GLX_USE_APPLEGL
2402   xGLXVendorPrivateWithReplyReq *vpreq;
2403   xGLXCreateGLXPixmapWithConfigSGIXReq *req;
2404   GLXPixmap xid = None;
2405   CARD8 opcode;
2406   __GLXscreenConfigs *psc;
2407#endif
2408   const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
2409
2410
2411   if ((dpy == NULL) || (config == NULL)) {
2412      return None;
2413   }
2414#ifdef GLX_USE_APPLEGL
2415   if(apple_glx_pixmap_create(dpy, fbconfig->screen, pixmap, fbconfig))
2416      return None;
2417   return pixmap;
2418#else
2419
2420   psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
2421   if ((psc != NULL)
2422       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
2423      opcode = __glXSetupForCommand(dpy);
2424      if (!opcode) {
2425         return None;
2426      }
2427
2428      /* Send the glXCreateGLXPixmapWithConfigSGIX request */
2429      LockDisplay(dpy);
2430      GetReqExtra(GLXVendorPrivateWithReply,
2431                  sz_xGLXCreateGLXPixmapWithConfigSGIXReq -
2432                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
2433      req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq;
2434      req->reqType = opcode;
2435      req->glxCode = X_GLXVendorPrivateWithReply;
2436      req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
2437      req->screen = fbconfig->screen;
2438      req->fbconfig = fbconfig->fbconfigID;
2439      req->pixmap = pixmap;
2440      req->glxpixmap = xid = XAllocID(dpy);
2441      UnlockDisplay(dpy);
2442      SyncHandle();
2443   }
2444
2445   return xid;
2446#endif
2447}
2448
2449PUBLIC GLXContext
2450glXCreateContextWithConfigSGIX(Display * dpy,
2451                               GLXFBConfigSGIX config, int renderType,
2452                               GLXContext shareList, Bool allowDirect)
2453{
2454   GLXContext gc = NULL;
2455   const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
2456   __GLXscreenConfigs *psc;
2457
2458
2459   if ((dpy == NULL) || (config == NULL)) {
2460      return None;
2461   }
2462
2463   psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
2464   if ((psc != NULL)
2465       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
2466      gc = CreateContext(dpy, fbconfig->fbconfigID, fbconfig, shareList,
2467                         allowDirect,
2468			 X_GLXvop_CreateContextWithConfigSGIX, renderType,
2469			 fbconfig->screen);
2470   }
2471
2472   return gc;
2473}
2474
2475
2476PUBLIC GLXFBConfigSGIX
2477glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
2478{
2479   __GLXdisplayPrivate *priv;
2480   __GLXscreenConfigs *psc = NULL;
2481
2482   if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success)
2483       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
2484       && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) {
2485      return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs,
2486                                                             vis->visualid);
2487   }
2488
2489   return NULL;
2490}
2491
2492#ifndef GLX_USE_APPLEGL
2493/*
2494** GLX_SGIX_swap_group
2495*/
2496static void
2497__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable,
2498                       GLXDrawable member)
2499{
2500   (void) dpy;
2501   (void) drawable;
2502   (void) member;
2503}
2504
2505
2506/*
2507** GLX_SGIX_swap_barrier
2508*/
2509static void
2510__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier)
2511{
2512   (void) dpy;
2513   (void) drawable;
2514   (void) barrier;
2515}
2516
2517static Bool
2518__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max)
2519{
2520   (void) dpy;
2521   (void) screen;
2522   (void) max;
2523   return False;
2524}
2525
2526
2527/*
2528** GLX_OML_sync_control
2529*/
2530static Bool
2531__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
2532                      int64_t * ust, int64_t * msc, int64_t * sbc)
2533{
2534   __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
2535   int i, ret;
2536#ifdef GLX_DIRECT_RENDERING
2537   __GLXDRIdrawable *pdraw;
2538#endif
2539   __GLXscreenConfigs *psc;
2540
2541   if (!priv)
2542      return False;
2543
2544#ifdef GLX_DIRECT_RENDERING
2545   pdraw = GetGLXDRIDrawable(dpy, drawable, &i);
2546#endif
2547   psc = priv->screenConfigs[i];
2548
2549#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER)
2550   if (pdraw && psc->sbc && psc->msc)
2551      return ( (pdraw && psc->sbc && psc->msc)
2552	       && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0)
2553	       && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0)
2554	       && (__glXGetUST(ust) == 0) );
2555#endif
2556
2557#ifdef GLX_DIRECT_RENDERING
2558   if (pdraw && psc && psc->driScreen && psc->driScreen->getDrawableMSC) {
2559      ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc);
2560      return ret;
2561   }
2562#endif
2563
2564   return False;
2565}
2566
2567#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
2568_X_HIDDEN GLboolean
2569__driGetMscRateOML(__DRIdrawable * draw,
2570                   int32_t * numerator, int32_t * denominator, void *private)
2571{
2572#ifdef XF86VIDMODE
2573   __GLXscreenConfigs *psc;
2574   XF86VidModeModeLine mode_line;
2575   int dot_clock;
2576   int i;
2577   __GLXDRIdrawable *glxDraw = private;
2578
2579   (void) draw;
2580
2581   psc = glxDraw->psc;
2582   if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
2583       XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) {
2584      unsigned n = dot_clock * 1000;
2585      unsigned d = mode_line.vtotal * mode_line.htotal;
2586
2587# define V_INTERLACE 0x010
2588# define V_DBLSCAN   0x020
2589
2590      if (mode_line.flags & V_INTERLACE)
2591         n *= 2;
2592      else if (mode_line.flags & V_DBLSCAN)
2593         d *= 2;
2594
2595      /* The OML_sync_control spec requires that if the refresh rate is a
2596       * whole number, that the returned numerator be equal to the refresh
2597       * rate and the denominator be 1.
2598       */
2599
2600      if (n % d == 0) {
2601         n /= d;
2602         d = 1;
2603      }
2604      else {
2605         static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
2606
2607         /* This is a poor man's way to reduce a fraction.  It's far from
2608          * perfect, but it will work well enough for this situation.
2609          */
2610
2611         for (i = 0; f[i] != 0; i++) {
2612            while (n % f[i] == 0 && d % f[i] == 0) {
2613               d /= f[i];
2614               n /= f[i];
2615            }
2616         }
2617      }
2618
2619      *numerator = n;
2620      *denominator = d;
2621
2622      return True;
2623   }
2624   else
2625      return False;
2626#else
2627   (void) draw;
2628   (void) numerator;
2629   (void) denominator;
2630   (void) private;
2631
2632   return False;
2633#endif
2634}
2635#endif
2636
2637/**
2638 * Determine the refresh rate of the specified drawable and display.
2639 *
2640 * \param dpy          Display whose refresh rate is to be determined.
2641 * \param drawable     Drawable whose refresh rate is to be determined.
2642 * \param numerator    Numerator of the refresh rate.
2643 * \param demoninator  Denominator of the refresh rate.
2644 * \return  If the refresh rate for the specified display and drawable could
2645 *          be calculated, True is returned.  Otherwise False is returned.
2646 *
2647 * \note This function is implemented entirely client-side.  A lot of other
2648 *       functionality is required to export GLX_OML_sync_control, so on
2649 *       XFree86 this function can be called for direct-rendering contexts
2650 *       when GLX_OML_sync_control appears in the client extension string.
2651 */
2652
2653_X_HIDDEN GLboolean
2654__glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
2655                   int32_t * numerator, int32_t * denominator)
2656{
2657#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE )
2658   __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL);
2659
2660   if (draw == NULL)
2661      return False;
2662
2663   return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw);
2664#else
2665   (void) dpy;
2666   (void) drawable;
2667   (void) numerator;
2668   (void) denominator;
2669#endif
2670   return False;
2671}
2672
2673
2674static int64_t
2675__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable,
2676                       int64_t target_msc, int64_t divisor, int64_t remainder)
2677{
2678   GLXContext gc = __glXGetCurrentContext();
2679   int screen;
2680#ifdef GLX_DIRECT_RENDERING
2681   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2682#endif
2683   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2684
2685   if (!gc) /* no GLX for this */
2686      return -1;
2687
2688#ifdef GLX_DIRECT_RENDERING
2689   if (!pdraw || !gc->driContext)
2690      return -1;
2691#endif
2692
2693   /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2694    * error", but it also says "It [glXSwapBuffersMscOML] will return a value
2695    * of -1 if the function failed because of errors detected in the input
2696    * parameters"
2697    */
2698   if (divisor < 0 || remainder < 0 || target_msc < 0)
2699      return -1;
2700   if (divisor > 0 && remainder >= divisor)
2701      return -1;
2702
2703   if (target_msc == 0 && divisor == 0 && remainder == 0)
2704      remainder = 1;
2705
2706#ifdef __DRI_SWAP_BUFFER_COUNTER
2707   if (psc->counters != NULL)
2708      return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc,
2709					 divisor, remainder);
2710#endif
2711
2712#ifdef GLX_DIRECT_RENDERING
2713   if (psc->driScreen && psc->driScreen->swapBuffers)
2714      return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor,
2715					    remainder);
2716#endif
2717
2718   return -1;
2719}
2720
2721
2722static Bool
2723__glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
2724                   int64_t target_msc, int64_t divisor,
2725                   int64_t remainder, int64_t * ust,
2726                   int64_t * msc, int64_t * sbc)
2727{
2728   int screen;
2729#ifdef GLX_DIRECT_RENDERING
2730   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2731#endif
2732   __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
2733   int ret;
2734
2735
2736   /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2737    * error", but the return type in the spec is Bool.
2738    */
2739   if (divisor < 0 || remainder < 0 || target_msc < 0)
2740      return False;
2741   if (divisor > 0 && remainder >= divisor)
2742      return False;
2743
2744#ifdef __DRI_MEDIA_STREAM_COUNTER
2745   if (pdraw != NULL && psc->msc != NULL) {
2746      ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc,
2747                                     divisor, remainder, msc, sbc);
2748
2749      /* __glXGetUST returns zero on success and non-zero on failure.
2750       * This function returns True on success and False on failure.
2751       */
2752      return ((ret == 0) && (__glXGetUST(ust) == 0));
2753   }
2754#endif
2755
2756#ifdef GLX_DIRECT_RENDERING
2757   if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) {
2758      ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder,
2759				       ust, msc, sbc);
2760      return ret;
2761   }
2762#endif
2763
2764   return False;
2765}
2766
2767
2768static Bool
2769__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
2770                   int64_t target_sbc, int64_t * ust,
2771                   int64_t * msc, int64_t * sbc)
2772{
2773   int screen;
2774#ifdef GLX_DIRECT_RENDERING
2775   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2776#endif
2777   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2778   int ret;
2779
2780   /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE
2781    * error", but the return type in the spec is Bool.
2782    */
2783   if (target_sbc < 0)
2784      return False;
2785#ifdef __DRI_SWAP_BUFFER_COUNTER
2786   if (pdraw != NULL && psc->sbc != NULL) {
2787      ret =
2788         (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc);
2789
2790      /* __glXGetUST returns zero on success and non-zero on failure.
2791       * This function returns True on success and False on failure.
2792       */
2793      return ((ret == 0) && (__glXGetUST(ust) == 0));
2794   }
2795#endif
2796
2797#ifdef GLX_DIRECT_RENDERING
2798   if (pdraw && psc->driScreen && psc->driScreen->waitForSBC) {
2799      ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc);
2800      return ret;
2801   }
2802#endif
2803
2804   return False;
2805}
2806
2807
2808/**
2809 * GLX_MESA_allocate_memory
2810 */
2811/*@{*/
2812
2813PUBLIC void *
2814glXAllocateMemoryMESA(Display * dpy, int scrn,
2815                      size_t size, float readFreq,
2816                      float writeFreq, float priority)
2817{
2818#ifdef __DRI_ALLOCATE
2819   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
2820
2821   if (psc && psc->allocate)
2822      return (*psc->allocate->allocateMemory) (psc->__driScreen, size,
2823                                               readFreq, writeFreq, priority);
2824
2825#else
2826   (void) dpy;
2827   (void) scrn;
2828   (void) size;
2829   (void) readFreq;
2830   (void) writeFreq;
2831   (void) priority;
2832#endif /* __DRI_ALLOCATE */
2833
2834   return NULL;
2835}
2836
2837
2838PUBLIC void
2839glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer)
2840{
2841#ifdef __DRI_ALLOCATE
2842   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
2843
2844   if (psc && psc->allocate)
2845      (*psc->allocate->freeMemory) (psc->__driScreen, pointer);
2846
2847#else
2848   (void) dpy;
2849   (void) scrn;
2850   (void) pointer;
2851#endif /* __DRI_ALLOCATE */
2852}
2853
2854
2855PUBLIC GLuint
2856glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer)
2857{
2858#ifdef __DRI_ALLOCATE
2859   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
2860
2861   if (psc && psc->allocate)
2862      return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer);
2863
2864#else
2865   (void) dpy;
2866   (void) scrn;
2867   (void) pointer;
2868#endif /* GLX_DIRECT_RENDERING */
2869
2870   return ~0L;
2871}
2872
2873/*@}*/
2874
2875
2876/**
2877 * Mesa extension stubs.  These will help reduce portability problems.
2878 */
2879/*@{*/
2880
2881/**
2882 * Release all buffers associated with the specified GLX drawable.
2883 *
2884 * \todo
2885 * This function was intended for stand-alone Mesa.  The issue there is that
2886 * the library doesn't get any notification when a window is closed.  In
2887 * DRI there is a similar but slightly different issue.  When GLX 1.3 is
2888 * supported, there are 3 different functions to destroy a drawable.  It
2889 * should be possible to create GLX protocol (or have it determine which
2890 * protocol to use based on the type of the drawable) to have one function
2891 * do the work of 3.  For the direct-rendering case, this function could
2892 * just call the driver's \c __DRIdrawableRec::destroyDrawable function.
2893 * This would reduce the frequency with which \c __driGarbageCollectDrawables
2894 * would need to be used.  This really should be done as part of the new DRI
2895 * interface work.
2896 *
2897 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt
2898 *     __driGarbageCollectDrawables
2899 *     glXDestroyGLXPixmap
2900 *     glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow
2901 *     glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX
2902 */
2903static Bool
2904__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d)
2905{
2906   (void) dpy;
2907   (void) d;
2908   return False;
2909}
2910
2911
2912PUBLIC GLXPixmap
2913glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual,
2914                       Pixmap pixmap, Colormap cmap)
2915{
2916   (void) dpy;
2917   (void) visual;
2918   (void) pixmap;
2919   (void) cmap;
2920   return 0;
2921}
2922
2923/*@}*/
2924
2925
2926/**
2927 * GLX_MESA_copy_sub_buffer
2928 */
2929#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
2930static void
2931__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable,
2932                       int x, int y, int width, int height)
2933{
2934   xGLXVendorPrivateReq *req;
2935   GLXContext gc;
2936   GLXContextTag tag;
2937   CARD32 *drawable_ptr;
2938   INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
2939   CARD8 opcode;
2940
2941#ifdef __DRI_COPY_SUB_BUFFER
2942   int screen;
2943   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2944   if (pdraw != NULL) {
2945      __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2946      if (psc->driScreen->copySubBuffer != NULL) {
2947         glFlush();
2948         (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height);
2949      }
2950
2951      return;
2952   }
2953#endif
2954
2955   opcode = __glXSetupForCommand(dpy);
2956   if (!opcode)
2957      return;
2958
2959   /*
2960    ** The calling thread may or may not have a current context.  If it
2961    ** does, send the context tag so the server can do a flush.
2962    */
2963   gc = __glXGetCurrentContext();
2964   if ((gc != NULL) && (dpy == gc->currentDpy) &&
2965       ((drawable == gc->currentDrawable) ||
2966        (drawable == gc->currentReadable))) {
2967      tag = gc->currentContextTag;
2968   }
2969   else {
2970      tag = 0;
2971   }
2972
2973   LockDisplay(dpy);
2974   GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req);
2975   req->reqType = opcode;
2976   req->glxCode = X_GLXVendorPrivate;
2977   req->vendorCode = X_GLXvop_CopySubBufferMESA;
2978   req->contextTag = tag;
2979
2980   drawable_ptr = (CARD32 *) (req + 1);
2981   x_ptr = (INT32 *) (drawable_ptr + 1);
2982   y_ptr = (INT32 *) (drawable_ptr + 2);
2983   w_ptr = (INT32 *) (drawable_ptr + 3);
2984   h_ptr = (INT32 *) (drawable_ptr + 4);
2985
2986   *drawable_ptr = drawable;
2987   *x_ptr = x;
2988   *y_ptr = y;
2989   *w_ptr = width;
2990   *h_ptr = height;
2991
2992   UnlockDisplay(dpy);
2993   SyncHandle();
2994}
2995
2996
2997/**
2998 * GLX_EXT_texture_from_pixmap
2999 */
3000static void
3001glx_indirect_bind_tex_image(Display * dpy,
3002			    GLXDrawable drawable,
3003			    int buffer, const int *attrib_list)
3004{
3005   xGLXVendorPrivateReq *req;
3006   GLXContext gc = __glXGetCurrentContext();
3007   CARD32 *drawable_ptr;
3008   INT32 *buffer_ptr;
3009   CARD32 *num_attrib_ptr;
3010   CARD32 *attrib_ptr;
3011   CARD8 opcode;
3012   unsigned int i;
3013
3014   i = 0;
3015   if (attrib_list) {
3016      while (attrib_list[i * 2] != None)
3017         i++;
3018   }
3019
3020   opcode = __glXSetupForCommand(dpy);
3021   if (!opcode)
3022      return;
3023
3024   LockDisplay(dpy);
3025   GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
3026   req->reqType = opcode;
3027   req->glxCode = X_GLXVendorPrivate;
3028   req->vendorCode = X_GLXvop_BindTexImageEXT;
3029   req->contextTag = gc->currentContextTag;
3030
3031   drawable_ptr = (CARD32 *) (req + 1);
3032   buffer_ptr = (INT32 *) (drawable_ptr + 1);
3033   num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
3034   attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
3035
3036   *drawable_ptr = drawable;
3037   *buffer_ptr = buffer;
3038   *num_attrib_ptr = (CARD32) i;
3039
3040   i = 0;
3041   if (attrib_list) {
3042      while (attrib_list[i * 2] != None) {
3043         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
3044         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
3045         i++;
3046      }
3047   }
3048
3049   UnlockDisplay(dpy);
3050   SyncHandle();
3051}
3052
3053static void
3054glx_indirect_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
3055{
3056   xGLXVendorPrivateReq *req;
3057   GLXContext gc = __glXGetCurrentContext();
3058   CARD32 *drawable_ptr;
3059   INT32 *buffer_ptr;
3060   CARD8 opcode;
3061
3062   opcode = __glXSetupForCommand(dpy);
3063   if (!opcode)
3064      return;
3065
3066   LockDisplay(dpy);
3067   GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
3068   req->reqType = opcode;
3069   req->glxCode = X_GLXVendorPrivate;
3070   req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
3071   req->contextTag = gc->currentContextTag;
3072
3073   drawable_ptr = (CARD32 *) (req + 1);
3074   buffer_ptr = (INT32 *) (drawable_ptr + 1);
3075
3076   *drawable_ptr = drawable;
3077   *buffer_ptr = buffer;
3078
3079   UnlockDisplay(dpy);
3080   SyncHandle();
3081}
3082
3083static const struct glx_context_vtable glx_indirect_context_vtable = {
3084   glx_indirect_bind_tex_image,
3085   glx_indirect_release_tex_image,
3086};
3087
3088/*@{*/
3089static void
3090__glXBindTexImageEXT(Display * dpy,
3091                     GLXDrawable drawable, int buffer, const int *attrib_list)
3092{
3093   GLXContext gc = __glXGetCurrentContext();
3094
3095   if (gc == NULL || gc->vtable->bind_tex_image == NULL)
3096      return;
3097
3098   gc->vtable->bind_tex_image(dpy, drawable, buffer, attrib_list);
3099}
3100
3101static void
3102__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer)
3103{
3104   GLXContext gc = __glXGetCurrentContext();
3105
3106   if (gc == NULL || gc->vtable->release_tex_image == NULL)
3107      return;
3108
3109   gc->vtable->release_tex_image(dpy, drawable, buffer);
3110}
3111
3112/*@}*/
3113
3114#endif /* GLX_USE_APPLEGL */
3115
3116/**
3117 * \c strdup is actually not a standard ANSI C or POSIX routine.
3118 * Irix will not define it if ANSI mode is in effect.
3119 *
3120 * \sa strdup
3121 */
3122_X_HIDDEN char *
3123__glXstrdup(const char *str)
3124{
3125   char *copy;
3126   copy = (char *) Xmalloc(strlen(str) + 1);
3127   if (!copy)
3128      return NULL;
3129   strcpy(copy, str);
3130   return copy;
3131}
3132
3133/*
3134** glXGetProcAddress support
3135*/
3136
3137struct name_address_pair
3138{
3139   const char *Name;
3140   GLvoid *Address;
3141};
3142
3143#define GLX_FUNCTION(f) { # f, (GLvoid *) f }
3144#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f }
3145
3146static const struct name_address_pair GLX_functions[] = {
3147   /*** GLX_VERSION_1_0 ***/
3148   GLX_FUNCTION(glXChooseVisual),
3149   GLX_FUNCTION(glXCopyContext),
3150   GLX_FUNCTION(glXCreateContext),
3151   GLX_FUNCTION(glXCreateGLXPixmap),
3152   GLX_FUNCTION(glXDestroyContext),
3153   GLX_FUNCTION(glXDestroyGLXPixmap),
3154   GLX_FUNCTION(glXGetConfig),
3155   GLX_FUNCTION(glXGetCurrentContext),
3156   GLX_FUNCTION(glXGetCurrentDrawable),
3157   GLX_FUNCTION(glXIsDirect),
3158   GLX_FUNCTION(glXMakeCurrent),
3159   GLX_FUNCTION(glXQueryExtension),
3160   GLX_FUNCTION(glXQueryVersion),
3161   GLX_FUNCTION(glXSwapBuffers),
3162   GLX_FUNCTION(glXUseXFont),
3163   GLX_FUNCTION(glXWaitGL),
3164   GLX_FUNCTION(glXWaitX),
3165
3166   /*** GLX_VERSION_1_1 ***/
3167   GLX_FUNCTION(glXGetClientString),
3168   GLX_FUNCTION(glXQueryExtensionsString),
3169   GLX_FUNCTION(glXQueryServerString),
3170
3171   /*** GLX_VERSION_1_2 ***/
3172   GLX_FUNCTION(glXGetCurrentDisplay),
3173
3174   /*** GLX_VERSION_1_3 ***/
3175   GLX_FUNCTION(glXChooseFBConfig),
3176   GLX_FUNCTION(glXCreateNewContext),
3177   GLX_FUNCTION(glXCreatePbuffer),
3178   GLX_FUNCTION(glXCreatePixmap),
3179   GLX_FUNCTION(glXCreateWindow),
3180   GLX_FUNCTION(glXDestroyPbuffer),
3181   GLX_FUNCTION(glXDestroyPixmap),
3182   GLX_FUNCTION(glXDestroyWindow),
3183   GLX_FUNCTION(glXGetCurrentReadDrawable),
3184   GLX_FUNCTION(glXGetFBConfigAttrib),
3185   GLX_FUNCTION(glXGetFBConfigs),
3186   GLX_FUNCTION(glXGetSelectedEvent),
3187   GLX_FUNCTION(glXGetVisualFromFBConfig),
3188   GLX_FUNCTION(glXMakeContextCurrent),
3189   GLX_FUNCTION(glXQueryContext),
3190   GLX_FUNCTION(glXQueryDrawable),
3191   GLX_FUNCTION(glXSelectEvent),
3192
3193#ifndef GLX_USE_APPLEGL
3194   /*** GLX_SGI_swap_control ***/
3195   GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI),
3196
3197   /*** GLX_SGI_video_sync ***/
3198   GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI),
3199   GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI),
3200
3201   /*** GLX_SGI_make_current_read ***/
3202   GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent),
3203   GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable),
3204
3205   /*** GLX_EXT_import_context ***/
3206   GLX_FUNCTION(glXFreeContextEXT),
3207   GLX_FUNCTION(glXGetContextIDEXT),
3208   GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay),
3209   GLX_FUNCTION(glXImportContextEXT),
3210   GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext),
3211#endif
3212
3213   /*** GLX_SGIX_fbconfig ***/
3214   GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib),
3215   GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig),
3216   GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX),
3217   GLX_FUNCTION(glXCreateContextWithConfigSGIX),
3218   GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig),
3219   GLX_FUNCTION(glXGetFBConfigFromVisualSGIX),
3220
3221#ifndef GLX_USE_APPLEGL
3222   /*** GLX_SGIX_pbuffer ***/
3223   GLX_FUNCTION(glXCreateGLXPbufferSGIX),
3224   GLX_FUNCTION(glXDestroyGLXPbufferSGIX),
3225   GLX_FUNCTION(glXQueryGLXPbufferSGIX),
3226   GLX_FUNCTION(glXSelectEventSGIX),
3227   GLX_FUNCTION(glXGetSelectedEventSGIX),
3228
3229   /*** GLX_SGIX_swap_group ***/
3230   GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX),
3231
3232   /*** GLX_SGIX_swap_barrier ***/
3233   GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX),
3234   GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX),
3235
3236   /*** GLX_MESA_allocate_memory ***/
3237   GLX_FUNCTION(glXAllocateMemoryMESA),
3238   GLX_FUNCTION(glXFreeMemoryMESA),
3239   GLX_FUNCTION(glXGetMemoryOffsetMESA),
3240
3241   /*** GLX_MESA_copy_sub_buffer ***/
3242   GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA),
3243
3244   /*** GLX_MESA_pixmap_colormap ***/
3245   GLX_FUNCTION(glXCreateGLXPixmapMESA),
3246
3247   /*** GLX_MESA_release_buffers ***/
3248   GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA),
3249
3250   /*** GLX_MESA_swap_control ***/
3251   GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA),
3252   GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA),
3253
3254   /*** GLX_MESA_swap_frame_usage ***/
3255   GLX_FUNCTION2(glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA),
3256   GLX_FUNCTION2(glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA),
3257   GLX_FUNCTION2(glXGetFrameUsageMESA, __glXGetFrameUsageMESA),
3258   GLX_FUNCTION2(glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA),
3259#endif
3260
3261   /*** GLX_ARB_get_proc_address ***/
3262   GLX_FUNCTION(glXGetProcAddressARB),
3263
3264   /*** GLX 1.4 ***/
3265   GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB),
3266
3267#ifndef GLX_USE_APPLEGL
3268   /*** GLX_OML_sync_control ***/
3269   GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML),
3270   GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML),
3271   GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML),
3272   GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML),
3273   GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML),
3274
3275   /*** GLX_EXT_texture_from_pixmap ***/
3276   GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT),
3277   GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT),
3278#endif
3279
3280#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
3281   /*** DRI configuration ***/
3282   GLX_FUNCTION(glXGetScreenDriver),
3283   GLX_FUNCTION(glXGetDriverConfig),
3284#endif
3285
3286   {NULL, NULL}                 /* end of list */
3287};
3288
3289#ifndef GLX_USE_APPLEGL
3290static const GLvoid *
3291get_glx_proc_address(const char *funcName)
3292{
3293   GLuint i;
3294
3295   /* try static functions */
3296   for (i = 0; GLX_functions[i].Name; i++) {
3297      if (strcmp(GLX_functions[i].Name, funcName) == 0)
3298         return GLX_functions[i].Address;
3299   }
3300
3301   return NULL;
3302}
3303#endif
3304
3305/**
3306 * Get the address of a named GL function.  This is the pre-GLX 1.4 name for
3307 * \c glXGetProcAddress.
3308 *
3309 * \param procName  Name of a GL or GLX function.
3310 * \returns         A pointer to the named function
3311 *
3312 * \sa glXGetProcAddress
3313 */
3314PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
3315{
3316   typedef void (*gl_function) (void);
3317   gl_function f;
3318
3319
3320   /* Search the table of GLX and internal functions first.  If that
3321    * fails and the supplied name could be a valid core GL name, try
3322    * searching the core GL function table.  This check is done to prevent
3323    * DRI based drivers from searching the core GL function table for
3324    * internal API functions.
3325    */
3326#ifdef GLX_USE_APPLEGL
3327   f = (gl_function) apple_glx_get_proc_address(procName);
3328#else
3329   f = (gl_function) get_glx_proc_address((const char *) procName);
3330   if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
3331       && (procName[2] != 'X')) {
3332      f = (gl_function) _glapi_get_proc_address((const char *) procName);
3333   }
3334#endif
3335   return f;
3336}
3337
3338/**
3339 * Get the address of a named GL function.  This is the GLX 1.4 name for
3340 * \c glXGetProcAddressARB.
3341 *
3342 * \param procName  Name of a GL or GLX function.
3343 * \returns         A pointer to the named function
3344 *
3345 * \sa glXGetProcAddressARB
3346 */
3347PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void)
3348#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED)
3349   __attribute__ ((alias("glXGetProcAddressARB")));
3350#else
3351{
3352   return glXGetProcAddressARB(procName);
3353}
3354#endif /* __GNUC__ */
3355
3356
3357#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
3358/**
3359 * Get the unadjusted system time (UST).  Currently, the UST is measured in
3360 * microseconds since Epoc.  The actual resolution of the UST may vary from
3361 * system to system, and the units may vary from release to release.
3362 * Drivers should not call this function directly.  They should instead use
3363 * \c glXGetProcAddress to obtain a pointer to the function.
3364 *
3365 * \param ust Location to store the 64-bit UST
3366 * \returns Zero on success or a negative errno value on failure.
3367 *
3368 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
3369 *
3370 * \since Internal API version 20030317.
3371 */
3372_X_HIDDEN int
3373__glXGetUST(int64_t * ust)
3374{
3375   struct timeval tv;
3376
3377   if (ust == NULL) {
3378      return -EFAULT;
3379   }
3380
3381   if (gettimeofday(&tv, NULL) == 0) {
3382      ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
3383      return 0;
3384   }
3385   else {
3386      return -errno;
3387   }
3388}
3389#endif /* GLX_DIRECT_RENDERING */
3390