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