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