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