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