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