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