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