glxcmds.c revision f972115d33e391499e049b83a1559959f2ca9f72
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"; 65static const struct glx_context_vtable glx_indirect_context_vtable; 66 67#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 68 69static Bool windowExistsFlag; 70static int 71windowExistsErrorHandler(Display * dpy, XErrorEvent * xerr) 72{ 73 (void) dpy; 74 75 if (xerr->error_code == BadWindow) { 76 windowExistsFlag = GL_FALSE; 77 } 78 return 0; 79} 80 81/** 82 * Find drawables in the local hash that have been destroyed on the 83 * server. 84 * 85 * \param dpy Display to destroy drawables for 86 * \param screen Screen number to destroy drawables for 87 */ 88static void 89GarbageCollectDRIDrawables(Display * dpy, __GLXscreenConfigs * sc) 90{ 91 XID draw; 92 __GLXDRIdrawable *pdraw; 93 XWindowAttributes xwa; 94 int (*oldXErrorHandler) (Display *, XErrorEvent *); 95 96 /* Set no-op error handler so Xlib doesn't bail out if the windows 97 * has alreay been destroyed on the server. */ 98 XSync(dpy, GL_FALSE); 99 oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler); 100 101 if (__glxHashFirst(sc->drawHash, &draw, (void *) &pdraw) == 1) { 102 do { 103 windowExistsFlag = GL_TRUE; 104 XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */ 105 if (!windowExistsFlag) { 106 /* Destroy the local drawable data, if the drawable no 107 longer exists in the Xserver */ 108 (*pdraw->destroyDrawable) (pdraw); 109 __glxHashDelete(sc->drawHash, draw); 110 } 111 } while (__glxHashNext(sc->drawHash, &draw, (void *) &pdraw) == 1); 112 } 113 114 XSync(dpy, GL_FALSE); 115 XSetErrorHandler(oldXErrorHandler); 116} 117 118/** 119 * Get the __DRIdrawable for the drawable associated with a GLXContext 120 * 121 * \param dpy The display associated with \c drawable. 122 * \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved. 123 * \param scrn_num If non-NULL, the drawables screen is stored there 124 * \returns A pointer to the context's __DRIdrawable on success, or NULL if 125 * the drawable is not associated with a direct-rendering context. 126 */ 127_X_HIDDEN __GLXDRIdrawable * 128GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable, int *const scrn_num) 129{ 130 __GLXdisplayPrivate *priv = __glXInitialize(dpy); 131 __GLXDRIdrawable *pdraw; 132 const unsigned screen_count = ScreenCount(dpy); 133 unsigned i; 134 __GLXscreenConfigs *psc; 135 136 if (priv == NULL) 137 return NULL; 138 139 for (i = 0; i < screen_count; i++) { 140 psc = priv->screenConfigs[i]; 141 if (psc->drawHash == NULL) 142 continue; 143 144 if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) { 145 if (scrn_num != NULL) 146 *scrn_num = i; 147 return pdraw; 148 } 149 } 150 151 return NULL; 152} 153 154#endif 155 156 157/** 158 * Get the GLX per-screen data structure associated with a GLX context. 159 * 160 * \param dpy Display for which the GLX per-screen information is to be 161 * retrieved. 162 * \param scrn Screen on \c dpy for which the GLX per-screen information is 163 * to be retrieved. 164 * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn 165 * specify a valid GLX screen, or NULL otherwise. 166 * 167 * \todo Should this function validate that \c scrn is within the screen 168 * number range for \c dpy? 169 */ 170 171static __GLXscreenConfigs * 172GetGLXScreenConfigs(Display * dpy, int scrn) 173{ 174 __GLXdisplayPrivate *const priv = __glXInitialize(dpy); 175 176 return (priv 177 && priv->screenConfigs != 178 NULL) ? priv->screenConfigs[scrn] : NULL; 179} 180 181 182static int 183GetGLXPrivScreenConfig(Display * dpy, int scrn, __GLXdisplayPrivate ** ppriv, 184 __GLXscreenConfigs ** ppsc) 185{ 186 /* Initialize the extension, if needed . This has the added value 187 * of initializing/allocating the display private 188 */ 189 190 if (dpy == NULL) { 191 return GLX_NO_EXTENSION; 192 } 193 194 *ppriv = __glXInitialize(dpy); 195 if (*ppriv == NULL) { 196 return GLX_NO_EXTENSION; 197 } 198 199 /* Check screen number to see if its valid */ 200 if ((scrn < 0) || (scrn >= ScreenCount(dpy))) { 201 return GLX_BAD_SCREEN; 202 } 203 204 /* Check to see if the GL is supported on this screen */ 205 *ppsc = (*ppriv)->screenConfigs[scrn]; 206 if ((*ppsc)->configs == NULL) { 207 /* No support for GL on this screen regardless of visual */ 208 return GLX_BAD_VISUAL; 209 } 210 211 return Success; 212} 213 214 215/** 216 * Determine if a \c GLXFBConfig supplied by the application is valid. 217 * 218 * \param dpy Application supplied \c Display pointer. 219 * \param config Application supplied \c GLXFBConfig. 220 * 221 * \returns If the \c GLXFBConfig is valid, the a pointer to the matching 222 * \c __GLcontextModes structure is returned. Otherwise, \c NULL 223 * is returned. 224 */ 225static __GLcontextModes * 226ValidateGLXFBConfig(Display * dpy, GLXFBConfig config) 227{ 228 __GLXdisplayPrivate *const priv = __glXInitialize(dpy); 229 const unsigned num_screens = ScreenCount(dpy); 230 unsigned i; 231 const __GLcontextModes *modes; 232 233 234 if (priv != NULL) { 235 for (i = 0; i < num_screens; i++) { 236 for (modes = priv->screenConfigs[i]->configs; modes != NULL; 237 modes = modes->next) { 238 if (modes == (__GLcontextModes *) config) { 239 return (__GLcontextModes *) config; 240 } 241 } 242 } 243 } 244 245 return NULL; 246} 247 248 249/** 250 * \todo It should be possible to move the allocate of \c client_state_private 251 * later in the function for direct-rendering contexts. Direct-rendering 252 * contexts don't need to track client state, so they don't need that memory 253 * at all. 254 * 255 * \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new 256 * function called \c __glXAllocateClientState that allocates the memory and 257 * does all the initialization (including the pixel pack / unpack). 258 */ 259static GLXContext 260AllocateGLXContext(Display * dpy) 261{ 262 GLXContext gc; 263 int bufSize; 264 CARD8 opcode; 265 __GLXattribute *state; 266 267 if (!dpy) 268 return NULL; 269 270 opcode = __glXSetupForCommand(dpy); 271 if (!opcode) { 272 return NULL; 273 } 274 275 /* Allocate our context record */ 276 gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec)); 277 if (!gc) { 278 /* Out of memory */ 279 return NULL; 280 } 281 memset(gc, 0, sizeof(struct __GLXcontextRec)); 282 283 state = Xmalloc(sizeof(struct __GLXattributeRec)); 284 if (state == NULL) { 285 /* Out of memory */ 286 Xfree(gc); 287 return NULL; 288 } 289 gc->client_state_private = state; 290 memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec)); 291 state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL); 292 293 /* 294 ** Create a temporary buffer to hold GLX rendering commands. The size 295 ** of the buffer is selected so that the maximum number of GLX rendering 296 ** commands can fit in a single X packet and still have room in the X 297 ** packet for the GLXRenderReq header. 298 */ 299 300 bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq; 301 gc->buf = (GLubyte *) Xmalloc(bufSize); 302 if (!gc->buf) { 303 Xfree(gc->client_state_private); 304 Xfree(gc); 305 return NULL; 306 } 307 gc->bufSize = bufSize; 308 309 /* Fill in the new context */ 310 gc->renderMode = GL_RENDER; 311 312 state->storePack.alignment = 4; 313 state->storeUnpack.alignment = 4; 314 315 gc->attributes.stackPointer = &gc->attributes.stack[0]; 316 317 /* 318 ** PERFORMANCE NOTE: A mode dependent fill image can speed things up. 319 ** Other code uses the fastImageUnpack bit, but it is never set 320 ** to GL_TRUE. 321 */ 322 gc->fastImageUnpack = GL_FALSE; 323 gc->fillImage = __glFillImage; 324 gc->pc = gc->buf; 325 gc->bufEnd = gc->buf + bufSize; 326 gc->isDirect = GL_FALSE; 327 if (__glXDebug) { 328 /* 329 ** Set limit register so that there will be one command per packet 330 */ 331 gc->limit = gc->buf; 332 } 333 else { 334 gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE; 335 } 336 gc->createDpy = dpy; 337 gc->majorOpcode = opcode; 338 339 /* 340 ** Constrain the maximum drawing command size allowed to be 341 ** transfered using the X_GLXRender protocol request. First 342 ** constrain by a software limit, then constrain by the protocl 343 ** limit. 344 */ 345 if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) { 346 bufSize = __GLX_RENDER_CMD_SIZE_LIMIT; 347 } 348 if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) { 349 bufSize = __GLX_MAX_RENDER_CMD_SIZE; 350 } 351 gc->maxSmallRenderCommandSize = bufSize; 352 353#ifdef GLX_USE_APPLEGL 354 gc->driContext = NULL; 355 gc->do_destroy = False; 356#endif 357 358 return gc; 359} 360 361 362/** 363 * Create a new context. Exactly one of \c vis and \c fbconfig should be 364 * non-NULL. 365 * 366 * \param use_glx_1_3 For FBConfigs, should GLX 1.3 protocol or 367 * SGIX_fbconfig protocol be used? 368 * \param renderType For FBConfigs, what is the rendering type? 369 */ 370 371static GLXContext 372CreateContext(Display * dpy, int generic_id, 373 const __GLcontextModes * const fbconfig, 374 GLXContext shareList, 375 Bool allowDirect, 376 unsigned code, int renderType, int screen) 377{ 378 GLXContext gc; 379 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 380#if defined(GLX_DIRECT_RENDERING) && defined(GLX_USE_APPLEGL) 381 int errorcode; 382 bool x11error; 383#endif 384 385 if (dpy == NULL) 386 return NULL; 387 388 if (generic_id == None) 389 return NULL; 390 391 gc = AllocateGLXContext(dpy); 392 if (!gc) 393 return NULL; 394 395#ifndef GLX_USE_APPLEGL /* TODO: darwin indirect */ 396#ifdef GLX_DIRECT_RENDERING 397 if (allowDirect && psc->driScreen) { 398 gc->driContext = psc->driScreen->createContext(psc, fbconfig, gc, 399 shareList, renderType); 400 if (gc->driContext != NULL) { 401 gc->screen = screen; 402 gc->psc = psc; 403 gc->mode = fbconfig; 404 gc->isDirect = GL_TRUE; 405 } 406 } 407#endif 408 409 if (gc->driContext != NULL) 410 gc->vtable = psc->direct_context_vtable; 411 else 412 gc->vtable = &glx_indirect_context_vtable; 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 1770 /* Look up screen first so we can look up visuals/fbconfigs later */ 1771 pProp = propList; 1772 for (i = 0; i < numValues; i++, pProp += 2) 1773 if (pProp[0] == GLX_SCREEN) { 1774 ctx->screen = pProp[1]; 1775 ctx->psc = GetGLXScreenConfigs(dpy, ctx->screen); 1776 } 1777 1778 pProp = propList; 1779 for (i = 0; i < numValues; i++) { 1780 switch (*pProp++) { 1781 case GLX_SHARE_CONTEXT_EXT: 1782 ctx->share_xid = *pProp++; 1783 break; 1784 case GLX_VISUAL_ID_EXT: 1785 ctx->mode = 1786 _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++); 1787 break; 1788 case GLX_FBCONFIG_ID: 1789 ctx->mode = 1790 _gl_context_modes_find_fbconfig(ctx->psc->configs, 1791 *pProp++); 1792 break; 1793 case GLX_RENDER_TYPE: 1794 ctx->renderType = *pProp++; 1795 break; 1796 case GLX_SCREEN: 1797 default: 1798 pProp++; 1799 continue; 1800 } 1801 } 1802 Xfree((char *) propList); 1803 retval = Success; 1804 } 1805 } 1806 UnlockDisplay(dpy); 1807 SyncHandle(); 1808 return retval; 1809} 1810 1811#endif 1812 1813PUBLIC int 1814glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int *value) 1815{ 1816#ifndef GLX_USE_APPLEGL 1817 int retVal; 1818 1819 /* get the information from the server if we don't have it already */ 1820#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 1821 if (!ctx->driContext && (ctx->mode == NULL)) { 1822#else 1823 if (ctx->mode == NULL) { 1824#endif 1825 retVal = __glXQueryContextInfo(dpy, ctx); 1826 if (Success != retVal) 1827 return retVal; 1828 } 1829#endif 1830 1831 switch (attribute) { 1832#ifndef GLX_USE_APPLEGL 1833 case GLX_SHARE_CONTEXT_EXT: 1834 *value = (int) (ctx->share_xid); 1835 break; 1836 case GLX_VISUAL_ID_EXT: 1837 *value = ctx->mode ? ctx->mode->visualID : None; 1838 break; 1839#endif 1840 case GLX_SCREEN: 1841 *value = (int) (ctx->screen); 1842 break; 1843 case GLX_FBCONFIG_ID: 1844 *value = ctx->mode ? ctx->mode->fbconfigID : None; 1845 break; 1846 case GLX_RENDER_TYPE: 1847 *value = (int) (ctx->renderType); 1848 break; 1849 default: 1850 return GLX_BAD_ATTRIBUTE; 1851 } 1852 return Success; 1853} 1854 1855PUBLIC 1856GLX_ALIAS(int, glXQueryContextInfoEXT, 1857 (Display * dpy, GLXContext ctx, int attribute, int *value), 1858 (dpy, ctx, attribute, value), glXQueryContext) 1859 1860PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx) 1861{ 1862 return ctx->xid; 1863} 1864 1865PUBLIC GLXContext 1866glXImportContextEXT(Display * dpy, GLXContextID contextID) 1867{ 1868#ifdef GLX_USE_APPLEGL 1869 return NULL; 1870#else 1871 GLXContext ctx; 1872 1873 if (contextID == None) { 1874 return NULL; 1875 } 1876 if (__glXIsDirect(dpy, contextID)) { 1877 return NULL; 1878 } 1879 1880 ctx = AllocateGLXContext(dpy); 1881 if (NULL != ctx) { 1882 ctx->xid = contextID; 1883 ctx->imported = GL_TRUE; 1884 1885 if (Success != __glXQueryContextInfo(dpy, ctx)) { 1886 __glXFreeContext(ctx); 1887 ctx = NULL; 1888 } 1889 } 1890 return ctx; 1891#endif 1892} 1893 1894PUBLIC void 1895glXFreeContextEXT(Display * dpy, GLXContext ctx) 1896{ 1897 DestroyContext(dpy, ctx); 1898} 1899 1900 1901 1902/* 1903 * GLX 1.3 functions - these are just stubs for now! 1904 */ 1905 1906PUBLIC GLXFBConfig * 1907glXChooseFBConfig(Display * dpy, int screen, 1908 const int *attribList, int *nitems) 1909{ 1910 __GLcontextModes **config_list; 1911 int list_size; 1912 1913 1914 config_list = (__GLcontextModes **) 1915 glXGetFBConfigs(dpy, screen, &list_size); 1916 1917 if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) { 1918 list_size = choose_visual(config_list, list_size, attribList, GL_TRUE); 1919 if (list_size == 0) { 1920 XFree(config_list); 1921 config_list = NULL; 1922 } 1923 } 1924 1925 *nitems = list_size; 1926 return (GLXFBConfig *) config_list; 1927} 1928 1929 1930PUBLIC GLXContext 1931glXCreateNewContext(Display * dpy, GLXFBConfig config, 1932 int renderType, GLXContext shareList, Bool allowDirect) 1933{ 1934 const __GLcontextModes *const fbconfig = 1935 (const __GLcontextModes *const) config; 1936 1937 return CreateContext(dpy, fbconfig->fbconfigID, fbconfig, shareList, 1938 allowDirect, X_GLXCreateNewContext, renderType, 1939 fbconfig->screen); 1940} 1941 1942 1943PUBLIC GLXDrawable 1944glXGetCurrentReadDrawable(void) 1945{ 1946 GLXContext gc = __glXGetCurrentContext(); 1947 return gc->currentReadable; 1948} 1949 1950 1951PUBLIC GLXFBConfig * 1952glXGetFBConfigs(Display * dpy, int screen, int *nelements) 1953{ 1954 __GLXdisplayPrivate *priv = __glXInitialize(dpy); 1955 __GLcontextModes **config = NULL; 1956 int i; 1957 1958 *nelements = 0; 1959 if (priv && (priv->screenConfigs != NULL) 1960 && (screen >= 0) && (screen <= ScreenCount(dpy)) 1961 && (priv->screenConfigs[screen]->configs != NULL) 1962 && (priv->screenConfigs[screen]->configs->fbconfigID 1963 != (int) GLX_DONT_CARE)) { 1964 unsigned num_configs = 0; 1965 __GLcontextModes *modes; 1966 1967 1968 for (modes = priv->screenConfigs[screen]->configs; modes != NULL; 1969 modes = modes->next) { 1970 if (modes->fbconfigID != (int) GLX_DONT_CARE) { 1971 num_configs++; 1972 } 1973 } 1974 1975 config = (__GLcontextModes **) Xmalloc(sizeof(__GLcontextModes *) 1976 * num_configs); 1977 if (config != NULL) { 1978 *nelements = num_configs; 1979 i = 0; 1980 for (modes = priv->screenConfigs[screen]->configs; modes != NULL; 1981 modes = modes->next) { 1982 if (modes->fbconfigID != (int) GLX_DONT_CARE) { 1983 config[i] = modes; 1984 i++; 1985 } 1986 } 1987 } 1988 } 1989 return (GLXFBConfig *) config; 1990} 1991 1992 1993PUBLIC int 1994glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config, 1995 int attribute, int *value) 1996{ 1997 __GLcontextModes *const modes = ValidateGLXFBConfig(dpy, config); 1998 1999 return (modes != NULL) 2000 ? _gl_get_context_mode_data(modes, attribute, value) 2001 : GLXBadFBConfig; 2002} 2003 2004 2005PUBLIC XVisualInfo * 2006glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config) 2007{ 2008 XVisualInfo visualTemplate; 2009 __GLcontextModes *fbconfig = (__GLcontextModes *) config; 2010 int count; 2011 2012 /* 2013 ** Get a list of all visuals, return if list is empty 2014 */ 2015 visualTemplate.visualid = fbconfig->visualID; 2016 return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count); 2017} 2018 2019#ifndef GLX_USE_APPLEGL 2020/* 2021** GLX_SGI_swap_control 2022*/ 2023static int 2024__glXSwapIntervalSGI(int interval) 2025{ 2026 xGLXVendorPrivateReq *req; 2027 GLXContext gc = __glXGetCurrentContext(); 2028 __GLXscreenConfigs *psc; 2029 Display *dpy; 2030 CARD32 *interval_ptr; 2031 CARD8 opcode; 2032 2033 if (gc == NULL) { 2034 return GLX_BAD_CONTEXT; 2035 } 2036 2037 if (interval <= 0) { 2038 return GLX_BAD_VALUE; 2039 } 2040 2041#ifdef __DRI_SWAP_CONTROL 2042 if (gc->driContext) { 2043 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, 2044 gc->screen ); 2045 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 2046 gc->currentDrawable, 2047 NULL); 2048 if (psc->swapControl != NULL && pdraw != NULL) { 2049 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); 2050 return 0; 2051 } 2052 else if (pdraw == NULL) { 2053 return GLX_BAD_CONTEXT; 2054 } 2055 } 2056#endif 2057 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 2058 2059#ifdef GLX_DIRECT_RENDERING 2060 if (gc->driContext && psc->driScreen && psc->driScreen->setSwapInterval) { 2061 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 2062 gc->currentDrawable, 2063 NULL); 2064 psc->driScreen->setSwapInterval(pdraw, interval); 2065 return 0; 2066 } 2067#endif 2068 2069 dpy = gc->currentDpy; 2070 opcode = __glXSetupForCommand(dpy); 2071 if (!opcode) { 2072 return 0; 2073 } 2074 2075 /* Send the glXSwapIntervalSGI request */ 2076 LockDisplay(dpy); 2077 GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req); 2078 req->reqType = opcode; 2079 req->glxCode = X_GLXVendorPrivate; 2080 req->vendorCode = X_GLXvop_SwapIntervalSGI; 2081 req->contextTag = gc->currentContextTag; 2082 2083 interval_ptr = (CARD32 *) (req + 1); 2084 *interval_ptr = interval; 2085 2086 UnlockDisplay(dpy); 2087 SyncHandle(); 2088 XFlush(dpy); 2089 2090 return 0; 2091} 2092 2093 2094/* 2095** GLX_MESA_swap_control 2096*/ 2097static int 2098__glXSwapIntervalMESA(unsigned int interval) 2099{ 2100 GLXContext gc = __glXGetCurrentContext(); 2101 2102#ifdef __DRI_SWAP_CONTROL 2103 if (gc != NULL && gc->driContext) { 2104 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, 2105 gc->screen); 2106 2107 if ((psc != NULL) && (psc->driScreen != NULL)) { 2108 __GLXDRIdrawable *pdraw = 2109 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2110 if (psc->swapControl != NULL && pdraw != NULL) { 2111 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); 2112 return 0; 2113 } 2114 } 2115 } 2116#endif 2117 2118#ifdef GLX_DIRECT_RENDERING 2119 if (gc != NULL && gc->driContext) { 2120 __GLXscreenConfigs *psc; 2121 2122 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 2123 if (psc->driScreen && psc->driScreen->setSwapInterval) { 2124 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 2125 gc->currentDrawable, NULL); 2126 psc->driScreen->setSwapInterval(pdraw, interval); 2127 return 0; 2128 } 2129 } 2130#endif 2131 2132 return GLX_BAD_CONTEXT; 2133} 2134 2135 2136static int 2137__glXGetSwapIntervalMESA(void) 2138{ 2139#ifdef __DRI_SWAP_CONTROL 2140 GLXContext gc = __glXGetCurrentContext(); 2141 2142 if (gc != NULL && gc->driContext) { 2143 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, 2144 gc->screen); 2145 2146 if ((psc != NULL) && (psc->driScreen != NULL)) { 2147 __GLXDRIdrawable *pdraw = 2148 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2149 if (psc->swapControl != NULL && pdraw != NULL) { 2150 return psc->swapControl->getSwapInterval(pdraw->driDrawable); 2151 } 2152 } 2153 } 2154#endif 2155 2156#ifdef GLX_DIRECT_RENDERING 2157 if (gc != NULL && gc->driContext) { 2158 __GLXscreenConfigs *psc; 2159 2160 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 2161 if (psc->driScreen && psc->driScreen->getSwapInterval) { 2162 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, 2163 gc->currentDrawable, NULL); 2164 return psc->driScreen->getSwapInterval(pdraw); 2165 } 2166 } 2167#endif 2168 2169 return 0; 2170} 2171 2172 2173/* 2174** GLX_MESA_swap_frame_usage 2175*/ 2176 2177static GLint 2178__glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable) 2179{ 2180 int status = GLX_BAD_CONTEXT; 2181#ifdef __DRI_FRAME_TRACKING 2182 int screen = 0; 2183 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2184 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2185 2186 if (pdraw != NULL && psc->frameTracking != NULL) 2187 status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE); 2188#else 2189 (void) dpy; 2190 (void) drawable; 2191#endif 2192 return status; 2193} 2194 2195 2196static GLint 2197__glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable) 2198{ 2199 int status = GLX_BAD_CONTEXT; 2200#ifdef __DRI_FRAME_TRACKING 2201 int screen = 0; 2202 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2203 __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen); 2204 2205 if (pdraw != NULL && psc->frameTracking != NULL) 2206 status = psc->frameTracking->frameTracking(pdraw->driDrawable, 2207 GL_FALSE); 2208#else 2209 (void) dpy; 2210 (void) drawable; 2211#endif 2212 return status; 2213} 2214 2215 2216static GLint 2217__glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage) 2218{ 2219 int status = GLX_BAD_CONTEXT; 2220#ifdef __DRI_FRAME_TRACKING 2221 int screen = 0; 2222 __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2223 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2224 2225 if (pdraw != NULL && psc->frameTracking != NULL) { 2226 int64_t sbc, missedFrames; 2227 float lastMissedUsage; 2228 2229 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, 2230 &sbc, 2231 &missedFrames, 2232 &lastMissedUsage, 2233 usage); 2234 } 2235#else 2236 (void) dpy; 2237 (void) drawable; 2238 (void) usage; 2239#endif 2240 return status; 2241} 2242 2243 2244static GLint 2245__glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable, 2246 int64_t * sbc, int64_t * missedFrames, 2247 GLfloat * lastMissedUsage) 2248{ 2249 int status = GLX_BAD_CONTEXT; 2250#ifdef __DRI_FRAME_TRACKING 2251 int screen = 0; 2252 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2253 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2254 2255 if (pdraw != NULL && psc->frameTracking != NULL) { 2256 float usage; 2257 2258 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, 2259 sbc, missedFrames, 2260 lastMissedUsage, 2261 &usage); 2262 } 2263#else 2264 (void) dpy; 2265 (void) drawable; 2266 (void) sbc; 2267 (void) missedFrames; 2268 (void) lastMissedUsage; 2269#endif 2270 return status; 2271} 2272 2273 2274/* 2275** GLX_SGI_video_sync 2276*/ 2277static int 2278__glXGetVideoSyncSGI(unsigned int *count) 2279{ 2280 int64_t ust, msc, sbc; 2281 int ret; 2282 GLXContext gc = __glXGetCurrentContext(); 2283 __GLXscreenConfigs *psc; 2284#ifdef GLX_DIRECT_RENDERING 2285 __GLXDRIdrawable *pdraw; 2286#endif 2287 2288 if (!gc) 2289 return GLX_BAD_CONTEXT; 2290 2291#ifdef GLX_DIRECT_RENDERING 2292 if (!gc->driContext) 2293 return GLX_BAD_CONTEXT; 2294#endif 2295 2296 psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen); 2297#ifdef GLX_DIRECT_RENDERING 2298 pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2299#endif 2300 2301 /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry, 2302 * FIXME: there should be a GLX encoding for this call. I can find no 2303 * FIXME: documentation for the GLX encoding. 2304 */ 2305#ifdef __DRI_MEDIA_STREAM_COUNTER 2306 if ( psc->msc && psc->driScreen ) { 2307 ret = (*psc->msc->getDrawableMSC)(psc->__driScreen, 2308 pdraw->driDrawable, &msc); 2309 *count = (unsigned) msc; 2310 2311 return (ret == 0) ? 0 : GLX_BAD_CONTEXT; 2312 } 2313#endif 2314 2315#ifdef GLX_DIRECT_RENDERING 2316 if (psc->driScreen && psc->driScreen->getDrawableMSC) { 2317 ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc); 2318 *count = (unsigned) msc; 2319 return (ret == True) ? 0 : GLX_BAD_CONTEXT; 2320 } 2321#endif 2322 2323 return GLX_BAD_CONTEXT; 2324} 2325 2326static int 2327__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) 2328{ 2329 GLXContext gc = __glXGetCurrentContext(); 2330 __GLXscreenConfigs *psc; 2331#ifdef GLX_DIRECT_RENDERING 2332 __GLXDRIdrawable *pdraw; 2333#endif 2334 int64_t ust, msc, sbc; 2335 int ret; 2336 2337 if (divisor <= 0 || remainder < 0) 2338 return GLX_BAD_VALUE; 2339 2340 if (!gc) 2341 return GLX_BAD_CONTEXT; 2342 2343#ifdef GLX_DIRECT_RENDERING 2344 if (!gc->driContext) 2345 return GLX_BAD_CONTEXT; 2346#endif 2347 2348 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 2349#ifdef GLX_DIRECT_RENDERING 2350 pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); 2351#endif 2352 2353#ifdef __DRI_MEDIA_STREAM_COUNTER 2354 if (psc->msc != NULL && psc->driScreen ) { 2355 ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0, 2356 divisor, remainder, &msc, &sbc); 2357 *count = (unsigned) msc; 2358 return (ret == 0) ? 0 : GLX_BAD_CONTEXT; 2359 } 2360#endif 2361 2362#ifdef GLX_DIRECT_RENDERING 2363 if (psc->driScreen && psc->driScreen->waitForMSC) { 2364 ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc, 2365 &sbc); 2366 *count = (unsigned) msc; 2367 return (ret == True) ? 0 : GLX_BAD_CONTEXT; 2368 } 2369#endif 2370 2371 return GLX_BAD_CONTEXT; 2372} 2373 2374#endif /* GLX_USE_APPLEGL */ 2375 2376/* 2377** GLX_SGIX_fbconfig 2378** Many of these functions are aliased to GLX 1.3 entry points in the 2379** GLX_functions table. 2380*/ 2381 2382PUBLIC 2383GLX_ALIAS(int, glXGetFBConfigAttribSGIX, 2384 (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value), 2385 (dpy, config, attribute, value), glXGetFBConfigAttrib) 2386 2387PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX, 2388 (Display * dpy, int screen, int *attrib_list, 2389 int *nelements), (dpy, screen, attrib_list, nelements), 2390 glXChooseFBConfig) 2391 2392PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX, 2393 (Display * dpy, GLXFBConfigSGIX config), 2394 (dpy, config), glXGetVisualFromFBConfig) 2395 2396PUBLIC GLXPixmap 2397glXCreateGLXPixmapWithConfigSGIX(Display * dpy, 2398 GLXFBConfigSGIX config, 2399 Pixmap pixmap) 2400{ 2401#ifndef GLX_USE_APPLEGL 2402 xGLXVendorPrivateWithReplyReq *vpreq; 2403 xGLXCreateGLXPixmapWithConfigSGIXReq *req; 2404 GLXPixmap xid = None; 2405 CARD8 opcode; 2406 __GLXscreenConfigs *psc; 2407#endif 2408 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config; 2409 2410 2411 if ((dpy == NULL) || (config == NULL)) { 2412 return None; 2413 } 2414#ifdef GLX_USE_APPLEGL 2415 if(apple_glx_pixmap_create(dpy, fbconfig->screen, pixmap, fbconfig)) 2416 return None; 2417 return pixmap; 2418#else 2419 2420 psc = GetGLXScreenConfigs(dpy, fbconfig->screen); 2421 if ((psc != NULL) 2422 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 2423 opcode = __glXSetupForCommand(dpy); 2424 if (!opcode) { 2425 return None; 2426 } 2427 2428 /* Send the glXCreateGLXPixmapWithConfigSGIX request */ 2429 LockDisplay(dpy); 2430 GetReqExtra(GLXVendorPrivateWithReply, 2431 sz_xGLXCreateGLXPixmapWithConfigSGIXReq - 2432 sz_xGLXVendorPrivateWithReplyReq, vpreq); 2433 req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq; 2434 req->reqType = opcode; 2435 req->glxCode = X_GLXVendorPrivateWithReply; 2436 req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; 2437 req->screen = fbconfig->screen; 2438 req->fbconfig = fbconfig->fbconfigID; 2439 req->pixmap = pixmap; 2440 req->glxpixmap = xid = XAllocID(dpy); 2441 UnlockDisplay(dpy); 2442 SyncHandle(); 2443 } 2444 2445 return xid; 2446#endif 2447} 2448 2449PUBLIC GLXContext 2450glXCreateContextWithConfigSGIX(Display * dpy, 2451 GLXFBConfigSGIX config, int renderType, 2452 GLXContext shareList, Bool allowDirect) 2453{ 2454 GLXContext gc = NULL; 2455 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config; 2456 __GLXscreenConfigs *psc; 2457 2458 2459 if ((dpy == NULL) || (config == NULL)) { 2460 return None; 2461 } 2462 2463 psc = GetGLXScreenConfigs(dpy, fbconfig->screen); 2464 if ((psc != NULL) 2465 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 2466 gc = CreateContext(dpy, fbconfig->fbconfigID, fbconfig, shareList, 2467 allowDirect, 2468 X_GLXvop_CreateContextWithConfigSGIX, renderType, 2469 fbconfig->screen); 2470 } 2471 2472 return gc; 2473} 2474 2475 2476PUBLIC GLXFBConfigSGIX 2477glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis) 2478{ 2479 __GLXdisplayPrivate *priv; 2480 __GLXscreenConfigs *psc = NULL; 2481 2482 if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success) 2483 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit) 2484 && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) { 2485 return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs, 2486 vis->visualid); 2487 } 2488 2489 return NULL; 2490} 2491 2492#ifndef GLX_USE_APPLEGL 2493/* 2494** GLX_SGIX_swap_group 2495*/ 2496static void 2497__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable, 2498 GLXDrawable member) 2499{ 2500 (void) dpy; 2501 (void) drawable; 2502 (void) member; 2503} 2504 2505 2506/* 2507** GLX_SGIX_swap_barrier 2508*/ 2509static void 2510__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier) 2511{ 2512 (void) dpy; 2513 (void) drawable; 2514 (void) barrier; 2515} 2516 2517static Bool 2518__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max) 2519{ 2520 (void) dpy; 2521 (void) screen; 2522 (void) max; 2523 return False; 2524} 2525 2526 2527/* 2528** GLX_OML_sync_control 2529*/ 2530static Bool 2531__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable, 2532 int64_t * ust, int64_t * msc, int64_t * sbc) 2533{ 2534 __GLXdisplayPrivate * const priv = __glXInitialize(dpy); 2535 int i, ret; 2536#ifdef GLX_DIRECT_RENDERING 2537 __GLXDRIdrawable *pdraw; 2538#endif 2539 __GLXscreenConfigs *psc; 2540 2541 if (!priv) 2542 return False; 2543 2544#ifdef GLX_DIRECT_RENDERING 2545 pdraw = GetGLXDRIDrawable(dpy, drawable, &i); 2546#endif 2547 psc = priv->screenConfigs[i]; 2548 2549#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER) 2550 if (pdraw && psc->sbc && psc->msc) 2551 return ( (pdraw && psc->sbc && psc->msc) 2552 && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0) 2553 && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0) 2554 && (__glXGetUST(ust) == 0) ); 2555#endif 2556 2557#ifdef GLX_DIRECT_RENDERING 2558 if (pdraw && psc && psc->driScreen && psc->driScreen->getDrawableMSC) { 2559 ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc); 2560 return ret; 2561 } 2562#endif 2563 2564 return False; 2565} 2566 2567#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2568_X_HIDDEN GLboolean 2569__driGetMscRateOML(__DRIdrawable * draw, 2570 int32_t * numerator, int32_t * denominator, void *private) 2571{ 2572#ifdef XF86VIDMODE 2573 __GLXscreenConfigs *psc; 2574 XF86VidModeModeLine mode_line; 2575 int dot_clock; 2576 int i; 2577 __GLXDRIdrawable *glxDraw = private; 2578 2579 (void) draw; 2580 2581 psc = glxDraw->psc; 2582 if (XF86VidModeQueryVersion(psc->dpy, &i, &i) && 2583 XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) { 2584 unsigned n = dot_clock * 1000; 2585 unsigned d = mode_line.vtotal * mode_line.htotal; 2586 2587# define V_INTERLACE 0x010 2588# define V_DBLSCAN 0x020 2589 2590 if (mode_line.flags & V_INTERLACE) 2591 n *= 2; 2592 else if (mode_line.flags & V_DBLSCAN) 2593 d *= 2; 2594 2595 /* The OML_sync_control spec requires that if the refresh rate is a 2596 * whole number, that the returned numerator be equal to the refresh 2597 * rate and the denominator be 1. 2598 */ 2599 2600 if (n % d == 0) { 2601 n /= d; 2602 d = 1; 2603 } 2604 else { 2605 static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 }; 2606 2607 /* This is a poor man's way to reduce a fraction. It's far from 2608 * perfect, but it will work well enough for this situation. 2609 */ 2610 2611 for (i = 0; f[i] != 0; i++) { 2612 while (n % f[i] == 0 && d % f[i] == 0) { 2613 d /= f[i]; 2614 n /= f[i]; 2615 } 2616 } 2617 } 2618 2619 *numerator = n; 2620 *denominator = d; 2621 2622 return True; 2623 } 2624 else 2625 return False; 2626#else 2627 (void) draw; 2628 (void) numerator; 2629 (void) denominator; 2630 (void) private; 2631 2632 return False; 2633#endif 2634} 2635#endif 2636 2637/** 2638 * Determine the refresh rate of the specified drawable and display. 2639 * 2640 * \param dpy Display whose refresh rate is to be determined. 2641 * \param drawable Drawable whose refresh rate is to be determined. 2642 * \param numerator Numerator of the refresh rate. 2643 * \param demoninator Denominator of the refresh rate. 2644 * \return If the refresh rate for the specified display and drawable could 2645 * be calculated, True is returned. Otherwise False is returned. 2646 * 2647 * \note This function is implemented entirely client-side. A lot of other 2648 * functionality is required to export GLX_OML_sync_control, so on 2649 * XFree86 this function can be called for direct-rendering contexts 2650 * when GLX_OML_sync_control appears in the client extension string. 2651 */ 2652 2653_X_HIDDEN GLboolean 2654__glXGetMscRateOML(Display * dpy, GLXDrawable drawable, 2655 int32_t * numerator, int32_t * denominator) 2656{ 2657#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE ) 2658 __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL); 2659 2660 if (draw == NULL) 2661 return False; 2662 2663 return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw); 2664#else 2665 (void) dpy; 2666 (void) drawable; 2667 (void) numerator; 2668 (void) denominator; 2669#endif 2670 return False; 2671} 2672 2673 2674static int64_t 2675__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, 2676 int64_t target_msc, int64_t divisor, int64_t remainder) 2677{ 2678 GLXContext gc = __glXGetCurrentContext(); 2679 int screen; 2680#ifdef GLX_DIRECT_RENDERING 2681 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2682#endif 2683 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2684 2685 if (!gc) /* no GLX for this */ 2686 return -1; 2687 2688#ifdef GLX_DIRECT_RENDERING 2689 if (!pdraw || !gc->driContext) 2690 return -1; 2691#endif 2692 2693 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2694 * error", but it also says "It [glXSwapBuffersMscOML] will return a value 2695 * of -1 if the function failed because of errors detected in the input 2696 * parameters" 2697 */ 2698 if (divisor < 0 || remainder < 0 || target_msc < 0) 2699 return -1; 2700 if (divisor > 0 && remainder >= divisor) 2701 return -1; 2702 2703 if (target_msc == 0 && divisor == 0 && remainder == 0) 2704 remainder = 1; 2705 2706#ifdef __DRI_SWAP_BUFFER_COUNTER 2707 if (psc->counters != NULL) 2708 return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc, 2709 divisor, remainder); 2710#endif 2711 2712#ifdef GLX_DIRECT_RENDERING 2713 if (psc->driScreen && psc->driScreen->swapBuffers) 2714 return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor, 2715 remainder); 2716#endif 2717 2718 return -1; 2719} 2720 2721 2722static Bool 2723__glXWaitForMscOML(Display * dpy, GLXDrawable drawable, 2724 int64_t target_msc, int64_t divisor, 2725 int64_t remainder, int64_t * ust, 2726 int64_t * msc, int64_t * sbc) 2727{ 2728 int screen; 2729#ifdef GLX_DIRECT_RENDERING 2730 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2731#endif 2732 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); 2733 int ret; 2734 2735 2736 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2737 * error", but the return type in the spec is Bool. 2738 */ 2739 if (divisor < 0 || remainder < 0 || target_msc < 0) 2740 return False; 2741 if (divisor > 0 && remainder >= divisor) 2742 return False; 2743 2744#ifdef __DRI_MEDIA_STREAM_COUNTER 2745 if (pdraw != NULL && psc->msc != NULL) { 2746 ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc, 2747 divisor, remainder, msc, sbc); 2748 2749 /* __glXGetUST returns zero on success and non-zero on failure. 2750 * This function returns True on success and False on failure. 2751 */ 2752 return ((ret == 0) && (__glXGetUST(ust) == 0)); 2753 } 2754#endif 2755 2756#ifdef GLX_DIRECT_RENDERING 2757 if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) { 2758 ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder, 2759 ust, msc, sbc); 2760 return ret; 2761 } 2762#endif 2763 2764 return False; 2765} 2766 2767 2768static Bool 2769__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, 2770 int64_t target_sbc, int64_t * ust, 2771 int64_t * msc, int64_t * sbc) 2772{ 2773 int screen; 2774#ifdef GLX_DIRECT_RENDERING 2775 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2776#endif 2777 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2778 int ret; 2779 2780 /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE 2781 * error", but the return type in the spec is Bool. 2782 */ 2783 if (target_sbc < 0) 2784 return False; 2785#ifdef __DRI_SWAP_BUFFER_COUNTER 2786 if (pdraw != NULL && psc->sbc != NULL) { 2787 ret = 2788 (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc); 2789 2790 /* __glXGetUST returns zero on success and non-zero on failure. 2791 * This function returns True on success and False on failure. 2792 */ 2793 return ((ret == 0) && (__glXGetUST(ust) == 0)); 2794 } 2795#endif 2796 2797#ifdef GLX_DIRECT_RENDERING 2798 if (pdraw && psc->driScreen && psc->driScreen->waitForSBC) { 2799 ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc); 2800 return ret; 2801 } 2802#endif 2803 2804 return False; 2805} 2806 2807 2808/** 2809 * GLX_MESA_allocate_memory 2810 */ 2811/*@{*/ 2812 2813PUBLIC void * 2814glXAllocateMemoryMESA(Display * dpy, int scrn, 2815 size_t size, float readFreq, 2816 float writeFreq, float priority) 2817{ 2818#ifdef __DRI_ALLOCATE 2819 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2820 2821 if (psc && psc->allocate) 2822 return (*psc->allocate->allocateMemory) (psc->__driScreen, size, 2823 readFreq, writeFreq, priority); 2824 2825#else 2826 (void) dpy; 2827 (void) scrn; 2828 (void) size; 2829 (void) readFreq; 2830 (void) writeFreq; 2831 (void) priority; 2832#endif /* __DRI_ALLOCATE */ 2833 2834 return NULL; 2835} 2836 2837 2838PUBLIC void 2839glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer) 2840{ 2841#ifdef __DRI_ALLOCATE 2842 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2843 2844 if (psc && psc->allocate) 2845 (*psc->allocate->freeMemory) (psc->__driScreen, pointer); 2846 2847#else 2848 (void) dpy; 2849 (void) scrn; 2850 (void) pointer; 2851#endif /* __DRI_ALLOCATE */ 2852} 2853 2854 2855PUBLIC GLuint 2856glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer) 2857{ 2858#ifdef __DRI_ALLOCATE 2859 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); 2860 2861 if (psc && psc->allocate) 2862 return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer); 2863 2864#else 2865 (void) dpy; 2866 (void) scrn; 2867 (void) pointer; 2868#endif /* GLX_DIRECT_RENDERING */ 2869 2870 return ~0L; 2871} 2872 2873/*@}*/ 2874 2875 2876/** 2877 * Mesa extension stubs. These will help reduce portability problems. 2878 */ 2879/*@{*/ 2880 2881/** 2882 * Release all buffers associated with the specified GLX drawable. 2883 * 2884 * \todo 2885 * This function was intended for stand-alone Mesa. The issue there is that 2886 * the library doesn't get any notification when a window is closed. In 2887 * DRI there is a similar but slightly different issue. When GLX 1.3 is 2888 * supported, there are 3 different functions to destroy a drawable. It 2889 * should be possible to create GLX protocol (or have it determine which 2890 * protocol to use based on the type of the drawable) to have one function 2891 * do the work of 3. For the direct-rendering case, this function could 2892 * just call the driver's \c __DRIdrawableRec::destroyDrawable function. 2893 * This would reduce the frequency with which \c __driGarbageCollectDrawables 2894 * would need to be used. This really should be done as part of the new DRI 2895 * interface work. 2896 * 2897 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt 2898 * __driGarbageCollectDrawables 2899 * glXDestroyGLXPixmap 2900 * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow 2901 * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX 2902 */ 2903static Bool 2904__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d) 2905{ 2906 (void) dpy; 2907 (void) d; 2908 return False; 2909} 2910 2911 2912PUBLIC GLXPixmap 2913glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual, 2914 Pixmap pixmap, Colormap cmap) 2915{ 2916 (void) dpy; 2917 (void) visual; 2918 (void) pixmap; 2919 (void) cmap; 2920 return 0; 2921} 2922 2923/*@}*/ 2924 2925 2926/** 2927 * GLX_MESA_copy_sub_buffer 2928 */ 2929#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */ 2930static void 2931__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable, 2932 int x, int y, int width, int height) 2933{ 2934 xGLXVendorPrivateReq *req; 2935 GLXContext gc; 2936 GLXContextTag tag; 2937 CARD32 *drawable_ptr; 2938 INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr; 2939 CARD8 opcode; 2940 2941#ifdef __DRI_COPY_SUB_BUFFER 2942 int screen; 2943 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); 2944 if (pdraw != NULL) { 2945 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); 2946 if (psc->driScreen->copySubBuffer != NULL) { 2947 glFlush(); 2948 (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height); 2949 } 2950 2951 return; 2952 } 2953#endif 2954 2955 opcode = __glXSetupForCommand(dpy); 2956 if (!opcode) 2957 return; 2958 2959 /* 2960 ** The calling thread may or may not have a current context. If it 2961 ** does, send the context tag so the server can do a flush. 2962 */ 2963 gc = __glXGetCurrentContext(); 2964 if ((gc != NULL) && (dpy == gc->currentDpy) && 2965 ((drawable == gc->currentDrawable) || 2966 (drawable == gc->currentReadable))) { 2967 tag = gc->currentContextTag; 2968 } 2969 else { 2970 tag = 0; 2971 } 2972 2973 LockDisplay(dpy); 2974 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req); 2975 req->reqType = opcode; 2976 req->glxCode = X_GLXVendorPrivate; 2977 req->vendorCode = X_GLXvop_CopySubBufferMESA; 2978 req->contextTag = tag; 2979 2980 drawable_ptr = (CARD32 *) (req + 1); 2981 x_ptr = (INT32 *) (drawable_ptr + 1); 2982 y_ptr = (INT32 *) (drawable_ptr + 2); 2983 w_ptr = (INT32 *) (drawable_ptr + 3); 2984 h_ptr = (INT32 *) (drawable_ptr + 4); 2985 2986 *drawable_ptr = drawable; 2987 *x_ptr = x; 2988 *y_ptr = y; 2989 *w_ptr = width; 2990 *h_ptr = height; 2991 2992 UnlockDisplay(dpy); 2993 SyncHandle(); 2994} 2995 2996 2997/** 2998 * GLX_EXT_texture_from_pixmap 2999 */ 3000static void 3001glx_indirect_bind_tex_image(Display * dpy, 3002 GLXDrawable drawable, 3003 int buffer, const int *attrib_list) 3004{ 3005 xGLXVendorPrivateReq *req; 3006 GLXContext gc = __glXGetCurrentContext(); 3007 CARD32 *drawable_ptr; 3008 INT32 *buffer_ptr; 3009 CARD32 *num_attrib_ptr; 3010 CARD32 *attrib_ptr; 3011 CARD8 opcode; 3012 unsigned int i; 3013 3014 i = 0; 3015 if (attrib_list) { 3016 while (attrib_list[i * 2] != None) 3017 i++; 3018 } 3019 3020 opcode = __glXSetupForCommand(dpy); 3021 if (!opcode) 3022 return; 3023 3024 LockDisplay(dpy); 3025 GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req); 3026 req->reqType = opcode; 3027 req->glxCode = X_GLXVendorPrivate; 3028 req->vendorCode = X_GLXvop_BindTexImageEXT; 3029 req->contextTag = gc->currentContextTag; 3030 3031 drawable_ptr = (CARD32 *) (req + 1); 3032 buffer_ptr = (INT32 *) (drawable_ptr + 1); 3033 num_attrib_ptr = (CARD32 *) (buffer_ptr + 1); 3034 attrib_ptr = (CARD32 *) (num_attrib_ptr + 1); 3035 3036 *drawable_ptr = drawable; 3037 *buffer_ptr = buffer; 3038 *num_attrib_ptr = (CARD32) i; 3039 3040 i = 0; 3041 if (attrib_list) { 3042 while (attrib_list[i * 2] != None) { 3043 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0]; 3044 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1]; 3045 i++; 3046 } 3047 } 3048 3049 UnlockDisplay(dpy); 3050 SyncHandle(); 3051} 3052 3053static void 3054glx_indirect_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer) 3055{ 3056 xGLXVendorPrivateReq *req; 3057 GLXContext gc = __glXGetCurrentContext(); 3058 CARD32 *drawable_ptr; 3059 INT32 *buffer_ptr; 3060 CARD8 opcode; 3061 3062 opcode = __glXSetupForCommand(dpy); 3063 if (!opcode) 3064 return; 3065 3066 LockDisplay(dpy); 3067 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req); 3068 req->reqType = opcode; 3069 req->glxCode = X_GLXVendorPrivate; 3070 req->vendorCode = X_GLXvop_ReleaseTexImageEXT; 3071 req->contextTag = gc->currentContextTag; 3072 3073 drawable_ptr = (CARD32 *) (req + 1); 3074 buffer_ptr = (INT32 *) (drawable_ptr + 1); 3075 3076 *drawable_ptr = drawable; 3077 *buffer_ptr = buffer; 3078 3079 UnlockDisplay(dpy); 3080 SyncHandle(); 3081} 3082 3083static const struct glx_context_vtable glx_indirect_context_vtable = { 3084 glx_indirect_bind_tex_image, 3085 glx_indirect_release_tex_image, 3086}; 3087 3088/*@{*/ 3089static void 3090__glXBindTexImageEXT(Display * dpy, 3091 GLXDrawable drawable, int buffer, const int *attrib_list) 3092{ 3093 GLXContext gc = __glXGetCurrentContext(); 3094 3095 if (gc == NULL || gc->vtable->bind_tex_image == NULL) 3096 return; 3097 3098 gc->vtable->bind_tex_image(dpy, drawable, buffer, attrib_list); 3099} 3100 3101static void 3102__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer) 3103{ 3104 GLXContext gc = __glXGetCurrentContext(); 3105 3106 if (gc == NULL || gc->vtable->release_tex_image == NULL) 3107 return; 3108 3109 gc->vtable->release_tex_image(dpy, drawable, buffer); 3110} 3111 3112/*@}*/ 3113 3114#endif /* GLX_USE_APPLEGL */ 3115 3116/** 3117 * \c strdup is actually not a standard ANSI C or POSIX routine. 3118 * Irix will not define it if ANSI mode is in effect. 3119 * 3120 * \sa strdup 3121 */ 3122_X_HIDDEN char * 3123__glXstrdup(const char *str) 3124{ 3125 char *copy; 3126 copy = (char *) Xmalloc(strlen(str) + 1); 3127 if (!copy) 3128 return NULL; 3129 strcpy(copy, str); 3130 return copy; 3131} 3132 3133/* 3134** glXGetProcAddress support 3135*/ 3136 3137struct name_address_pair 3138{ 3139 const char *Name; 3140 GLvoid *Address; 3141}; 3142 3143#define GLX_FUNCTION(f) { # f, (GLvoid *) f } 3144#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f } 3145 3146static const struct name_address_pair GLX_functions[] = { 3147 /*** GLX_VERSION_1_0 ***/ 3148 GLX_FUNCTION(glXChooseVisual), 3149 GLX_FUNCTION(glXCopyContext), 3150 GLX_FUNCTION(glXCreateContext), 3151 GLX_FUNCTION(glXCreateGLXPixmap), 3152 GLX_FUNCTION(glXDestroyContext), 3153 GLX_FUNCTION(glXDestroyGLXPixmap), 3154 GLX_FUNCTION(glXGetConfig), 3155 GLX_FUNCTION(glXGetCurrentContext), 3156 GLX_FUNCTION(glXGetCurrentDrawable), 3157 GLX_FUNCTION(glXIsDirect), 3158 GLX_FUNCTION(glXMakeCurrent), 3159 GLX_FUNCTION(glXQueryExtension), 3160 GLX_FUNCTION(glXQueryVersion), 3161 GLX_FUNCTION(glXSwapBuffers), 3162 GLX_FUNCTION(glXUseXFont), 3163 GLX_FUNCTION(glXWaitGL), 3164 GLX_FUNCTION(glXWaitX), 3165 3166 /*** GLX_VERSION_1_1 ***/ 3167 GLX_FUNCTION(glXGetClientString), 3168 GLX_FUNCTION(glXQueryExtensionsString), 3169 GLX_FUNCTION(glXQueryServerString), 3170 3171 /*** GLX_VERSION_1_2 ***/ 3172 GLX_FUNCTION(glXGetCurrentDisplay), 3173 3174 /*** GLX_VERSION_1_3 ***/ 3175 GLX_FUNCTION(glXChooseFBConfig), 3176 GLX_FUNCTION(glXCreateNewContext), 3177 GLX_FUNCTION(glXCreatePbuffer), 3178 GLX_FUNCTION(glXCreatePixmap), 3179 GLX_FUNCTION(glXCreateWindow), 3180 GLX_FUNCTION(glXDestroyPbuffer), 3181 GLX_FUNCTION(glXDestroyPixmap), 3182 GLX_FUNCTION(glXDestroyWindow), 3183 GLX_FUNCTION(glXGetCurrentReadDrawable), 3184 GLX_FUNCTION(glXGetFBConfigAttrib), 3185 GLX_FUNCTION(glXGetFBConfigs), 3186 GLX_FUNCTION(glXGetSelectedEvent), 3187 GLX_FUNCTION(glXGetVisualFromFBConfig), 3188 GLX_FUNCTION(glXMakeContextCurrent), 3189 GLX_FUNCTION(glXQueryContext), 3190 GLX_FUNCTION(glXQueryDrawable), 3191 GLX_FUNCTION(glXSelectEvent), 3192 3193#ifndef GLX_USE_APPLEGL 3194 /*** GLX_SGI_swap_control ***/ 3195 GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI), 3196 3197 /*** GLX_SGI_video_sync ***/ 3198 GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI), 3199 GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI), 3200 3201 /*** GLX_SGI_make_current_read ***/ 3202 GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent), 3203 GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable), 3204 3205 /*** GLX_EXT_import_context ***/ 3206 GLX_FUNCTION(glXFreeContextEXT), 3207 GLX_FUNCTION(glXGetContextIDEXT), 3208 GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay), 3209 GLX_FUNCTION(glXImportContextEXT), 3210 GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext), 3211#endif 3212 3213 /*** GLX_SGIX_fbconfig ***/ 3214 GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib), 3215 GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig), 3216 GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX), 3217 GLX_FUNCTION(glXCreateContextWithConfigSGIX), 3218 GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig), 3219 GLX_FUNCTION(glXGetFBConfigFromVisualSGIX), 3220 3221#ifndef GLX_USE_APPLEGL 3222 /*** GLX_SGIX_pbuffer ***/ 3223 GLX_FUNCTION(glXCreateGLXPbufferSGIX), 3224 GLX_FUNCTION(glXDestroyGLXPbufferSGIX), 3225 GLX_FUNCTION(glXQueryGLXPbufferSGIX), 3226 GLX_FUNCTION(glXSelectEventSGIX), 3227 GLX_FUNCTION(glXGetSelectedEventSGIX), 3228 3229 /*** GLX_SGIX_swap_group ***/ 3230 GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX), 3231 3232 /*** GLX_SGIX_swap_barrier ***/ 3233 GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX), 3234 GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX), 3235 3236 /*** GLX_MESA_allocate_memory ***/ 3237 GLX_FUNCTION(glXAllocateMemoryMESA), 3238 GLX_FUNCTION(glXFreeMemoryMESA), 3239 GLX_FUNCTION(glXGetMemoryOffsetMESA), 3240 3241 /*** GLX_MESA_copy_sub_buffer ***/ 3242 GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA), 3243 3244 /*** GLX_MESA_pixmap_colormap ***/ 3245 GLX_FUNCTION(glXCreateGLXPixmapMESA), 3246 3247 /*** GLX_MESA_release_buffers ***/ 3248 GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA), 3249 3250 /*** GLX_MESA_swap_control ***/ 3251 GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA), 3252 GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA), 3253 3254 /*** GLX_MESA_swap_frame_usage ***/ 3255 GLX_FUNCTION2(glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA), 3256 GLX_FUNCTION2(glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA), 3257 GLX_FUNCTION2(glXGetFrameUsageMESA, __glXGetFrameUsageMESA), 3258 GLX_FUNCTION2(glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA), 3259#endif 3260 3261 /*** GLX_ARB_get_proc_address ***/ 3262 GLX_FUNCTION(glXGetProcAddressARB), 3263 3264 /*** GLX 1.4 ***/ 3265 GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB), 3266 3267#ifndef GLX_USE_APPLEGL 3268 /*** GLX_OML_sync_control ***/ 3269 GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML), 3270 GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML), 3271 GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML), 3272 GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML), 3273 GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML), 3274 3275 /*** GLX_EXT_texture_from_pixmap ***/ 3276 GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT), 3277 GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT), 3278#endif 3279 3280#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 3281 /*** DRI configuration ***/ 3282 GLX_FUNCTION(glXGetScreenDriver), 3283 GLX_FUNCTION(glXGetDriverConfig), 3284#endif 3285 3286 {NULL, NULL} /* end of list */ 3287}; 3288 3289#ifndef GLX_USE_APPLEGL 3290static const GLvoid * 3291get_glx_proc_address(const char *funcName) 3292{ 3293 GLuint i; 3294 3295 /* try static functions */ 3296 for (i = 0; GLX_functions[i].Name; i++) { 3297 if (strcmp(GLX_functions[i].Name, funcName) == 0) 3298 return GLX_functions[i].Address; 3299 } 3300 3301 return NULL; 3302} 3303#endif 3304 3305/** 3306 * Get the address of a named GL function. This is the pre-GLX 1.4 name for 3307 * \c glXGetProcAddress. 3308 * 3309 * \param procName Name of a GL or GLX function. 3310 * \returns A pointer to the named function 3311 * 3312 * \sa glXGetProcAddress 3313 */ 3314PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void) 3315{ 3316 typedef void (*gl_function) (void); 3317 gl_function f; 3318 3319 3320 /* Search the table of GLX and internal functions first. If that 3321 * fails and the supplied name could be a valid core GL name, try 3322 * searching the core GL function table. This check is done to prevent 3323 * DRI based drivers from searching the core GL function table for 3324 * internal API functions. 3325 */ 3326#ifdef GLX_USE_APPLEGL 3327 f = (gl_function) apple_glx_get_proc_address(procName); 3328#else 3329 f = (gl_function) get_glx_proc_address((const char *) procName); 3330 if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l') 3331 && (procName[2] != 'X')) { 3332 f = (gl_function) _glapi_get_proc_address((const char *) procName); 3333 } 3334#endif 3335 return f; 3336} 3337 3338/** 3339 * Get the address of a named GL function. This is the GLX 1.4 name for 3340 * \c glXGetProcAddressARB. 3341 * 3342 * \param procName Name of a GL or GLX function. 3343 * \returns A pointer to the named function 3344 * 3345 * \sa glXGetProcAddressARB 3346 */ 3347PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void) 3348#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED) 3349 __attribute__ ((alias("glXGetProcAddressARB"))); 3350#else 3351{ 3352 return glXGetProcAddressARB(procName); 3353} 3354#endif /* __GNUC__ */ 3355 3356 3357#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 3358/** 3359 * Get the unadjusted system time (UST). Currently, the UST is measured in 3360 * microseconds since Epoc. The actual resolution of the UST may vary from 3361 * system to system, and the units may vary from release to release. 3362 * Drivers should not call this function directly. They should instead use 3363 * \c glXGetProcAddress to obtain a pointer to the function. 3364 * 3365 * \param ust Location to store the 64-bit UST 3366 * \returns Zero on success or a negative errno value on failure. 3367 * 3368 * \sa glXGetProcAddress, PFNGLXGETUSTPROC 3369 * 3370 * \since Internal API version 20030317. 3371 */ 3372_X_HIDDEN int 3373__glXGetUST(int64_t * ust) 3374{ 3375 struct timeval tv; 3376 3377 if (ust == NULL) { 3378 return -EFAULT; 3379 } 3380 3381 if (gettimeofday(&tv, NULL) == 0) { 3382 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; 3383 return 0; 3384 } 3385 else { 3386 return -errno; 3387 } 3388} 3389#endif /* GLX_DIRECT_RENDERING */ 3390