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