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