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