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