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