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