glxcmds.c revision e975e18bebb54b20f00c568e7870932402b79f8f
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->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; 1415 xGLXQueryContextReply reply; 1416 CARD8 opcode; 1417 struct glx_context *ctx; 1418 int propList[__GLX_MAX_CONTEXT_PROPS * 2], *pProp, nPropListBytes; 1419 int i, renderType; 1420 XID share; 1421 struct glx_config *mode; 1422 1423 if (contextID == None || __glXIsDirect(dpy, contextID)) 1424 return NULL; 1425 1426 opcode = __glXSetupForCommand(dpy); 1427 if (!opcode) 1428 return 0; 1429 1430 /* Send the glXQueryContextInfoEXT request */ 1431 LockDisplay(dpy); 1432 1433 if (priv->majorVersion > 1 || priv->minorVersion >= 3) { 1434 xGLXQueryContextReq *req; 1435 1436 GetReq(GLXQueryContext, req); 1437 1438 req->reqType = opcode; 1439 req->glxCode = X_GLXQueryContext; 1440 req->context = contextID; 1441 } 1442 else { 1443 xGLXVendorPrivateReq *vpreq; 1444 xGLXQueryContextInfoEXTReq *req; 1445 1446 GetReqExtra(GLXVendorPrivate, 1447 sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq, 1448 vpreq); 1449 req = (xGLXQueryContextInfoEXTReq *) vpreq; 1450 req->reqType = opcode; 1451 req->glxCode = X_GLXVendorPrivateWithReply; 1452 req->vendorCode = X_GLXvop_QueryContextInfoEXT; 1453 req->context = contextID; 1454 } 1455 1456 _XReply(dpy, (xReply *) & reply, 0, False); 1457 1458 if (reply.n <= __GLX_MAX_CONTEXT_PROPS) 1459 nPropListBytes = reply.n * 2 * sizeof propList[0]; 1460 else 1461 nPropListBytes = 0; 1462 _XRead(dpy, (char *) propList, nPropListBytes); 1463 UnlockDisplay(dpy); 1464 SyncHandle(); 1465 1466 /* Look up screen first so we can look up visuals/fbconfigs later */ 1467 psc = NULL; 1468 for (i = 0, pProp = propList; i < reply.n; i++, pProp += 2) 1469 if (pProp[0] == GLX_SCREEN) 1470 psc = GetGLXScreenConfigs(dpy, pProp[1]); 1471 if (psc == NULL) 1472 return NULL; 1473 1474 share = None; 1475 mode = NULL; 1476 renderType = 0; 1477 pProp = propList; 1478 1479 for (i = 0, pProp = propList; i < reply.n; i++, pProp += 2) 1480 switch (pProp[0]) { 1481 case GLX_SHARE_CONTEXT_EXT: 1482 share = pProp[1]; 1483 break; 1484 case GLX_VISUAL_ID_EXT: 1485 mode = glx_config_find_visual(psc->visuals, pProp[1]); 1486 break; 1487 case GLX_FBCONFIG_ID: 1488 mode = glx_config_find_fbconfig(psc->configs, pProp[1]); 1489 break; 1490 case GLX_RENDER_TYPE: 1491 renderType = pProp[1]; 1492 break; 1493 } 1494 1495 if (mode == NULL) 1496 return NULL; 1497 1498 ctx = indirect_create_context(psc, mode, NULL, renderType); 1499 if (ctx == NULL) 1500 return NULL; 1501 1502 ctx->xid = contextID; 1503 ctx->imported = GL_TRUE; 1504 ctx->share_xid = share; 1505 1506 return (GLXContext) ctx; 1507} 1508 1509#endif 1510 1511_X_EXPORT int 1512glXQueryContext(Display * dpy, GLXContext ctx_user, int attribute, int *value) 1513{ 1514 struct glx_context *ctx = (struct glx_context *) ctx_user; 1515 1516 switch (attribute) { 1517 case GLX_SHARE_CONTEXT_EXT: 1518 *value = ctx->share_xid; 1519 break; 1520 case GLX_VISUAL_ID_EXT: 1521 *value = ctx->config ? ctx->config->visualID : None; 1522 break; 1523 case GLX_SCREEN: 1524 *value = ctx->screen; 1525 break; 1526 case GLX_FBCONFIG_ID: 1527 *value = ctx->config ? ctx->config->fbconfigID : None; 1528 break; 1529 case GLX_RENDER_TYPE: 1530 *value = ctx->renderType; 1531 break; 1532 default: 1533 return GLX_BAD_ATTRIBUTE; 1534 } 1535 return Success; 1536} 1537 1538_X_EXPORT 1539GLX_ALIAS(int, glXQueryContextInfoEXT, 1540 (Display * dpy, GLXContext ctx, int attribute, int *value), 1541 (dpy, ctx, attribute, value), glXQueryContext) 1542 1543_X_EXPORT GLXContextID glXGetContextIDEXT(const GLXContext ctx_user) 1544{ 1545 struct glx_context *ctx = (struct glx_context *) ctx_user; 1546 1547 return ctx->xid; 1548} 1549 1550_X_EXPORT 1551GLX_ALIAS_VOID(glXFreeContextEXT, (Display *dpy, GLXContext ctx), (dpy, ctx), 1552 glXDestroyContext); 1553 1554_X_EXPORT GLXFBConfig * 1555glXChooseFBConfig(Display * dpy, int screen, 1556 const int *attribList, int *nitems) 1557{ 1558 struct glx_config **config_list; 1559 int list_size; 1560 1561 1562 config_list = (struct glx_config **) 1563 glXGetFBConfigs(dpy, screen, &list_size); 1564 1565 if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) { 1566 list_size = choose_visual(config_list, list_size, attribList, GL_TRUE); 1567 if (list_size == 0) { 1568 XFree(config_list); 1569 config_list = NULL; 1570 } 1571 } 1572 1573 *nitems = list_size; 1574 return (GLXFBConfig *) config_list; 1575} 1576 1577 1578_X_EXPORT GLXContext 1579glXCreateNewContext(Display * dpy, GLXFBConfig fbconfig, 1580 int renderType, GLXContext shareList, Bool allowDirect) 1581{ 1582 struct glx_config *config = (struct glx_config *) fbconfig; 1583 1584 return CreateContext(dpy, config->fbconfigID, config, shareList, 1585 allowDirect, X_GLXCreateNewContext, renderType, 1586 config->screen); 1587} 1588 1589 1590_X_EXPORT GLXDrawable 1591glXGetCurrentReadDrawable(void) 1592{ 1593 struct glx_context *gc = __glXGetCurrentContext(); 1594 1595 return gc->currentReadable; 1596} 1597 1598 1599_X_EXPORT GLXFBConfig * 1600glXGetFBConfigs(Display * dpy, int screen, int *nelements) 1601{ 1602 struct glx_display *priv = __glXInitialize(dpy); 1603 struct glx_config **config_list = NULL; 1604 struct glx_config *config; 1605 unsigned num_configs = 0; 1606 int i; 1607 1608 *nelements = 0; 1609 if (priv && (priv->screens != NULL) 1610 && (screen >= 0) && (screen <= ScreenCount(dpy)) 1611 && (priv->screens[screen]->configs != NULL) 1612 && (priv->screens[screen]->configs->fbconfigID 1613 != (int) GLX_DONT_CARE)) { 1614 1615 for (config = priv->screens[screen]->configs; config != NULL; 1616 config = config->next) { 1617 if (config->fbconfigID != (int) GLX_DONT_CARE) { 1618 num_configs++; 1619 } 1620 } 1621 1622 config_list = Xmalloc(num_configs * sizeof *config_list); 1623 if (config_list != NULL) { 1624 *nelements = num_configs; 1625 i = 0; 1626 for (config = priv->screens[screen]->configs; config != NULL; 1627 config = config->next) { 1628 if (config->fbconfigID != (int) GLX_DONT_CARE) { 1629 config_list[i] = config; 1630 i++; 1631 } 1632 } 1633 } 1634 } 1635 1636 return (GLXFBConfig *) config_list; 1637} 1638 1639 1640_X_EXPORT int 1641glXGetFBConfigAttrib(Display * dpy, GLXFBConfig fbconfig, 1642 int attribute, int *value) 1643{ 1644 struct glx_config *config = ValidateGLXFBConfig(dpy, fbconfig); 1645 1646 if (config == NULL) 1647 return GLXBadFBConfig; 1648 1649 return glx_config_get(config, attribute, value); 1650} 1651 1652 1653_X_EXPORT XVisualInfo * 1654glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig fbconfig) 1655{ 1656 XVisualInfo visualTemplate; 1657 struct glx_config *config = (struct glx_config *) fbconfig; 1658 int count; 1659 1660 /* 1661 ** Get a list of all visuals, return if list is empty 1662 */ 1663 visualTemplate.visualid = config->visualID; 1664 return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count); 1665} 1666 1667#ifndef GLX_USE_APPLEGL 1668/* 1669** GLX_SGI_swap_control 1670*/ 1671static int 1672__glXSwapIntervalSGI(int interval) 1673{ 1674 xGLXVendorPrivateReq *req; 1675 struct glx_context *gc = __glXGetCurrentContext(); 1676 struct glx_screen *psc; 1677 Display *dpy; 1678 CARD32 *interval_ptr; 1679 CARD8 opcode; 1680 1681 if (gc == NULL) { 1682 return GLX_BAD_CONTEXT; 1683 } 1684 1685 if (interval <= 0) { 1686 return GLX_BAD_VALUE; 1687 } 1688 1689 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1690 1691#ifdef GLX_DIRECT_RENDERING 1692 if (gc->isDirect && psc->driScreen && psc->driScreen->setSwapInterval) { 1693 __GLXDRIdrawable *pdraw = 1694 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 1695 psc->driScreen->setSwapInterval(pdraw, interval); 1696 return 0; 1697 } 1698#endif 1699 1700 dpy = gc->currentDpy; 1701 opcode = __glXSetupForCommand(dpy); 1702 if (!opcode) { 1703 return 0; 1704 } 1705 1706 /* Send the glXSwapIntervalSGI request */ 1707 LockDisplay(dpy); 1708 GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req); 1709 req->reqType = opcode; 1710 req->glxCode = X_GLXVendorPrivate; 1711 req->vendorCode = X_GLXvop_SwapIntervalSGI; 1712 req->contextTag = gc->currentContextTag; 1713 1714 interval_ptr = (CARD32 *) (req + 1); 1715 *interval_ptr = interval; 1716 1717 UnlockDisplay(dpy); 1718 SyncHandle(); 1719 XFlush(dpy); 1720 1721 return 0; 1722} 1723 1724 1725/* 1726** GLX_MESA_swap_control 1727*/ 1728static int 1729__glXSwapIntervalMESA(unsigned int interval) 1730{ 1731#ifdef GLX_DIRECT_RENDERING 1732 struct glx_context *gc = __glXGetCurrentContext(); 1733 1734 if (gc != NULL && gc->isDirect) { 1735 struct glx_screen *psc; 1736 1737 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1738 if (psc->driScreen && psc->driScreen->setSwapInterval) { 1739 __GLXDRIdrawable *pdraw = 1740 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 1741 return psc->driScreen->setSwapInterval(pdraw, interval); 1742 } 1743 } 1744#endif 1745 1746 return GLX_BAD_CONTEXT; 1747} 1748 1749 1750static int 1751__glXGetSwapIntervalMESA(void) 1752{ 1753#ifdef GLX_DIRECT_RENDERING 1754 struct glx_context *gc = __glXGetCurrentContext(); 1755 1756 if (gc != NULL && gc->isDirect) { 1757 struct glx_screen *psc; 1758 1759 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1760 if (psc->driScreen && psc->driScreen->getSwapInterval) { 1761 __GLXDRIdrawable *pdraw = 1762 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 1763 return psc->driScreen->getSwapInterval(pdraw); 1764 } 1765 } 1766#endif 1767 1768 return 0; 1769} 1770 1771 1772/* 1773** GLX_SGI_video_sync 1774*/ 1775static int 1776__glXGetVideoSyncSGI(unsigned int *count) 1777{ 1778 int64_t ust, msc, sbc; 1779 int ret; 1780 struct glx_context *gc = __glXGetCurrentContext(); 1781 struct glx_screen *psc; 1782#ifdef GLX_DIRECT_RENDERING 1783 __GLXDRIdrawable *pdraw; 1784#endif 1785 1786 if (!gc) 1787 return GLX_BAD_CONTEXT; 1788 1789#ifdef GLX_DIRECT_RENDERING 1790 if (!gc->isDirect) 1791 return GLX_BAD_CONTEXT; 1792#endif 1793 1794 psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen); 1795#ifdef GLX_DIRECT_RENDERING 1796 pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 1797#endif 1798 1799 /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry, 1800 * FIXME: there should be a GLX encoding for this call. I can find no 1801 * FIXME: documentation for the GLX encoding. 1802 */ 1803#ifdef GLX_DIRECT_RENDERING 1804 if (psc->driScreen && psc->driScreen->getDrawableMSC) { 1805 ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc); 1806 *count = (unsigned) msc; 1807 return (ret == True) ? 0 : GLX_BAD_CONTEXT; 1808 } 1809#endif 1810 1811 return GLX_BAD_CONTEXT; 1812} 1813 1814static int 1815__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) 1816{ 1817 struct glx_context *gc = __glXGetCurrentContext(); 1818 struct glx_screen *psc; 1819#ifdef GLX_DIRECT_RENDERING 1820 __GLXDRIdrawable *pdraw; 1821#endif 1822 int64_t ust, msc, sbc; 1823 int ret; 1824 1825 if (divisor <= 0 || remainder < 0) 1826 return GLX_BAD_VALUE; 1827 1828 if (!gc) 1829 return GLX_BAD_CONTEXT; 1830 1831#ifdef GLX_DIRECT_RENDERING 1832 if (!gc->isDirect) 1833 return GLX_BAD_CONTEXT; 1834#endif 1835 1836 psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1837#ifdef GLX_DIRECT_RENDERING 1838 pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 1839#endif 1840 1841#ifdef GLX_DIRECT_RENDERING 1842 if (psc->driScreen && psc->driScreen->waitForMSC) { 1843 ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc, 1844 &sbc); 1845 *count = (unsigned) msc; 1846 return (ret == True) ? 0 : GLX_BAD_CONTEXT; 1847 } 1848#endif 1849 1850 return GLX_BAD_CONTEXT; 1851} 1852 1853#endif /* GLX_USE_APPLEGL */ 1854 1855/* 1856** GLX_SGIX_fbconfig 1857** Many of these functions are aliased to GLX 1.3 entry points in the 1858** GLX_functions table. 1859*/ 1860 1861_X_EXPORT 1862GLX_ALIAS(int, glXGetFBConfigAttribSGIX, 1863 (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value), 1864 (dpy, config, attribute, value), glXGetFBConfigAttrib) 1865 1866_X_EXPORT GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX, 1867 (Display * dpy, int screen, int *attrib_list, 1868 int *nelements), (dpy, screen, attrib_list, nelements), 1869 glXChooseFBConfig) 1870 1871_X_EXPORT GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX, 1872 (Display * dpy, GLXFBConfigSGIX config), 1873 (dpy, config), glXGetVisualFromFBConfig) 1874 1875_X_EXPORT GLXPixmap 1876glXCreateGLXPixmapWithConfigSGIX(Display * dpy, 1877 GLXFBConfigSGIX fbconfig, 1878 Pixmap pixmap) 1879{ 1880#ifndef GLX_USE_APPLEGL 1881 xGLXVendorPrivateWithReplyReq *vpreq; 1882 xGLXCreateGLXPixmapWithConfigSGIXReq *req; 1883 GLXPixmap xid = None; 1884 CARD8 opcode; 1885 struct glx_screen *psc; 1886#endif 1887 struct glx_config *config = (struct glx_config *) fbconfig; 1888 1889 1890 if ((dpy == NULL) || (config == NULL)) { 1891 return None; 1892 } 1893#ifdef GLX_USE_APPLEGL 1894 if(apple_glx_pixmap_create(dpy, config->screen, pixmap, config)) 1895 return None; 1896 return pixmap; 1897#else 1898 1899 psc = GetGLXScreenConfigs(dpy, config->screen); 1900 if ((psc != NULL) 1901 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 1902 opcode = __glXSetupForCommand(dpy); 1903 if (!opcode) { 1904 return None; 1905 } 1906 1907 /* Send the glXCreateGLXPixmapWithConfigSGIX request */ 1908 LockDisplay(dpy); 1909 GetReqExtra(GLXVendorPrivateWithReply, 1910 sz_xGLXCreateGLXPixmapWithConfigSGIXReq - 1911 sz_xGLXVendorPrivateWithReplyReq, vpreq); 1912 req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq; 1913 req->reqType = opcode; 1914 req->glxCode = X_GLXVendorPrivateWithReply; 1915 req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; 1916 req->screen = config->screen; 1917 req->fbconfig = config->fbconfigID; 1918 req->pixmap = pixmap; 1919 req->glxpixmap = xid = XAllocID(dpy); 1920 UnlockDisplay(dpy); 1921 SyncHandle(); 1922 } 1923 1924 return xid; 1925#endif 1926} 1927 1928_X_EXPORT GLXContext 1929glXCreateContextWithConfigSGIX(Display * dpy, 1930 GLXFBConfigSGIX fbconfig, int renderType, 1931 GLXContext shareList, Bool allowDirect) 1932{ 1933 GLXContext gc = NULL; 1934 struct glx_config *config = (struct glx_config *) fbconfig; 1935 struct glx_screen *psc; 1936 1937 1938 if ((dpy == NULL) || (config == NULL)) { 1939 return None; 1940 } 1941 1942 psc = GetGLXScreenConfigs(dpy, config->screen); 1943 if ((psc != NULL) 1944 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 1945 gc = CreateContext(dpy, config->fbconfigID, config, shareList, 1946 allowDirect, 1947 X_GLXvop_CreateContextWithConfigSGIX, renderType, 1948 config->screen); 1949 } 1950 1951 return gc; 1952} 1953 1954 1955_X_EXPORT GLXFBConfigSGIX 1956glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis) 1957{ 1958 struct glx_display *priv; 1959 struct glx_screen *psc = NULL; 1960 1961 if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) == Success) 1962 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit) 1963 && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) { 1964 return (GLXFBConfigSGIX) glx_config_find_visual(psc->configs, 1965 vis->visualid); 1966 } 1967 1968 return NULL; 1969} 1970 1971#ifndef GLX_USE_APPLEGL 1972/* 1973** GLX_SGIX_swap_group 1974*/ 1975static void 1976__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable, 1977 GLXDrawable member) 1978{ 1979 (void) dpy; 1980 (void) drawable; 1981 (void) member; 1982} 1983 1984 1985/* 1986** GLX_SGIX_swap_barrier 1987*/ 1988static void 1989__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier) 1990{ 1991 (void) dpy; 1992 (void) drawable; 1993 (void) barrier; 1994} 1995 1996static Bool 1997__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max) 1998{ 1999 (void) dpy; 2000 (void) screen; 2001 (void) max; 2002 return False; 2003} 2004 2005 2006/* 2007** GLX_OML_sync_control 2008*/ 2009static Bool 2010__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable, 2011 int64_t * ust, int64_t * msc, int64_t * sbc) 2012{ 2013 struct glx_display * const priv = __glXInitialize(dpy); 2014 int ret; 2015#ifdef GLX_DIRECT_RENDERING 2016 __GLXDRIdrawable *pdraw; 2017#endif 2018 struct glx_screen *psc; 2019 2020 if (!priv) 2021 return False; 2022 2023#ifdef GLX_DIRECT_RENDERING 2024 pdraw = GetGLXDRIDrawable(dpy, drawable); 2025 psc = pdraw ? pdraw->psc : NULL; 2026 if (pdraw && psc->driScreen->getDrawableMSC) { 2027 ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc); 2028 return ret; 2029 } 2030#endif 2031 2032 return False; 2033} 2034 2035#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2036_X_HIDDEN GLboolean 2037__glxGetMscRate(__GLXDRIdrawable *glxDraw, 2038 int32_t * numerator, int32_t * denominator) 2039{ 2040#ifdef XF86VIDMODE 2041 struct glx_screen *psc; 2042 XF86VidModeModeLine mode_line; 2043 int dot_clock; 2044 int i; 2045 2046 psc = glxDraw->psc; 2047 if (XF86VidModeQueryVersion(psc->dpy, &i, &i) && 2048 XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) { 2049 unsigned n = dot_clock * 1000; 2050 unsigned d = mode_line.vtotal * mode_line.htotal; 2051 2052# define V_INTERLACE 0x010 2053# define V_DBLSCAN 0x020 2054 2055 if (mode_line.flags & V_INTERLACE) 2056 n *= 2; 2057 else if (mode_line.flags & V_DBLSCAN) 2058 d *= 2; 2059 2060 /* The OML_sync_control spec requires that if the refresh rate is a 2061 * whole number, that the returned numerator be equal to the refresh 2062 * rate and the denominator be 1. 2063 */ 2064 2065 if (n % d == 0) { 2066 n /= d; 2067 d = 1; 2068 } 2069 else { 2070 static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 }; 2071 2072 /* This is a poor man's way to reduce a fraction. It's far from 2073 * perfect, but it will work well enough for this situation. 2074 */ 2075 2076 for (i = 0; f[i] != 0; i++) { 2077 while (n % f[i] == 0 && d % f[i] == 0) { 2078 d /= f[i]; 2079 n /= f[i]; 2080 } 2081 } 2082 } 2083 2084 *numerator = n; 2085 *denominator = d; 2086 2087 return True; 2088 } 2089 else 2090#endif 2091 2092 return False; 2093} 2094#endif 2095 2096/** 2097 * Determine the refresh rate of the specified drawable and display. 2098 * 2099 * \param dpy Display whose refresh rate is to be determined. 2100 * \param drawable Drawable whose refresh rate is to be determined. 2101 * \param numerator Numerator of the refresh rate. 2102 * \param demoninator Denominator of the refresh rate. 2103 * \return If the refresh rate for the specified display and drawable could 2104 * be calculated, True is returned. Otherwise False is returned. 2105 * 2106 * \note This function is implemented entirely client-side. A lot of other 2107 * functionality is required to export GLX_OML_sync_control, so on 2108 * XFree86 this function can be called for direct-rendering contexts 2109 * when GLX_OML_sync_control appears in the client extension string. 2110 */ 2111 2112_X_HIDDEN GLboolean 2113__glXGetMscRateOML(Display * dpy, GLXDrawable drawable, 2114 int32_t * numerator, int32_t * denominator) 2115{ 2116#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE ) 2117 __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable); 2118 2119 if (draw == NULL) 2120 return False; 2121 2122 return __glxGetMscRate(draw, numerator, denominator); 2123#else 2124 (void) dpy; 2125 (void) drawable; 2126 (void) numerator; 2127 (void) denominator; 2128#endif 2129 return False; 2130} 2131 2132 2133static int64_t 2134__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, 2135 int64_t target_msc, int64_t divisor, int64_t remainder) 2136{ 2137 struct glx_context *gc = __glXGetCurrentContext(); 2138#ifdef GLX_DIRECT_RENDERING 2139 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 2140 struct glx_screen *psc = pdraw ? pdraw->psc : NULL; 2141#endif 2142 2143 if (!gc) /* no GLX for this */ 2144 return -1; 2145 2146#ifdef GLX_DIRECT_RENDERING 2147 if (!pdraw || !gc->isDirect) 2148 return -1; 2149#endif 2150 2151 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2152 * error", but it also says "It [glXSwapBuffersMscOML] will return a value 2153 * of -1 if the function failed because of errors detected in the input 2154 * parameters" 2155 */ 2156 if (divisor < 0 || remainder < 0 || target_msc < 0) 2157 return -1; 2158 if (divisor > 0 && remainder >= divisor) 2159 return -1; 2160 2161 if (target_msc == 0 && divisor == 0 && remainder == 0) 2162 remainder = 1; 2163 2164#ifdef GLX_DIRECT_RENDERING 2165 if (psc->driScreen && psc->driScreen->swapBuffers) 2166 return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor, 2167 remainder); 2168#endif 2169 2170 return -1; 2171} 2172 2173 2174static Bool 2175__glXWaitForMscOML(Display * dpy, GLXDrawable drawable, 2176 int64_t target_msc, int64_t divisor, 2177 int64_t remainder, int64_t * ust, 2178 int64_t * msc, int64_t * sbc) 2179{ 2180#ifdef GLX_DIRECT_RENDERING 2181 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 2182 struct glx_screen *psc = pdraw ? pdraw->psc : NULL; 2183 int ret; 2184#endif 2185 2186 2187 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2188 * error", but the return type in the spec is Bool. 2189 */ 2190 if (divisor < 0 || remainder < 0 || target_msc < 0) 2191 return False; 2192 if (divisor > 0 && remainder >= divisor) 2193 return False; 2194 2195#ifdef GLX_DIRECT_RENDERING 2196 if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) { 2197 ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder, 2198 ust, msc, sbc); 2199 return ret; 2200 } 2201#endif 2202 2203 return False; 2204} 2205 2206 2207static Bool 2208__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, 2209 int64_t target_sbc, int64_t * ust, 2210 int64_t * msc, int64_t * sbc) 2211{ 2212#ifdef GLX_DIRECT_RENDERING 2213 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 2214 struct glx_screen *psc = pdraw ? pdraw->psc : NULL; 2215 int ret; 2216#endif 2217 2218 /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE 2219 * error", but the return type in the spec is Bool. 2220 */ 2221 if (target_sbc < 0) 2222 return False; 2223 2224#ifdef GLX_DIRECT_RENDERING 2225 if (pdraw && psc->driScreen && psc->driScreen->waitForSBC) { 2226 ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc); 2227 return ret; 2228 } 2229#endif 2230 2231 return False; 2232} 2233 2234/*@}*/ 2235 2236 2237/** 2238 * Mesa extension stubs. These will help reduce portability problems. 2239 */ 2240/*@{*/ 2241 2242/** 2243 * Release all buffers associated with the specified GLX drawable. 2244 * 2245 * \todo 2246 * This function was intended for stand-alone Mesa. The issue there is that 2247 * the library doesn't get any notification when a window is closed. In 2248 * DRI there is a similar but slightly different issue. When GLX 1.3 is 2249 * supported, there are 3 different functions to destroy a drawable. It 2250 * should be possible to create GLX protocol (or have it determine which 2251 * protocol to use based on the type of the drawable) to have one function 2252 * do the work of 3. For the direct-rendering case, this function could 2253 * just call the driver's \c __DRIdrawableRec::destroyDrawable function. 2254 * This would reduce the frequency with which \c __driGarbageCollectDrawables 2255 * would need to be used. This really should be done as part of the new DRI 2256 * interface work. 2257 * 2258 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt 2259 * __driGarbageCollectDrawables 2260 * glXDestroyGLXPixmap 2261 * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow 2262 * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX 2263 */ 2264static Bool 2265__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d) 2266{ 2267 (void) dpy; 2268 (void) d; 2269 return False; 2270} 2271 2272 2273_X_EXPORT GLXPixmap 2274glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual, 2275 Pixmap pixmap, Colormap cmap) 2276{ 2277 (void) dpy; 2278 (void) visual; 2279 (void) pixmap; 2280 (void) cmap; 2281 return 0; 2282} 2283 2284/*@}*/ 2285 2286 2287/** 2288 * GLX_MESA_copy_sub_buffer 2289 */ 2290#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */ 2291static void 2292__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable, 2293 int x, int y, int width, int height) 2294{ 2295 xGLXVendorPrivateReq *req; 2296 struct glx_context *gc; 2297 GLXContextTag tag; 2298 CARD32 *drawable_ptr; 2299 INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr; 2300 CARD8 opcode; 2301 2302#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2303 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 2304 if (pdraw != NULL) { 2305 struct glx_screen *psc = pdraw->psc; 2306 if (psc->driScreen->copySubBuffer != NULL) { 2307 glFlush(); 2308 (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height); 2309 } 2310 2311 return; 2312 } 2313#endif 2314 2315 opcode = __glXSetupForCommand(dpy); 2316 if (!opcode) 2317 return; 2318 2319 /* 2320 ** The calling thread may or may not have a current context. If it 2321 ** does, send the context tag so the server can do a flush. 2322 */ 2323 gc = __glXGetCurrentContext(); 2324 if ((gc != NULL) && (dpy == gc->currentDpy) && 2325 ((drawable == gc->currentDrawable) || 2326 (drawable == gc->currentReadable))) { 2327 tag = gc->currentContextTag; 2328 } 2329 else { 2330 tag = 0; 2331 } 2332 2333 LockDisplay(dpy); 2334 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req); 2335 req->reqType = opcode; 2336 req->glxCode = X_GLXVendorPrivate; 2337 req->vendorCode = X_GLXvop_CopySubBufferMESA; 2338 req->contextTag = tag; 2339 2340 drawable_ptr = (CARD32 *) (req + 1); 2341 x_ptr = (INT32 *) (drawable_ptr + 1); 2342 y_ptr = (INT32 *) (drawable_ptr + 2); 2343 w_ptr = (INT32 *) (drawable_ptr + 3); 2344 h_ptr = (INT32 *) (drawable_ptr + 4); 2345 2346 *drawable_ptr = drawable; 2347 *x_ptr = x; 2348 *y_ptr = y; 2349 *w_ptr = width; 2350 *h_ptr = height; 2351 2352 UnlockDisplay(dpy); 2353 SyncHandle(); 2354} 2355 2356/*@{*/ 2357static void 2358__glXBindTexImageEXT(Display * dpy, 2359 GLXDrawable drawable, int buffer, const int *attrib_list) 2360{ 2361 struct glx_context *gc = __glXGetCurrentContext(); 2362 2363 if (gc == NULL || gc->vtable->bind_tex_image == NULL) 2364 return; 2365 2366 gc->vtable->bind_tex_image(dpy, drawable, buffer, attrib_list); 2367} 2368 2369static void 2370__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer) 2371{ 2372 struct glx_context *gc = __glXGetCurrentContext(); 2373 2374 if (gc == NULL || gc->vtable->release_tex_image == NULL) 2375 return; 2376 2377 gc->vtable->release_tex_image(dpy, drawable, buffer); 2378} 2379 2380/*@}*/ 2381 2382#endif /* GLX_USE_APPLEGL */ 2383 2384/** 2385 * \c strdup is actually not a standard ANSI C or POSIX routine. 2386 * Irix will not define it if ANSI mode is in effect. 2387 * 2388 * \sa strdup 2389 */ 2390_X_HIDDEN char * 2391__glXstrdup(const char *str) 2392{ 2393 char *copy; 2394 copy = (char *) Xmalloc(strlen(str) + 1); 2395 if (!copy) 2396 return NULL; 2397 strcpy(copy, str); 2398 return copy; 2399} 2400 2401/* 2402** glXGetProcAddress support 2403*/ 2404 2405struct name_address_pair 2406{ 2407 const char *Name; 2408 GLvoid *Address; 2409}; 2410 2411#define GLX_FUNCTION(f) { # f, (GLvoid *) f } 2412#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f } 2413 2414static const struct name_address_pair GLX_functions[] = { 2415 /*** GLX_VERSION_1_0 ***/ 2416 GLX_FUNCTION(glXChooseVisual), 2417 GLX_FUNCTION(glXCopyContext), 2418 GLX_FUNCTION(glXCreateContext), 2419 GLX_FUNCTION(glXCreateGLXPixmap), 2420 GLX_FUNCTION(glXDestroyContext), 2421 GLX_FUNCTION(glXDestroyGLXPixmap), 2422 GLX_FUNCTION(glXGetConfig), 2423 GLX_FUNCTION(glXGetCurrentContext), 2424 GLX_FUNCTION(glXGetCurrentDrawable), 2425 GLX_FUNCTION(glXIsDirect), 2426 GLX_FUNCTION(glXMakeCurrent), 2427 GLX_FUNCTION(glXQueryExtension), 2428 GLX_FUNCTION(glXQueryVersion), 2429 GLX_FUNCTION(glXSwapBuffers), 2430 GLX_FUNCTION(glXUseXFont), 2431 GLX_FUNCTION(glXWaitGL), 2432 GLX_FUNCTION(glXWaitX), 2433 2434 /*** GLX_VERSION_1_1 ***/ 2435 GLX_FUNCTION(glXGetClientString), 2436 GLX_FUNCTION(glXQueryExtensionsString), 2437 GLX_FUNCTION(glXQueryServerString), 2438 2439 /*** GLX_VERSION_1_2 ***/ 2440 GLX_FUNCTION(glXGetCurrentDisplay), 2441 2442 /*** GLX_VERSION_1_3 ***/ 2443 GLX_FUNCTION(glXChooseFBConfig), 2444 GLX_FUNCTION(glXCreateNewContext), 2445 GLX_FUNCTION(glXCreatePbuffer), 2446 GLX_FUNCTION(glXCreatePixmap), 2447 GLX_FUNCTION(glXCreateWindow), 2448 GLX_FUNCTION(glXDestroyPbuffer), 2449 GLX_FUNCTION(glXDestroyPixmap), 2450 GLX_FUNCTION(glXDestroyWindow), 2451 GLX_FUNCTION(glXGetCurrentReadDrawable), 2452 GLX_FUNCTION(glXGetFBConfigAttrib), 2453 GLX_FUNCTION(glXGetFBConfigs), 2454 GLX_FUNCTION(glXGetSelectedEvent), 2455 GLX_FUNCTION(glXGetVisualFromFBConfig), 2456 GLX_FUNCTION(glXMakeContextCurrent), 2457 GLX_FUNCTION(glXQueryContext), 2458 GLX_FUNCTION(glXQueryDrawable), 2459 GLX_FUNCTION(glXSelectEvent), 2460 2461#ifndef GLX_USE_APPLEGL 2462 /*** GLX_SGI_swap_control ***/ 2463 GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI), 2464 2465 /*** GLX_SGI_video_sync ***/ 2466 GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI), 2467 GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI), 2468 2469 /*** GLX_SGI_make_current_read ***/ 2470 GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent), 2471 GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable), 2472 2473 /*** GLX_EXT_import_context ***/ 2474 GLX_FUNCTION(glXFreeContextEXT), 2475 GLX_FUNCTION(glXGetContextIDEXT), 2476 GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay), 2477 GLX_FUNCTION(glXImportContextEXT), 2478 GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext), 2479#endif 2480 2481 /*** GLX_SGIX_fbconfig ***/ 2482 GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib), 2483 GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig), 2484 GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX), 2485 GLX_FUNCTION(glXCreateContextWithConfigSGIX), 2486 GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig), 2487 GLX_FUNCTION(glXGetFBConfigFromVisualSGIX), 2488 2489#ifndef GLX_USE_APPLEGL 2490 /*** GLX_SGIX_pbuffer ***/ 2491 GLX_FUNCTION(glXCreateGLXPbufferSGIX), 2492 GLX_FUNCTION(glXDestroyGLXPbufferSGIX), 2493 GLX_FUNCTION(glXQueryGLXPbufferSGIX), 2494 GLX_FUNCTION(glXSelectEventSGIX), 2495 GLX_FUNCTION(glXGetSelectedEventSGIX), 2496 2497 /*** GLX_SGIX_swap_group ***/ 2498 GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX), 2499 2500 /*** GLX_SGIX_swap_barrier ***/ 2501 GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX), 2502 GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX), 2503 2504 /*** GLX_MESA_copy_sub_buffer ***/ 2505 GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA), 2506 2507 /*** GLX_MESA_pixmap_colormap ***/ 2508 GLX_FUNCTION(glXCreateGLXPixmapMESA), 2509 2510 /*** GLX_MESA_release_buffers ***/ 2511 GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA), 2512 2513 /*** GLX_MESA_swap_control ***/ 2514 GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA), 2515 GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA), 2516#endif 2517 2518 /*** GLX_ARB_get_proc_address ***/ 2519 GLX_FUNCTION(glXGetProcAddressARB), 2520 2521 /*** GLX 1.4 ***/ 2522 GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB), 2523 2524#ifndef GLX_USE_APPLEGL 2525 /*** GLX_OML_sync_control ***/ 2526 GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML), 2527 GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML), 2528 GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML), 2529 GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML), 2530 GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML), 2531 2532 /*** GLX_EXT_texture_from_pixmap ***/ 2533 GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT), 2534 GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT), 2535#endif 2536 2537#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2538 /*** DRI configuration ***/ 2539 GLX_FUNCTION(glXGetScreenDriver), 2540 GLX_FUNCTION(glXGetDriverConfig), 2541#endif 2542 2543 {NULL, NULL} /* end of list */ 2544}; 2545 2546static const GLvoid * 2547get_glx_proc_address(const char *funcName) 2548{ 2549 GLuint i; 2550 2551 /* try static functions */ 2552 for (i = 0; GLX_functions[i].Name; i++) { 2553 if (strcmp(GLX_functions[i].Name, funcName) == 0) 2554 return GLX_functions[i].Address; 2555 } 2556 2557 return NULL; 2558} 2559 2560/** 2561 * Get the address of a named GL function. This is the pre-GLX 1.4 name for 2562 * \c glXGetProcAddress. 2563 * 2564 * \param procName Name of a GL or GLX function. 2565 * \returns A pointer to the named function 2566 * 2567 * \sa glXGetProcAddress 2568 */ 2569_X_EXPORT void (*glXGetProcAddressARB(const GLubyte * procName)) (void) 2570{ 2571 typedef void (*gl_function) (void); 2572 gl_function f; 2573 2574 2575 /* Search the table of GLX and internal functions first. If that 2576 * fails and the supplied name could be a valid core GL name, try 2577 * searching the core GL function table. This check is done to prevent 2578 * DRI based drivers from searching the core GL function table for 2579 * internal API functions. 2580 */ 2581 f = (gl_function) get_glx_proc_address((const char *) procName); 2582 if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l') 2583 && (procName[2] != 'X')) { 2584#ifdef GLX_SHARED_GLAPI 2585 f = (gl_function) __indirect_get_proc_address((const char *) procName); 2586#endif 2587 if (!f) 2588 f = (gl_function) _glapi_get_proc_address((const char *) procName); 2589 if (!f) { 2590 struct glx_context *gc = __glXGetCurrentContext(); 2591 2592 if (gc != NULL && gc->vtable->get_proc_address != NULL) 2593 f = gc->vtable->get_proc_address((const char *) procName); 2594 } 2595 } 2596 return f; 2597} 2598 2599/** 2600 * Get the address of a named GL function. This is the GLX 1.4 name for 2601 * \c glXGetProcAddressARB. 2602 * 2603 * \param procName Name of a GL or GLX function. 2604 * \returns A pointer to the named function 2605 * 2606 * \sa glXGetProcAddressARB 2607 */ 2608_X_EXPORT void (*glXGetProcAddress(const GLubyte * procName)) (void) 2609#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED) 2610 __attribute__ ((alias("glXGetProcAddressARB"))); 2611#else 2612{ 2613 return glXGetProcAddressARB(procName); 2614} 2615#endif /* __GNUC__ */ 2616 2617 2618#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2619/** 2620 * Get the unadjusted system time (UST). Currently, the UST is measured in 2621 * microseconds since Epoc. The actual resolution of the UST may vary from 2622 * system to system, and the units may vary from release to release. 2623 * Drivers should not call this function directly. They should instead use 2624 * \c glXGetProcAddress to obtain a pointer to the function. 2625 * 2626 * \param ust Location to store the 64-bit UST 2627 * \returns Zero on success or a negative errno value on failure. 2628 * 2629 * \sa glXGetProcAddress, PFNGLXGETUSTPROC 2630 * 2631 * \since Internal API version 20030317. 2632 */ 2633_X_HIDDEN int 2634__glXGetUST(int64_t * ust) 2635{ 2636 struct timeval tv; 2637 2638 if (ust == NULL) { 2639 return -EFAULT; 2640 } 2641 2642 if (gettimeofday(&tv, NULL) == 0) { 2643 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; 2644 return 0; 2645 } 2646 else { 2647 return -errno; 2648 } 2649} 2650#endif /* GLX_DIRECT_RENDERING */ 2651