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