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