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