glxext.c revision 66fc35cde9ed68a09920ad6a28de794dd1d3aa8c
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(__GLXcontext * 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; 71static __GLXdisplayPrivate *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 __GLXdisplayPrivate *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 __GLXdisplayPrivate *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 200FreeScreenConfigs(__GLXdisplayPrivate * 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 __GLXdisplayPrivate *priv, **prev; 243 GLXContext 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 __GLXdisplayPrivate *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 678getFBConfigs(struct glx_screen *psc, __GLXdisplayPrivate *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, __GLXdisplayPrivate * 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, __GLXdisplayPrivate * 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 (psc == NULL) 776 psc = indirect_create_screen(i, priv); 777 priv->screens[i] = psc; 778 } 779 SyncHandle(); 780 return GL_TRUE; 781} 782 783/* 784** Initialize the client side extension code. 785*/ 786_X_HIDDEN __GLXdisplayPrivate * 787__glXInitialize(Display * dpy) 788{ 789 __GLXdisplayPrivate *dpyPriv; 790#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 791 Bool glx_direct, glx_accel; 792#endif 793 int i; 794 795 _XLockMutex(_Xglobal_lock); 796 797 for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) { 798 if (dpyPriv->dpy == dpy) { 799 _XUnlockMutex(_Xglobal_lock); 800 return dpyPriv; 801 } 802 } 803 804 dpyPriv = Xcalloc(1, sizeof *dpyPriv); 805 if (!dpyPriv) 806 return NULL; 807 808 dpyPriv->codes = XInitExtension(dpy, __glXExtensionName); 809 if (!dpyPriv->codes) { 810 Xfree(dpyPriv); 811 _XUnlockMutex(_Xglobal_lock); 812 return NULL; 813 } 814 815 dpyPriv->dpy = dpy; 816 dpyPriv->majorOpcode = dpyPriv->codes->major_opcode; 817 dpyPriv->serverGLXvendor = 0x0; 818 dpyPriv->serverGLXversion = 0x0; 819 820 /* See if the versions are compatible */ 821 if (!QueryVersion(dpy, dpyPriv->majorOpcode, 822 &dpyPriv->majorVersion, &dpyPriv->minorVersion)) { 823 Xfree(dpyPriv); 824 _XUnlockMutex(_Xglobal_lock); 825 return NULL; 826 } 827 828 for (i = 0; i < __GLX_NUMBER_EVENTS; i++) { 829 XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent); 830 XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire); 831 } 832 833 XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay); 834 XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString); 835 836#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 837 glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL); 838 glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL); 839 840 dpyPriv->drawHash = __glxHashCreate(); 841 842 /* 843 ** Initialize the direct rendering per display data and functions. 844 ** Note: This _must_ be done before calling any other DRI routines 845 ** (e.g., those called in AllocAndFetchScreenConfigs). 846 */ 847 if (glx_direct && glx_accel) { 848 dpyPriv->dri2Display = dri2CreateDisplay(dpy); 849 dpyPriv->driDisplay = driCreateDisplay(dpy); 850 } 851 if (glx_direct) 852 dpyPriv->driswDisplay = driswCreateDisplay(dpy); 853#endif 854 855#ifdef GLX_USE_APPLEGL 856 if (apple_init_glx(dpy)) { 857 Xfree(dpyPriv); 858 return NULL; 859 } 860#endif 861 if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { 862 Xfree(dpyPriv); 863 return NULL; 864 } 865 866 if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1) 867 __glXClientInfo(dpy, dpyPriv->majorOpcode); 868 869 dpyPriv->next = glx_displays; 870 glx_displays = dpyPriv; 871 872 _XUnlockMutex(_Xglobal_lock); 873 874 return dpyPriv; 875} 876 877/* 878** Setup for sending a GLX command on dpy. Make sure the extension is 879** initialized. Try to avoid calling __glXInitialize as its kinda slow. 880*/ 881_X_HIDDEN CARD8 882__glXSetupForCommand(Display * dpy) 883{ 884 GLXContext gc; 885 __GLXdisplayPrivate *priv; 886 887 /* If this thread has a current context, flush its rendering commands */ 888 gc = __glXGetCurrentContext(); 889 if (gc->currentDpy) { 890 /* Flush rendering buffer of the current context, if any */ 891 (void) __glXFlushRenderBuffer(gc, gc->pc); 892 893 if (gc->currentDpy == dpy) { 894 /* Use opcode from gc because its right */ 895 return gc->majorOpcode; 896 } 897 else { 898 /* 899 ** Have to get info about argument dpy because it might be to 900 ** a different server 901 */ 902 } 903 } 904 905 /* Forced to lookup extension via the slow initialize route */ 906 priv = __glXInitialize(dpy); 907 if (!priv) { 908 return 0; 909 } 910 return priv->majorOpcode; 911} 912 913/** 914 * Flush the drawing command transport buffer. 915 * 916 * \param ctx Context whose transport buffer is to be flushed. 917 * \param pc Pointer to first unused buffer location. 918 * 919 * \todo 920 * Modify this function to use \c ctx->pc instead of the explicit 921 * \c pc parameter. 922 */ 923_X_HIDDEN GLubyte * 924__glXFlushRenderBuffer(__GLXcontext * ctx, GLubyte * pc) 925{ 926 Display *const dpy = ctx->currentDpy; 927#ifdef USE_XCB 928 xcb_connection_t *c = XGetXCBConnection(dpy); 929#else 930 xGLXRenderReq *req; 931#endif /* USE_XCB */ 932 const GLint size = pc - ctx->buf; 933 934 if ((dpy != NULL) && (size > 0)) { 935#ifdef USE_XCB 936 xcb_glx_render(c, ctx->currentContextTag, size, 937 (const uint8_t *) ctx->buf); 938#else 939 /* Send the entire buffer as an X request */ 940 LockDisplay(dpy); 941 GetReq(GLXRender, req); 942 req->reqType = ctx->majorOpcode; 943 req->glxCode = X_GLXRender; 944 req->contextTag = ctx->currentContextTag; 945 req->length += (size + 3) >> 2; 946 _XSend(dpy, (char *) ctx->buf, size); 947 UnlockDisplay(dpy); 948 SyncHandle(); 949#endif 950 } 951 952 /* Reset pointer and return it */ 953 ctx->pc = ctx->buf; 954 return ctx->pc; 955} 956 957 958/** 959 * Send a portion of a GLXRenderLarge command to the server. The advantage of 960 * this function over \c __glXSendLargeCommand is that callers can use the 961 * data buffer in the GLX context and may be able to avoid allocating an 962 * extra buffer. The disadvantage is the clients will have to do more 963 * GLX protocol work (i.e., calculating \c totalRequests, etc.). 964 * 965 * \sa __glXSendLargeCommand 966 * 967 * \param gc GLX context 968 * \param requestNumber Which part of the whole command is this? The first 969 * request is 1. 970 * \param totalRequests How many requests will there be? 971 * \param data Command data. 972 * \param dataLen Size, in bytes, of the command data. 973 */ 974_X_HIDDEN void 975__glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber, 976 GLint totalRequests, const GLvoid * data, GLint dataLen) 977{ 978 Display *dpy = gc->currentDpy; 979#ifdef USE_XCB 980 xcb_connection_t *c = XGetXCBConnection(dpy); 981 xcb_glx_render_large(c, gc->currentContextTag, requestNumber, 982 totalRequests, dataLen, data); 983#else 984 xGLXRenderLargeReq *req; 985 986 if (requestNumber == 1) { 987 LockDisplay(dpy); 988 } 989 990 GetReq(GLXRenderLarge, req); 991 req->reqType = gc->majorOpcode; 992 req->glxCode = X_GLXRenderLarge; 993 req->contextTag = gc->currentContextTag; 994 req->length += (dataLen + 3) >> 2; 995 req->requestNumber = requestNumber; 996 req->requestTotal = totalRequests; 997 req->dataBytes = dataLen; 998 Data(dpy, data, dataLen); 999 1000 if (requestNumber == totalRequests) { 1001 UnlockDisplay(dpy); 1002 SyncHandle(); 1003 } 1004#endif /* USE_XCB */ 1005} 1006 1007 1008/** 1009 * Send a command that is too large for the GLXRender protocol request. 1010 * 1011 * Send a large command, one that is too large for some reason to 1012 * send using the GLXRender protocol request. One reason to send 1013 * a large command is to avoid copying the data. 1014 * 1015 * \param ctx GLX context 1016 * \param header Header data. 1017 * \param headerLen Size, in bytes, of the header data. It is assumed that 1018 * the header data will always be small enough to fit in 1019 * a single X protocol packet. 1020 * \param data Command data. 1021 * \param dataLen Size, in bytes, of the command data. 1022 */ 1023_X_HIDDEN void 1024__glXSendLargeCommand(__GLXcontext * ctx, 1025 const GLvoid * header, GLint headerLen, 1026 const GLvoid * data, GLint dataLen) 1027{ 1028 GLint maxSize; 1029 GLint totalRequests, requestNumber; 1030 1031 /* 1032 ** Calculate the maximum amount of data can be stuffed into a single 1033 ** packet. sz_xGLXRenderReq is added because bufSize is the maximum 1034 ** packet size minus sz_xGLXRenderReq. 1035 */ 1036 maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq; 1037 totalRequests = 1 + (dataLen / maxSize); 1038 if (dataLen % maxSize) 1039 totalRequests++; 1040 1041 /* 1042 ** Send all of the command, except the large array, as one request. 1043 */ 1044 assert(headerLen <= maxSize); 1045 __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen); 1046 1047 /* 1048 ** Send enough requests until the whole array is sent. 1049 */ 1050 for (requestNumber = 2; requestNumber <= (totalRequests - 1); 1051 requestNumber++) { 1052 __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize); 1053 data = (const GLvoid *) (((const GLubyte *) data) + maxSize); 1054 dataLen -= maxSize; 1055 assert(dataLen > 0); 1056 } 1057 1058 assert(dataLen <= maxSize); 1059 __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen); 1060} 1061 1062/************************************************************************/ 1063 1064#ifdef DEBUG 1065_X_HIDDEN void 1066__glXDumpDrawBuffer(__GLXcontext * ctx) 1067{ 1068 GLubyte *p = ctx->buf; 1069 GLubyte *end = ctx->pc; 1070 GLushort opcode, length; 1071 1072 while (p < end) { 1073 /* Fetch opcode */ 1074 opcode = *((GLushort *) p); 1075 length = *((GLushort *) (p + 2)); 1076 printf("%2x: %5d: ", opcode, length); 1077 length -= 4; 1078 p += 4; 1079 while (length > 0) { 1080 printf("%08x ", *((unsigned *) p)); 1081 p += 4; 1082 length -= 4; 1083 } 1084 printf("\n"); 1085 } 1086} 1087#endif 1088