glxcmds.c revision 251bf298bfddd06c6d6cd4b03ba9aadfc02e2895
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 if (gc->driContext && psc->driScreen && psc->driScreen->setSwapInterval) { 1921 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 1922 gc->currentDrawable, 1923 NULL); 1924 psc->driScreen->setSwapInterval(pdraw, interval); 1925 return 0; 1926 } 1927 1928 dpy = gc->currentDpy; 1929 opcode = __glXSetupForCommand(dpy); 1930 if (!opcode) { 1931 return 0; 1932 } 1933 1934 /* Send the glXSwapIntervalSGI request */ 1935 LockDisplay(dpy); 1936 GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req); 1937 req->reqType = opcode; 1938 req->glxCode = X_GLXVendorPrivate; 1939 req->vendorCode = X_GLXvop_SwapIntervalSGI; 1940 req->contextTag = gc->currentContextTag; 1941 1942 interval_ptr = (CARD32 *) (req + 1); 1943 *interval_ptr = interval; 1944 1945 UnlockDisplay(dpy); 1946 SyncHandle(); 1947 XFlush(dpy); 1948 1949 return 0; 1950} 1951 1952 1953/* 1954** GLX_MESA_swap_control 1955*/ 1956static int 1957__glXSwapIntervalMESA(unsigned int interval) 1958{ 1959 GLXContext gc = __glXGetCurrentContext(); 1960 1961#ifdef __DRI_SWAP_CONTROL 1962 if (gc != NULL && gc->driContext) { 1963 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, 1964 gc->screen); 1965 1966 if ((psc != NULL) && (psc->driScreen != NULL)) { 1967 __GLXDRIdrawable *pdraw = 1968 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 1969 if (psc->swapControl != NULL && pdraw != NULL) { 1970 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); 1971 return 0; 1972 } 1973 } 1974 } 1975#endif 1976 1977 if (gc != NULL && gc->driContext) { 1978 __GLXscreenConfigs *psc; 1979 1980 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1981 if (psc->driScreen && psc->driScreen->setSwapInterval) { 1982 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 1983 gc->currentDrawable, NULL); 1984 psc->driScreen->setSwapInterval(pdraw, interval); 1985 return 0; 1986 } 1987 } 1988 1989 return GLX_BAD_CONTEXT; 1990} 1991 1992 1993static int 1994__glXGetSwapIntervalMESA(void) 1995{ 1996#ifdef __DRI_SWAP_CONTROL 1997 GLXContext gc = __glXGetCurrentContext(); 1998 1999 if (gc != NULL && gc->driContext) { 2000 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, 2001 gc->screen); 2002 2003 if ((psc != NULL) && (psc->driScreen != NULL)) { 2004 __GLXDRIdrawable *pdraw = 2005 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2006 if (psc->swapControl != NULL && pdraw != NULL) { 2007 return psc->swapControl->getSwapInterval(pdraw->driDrawable); 2008 } 2009 } 2010 } 2011#endif 2012 if (gc != NULL && gc->driContext) { 2013 __GLXscreenConfigs *psc; 2014 2015 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 2016 if (psc->driScreen && psc->driScreen->getSwapInterval) { 2017 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 2018 gc->currentDrawable, NULL); 2019 return psc->driScreen->getSwapInterval(pdraw); 2020 } 2021 } 2022 2023 return 0; 2024} 2025 2026 2027/* 2028** GLX_MESA_swap_frame_usage 2029*/ 2030 2031static GLint 2032__glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable) 2033{ 2034 int status = GLX_BAD_CONTEXT; 2035#ifdef __DRI_FRAME_TRACKING 2036 int screen = 0; 2037 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2038 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2039 2040 if (pdraw != NULL && psc->frameTracking != NULL) 2041 status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE); 2042#else 2043 (void) dpy; 2044 (void) drawable; 2045#endif 2046 return status; 2047} 2048 2049 2050static GLint 2051__glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable) 2052{ 2053 int status = GLX_BAD_CONTEXT; 2054#ifdef __DRI_FRAME_TRACKING 2055 int screen = 0; 2056 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2057 __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen); 2058 2059 if (pdraw != NULL && psc->frameTracking != NULL) 2060 status = psc->frameTracking->frameTracking(pdraw->driDrawable, 2061 GL_FALSE); 2062#else 2063 (void) dpy; 2064 (void) drawable; 2065#endif 2066 return status; 2067} 2068 2069 2070static GLint 2071__glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage) 2072{ 2073 int status = GLX_BAD_CONTEXT; 2074#ifdef __DRI_FRAME_TRACKING 2075 int screen = 0; 2076 __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2077 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2078 2079 if (pdraw != NULL && psc->frameTracking != NULL) { 2080 int64_t sbc, missedFrames; 2081 float lastMissedUsage; 2082 2083 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, 2084 &sbc, 2085 &missedFrames, 2086 &lastMissedUsage, 2087 usage); 2088 } 2089#else 2090 (void) dpy; 2091 (void) drawable; 2092 (void) usage; 2093#endif 2094 return status; 2095} 2096 2097 2098static GLint 2099__glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable, 2100 int64_t * sbc, int64_t * missedFrames, 2101 GLfloat * lastMissedUsage) 2102{ 2103 int status = GLX_BAD_CONTEXT; 2104#ifdef __DRI_FRAME_TRACKING 2105 int screen = 0; 2106 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2107 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2108 2109 if (pdraw != NULL && psc->frameTracking != NULL) { 2110 float usage; 2111 2112 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, 2113 sbc, missedFrames, 2114 lastMissedUsage, 2115 &usage); 2116 } 2117#else 2118 (void) dpy; 2119 (void) drawable; 2120 (void) sbc; 2121 (void) missedFrames; 2122 (void) lastMissedUsage; 2123#endif 2124 return status; 2125} 2126 2127 2128/* 2129** GLX_SGI_video_sync 2130*/ 2131static int 2132__glXGetVideoSyncSGI(unsigned int *count) 2133{ 2134 int64_t ust, msc, sbc; 2135 int ret; 2136 GLXContext gc = __glXGetCurrentContext(); 2137 __GLXscreenConfigs *psc; 2138 __GLXDRIdrawable *pdraw; 2139 2140 if (!gc || !gc->driContext) 2141 return GLX_BAD_CONTEXT; 2142 2143 psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen); 2144 pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2145 2146 /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry, 2147 * FIXME: there should be a GLX encoding for this call. I can find no 2148 * FIXME: documentation for the GLX encoding. 2149 */ 2150#ifdef __DRI_MEDIA_STREAM_COUNTER 2151 if ( psc->msc && psc->driScreen ) { 2152 ret = (*psc->msc->getDrawableMSC)(psc->__driScreen, 2153 pdraw->driDrawable, &msc); 2154 *count = (unsigned) msc; 2155 2156 return (ret == 0) ? 0 : GLX_BAD_CONTEXT; 2157 } 2158#endif 2159 if (psc->driScreen && psc->driScreen->getDrawableMSC) { 2160 ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc); 2161 *count = (unsigned) msc; 2162 return (ret == True) ? 0 : GLX_BAD_CONTEXT; 2163 } 2164 2165 return GLX_BAD_CONTEXT; 2166} 2167 2168static int 2169__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) 2170{ 2171 GLXContext gc = __glXGetCurrentContext(); 2172 __GLXscreenConfigs *psc; 2173 __GLXDRIdrawable *pdraw; 2174 int64_t ust, msc, sbc; 2175 int ret; 2176 2177 if (divisor <= 0 || remainder < 0) 2178 return GLX_BAD_VALUE; 2179 2180 if (!gc || !gc->driContext) 2181 return GLX_BAD_CONTEXT; 2182 2183 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 2184 pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2185 2186#ifdef __DRI_MEDIA_STREAM_COUNTER 2187 if (psc->msc != NULL && psc->driScreen ) { 2188 ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0, 2189 divisor, remainder, &msc, &sbc); 2190 *count = (unsigned) msc; 2191 return (ret == 0) ? 0 : GLX_BAD_CONTEXT; 2192 } 2193#endif 2194 if (psc->driScreen && psc->driScreen->waitForMSC) { 2195 ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc, 2196 &sbc); 2197 *count = (unsigned) msc; 2198 return (ret == True) ? 0 : GLX_BAD_CONTEXT; 2199 } 2200 2201 return GLX_BAD_CONTEXT; 2202} 2203 2204 2205/* 2206** GLX_SGIX_fbconfig 2207** Many of these functions are aliased to GLX 1.3 entry points in the 2208** GLX_functions table. 2209*/ 2210 2211PUBLIC 2212GLX_ALIAS(int, glXGetFBConfigAttribSGIX, 2213 (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value), 2214 (dpy, config, attribute, value), glXGetFBConfigAttrib) 2215 2216PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX, 2217 (Display * dpy, int screen, int *attrib_list, 2218 int *nelements), (dpy, screen, attrib_list, nelements), 2219 glXChooseFBConfig) 2220 2221PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX, 2222 (Display * dpy, GLXFBConfigSGIX config), 2223 (dpy, config), glXGetVisualFromFBConfig) 2224 2225PUBLIC GLXPixmap 2226glXCreateGLXPixmapWithConfigSGIX(Display * dpy, 2227 GLXFBConfigSGIX config, 2228 Pixmap pixmap) 2229{ 2230 xGLXVendorPrivateWithReplyReq *vpreq; 2231 xGLXCreateGLXPixmapWithConfigSGIXReq *req; 2232 GLXPixmap xid = None; 2233 CARD8 opcode; 2234 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config; 2235 __GLXscreenConfigs *psc; 2236 2237 2238 if ((dpy == NULL) || (config == NULL)) { 2239 return None; 2240 } 2241 2242 psc = GetGLXScreenConfigs(dpy, fbconfig->screen); 2243 if ((psc != NULL) 2244 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 2245 opcode = __glXSetupForCommand(dpy); 2246 if (!opcode) { 2247 return None; 2248 } 2249 2250 /* Send the glXCreateGLXPixmapWithConfigSGIX request */ 2251 LockDisplay(dpy); 2252 GetReqExtra(GLXVendorPrivateWithReply, 2253 sz_xGLXCreateGLXPixmapWithConfigSGIXReq - 2254 sz_xGLXVendorPrivateWithReplyReq, vpreq); 2255 req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq; 2256 req->reqType = opcode; 2257 req->glxCode = X_GLXVendorPrivateWithReply; 2258 req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; 2259 req->screen = fbconfig->screen; 2260 req->fbconfig = fbconfig->fbconfigID; 2261 req->pixmap = pixmap; 2262 req->glxpixmap = xid = XAllocID(dpy); 2263 UnlockDisplay(dpy); 2264 SyncHandle(); 2265 } 2266 2267 return xid; 2268} 2269 2270PUBLIC GLXContext 2271glXCreateContextWithConfigSGIX(Display * dpy, 2272 GLXFBConfigSGIX config, int renderType, 2273 GLXContext shareList, Bool allowDirect) 2274{ 2275 GLXContext gc = NULL; 2276 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config; 2277 __GLXscreenConfigs *psc; 2278 2279 2280 if ((dpy == NULL) || (config == NULL)) { 2281 return None; 2282 } 2283 2284 psc = GetGLXScreenConfigs(dpy, fbconfig->screen); 2285 if ((psc != NULL) 2286 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 2287 gc = CreateContext(dpy, fbconfig->fbconfigID, fbconfig, shareList, 2288 allowDirect, 2289 X_GLXvop_CreateContextWithConfigSGIX, renderType, 2290 fbconfig->screen); 2291 } 2292 2293 return gc; 2294} 2295 2296 2297PUBLIC GLXFBConfigSGIX 2298glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis) 2299{ 2300 __GLXdisplayPrivate *priv; 2301 __GLXscreenConfigs *psc = NULL; 2302 2303 if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success) 2304 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit) 2305 && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) { 2306 return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs, 2307 vis->visualid); 2308 } 2309 2310 return NULL; 2311} 2312 2313 2314/* 2315** GLX_SGIX_swap_group 2316*/ 2317static void 2318__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable, 2319 GLXDrawable member) 2320{ 2321 (void) dpy; 2322 (void) drawable; 2323 (void) member; 2324} 2325 2326 2327/* 2328** GLX_SGIX_swap_barrier 2329*/ 2330static void 2331__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier) 2332{ 2333 (void) dpy; 2334 (void) drawable; 2335 (void) barrier; 2336} 2337 2338static Bool 2339__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max) 2340{ 2341 (void) dpy; 2342 (void) screen; 2343 (void) max; 2344 return False; 2345} 2346 2347 2348/* 2349** GLX_OML_sync_control 2350*/ 2351static Bool 2352__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable, 2353 int64_t * ust, int64_t * msc, int64_t * sbc) 2354{ 2355 __GLXdisplayPrivate * const priv = __glXInitialize(dpy); 2356 int i, ret; 2357 __GLXDRIdrawable *pdraw; 2358 __GLXscreenConfigs *psc; 2359 2360 if (!priv) 2361 return False; 2362 2363 pdraw = GetGLXDRIDrawable(dpy, drawable, &i); 2364 psc = &priv->screenConfigs[i]; 2365 2366#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER) 2367 if (pdraw && psc->sbc && psc->msc) 2368 return ( (pdraw && psc->sbc && psc->msc) 2369 && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0) 2370 && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0) 2371 && (__glXGetUST(ust) == 0) ); 2372#endif 2373 if (pdraw && psc && psc->driScreen && psc->driScreen->getDrawableMSC) { 2374 ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc); 2375 return ret; 2376 } 2377 2378 return False; 2379} 2380 2381#ifdef GLX_DIRECT_RENDERING 2382_X_HIDDEN GLboolean 2383__driGetMscRateOML(__DRIdrawable * draw, 2384 int32_t * numerator, int32_t * denominator, void *private) 2385{ 2386#ifdef XF86VIDMODE 2387 __GLXscreenConfigs *psc; 2388 XF86VidModeModeLine mode_line; 2389 int dot_clock; 2390 int i; 2391 __GLXDRIdrawable *glxDraw = private; 2392 2393 (void) draw; 2394 2395 psc = glxDraw->psc; 2396 if (XF86VidModeQueryVersion(psc->dpy, &i, &i) && 2397 XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) { 2398 unsigned n = dot_clock * 1000; 2399 unsigned d = mode_line.vtotal * mode_line.htotal; 2400 2401# define V_INTERLACE 0x010 2402# define V_DBLSCAN 0x020 2403 2404 if (mode_line.flags & V_INTERLACE) 2405 n *= 2; 2406 else if (mode_line.flags & V_DBLSCAN) 2407 d *= 2; 2408 2409 /* The OML_sync_control spec requires that if the refresh rate is a 2410 * whole number, that the returned numerator be equal to the refresh 2411 * rate and the denominator be 1. 2412 */ 2413 2414 if (n % d == 0) { 2415 n /= d; 2416 d = 1; 2417 } 2418 else { 2419 static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 }; 2420 2421 /* This is a poor man's way to reduce a fraction. It's far from 2422 * perfect, but it will work well enough for this situation. 2423 */ 2424 2425 for (i = 0; f[i] != 0; i++) { 2426 while (n % f[i] == 0 && d % f[i] == 0) { 2427 d /= f[i]; 2428 n /= f[i]; 2429 } 2430 } 2431 } 2432 2433 *numerator = n; 2434 *denominator = d; 2435 2436 return True; 2437 } 2438 else 2439 return False; 2440#else 2441 (void) draw; 2442 (void) numerator; 2443 (void) denominator; 2444 (void) private; 2445 2446 return False; 2447#endif 2448} 2449#endif 2450 2451/** 2452 * Determine the refresh rate of the specified drawable and display. 2453 * 2454 * \param dpy Display whose refresh rate is to be determined. 2455 * \param drawable Drawable whose refresh rate is to be determined. 2456 * \param numerator Numerator of the refresh rate. 2457 * \param demoninator Denominator of the refresh rate. 2458 * \return If the refresh rate for the specified display and drawable could 2459 * be calculated, True is returned. Otherwise False is returned. 2460 * 2461 * \note This function is implemented entirely client-side. A lot of other 2462 * functionality is required to export GLX_OML_sync_control, so on 2463 * XFree86 this function can be called for direct-rendering contexts 2464 * when GLX_OML_sync_control appears in the client extension string. 2465 */ 2466 2467_X_HIDDEN GLboolean 2468__glXGetMscRateOML(Display * dpy, GLXDrawable drawable, 2469 int32_t * numerator, int32_t * denominator) 2470{ 2471#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE ) 2472 __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL); 2473 2474 if (draw == NULL) 2475 return False; 2476 2477 return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw); 2478#else 2479 (void) dpy; 2480 (void) drawable; 2481 (void) numerator; 2482 (void) denominator; 2483#endif 2484 return False; 2485} 2486 2487 2488static int64_t 2489__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, 2490 int64_t target_msc, int64_t divisor, int64_t remainder) 2491{ 2492 GLXContext gc = __glXGetCurrentContext(); 2493 int screen; 2494 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2495 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2496 2497 if (!pdraw || !gc || !gc->driContext) /* no GLX for this */ 2498 return -1; 2499 2500 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2501 * error", but it also says "It [glXSwapBuffersMscOML] will return a value 2502 * of -1 if the function failed because of errors detected in the input 2503 * parameters" 2504 */ 2505 if (divisor < 0 || remainder < 0 || target_msc < 0) 2506 return -1; 2507 if (divisor > 0 && remainder >= divisor) 2508 return -1; 2509 2510#ifdef __DRI_SWAP_BUFFER_COUNTER 2511 if (psc->counters != NULL) 2512 return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc, 2513 divisor, remainder); 2514#endif 2515 2516#ifdef GLX_DIRECT_RENDERING 2517 if (psc->driScreen && psc->driScreen->swapBuffers) 2518 return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor, 2519 remainder); 2520#endif 2521 2522 return -1; 2523} 2524 2525 2526static Bool 2527__glXWaitForMscOML(Display * dpy, GLXDrawable drawable, 2528 int64_t target_msc, int64_t divisor, 2529 int64_t remainder, int64_t * ust, 2530 int64_t * msc, int64_t * sbc) 2531{ 2532 int screen; 2533 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2534 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); 2535 int ret; 2536 2537 fprintf(stderr, "waitmsc: %lld, %lld, %lld\n", target_msc, divisor, 2538 remainder); 2539 2540 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2541 * error", but the return type in the spec is Bool. 2542 */ 2543 if (divisor < 0 || remainder < 0 || target_msc < 0) 2544 return False; 2545 if (divisor > 0 && remainder >= divisor) 2546 return False; 2547 2548#ifdef __DRI_MEDIA_STREAM_COUNTER 2549 if (pdraw != NULL && psc->msc != NULL) { 2550 fprintf(stderr, "dri1 msc\n"); 2551 ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc, 2552 divisor, remainder, msc, sbc); 2553 2554 /* __glXGetUST returns zero on success and non-zero on failure. 2555 * This function returns True on success and False on failure. 2556 */ 2557 return ((ret == 0) && (__glXGetUST(ust) == 0)); 2558 } 2559#endif 2560 if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) { 2561 ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder, 2562 ust, msc, sbc); 2563 return ret; 2564 } 2565 2566 fprintf(stderr, "no drawable??\n"); 2567 return False; 2568} 2569 2570 2571static Bool 2572__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, 2573 int64_t target_sbc, int64_t * ust, 2574 int64_t * msc, int64_t * sbc) 2575{ 2576 int screen; 2577 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2578 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2579 int ret; 2580 2581 /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE 2582 * error", but the return type in the spec is Bool. 2583 */ 2584 if (target_sbc < 0) 2585 return False; 2586#ifdef __DRI_SWAP_BUFFER_COUNTER 2587 if (pdraw != NULL && psc->sbc != NULL) { 2588 ret = 2589 (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc); 2590 2591 /* __glXGetUST returns zero on success and non-zero on failure. 2592 * This function returns True on success and False on failure. 2593 */ 2594 return ((ret == 0) && (__glXGetUST(ust) == 0)); 2595 } 2596#endif 2597 if (pdraw && psc->driScreen && psc->driScreen->waitForSBC) { 2598 ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc); 2599 return ret; 2600 } 2601 return False; 2602} 2603 2604 2605/** 2606 * GLX_MESA_allocate_memory 2607 */ 2608/*@{*/ 2609 2610PUBLIC void * 2611glXAllocateMemoryMESA(Display * dpy, int scrn, 2612 size_t size, float readFreq, 2613 float writeFreq, float priority) 2614{ 2615#ifdef __DRI_ALLOCATE 2616 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2617 2618 if (psc && psc->allocate) 2619 return (*psc->allocate->allocateMemory) (psc->__driScreen, size, 2620 readFreq, writeFreq, priority); 2621 2622#else 2623 (void) dpy; 2624 (void) scrn; 2625 (void) size; 2626 (void) readFreq; 2627 (void) writeFreq; 2628 (void) priority; 2629#endif /* __DRI_ALLOCATE */ 2630 2631 return NULL; 2632} 2633 2634 2635PUBLIC void 2636glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer) 2637{ 2638#ifdef __DRI_ALLOCATE 2639 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2640 2641 if (psc && psc->allocate) 2642 (*psc->allocate->freeMemory) (psc->__driScreen, pointer); 2643 2644#else 2645 (void) dpy; 2646 (void) scrn; 2647 (void) pointer; 2648#endif /* __DRI_ALLOCATE */ 2649} 2650 2651 2652PUBLIC GLuint 2653glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer) 2654{ 2655#ifdef __DRI_ALLOCATE 2656 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2657 2658 if (psc && psc->allocate) 2659 return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer); 2660 2661#else 2662 (void) dpy; 2663 (void) scrn; 2664 (void) pointer; 2665#endif /* GLX_DIRECT_RENDERING */ 2666 2667 return ~0L; 2668} 2669 2670/*@}*/ 2671 2672 2673/** 2674 * Mesa extension stubs. These will help reduce portability problems. 2675 */ 2676/*@{*/ 2677 2678/** 2679 * Release all buffers associated with the specified GLX drawable. 2680 * 2681 * \todo 2682 * This function was intended for stand-alone Mesa. The issue there is that 2683 * the library doesn't get any notification when a window is closed. In 2684 * DRI there is a similar but slightly different issue. When GLX 1.3 is 2685 * supported, there are 3 different functions to destroy a drawable. It 2686 * should be possible to create GLX protocol (or have it determine which 2687 * protocol to use based on the type of the drawable) to have one function 2688 * do the work of 3. For the direct-rendering case, this function could 2689 * just call the driver's \c __DRIdrawableRec::destroyDrawable function. 2690 * This would reduce the frequency with which \c __driGarbageCollectDrawables 2691 * would need to be used. This really should be done as part of the new DRI 2692 * interface work. 2693 * 2694 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt 2695 * __driGarbageCollectDrawables 2696 * glXDestroyGLXPixmap 2697 * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow 2698 * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX 2699 */ 2700static Bool 2701__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d) 2702{ 2703 (void) dpy; 2704 (void) d; 2705 return False; 2706} 2707 2708 2709PUBLIC GLXPixmap 2710glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual, 2711 Pixmap pixmap, Colormap cmap) 2712{ 2713 (void) dpy; 2714 (void) visual; 2715 (void) pixmap; 2716 (void) cmap; 2717 return 0; 2718} 2719 2720/*@}*/ 2721 2722 2723/** 2724 * GLX_MESA_copy_sub_buffer 2725 */ 2726#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */ 2727static void 2728__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable, 2729 int x, int y, int width, int height) 2730{ 2731 xGLXVendorPrivateReq *req; 2732 GLXContext gc; 2733 GLXContextTag tag; 2734 CARD32 *drawable_ptr; 2735 INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr; 2736 CARD8 opcode; 2737 2738#ifdef __DRI_COPY_SUB_BUFFER 2739 int screen; 2740 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2741 if (pdraw != NULL) { 2742 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2743 if (psc->driScreen->copySubBuffer != NULL) { 2744 glFlush(); 2745 (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height); 2746 } 2747 2748 return; 2749 } 2750#endif 2751 2752 opcode = __glXSetupForCommand(dpy); 2753 if (!opcode) 2754 return; 2755 2756 /* 2757 ** The calling thread may or may not have a current context. If it 2758 ** does, send the context tag so the server can do a flush. 2759 */ 2760 gc = __glXGetCurrentContext(); 2761 if ((gc != NULL) && (dpy == gc->currentDpy) && 2762 ((drawable == gc->currentDrawable) || 2763 (drawable == gc->currentReadable))) { 2764 tag = gc->currentContextTag; 2765 } 2766 else { 2767 tag = 0; 2768 } 2769 2770 LockDisplay(dpy); 2771 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req); 2772 req->reqType = opcode; 2773 req->glxCode = X_GLXVendorPrivate; 2774 req->vendorCode = X_GLXvop_CopySubBufferMESA; 2775 req->contextTag = tag; 2776 2777 drawable_ptr = (CARD32 *) (req + 1); 2778 x_ptr = (INT32 *) (drawable_ptr + 1); 2779 y_ptr = (INT32 *) (drawable_ptr + 2); 2780 w_ptr = (INT32 *) (drawable_ptr + 3); 2781 h_ptr = (INT32 *) (drawable_ptr + 4); 2782 2783 *drawable_ptr = drawable; 2784 *x_ptr = x; 2785 *y_ptr = y; 2786 *w_ptr = width; 2787 *h_ptr = height; 2788 2789 UnlockDisplay(dpy); 2790 SyncHandle(); 2791} 2792 2793 2794/** 2795 * GLX_EXT_texture_from_pixmap 2796 */ 2797/*@{*/ 2798static void 2799__glXBindTexImageEXT(Display * dpy, 2800 GLXDrawable drawable, int buffer, const int *attrib_list) 2801{ 2802 xGLXVendorPrivateReq *req; 2803 GLXContext gc = __glXGetCurrentContext(); 2804 CARD32 *drawable_ptr; 2805 INT32 *buffer_ptr; 2806 CARD32 *num_attrib_ptr; 2807 CARD32 *attrib_ptr; 2808 CARD8 opcode; 2809 unsigned int i; 2810 2811 if (gc == NULL) 2812 return; 2813 2814 i = 0; 2815 if (attrib_list) { 2816 while (attrib_list[i * 2] != None) 2817 i++; 2818 } 2819 2820#ifdef GLX_DIRECT_RENDERING 2821 if (gc->driContext) { 2822 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); 2823 2824 if (pdraw != NULL) { 2825 if (pdraw->psc->texBuffer->base.version >= 2 && 2826 pdraw->psc->texBuffer->setTexBuffer2 != NULL) { 2827 (*pdraw->psc->texBuffer->setTexBuffer2) (gc->__driContext, 2828 pdraw->textureTarget, 2829 pdraw->textureFormat, 2830 pdraw->driDrawable); 2831 } 2832 else { 2833 (*pdraw->psc->texBuffer->setTexBuffer) (gc->__driContext, 2834 pdraw->textureTarget, 2835 pdraw->driDrawable); 2836 } 2837 } 2838 return; 2839 } 2840#endif 2841 2842 opcode = __glXSetupForCommand(dpy); 2843 if (!opcode) 2844 return; 2845 2846 LockDisplay(dpy); 2847 GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req); 2848 req->reqType = opcode; 2849 req->glxCode = X_GLXVendorPrivate; 2850 req->vendorCode = X_GLXvop_BindTexImageEXT; 2851 req->contextTag = gc->currentContextTag; 2852 2853 drawable_ptr = (CARD32 *) (req + 1); 2854 buffer_ptr = (INT32 *) (drawable_ptr + 1); 2855 num_attrib_ptr = (CARD32 *) (buffer_ptr + 1); 2856 attrib_ptr = (CARD32 *) (num_attrib_ptr + 1); 2857 2858 *drawable_ptr = drawable; 2859 *buffer_ptr = buffer; 2860 *num_attrib_ptr = (CARD32) i; 2861 2862 i = 0; 2863 if (attrib_list) { 2864 while (attrib_list[i * 2] != None) { 2865 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0]; 2866 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1]; 2867 i++; 2868 } 2869 } 2870 2871 UnlockDisplay(dpy); 2872 SyncHandle(); 2873} 2874 2875static void 2876__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer) 2877{ 2878 xGLXVendorPrivateReq *req; 2879 GLXContext gc = __glXGetCurrentContext(); 2880 CARD32 *drawable_ptr; 2881 INT32 *buffer_ptr; 2882 CARD8 opcode; 2883 2884 if ((gc == NULL) || GC_IS_DIRECT(gc)) 2885 return; 2886 2887 opcode = __glXSetupForCommand(dpy); 2888 if (!opcode) 2889 return; 2890 2891 LockDisplay(dpy); 2892 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req); 2893 req->reqType = opcode; 2894 req->glxCode = X_GLXVendorPrivate; 2895 req->vendorCode = X_GLXvop_ReleaseTexImageEXT; 2896 req->contextTag = gc->currentContextTag; 2897 2898 drawable_ptr = (CARD32 *) (req + 1); 2899 buffer_ptr = (INT32 *) (drawable_ptr + 1); 2900 2901 *drawable_ptr = drawable; 2902 *buffer_ptr = buffer; 2903 2904 UnlockDisplay(dpy); 2905 SyncHandle(); 2906} 2907 2908/*@}*/ 2909 2910/** 2911 * \c strdup is actually not a standard ANSI C or POSIX routine. 2912 * Irix will not define it if ANSI mode is in effect. 2913 * 2914 * \sa strdup 2915 */ 2916_X_HIDDEN char * 2917__glXstrdup(const char *str) 2918{ 2919 char *copy; 2920 copy = (char *) Xmalloc(strlen(str) + 1); 2921 if (!copy) 2922 return NULL; 2923 strcpy(copy, str); 2924 return copy; 2925} 2926 2927/* 2928** glXGetProcAddress support 2929*/ 2930 2931struct name_address_pair 2932{ 2933 const char *Name; 2934 GLvoid *Address; 2935}; 2936 2937#define GLX_FUNCTION(f) { # f, (GLvoid *) f } 2938#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f } 2939 2940static const struct name_address_pair GLX_functions[] = { 2941 /*** GLX_VERSION_1_0 ***/ 2942 GLX_FUNCTION(glXChooseVisual), 2943 GLX_FUNCTION(glXCopyContext), 2944 GLX_FUNCTION(glXCreateContext), 2945 GLX_FUNCTION(glXCreateGLXPixmap), 2946 GLX_FUNCTION(glXDestroyContext), 2947 GLX_FUNCTION(glXDestroyGLXPixmap), 2948 GLX_FUNCTION(glXGetConfig), 2949 GLX_FUNCTION(glXGetCurrentContext), 2950 GLX_FUNCTION(glXGetCurrentDrawable), 2951 GLX_FUNCTION(glXIsDirect), 2952 GLX_FUNCTION(glXMakeCurrent), 2953 GLX_FUNCTION(glXQueryExtension), 2954 GLX_FUNCTION(glXQueryVersion), 2955 GLX_FUNCTION(glXSwapBuffers), 2956 GLX_FUNCTION(glXUseXFont), 2957 GLX_FUNCTION(glXWaitGL), 2958 GLX_FUNCTION(glXWaitX), 2959 2960 /*** GLX_VERSION_1_1 ***/ 2961 GLX_FUNCTION(glXGetClientString), 2962 GLX_FUNCTION(glXQueryExtensionsString), 2963 GLX_FUNCTION(glXQueryServerString), 2964 2965 /*** GLX_VERSION_1_2 ***/ 2966 GLX_FUNCTION(glXGetCurrentDisplay), 2967 2968 /*** GLX_VERSION_1_3 ***/ 2969 GLX_FUNCTION(glXChooseFBConfig), 2970 GLX_FUNCTION(glXCreateNewContext), 2971 GLX_FUNCTION(glXCreatePbuffer), 2972 GLX_FUNCTION(glXCreatePixmap), 2973 GLX_FUNCTION(glXCreateWindow), 2974 GLX_FUNCTION(glXDestroyPbuffer), 2975 GLX_FUNCTION(glXDestroyPixmap), 2976 GLX_FUNCTION(glXDestroyWindow), 2977 GLX_FUNCTION(glXGetCurrentReadDrawable), 2978 GLX_FUNCTION(glXGetFBConfigAttrib), 2979 GLX_FUNCTION(glXGetFBConfigs), 2980 GLX_FUNCTION(glXGetSelectedEvent), 2981 GLX_FUNCTION(glXGetVisualFromFBConfig), 2982 GLX_FUNCTION(glXMakeContextCurrent), 2983 GLX_FUNCTION(glXQueryContext), 2984 GLX_FUNCTION(glXQueryDrawable), 2985 GLX_FUNCTION(glXSelectEvent), 2986 2987 /*** GLX_SGI_swap_control ***/ 2988 GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI), 2989 2990 /*** GLX_SGI_video_sync ***/ 2991 GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI), 2992 GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI), 2993 2994 /*** GLX_SGI_make_current_read ***/ 2995 GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent), 2996 GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable), 2997 2998 /*** GLX_EXT_import_context ***/ 2999 GLX_FUNCTION(glXFreeContextEXT), 3000 GLX_FUNCTION(glXGetContextIDEXT), 3001 GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay), 3002 GLX_FUNCTION(glXImportContextEXT), 3003 GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext), 3004 3005 /*** GLX_SGIX_fbconfig ***/ 3006 GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib), 3007 GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig), 3008 GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX), 3009 GLX_FUNCTION(glXCreateContextWithConfigSGIX), 3010 GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig), 3011 GLX_FUNCTION(glXGetFBConfigFromVisualSGIX), 3012 3013 /*** GLX_SGIX_pbuffer ***/ 3014 GLX_FUNCTION(glXCreateGLXPbufferSGIX), 3015 GLX_FUNCTION(glXDestroyGLXPbufferSGIX), 3016 GLX_FUNCTION(glXQueryGLXPbufferSGIX), 3017 GLX_FUNCTION(glXSelectEventSGIX), 3018 GLX_FUNCTION(glXGetSelectedEventSGIX), 3019 3020 /*** GLX_SGIX_swap_group ***/ 3021 GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX), 3022 3023 /*** GLX_SGIX_swap_barrier ***/ 3024 GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX), 3025 GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX), 3026 3027 /*** GLX_MESA_allocate_memory ***/ 3028 GLX_FUNCTION(glXAllocateMemoryMESA), 3029 GLX_FUNCTION(glXFreeMemoryMESA), 3030 GLX_FUNCTION(glXGetMemoryOffsetMESA), 3031 3032 /*** GLX_MESA_copy_sub_buffer ***/ 3033 GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA), 3034 3035 /*** GLX_MESA_pixmap_colormap ***/ 3036 GLX_FUNCTION(glXCreateGLXPixmapMESA), 3037 3038 /*** GLX_MESA_release_buffers ***/ 3039 GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA), 3040 3041 /*** GLX_MESA_swap_control ***/ 3042 GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA), 3043 GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA), 3044 3045 /*** GLX_MESA_swap_frame_usage ***/ 3046 GLX_FUNCTION2(glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA), 3047 GLX_FUNCTION2(glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA), 3048 GLX_FUNCTION2(glXGetFrameUsageMESA, __glXGetFrameUsageMESA), 3049 GLX_FUNCTION2(glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA), 3050 3051 /*** GLX_ARB_get_proc_address ***/ 3052 GLX_FUNCTION(glXGetProcAddressARB), 3053 3054 /*** GLX 1.4 ***/ 3055 GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB), 3056 3057 /*** GLX_OML_sync_control ***/ 3058 GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML), 3059 GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML), 3060 GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML), 3061 GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML), 3062 GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML), 3063 3064 /*** GLX_EXT_texture_from_pixmap ***/ 3065 GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT), 3066 GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT), 3067 3068#ifdef GLX_DIRECT_RENDERING 3069 /*** DRI configuration ***/ 3070 GLX_FUNCTION(glXGetScreenDriver), 3071 GLX_FUNCTION(glXGetDriverConfig), 3072#endif 3073 3074 {NULL, NULL} /* end of list */ 3075}; 3076 3077 3078static const GLvoid * 3079get_glx_proc_address(const char *funcName) 3080{ 3081 GLuint i; 3082 3083 /* try static functions */ 3084 for (i = 0; GLX_functions[i].Name; i++) { 3085 if (strcmp(GLX_functions[i].Name, funcName) == 0) 3086 return GLX_functions[i].Address; 3087 } 3088 3089 return NULL; 3090} 3091 3092 3093/** 3094 * Get the address of a named GL function. This is the pre-GLX 1.4 name for 3095 * \c glXGetProcAddress. 3096 * 3097 * \param procName Name of a GL or GLX function. 3098 * \returns A pointer to the named function 3099 * 3100 * \sa glXGetProcAddress 3101 */ 3102PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void) 3103{ 3104 typedef void (*gl_function) (void); 3105 gl_function f; 3106 3107 3108 /* Search the table of GLX and internal functions first. If that 3109 * fails and the supplied name could be a valid core GL name, try 3110 * searching the core GL function table. This check is done to prevent 3111 * DRI based drivers from searching the core GL function table for 3112 * internal API functions. 3113 */ 3114 3115 f = (gl_function) get_glx_proc_address((const char *) procName); 3116 if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l') 3117 && (procName[2] != 'X')) { 3118 f = (gl_function) _glapi_get_proc_address((const char *) procName); 3119 } 3120 3121 return f; 3122} 3123 3124/** 3125 * Get the address of a named GL function. This is the GLX 1.4 name for 3126 * \c glXGetProcAddressARB. 3127 * 3128 * \param procName Name of a GL or GLX function. 3129 * \returns A pointer to the named function 3130 * 3131 * \sa glXGetProcAddressARB 3132 */ 3133PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void) 3134#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED) 3135 __attribute__ ((alias("glXGetProcAddressARB"))); 3136#else 3137{ 3138 return glXGetProcAddressARB(procName); 3139} 3140#endif /* __GNUC__ */ 3141 3142 3143#ifdef GLX_DIRECT_RENDERING 3144/** 3145 * Get the unadjusted system time (UST). Currently, the UST is measured in 3146 * microseconds since Epoc. The actual resolution of the UST may vary from 3147 * system to system, and the units may vary from release to release. 3148 * Drivers should not call this function directly. They should instead use 3149 * \c glXGetProcAddress to obtain a pointer to the function. 3150 * 3151 * \param ust Location to store the 64-bit UST 3152 * \returns Zero on success or a negative errno value on failure. 3153 * 3154 * \sa glXGetProcAddress, PFNGLXGETUSTPROC 3155 * 3156 * \since Internal API version 20030317. 3157 */ 3158_X_HIDDEN int 3159__glXGetUST(int64_t * ust) 3160{ 3161 struct timeval tv; 3162 3163 if (ust == NULL) { 3164 return -EFAULT; 3165 } 3166 3167 if (gettimeofday(&tv, NULL) == 0) { 3168 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; 3169 return 0; 3170 } 3171 else { 3172 return -errno; 3173 } 3174} 3175#endif /* GLX_DIRECT_RENDERING */ 3176