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