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