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