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