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