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