glxext.c revision ad7d36e91933a49ce3f6ed2c14ae585a8a84fdf5
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 /* Ignore the unrecognized tag's value */ 543 bp++; 544 break; 545 } 546 } 547 548 config->renderType = 549 (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; 550 551 config->haveAccumBuffer = ((config->accumRedBits + 552 config->accumGreenBits + 553 config->accumBlueBits + 554 config->accumAlphaBits) > 0); 555 config->haveDepthBuffer = (config->depthBits > 0); 556 config->haveStencilBuffer = (config->stencilBits > 0); 557} 558 559static __GLcontextModes * 560createConfigsFromProperties(Display * dpy, int nvisuals, int nprops, 561 int screen, GLboolean tagged_only) 562{ 563 INT32 buf[__GLX_TOTAL_CONFIG], *props; 564 unsigned prop_size; 565 __GLcontextModes *modes, *m; 566 int i; 567 568 if (nprops == 0) 569 return NULL; 570 571 /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */ 572 573 /* Check number of properties */ 574 if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS) 575 return NULL; 576 577 /* Allocate memory for our config structure */ 578 modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes)); 579 if (!modes) 580 return NULL; 581 582 prop_size = nprops * __GLX_SIZE_INT32; 583 if (prop_size <= sizeof(buf)) 584 props = buf; 585 else 586 props = Xmalloc(prop_size); 587 588 /* Read each config structure and convert it into our format */ 589 m = modes; 590 for (i = 0; i < nvisuals; i++) { 591 _XRead(dpy, (char *) props, prop_size); 592 /* Older X servers don't send this so we default it here. */ 593 m->drawableType = GLX_WINDOW_BIT; 594 __glXInitializeVisualConfigFromTags(m, nprops, props, 595 tagged_only, GL_TRUE); 596 m->screen = screen; 597 m = m->next; 598 } 599 600 if (props != buf) 601 Xfree(props); 602 603 return modes; 604} 605 606static GLboolean 607getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) 608{ 609 xGLXGetVisualConfigsReq *req; 610 __GLXscreenConfigs *psc; 611 xGLXGetVisualConfigsReply reply; 612 613 LockDisplay(dpy); 614 615 psc = priv->screenConfigs + screen; 616 psc->visuals = NULL; 617 GetReq(GLXGetVisualConfigs, req); 618 req->reqType = priv->majorOpcode; 619 req->glxCode = X_GLXGetVisualConfigs; 620 req->screen = screen; 621 622 if (!_XReply(dpy, (xReply *) & reply, 0, False)) 623 goto out; 624 625 psc->visuals = createConfigsFromProperties(dpy, 626 reply.numVisuals, 627 reply.numProps, 628 screen, GL_FALSE); 629 630 out: 631 UnlockDisplay(dpy); 632 return psc->visuals != NULL; 633} 634 635static GLboolean 636getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) 637{ 638 xGLXGetFBConfigsReq *fb_req; 639 xGLXGetFBConfigsSGIXReq *sgi_req; 640 xGLXVendorPrivateWithReplyReq *vpreq; 641 xGLXGetFBConfigsReply reply; 642 __GLXscreenConfigs *psc; 643 644 psc = priv->screenConfigs + screen; 645 psc->serverGLXexts = 646 __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); 647 648 LockDisplay(dpy); 649 650 psc->configs = NULL; 651 if (atof(priv->serverGLXversion) >= 1.3) { 652 GetReq(GLXGetFBConfigs, fb_req); 653 fb_req->reqType = priv->majorOpcode; 654 fb_req->glxCode = X_GLXGetFBConfigs; 655 fb_req->screen = screen; 656 } 657 else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { 658 GetReqExtra(GLXVendorPrivateWithReply, 659 sz_xGLXGetFBConfigsSGIXReq + 660 sz_xGLXVendorPrivateWithReplyReq, vpreq); 661 sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; 662 sgi_req->reqType = priv->majorOpcode; 663 sgi_req->glxCode = X_GLXVendorPrivateWithReply; 664 sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; 665 sgi_req->screen = screen; 666 } 667 else 668 goto out; 669 670 if (!_XReply(dpy, (xReply *) & reply, 0, False)) 671 goto out; 672 673 psc->configs = createConfigsFromProperties(dpy, 674 reply.numFBConfigs, 675 reply.numAttribs * 2, 676 screen, GL_TRUE); 677 678 out: 679 UnlockDisplay(dpy); 680 return psc->configs != NULL; 681} 682 683/* 684** Allocate the memory for the per screen configs for each screen. 685** If that works then fetch the per screen configs data. 686*/ 687static Bool 688AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) 689{ 690 __GLXscreenConfigs *psc; 691 GLint i, screens; 692 693 /* 694 ** First allocate memory for the array of per screen configs. 695 */ 696 screens = ScreenCount(dpy); 697 psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs)); 698 if (!psc) { 699 return GL_FALSE; 700 } 701 memset(psc, 0, screens * sizeof(__GLXscreenConfigs)); 702 priv->screenConfigs = psc; 703 704 priv->serverGLXversion = 705 __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); 706 if (priv->serverGLXversion == NULL) { 707 FreeScreenConfigs(priv); 708 return GL_FALSE; 709 } 710 711 for (i = 0; i < screens; i++, psc++) { 712 getVisualConfigs(dpy, priv, i); 713 getFBConfigs(dpy, priv, i); 714 715#ifdef GLX_DIRECT_RENDERING 716 psc->scr = i; 717 psc->dpy = dpy; 718 psc->drawHash = __glxHashCreate(); 719 if (psc->drawHash == NULL) 720 continue; 721 722 /* Initialize per screen dynamic client GLX extensions */ 723 psc->ext_list_first_time = GL_TRUE; 724 725 if (priv->dri2Display) 726 psc->driScreen = (*priv->dri2Display->createScreen) (psc, i, priv); 727 728 if (psc->driScreen == NULL && priv->driDisplay) 729 psc->driScreen = (*priv->driDisplay->createScreen) (psc, i, priv); 730 731 if (psc->driScreen == NULL && priv->driswDisplay) 732 psc->driScreen = (*priv->driswDisplay->createScreen) (psc, i, priv); 733 734 if (psc->driScreen == NULL) { 735 __glxHashDestroy(psc->drawHash); 736 psc->drawHash = NULL; 737 } 738#endif 739 } 740 SyncHandle(); 741 return GL_TRUE; 742} 743 744/* 745** Initialize the client side extension code. 746*/ 747_X_HIDDEN __GLXdisplayPrivate * 748__glXInitialize(Display * dpy) 749{ 750 XExtDisplayInfo *info = __glXFindDisplay(dpy); 751 XExtData **privList, *private, *found; 752 __GLXdisplayPrivate *dpyPriv; 753 XEDataObject dataObj; 754 int major, minor; 755#ifdef GLX_DIRECT_RENDERING 756 Bool glx_direct, glx_accel; 757#endif 758 759 /* The one and only long long lock */ 760 __glXLock(); 761 762 if (!XextHasExtension(info)) { 763 /* No GLX extension supported by this server. Oh well. */ 764 __glXUnlock(); 765 XMissingExtension(dpy, __glXExtensionName); 766 return 0; 767 } 768 769 /* See if a display private already exists. If so, return it */ 770 dataObj.display = dpy; 771 privList = XEHeadOfExtensionList(dataObj); 772 found = XFindOnExtensionList(privList, info->codes->extension); 773 if (found) { 774 __glXUnlock(); 775 return (__GLXdisplayPrivate *) found->private_data; 776 } 777 778 /* See if the versions are compatible */ 779 if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) { 780 /* The client and server do not agree on versions. Punt. */ 781 __glXUnlock(); 782 return 0; 783 } 784 785 /* 786 ** Allocate memory for all the pieces needed for this buffer. 787 */ 788 private = (XExtData *) Xmalloc(sizeof(XExtData)); 789 if (!private) { 790 __glXUnlock(); 791 return 0; 792 } 793 dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate)); 794 if (!dpyPriv) { 795 __glXUnlock(); 796 Xfree((char *) private); 797 return 0; 798 } 799 800 /* 801 ** Init the display private and then read in the screen config 802 ** structures from the server. 803 */ 804 dpyPriv->majorOpcode = info->codes->major_opcode; 805 dpyPriv->majorVersion = major; 806 dpyPriv->minorVersion = minor; 807 dpyPriv->dpy = dpy; 808 809 dpyPriv->serverGLXvendor = 0x0; 810 dpyPriv->serverGLXversion = 0x0; 811 812#ifdef GLX_DIRECT_RENDERING 813 glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL); 814 glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL); 815 816 /* 817 ** Initialize the direct rendering per display data and functions. 818 ** Note: This _must_ be done before calling any other DRI routines 819 ** (e.g., those called in AllocAndFetchScreenConfigs). 820 */ 821 if (glx_direct && glx_accel) { 822 dpyPriv->dri2Display = dri2CreateDisplay(dpy); 823 dpyPriv->driDisplay = driCreateDisplay(dpy); 824 } 825 if (glx_direct) 826 dpyPriv->driswDisplay = driswCreateDisplay(dpy); 827#endif 828 829 if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { 830 __glXUnlock(); 831 Xfree((char *) dpyPriv); 832 Xfree((char *) private); 833 return 0; 834 } 835 836 /* 837 ** Fill in the private structure. This is the actual structure that 838 ** hangs off of the Display structure. Our private structure is 839 ** referred to by this structure. Got that? 840 */ 841 private->number = info->codes->extension; 842 private->next = 0; 843 private->free_private = __glXFreeDisplayPrivate; 844 private->private_data = (char *) dpyPriv; 845 XAddToExtensionList(privList, private); 846 847 if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1) { 848 __glXClientInfo(dpy, dpyPriv->majorOpcode); 849 } 850 __glXUnlock(); 851 852 return dpyPriv; 853} 854 855/* 856** Setup for sending a GLX command on dpy. Make sure the extension is 857** initialized. Try to avoid calling __glXInitialize as its kinda slow. 858*/ 859_X_HIDDEN CARD8 860__glXSetupForCommand(Display * dpy) 861{ 862 GLXContext gc; 863 __GLXdisplayPrivate *priv; 864 865 /* If this thread has a current context, flush its rendering commands */ 866 gc = __glXGetCurrentContext(); 867 if (gc->currentDpy) { 868 /* Flush rendering buffer of the current context, if any */ 869 (void) __glXFlushRenderBuffer(gc, gc->pc); 870 871 if (gc->currentDpy == dpy) { 872 /* Use opcode from gc because its right */ 873 return gc->majorOpcode; 874 } 875 else { 876 /* 877 ** Have to get info about argument dpy because it might be to 878 ** a different server 879 */ 880 } 881 } 882 883 /* Forced to lookup extension via the slow initialize route */ 884 priv = __glXInitialize(dpy); 885 if (!priv) { 886 return 0; 887 } 888 return priv->majorOpcode; 889} 890 891/** 892 * Flush the drawing command transport buffer. 893 * 894 * \param ctx Context whose transport buffer is to be flushed. 895 * \param pc Pointer to first unused buffer location. 896 * 897 * \todo 898 * Modify this function to use \c ctx->pc instead of the explicit 899 * \c pc parameter. 900 */ 901_X_HIDDEN GLubyte * 902__glXFlushRenderBuffer(__GLXcontext * ctx, GLubyte * pc) 903{ 904 Display *const dpy = ctx->currentDpy; 905#ifdef USE_XCB 906 xcb_connection_t *c = XGetXCBConnection(dpy); 907#else 908 xGLXRenderReq *req; 909#endif /* USE_XCB */ 910 const GLint size = pc - ctx->buf; 911 912 if ((dpy != NULL) && (size > 0)) { 913#ifdef USE_XCB 914 xcb_glx_render(c, ctx->currentContextTag, size, 915 (const uint8_t *) ctx->buf); 916#else 917 /* Send the entire buffer as an X request */ 918 LockDisplay(dpy); 919 GetReq(GLXRender, req); 920 req->reqType = ctx->majorOpcode; 921 req->glxCode = X_GLXRender; 922 req->contextTag = ctx->currentContextTag; 923 req->length += (size + 3) >> 2; 924 _XSend(dpy, (char *) ctx->buf, size); 925 UnlockDisplay(dpy); 926 SyncHandle(); 927#endif 928 } 929 930 /* Reset pointer and return it */ 931 ctx->pc = ctx->buf; 932 return ctx->pc; 933} 934 935 936/** 937 * Send a portion of a GLXRenderLarge command to the server. The advantage of 938 * this function over \c __glXSendLargeCommand is that callers can use the 939 * data buffer in the GLX context and may be able to avoid allocating an 940 * extra buffer. The disadvantage is the clients will have to do more 941 * GLX protocol work (i.e., calculating \c totalRequests, etc.). 942 * 943 * \sa __glXSendLargeCommand 944 * 945 * \param gc GLX context 946 * \param requestNumber Which part of the whole command is this? The first 947 * request is 1. 948 * \param totalRequests How many requests will there be? 949 * \param data Command data. 950 * \param dataLen Size, in bytes, of the command data. 951 */ 952_X_HIDDEN void 953__glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber, 954 GLint totalRequests, const GLvoid * data, GLint dataLen) 955{ 956 Display *dpy = gc->currentDpy; 957#ifdef USE_XCB 958 xcb_connection_t *c = XGetXCBConnection(dpy); 959 xcb_glx_render_large(c, gc->currentContextTag, requestNumber, 960 totalRequests, dataLen, data); 961#else 962 xGLXRenderLargeReq *req; 963 964 if (requestNumber == 1) { 965 LockDisplay(dpy); 966 } 967 968 GetReq(GLXRenderLarge, req); 969 req->reqType = gc->majorOpcode; 970 req->glxCode = X_GLXRenderLarge; 971 req->contextTag = gc->currentContextTag; 972 req->length += (dataLen + 3) >> 2; 973 req->requestNumber = requestNumber; 974 req->requestTotal = totalRequests; 975 req->dataBytes = dataLen; 976 Data(dpy, data, dataLen); 977 978 if (requestNumber == totalRequests) { 979 UnlockDisplay(dpy); 980 SyncHandle(); 981 } 982#endif /* USE_XCB */ 983} 984 985 986/** 987 * Send a command that is too large for the GLXRender protocol request. 988 * 989 * Send a large command, one that is too large for some reason to 990 * send using the GLXRender protocol request. One reason to send 991 * a large command is to avoid copying the data. 992 * 993 * \param ctx GLX context 994 * \param header Header data. 995 * \param headerLen Size, in bytes, of the header data. It is assumed that 996 * the header data will always be small enough to fit in 997 * a single X protocol packet. 998 * \param data Command data. 999 * \param dataLen Size, in bytes, of the command data. 1000 */ 1001_X_HIDDEN void 1002__glXSendLargeCommand(__GLXcontext * ctx, 1003 const GLvoid * header, GLint headerLen, 1004 const GLvoid * data, GLint dataLen) 1005{ 1006 GLint maxSize; 1007 GLint totalRequests, requestNumber; 1008 1009 /* 1010 ** Calculate the maximum amount of data can be stuffed into a single 1011 ** packet. sz_xGLXRenderReq is added because bufSize is the maximum 1012 ** packet size minus sz_xGLXRenderReq. 1013 */ 1014 maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq; 1015 totalRequests = 1 + (dataLen / maxSize); 1016 if (dataLen % maxSize) 1017 totalRequests++; 1018 1019 /* 1020 ** Send all of the command, except the large array, as one request. 1021 */ 1022 assert(headerLen <= maxSize); 1023 __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen); 1024 1025 /* 1026 ** Send enough requests until the whole array is sent. 1027 */ 1028 for (requestNumber = 2; requestNumber <= (totalRequests - 1); 1029 requestNumber++) { 1030 __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize); 1031 data = (const GLvoid *) (((const GLubyte *) data) + maxSize); 1032 dataLen -= maxSize; 1033 assert(dataLen > 0); 1034 } 1035 1036 assert(dataLen <= maxSize); 1037 __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen); 1038} 1039 1040/************************************************************************/ 1041 1042#ifdef DEBUG 1043_X_HIDDEN void 1044__glXDumpDrawBuffer(__GLXcontext * ctx) 1045{ 1046 GLubyte *p = ctx->buf; 1047 GLubyte *end = ctx->pc; 1048 GLushort opcode, length; 1049 1050 while (p < end) { 1051 /* Fetch opcode */ 1052 opcode = *((GLushort *) p); 1053 length = *((GLushort *) (p + 2)); 1054 printf("%2x: %5d: ", opcode, length); 1055 length -= 4; 1056 p += 4; 1057 while (length > 0) { 1058 printf("%08x ", *((unsigned *) p)); 1059 p += 4; 1060 length -= 4; 1061 } 1062 printf("\n"); 1063 } 1064} 1065#endif 1066