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