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