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