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