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