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