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