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