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