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