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