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