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