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