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