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