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