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