glxcmds.c revision edb5253dfa0751e451dca7c9a494be4609390545
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/* Test that all bits from a are contained in b */ 1114#define MATCH_MASK(param) \ 1115 do { \ 1116 if ((a->param & ~b->param) != 0) \ 1117 return False; \ 1118 } while (0); 1119 1120/** 1121 * Determine if two GLXFBConfigs are compatible. 1122 * 1123 * \param a Application specified config to test. 1124 * \param b Server specified config to test against \c a. 1125 */ 1126static Bool 1127fbconfigs_compatible(const __GLcontextModes * const a, 1128 const __GLcontextModes * const b) 1129{ 1130 MATCH_DONT_CARE(doubleBufferMode); 1131 MATCH_DONT_CARE(visualType); 1132 MATCH_DONT_CARE(visualRating); 1133 MATCH_DONT_CARE(xRenderable); 1134 MATCH_DONT_CARE(fbconfigID); 1135 MATCH_DONT_CARE(swapMethod); 1136 1137 MATCH_MINIMUM(rgbBits); 1138 MATCH_MINIMUM(numAuxBuffers); 1139 MATCH_MINIMUM(redBits); 1140 MATCH_MINIMUM(greenBits); 1141 MATCH_MINIMUM(blueBits); 1142 MATCH_MINIMUM(alphaBits); 1143 MATCH_MINIMUM(depthBits); 1144 MATCH_MINIMUM(stencilBits); 1145 MATCH_MINIMUM(accumRedBits); 1146 MATCH_MINIMUM(accumGreenBits); 1147 MATCH_MINIMUM(accumBlueBits); 1148 MATCH_MINIMUM(accumAlphaBits); 1149 MATCH_MINIMUM(sampleBuffers); 1150 MATCH_MINIMUM(maxPbufferWidth); 1151 MATCH_MINIMUM(maxPbufferHeight); 1152 MATCH_MINIMUM(maxPbufferPixels); 1153 MATCH_MINIMUM(samples); 1154 1155 MATCH_DONT_CARE(stereoMode); 1156 MATCH_EXACT(level); 1157 1158 MATCH_MASK(drawableType); 1159 MATCH_MASK(renderType); 1160 1161 /* There is a bug in a few of the XFree86 DDX drivers. They contain 1162 * visuals with a "transparent type" of 0 when they really mean GLX_NONE. 1163 * Technically speaking, it is a bug in the DDX driver, but there is 1164 * enough of an installed base to work around the problem here. In any 1165 * case, 0 is not a valid value of the transparent type, so we'll treat 0 1166 * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and 1167 * 0 from the server to be a match to maintain backward compatibility with 1168 * the (broken) drivers. 1169 */ 1170 1171 if (a->transparentPixel != (int) GLX_DONT_CARE && a->transparentPixel != 0) { 1172 if (a->transparentPixel == GLX_NONE) { 1173 if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0) 1174 return False; 1175 } 1176 else { 1177 MATCH_EXACT(transparentPixel); 1178 } 1179 1180 switch (a->transparentPixel) { 1181 case GLX_TRANSPARENT_RGB: 1182 MATCH_DONT_CARE(transparentRed); 1183 MATCH_DONT_CARE(transparentGreen); 1184 MATCH_DONT_CARE(transparentBlue); 1185 MATCH_DONT_CARE(transparentAlpha); 1186 break; 1187 1188 case GLX_TRANSPARENT_INDEX: 1189 MATCH_DONT_CARE(transparentIndex); 1190 break; 1191 1192 default: 1193 break; 1194 } 1195 } 1196 1197 return True; 1198} 1199 1200 1201/* There's some trickly language in the GLX spec about how this is supposed 1202 * to work. Basically, if a given component size is either not specified 1203 * or the requested size is zero, it is supposed to act like PERFER_SMALLER. 1204 * Well, that's really hard to do with the code as-is. This behavior is 1205 * closer to correct, but still not technically right. 1206 */ 1207#define PREFER_LARGER_OR_ZERO(comp) \ 1208 do { \ 1209 if ( ((*a)-> comp) != ((*b)-> comp) ) { \ 1210 if ( ((*a)-> comp) == 0 ) { \ 1211 return -1; \ 1212 } \ 1213 else if ( ((*b)-> comp) == 0 ) { \ 1214 return 1; \ 1215 } \ 1216 else { \ 1217 return ((*b)-> comp) - ((*a)-> comp) ; \ 1218 } \ 1219 } \ 1220 } while( 0 ) 1221 1222#define PREFER_LARGER(comp) \ 1223 do { \ 1224 if ( ((*a)-> comp) != ((*b)-> comp) ) { \ 1225 return ((*b)-> comp) - ((*a)-> comp) ; \ 1226 } \ 1227 } while( 0 ) 1228 1229#define PREFER_SMALLER(comp) \ 1230 do { \ 1231 if ( ((*a)-> comp) != ((*b)-> comp) ) { \ 1232 return ((*a)-> comp) - ((*b)-> comp) ; \ 1233 } \ 1234 } while( 0 ) 1235 1236/** 1237 * Compare two GLXFBConfigs. This function is intended to be used as the 1238 * compare function passed in to qsort. 1239 * 1240 * \returns If \c a is a "better" config, according to the specification of 1241 * SGIX_fbconfig, a number less than zero is returned. If \c b is 1242 * better, then a number greater than zero is return. If both are 1243 * equal, zero is returned. 1244 * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX 1245 */ 1246static int 1247fbconfig_compare(const __GLcontextModes * const *const a, 1248 const __GLcontextModes * const *const b) 1249{ 1250 /* The order of these comparisons must NOT change. It is defined by 1251 * the GLX 1.3 spec and ARB_multisample. 1252 */ 1253 1254 PREFER_SMALLER(visualSelectGroup); 1255 1256 /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and 1257 * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the 1258 * numerical sort order of the enums (0x8000, 0x8001, and 0x800D). 1259 */ 1260 PREFER_SMALLER(visualRating); 1261 1262 /* This isn't quite right. It is supposed to compare the sum of the 1263 * components the user specifically set minimums for. 1264 */ 1265 PREFER_LARGER_OR_ZERO(redBits); 1266 PREFER_LARGER_OR_ZERO(greenBits); 1267 PREFER_LARGER_OR_ZERO(blueBits); 1268 PREFER_LARGER_OR_ZERO(alphaBits); 1269 1270 PREFER_SMALLER(rgbBits); 1271 1272 if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) { 1273 /* Prefer single-buffer. 1274 */ 1275 return (!(*a)->doubleBufferMode) ? -1 : 1; 1276 } 1277 1278 PREFER_SMALLER(numAuxBuffers); 1279 1280 PREFER_LARGER_OR_ZERO(depthBits); 1281 PREFER_SMALLER(stencilBits); 1282 1283 /* This isn't quite right. It is supposed to compare the sum of the 1284 * components the user specifically set minimums for. 1285 */ 1286 PREFER_LARGER_OR_ZERO(accumRedBits); 1287 PREFER_LARGER_OR_ZERO(accumGreenBits); 1288 PREFER_LARGER_OR_ZERO(accumBlueBits); 1289 PREFER_LARGER_OR_ZERO(accumAlphaBits); 1290 1291 PREFER_SMALLER(visualType); 1292 1293 /* None of the multisample specs say where this comparison should happen, 1294 * so I put it near the end. 1295 */ 1296 PREFER_SMALLER(sampleBuffers); 1297 PREFER_SMALLER(samples); 1298 1299 /* None of the pbuffer or fbconfig specs say that this comparison needs 1300 * to happen at all, but it seems like it should. 1301 */ 1302 PREFER_LARGER(maxPbufferWidth); 1303 PREFER_LARGER(maxPbufferHeight); 1304 PREFER_LARGER(maxPbufferPixels); 1305 1306 return 0; 1307} 1308 1309 1310/** 1311 * Selects and sorts a subset of the supplied configs based on the attributes. 1312 * This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig, 1313 * and \c glXChooseFBConfigSGIX. 1314 * 1315 * \param configs Array of pointers to possible configs. The elements of 1316 * this array that do not meet the criteria will be set to 1317 * NULL. The remaining elements will be sorted according to 1318 * the various visual / FBConfig selection rules. 1319 * \param num_configs Number of elements in the \c configs array. 1320 * \param attribList Attributes used select from \c configs. This array is 1321 * terminated by a \c None tag. The array can either take 1322 * the form expected by \c glXChooseVisual (where boolean 1323 * tags do not have a value) or by \c glXChooseFBConfig 1324 * (where every tag has a value). 1325 * \param fbconfig_style_tags Selects whether \c attribList is in 1326 * \c glXChooseVisual style or 1327 * \c glXChooseFBConfig style. 1328 * \returns The number of valid elements left in \c configs. 1329 * 1330 * \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX 1331 */ 1332static int 1333choose_visual(__GLcontextModes ** configs, int num_configs, 1334 const int *attribList, GLboolean fbconfig_style_tags) 1335{ 1336 __GLcontextModes test_config; 1337 int base; 1338 int i; 1339 1340 /* This is a fairly direct implementation of the selection method 1341 * described by GLX_SGIX_fbconfig. Start by culling out all the 1342 * configs that are not compatible with the selected parameter 1343 * list. 1344 */ 1345 1346 init_fbconfig_for_chooser(&test_config, fbconfig_style_tags); 1347 __glXInitializeVisualConfigFromTags(&test_config, 512, 1348 (const INT32 *) attribList, 1349 GL_TRUE, fbconfig_style_tags); 1350 1351 base = 0; 1352 for (i = 0; i < num_configs; i++) { 1353 if (fbconfigs_compatible(&test_config, configs[i])) { 1354 configs[base] = configs[i]; 1355 base++; 1356 } 1357 } 1358 1359 if (base == 0) { 1360 return 0; 1361 } 1362 1363 if (base < num_configs) { 1364 (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base)); 1365 } 1366 1367 /* After the incompatible configs are removed, the resulting 1368 * list is sorted according to the rules set out in the various 1369 * specifications. 1370 */ 1371 1372 qsort(configs, base, sizeof(__GLcontextModes *), 1373 (int (*)(const void *, const void *)) fbconfig_compare); 1374 return base; 1375} 1376 1377 1378 1379 1380/* 1381** Return the visual that best matches the template. Return None if no 1382** visual matches the template. 1383*/ 1384PUBLIC XVisualInfo * 1385glXChooseVisual(Display * dpy, int screen, int *attribList) 1386{ 1387 XVisualInfo *visualList = NULL; 1388 __GLXdisplayPrivate *priv; 1389 __GLXscreenConfigs *psc; 1390 __GLcontextModes test_config; 1391 __GLcontextModes *modes; 1392 const __GLcontextModes *best_config = NULL; 1393 1394 /* 1395 ** Get a list of all visuals, return if list is empty 1396 */ 1397 if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { 1398 return None; 1399 } 1400 1401 1402 /* 1403 ** Build a template from the defaults and the attribute list 1404 ** Free visual list and return if an unexpected token is encountered 1405 */ 1406 init_fbconfig_for_chooser(&test_config, GL_FALSE); 1407 __glXInitializeVisualConfigFromTags(&test_config, 512, 1408 (const INT32 *) attribList, 1409 GL_TRUE, GL_FALSE); 1410 1411 /* 1412 ** Eliminate visuals that don't meet minimum requirements 1413 ** Compute a score for those that do 1414 ** Remember which visual, if any, got the highest score 1415 ** If no visual is acceptable, return None 1416 ** Otherwise, create an XVisualInfo list with just the selected X visual 1417 ** and return this. 1418 */ 1419 for (modes = psc->visuals; modes != NULL; modes = modes->next) { 1420 if (fbconfigs_compatible(&test_config, modes) 1421 && ((best_config == NULL) 1422 || 1423 (fbconfig_compare 1424 ((const __GLcontextModes * const *const) &modes, 1425 &best_config) < 0))) { 1426 XVisualInfo visualTemplate; 1427 XVisualInfo *newList; 1428 int i; 1429 1430 visualTemplate.screen = screen; 1431 visualTemplate.visualid = modes->visualID; 1432 newList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, 1433 &visualTemplate, &i); 1434 1435 if (newList) { 1436 Xfree(visualList); 1437 visualList = newList; 1438 best_config = modes; 1439 } 1440 } 1441 } 1442 1443 return visualList; 1444} 1445 1446 1447PUBLIC const char * 1448glXQueryExtensionsString(Display * dpy, int screen) 1449{ 1450 __GLXscreenConfigs *psc; 1451 __GLXdisplayPrivate *priv; 1452 1453 if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { 1454 return NULL; 1455 } 1456 1457 if (!psc->effectiveGLXexts) { 1458 if (!psc->serverGLXexts) { 1459 psc->serverGLXexts = 1460 __glXQueryServerString(dpy, priv->majorOpcode, screen, 1461 GLX_EXTENSIONS); 1462 } 1463 1464 __glXCalculateUsableExtensions(psc, 1465#ifdef GLX_DIRECT_RENDERING 1466 (psc->driScreen != NULL), 1467#else 1468 GL_FALSE, 1469#endif 1470 priv->minorVersion); 1471 } 1472 1473 return psc->effectiveGLXexts; 1474} 1475 1476PUBLIC const char * 1477glXGetClientString(Display * dpy, int name) 1478{ 1479 (void) dpy; 1480 1481 switch (name) { 1482 case GLX_VENDOR: 1483 return (__glXGLXClientVendorName); 1484 case GLX_VERSION: 1485 return (__glXGLXClientVersion); 1486 case GLX_EXTENSIONS: 1487 return (__glXGetClientExtensions()); 1488 default: 1489 return NULL; 1490 } 1491} 1492 1493PUBLIC const char * 1494glXQueryServerString(Display * dpy, int screen, int name) 1495{ 1496 __GLXscreenConfigs *psc; 1497 __GLXdisplayPrivate *priv; 1498 const char **str; 1499 1500 1501 if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { 1502 return NULL; 1503 } 1504 1505 switch (name) { 1506 case GLX_VENDOR: 1507 str = &priv->serverGLXvendor; 1508 break; 1509 case GLX_VERSION: 1510 str = &priv->serverGLXversion; 1511 break; 1512 case GLX_EXTENSIONS: 1513 str = &psc->serverGLXexts; 1514 break; 1515 default: 1516 return NULL; 1517 } 1518 1519 if (*str == NULL) { 1520 *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name); 1521 } 1522 1523 return *str; 1524} 1525 1526void 1527__glXClientInfo(Display * dpy, int opcode) 1528{ 1529 char *ext_str = __glXGetClientGLExtensionString(); 1530 int size = strlen(ext_str) + 1; 1531 1532#ifdef USE_XCB 1533 xcb_connection_t *c = XGetXCBConnection(dpy); 1534 xcb_glx_client_info(c, 1535 GLX_MAJOR_VERSION, GLX_MINOR_VERSION, size, ext_str); 1536#else 1537 xGLXClientInfoReq *req; 1538 1539 /* Send the glXClientInfo request */ 1540 LockDisplay(dpy); 1541 GetReq(GLXClientInfo, req); 1542 req->reqType = opcode; 1543 req->glxCode = X_GLXClientInfo; 1544 req->major = GLX_MAJOR_VERSION; 1545 req->minor = GLX_MINOR_VERSION; 1546 1547 req->length += (size + 3) >> 2; 1548 req->numbytes = size; 1549 Data(dpy, ext_str, size); 1550 1551 UnlockDisplay(dpy); 1552 SyncHandle(); 1553#endif /* USE_XCB */ 1554 1555 Xfree(ext_str); 1556} 1557 1558 1559/* 1560** EXT_import_context 1561*/ 1562 1563PUBLIC Display * 1564glXGetCurrentDisplay(void) 1565{ 1566 GLXContext gc = __glXGetCurrentContext(); 1567 if (NULL == gc) 1568 return NULL; 1569 return gc->currentDpy; 1570} 1571 1572PUBLIC 1573GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (), 1574 glXGetCurrentDisplay) 1575 1576/** 1577 * Used internally by libGL to send \c xGLXQueryContextinfoExtReq requests 1578 * to the X-server. 1579 * 1580 * \param dpy Display where \c ctx was created. 1581 * \param ctx Context to query. 1582 * \returns \c Success on success. \c GLX_BAD_CONTEXT if \c ctx is invalid, 1583 * or zero if the request failed due to internal problems (i.e., 1584 * unable to allocate temporary memory, etc.) 1585 * 1586 * \note 1587 * This function dynamically determines whether to use the EXT_import_context 1588 * version of the protocol or the GLX 1.3 version of the protocol. 1589 */ 1590static int __glXQueryContextInfo(Display * dpy, GLXContext ctx) 1591{ 1592 __GLXdisplayPrivate *priv = __glXInitialize(dpy); 1593 xGLXQueryContextReply reply; 1594 CARD8 opcode; 1595 GLuint numValues; 1596 int retval; 1597 1598 if (ctx == NULL) { 1599 return GLX_BAD_CONTEXT; 1600 } 1601 opcode = __glXSetupForCommand(dpy); 1602 if (!opcode) { 1603 return 0; 1604 } 1605 1606 /* Send the glXQueryContextInfoEXT request */ 1607 LockDisplay(dpy); 1608 1609 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { 1610 xGLXQueryContextReq *req; 1611 1612 GetReq(GLXQueryContext, req); 1613 1614 req->reqType = opcode; 1615 req->glxCode = X_GLXQueryContext; 1616 req->context = (unsigned int) (ctx->xid); 1617 } 1618 else { 1619 xGLXVendorPrivateReq *vpreq; 1620 xGLXQueryContextInfoEXTReq *req; 1621 1622 GetReqExtra(GLXVendorPrivate, 1623 sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq, 1624 vpreq); 1625 req = (xGLXQueryContextInfoEXTReq *) vpreq; 1626 req->reqType = opcode; 1627 req->glxCode = X_GLXVendorPrivateWithReply; 1628 req->vendorCode = X_GLXvop_QueryContextInfoEXT; 1629 req->context = (unsigned int) (ctx->xid); 1630 } 1631 1632 _XReply(dpy, (xReply *) & reply, 0, False); 1633 1634 numValues = reply.n; 1635 if (numValues == 0) 1636 retval = Success; 1637 else if (numValues > __GLX_MAX_CONTEXT_PROPS) 1638 retval = 0; 1639 else { 1640 int *propList, *pProp; 1641 int nPropListBytes; 1642 1643 nPropListBytes = numValues << 3; 1644 propList = (int *) Xmalloc(nPropListBytes); 1645 if (NULL == propList) { 1646 retval = 0; 1647 } 1648 else { 1649 unsigned i; 1650 1651 _XRead(dpy, (char *) propList, nPropListBytes); 1652 pProp = propList; 1653 for (i = 0; i < numValues; i++) { 1654 switch (*pProp++) { 1655 case GLX_SHARE_CONTEXT_EXT: 1656 ctx->share_xid = *pProp++; 1657 break; 1658 case GLX_VISUAL_ID_EXT: 1659 ctx->mode = 1660 _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++); 1661 break; 1662 case GLX_SCREEN: 1663 ctx->screen = *pProp++; 1664 break; 1665 case GLX_FBCONFIG_ID: 1666 ctx->mode = 1667 _gl_context_modes_find_fbconfig(ctx->psc->configs, 1668 *pProp++); 1669 break; 1670 case GLX_RENDER_TYPE: 1671 ctx->renderType = *pProp++; 1672 break; 1673 default: 1674 pProp++; 1675 continue; 1676 } 1677 } 1678 Xfree((char *) propList); 1679 retval = Success; 1680 } 1681 } 1682 UnlockDisplay(dpy); 1683 SyncHandle(); 1684 return retval; 1685} 1686 1687PUBLIC int 1688glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int *value) 1689{ 1690 int retVal; 1691 1692 /* get the information from the server if we don't have it already */ 1693#ifdef GLX_DIRECT_RENDERING 1694 if (!ctx->driContext && (ctx->mode == NULL)) { 1695#else 1696 if (ctx->mode == NULL) { 1697#endif 1698 retVal = __glXQueryContextInfo(dpy, ctx); 1699 if (Success != retVal) 1700 return retVal; 1701 } 1702 switch (attribute) { 1703 case GLX_SHARE_CONTEXT_EXT: 1704 *value = (int) (ctx->share_xid); 1705 break; 1706 case GLX_VISUAL_ID_EXT: 1707 *value = ctx->mode ? ctx->mode->visualID : None; 1708 break; 1709 case GLX_SCREEN: 1710 *value = (int) (ctx->screen); 1711 break; 1712 case GLX_FBCONFIG_ID: 1713 *value = ctx->mode ? ctx->mode->fbconfigID : None; 1714 break; 1715 case GLX_RENDER_TYPE: 1716 *value = (int) (ctx->renderType); 1717 break; 1718 default: 1719 return GLX_BAD_ATTRIBUTE; 1720 } 1721 return Success; 1722} 1723 1724PUBLIC 1725GLX_ALIAS(int, glXQueryContextInfoEXT, 1726 (Display * dpy, GLXContext ctx, int attribute, int *value), 1727 (dpy, ctx, attribute, value), glXQueryContext) 1728 1729PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx) 1730{ 1731 return ctx->xid; 1732} 1733 1734PUBLIC GLXContext 1735glXImportContextEXT(Display * dpy, GLXContextID contextID) 1736{ 1737 GLXContext ctx; 1738 1739 if (contextID == None) { 1740 return NULL; 1741 } 1742 if (__glXIsDirect(dpy, contextID)) { 1743 return NULL; 1744 } 1745 1746 ctx = AllocateGLXContext(dpy); 1747 if (NULL != ctx) { 1748 ctx->xid = contextID; 1749 ctx->imported = GL_TRUE; 1750 1751 if (Success != __glXQueryContextInfo(dpy, ctx)) { 1752 __glXFreeContext(ctx); 1753 ctx = NULL; 1754 } 1755 } 1756 return ctx; 1757} 1758 1759PUBLIC void 1760glXFreeContextEXT(Display * dpy, GLXContext ctx) 1761{ 1762 DestroyContext(dpy, ctx); 1763} 1764 1765 1766 1767/* 1768 * GLX 1.3 functions - these are just stubs for now! 1769 */ 1770 1771PUBLIC GLXFBConfig * 1772glXChooseFBConfig(Display * dpy, int screen, 1773 const int *attribList, int *nitems) 1774{ 1775 __GLcontextModes **config_list; 1776 int list_size; 1777 1778 1779 config_list = (__GLcontextModes **) 1780 glXGetFBConfigs(dpy, screen, &list_size); 1781 1782 if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) { 1783 list_size = choose_visual(config_list, list_size, attribList, GL_TRUE); 1784 if (list_size == 0) { 1785 XFree(config_list); 1786 config_list = NULL; 1787 } 1788 } 1789 1790 *nitems = list_size; 1791 return (GLXFBConfig *) config_list; 1792} 1793 1794 1795PUBLIC GLXContext 1796glXCreateNewContext(Display * dpy, GLXFBConfig config, 1797 int renderType, GLXContext shareList, Bool allowDirect) 1798{ 1799 const __GLcontextModes *const fbconfig = 1800 (const __GLcontextModes *const) config; 1801 1802 return CreateContext(dpy, fbconfig->fbconfigID, fbconfig, shareList, 1803 allowDirect, X_GLXCreateNewContext, renderType, 1804 fbconfig->screen); 1805} 1806 1807 1808PUBLIC GLXDrawable 1809glXGetCurrentReadDrawable(void) 1810{ 1811 GLXContext gc = __glXGetCurrentContext(); 1812 return gc->currentReadable; 1813} 1814 1815 1816PUBLIC GLXFBConfig * 1817glXGetFBConfigs(Display * dpy, int screen, int *nelements) 1818{ 1819 __GLXdisplayPrivate *priv = __glXInitialize(dpy); 1820 __GLcontextModes **config = NULL; 1821 int i; 1822 1823 *nelements = 0; 1824 if (priv && (priv->screenConfigs != NULL) 1825 && (screen >= 0) && (screen <= ScreenCount(dpy)) 1826 && (priv->screenConfigs[screen].configs != NULL) 1827 && (priv->screenConfigs[screen].configs->fbconfigID 1828 != (int) GLX_DONT_CARE)) { 1829 unsigned num_configs = 0; 1830 __GLcontextModes *modes; 1831 1832 1833 for (modes = priv->screenConfigs[screen].configs; modes != NULL; 1834 modes = modes->next) { 1835 if (modes->fbconfigID != (int) GLX_DONT_CARE) { 1836 num_configs++; 1837 } 1838 } 1839 1840 config = (__GLcontextModes **) Xmalloc(sizeof(__GLcontextModes *) 1841 * num_configs); 1842 if (config != NULL) { 1843 *nelements = num_configs; 1844 i = 0; 1845 for (modes = priv->screenConfigs[screen].configs; modes != NULL; 1846 modes = modes->next) { 1847 if (modes->fbconfigID != (int) GLX_DONT_CARE) { 1848 config[i] = modes; 1849 i++; 1850 } 1851 } 1852 } 1853 } 1854 return (GLXFBConfig *) config; 1855} 1856 1857 1858PUBLIC int 1859glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config, 1860 int attribute, int *value) 1861{ 1862 __GLcontextModes *const modes = ValidateGLXFBConfig(dpy, config); 1863 1864 return (modes != NULL) 1865 ? _gl_get_context_mode_data(modes, attribute, value) 1866 : GLXBadFBConfig; 1867} 1868 1869 1870PUBLIC XVisualInfo * 1871glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config) 1872{ 1873 XVisualInfo visualTemplate; 1874 __GLcontextModes *fbconfig = (__GLcontextModes *) config; 1875 int count; 1876 1877 /* 1878 ** Get a list of all visuals, return if list is empty 1879 */ 1880 visualTemplate.visualid = fbconfig->visualID; 1881 return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count); 1882} 1883 1884 1885/* 1886** GLX_SGI_swap_control 1887*/ 1888static int 1889__glXSwapIntervalSGI(int interval) 1890{ 1891 xGLXVendorPrivateReq *req; 1892 GLXContext gc = __glXGetCurrentContext(); 1893 __GLXscreenConfigs *psc; 1894 Display *dpy; 1895 CARD32 *interval_ptr; 1896 CARD8 opcode; 1897 1898 if (gc == NULL) { 1899 return GLX_BAD_CONTEXT; 1900 } 1901 1902 if (interval <= 0) { 1903 return GLX_BAD_VALUE; 1904 } 1905 1906#ifdef __DRI_SWAP_CONTROL 1907 if (gc->driContext) { 1908 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, 1909 gc->screen ); 1910 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 1911 gc->currentDrawable, 1912 NULL); 1913 if (psc->swapControl != NULL && pdraw != NULL) { 1914 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); 1915 return 0; 1916 } 1917 else if (pdraw == NULL) { 1918 return GLX_BAD_CONTEXT; 1919 } 1920 } 1921#endif 1922 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1923 1924#ifdef GLX_DIRECT_RENDERING 1925 if (gc->driContext && psc->driScreen && psc->driScreen->setSwapInterval) { 1926 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 1927 gc->currentDrawable, 1928 NULL); 1929 psc->driScreen->setSwapInterval(pdraw, interval); 1930 return 0; 1931 } 1932#endif 1933 1934 dpy = gc->currentDpy; 1935 opcode = __glXSetupForCommand(dpy); 1936 if (!opcode) { 1937 return 0; 1938 } 1939 1940 /* Send the glXSwapIntervalSGI request */ 1941 LockDisplay(dpy); 1942 GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req); 1943 req->reqType = opcode; 1944 req->glxCode = X_GLXVendorPrivate; 1945 req->vendorCode = X_GLXvop_SwapIntervalSGI; 1946 req->contextTag = gc->currentContextTag; 1947 1948 interval_ptr = (CARD32 *) (req + 1); 1949 *interval_ptr = interval; 1950 1951 UnlockDisplay(dpy); 1952 SyncHandle(); 1953 XFlush(dpy); 1954 1955 return 0; 1956} 1957 1958 1959/* 1960** GLX_MESA_swap_control 1961*/ 1962static int 1963__glXSwapIntervalMESA(unsigned int interval) 1964{ 1965 GLXContext gc = __glXGetCurrentContext(); 1966 1967#ifdef __DRI_SWAP_CONTROL 1968 if (gc != NULL && gc->driContext) { 1969 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, 1970 gc->screen); 1971 1972 if ((psc != NULL) && (psc->driScreen != NULL)) { 1973 __GLXDRIdrawable *pdraw = 1974 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 1975 if (psc->swapControl != NULL && pdraw != NULL) { 1976 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); 1977 return 0; 1978 } 1979 } 1980 } 1981#endif 1982 1983#ifdef GLX_DIRECT_RENDERING 1984 if (gc != NULL && gc->driContext) { 1985 __GLXscreenConfigs *psc; 1986 1987 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1988 if (psc->driScreen && psc->driScreen->setSwapInterval) { 1989 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 1990 gc->currentDrawable, NULL); 1991 psc->driScreen->setSwapInterval(pdraw, interval); 1992 return 0; 1993 } 1994 } 1995#endif 1996 1997 return GLX_BAD_CONTEXT; 1998} 1999 2000 2001static int 2002__glXGetSwapIntervalMESA(void) 2003{ 2004#ifdef __DRI_SWAP_CONTROL 2005 GLXContext gc = __glXGetCurrentContext(); 2006 2007 if (gc != NULL && gc->driContext) { 2008 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, 2009 gc->screen); 2010 2011 if ((psc != NULL) && (psc->driScreen != NULL)) { 2012 __GLXDRIdrawable *pdraw = 2013 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2014 if (psc->swapControl != NULL && pdraw != NULL) { 2015 return psc->swapControl->getSwapInterval(pdraw->driDrawable); 2016 } 2017 } 2018 } 2019#endif 2020 2021#ifdef GLX_DIRECT_RENDERING 2022 if (gc != NULL && gc->driContext) { 2023 __GLXscreenConfigs *psc; 2024 2025 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 2026 if (psc->driScreen && psc->driScreen->getSwapInterval) { 2027 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 2028 gc->currentDrawable, NULL); 2029 return psc->driScreen->getSwapInterval(pdraw); 2030 } 2031 } 2032#endif 2033 2034 return 0; 2035} 2036 2037 2038/* 2039** GLX_MESA_swap_frame_usage 2040*/ 2041 2042static GLint 2043__glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable) 2044{ 2045 int status = GLX_BAD_CONTEXT; 2046#ifdef __DRI_FRAME_TRACKING 2047 int screen = 0; 2048 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2049 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2050 2051 if (pdraw != NULL && psc->frameTracking != NULL) 2052 status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE); 2053#else 2054 (void) dpy; 2055 (void) drawable; 2056#endif 2057 return status; 2058} 2059 2060 2061static GLint 2062__glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable) 2063{ 2064 int status = GLX_BAD_CONTEXT; 2065#ifdef __DRI_FRAME_TRACKING 2066 int screen = 0; 2067 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2068 __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen); 2069 2070 if (pdraw != NULL && psc->frameTracking != NULL) 2071 status = psc->frameTracking->frameTracking(pdraw->driDrawable, 2072 GL_FALSE); 2073#else 2074 (void) dpy; 2075 (void) drawable; 2076#endif 2077 return status; 2078} 2079 2080 2081static GLint 2082__glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage) 2083{ 2084 int status = GLX_BAD_CONTEXT; 2085#ifdef __DRI_FRAME_TRACKING 2086 int screen = 0; 2087 __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2088 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2089 2090 if (pdraw != NULL && psc->frameTracking != NULL) { 2091 int64_t sbc, missedFrames; 2092 float lastMissedUsage; 2093 2094 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, 2095 &sbc, 2096 &missedFrames, 2097 &lastMissedUsage, 2098 usage); 2099 } 2100#else 2101 (void) dpy; 2102 (void) drawable; 2103 (void) usage; 2104#endif 2105 return status; 2106} 2107 2108 2109static GLint 2110__glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable, 2111 int64_t * sbc, int64_t * missedFrames, 2112 GLfloat * lastMissedUsage) 2113{ 2114 int status = GLX_BAD_CONTEXT; 2115#ifdef __DRI_FRAME_TRACKING 2116 int screen = 0; 2117 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2118 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2119 2120 if (pdraw != NULL && psc->frameTracking != NULL) { 2121 float usage; 2122 2123 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, 2124 sbc, missedFrames, 2125 lastMissedUsage, 2126 &usage); 2127 } 2128#else 2129 (void) dpy; 2130 (void) drawable; 2131 (void) sbc; 2132 (void) missedFrames; 2133 (void) lastMissedUsage; 2134#endif 2135 return status; 2136} 2137 2138 2139/* 2140** GLX_SGI_video_sync 2141*/ 2142static int 2143__glXGetVideoSyncSGI(unsigned int *count) 2144{ 2145 int64_t ust, msc, sbc; 2146 int ret; 2147 GLXContext gc = __glXGetCurrentContext(); 2148 __GLXscreenConfigs *psc; 2149#ifdef GLX_DIRECT_RENDERING 2150 __GLXDRIdrawable *pdraw; 2151#endif 2152 2153 if (!gc) 2154 return GLX_BAD_CONTEXT; 2155 2156#ifdef GLX_DIRECT_RENDERING 2157 if (!gc->driContext) 2158 return GLX_BAD_CONTEXT; 2159#endif 2160 2161 psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen); 2162#ifdef GLX_DIRECT_RENDERING 2163 pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2164#endif 2165 2166 /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry, 2167 * FIXME: there should be a GLX encoding for this call. I can find no 2168 * FIXME: documentation for the GLX encoding. 2169 */ 2170#ifdef __DRI_MEDIA_STREAM_COUNTER 2171 if ( psc->msc && psc->driScreen ) { 2172 ret = (*psc->msc->getDrawableMSC)(psc->__driScreen, 2173 pdraw->driDrawable, &msc); 2174 *count = (unsigned) msc; 2175 2176 return (ret == 0) ? 0 : GLX_BAD_CONTEXT; 2177 } 2178#endif 2179 2180#ifdef GLX_DIRECT_RENDERING 2181 if (psc->driScreen && psc->driScreen->getDrawableMSC) { 2182 ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc); 2183 *count = (unsigned) msc; 2184 return (ret == True) ? 0 : GLX_BAD_CONTEXT; 2185 } 2186#endif 2187 2188 return GLX_BAD_CONTEXT; 2189} 2190 2191static int 2192__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) 2193{ 2194 GLXContext gc = __glXGetCurrentContext(); 2195 __GLXscreenConfigs *psc; 2196#ifdef GLX_DIRECT_RENDERING 2197 __GLXDRIdrawable *pdraw; 2198#endif 2199 int64_t ust, msc, sbc; 2200 int ret; 2201 2202 if (divisor <= 0 || remainder < 0) 2203 return GLX_BAD_VALUE; 2204 2205 if (!gc) 2206 return GLX_BAD_CONTEXT; 2207 2208#ifdef GLX_DIRECT_RENDERING 2209 if (!gc->driContext) 2210 return GLX_BAD_CONTEXT; 2211#endif 2212 2213 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 2214#ifdef GLX_DIRECT_RENDERING 2215 pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2216#endif 2217 2218#ifdef __DRI_MEDIA_STREAM_COUNTER 2219 if (psc->msc != NULL && psc->driScreen ) { 2220 ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0, 2221 divisor, remainder, &msc, &sbc); 2222 *count = (unsigned) msc; 2223 return (ret == 0) ? 0 : GLX_BAD_CONTEXT; 2224 } 2225#endif 2226 2227#ifdef GLX_DIRECT_RENDERING 2228 if (psc->driScreen && psc->driScreen->waitForMSC) { 2229 ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc, 2230 &sbc); 2231 *count = (unsigned) msc; 2232 return (ret == True) ? 0 : GLX_BAD_CONTEXT; 2233 } 2234#endif 2235 2236 return GLX_BAD_CONTEXT; 2237} 2238 2239 2240/* 2241** GLX_SGIX_fbconfig 2242** Many of these functions are aliased to GLX 1.3 entry points in the 2243** GLX_functions table. 2244*/ 2245 2246PUBLIC 2247GLX_ALIAS(int, glXGetFBConfigAttribSGIX, 2248 (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value), 2249 (dpy, config, attribute, value), glXGetFBConfigAttrib) 2250 2251PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX, 2252 (Display * dpy, int screen, int *attrib_list, 2253 int *nelements), (dpy, screen, attrib_list, nelements), 2254 glXChooseFBConfig) 2255 2256PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX, 2257 (Display * dpy, GLXFBConfigSGIX config), 2258 (dpy, config), glXGetVisualFromFBConfig) 2259 2260PUBLIC GLXPixmap 2261glXCreateGLXPixmapWithConfigSGIX(Display * dpy, 2262 GLXFBConfigSGIX config, 2263 Pixmap pixmap) 2264{ 2265 xGLXVendorPrivateWithReplyReq *vpreq; 2266 xGLXCreateGLXPixmapWithConfigSGIXReq *req; 2267 GLXPixmap xid = None; 2268 CARD8 opcode; 2269 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config; 2270 __GLXscreenConfigs *psc; 2271 2272 2273 if ((dpy == NULL) || (config == NULL)) { 2274 return None; 2275 } 2276 2277 psc = GetGLXScreenConfigs(dpy, fbconfig->screen); 2278 if ((psc != NULL) 2279 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 2280 opcode = __glXSetupForCommand(dpy); 2281 if (!opcode) { 2282 return None; 2283 } 2284 2285 /* Send the glXCreateGLXPixmapWithConfigSGIX request */ 2286 LockDisplay(dpy); 2287 GetReqExtra(GLXVendorPrivateWithReply, 2288 sz_xGLXCreateGLXPixmapWithConfigSGIXReq - 2289 sz_xGLXVendorPrivateWithReplyReq, vpreq); 2290 req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq; 2291 req->reqType = opcode; 2292 req->glxCode = X_GLXVendorPrivateWithReply; 2293 req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; 2294 req->screen = fbconfig->screen; 2295 req->fbconfig = fbconfig->fbconfigID; 2296 req->pixmap = pixmap; 2297 req->glxpixmap = xid = XAllocID(dpy); 2298 UnlockDisplay(dpy); 2299 SyncHandle(); 2300 } 2301 2302 return xid; 2303} 2304 2305PUBLIC GLXContext 2306glXCreateContextWithConfigSGIX(Display * dpy, 2307 GLXFBConfigSGIX config, int renderType, 2308 GLXContext shareList, Bool allowDirect) 2309{ 2310 GLXContext gc = NULL; 2311 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config; 2312 __GLXscreenConfigs *psc; 2313 2314 2315 if ((dpy == NULL) || (config == NULL)) { 2316 return None; 2317 } 2318 2319 psc = GetGLXScreenConfigs(dpy, fbconfig->screen); 2320 if ((psc != NULL) 2321 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 2322 gc = CreateContext(dpy, fbconfig->fbconfigID, fbconfig, shareList, 2323 allowDirect, 2324 X_GLXvop_CreateContextWithConfigSGIX, renderType, 2325 fbconfig->screen); 2326 } 2327 2328 return gc; 2329} 2330 2331 2332PUBLIC GLXFBConfigSGIX 2333glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis) 2334{ 2335 __GLXdisplayPrivate *priv; 2336 __GLXscreenConfigs *psc = NULL; 2337 2338 if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success) 2339 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit) 2340 && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) { 2341 return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs, 2342 vis->visualid); 2343 } 2344 2345 return NULL; 2346} 2347 2348 2349/* 2350** GLX_SGIX_swap_group 2351*/ 2352static void 2353__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable, 2354 GLXDrawable member) 2355{ 2356 (void) dpy; 2357 (void) drawable; 2358 (void) member; 2359} 2360 2361 2362/* 2363** GLX_SGIX_swap_barrier 2364*/ 2365static void 2366__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier) 2367{ 2368 (void) dpy; 2369 (void) drawable; 2370 (void) barrier; 2371} 2372 2373static Bool 2374__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max) 2375{ 2376 (void) dpy; 2377 (void) screen; 2378 (void) max; 2379 return False; 2380} 2381 2382 2383/* 2384** GLX_OML_sync_control 2385*/ 2386static Bool 2387__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable, 2388 int64_t * ust, int64_t * msc, int64_t * sbc) 2389{ 2390 __GLXdisplayPrivate * const priv = __glXInitialize(dpy); 2391 int i, ret; 2392#ifdef GLX_DIRECT_RENDERING 2393 __GLXDRIdrawable *pdraw; 2394#endif 2395 __GLXscreenConfigs *psc; 2396 2397 if (!priv) 2398 return False; 2399 2400#ifdef GLX_DIRECT_RENDERING 2401 pdraw = GetGLXDRIDrawable(dpy, drawable, &i); 2402#endif 2403 psc = &priv->screenConfigs[i]; 2404 2405#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER) 2406 if (pdraw && psc->sbc && psc->msc) 2407 return ( (pdraw && psc->sbc && psc->msc) 2408 && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0) 2409 && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0) 2410 && (__glXGetUST(ust) == 0) ); 2411#endif 2412 2413#ifdef GLX_DIRECT_RENDERING 2414 if (pdraw && psc && psc->driScreen && psc->driScreen->getDrawableMSC) { 2415 ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc); 2416 return ret; 2417 } 2418#endif 2419 2420 return False; 2421} 2422 2423#ifdef GLX_DIRECT_RENDERING 2424_X_HIDDEN GLboolean 2425__driGetMscRateOML(__DRIdrawable * draw, 2426 int32_t * numerator, int32_t * denominator, void *private) 2427{ 2428#ifdef XF86VIDMODE 2429 __GLXscreenConfigs *psc; 2430 XF86VidModeModeLine mode_line; 2431 int dot_clock; 2432 int i; 2433 __GLXDRIdrawable *glxDraw = private; 2434 2435 (void) draw; 2436 2437 psc = glxDraw->psc; 2438 if (XF86VidModeQueryVersion(psc->dpy, &i, &i) && 2439 XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) { 2440 unsigned n = dot_clock * 1000; 2441 unsigned d = mode_line.vtotal * mode_line.htotal; 2442 2443# define V_INTERLACE 0x010 2444# define V_DBLSCAN 0x020 2445 2446 if (mode_line.flags & V_INTERLACE) 2447 n *= 2; 2448 else if (mode_line.flags & V_DBLSCAN) 2449 d *= 2; 2450 2451 /* The OML_sync_control spec requires that if the refresh rate is a 2452 * whole number, that the returned numerator be equal to the refresh 2453 * rate and the denominator be 1. 2454 */ 2455 2456 if (n % d == 0) { 2457 n /= d; 2458 d = 1; 2459 } 2460 else { 2461 static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 }; 2462 2463 /* This is a poor man's way to reduce a fraction. It's far from 2464 * perfect, but it will work well enough for this situation. 2465 */ 2466 2467 for (i = 0; f[i] != 0; i++) { 2468 while (n % f[i] == 0 && d % f[i] == 0) { 2469 d /= f[i]; 2470 n /= f[i]; 2471 } 2472 } 2473 } 2474 2475 *numerator = n; 2476 *denominator = d; 2477 2478 return True; 2479 } 2480 else 2481 return False; 2482#else 2483 (void) draw; 2484 (void) numerator; 2485 (void) denominator; 2486 (void) private; 2487 2488 return False; 2489#endif 2490} 2491#endif 2492 2493/** 2494 * Determine the refresh rate of the specified drawable and display. 2495 * 2496 * \param dpy Display whose refresh rate is to be determined. 2497 * \param drawable Drawable whose refresh rate is to be determined. 2498 * \param numerator Numerator of the refresh rate. 2499 * \param demoninator Denominator of the refresh rate. 2500 * \return If the refresh rate for the specified display and drawable could 2501 * be calculated, True is returned. Otherwise False is returned. 2502 * 2503 * \note This function is implemented entirely client-side. A lot of other 2504 * functionality is required to export GLX_OML_sync_control, so on 2505 * XFree86 this function can be called for direct-rendering contexts 2506 * when GLX_OML_sync_control appears in the client extension string. 2507 */ 2508 2509_X_HIDDEN GLboolean 2510__glXGetMscRateOML(Display * dpy, GLXDrawable drawable, 2511 int32_t * numerator, int32_t * denominator) 2512{ 2513#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE ) 2514 __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL); 2515 2516 if (draw == NULL) 2517 return False; 2518 2519 return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw); 2520#else 2521 (void) dpy; 2522 (void) drawable; 2523 (void) numerator; 2524 (void) denominator; 2525#endif 2526 return False; 2527} 2528 2529 2530static int64_t 2531__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, 2532 int64_t target_msc, int64_t divisor, int64_t remainder) 2533{ 2534 GLXContext gc = __glXGetCurrentContext(); 2535 int screen; 2536#ifdef GLX_DIRECT_RENDERING 2537 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2538#endif 2539 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2540 2541 if (!gc) /* no GLX for this */ 2542 return -1; 2543 2544#ifdef GLX_DIRECT_RENDERING 2545 if (!pdraw || !gc->driContext) 2546 return -1; 2547#endif 2548 2549 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2550 * error", but it also says "It [glXSwapBuffersMscOML] will return a value 2551 * of -1 if the function failed because of errors detected in the input 2552 * parameters" 2553 */ 2554 if (divisor < 0 || remainder < 0 || target_msc < 0) 2555 return -1; 2556 if (divisor > 0 && remainder >= divisor) 2557 return -1; 2558 2559 if (target_msc == 0 && divisor == 0 && remainder == 0) 2560 remainder = 1; 2561 2562#ifdef __DRI_SWAP_BUFFER_COUNTER 2563 if (psc->counters != NULL) 2564 return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc, 2565 divisor, remainder); 2566#endif 2567 2568#ifdef GLX_DIRECT_RENDERING 2569 if (psc->driScreen && psc->driScreen->swapBuffers) 2570 return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor, 2571 remainder); 2572#endif 2573 2574 return -1; 2575} 2576 2577 2578static Bool 2579__glXWaitForMscOML(Display * dpy, GLXDrawable drawable, 2580 int64_t target_msc, int64_t divisor, 2581 int64_t remainder, int64_t * ust, 2582 int64_t * msc, int64_t * sbc) 2583{ 2584 int screen; 2585#ifdef GLX_DIRECT_RENDERING 2586 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2587#endif 2588 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); 2589 int ret; 2590 2591 2592 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2593 * error", but the return type in the spec is Bool. 2594 */ 2595 if (divisor < 0 || remainder < 0 || target_msc < 0) 2596 return False; 2597 if (divisor > 0 && remainder >= divisor) 2598 return False; 2599 2600#ifdef __DRI_MEDIA_STREAM_COUNTER 2601 if (pdraw != NULL && psc->msc != NULL) { 2602 ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc, 2603 divisor, remainder, msc, sbc); 2604 2605 /* __glXGetUST returns zero on success and non-zero on failure. 2606 * This function returns True on success and False on failure. 2607 */ 2608 return ((ret == 0) && (__glXGetUST(ust) == 0)); 2609 } 2610#endif 2611 2612#ifdef GLX_DIRECT_RENDERING 2613 if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) { 2614 ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder, 2615 ust, msc, sbc); 2616 return ret; 2617 } 2618#endif 2619 2620 return False; 2621} 2622 2623 2624static Bool 2625__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, 2626 int64_t target_sbc, int64_t * ust, 2627 int64_t * msc, int64_t * sbc) 2628{ 2629 int screen; 2630#ifdef GLX_DIRECT_RENDERING 2631 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2632#endif 2633 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2634 int ret; 2635 2636 /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE 2637 * error", but the return type in the spec is Bool. 2638 */ 2639 if (target_sbc < 0) 2640 return False; 2641#ifdef __DRI_SWAP_BUFFER_COUNTER 2642 if (pdraw != NULL && psc->sbc != NULL) { 2643 ret = 2644 (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc); 2645 2646 /* __glXGetUST returns zero on success and non-zero on failure. 2647 * This function returns True on success and False on failure. 2648 */ 2649 return ((ret == 0) && (__glXGetUST(ust) == 0)); 2650 } 2651#endif 2652 2653#ifdef GLX_DIRECT_RENDERING 2654 if (pdraw && psc->driScreen && psc->driScreen->waitForSBC) { 2655 ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc); 2656 return ret; 2657 } 2658#endif 2659 2660 return False; 2661} 2662 2663 2664/** 2665 * GLX_MESA_allocate_memory 2666 */ 2667/*@{*/ 2668 2669PUBLIC void * 2670glXAllocateMemoryMESA(Display * dpy, int scrn, 2671 size_t size, float readFreq, 2672 float writeFreq, float priority) 2673{ 2674#ifdef __DRI_ALLOCATE 2675 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2676 2677 if (psc && psc->allocate) 2678 return (*psc->allocate->allocateMemory) (psc->__driScreen, size, 2679 readFreq, writeFreq, priority); 2680 2681#else 2682 (void) dpy; 2683 (void) scrn; 2684 (void) size; 2685 (void) readFreq; 2686 (void) writeFreq; 2687 (void) priority; 2688#endif /* __DRI_ALLOCATE */ 2689 2690 return NULL; 2691} 2692 2693 2694PUBLIC void 2695glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer) 2696{ 2697#ifdef __DRI_ALLOCATE 2698 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2699 2700 if (psc && psc->allocate) 2701 (*psc->allocate->freeMemory) (psc->__driScreen, pointer); 2702 2703#else 2704 (void) dpy; 2705 (void) scrn; 2706 (void) pointer; 2707#endif /* __DRI_ALLOCATE */ 2708} 2709 2710 2711PUBLIC GLuint 2712glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer) 2713{ 2714#ifdef __DRI_ALLOCATE 2715 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2716 2717 if (psc && psc->allocate) 2718 return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer); 2719 2720#else 2721 (void) dpy; 2722 (void) scrn; 2723 (void) pointer; 2724#endif /* GLX_DIRECT_RENDERING */ 2725 2726 return ~0L; 2727} 2728 2729/*@}*/ 2730 2731 2732/** 2733 * Mesa extension stubs. These will help reduce portability problems. 2734 */ 2735/*@{*/ 2736 2737/** 2738 * Release all buffers associated with the specified GLX drawable. 2739 * 2740 * \todo 2741 * This function was intended for stand-alone Mesa. The issue there is that 2742 * the library doesn't get any notification when a window is closed. In 2743 * DRI there is a similar but slightly different issue. When GLX 1.3 is 2744 * supported, there are 3 different functions to destroy a drawable. It 2745 * should be possible to create GLX protocol (or have it determine which 2746 * protocol to use based on the type of the drawable) to have one function 2747 * do the work of 3. For the direct-rendering case, this function could 2748 * just call the driver's \c __DRIdrawableRec::destroyDrawable function. 2749 * This would reduce the frequency with which \c __driGarbageCollectDrawables 2750 * would need to be used. This really should be done as part of the new DRI 2751 * interface work. 2752 * 2753 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt 2754 * __driGarbageCollectDrawables 2755 * glXDestroyGLXPixmap 2756 * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow 2757 * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX 2758 */ 2759static Bool 2760__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d) 2761{ 2762 (void) dpy; 2763 (void) d; 2764 return False; 2765} 2766 2767 2768PUBLIC GLXPixmap 2769glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual, 2770 Pixmap pixmap, Colormap cmap) 2771{ 2772 (void) dpy; 2773 (void) visual; 2774 (void) pixmap; 2775 (void) cmap; 2776 return 0; 2777} 2778 2779/*@}*/ 2780 2781 2782/** 2783 * GLX_MESA_copy_sub_buffer 2784 */ 2785#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */ 2786static void 2787__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable, 2788 int x, int y, int width, int height) 2789{ 2790 xGLXVendorPrivateReq *req; 2791 GLXContext gc; 2792 GLXContextTag tag; 2793 CARD32 *drawable_ptr; 2794 INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr; 2795 CARD8 opcode; 2796 2797#ifdef __DRI_COPY_SUB_BUFFER 2798 int screen; 2799 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2800 if (pdraw != NULL) { 2801 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2802 if (psc->driScreen->copySubBuffer != NULL) { 2803 glFlush(); 2804 (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height); 2805 } 2806 2807 return; 2808 } 2809#endif 2810 2811 opcode = __glXSetupForCommand(dpy); 2812 if (!opcode) 2813 return; 2814 2815 /* 2816 ** The calling thread may or may not have a current context. If it 2817 ** does, send the context tag so the server can do a flush. 2818 */ 2819 gc = __glXGetCurrentContext(); 2820 if ((gc != NULL) && (dpy == gc->currentDpy) && 2821 ((drawable == gc->currentDrawable) || 2822 (drawable == gc->currentReadable))) { 2823 tag = gc->currentContextTag; 2824 } 2825 else { 2826 tag = 0; 2827 } 2828 2829 LockDisplay(dpy); 2830 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req); 2831 req->reqType = opcode; 2832 req->glxCode = X_GLXVendorPrivate; 2833 req->vendorCode = X_GLXvop_CopySubBufferMESA; 2834 req->contextTag = tag; 2835 2836 drawable_ptr = (CARD32 *) (req + 1); 2837 x_ptr = (INT32 *) (drawable_ptr + 1); 2838 y_ptr = (INT32 *) (drawable_ptr + 2); 2839 w_ptr = (INT32 *) (drawable_ptr + 3); 2840 h_ptr = (INT32 *) (drawable_ptr + 4); 2841 2842 *drawable_ptr = drawable; 2843 *x_ptr = x; 2844 *y_ptr = y; 2845 *w_ptr = width; 2846 *h_ptr = height; 2847 2848 UnlockDisplay(dpy); 2849 SyncHandle(); 2850} 2851 2852 2853/** 2854 * GLX_EXT_texture_from_pixmap 2855 */ 2856/*@{*/ 2857static void 2858__glXBindTexImageEXT(Display * dpy, 2859 GLXDrawable drawable, int buffer, const int *attrib_list) 2860{ 2861 xGLXVendorPrivateReq *req; 2862 GLXContext gc = __glXGetCurrentContext(); 2863 CARD32 *drawable_ptr; 2864 INT32 *buffer_ptr; 2865 CARD32 *num_attrib_ptr; 2866 CARD32 *attrib_ptr; 2867 CARD8 opcode; 2868 unsigned int i; 2869 2870 if (gc == NULL) 2871 return; 2872 2873 i = 0; 2874 if (attrib_list) { 2875 while (attrib_list[i * 2] != None) 2876 i++; 2877 } 2878 2879#ifdef GLX_DIRECT_RENDERING 2880 if (gc->driContext) { 2881 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); 2882 2883 if (pdraw != NULL) { 2884 if (pdraw->psc->texBuffer->base.version >= 2 && 2885 pdraw->psc->texBuffer->setTexBuffer2 != NULL) { 2886 (*pdraw->psc->texBuffer->setTexBuffer2) (gc->__driContext, 2887 pdraw->textureTarget, 2888 pdraw->textureFormat, 2889 pdraw->driDrawable); 2890 } 2891 else { 2892 (*pdraw->psc->texBuffer->setTexBuffer) (gc->__driContext, 2893 pdraw->textureTarget, 2894 pdraw->driDrawable); 2895 } 2896 } 2897 return; 2898 } 2899#endif 2900 2901 opcode = __glXSetupForCommand(dpy); 2902 if (!opcode) 2903 return; 2904 2905 LockDisplay(dpy); 2906 GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req); 2907 req->reqType = opcode; 2908 req->glxCode = X_GLXVendorPrivate; 2909 req->vendorCode = X_GLXvop_BindTexImageEXT; 2910 req->contextTag = gc->currentContextTag; 2911 2912 drawable_ptr = (CARD32 *) (req + 1); 2913 buffer_ptr = (INT32 *) (drawable_ptr + 1); 2914 num_attrib_ptr = (CARD32 *) (buffer_ptr + 1); 2915 attrib_ptr = (CARD32 *) (num_attrib_ptr + 1); 2916 2917 *drawable_ptr = drawable; 2918 *buffer_ptr = buffer; 2919 *num_attrib_ptr = (CARD32) i; 2920 2921 i = 0; 2922 if (attrib_list) { 2923 while (attrib_list[i * 2] != None) { 2924 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0]; 2925 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1]; 2926 i++; 2927 } 2928 } 2929 2930 UnlockDisplay(dpy); 2931 SyncHandle(); 2932} 2933 2934static void 2935__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer) 2936{ 2937 xGLXVendorPrivateReq *req; 2938 GLXContext gc = __glXGetCurrentContext(); 2939 CARD32 *drawable_ptr; 2940 INT32 *buffer_ptr; 2941 CARD8 opcode; 2942 2943 if ((gc == NULL) || GC_IS_DIRECT(gc)) 2944 return; 2945 2946 opcode = __glXSetupForCommand(dpy); 2947 if (!opcode) 2948 return; 2949 2950 LockDisplay(dpy); 2951 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req); 2952 req->reqType = opcode; 2953 req->glxCode = X_GLXVendorPrivate; 2954 req->vendorCode = X_GLXvop_ReleaseTexImageEXT; 2955 req->contextTag = gc->currentContextTag; 2956 2957 drawable_ptr = (CARD32 *) (req + 1); 2958 buffer_ptr = (INT32 *) (drawable_ptr + 1); 2959 2960 *drawable_ptr = drawable; 2961 *buffer_ptr = buffer; 2962 2963 UnlockDisplay(dpy); 2964 SyncHandle(); 2965} 2966 2967/*@}*/ 2968 2969/** 2970 * \c strdup is actually not a standard ANSI C or POSIX routine. 2971 * Irix will not define it if ANSI mode is in effect. 2972 * 2973 * \sa strdup 2974 */ 2975_X_HIDDEN char * 2976__glXstrdup(const char *str) 2977{ 2978 char *copy; 2979 copy = (char *) Xmalloc(strlen(str) + 1); 2980 if (!copy) 2981 return NULL; 2982 strcpy(copy, str); 2983 return copy; 2984} 2985 2986/* 2987** glXGetProcAddress support 2988*/ 2989 2990struct name_address_pair 2991{ 2992 const char *Name; 2993 GLvoid *Address; 2994}; 2995 2996#define GLX_FUNCTION(f) { # f, (GLvoid *) f } 2997#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f } 2998 2999static const struct name_address_pair GLX_functions[] = { 3000 /*** GLX_VERSION_1_0 ***/ 3001 GLX_FUNCTION(glXChooseVisual), 3002 GLX_FUNCTION(glXCopyContext), 3003 GLX_FUNCTION(glXCreateContext), 3004 GLX_FUNCTION(glXCreateGLXPixmap), 3005 GLX_FUNCTION(glXDestroyContext), 3006 GLX_FUNCTION(glXDestroyGLXPixmap), 3007 GLX_FUNCTION(glXGetConfig), 3008 GLX_FUNCTION(glXGetCurrentContext), 3009 GLX_FUNCTION(glXGetCurrentDrawable), 3010 GLX_FUNCTION(glXIsDirect), 3011 GLX_FUNCTION(glXMakeCurrent), 3012 GLX_FUNCTION(glXQueryExtension), 3013 GLX_FUNCTION(glXQueryVersion), 3014 GLX_FUNCTION(glXSwapBuffers), 3015 GLX_FUNCTION(glXUseXFont), 3016 GLX_FUNCTION(glXWaitGL), 3017 GLX_FUNCTION(glXWaitX), 3018 3019 /*** GLX_VERSION_1_1 ***/ 3020 GLX_FUNCTION(glXGetClientString), 3021 GLX_FUNCTION(glXQueryExtensionsString), 3022 GLX_FUNCTION(glXQueryServerString), 3023 3024 /*** GLX_VERSION_1_2 ***/ 3025 GLX_FUNCTION(glXGetCurrentDisplay), 3026 3027 /*** GLX_VERSION_1_3 ***/ 3028 GLX_FUNCTION(glXChooseFBConfig), 3029 GLX_FUNCTION(glXCreateNewContext), 3030 GLX_FUNCTION(glXCreatePbuffer), 3031 GLX_FUNCTION(glXCreatePixmap), 3032 GLX_FUNCTION(glXCreateWindow), 3033 GLX_FUNCTION(glXDestroyPbuffer), 3034 GLX_FUNCTION(glXDestroyPixmap), 3035 GLX_FUNCTION(glXDestroyWindow), 3036 GLX_FUNCTION(glXGetCurrentReadDrawable), 3037 GLX_FUNCTION(glXGetFBConfigAttrib), 3038 GLX_FUNCTION(glXGetFBConfigs), 3039 GLX_FUNCTION(glXGetSelectedEvent), 3040 GLX_FUNCTION(glXGetVisualFromFBConfig), 3041 GLX_FUNCTION(glXMakeContextCurrent), 3042 GLX_FUNCTION(glXQueryContext), 3043 GLX_FUNCTION(glXQueryDrawable), 3044 GLX_FUNCTION(glXSelectEvent), 3045 3046 /*** GLX_SGI_swap_control ***/ 3047 GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI), 3048 3049 /*** GLX_SGI_video_sync ***/ 3050 GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI), 3051 GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI), 3052 3053 /*** GLX_SGI_make_current_read ***/ 3054 GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent), 3055 GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable), 3056 3057 /*** GLX_EXT_import_context ***/ 3058 GLX_FUNCTION(glXFreeContextEXT), 3059 GLX_FUNCTION(glXGetContextIDEXT), 3060 GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay), 3061 GLX_FUNCTION(glXImportContextEXT), 3062 GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext), 3063 3064 /*** GLX_SGIX_fbconfig ***/ 3065 GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib), 3066 GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig), 3067 GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX), 3068 GLX_FUNCTION(glXCreateContextWithConfigSGIX), 3069 GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig), 3070 GLX_FUNCTION(glXGetFBConfigFromVisualSGIX), 3071 3072 /*** GLX_SGIX_pbuffer ***/ 3073 GLX_FUNCTION(glXCreateGLXPbufferSGIX), 3074 GLX_FUNCTION(glXDestroyGLXPbufferSGIX), 3075 GLX_FUNCTION(glXQueryGLXPbufferSGIX), 3076 GLX_FUNCTION(glXSelectEventSGIX), 3077 GLX_FUNCTION(glXGetSelectedEventSGIX), 3078 3079 /*** GLX_SGIX_swap_group ***/ 3080 GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX), 3081 3082 /*** GLX_SGIX_swap_barrier ***/ 3083 GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX), 3084 GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX), 3085 3086 /*** GLX_MESA_allocate_memory ***/ 3087 GLX_FUNCTION(glXAllocateMemoryMESA), 3088 GLX_FUNCTION(glXFreeMemoryMESA), 3089 GLX_FUNCTION(glXGetMemoryOffsetMESA), 3090 3091 /*** GLX_MESA_copy_sub_buffer ***/ 3092 GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA), 3093 3094 /*** GLX_MESA_pixmap_colormap ***/ 3095 GLX_FUNCTION(glXCreateGLXPixmapMESA), 3096 3097 /*** GLX_MESA_release_buffers ***/ 3098 GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA), 3099 3100 /*** GLX_MESA_swap_control ***/ 3101 GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA), 3102 GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA), 3103 3104 /*** GLX_MESA_swap_frame_usage ***/ 3105 GLX_FUNCTION2(glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA), 3106 GLX_FUNCTION2(glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA), 3107 GLX_FUNCTION2(glXGetFrameUsageMESA, __glXGetFrameUsageMESA), 3108 GLX_FUNCTION2(glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA), 3109 3110 /*** GLX_ARB_get_proc_address ***/ 3111 GLX_FUNCTION(glXGetProcAddressARB), 3112 3113 /*** GLX 1.4 ***/ 3114 GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB), 3115 3116 /*** GLX_OML_sync_control ***/ 3117 GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML), 3118 GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML), 3119 GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML), 3120 GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML), 3121 GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML), 3122 3123 /*** GLX_EXT_texture_from_pixmap ***/ 3124 GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT), 3125 GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT), 3126 3127#ifdef GLX_DIRECT_RENDERING 3128 /*** DRI configuration ***/ 3129 GLX_FUNCTION(glXGetScreenDriver), 3130 GLX_FUNCTION(glXGetDriverConfig), 3131#endif 3132 3133 {NULL, NULL} /* end of list */ 3134}; 3135 3136 3137static const GLvoid * 3138get_glx_proc_address(const char *funcName) 3139{ 3140 GLuint i; 3141 3142 /* try static functions */ 3143 for (i = 0; GLX_functions[i].Name; i++) { 3144 if (strcmp(GLX_functions[i].Name, funcName) == 0) 3145 return GLX_functions[i].Address; 3146 } 3147 3148 return NULL; 3149} 3150 3151 3152/** 3153 * Get the address of a named GL function. This is the pre-GLX 1.4 name for 3154 * \c glXGetProcAddress. 3155 * 3156 * \param procName Name of a GL or GLX function. 3157 * \returns A pointer to the named function 3158 * 3159 * \sa glXGetProcAddress 3160 */ 3161PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void) 3162{ 3163 typedef void (*gl_function) (void); 3164 gl_function f; 3165 3166 3167 /* Search the table of GLX and internal functions first. If that 3168 * fails and the supplied name could be a valid core GL name, try 3169 * searching the core GL function table. This check is done to prevent 3170 * DRI based drivers from searching the core GL function table for 3171 * internal API functions. 3172 */ 3173 3174 f = (gl_function) get_glx_proc_address((const char *) procName); 3175 if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l') 3176 && (procName[2] != 'X')) { 3177 f = (gl_function) _glapi_get_proc_address((const char *) procName); 3178 } 3179 3180 return f; 3181} 3182 3183/** 3184 * Get the address of a named GL function. This is the GLX 1.4 name for 3185 * \c glXGetProcAddressARB. 3186 * 3187 * \param procName Name of a GL or GLX function. 3188 * \returns A pointer to the named function 3189 * 3190 * \sa glXGetProcAddressARB 3191 */ 3192PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void) 3193#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED) 3194 __attribute__ ((alias("glXGetProcAddressARB"))); 3195#else 3196{ 3197 return glXGetProcAddressARB(procName); 3198} 3199#endif /* __GNUC__ */ 3200 3201 3202#ifdef GLX_DIRECT_RENDERING 3203/** 3204 * Get the unadjusted system time (UST). Currently, the UST is measured in 3205 * microseconds since Epoc. The actual resolution of the UST may vary from 3206 * system to system, and the units may vary from release to release. 3207 * Drivers should not call this function directly. They should instead use 3208 * \c glXGetProcAddress to obtain a pointer to the function. 3209 * 3210 * \param ust Location to store the 64-bit UST 3211 * \returns Zero on success or a negative errno value on failure. 3212 * 3213 * \sa glXGetProcAddress, PFNGLXGETUSTPROC 3214 * 3215 * \since Internal API version 20030317. 3216 */ 3217_X_HIDDEN int 3218__glXGetUST(int64_t * ust) 3219{ 3220 struct timeval tv; 3221 3222 if (ust == NULL) { 3223 return -EFAULT; 3224 } 3225 3226 if (gettimeofday(&tv, NULL) == 0) { 3227 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; 3228 return 0; 3229 } 3230 else { 3231 return -errno; 3232 } 3233} 3234#endif /* GLX_DIRECT_RENDERING */ 3235