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