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