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