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