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