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