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