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