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