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