glxext.c revision 8d00f077c9672ed2f00a1c67b688c82c3fc7d480
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 glxext.c 33 * GLX protocol interface boot-strap code. 34 * 35 * Direct rendering support added by Precision Insight, Inc. 36 * 37 * \author Kevin E. Martin <kevin@precisioninsight.com> 38 */ 39 40#include <assert.h> 41#include "glxclient.h" 42#include <X11/extensions/Xext.h> 43#include <X11/extensions/extutil.h> 44#ifdef GLX_USE_APPLEGL 45#include "apple_glx.h" 46#include "apple_visual.h" 47#endif 48#include "glxextensions.h" 49 50#ifdef USE_XCB 51#include <X11/Xlib-xcb.h> 52#include <xcb/xcb.h> 53#include <xcb/glx.h> 54#endif 55 56 57#ifdef DEBUG 58void __glXDumpDrawBuffer(struct glx_context * ctx); 59#endif 60 61/* 62** You can set this cell to 1 to force the gl drawing stuff to be 63** one command per packet 64*/ 65_X_HIDDEN int __glXDebug = 0; 66 67/* Extension required boiler plate */ 68 69static const char __glXExtensionName[] = GLX_EXTENSION_NAME; 70 static struct glx_display *glx_displays; 71 72static /* const */ char *error_list[] = { 73 "GLXBadContext", 74 "GLXBadContextState", 75 "GLXBadDrawable", 76 "GLXBadPixmap", 77 "GLXBadContextTag", 78 "GLXBadCurrentWindow", 79 "GLXBadRenderRequest", 80 "GLXBadLargeRequest", 81 "GLXUnsupportedPrivateRequest", 82 "GLXBadFBConfig", 83 "GLXBadPbuffer", 84 "GLXBadCurrentDrawable", 85 "GLXBadWindow", 86 "GLXBadProfileARB", 87}; 88 89#ifdef GLX_USE_APPLEGL 90static char *__glXErrorString(Display *dpy, int code, XExtCodes *codes, 91 char *buf, int n); 92#endif 93 94static 95XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName, 96 __GLX_NUMBER_ERRORS, error_list) 97 98/* 99 * GLX events are a bit funky. We don't stuff the X event code into 100 * our user exposed (via XNextEvent) structure. Instead we use the GLX 101 * private event code namespace (and hope it doesn't conflict). Clients 102 * have to know that bit 15 in the event type field means they're getting 103 * a GLX event, and then handle the various sub-event types there, rather 104 * than simply checking the event code and handling it directly. 105 */ 106 107static Bool 108__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire) 109{ 110 struct glx_display *glx_dpy = __glXInitialize(dpy); 111 112 if (glx_dpy == NULL) 113 return False; 114 115 switch ((wire->u.u.type & 0x7f) - glx_dpy->codes->first_event) { 116 case GLX_PbufferClobber: 117 { 118 GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event; 119 xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire; 120 aevent->event_type = awire->type; 121 aevent->serial = awire->sequenceNumber; 122 aevent->event_type = awire->event_type; 123 aevent->draw_type = awire->draw_type; 124 aevent->drawable = awire->drawable; 125 aevent->buffer_mask = awire->buffer_mask; 126 aevent->aux_buffer = awire->aux_buffer; 127 aevent->x = awire->x; 128 aevent->y = awire->y; 129 aevent->width = awire->width; 130 aevent->height = awire->height; 131 aevent->count = awire->count; 132 return True; 133 } 134 case GLX_BufferSwapComplete: 135 { 136 GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; 137 xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire; 138 struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable); 139 aevent->event_type = awire->event_type; 140 aevent->drawable = awire->drawable; 141 aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; 142 aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; 143 144 if (!glxDraw) 145 return False; 146 147 if (awire->sbc < glxDraw->lastEventSbc) 148 glxDraw->eventSbcWrap += 0x100000000; 149 glxDraw->lastEventSbc = awire->sbc; 150 aevent->sbc = awire->sbc + glxDraw->eventSbcWrap; 151 return True; 152 } 153 default: 154 /* client doesn't support server event */ 155 break; 156 } 157 158 return False; 159} 160 161/* We don't actually support this. It doesn't make sense for clients to 162 * send each other GLX events. 163 */ 164static Status 165__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire) 166{ 167 struct glx_display *glx_dpy = __glXInitialize(dpy); 168 169 if (glx_dpy == NULL) 170 return False; 171 172 switch (event->type) { 173 case GLX_DAMAGED: 174 break; 175 case GLX_SAVED: 176 break; 177 case GLX_EXCHANGE_COMPLETE_INTEL: 178 break; 179 case GLX_COPY_COMPLETE_INTEL: 180 break; 181 case GLX_FLIP_COMPLETE_INTEL: 182 break; 183 default: 184 /* client doesn't support server event */ 185 break; 186 } 187 188 return Success; 189} 190 191/************************************************************************/ 192/* 193** Free the per screen configs data as well as the array of 194** __glXScreenConfigs. 195*/ 196static void 197FreeScreenConfigs(struct glx_display * priv) 198{ 199 struct glx_screen *psc; 200 GLint i, screens; 201 202 /* Free screen configuration information */ 203 screens = ScreenCount(priv->dpy); 204 for (i = 0; i < screens; i++) { 205 psc = priv->screens[i]; 206 glx_screen_cleanup(psc); 207 208#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 209 if (psc->driScreen) { 210 psc->driScreen->destroyScreen(psc); 211 } else { 212 Xfree(psc); 213 } 214#else 215 Xfree(psc); 216#endif 217 } 218 XFree((char *) priv->screens); 219 priv->screens = NULL; 220} 221 222static void 223glx_display_free(struct glx_display *priv) 224{ 225 struct glx_context *gc; 226 227 gc = __glXGetCurrentContext(); 228 if (priv->dpy == gc->currentDpy) { 229 gc->vtable->destroy(gc); 230 __glXSetCurrentContextNull(); 231 } 232 233 FreeScreenConfigs(priv); 234 if (priv->serverGLXvendor) 235 Xfree((char *) priv->serverGLXvendor); 236 if (priv->serverGLXversion) 237 Xfree((char *) priv->serverGLXversion); 238 239 __glxHashDestroy(priv->glXDrawHash); 240 241#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 242 __glxHashDestroy(priv->drawHash); 243 244 /* Free the direct rendering per display data */ 245 if (priv->driswDisplay) 246 (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay); 247 priv->driswDisplay = NULL; 248 249 if (priv->driDisplay) 250 (*priv->driDisplay->destroyDisplay) (priv->driDisplay); 251 priv->driDisplay = NULL; 252 253 if (priv->dri2Display) 254 (*priv->dri2Display->destroyDisplay) (priv->dri2Display); 255 priv->dri2Display = NULL; 256#endif 257 258 Xfree((char *) priv); 259} 260 261static int 262__glXCloseDisplay(Display * dpy, XExtCodes * codes) 263{ 264 struct glx_display *priv, **prev; 265 266 _XLockMutex(_Xglobal_lock); 267 prev = &glx_displays; 268 for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) { 269 if (priv->dpy == dpy) { 270 *prev = priv->next; 271 break; 272 } 273 } 274 _XUnlockMutex(_Xglobal_lock); 275 276 glx_display_free(priv); 277 278 return 1; 279} 280 281/* 282** Query the version of the GLX extension. This procedure works even if 283** the client extension is not completely set up. 284*/ 285static Bool 286QueryVersion(Display * dpy, int opcode, int *major, int *minor) 287{ 288#ifdef USE_XCB 289 xcb_connection_t *c = XGetXCBConnection(dpy); 290 xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c, 291 xcb_glx_query_version 292 (c, 293 GLX_MAJOR_VERSION, 294 GLX_MINOR_VERSION), 295 NULL); 296 297 if (!reply) 298 return GL_FALSE; 299 300 if (reply->major_version != GLX_MAJOR_VERSION) { 301 free(reply); 302 return GL_FALSE; 303 } 304 *major = reply->major_version; 305 *minor = min(reply->minor_version, GLX_MINOR_VERSION); 306 free(reply); 307 return GL_TRUE; 308#else 309 xGLXQueryVersionReq *req; 310 xGLXQueryVersionReply reply; 311 312 /* Send the glXQueryVersion request */ 313 LockDisplay(dpy); 314 GetReq(GLXQueryVersion, req); 315 req->reqType = opcode; 316 req->glxCode = X_GLXQueryVersion; 317 req->majorVersion = GLX_MAJOR_VERSION; 318 req->minorVersion = GLX_MINOR_VERSION; 319 _XReply(dpy, (xReply *) & reply, 0, False); 320 UnlockDisplay(dpy); 321 SyncHandle(); 322 323 if (reply.majorVersion != GLX_MAJOR_VERSION) { 324 /* 325 ** The server does not support the same major release as this 326 ** client. 327 */ 328 return GL_FALSE; 329 } 330 *major = reply.majorVersion; 331 *minor = min(reply.minorVersion, GLX_MINOR_VERSION); 332 return GL_TRUE; 333#endif /* USE_XCB */ 334} 335 336/* 337 * We don't want to enable this GLX_OML_swap_method in glxext.h, 338 * because we can't support it. The X server writes it out though, 339 * so we should handle it somehow, to avoid false warnings. 340 */ 341enum { 342 IGNORE_GLX_SWAP_METHOD_OML = 0x8060 343}; 344 345 346static GLint 347convert_from_x_visual_type(int visualType) 348{ 349 static const int glx_visual_types[] = { 350 GLX_STATIC_GRAY, GLX_GRAY_SCALE, 351 GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, 352 GLX_TRUE_COLOR, GLX_DIRECT_COLOR 353 }; 354 355 if (visualType < ARRAY_SIZE(glx_visual_types)) 356 return glx_visual_types[visualType]; 357 358 return GLX_NONE; 359} 360 361/* 362 * getVisualConfigs uses the !tagged_only path. 363 * getFBConfigs uses the tagged_only path. 364 */ 365_X_HIDDEN void 366__glXInitializeVisualConfigFromTags(struct glx_config * config, int count, 367 const INT32 * bp, Bool tagged_only, 368 Bool fbconfig_style_tags) 369{ 370 int i; 371 372 if (!tagged_only) { 373 /* Copy in the first set of properties */ 374 config->visualID = *bp++; 375 376 config->visualType = convert_from_x_visual_type(*bp++); 377 378 config->rgbMode = *bp++; 379 380 config->redBits = *bp++; 381 config->greenBits = *bp++; 382 config->blueBits = *bp++; 383 config->alphaBits = *bp++; 384 config->accumRedBits = *bp++; 385 config->accumGreenBits = *bp++; 386 config->accumBlueBits = *bp++; 387 config->accumAlphaBits = *bp++; 388 389 config->doubleBufferMode = *bp++; 390 config->stereoMode = *bp++; 391 392 config->rgbBits = *bp++; 393 config->depthBits = *bp++; 394 config->stencilBits = *bp++; 395 config->numAuxBuffers = *bp++; 396 config->level = *bp++; 397 398#ifdef GLX_USE_APPLEGL 399 /* AppleSGLX supports pixmap and pbuffers with all config. */ 400 config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 401 /* Unfortunately this can create an ABI compatibility problem. */ 402 count -= 18; 403#else 404 count -= __GLX_MIN_CONFIG_PROPS; 405#endif 406 } 407 408 /* 409 ** Additional properties may be in a list at the end 410 ** of the reply. They are in pairs of property type 411 ** and property value. 412 */ 413 414#define FETCH_OR_SET(tag) \ 415 config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1 416 417 for (i = 0; i < count; i += 2) { 418 long int tag = *bp++; 419 420 switch (tag) { 421 case GLX_RGBA: 422 FETCH_OR_SET(rgbMode); 423 break; 424 case GLX_BUFFER_SIZE: 425 config->rgbBits = *bp++; 426 break; 427 case GLX_LEVEL: 428 config->level = *bp++; 429 break; 430 case GLX_DOUBLEBUFFER: 431 FETCH_OR_SET(doubleBufferMode); 432 break; 433 case GLX_STEREO: 434 FETCH_OR_SET(stereoMode); 435 break; 436 case GLX_AUX_BUFFERS: 437 config->numAuxBuffers = *bp++; 438 break; 439 case GLX_RED_SIZE: 440 config->redBits = *bp++; 441 break; 442 case GLX_GREEN_SIZE: 443 config->greenBits = *bp++; 444 break; 445 case GLX_BLUE_SIZE: 446 config->blueBits = *bp++; 447 break; 448 case GLX_ALPHA_SIZE: 449 config->alphaBits = *bp++; 450 break; 451 case GLX_DEPTH_SIZE: 452 config->depthBits = *bp++; 453 break; 454 case GLX_STENCIL_SIZE: 455 config->stencilBits = *bp++; 456 break; 457 case GLX_ACCUM_RED_SIZE: 458 config->accumRedBits = *bp++; 459 break; 460 case GLX_ACCUM_GREEN_SIZE: 461 config->accumGreenBits = *bp++; 462 break; 463 case GLX_ACCUM_BLUE_SIZE: 464 config->accumBlueBits = *bp++; 465 break; 466 case GLX_ACCUM_ALPHA_SIZE: 467 config->accumAlphaBits = *bp++; 468 break; 469 case GLX_VISUAL_CAVEAT_EXT: 470 config->visualRating = *bp++; 471 break; 472 case GLX_X_VISUAL_TYPE: 473 config->visualType = *bp++; 474 break; 475 case GLX_TRANSPARENT_TYPE: 476 config->transparentPixel = *bp++; 477 break; 478 case GLX_TRANSPARENT_INDEX_VALUE: 479 config->transparentIndex = *bp++; 480 break; 481 case GLX_TRANSPARENT_RED_VALUE: 482 config->transparentRed = *bp++; 483 break; 484 case GLX_TRANSPARENT_GREEN_VALUE: 485 config->transparentGreen = *bp++; 486 break; 487 case GLX_TRANSPARENT_BLUE_VALUE: 488 config->transparentBlue = *bp++; 489 break; 490 case GLX_TRANSPARENT_ALPHA_VALUE: 491 config->transparentAlpha = *bp++; 492 break; 493 case GLX_VISUAL_ID: 494 config->visualID = *bp++; 495 break; 496 case GLX_DRAWABLE_TYPE: 497 config->drawableType = *bp++; 498#ifdef GLX_USE_APPLEGL 499 /* AppleSGLX supports pixmap and pbuffers with all config. */ 500 config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 501#endif 502 break; 503 case GLX_RENDER_TYPE: 504 config->renderType = *bp++; 505 break; 506 case GLX_X_RENDERABLE: 507 config->xRenderable = *bp++; 508 break; 509 case GLX_FBCONFIG_ID: 510 config->fbconfigID = *bp++; 511 break; 512 case GLX_MAX_PBUFFER_WIDTH: 513 config->maxPbufferWidth = *bp++; 514 break; 515 case GLX_MAX_PBUFFER_HEIGHT: 516 config->maxPbufferHeight = *bp++; 517 break; 518 case GLX_MAX_PBUFFER_PIXELS: 519 config->maxPbufferPixels = *bp++; 520 break; 521#ifndef GLX_USE_APPLEGL 522 case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: 523 config->optimalPbufferWidth = *bp++; 524 break; 525 case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: 526 config->optimalPbufferHeight = *bp++; 527 break; 528 case GLX_VISUAL_SELECT_GROUP_SGIX: 529 config->visualSelectGroup = *bp++; 530 break; 531 case GLX_SWAP_METHOD_OML: 532 config->swapMethod = *bp++; 533 break; 534#endif 535 case GLX_SAMPLE_BUFFERS_SGIS: 536 config->sampleBuffers = *bp++; 537 break; 538 case GLX_SAMPLES_SGIS: 539 config->samples = *bp++; 540 break; 541#ifdef GLX_USE_APPLEGL 542 case IGNORE_GLX_SWAP_METHOD_OML: 543 /* We ignore this tag. See the comment above this function. */ 544 ++bp; 545 break; 546#else 547 case GLX_BIND_TO_TEXTURE_RGB_EXT: 548 config->bindToTextureRgb = *bp++; 549 break; 550 case GLX_BIND_TO_TEXTURE_RGBA_EXT: 551 config->bindToTextureRgba = *bp++; 552 break; 553 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 554 config->bindToMipmapTexture = *bp++; 555 break; 556 case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 557 config->bindToTextureTargets = *bp++; 558 break; 559 case GLX_Y_INVERTED_EXT: 560 config->yInverted = *bp++; 561 break; 562#endif 563 case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT: 564 config->sRGBCapable = *bp++; 565 break; 566 567 case GLX_USE_GL: 568 if (fbconfig_style_tags) 569 bp++; 570 break; 571 case None: 572 i = count; 573 break; 574 default: 575 if(getenv("LIBGL_DIAGNOSTIC")) { 576 long int tagvalue = *bp++; 577 fprintf(stderr, "WARNING: unknown GLX tag from server: " 578 "tag 0x%lx value 0x%lx\n", tag, tagvalue); 579 } else { 580 /* Ignore the unrecognized tag's value */ 581 bp++; 582 } 583 break; 584 } 585 } 586 587 config->renderType = 588 (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; 589} 590 591static struct glx_config * 592createConfigsFromProperties(Display * dpy, int nvisuals, int nprops, 593 int screen, GLboolean tagged_only) 594{ 595 INT32 buf[__GLX_TOTAL_CONFIG], *props; 596 unsigned prop_size; 597 struct glx_config *modes, *m; 598 int i; 599 600 if (nprops == 0) 601 return NULL; 602 603 /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */ 604 605 /* Check number of properties */ 606 if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS) 607 return NULL; 608 609 /* Allocate memory for our config structure */ 610 modes = glx_config_create_list(nvisuals); 611 if (!modes) 612 return NULL; 613 614 prop_size = nprops * __GLX_SIZE_INT32; 615 if (prop_size <= sizeof(buf)) 616 props = buf; 617 else 618 props = Xmalloc(prop_size); 619 620 /* Read each config structure and convert it into our format */ 621 m = modes; 622 for (i = 0; i < nvisuals; i++) { 623 _XRead(dpy, (char *) props, prop_size); 624#ifdef GLX_USE_APPLEGL 625 /* Older X servers don't send this so we default it here. */ 626 m->drawableType = GLX_WINDOW_BIT; 627#else 628 /* 629 * The XQuartz 2.3.2.1 X server doesn't set this properly, so 630 * set the proper bits here. 631 * AppleSGLX supports windows, pixmaps, and pbuffers with all config. 632 */ 633 m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 634#endif 635 __glXInitializeVisualConfigFromTags(m, nprops, props, 636 tagged_only, GL_TRUE); 637 m->screen = screen; 638 m = m->next; 639 } 640 641 if (props != buf) 642 Xfree(props); 643 644 return modes; 645} 646 647static GLboolean 648getVisualConfigs(struct glx_screen *psc, 649 struct glx_display *priv, int screen) 650{ 651 xGLXGetVisualConfigsReq *req; 652 xGLXGetVisualConfigsReply reply; 653 Display *dpy = priv->dpy; 654 655 LockDisplay(dpy); 656 657 psc->visuals = NULL; 658 GetReq(GLXGetVisualConfigs, req); 659 req->reqType = priv->majorOpcode; 660 req->glxCode = X_GLXGetVisualConfigs; 661 req->screen = screen; 662 663 if (!_XReply(dpy, (xReply *) & reply, 0, False)) 664 goto out; 665 666 psc->visuals = createConfigsFromProperties(dpy, 667 reply.numVisuals, 668 reply.numProps, 669 screen, GL_FALSE); 670 671 out: 672 UnlockDisplay(dpy); 673 return psc->visuals != NULL; 674} 675 676static GLboolean 677 getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen) 678{ 679 xGLXGetFBConfigsReq *fb_req; 680 xGLXGetFBConfigsSGIXReq *sgi_req; 681 xGLXVendorPrivateWithReplyReq *vpreq; 682 xGLXGetFBConfigsReply reply; 683 Display *dpy = priv->dpy; 684 685 psc->serverGLXexts = 686 __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); 687 688 LockDisplay(dpy); 689 690 psc->configs = NULL; 691 if (atof(priv->serverGLXversion) >= 1.3) { 692 GetReq(GLXGetFBConfigs, fb_req); 693 fb_req->reqType = priv->majorOpcode; 694 fb_req->glxCode = X_GLXGetFBConfigs; 695 fb_req->screen = screen; 696 } 697 else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { 698 GetReqExtra(GLXVendorPrivateWithReply, 699 sz_xGLXGetFBConfigsSGIXReq - 700 sz_xGLXVendorPrivateWithReplyReq, vpreq); 701 sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; 702 sgi_req->reqType = priv->majorOpcode; 703 sgi_req->glxCode = X_GLXVendorPrivateWithReply; 704 sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; 705 sgi_req->screen = screen; 706 } 707 else 708 goto out; 709 710 if (!_XReply(dpy, (xReply *) & reply, 0, False)) 711 goto out; 712 713 psc->configs = createConfigsFromProperties(dpy, 714 reply.numFBConfigs, 715 reply.numAttribs * 2, 716 screen, GL_TRUE); 717 718 out: 719 UnlockDisplay(dpy); 720 return psc->configs != NULL; 721} 722 723_X_HIDDEN Bool 724glx_screen_init(struct glx_screen *psc, 725 int screen, struct glx_display * priv) 726{ 727 /* Initialize per screen dynamic client GLX extensions */ 728 psc->ext_list_first_time = GL_TRUE; 729 psc->scr = screen; 730 psc->dpy = priv->dpy; 731 psc->display = priv; 732 733 getVisualConfigs(psc, priv, screen); 734 getFBConfigs(psc, priv, screen); 735 736 return GL_TRUE; 737} 738 739_X_HIDDEN void 740glx_screen_cleanup(struct glx_screen *psc) 741{ 742 if (psc->configs) { 743 glx_config_destroy_list(psc->configs); 744 if (psc->effectiveGLXexts) 745 Xfree(psc->effectiveGLXexts); 746 psc->configs = NULL; /* NOTE: just for paranoia */ 747 } 748 if (psc->visuals) { 749 glx_config_destroy_list(psc->visuals); 750 psc->visuals = NULL; /* NOTE: just for paranoia */ 751 } 752 Xfree((char *) psc->serverGLXexts); 753} 754 755/* 756** Allocate the memory for the per screen configs for each screen. 757** If that works then fetch the per screen configs data. 758*/ 759static Bool 760AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv) 761{ 762 struct glx_screen *psc; 763 GLint i, screens; 764 765 /* 766 ** First allocate memory for the array of per screen configs. 767 */ 768 screens = ScreenCount(dpy); 769 priv->screens = Xmalloc(screens * sizeof *priv->screens); 770 if (!priv->screens) 771 return GL_FALSE; 772 773 priv->serverGLXversion = 774 __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); 775 if (priv->serverGLXversion == NULL) { 776 FreeScreenConfigs(priv); 777 return GL_FALSE; 778 } 779 780 for (i = 0; i < screens; i++, psc++) { 781 psc = NULL; 782#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 783 if (priv->dri2Display) 784 psc = (*priv->dri2Display->createScreen) (i, priv); 785 if (psc == NULL && priv->driDisplay) 786 psc = (*priv->driDisplay->createScreen) (i, priv); 787 if (psc == NULL && priv->driswDisplay) 788 psc = (*priv->driswDisplay->createScreen) (i, priv); 789#endif 790#if defined(GLX_USE_APPLEGL) 791 if (psc == NULL) 792 psc = applegl_create_screen(i, priv); 793#else 794 if (psc == NULL) 795 psc = indirect_create_screen(i, priv); 796#endif 797 priv->screens[i] = psc; 798 } 799 SyncHandle(); 800 return GL_TRUE; 801} 802 803/* 804** Initialize the client side extension code. 805*/ 806 _X_HIDDEN struct glx_display * 807__glXInitialize(Display * dpy) 808{ 809 struct glx_display *dpyPriv, *d; 810#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 811 Bool glx_direct, glx_accel; 812#endif 813 int i; 814 815 _XLockMutex(_Xglobal_lock); 816 817 for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) { 818 if (dpyPriv->dpy == dpy) { 819 _XUnlockMutex(_Xglobal_lock); 820 return dpyPriv; 821 } 822 } 823 824 /* Drop the lock while we create the display private. */ 825 _XUnlockMutex(_Xglobal_lock); 826 827 dpyPriv = Xcalloc(1, sizeof *dpyPriv); 828 if (!dpyPriv) 829 return NULL; 830 831 dpyPriv->codes = XInitExtension(dpy, __glXExtensionName); 832 if (!dpyPriv->codes) { 833 Xfree(dpyPriv); 834 _XUnlockMutex(_Xglobal_lock); 835 return NULL; 836 } 837 838 dpyPriv->dpy = dpy; 839 dpyPriv->majorOpcode = dpyPriv->codes->major_opcode; 840 dpyPriv->serverGLXvendor = 0x0; 841 dpyPriv->serverGLXversion = 0x0; 842 843 /* See if the versions are compatible. This GLX implementation does not 844 * work with servers that only support GLX 1.0. 845 */ 846 if (!QueryVersion(dpy, dpyPriv->majorOpcode, 847 &dpyPriv->majorVersion, &dpyPriv->minorVersion) 848 || (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion < 1)) { 849 Xfree(dpyPriv); 850 _XUnlockMutex(_Xglobal_lock); 851 return NULL; 852 } 853 854 for (i = 0; i < __GLX_NUMBER_EVENTS; i++) { 855 XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent); 856 XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire); 857 } 858 859 XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay); 860 XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString); 861 862 dpyPriv->glXDrawHash = __glxHashCreate(); 863 864#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 865 glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL); 866 glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL); 867 868 dpyPriv->drawHash = __glxHashCreate(); 869 870 /* 871 ** Initialize the direct rendering per display data and functions. 872 ** Note: This _must_ be done before calling any other DRI routines 873 ** (e.g., those called in AllocAndFetchScreenConfigs). 874 */ 875 if (glx_direct && glx_accel) { 876 dpyPriv->dri2Display = dri2CreateDisplay(dpy); 877 dpyPriv->driDisplay = driCreateDisplay(dpy); 878 } 879 if (glx_direct) 880 dpyPriv->driswDisplay = driswCreateDisplay(dpy); 881#endif 882 883#ifdef GLX_USE_APPLEGL 884 if (!applegl_create_display(dpyPriv)) { 885 Xfree(dpyPriv); 886 return NULL; 887 } 888#endif 889 if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { 890 Xfree(dpyPriv); 891 return NULL; 892 } 893 894#ifdef USE_XCB 895 __glX_send_client_info(dpyPriv); 896#else 897 __glXClientInfo(dpy, dpyPriv->majorOpcode); 898#endif 899 900 /* Grab the lock again and add the dispay private, unless somebody 901 * beat us to initializing on this display in the meantime. */ 902 _XLockMutex(_Xglobal_lock); 903 904 for (d = glx_displays; d; d = d->next) { 905 if (d->dpy == dpy) { 906 _XUnlockMutex(_Xglobal_lock); 907 glx_display_free(dpyPriv); 908 return d; 909 } 910 } 911 912 dpyPriv->next = glx_displays; 913 glx_displays = dpyPriv; 914 915 _XUnlockMutex(_Xglobal_lock); 916 917 return dpyPriv; 918} 919 920/* 921** Setup for sending a GLX command on dpy. Make sure the extension is 922** initialized. Try to avoid calling __glXInitialize as its kinda slow. 923*/ 924_X_HIDDEN CARD8 925__glXSetupForCommand(Display * dpy) 926{ 927 struct glx_context *gc; 928 struct glx_display *priv; 929 930 /* If this thread has a current context, flush its rendering commands */ 931 gc = __glXGetCurrentContext(); 932 if (gc->currentDpy) { 933 /* Flush rendering buffer of the current context, if any */ 934 (void) __glXFlushRenderBuffer(gc, gc->pc); 935 936 if (gc->currentDpy == dpy) { 937 /* Use opcode from gc because its right */ 938 return gc->majorOpcode; 939 } 940 else { 941 /* 942 ** Have to get info about argument dpy because it might be to 943 ** a different server 944 */ 945 } 946 } 947 948 /* Forced to lookup extension via the slow initialize route */ 949 priv = __glXInitialize(dpy); 950 if (!priv) { 951 return 0; 952 } 953 return priv->majorOpcode; 954} 955 956/** 957 * Flush the drawing command transport buffer. 958 * 959 * \param ctx Context whose transport buffer is to be flushed. 960 * \param pc Pointer to first unused buffer location. 961 * 962 * \todo 963 * Modify this function to use \c ctx->pc instead of the explicit 964 * \c pc parameter. 965 */ 966_X_HIDDEN GLubyte * 967__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc) 968{ 969 Display *const dpy = ctx->currentDpy; 970#ifdef USE_XCB 971 xcb_connection_t *c = XGetXCBConnection(dpy); 972#else 973 xGLXRenderReq *req; 974#endif /* USE_XCB */ 975 const GLint size = pc - ctx->buf; 976 977 if ((dpy != NULL) && (size > 0)) { 978#ifdef USE_XCB 979 xcb_glx_render(c, ctx->currentContextTag, size, 980 (const uint8_t *) ctx->buf); 981#else 982 /* Send the entire buffer as an X request */ 983 LockDisplay(dpy); 984 GetReq(GLXRender, req); 985 req->reqType = ctx->majorOpcode; 986 req->glxCode = X_GLXRender; 987 req->contextTag = ctx->currentContextTag; 988 req->length += (size + 3) >> 2; 989 _XSend(dpy, (char *) ctx->buf, size); 990 UnlockDisplay(dpy); 991 SyncHandle(); 992#endif 993 } 994 995 /* Reset pointer and return it */ 996 ctx->pc = ctx->buf; 997 return ctx->pc; 998} 999 1000 1001/** 1002 * Send a portion of a GLXRenderLarge command to the server. The advantage of 1003 * this function over \c __glXSendLargeCommand is that callers can use the 1004 * data buffer in the GLX context and may be able to avoid allocating an 1005 * extra buffer. The disadvantage is the clients will have to do more 1006 * GLX protocol work (i.e., calculating \c totalRequests, etc.). 1007 * 1008 * \sa __glXSendLargeCommand 1009 * 1010 * \param gc GLX context 1011 * \param requestNumber Which part of the whole command is this? The first 1012 * request is 1. 1013 * \param totalRequests How many requests will there be? 1014 * \param data Command data. 1015 * \param dataLen Size, in bytes, of the command data. 1016 */ 1017_X_HIDDEN void 1018__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber, 1019 GLint totalRequests, const GLvoid * data, GLint dataLen) 1020{ 1021 Display *dpy = gc->currentDpy; 1022#ifdef USE_XCB 1023 xcb_connection_t *c = XGetXCBConnection(dpy); 1024 xcb_glx_render_large(c, gc->currentContextTag, requestNumber, 1025 totalRequests, dataLen, data); 1026#else 1027 xGLXRenderLargeReq *req; 1028 1029 if (requestNumber == 1) { 1030 LockDisplay(dpy); 1031 } 1032 1033 GetReq(GLXRenderLarge, req); 1034 req->reqType = gc->majorOpcode; 1035 req->glxCode = X_GLXRenderLarge; 1036 req->contextTag = gc->currentContextTag; 1037 req->length += (dataLen + 3) >> 2; 1038 req->requestNumber = requestNumber; 1039 req->requestTotal = totalRequests; 1040 req->dataBytes = dataLen; 1041 Data(dpy, data, dataLen); 1042 1043 if (requestNumber == totalRequests) { 1044 UnlockDisplay(dpy); 1045 SyncHandle(); 1046 } 1047#endif /* USE_XCB */ 1048} 1049 1050 1051/** 1052 * Send a command that is too large for the GLXRender protocol request. 1053 * 1054 * Send a large command, one that is too large for some reason to 1055 * send using the GLXRender protocol request. One reason to send 1056 * a large command is to avoid copying the data. 1057 * 1058 * \param ctx GLX context 1059 * \param header Header data. 1060 * \param headerLen Size, in bytes, of the header data. It is assumed that 1061 * the header data will always be small enough to fit in 1062 * a single X protocol packet. 1063 * \param data Command data. 1064 * \param dataLen Size, in bytes, of the command data. 1065 */ 1066_X_HIDDEN void 1067__glXSendLargeCommand(struct glx_context * ctx, 1068 const GLvoid * header, GLint headerLen, 1069 const GLvoid * data, GLint dataLen) 1070{ 1071 GLint maxSize; 1072 GLint totalRequests, requestNumber; 1073 1074 /* 1075 ** Calculate the maximum amount of data can be stuffed into a single 1076 ** packet. sz_xGLXRenderReq is added because bufSize is the maximum 1077 ** packet size minus sz_xGLXRenderReq. 1078 */ 1079 maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq; 1080 totalRequests = 1 + (dataLen / maxSize); 1081 if (dataLen % maxSize) 1082 totalRequests++; 1083 1084 /* 1085 ** Send all of the command, except the large array, as one request. 1086 */ 1087 assert(headerLen <= maxSize); 1088 __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen); 1089 1090 /* 1091 ** Send enough requests until the whole array is sent. 1092 */ 1093 for (requestNumber = 2; requestNumber <= (totalRequests - 1); 1094 requestNumber++) { 1095 __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize); 1096 data = (const GLvoid *) (((const GLubyte *) data) + maxSize); 1097 dataLen -= maxSize; 1098 assert(dataLen > 0); 1099 } 1100 1101 assert(dataLen <= maxSize); 1102 __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen); 1103} 1104 1105/************************************************************************/ 1106 1107#ifdef DEBUG 1108_X_HIDDEN void 1109__glXDumpDrawBuffer(struct glx_context * ctx) 1110{ 1111 GLubyte *p = ctx->buf; 1112 GLubyte *end = ctx->pc; 1113 GLushort opcode, length; 1114 1115 while (p < end) { 1116 /* Fetch opcode */ 1117 opcode = *((GLushort *) p); 1118 length = *((GLushort *) (p + 2)); 1119 printf("%2x: %5d: ", opcode, length); 1120 length -= 4; 1121 p += 4; 1122 while (length > 0) { 1123 printf("%08x ", *((unsigned *) p)); 1124 p += 4; 1125 length -= 4; 1126 } 1127 printf("\n"); 1128 } 1129} 1130#endif 1131