glxcmds.c revision d46d30f997c1718217545947ca4d80ec7d18e684
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, int generic_id, 366 const __GLcontextModes * const fbconfig, 367 GLXContext shareList, 368 Bool allowDirect, 369 unsigned code, int renderType, int screen) 370{ 371 GLXContext gc; 372#ifdef GLX_DIRECT_RENDERING 373 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 374#endif 375 376 if (dpy == NULL) 377 return NULL; 378 379 if (generic_id == None) 380 return NULL; 381 382 gc = AllocateGLXContext(dpy); 383 if (!gc) 384 return NULL; 385 386#ifdef GLX_DIRECT_RENDERING 387 if (allowDirect && psc->driScreen) { 388 gc->driContext = psc->driScreen->createContext(psc, fbconfig, gc, 389 shareList, renderType); 390 if (gc->driContext != NULL) { 391 gc->screen = screen; 392 gc->psc = psc; 393 gc->mode = fbconfig; 394 gc->isDirect = GL_TRUE; 395 } 396 } 397#endif 398 399 LockDisplay(dpy); 400 switch (code) { 401 case X_GLXCreateContext: { 402 xGLXCreateContextReq *req; 403 404 /* Send the glXCreateContext request */ 405 GetReq(GLXCreateContext, req); 406 req->reqType = gc->majorOpcode; 407 req->glxCode = X_GLXCreateContext; 408 req->context = gc->xid = XAllocID(dpy); 409 req->visual = generic_id; 410 req->screen = screen; 411 req->shareList = shareList ? shareList->xid : None; 412 req->isDirect = GC_IS_DIRECT(gc); 413 break; 414 } 415 416 case X_GLXCreateNewContext: { 417 xGLXCreateNewContextReq *req; 418 419 /* Send the glXCreateNewContext request */ 420 GetReq(GLXCreateNewContext, req); 421 req->reqType = gc->majorOpcode; 422 req->glxCode = X_GLXCreateNewContext; 423 req->context = gc->xid = XAllocID(dpy); 424 req->fbconfig = generic_id; 425 req->screen = screen; 426 req->renderType = renderType; 427 req->shareList = shareList ? shareList->xid : None; 428 req->isDirect = GC_IS_DIRECT(gc); 429 break; 430 } 431 432 case X_GLXvop_CreateContextWithConfigSGIX: { 433 xGLXVendorPrivateWithReplyReq *vpreq; 434 xGLXCreateContextWithConfigSGIXReq *req; 435 436 /* Send the glXCreateNewContext request */ 437 GetReqExtra(GLXVendorPrivateWithReply, 438 sz_xGLXCreateContextWithConfigSGIXReq - 439 sz_xGLXVendorPrivateWithReplyReq, vpreq); 440 req = (xGLXCreateContextWithConfigSGIXReq *) vpreq; 441 req->reqType = gc->majorOpcode; 442 req->glxCode = X_GLXVendorPrivateWithReply; 443 req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX; 444 req->context = gc->xid = XAllocID(dpy); 445 req->fbconfig = generic_id; 446 req->screen = screen; 447 req->renderType = renderType; 448 req->shareList = shareList ? shareList->xid : None; 449 req->isDirect = GC_IS_DIRECT(gc); 450 break; 451 } 452 453 default: 454 /* What to do here? This case is the sign of an internal error. It 455 * should never be reachable. 456 */ 457 break; 458 } 459 460 UnlockDisplay(dpy); 461 SyncHandle(); 462 463 gc->imported = GL_FALSE; 464 gc->renderType = renderType; 465 466 return gc; 467} 468 469PUBLIC GLXContext 470glXCreateContext(Display * dpy, XVisualInfo * vis, 471 GLXContext shareList, Bool allowDirect) 472{ 473 const __GLcontextModes *mode = NULL; 474 int renderType = 0; 475 476#ifdef GLX_DIRECT_RENDERING 477 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, vis->screen); 478 479 mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid); 480 if (mode == NULL) { 481 xError error; 482 483 error.errorCode = BadValue; 484 error.resourceID = vis->visualid; 485 error.sequenceNumber = dpy->request; 486 error.type = X_Error; 487 error.majorCode = __glXSetupForCommand(dpy); 488 error.minorCode = X_GLXCreateContext; 489 _XError(dpy, &error); 490 return None; 491 } 492 493 renderType = mode->rgbMode ? GLX_RGBA_TYPE : GLX_COLOR_INDEX_TYPE; 494#endif 495 496 return CreateContext(dpy, vis->visualid, mode, shareList, allowDirect, 497 X_GLXCreateContext, renderType, vis->screen); 498} 499 500_X_HIDDEN void 501__glXFreeContext(__GLXcontext * gc) 502{ 503 if (gc->vendor) 504 XFree((char *) gc->vendor); 505 if (gc->renderer) 506 XFree((char *) gc->renderer); 507 if (gc->version) 508 XFree((char *) gc->version); 509 if (gc->extensions) 510 XFree((char *) gc->extensions); 511 __glFreeAttributeState(gc); 512 XFree((char *) gc->buf); 513 Xfree((char *) gc->client_state_private); 514 XFree((char *) gc); 515 516} 517 518/* 519** Destroy the named context 520*/ 521static void 522DestroyContext(Display * dpy, GLXContext gc) 523{ 524 xGLXDestroyContextReq *req; 525 GLXContextID xid; 526 CARD8 opcode; 527 GLboolean imported; 528 529 opcode = __glXSetupForCommand(dpy); 530 if (!opcode || !gc) { 531 return; 532 } 533 534 __glXLock(); 535 xid = gc->xid; 536 imported = gc->imported; 537 gc->xid = None; 538 539 if (gc->currentDpy) { 540 /* This context is bound to some thread. According to the man page, 541 * we should not actually delete the context until it's unbound. 542 * Note that we set gc->xid = None above. In MakeContextCurrent() 543 * we check for that and delete the context there. 544 */ 545 __glXUnlock(); 546 return; 547 } 548 549#ifdef GLX_DIRECT_RENDERING 550 /* Destroy the direct rendering context */ 551 if (gc->driContext) { 552 (*gc->driContext->destroyContext) (gc->driContext, gc->psc, dpy); 553 gc->driContext = NULL; 554 GarbageCollectDRIDrawables(dpy, gc->psc); 555 } 556#endif 557 558 __glXFreeVertexArrayState(gc); 559 560 if (gc->currentDpy) { 561 /* Have to free later cuz it's in use now */ 562 __glXUnlock(); 563 } 564 else { 565 /* Destroy the handle if not current to anybody */ 566 __glXUnlock(); 567 __glXFreeContext(gc); 568 } 569 570 if (!imported) { 571 /* 572 ** This dpy also created the server side part of the context. 573 ** Send the glXDestroyContext request. 574 */ 575 LockDisplay(dpy); 576 GetReq(GLXDestroyContext, req); 577 req->reqType = opcode; 578 req->glxCode = X_GLXDestroyContext; 579 req->context = xid; 580 UnlockDisplay(dpy); 581 SyncHandle(); 582 } 583} 584 585PUBLIC void 586glXDestroyContext(Display * dpy, GLXContext gc) 587{ 588 DestroyContext(dpy, gc); 589} 590 591/* 592** Return the major and minor version #s for the GLX extension 593*/ 594PUBLIC Bool 595glXQueryVersion(Display * dpy, int *major, int *minor) 596{ 597 __GLXdisplayPrivate *priv; 598 599 /* Init the extension. This fetches the major and minor version. */ 600 priv = __glXInitialize(dpy); 601 if (!priv) 602 return GL_FALSE; 603 604 if (major) 605 *major = priv->majorVersion; 606 if (minor) 607 *minor = priv->minorVersion; 608 return GL_TRUE; 609} 610 611/* 612** Query the existance of the GLX extension 613*/ 614PUBLIC Bool 615glXQueryExtension(Display * dpy, int *errorBase, int *eventBase) 616{ 617 int major_op, erb, evb; 618 Bool rv; 619 620 rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb); 621 if (rv) { 622 if (errorBase) 623 *errorBase = erb; 624 if (eventBase) 625 *eventBase = evb; 626 } 627 return rv; 628} 629 630/* 631** Put a barrier in the token stream that forces the GL to finish its 632** work before X can proceed. 633*/ 634PUBLIC void 635glXWaitGL(void) 636{ 637 xGLXWaitGLReq *req; 638 GLXContext gc = __glXGetCurrentContext(); 639 Display *dpy = gc->currentDpy; 640 641 if (!dpy) 642 return; 643 644 /* Flush any pending commands out */ 645 __glXFlushRenderBuffer(gc, gc->pc); 646 647#ifdef GLX_DIRECT_RENDERING 648 if (gc->driContext) { 649 int screen; 650 __GLXDRIdrawable *pdraw = 651 GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen); 652 653 if (pdraw != NULL) { 654 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 655 glFlush(); 656 if (psc->driScreen->waitGL != NULL) 657 (*psc->driScreen->waitGL) (pdraw); 658 } 659 return; 660 } 661#endif 662 663 /* Send the glXWaitGL request */ 664 LockDisplay(dpy); 665 GetReq(GLXWaitGL, req); 666 req->reqType = gc->majorOpcode; 667 req->glxCode = X_GLXWaitGL; 668 req->contextTag = gc->currentContextTag; 669 UnlockDisplay(dpy); 670 SyncHandle(); 671} 672 673/* 674** Put a barrier in the token stream that forces X to finish its 675** work before GL can proceed. 676*/ 677PUBLIC void 678glXWaitX(void) 679{ 680 xGLXWaitXReq *req; 681 GLXContext gc = __glXGetCurrentContext(); 682 Display *dpy = gc->currentDpy; 683 684 if (!dpy) 685 return; 686 687 /* Flush any pending commands out */ 688 __glXFlushRenderBuffer(gc, gc->pc); 689 690#ifdef GLX_DIRECT_RENDERING 691 if (gc->driContext) { 692 int screen; 693 __GLXDRIdrawable *pdraw = 694 GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen); 695 696 if (pdraw != NULL) { 697 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 698 if (psc->driScreen->waitX != NULL) 699 (*psc->driScreen->waitX) (pdraw); 700 } 701 else 702 XSync(dpy, False); 703 return; 704 } 705#endif 706 707 /* 708 ** Send the glXWaitX request. 709 */ 710 LockDisplay(dpy); 711 GetReq(GLXWaitX, req); 712 req->reqType = gc->majorOpcode; 713 req->glxCode = X_GLXWaitX; 714 req->contextTag = gc->currentContextTag; 715 UnlockDisplay(dpy); 716 SyncHandle(); 717} 718 719PUBLIC void 720glXUseXFont(Font font, int first, int count, int listBase) 721{ 722 xGLXUseXFontReq *req; 723 GLXContext gc = __glXGetCurrentContext(); 724 Display *dpy = gc->currentDpy; 725 726 if (!dpy) 727 return; 728 729 /* Flush any pending commands out */ 730 (void) __glXFlushRenderBuffer(gc, gc->pc); 731 732#ifdef GLX_DIRECT_RENDERING 733 if (gc->driContext) { 734 DRI_glXUseXFont(font, first, count, listBase); 735 return; 736 } 737#endif 738 739 /* Send the glXUseFont request */ 740 LockDisplay(dpy); 741 GetReq(GLXUseXFont, req); 742 req->reqType = gc->majorOpcode; 743 req->glxCode = X_GLXUseXFont; 744 req->contextTag = gc->currentContextTag; 745 req->font = font; 746 req->first = first; 747 req->count = count; 748 req->listBase = listBase; 749 UnlockDisplay(dpy); 750 SyncHandle(); 751} 752 753/************************************************************************/ 754 755/* 756** Copy the source context to the destination context using the 757** attribute "mask". 758*/ 759PUBLIC void 760glXCopyContext(Display * dpy, GLXContext source, 761 GLXContext dest, unsigned long mask) 762{ 763 xGLXCopyContextReq *req; 764 GLXContext gc = __glXGetCurrentContext(); 765 GLXContextTag tag; 766 CARD8 opcode; 767 768 opcode = __glXSetupForCommand(dpy); 769 if (!opcode) { 770 return; 771 } 772 773#ifdef GLX_DIRECT_RENDERING 774 if (gc->driContext) { 775 /* NOT_DONE: This does not work yet */ 776 } 777#endif 778 779 /* 780 ** If the source is the current context, send its tag so that the context 781 ** can be flushed before the copy. 782 */ 783 if (source == gc && dpy == gc->currentDpy) { 784 tag = gc->currentContextTag; 785 } 786 else { 787 tag = 0; 788 } 789 790 /* Send the glXCopyContext request */ 791 LockDisplay(dpy); 792 GetReq(GLXCopyContext, req); 793 req->reqType = opcode; 794 req->glxCode = X_GLXCopyContext; 795 req->source = source ? source->xid : None; 796 req->dest = dest ? dest->xid : None; 797 req->mask = mask; 798 req->contextTag = tag; 799 UnlockDisplay(dpy); 800 SyncHandle(); 801} 802 803 804/** 805 * Determine if a context uses direct rendering. 806 * 807 * \param dpy Display where the context was created. 808 * \param contextID ID of the context to be tested. 809 * 810 * \returns \c GL_TRUE if the context is direct rendering or not. 811 */ 812static Bool 813__glXIsDirect(Display * dpy, GLXContextID contextID) 814{ 815#if !defined(USE_XCB) 816 xGLXIsDirectReq *req; 817 xGLXIsDirectReply reply; 818#endif 819 CARD8 opcode; 820 821 opcode = __glXSetupForCommand(dpy); 822 if (!opcode) { 823 return GL_FALSE; 824 } 825 826#ifdef USE_XCB 827 xcb_connection_t *c = XGetXCBConnection(dpy); 828 xcb_glx_is_direct_reply_t *reply = xcb_glx_is_direct_reply(c, 829 xcb_glx_is_direct 830 (c, contextID), 831 NULL); 832 833 const Bool is_direct = reply->is_direct ? True : False; 834 free(reply); 835 836 return is_direct; 837#else 838 /* Send the glXIsDirect request */ 839 LockDisplay(dpy); 840 GetReq(GLXIsDirect, req); 841 req->reqType = opcode; 842 req->glxCode = X_GLXIsDirect; 843 req->context = contextID; 844 _XReply(dpy, (xReply *) & reply, 0, False); 845 UnlockDisplay(dpy); 846 SyncHandle(); 847 848 return reply.isDirect; 849#endif /* USE_XCB */ 850} 851 852/** 853 * \todo 854 * Shouldn't this function \b always return \c GL_FALSE when 855 * \c GLX_DIRECT_RENDERING is not defined? Do we really need to bother with 856 * the GLX protocol here at all? 857 */ 858PUBLIC Bool 859glXIsDirect(Display * dpy, GLXContext gc) 860{ 861 if (!gc) { 862 return GL_FALSE; 863 } 864 else if (GC_IS_DIRECT(gc)) { 865 return GL_TRUE; 866 } 867 return __glXIsDirect(dpy, gc->xid); 868} 869 870PUBLIC GLXPixmap 871glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap) 872{ 873 xGLXCreateGLXPixmapReq *req; 874 GLXPixmap xid; 875 CARD8 opcode; 876 877 opcode = __glXSetupForCommand(dpy); 878 if (!opcode) { 879 return None; 880 } 881 882 /* Send the glXCreateGLXPixmap request */ 883 LockDisplay(dpy); 884 GetReq(GLXCreateGLXPixmap, req); 885 req->reqType = opcode; 886 req->glxCode = X_GLXCreateGLXPixmap; 887 req->screen = vis->screen; 888 req->visual = vis->visualid; 889 req->pixmap = pixmap; 890 req->glxpixmap = xid = XAllocID(dpy); 891 UnlockDisplay(dpy); 892 SyncHandle(); 893 894#ifdef GLX_DIRECT_RENDERING 895 do { 896 /* FIXME: Maybe delay __DRIdrawable creation until the drawable 897 * is actually bound to a context... */ 898 899 __GLXdisplayPrivate *const priv = __glXInitialize(dpy); 900 __GLXDRIdrawable *pdraw; 901 __GLXscreenConfigs *psc; 902 __GLcontextModes *modes; 903 904 psc = &priv->screenConfigs[vis->screen]; 905 if (psc->driScreen == NULL) 906 break; 907 modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid); 908 pdraw = psc->driScreen->createDrawable(psc, pixmap, req->glxpixmap, modes); 909 if (pdraw == NULL) { 910 fprintf(stderr, "failed to create pixmap\n"); 911 break; 912 } 913 914 if (__glxHashInsert(psc->drawHash, req->glxpixmap, pdraw)) { 915 (*pdraw->destroyDrawable) (pdraw); 916 return None; /* FIXME: Check what we're supposed to do here... */ 917 } 918 } while (0); 919#endif 920 921 return xid; 922} 923 924/* 925** Destroy the named pixmap 926*/ 927PUBLIC void 928glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap) 929{ 930 xGLXDestroyGLXPixmapReq *req; 931 CARD8 opcode; 932 933 opcode = __glXSetupForCommand(dpy); 934 if (!opcode) { 935 return; 936 } 937 938 /* Send the glXDestroyGLXPixmap request */ 939 LockDisplay(dpy); 940 GetReq(GLXDestroyGLXPixmap, req); 941 req->reqType = opcode; 942 req->glxCode = X_GLXDestroyGLXPixmap; 943 req->glxpixmap = glxpixmap; 944 UnlockDisplay(dpy); 945 SyncHandle(); 946 947#ifdef GLX_DIRECT_RENDERING 948 { 949 int screen; 950 __GLXdisplayPrivate *const priv = __glXInitialize(dpy); 951 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap, &screen); 952 __GLXscreenConfigs *psc = &priv->screenConfigs[screen]; 953 954 if (pdraw != NULL) { 955 (*pdraw->destroyDrawable) (pdraw); 956 __glxHashDelete(psc->drawHash, glxpixmap); 957 } 958 } 959#endif 960} 961 962PUBLIC void 963glXSwapBuffers(Display * dpy, GLXDrawable drawable) 964{ 965 GLXContext gc; 966 GLXContextTag tag; 967 CARD8 opcode; 968#ifdef USE_XCB 969 xcb_connection_t *c; 970#else 971 xGLXSwapBuffersReq *req; 972#endif 973 974#ifdef GLX_DIRECT_RENDERING 975 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); 976 977 if (pdraw != NULL) { 978 glFlush(); 979 (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0); 980 return; 981 } 982#endif 983 984 opcode = __glXSetupForCommand(dpy); 985 if (!opcode) { 986 return; 987 } 988 989 /* 990 ** The calling thread may or may not have a current context. If it 991 ** does, send the context tag so the server can do a flush. 992 */ 993 gc = __glXGetCurrentContext(); 994 if ((gc != NULL) && (dpy == gc->currentDpy) && 995 ((drawable == gc->currentDrawable) 996 || (drawable == gc->currentReadable))) { 997 tag = gc->currentContextTag; 998 } 999 else { 1000 tag = 0; 1001 } 1002 1003#ifdef USE_XCB 1004 c = XGetXCBConnection(dpy); 1005 xcb_glx_swap_buffers(c, tag, drawable); 1006 xcb_flush(c); 1007#else 1008 /* Send the glXSwapBuffers request */ 1009 LockDisplay(dpy); 1010 GetReq(GLXSwapBuffers, req); 1011 req->reqType = opcode; 1012 req->glxCode = X_GLXSwapBuffers; 1013 req->drawable = drawable; 1014 req->contextTag = tag; 1015 UnlockDisplay(dpy); 1016 SyncHandle(); 1017 XFlush(dpy); 1018#endif /* USE_XCB */ 1019} 1020 1021 1022/* 1023** Return configuration information for the given display, screen and 1024** visual combination. 1025*/ 1026PUBLIC int 1027glXGetConfig(Display * dpy, XVisualInfo * vis, int attribute, 1028 int *value_return) 1029{ 1030 __GLXdisplayPrivate *priv; 1031 __GLXscreenConfigs *psc; 1032 __GLcontextModes *modes; 1033 int status; 1034 1035 status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc); 1036 if (status == Success) { 1037 modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid); 1038 1039 /* Lookup attribute after first finding a match on the visual */ 1040 if (modes != NULL) { 1041 return _gl_get_context_mode_data(modes, attribute, value_return); 1042 } 1043 1044 status = GLX_BAD_VISUAL; 1045 } 1046 1047 /* 1048 ** If we can't find the config for this visual, this visual is not 1049 ** supported by the OpenGL implementation on the server. 1050 */ 1051 if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) { 1052 *value_return = GL_FALSE; 1053 status = Success; 1054 } 1055 1056 return status; 1057} 1058 1059/************************************************************************/ 1060 1061static void 1062init_fbconfig_for_chooser(__GLcontextModes * config, 1063 GLboolean fbconfig_style_tags) 1064{ 1065 memset(config, 0, sizeof(__GLcontextModes)); 1066 config->visualID = (XID) GLX_DONT_CARE; 1067 config->visualType = GLX_DONT_CARE; 1068 1069 /* glXChooseFBConfig specifies different defaults for these two than 1070 * glXChooseVisual. 1071 */ 1072 if (fbconfig_style_tags) { 1073 config->rgbMode = GL_TRUE; 1074 config->doubleBufferMode = GLX_DONT_CARE; 1075 } 1076 1077 config->visualRating = GLX_DONT_CARE; 1078 config->transparentPixel = GLX_NONE; 1079 config->transparentRed = GLX_DONT_CARE; 1080 config->transparentGreen = GLX_DONT_CARE; 1081 config->transparentBlue = GLX_DONT_CARE; 1082 config->transparentAlpha = GLX_DONT_CARE; 1083 config->transparentIndex = GLX_DONT_CARE; 1084 1085 config->drawableType = GLX_WINDOW_BIT; 1086 config->renderType = 1087 (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; 1088 config->xRenderable = GLX_DONT_CARE; 1089 config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE); 1090 1091 config->swapMethod = GLX_DONT_CARE; 1092} 1093 1094#define MATCH_DONT_CARE( param ) \ 1095 do { \ 1096 if ( ((int) a-> param != (int) GLX_DONT_CARE) \ 1097 && (a-> param != b-> param) ) { \ 1098 return False; \ 1099 } \ 1100 } while ( 0 ) 1101 1102#define MATCH_MINIMUM( param ) \ 1103 do { \ 1104 if ( ((int) a-> param != (int) GLX_DONT_CARE) \ 1105 && (a-> param > b-> param) ) { \ 1106 return False; \ 1107 } \ 1108 } while ( 0 ) 1109 1110#define MATCH_EXACT( param ) \ 1111 do { \ 1112 if ( a-> param != b-> param) { \ 1113 return False; \ 1114 } \ 1115 } while ( 0 ) 1116 1117/** 1118 * Determine if two GLXFBConfigs are compatible. 1119 * 1120 * \param a Application specified config to test. 1121 * \param b Server specified config to test against \c a. 1122 */ 1123static Bool 1124fbconfigs_compatible(const __GLcontextModes * const a, 1125 const __GLcontextModes * const b) 1126{ 1127 MATCH_DONT_CARE(doubleBufferMode); 1128 MATCH_DONT_CARE(visualType); 1129 MATCH_DONT_CARE(visualRating); 1130 MATCH_DONT_CARE(xRenderable); 1131 MATCH_DONT_CARE(fbconfigID); 1132 MATCH_DONT_CARE(swapMethod); 1133 1134 MATCH_MINIMUM(rgbBits); 1135 MATCH_MINIMUM(numAuxBuffers); 1136 MATCH_MINIMUM(redBits); 1137 MATCH_MINIMUM(greenBits); 1138 MATCH_MINIMUM(blueBits); 1139 MATCH_MINIMUM(alphaBits); 1140 MATCH_MINIMUM(depthBits); 1141 MATCH_MINIMUM(stencilBits); 1142 MATCH_MINIMUM(accumRedBits); 1143 MATCH_MINIMUM(accumGreenBits); 1144 MATCH_MINIMUM(accumBlueBits); 1145 MATCH_MINIMUM(accumAlphaBits); 1146 MATCH_MINIMUM(sampleBuffers); 1147 MATCH_MINIMUM(maxPbufferWidth); 1148 MATCH_MINIMUM(maxPbufferHeight); 1149 MATCH_MINIMUM(maxPbufferPixels); 1150 MATCH_MINIMUM(samples); 1151 1152 MATCH_DONT_CARE(stereoMode); 1153 MATCH_EXACT(level); 1154 1155 if (((a->drawableType & b->drawableType) == 0) 1156 || ((a->renderType & b->renderType) == 0)) { 1157 return False; 1158 } 1159 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 if (gc->driContext && psc->driScreen && psc->driScreen->setSwapInterval) { 1925 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 1926 gc->currentDrawable, 1927 NULL); 1928 psc->driScreen->setSwapInterval(pdraw, interval); 1929 return 0; 1930 } 1931 1932 dpy = gc->currentDpy; 1933 opcode = __glXSetupForCommand(dpy); 1934 if (!opcode) { 1935 return 0; 1936 } 1937 1938 /* Send the glXSwapIntervalSGI request */ 1939 LockDisplay(dpy); 1940 GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req); 1941 req->reqType = opcode; 1942 req->glxCode = X_GLXVendorPrivate; 1943 req->vendorCode = X_GLXvop_SwapIntervalSGI; 1944 req->contextTag = gc->currentContextTag; 1945 1946 interval_ptr = (CARD32 *) (req + 1); 1947 *interval_ptr = interval; 1948 1949 UnlockDisplay(dpy); 1950 SyncHandle(); 1951 XFlush(dpy); 1952 1953 return 0; 1954} 1955 1956 1957/* 1958** GLX_MESA_swap_control 1959*/ 1960static int 1961__glXSwapIntervalMESA(unsigned int interval) 1962{ 1963 GLXContext gc = __glXGetCurrentContext(); 1964 1965#ifdef __DRI_SWAP_CONTROL 1966 if (gc != NULL && gc->driContext) { 1967 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, 1968 gc->screen); 1969 1970 if ((psc != NULL) && (psc->driScreen != NULL)) { 1971 __GLXDRIdrawable *pdraw = 1972 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 1973 if (psc->swapControl != NULL && pdraw != NULL) { 1974 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); 1975 return 0; 1976 } 1977 } 1978 } 1979#endif 1980 1981 if (gc != NULL && gc->driContext) { 1982 __GLXscreenConfigs *psc; 1983 1984 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1985 if (psc->driScreen && psc->driScreen->setSwapInterval) { 1986 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 1987 gc->currentDrawable, NULL); 1988 psc->driScreen->setSwapInterval(pdraw, interval); 1989 return 0; 1990 } 1991 } 1992 1993 return GLX_BAD_CONTEXT; 1994} 1995 1996 1997static int 1998__glXGetSwapIntervalMESA(void) 1999{ 2000#ifdef __DRI_SWAP_CONTROL 2001 GLXContext gc = __glXGetCurrentContext(); 2002 2003 if (gc != NULL && gc->driContext) { 2004 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, 2005 gc->screen); 2006 2007 if ((psc != NULL) && (psc->driScreen != NULL)) { 2008 __GLXDRIdrawable *pdraw = 2009 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2010 if (psc->swapControl != NULL && pdraw != NULL) { 2011 return psc->swapControl->getSwapInterval(pdraw->driDrawable); 2012 } 2013 } 2014 } 2015#endif 2016 if (gc != NULL && gc->driContext) { 2017 __GLXscreenConfigs *psc; 2018 2019 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 2020 if (psc->driScreen && psc->driScreen->getSwapInterval) { 2021 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 2022 gc->currentDrawable, NULL); 2023 return psc->driScreen->getSwapInterval(pdraw); 2024 } 2025 } 2026 2027 return 0; 2028} 2029 2030 2031/* 2032** GLX_MESA_swap_frame_usage 2033*/ 2034 2035static GLint 2036__glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable) 2037{ 2038 int status = GLX_BAD_CONTEXT; 2039#ifdef __DRI_FRAME_TRACKING 2040 int screen = 0; 2041 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2042 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2043 2044 if (pdraw != NULL && psc->frameTracking != NULL) 2045 status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE); 2046#else 2047 (void) dpy; 2048 (void) drawable; 2049#endif 2050 return status; 2051} 2052 2053 2054static GLint 2055__glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable) 2056{ 2057 int status = GLX_BAD_CONTEXT; 2058#ifdef __DRI_FRAME_TRACKING 2059 int screen = 0; 2060 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2061 __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen); 2062 2063 if (pdraw != NULL && psc->frameTracking != NULL) 2064 status = psc->frameTracking->frameTracking(pdraw->driDrawable, 2065 GL_FALSE); 2066#else 2067 (void) dpy; 2068 (void) drawable; 2069#endif 2070 return status; 2071} 2072 2073 2074static GLint 2075__glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage) 2076{ 2077 int status = GLX_BAD_CONTEXT; 2078#ifdef __DRI_FRAME_TRACKING 2079 int screen = 0; 2080 __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2081 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2082 2083 if (pdraw != NULL && psc->frameTracking != NULL) { 2084 int64_t sbc, missedFrames; 2085 float lastMissedUsage; 2086 2087 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, 2088 &sbc, 2089 &missedFrames, 2090 &lastMissedUsage, 2091 usage); 2092 } 2093#else 2094 (void) dpy; 2095 (void) drawable; 2096 (void) usage; 2097#endif 2098 return status; 2099} 2100 2101 2102static GLint 2103__glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable, 2104 int64_t * sbc, int64_t * missedFrames, 2105 GLfloat * lastMissedUsage) 2106{ 2107 int status = GLX_BAD_CONTEXT; 2108#ifdef __DRI_FRAME_TRACKING 2109 int screen = 0; 2110 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2111 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2112 2113 if (pdraw != NULL && psc->frameTracking != NULL) { 2114 float usage; 2115 2116 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, 2117 sbc, missedFrames, 2118 lastMissedUsage, 2119 &usage); 2120 } 2121#else 2122 (void) dpy; 2123 (void) drawable; 2124 (void) sbc; 2125 (void) missedFrames; 2126 (void) lastMissedUsage; 2127#endif 2128 return status; 2129} 2130 2131 2132/* 2133** GLX_SGI_video_sync 2134*/ 2135static int 2136__glXGetVideoSyncSGI(unsigned int *count) 2137{ 2138 int64_t ust, msc, sbc; 2139 int ret; 2140 GLXContext gc = __glXGetCurrentContext(); 2141 __GLXscreenConfigs *psc; 2142 __GLXDRIdrawable *pdraw; 2143 2144 if (!gc || !gc->driContext) 2145 return GLX_BAD_CONTEXT; 2146 2147 psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen); 2148 pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2149 2150 /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry, 2151 * FIXME: there should be a GLX encoding for this call. I can find no 2152 * FIXME: documentation for the GLX encoding. 2153 */ 2154#ifdef __DRI_MEDIA_STREAM_COUNTER 2155 if ( psc->msc && psc->driScreen ) { 2156 ret = (*psc->msc->getDrawableMSC)(psc->__driScreen, 2157 pdraw->driDrawable, &msc); 2158 *count = (unsigned) msc; 2159 2160 return (ret == 0) ? 0 : GLX_BAD_CONTEXT; 2161 } 2162#endif 2163 if (psc->driScreen && psc->driScreen->getDrawableMSC) { 2164 ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc); 2165 *count = (unsigned) msc; 2166 return (ret == True) ? 0 : GLX_BAD_CONTEXT; 2167 } 2168 2169 return GLX_BAD_CONTEXT; 2170} 2171 2172static int 2173__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) 2174{ 2175 GLXContext gc = __glXGetCurrentContext(); 2176 __GLXscreenConfigs *psc; 2177 __GLXDRIdrawable *pdraw; 2178 int64_t ust, msc, sbc; 2179 int ret; 2180 2181 if (divisor <= 0 || remainder < 0) 2182 return GLX_BAD_VALUE; 2183 2184 if (!gc || !gc->driContext) 2185 return GLX_BAD_CONTEXT; 2186 2187 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 2188 pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2189 2190#ifdef __DRI_MEDIA_STREAM_COUNTER 2191 if (psc->msc != NULL && psc->driScreen ) { 2192 ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0, 2193 divisor, remainder, &msc, &sbc); 2194 *count = (unsigned) msc; 2195 return (ret == 0) ? 0 : GLX_BAD_CONTEXT; 2196 } 2197#endif 2198 if (psc->driScreen && psc->driScreen->waitForMSC) { 2199 ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc, 2200 &sbc); 2201 *count = (unsigned) msc; 2202 return (ret == True) ? 0 : GLX_BAD_CONTEXT; 2203 } 2204 2205 return GLX_BAD_CONTEXT; 2206} 2207 2208 2209/* 2210** GLX_SGIX_fbconfig 2211** Many of these functions are aliased to GLX 1.3 entry points in the 2212** GLX_functions table. 2213*/ 2214 2215PUBLIC 2216GLX_ALIAS(int, glXGetFBConfigAttribSGIX, 2217 (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value), 2218 (dpy, config, attribute, value), glXGetFBConfigAttrib) 2219 2220PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX, 2221 (Display * dpy, int screen, int *attrib_list, 2222 int *nelements), (dpy, screen, attrib_list, nelements), 2223 glXChooseFBConfig) 2224 2225PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX, 2226 (Display * dpy, GLXFBConfigSGIX config), 2227 (dpy, config), glXGetVisualFromFBConfig) 2228 2229PUBLIC GLXPixmap 2230glXCreateGLXPixmapWithConfigSGIX(Display * dpy, 2231 GLXFBConfigSGIX config, 2232 Pixmap pixmap) 2233{ 2234 xGLXVendorPrivateWithReplyReq *vpreq; 2235 xGLXCreateGLXPixmapWithConfigSGIXReq *req; 2236 GLXPixmap xid = None; 2237 CARD8 opcode; 2238 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config; 2239 __GLXscreenConfigs *psc; 2240 2241 2242 if ((dpy == NULL) || (config == NULL)) { 2243 return None; 2244 } 2245 2246 psc = GetGLXScreenConfigs(dpy, fbconfig->screen); 2247 if ((psc != NULL) 2248 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 2249 opcode = __glXSetupForCommand(dpy); 2250 if (!opcode) { 2251 return None; 2252 } 2253 2254 /* Send the glXCreateGLXPixmapWithConfigSGIX request */ 2255 LockDisplay(dpy); 2256 GetReqExtra(GLXVendorPrivateWithReply, 2257 sz_xGLXCreateGLXPixmapWithConfigSGIXReq - 2258 sz_xGLXVendorPrivateWithReplyReq, vpreq); 2259 req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq; 2260 req->reqType = opcode; 2261 req->glxCode = X_GLXVendorPrivateWithReply; 2262 req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; 2263 req->screen = fbconfig->screen; 2264 req->fbconfig = fbconfig->fbconfigID; 2265 req->pixmap = pixmap; 2266 req->glxpixmap = xid = XAllocID(dpy); 2267 UnlockDisplay(dpy); 2268 SyncHandle(); 2269 } 2270 2271 return xid; 2272} 2273 2274PUBLIC GLXContext 2275glXCreateContextWithConfigSGIX(Display * dpy, 2276 GLXFBConfigSGIX config, int renderType, 2277 GLXContext shareList, Bool allowDirect) 2278{ 2279 GLXContext gc = NULL; 2280 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config; 2281 __GLXscreenConfigs *psc; 2282 2283 2284 if ((dpy == NULL) || (config == NULL)) { 2285 return None; 2286 } 2287 2288 psc = GetGLXScreenConfigs(dpy, fbconfig->screen); 2289 if ((psc != NULL) 2290 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 2291 gc = CreateContext(dpy, fbconfig->fbconfigID, fbconfig, shareList, 2292 allowDirect, 2293 X_GLXvop_CreateContextWithConfigSGIX, renderType, 2294 fbconfig->screen); 2295 } 2296 2297 return gc; 2298} 2299 2300 2301PUBLIC GLXFBConfigSGIX 2302glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis) 2303{ 2304 __GLXdisplayPrivate *priv; 2305 __GLXscreenConfigs *psc = NULL; 2306 2307 if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success) 2308 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit) 2309 && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) { 2310 return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs, 2311 vis->visualid); 2312 } 2313 2314 return NULL; 2315} 2316 2317 2318/* 2319** GLX_SGIX_swap_group 2320*/ 2321static void 2322__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable, 2323 GLXDrawable member) 2324{ 2325 (void) dpy; 2326 (void) drawable; 2327 (void) member; 2328} 2329 2330 2331/* 2332** GLX_SGIX_swap_barrier 2333*/ 2334static void 2335__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier) 2336{ 2337 (void) dpy; 2338 (void) drawable; 2339 (void) barrier; 2340} 2341 2342static Bool 2343__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max) 2344{ 2345 (void) dpy; 2346 (void) screen; 2347 (void) max; 2348 return False; 2349} 2350 2351 2352/* 2353** GLX_OML_sync_control 2354*/ 2355static Bool 2356__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable, 2357 int64_t * ust, int64_t * msc, int64_t * sbc) 2358{ 2359 __GLXdisplayPrivate * const priv = __glXInitialize(dpy); 2360 int i, ret; 2361 __GLXDRIdrawable *pdraw; 2362 __GLXscreenConfigs *psc; 2363 2364 if (!priv) 2365 return False; 2366 2367 pdraw = GetGLXDRIDrawable(dpy, drawable, &i); 2368 psc = &priv->screenConfigs[i]; 2369 2370#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER) 2371 if (pdraw && psc->sbc && psc->sbc) 2372 return ( (pdraw && psc->sbc && psc->msc) 2373 && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0) 2374 && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0) 2375 && (__glXGetUST(ust) == 0) ); 2376#endif 2377 if (pdraw && psc && psc->driScreen && psc->driScreen->getDrawableMSC) { 2378 ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc); 2379 return ret; 2380 } 2381 2382 return False; 2383} 2384 2385#ifdef GLX_DIRECT_RENDERING 2386_X_HIDDEN GLboolean 2387__driGetMscRateOML(__DRIdrawable * draw, 2388 int32_t * numerator, int32_t * denominator, void *private) 2389{ 2390#ifdef XF86VIDMODE 2391 __GLXscreenConfigs *psc; 2392 XF86VidModeModeLine mode_line; 2393 int dot_clock; 2394 int i; 2395 __GLXDRIdrawable *glxDraw = private; 2396 2397 (void) draw; 2398 2399 psc = glxDraw->psc; 2400 if (XF86VidModeQueryVersion(psc->dpy, &i, &i) && 2401 XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) { 2402 unsigned n = dot_clock * 1000; 2403 unsigned d = mode_line.vtotal * mode_line.htotal; 2404 2405# define V_INTERLACE 0x010 2406# define V_DBLSCAN 0x020 2407 2408 if (mode_line.flags & V_INTERLACE) 2409 n *= 2; 2410 else if (mode_line.flags & V_DBLSCAN) 2411 d *= 2; 2412 2413 /* The OML_sync_control spec requires that if the refresh rate is a 2414 * whole number, that the returned numerator be equal to the refresh 2415 * rate and the denominator be 1. 2416 */ 2417 2418 if (n % d == 0) { 2419 n /= d; 2420 d = 1; 2421 } 2422 else { 2423 static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 }; 2424 2425 /* This is a poor man's way to reduce a fraction. It's far from 2426 * perfect, but it will work well enough for this situation. 2427 */ 2428 2429 for (i = 0; f[i] != 0; i++) { 2430 while (n % f[i] == 0 && d % f[i] == 0) { 2431 d /= f[i]; 2432 n /= f[i]; 2433 } 2434 } 2435 } 2436 2437 *numerator = n; 2438 *denominator = d; 2439 2440 return True; 2441 } 2442 else 2443 return False; 2444#else 2445 (void) draw; 2446 (void) numerator; 2447 (void) denominator; 2448 (void) private; 2449 2450 return False; 2451#endif 2452} 2453#endif 2454 2455/** 2456 * Determine the refresh rate of the specified drawable and display. 2457 * 2458 * \param dpy Display whose refresh rate is to be determined. 2459 * \param drawable Drawable whose refresh rate is to be determined. 2460 * \param numerator Numerator of the refresh rate. 2461 * \param demoninator Denominator of the refresh rate. 2462 * \return If the refresh rate for the specified display and drawable could 2463 * be calculated, True is returned. Otherwise False is returned. 2464 * 2465 * \note This function is implemented entirely client-side. A lot of other 2466 * functionality is required to export GLX_OML_sync_control, so on 2467 * XFree86 this function can be called for direct-rendering contexts 2468 * when GLX_OML_sync_control appears in the client extension string. 2469 */ 2470 2471_X_HIDDEN GLboolean 2472__glXGetMscRateOML(Display * dpy, GLXDrawable drawable, 2473 int32_t * numerator, int32_t * denominator) 2474{ 2475#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE ) 2476 __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL); 2477 2478 if (draw == NULL) 2479 return False; 2480 2481 return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw); 2482#else 2483 (void) dpy; 2484 (void) drawable; 2485 (void) numerator; 2486 (void) denominator; 2487#endif 2488 return False; 2489} 2490 2491 2492static int64_t 2493__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, 2494 int64_t target_msc, int64_t divisor, int64_t remainder) 2495{ 2496 GLXContext gc = __glXGetCurrentContext(); 2497 int screen; 2498 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2499 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2500 2501 if (!pdraw || !gc->driContext) /* no GLX for this */ 2502 return -1; 2503 2504 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2505 * error", but it also says "It [glXSwapBuffersMscOML] will return a value 2506 * of -1 if the function failed because of errors detected in the input 2507 * parameters" 2508 */ 2509 if (divisor < 0 || remainder < 0 || target_msc < 0) 2510 return -1; 2511 if (divisor > 0 && remainder >= divisor) 2512 return -1; 2513 2514#ifdef __DRI_SWAP_BUFFER_COUNTER 2515 if (psc->counters != NULL) 2516 return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc, 2517 divisor, remainder); 2518#endif 2519 2520#ifdef GLX_DIRECT_RENDERING 2521 if (psc->driScreen && psc->driScreen->swapBuffers) 2522 return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor, 2523 remainder); 2524#endif 2525 2526 return -1; 2527} 2528 2529 2530static Bool 2531__glXWaitForMscOML(Display * dpy, GLXDrawable drawable, 2532 int64_t target_msc, int64_t divisor, 2533 int64_t remainder, int64_t * ust, 2534 int64_t * msc, int64_t * sbc) 2535{ 2536 int screen; 2537 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2538 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); 2539 int ret; 2540 2541 fprintf(stderr, "waitmsc: %lld, %lld, %lld\n", target_msc, divisor, 2542 remainder); 2543 2544 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2545 * error", but the return type in the spec is Bool. 2546 */ 2547 if (divisor < 0 || remainder < 0 || target_msc < 0) 2548 return False; 2549 if (divisor > 0 && remainder >= divisor) 2550 return False; 2551 2552#ifdef __DRI_MEDIA_STREAM_COUNTER 2553 if (pdraw != NULL && psc->msc != NULL) { 2554 fprintf(stderr, "dri1 msc\n"); 2555 ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc, 2556 divisor, remainder, msc, sbc); 2557 2558 /* __glXGetUST returns zero on success and non-zero on failure. 2559 * This function returns True on success and False on failure. 2560 */ 2561 return ((ret == 0) && (__glXGetUST(ust) == 0)); 2562 } 2563#endif 2564 if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) { 2565 ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder, 2566 ust, msc, sbc); 2567 return ret; 2568 } 2569 2570 fprintf(stderr, "no drawable??\n"); 2571 return False; 2572} 2573 2574 2575static Bool 2576__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, 2577 int64_t target_sbc, int64_t * ust, 2578 int64_t * msc, int64_t * sbc) 2579{ 2580 int screen; 2581 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2582 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2583 int ret; 2584 2585 /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE 2586 * error", but the return type in the spec is Bool. 2587 */ 2588 if (target_sbc < 0) 2589 return False; 2590#ifdef __DRI_SWAP_BUFFER_COUNTER 2591 if (pdraw != NULL && psc->sbc != NULL) { 2592 ret = 2593 (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc); 2594 2595 /* __glXGetUST returns zero on success and non-zero on failure. 2596 * This function returns True on success and False on failure. 2597 */ 2598 return ((ret == 0) && (__glXGetUST(ust) == 0)); 2599 } 2600#endif 2601 if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) { 2602 ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc); 2603 return ret; 2604 } 2605 return False; 2606} 2607 2608 2609/** 2610 * GLX_MESA_allocate_memory 2611 */ 2612/*@{*/ 2613 2614PUBLIC void * 2615glXAllocateMemoryMESA(Display * dpy, int scrn, 2616 size_t size, float readFreq, 2617 float writeFreq, float priority) 2618{ 2619#ifdef __DRI_ALLOCATE 2620 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2621 2622 if (psc && psc->allocate) 2623 return (*psc->allocate->allocateMemory) (psc->__driScreen, size, 2624 readFreq, writeFreq, priority); 2625 2626#else 2627 (void) dpy; 2628 (void) scrn; 2629 (void) size; 2630 (void) readFreq; 2631 (void) writeFreq; 2632 (void) priority; 2633#endif /* __DRI_ALLOCATE */ 2634 2635 return NULL; 2636} 2637 2638 2639PUBLIC void 2640glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer) 2641{ 2642#ifdef __DRI_ALLOCATE 2643 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2644 2645 if (psc && psc->allocate) 2646 (*psc->allocate->freeMemory) (psc->__driScreen, pointer); 2647 2648#else 2649 (void) dpy; 2650 (void) scrn; 2651 (void) pointer; 2652#endif /* __DRI_ALLOCATE */ 2653} 2654 2655 2656PUBLIC GLuint 2657glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer) 2658{ 2659#ifdef __DRI_ALLOCATE 2660 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2661 2662 if (psc && psc->allocate) 2663 return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer); 2664 2665#else 2666 (void) dpy; 2667 (void) scrn; 2668 (void) pointer; 2669#endif /* GLX_DIRECT_RENDERING */ 2670 2671 return ~0L; 2672} 2673 2674/*@}*/ 2675 2676 2677/** 2678 * Mesa extension stubs. These will help reduce portability problems. 2679 */ 2680/*@{*/ 2681 2682/** 2683 * Release all buffers associated with the specified GLX drawable. 2684 * 2685 * \todo 2686 * This function was intended for stand-alone Mesa. The issue there is that 2687 * the library doesn't get any notification when a window is closed. In 2688 * DRI there is a similar but slightly different issue. When GLX 1.3 is 2689 * supported, there are 3 different functions to destroy a drawable. It 2690 * should be possible to create GLX protocol (or have it determine which 2691 * protocol to use based on the type of the drawable) to have one function 2692 * do the work of 3. For the direct-rendering case, this function could 2693 * just call the driver's \c __DRIdrawableRec::destroyDrawable function. 2694 * This would reduce the frequency with which \c __driGarbageCollectDrawables 2695 * would need to be used. This really should be done as part of the new DRI 2696 * interface work. 2697 * 2698 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt 2699 * __driGarbageCollectDrawables 2700 * glXDestroyGLXPixmap 2701 * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow 2702 * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX 2703 */ 2704static Bool 2705__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d) 2706{ 2707 (void) dpy; 2708 (void) d; 2709 return False; 2710} 2711 2712 2713PUBLIC GLXPixmap 2714glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual, 2715 Pixmap pixmap, Colormap cmap) 2716{ 2717 (void) dpy; 2718 (void) visual; 2719 (void) pixmap; 2720 (void) cmap; 2721 return 0; 2722} 2723 2724/*@}*/ 2725 2726 2727/** 2728 * GLX_MESA_copy_sub_buffer 2729 */ 2730#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */ 2731static void 2732__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable, 2733 int x, int y, int width, int height) 2734{ 2735 xGLXVendorPrivateReq *req; 2736 GLXContext gc; 2737 GLXContextTag tag; 2738 CARD32 *drawable_ptr; 2739 INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr; 2740 CARD8 opcode; 2741 2742#ifdef __DRI_COPY_SUB_BUFFER 2743 int screen; 2744 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2745 if (pdraw != NULL) { 2746 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2747 if (psc->driScreen->copySubBuffer != NULL) { 2748 glFlush(); 2749 (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height); 2750 } 2751 2752 return; 2753 } 2754#endif 2755 2756 opcode = __glXSetupForCommand(dpy); 2757 if (!opcode) 2758 return; 2759 2760 /* 2761 ** The calling thread may or may not have a current context. If it 2762 ** does, send the context tag so the server can do a flush. 2763 */ 2764 gc = __glXGetCurrentContext(); 2765 if ((gc != NULL) && (dpy == gc->currentDpy) && 2766 ((drawable == gc->currentDrawable) || 2767 (drawable == gc->currentReadable))) { 2768 tag = gc->currentContextTag; 2769 } 2770 else { 2771 tag = 0; 2772 } 2773 2774 LockDisplay(dpy); 2775 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req); 2776 req->reqType = opcode; 2777 req->glxCode = X_GLXVendorPrivate; 2778 req->vendorCode = X_GLXvop_CopySubBufferMESA; 2779 req->contextTag = tag; 2780 2781 drawable_ptr = (CARD32 *) (req + 1); 2782 x_ptr = (INT32 *) (drawable_ptr + 1); 2783 y_ptr = (INT32 *) (drawable_ptr + 2); 2784 w_ptr = (INT32 *) (drawable_ptr + 3); 2785 h_ptr = (INT32 *) (drawable_ptr + 4); 2786 2787 *drawable_ptr = drawable; 2788 *x_ptr = x; 2789 *y_ptr = y; 2790 *w_ptr = width; 2791 *h_ptr = height; 2792 2793 UnlockDisplay(dpy); 2794 SyncHandle(); 2795} 2796 2797 2798/** 2799 * GLX_EXT_texture_from_pixmap 2800 */ 2801/*@{*/ 2802static void 2803__glXBindTexImageEXT(Display * dpy, 2804 GLXDrawable drawable, int buffer, const int *attrib_list) 2805{ 2806 xGLXVendorPrivateReq *req; 2807 GLXContext gc = __glXGetCurrentContext(); 2808 CARD32 *drawable_ptr; 2809 INT32 *buffer_ptr; 2810 CARD32 *num_attrib_ptr; 2811 CARD32 *attrib_ptr; 2812 CARD8 opcode; 2813 unsigned int i; 2814 2815 if (gc == NULL) 2816 return; 2817 2818 i = 0; 2819 if (attrib_list) { 2820 while (attrib_list[i * 2] != None) 2821 i++; 2822 } 2823 2824#ifdef GLX_DIRECT_RENDERING 2825 if (gc->driContext) { 2826 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); 2827 2828 if (pdraw != NULL) { 2829 if (pdraw->psc->texBuffer->base.version >= 2 && 2830 pdraw->psc->texBuffer->setTexBuffer2 != NULL) { 2831 (*pdraw->psc->texBuffer->setTexBuffer2) (gc->__driContext, 2832 pdraw->textureTarget, 2833 pdraw->textureFormat, 2834 pdraw->driDrawable); 2835 } 2836 else { 2837 (*pdraw->psc->texBuffer->setTexBuffer) (gc->__driContext, 2838 pdraw->textureTarget, 2839 pdraw->driDrawable); 2840 } 2841 } 2842 return; 2843 } 2844#endif 2845 2846 opcode = __glXSetupForCommand(dpy); 2847 if (!opcode) 2848 return; 2849 2850 LockDisplay(dpy); 2851 GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req); 2852 req->reqType = opcode; 2853 req->glxCode = X_GLXVendorPrivate; 2854 req->vendorCode = X_GLXvop_BindTexImageEXT; 2855 req->contextTag = gc->currentContextTag; 2856 2857 drawable_ptr = (CARD32 *) (req + 1); 2858 buffer_ptr = (INT32 *) (drawable_ptr + 1); 2859 num_attrib_ptr = (CARD32 *) (buffer_ptr + 1); 2860 attrib_ptr = (CARD32 *) (num_attrib_ptr + 1); 2861 2862 *drawable_ptr = drawable; 2863 *buffer_ptr = buffer; 2864 *num_attrib_ptr = (CARD32) i; 2865 2866 i = 0; 2867 if (attrib_list) { 2868 while (attrib_list[i * 2] != None) { 2869 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0]; 2870 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1]; 2871 i++; 2872 } 2873 } 2874 2875 UnlockDisplay(dpy); 2876 SyncHandle(); 2877} 2878 2879static void 2880__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer) 2881{ 2882 xGLXVendorPrivateReq *req; 2883 GLXContext gc = __glXGetCurrentContext(); 2884 CARD32 *drawable_ptr; 2885 INT32 *buffer_ptr; 2886 CARD8 opcode; 2887 2888 if ((gc == NULL) || GC_IS_DIRECT(gc)) 2889 return; 2890 2891 opcode = __glXSetupForCommand(dpy); 2892 if (!opcode) 2893 return; 2894 2895 LockDisplay(dpy); 2896 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req); 2897 req->reqType = opcode; 2898 req->glxCode = X_GLXVendorPrivate; 2899 req->vendorCode = X_GLXvop_ReleaseTexImageEXT; 2900 req->contextTag = gc->currentContextTag; 2901 2902 drawable_ptr = (CARD32 *) (req + 1); 2903 buffer_ptr = (INT32 *) (drawable_ptr + 1); 2904 2905 *drawable_ptr = drawable; 2906 *buffer_ptr = buffer; 2907 2908 UnlockDisplay(dpy); 2909 SyncHandle(); 2910} 2911 2912/*@}*/ 2913 2914/** 2915 * \c strdup is actually not a standard ANSI C or POSIX routine. 2916 * Irix will not define it if ANSI mode is in effect. 2917 * 2918 * \sa strdup 2919 */ 2920_X_HIDDEN char * 2921__glXstrdup(const char *str) 2922{ 2923 char *copy; 2924 copy = (char *) Xmalloc(strlen(str) + 1); 2925 if (!copy) 2926 return NULL; 2927 strcpy(copy, str); 2928 return copy; 2929} 2930 2931/* 2932** glXGetProcAddress support 2933*/ 2934 2935struct name_address_pair 2936{ 2937 const char *Name; 2938 GLvoid *Address; 2939}; 2940 2941#define GLX_FUNCTION(f) { # f, (GLvoid *) f } 2942#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f } 2943 2944static const struct name_address_pair GLX_functions[] = { 2945 /*** GLX_VERSION_1_0 ***/ 2946 GLX_FUNCTION(glXChooseVisual), 2947 GLX_FUNCTION(glXCopyContext), 2948 GLX_FUNCTION(glXCreateContext), 2949 GLX_FUNCTION(glXCreateGLXPixmap), 2950 GLX_FUNCTION(glXDestroyContext), 2951 GLX_FUNCTION(glXDestroyGLXPixmap), 2952 GLX_FUNCTION(glXGetConfig), 2953 GLX_FUNCTION(glXGetCurrentContext), 2954 GLX_FUNCTION(glXGetCurrentDrawable), 2955 GLX_FUNCTION(glXIsDirect), 2956 GLX_FUNCTION(glXMakeCurrent), 2957 GLX_FUNCTION(glXQueryExtension), 2958 GLX_FUNCTION(glXQueryVersion), 2959 GLX_FUNCTION(glXSwapBuffers), 2960 GLX_FUNCTION(glXUseXFont), 2961 GLX_FUNCTION(glXWaitGL), 2962 GLX_FUNCTION(glXWaitX), 2963 2964 /*** GLX_VERSION_1_1 ***/ 2965 GLX_FUNCTION(glXGetClientString), 2966 GLX_FUNCTION(glXQueryExtensionsString), 2967 GLX_FUNCTION(glXQueryServerString), 2968 2969 /*** GLX_VERSION_1_2 ***/ 2970 GLX_FUNCTION(glXGetCurrentDisplay), 2971 2972 /*** GLX_VERSION_1_3 ***/ 2973 GLX_FUNCTION(glXChooseFBConfig), 2974 GLX_FUNCTION(glXCreateNewContext), 2975 GLX_FUNCTION(glXCreatePbuffer), 2976 GLX_FUNCTION(glXCreatePixmap), 2977 GLX_FUNCTION(glXCreateWindow), 2978 GLX_FUNCTION(glXDestroyPbuffer), 2979 GLX_FUNCTION(glXDestroyPixmap), 2980 GLX_FUNCTION(glXDestroyWindow), 2981 GLX_FUNCTION(glXGetCurrentReadDrawable), 2982 GLX_FUNCTION(glXGetFBConfigAttrib), 2983 GLX_FUNCTION(glXGetFBConfigs), 2984 GLX_FUNCTION(glXGetSelectedEvent), 2985 GLX_FUNCTION(glXGetVisualFromFBConfig), 2986 GLX_FUNCTION(glXMakeContextCurrent), 2987 GLX_FUNCTION(glXQueryContext), 2988 GLX_FUNCTION(glXQueryDrawable), 2989 GLX_FUNCTION(glXSelectEvent), 2990 2991 /*** GLX_SGI_swap_control ***/ 2992 GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI), 2993 2994 /*** GLX_SGI_video_sync ***/ 2995 GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI), 2996 GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI), 2997 2998 /*** GLX_SGI_make_current_read ***/ 2999 GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent), 3000 GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable), 3001 3002 /*** GLX_EXT_import_context ***/ 3003 GLX_FUNCTION(glXFreeContextEXT), 3004 GLX_FUNCTION(glXGetContextIDEXT), 3005 GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay), 3006 GLX_FUNCTION(glXImportContextEXT), 3007 GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext), 3008 3009 /*** GLX_SGIX_fbconfig ***/ 3010 GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib), 3011 GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig), 3012 GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX), 3013 GLX_FUNCTION(glXCreateContextWithConfigSGIX), 3014 GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig), 3015 GLX_FUNCTION(glXGetFBConfigFromVisualSGIX), 3016 3017 /*** GLX_SGIX_pbuffer ***/ 3018 GLX_FUNCTION(glXCreateGLXPbufferSGIX), 3019 GLX_FUNCTION(glXDestroyGLXPbufferSGIX), 3020 GLX_FUNCTION(glXQueryGLXPbufferSGIX), 3021 GLX_FUNCTION(glXSelectEventSGIX), 3022 GLX_FUNCTION(glXGetSelectedEventSGIX), 3023 3024 /*** GLX_SGIX_swap_group ***/ 3025 GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX), 3026 3027 /*** GLX_SGIX_swap_barrier ***/ 3028 GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX), 3029 GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX), 3030 3031 /*** GLX_MESA_allocate_memory ***/ 3032 GLX_FUNCTION(glXAllocateMemoryMESA), 3033 GLX_FUNCTION(glXFreeMemoryMESA), 3034 GLX_FUNCTION(glXGetMemoryOffsetMESA), 3035 3036 /*** GLX_MESA_copy_sub_buffer ***/ 3037 GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA), 3038 3039 /*** GLX_MESA_pixmap_colormap ***/ 3040 GLX_FUNCTION(glXCreateGLXPixmapMESA), 3041 3042 /*** GLX_MESA_release_buffers ***/ 3043 GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA), 3044 3045 /*** GLX_MESA_swap_control ***/ 3046 GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA), 3047 GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA), 3048 3049 /*** GLX_MESA_swap_frame_usage ***/ 3050 GLX_FUNCTION2(glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA), 3051 GLX_FUNCTION2(glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA), 3052 GLX_FUNCTION2(glXGetFrameUsageMESA, __glXGetFrameUsageMESA), 3053 GLX_FUNCTION2(glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA), 3054 3055 /*** GLX_ARB_get_proc_address ***/ 3056 GLX_FUNCTION(glXGetProcAddressARB), 3057 3058 /*** GLX 1.4 ***/ 3059 GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB), 3060 3061 /*** GLX_OML_sync_control ***/ 3062 GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML), 3063 GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML), 3064 GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML), 3065 GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML), 3066 GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML), 3067 3068 /*** GLX_EXT_texture_from_pixmap ***/ 3069 GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT), 3070 GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT), 3071 3072#ifdef GLX_DIRECT_RENDERING 3073 /*** DRI configuration ***/ 3074 GLX_FUNCTION(glXGetScreenDriver), 3075 GLX_FUNCTION(glXGetDriverConfig), 3076#endif 3077 3078 {NULL, NULL} /* end of list */ 3079}; 3080 3081 3082static const GLvoid * 3083get_glx_proc_address(const char *funcName) 3084{ 3085 GLuint i; 3086 3087 /* try static functions */ 3088 for (i = 0; GLX_functions[i].Name; i++) { 3089 if (strcmp(GLX_functions[i].Name, funcName) == 0) 3090 return GLX_functions[i].Address; 3091 } 3092 3093 return NULL; 3094} 3095 3096 3097/** 3098 * Get the address of a named GL function. This is the pre-GLX 1.4 name for 3099 * \c glXGetProcAddress. 3100 * 3101 * \param procName Name of a GL or GLX function. 3102 * \returns A pointer to the named function 3103 * 3104 * \sa glXGetProcAddress 3105 */ 3106PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void) 3107{ 3108 typedef void (*gl_function) (void); 3109 gl_function f; 3110 3111 3112 /* Search the table of GLX and internal functions first. If that 3113 * fails and the supplied name could be a valid core GL name, try 3114 * searching the core GL function table. This check is done to prevent 3115 * DRI based drivers from searching the core GL function table for 3116 * internal API functions. 3117 */ 3118 3119 f = (gl_function) get_glx_proc_address((const char *) procName); 3120 if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l') 3121 && (procName[2] != 'X')) { 3122 f = (gl_function) _glapi_get_proc_address((const char *) procName); 3123 } 3124 3125 return f; 3126} 3127 3128/** 3129 * Get the address of a named GL function. This is the GLX 1.4 name for 3130 * \c glXGetProcAddressARB. 3131 * 3132 * \param procName Name of a GL or GLX function. 3133 * \returns A pointer to the named function 3134 * 3135 * \sa glXGetProcAddressARB 3136 */ 3137PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void) 3138#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED) 3139 __attribute__ ((alias("glXGetProcAddressARB"))); 3140#else 3141{ 3142 return glXGetProcAddressARB(procName); 3143} 3144#endif /* __GNUC__ */ 3145 3146 3147#ifdef GLX_DIRECT_RENDERING 3148/** 3149 * Get the unadjusted system time (UST). Currently, the UST is measured in 3150 * microseconds since Epoc. The actual resolution of the UST may vary from 3151 * system to system, and the units may vary from release to release. 3152 * Drivers should not call this function directly. They should instead use 3153 * \c glXGetProcAddress to obtain a pointer to the function. 3154 * 3155 * \param ust Location to store the 64-bit UST 3156 * \returns Zero on success or a negative errno value on failure. 3157 * 3158 * \sa glXGetProcAddress, PFNGLXGETUSTPROC 3159 * 3160 * \since Internal API version 20030317. 3161 */ 3162_X_HIDDEN int 3163__glXGetUST(int64_t * ust) 3164{ 3165 struct timeval tv; 3166 3167 if (ust == NULL) { 3168 return -EFAULT; 3169 } 3170 3171 if (gettimeofday(&tv, NULL) == 0) { 3172 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; 3173 return 0; 3174 } 3175 else { 3176 return -errno; 3177 } 3178} 3179#endif /* GLX_DIRECT_RENDERING */ 3180