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