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