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