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