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