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