glxinit.c revision 87290a383be2eeffef4407eeb17c1070d1122b2f
1/** 2 * GLX initialization. Code based on glxext.c, glx_query.c, and 3 * glcontextmodes.c under src/glx/. The major difference is that DRI 4 * related code is stripped out. 5 * 6 * If the maintenance of this file takes too much time, we should consider 7 * refactoring glxext.c. 8 */ 9 10#include <assert.h> 11#include <X11/Xlib.h> 12#include <X11/Xproto.h> 13#include <X11/extensions/Xext.h> 14#include <X11/extensions/extutil.h> 15#include <sys/time.h> 16 17#include "glxinit.h" 18 19#ifdef GLX_DIRECT_RENDERING 20 21typedef struct GLXGenericGetString 22{ 23 CARD8 reqType; 24 CARD8 glxCode; 25 CARD16 length B16; 26 CARD32 for_whom B32; 27 CARD32 name B32; 28} xGLXGenericGetStringReq; 29 30#define sz_xGLXGenericGetStringReq 12 31#define X_GLXGenericGetString 0 32 33/* Extension required boiler plate */ 34 35static char *__glXExtensionName = GLX_EXTENSION_NAME; 36static XExtensionInfo *__glXExtensionInfo = NULL; 37 38static int 39__glXCloseDisplay(Display * dpy, XExtCodes * codes) 40{ 41 return XextRemoveDisplay(__glXExtensionInfo, dpy); 42} 43 44static /* const */ XExtensionHooks __glXExtensionHooks = { 45 NULL, /* create_gc */ 46 NULL, /* copy_gc */ 47 NULL, /* flush_gc */ 48 NULL, /* free_gc */ 49 NULL, /* create_font */ 50 NULL, /* free_font */ 51 __glXCloseDisplay, /* close_display */ 52 NULL, /* wire_to_event */ 53 NULL, /* event_to_wire */ 54 NULL, /* error */ 55 NULL, /* error_string */ 56}; 57 58XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo, 59 __glXExtensionName, &__glXExtensionHooks, 60 __GLX_NUMBER_EVENTS, NULL) 61 62static GLint 63_gl_convert_from_x_visual_type(int visualType) 64{ 65#define NUM_VISUAL_TYPES 6 66 static const int glx_visual_types[NUM_VISUAL_TYPES] = { 67 GLX_STATIC_GRAY, GLX_GRAY_SCALE, 68 GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, 69 GLX_TRUE_COLOR, GLX_DIRECT_COLOR 70 }; 71 72 return ((unsigned) visualType < NUM_VISUAL_TYPES) 73 ? glx_visual_types[visualType] : GLX_NONE; 74} 75 76static __GLcontextModes * 77_gl_context_modes_create(unsigned count, size_t minimum_size) 78{ 79 const size_t size = (minimum_size > sizeof(__GLcontextModes)) 80 ? minimum_size : sizeof(__GLcontextModes); 81 __GLcontextModes *base = NULL; 82 __GLcontextModes **next; 83 unsigned i; 84 85 next = &base; 86 for (i = 0; i < count; i++) { 87 *next = (__GLcontextModes *) Xmalloc(size); 88 if (*next == NULL) { 89 _gl_context_modes_destroy(base); 90 base = NULL; 91 break; 92 } 93 94 memset(*next, 0, size); 95 (*next)->visualID = GLX_DONT_CARE; 96 (*next)->visualType = GLX_DONT_CARE; 97 (*next)->visualRating = GLX_NONE; 98 (*next)->transparentPixel = GLX_NONE; 99 (*next)->transparentRed = GLX_DONT_CARE; 100 (*next)->transparentGreen = GLX_DONT_CARE; 101 (*next)->transparentBlue = GLX_DONT_CARE; 102 (*next)->transparentAlpha = GLX_DONT_CARE; 103 (*next)->transparentIndex = GLX_DONT_CARE; 104 (*next)->xRenderable = GLX_DONT_CARE; 105 (*next)->fbconfigID = GLX_DONT_CARE; 106 (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; 107 (*next)->bindToTextureRgb = GLX_DONT_CARE; 108 (*next)->bindToTextureRgba = GLX_DONT_CARE; 109 (*next)->bindToMipmapTexture = GLX_DONT_CARE; 110 (*next)->bindToTextureTargets = GLX_DONT_CARE; 111 (*next)->yInverted = GLX_DONT_CARE; 112 113 next = &((*next)->next); 114 } 115 116 return base; 117} 118 119_X_HIDDEN void 120_gl_context_modes_destroy(__GLcontextModes * modes) 121{ 122 while (modes != NULL) { 123 __GLcontextModes *const next = modes->next; 124 125 Xfree(modes); 126 modes = next; 127 } 128} 129 130_X_HIDDEN char * 131__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name) 132{ 133 xGLXGenericGetStringReq *req; 134 xGLXSingleReply reply; 135 int length; 136 int numbytes; 137 char *buf; 138 CARD32 for_whom = screen; 139 CARD32 glxCode = X_GLXQueryServerString; 140 141 142 LockDisplay(dpy); 143 144 145 /* All of the GLX protocol requests for getting a string from the server 146 * look the same. The exact meaning of the for_whom field is usually 147 * either the screen number (for glXQueryServerString) or the context tag 148 * (for GLXSingle). 149 */ 150 151 GetReq(GLXGenericGetString, req); 152 req->reqType = opcode; 153 req->glxCode = glxCode; 154 req->for_whom = for_whom; 155 req->name = name; 156 157 _XReply(dpy, (xReply *) & reply, 0, False); 158 159 length = reply.length * 4; 160 numbytes = reply.size; 161 162 buf = (char *) Xmalloc(numbytes); 163 if (buf != NULL) { 164 _XRead(dpy, buf, numbytes); 165 length -= numbytes; 166 } 167 168 _XEatData(dpy, length); 169 170 UnlockDisplay(dpy); 171 SyncHandle(); 172 173 return buf; 174} 175 176/************************************************************************/ 177/* 178** Free the per screen configs data as well as the array of 179** __glXScreenConfigs. 180*/ 181static void 182FreeScreenConfigs(__GLXdisplayPrivate * priv) 183{ 184 __GLXscreenConfigs *psc; 185 GLint i, screens; 186 187 /* Free screen configuration information */ 188 screens = ScreenCount(priv->dpy); 189 for (i = 0; i < screens; i++) { 190 psc = priv->screenConfigs[i]; 191 if (!psc) 192 continue; 193 if (psc->configs) { 194 _gl_context_modes_destroy(psc->configs); 195 psc->configs = NULL; /* NOTE: just for paranoia */ 196 } 197 if (psc->visuals) { 198 _gl_context_modes_destroy(psc->visuals); 199 psc->visuals = NULL; /* NOTE: just for paranoia */ 200 } 201 Xfree((char *) psc->serverGLXexts); 202 } 203 XFree((char *) priv->screenConfigs); 204 priv->screenConfigs = NULL; 205} 206 207/* 208** Release the private memory referred to in a display private 209** structure. The caller will free the extension structure. 210*/ 211static int 212__glXFreeDisplayPrivate(XExtData * extension) 213{ 214 __GLXdisplayPrivate *priv; 215 216 priv = (__GLXdisplayPrivate *) extension->private_data; 217 FreeScreenConfigs(priv); 218 if (priv->serverGLXvendor) { 219 Xfree((char *) priv->serverGLXvendor); 220 priv->serverGLXvendor = 0x0; /* to protect against double free's */ 221 } 222 if (priv->serverGLXversion) { 223 Xfree((char *) priv->serverGLXversion); 224 priv->serverGLXversion = 0x0; /* to protect against double free's */ 225 } 226 227 Xfree((char *) priv); 228 return 0; 229} 230 231/************************************************************************/ 232 233/* 234** Query the version of the GLX extension. This procedure works even if 235** the client extension is not completely set up. 236*/ 237static Bool 238QueryVersion(Display * dpy, int opcode, int *major, int *minor) 239{ 240 xGLXQueryVersionReq *req; 241 xGLXQueryVersionReply reply; 242 243 /* Send the glXQueryVersion request */ 244 LockDisplay(dpy); 245 GetReq(GLXQueryVersion, req); 246 req->reqType = opcode; 247 req->glxCode = X_GLXQueryVersion; 248 req->majorVersion = GLX_MAJOR_VERSION; 249 req->minorVersion = GLX_MINOR_VERSION; 250 _XReply(dpy, (xReply *) & reply, 0, False); 251 UnlockDisplay(dpy); 252 SyncHandle(); 253 254 if (reply.majorVersion != GLX_MAJOR_VERSION) { 255 /* 256 ** The server does not support the same major release as this 257 ** client. 258 */ 259 return GL_FALSE; 260 } 261 *major = reply.majorVersion; 262 *minor = min(reply.minorVersion, GLX_MINOR_VERSION); 263 return GL_TRUE; 264} 265 266_X_HIDDEN void 267__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, 268 const INT32 * bp, Bool tagged_only, 269 Bool fbconfig_style_tags) 270{ 271 int i; 272 273 if (!tagged_only) { 274 /* Copy in the first set of properties */ 275 config->visualID = *bp++; 276 277 config->visualType = _gl_convert_from_x_visual_type(*bp++); 278 279 config->rgbMode = *bp++; 280 281 config->redBits = *bp++; 282 config->greenBits = *bp++; 283 config->blueBits = *bp++; 284 config->alphaBits = *bp++; 285 config->accumRedBits = *bp++; 286 config->accumGreenBits = *bp++; 287 config->accumBlueBits = *bp++; 288 config->accumAlphaBits = *bp++; 289 290 config->doubleBufferMode = *bp++; 291 config->stereoMode = *bp++; 292 293 config->rgbBits = *bp++; 294 config->depthBits = *bp++; 295 config->stencilBits = *bp++; 296 config->numAuxBuffers = *bp++; 297 config->level = *bp++; 298 299 count -= __GLX_MIN_CONFIG_PROPS; 300 } 301 302 /* 303 ** Additional properties may be in a list at the end 304 ** of the reply. They are in pairs of property type 305 ** and property value. 306 */ 307 308#define FETCH_OR_SET(tag) \ 309 config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1 310 311 for (i = 0; i < count; i += 2) { 312 switch (*bp++) { 313 case GLX_RGBA: 314 FETCH_OR_SET(rgbMode); 315 break; 316 case GLX_BUFFER_SIZE: 317 config->rgbBits = *bp++; 318 break; 319 case GLX_LEVEL: 320 config->level = *bp++; 321 break; 322 case GLX_DOUBLEBUFFER: 323 FETCH_OR_SET(doubleBufferMode); 324 break; 325 case GLX_STEREO: 326 FETCH_OR_SET(stereoMode); 327 break; 328 case GLX_AUX_BUFFERS: 329 config->numAuxBuffers = *bp++; 330 break; 331 case GLX_RED_SIZE: 332 config->redBits = *bp++; 333 break; 334 case GLX_GREEN_SIZE: 335 config->greenBits = *bp++; 336 break; 337 case GLX_BLUE_SIZE: 338 config->blueBits = *bp++; 339 break; 340 case GLX_ALPHA_SIZE: 341 config->alphaBits = *bp++; 342 break; 343 case GLX_DEPTH_SIZE: 344 config->depthBits = *bp++; 345 break; 346 case GLX_STENCIL_SIZE: 347 config->stencilBits = *bp++; 348 break; 349 case GLX_ACCUM_RED_SIZE: 350 config->accumRedBits = *bp++; 351 break; 352 case GLX_ACCUM_GREEN_SIZE: 353 config->accumGreenBits = *bp++; 354 break; 355 case GLX_ACCUM_BLUE_SIZE: 356 config->accumBlueBits = *bp++; 357 break; 358 case GLX_ACCUM_ALPHA_SIZE: 359 config->accumAlphaBits = *bp++; 360 break; 361 case GLX_VISUAL_CAVEAT_EXT: 362 config->visualRating = *bp++; 363 break; 364 case GLX_X_VISUAL_TYPE: 365 config->visualType = *bp++; 366 break; 367 case GLX_TRANSPARENT_TYPE: 368 config->transparentPixel = *bp++; 369 break; 370 case GLX_TRANSPARENT_INDEX_VALUE: 371 config->transparentIndex = *bp++; 372 break; 373 case GLX_TRANSPARENT_RED_VALUE: 374 config->transparentRed = *bp++; 375 break; 376 case GLX_TRANSPARENT_GREEN_VALUE: 377 config->transparentGreen = *bp++; 378 break; 379 case GLX_TRANSPARENT_BLUE_VALUE: 380 config->transparentBlue = *bp++; 381 break; 382 case GLX_TRANSPARENT_ALPHA_VALUE: 383 config->transparentAlpha = *bp++; 384 break; 385 case GLX_VISUAL_ID: 386 config->visualID = *bp++; 387 break; 388 case GLX_DRAWABLE_TYPE: 389 config->drawableType = *bp++; 390 break; 391 case GLX_RENDER_TYPE: 392 config->renderType = *bp++; 393 break; 394 case GLX_X_RENDERABLE: 395 config->xRenderable = *bp++; 396 break; 397 case GLX_FBCONFIG_ID: 398 config->fbconfigID = *bp++; 399 break; 400 case GLX_MAX_PBUFFER_WIDTH: 401 config->maxPbufferWidth = *bp++; 402 break; 403 case GLX_MAX_PBUFFER_HEIGHT: 404 config->maxPbufferHeight = *bp++; 405 break; 406 case GLX_MAX_PBUFFER_PIXELS: 407 config->maxPbufferPixels = *bp++; 408 break; 409 case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: 410 config->optimalPbufferWidth = *bp++; 411 break; 412 case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: 413 config->optimalPbufferHeight = *bp++; 414 break; 415 case GLX_VISUAL_SELECT_GROUP_SGIX: 416 config->visualSelectGroup = *bp++; 417 break; 418 case GLX_SWAP_METHOD_OML: 419 config->swapMethod = *bp++; 420 break; 421 case GLX_SAMPLE_BUFFERS_SGIS: 422 config->sampleBuffers = *bp++; 423 break; 424 case GLX_SAMPLES_SGIS: 425 config->samples = *bp++; 426 break; 427 case GLX_BIND_TO_TEXTURE_RGB_EXT: 428 config->bindToTextureRgb = *bp++; 429 break; 430 case GLX_BIND_TO_TEXTURE_RGBA_EXT: 431 config->bindToTextureRgba = *bp++; 432 break; 433 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 434 config->bindToMipmapTexture = *bp++; 435 break; 436 case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 437 config->bindToTextureTargets = *bp++; 438 break; 439 case GLX_Y_INVERTED_EXT: 440 config->yInverted = *bp++; 441 break; 442 case None: 443 i = count; 444 break; 445 default: 446 break; 447 } 448 } 449 450 config->renderType = 451 (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; 452 453 config->haveAccumBuffer = ((config->accumRedBits + 454 config->accumGreenBits + 455 config->accumBlueBits + 456 config->accumAlphaBits) > 0); 457 config->haveDepthBuffer = (config->depthBits > 0); 458 config->haveStencilBuffer = (config->stencilBits > 0); 459} 460 461static __GLcontextModes * 462createConfigsFromProperties(Display * dpy, int nvisuals, int nprops, 463 int screen, GLboolean tagged_only) 464{ 465 INT32 buf[__GLX_TOTAL_CONFIG], *props; 466 unsigned prop_size; 467 __GLcontextModes *modes, *m; 468 int i; 469 470 if (nprops == 0) 471 return NULL; 472 473 /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */ 474 475 /* Check number of properties */ 476 if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS) 477 return NULL; 478 479 /* Allocate memory for our config structure */ 480 modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes)); 481 if (!modes) 482 return NULL; 483 484 prop_size = nprops * __GLX_SIZE_INT32; 485 if (prop_size <= sizeof(buf)) 486 props = buf; 487 else 488 props = Xmalloc(prop_size); 489 490 /* Read each config structure and convert it into our format */ 491 m = modes; 492 for (i = 0; i < nvisuals; i++) { 493 _XRead(dpy, (char *) props, prop_size); 494 /* Older X servers don't send this so we default it here. */ 495 m->drawableType = GLX_WINDOW_BIT; 496 __glXInitializeVisualConfigFromTags(m, nprops, props, 497 tagged_only, GL_TRUE); 498 m->screen = screen; 499 m = m->next; 500 } 501 502 if (props != buf) 503 Xfree(props); 504 505 return modes; 506} 507 508static GLboolean 509getVisualConfigs(__GLXscreenConfigs *psc, 510 __GLXdisplayPrivate *priv, int screen) 511{ 512 xGLXGetVisualConfigsReq *req; 513 xGLXGetVisualConfigsReply reply; 514 Display *dpy = priv->dpy; 515 516 LockDisplay(dpy); 517 518 psc->visuals = NULL; 519 GetReq(GLXGetVisualConfigs, req); 520 req->reqType = priv->majorOpcode; 521 req->glxCode = X_GLXGetVisualConfigs; 522 req->screen = screen; 523 524 if (!_XReply(dpy, (xReply *) & reply, 0, False)) 525 goto out; 526 527 psc->visuals = createConfigsFromProperties(dpy, 528 reply.numVisuals, 529 reply.numProps, 530 screen, GL_FALSE); 531 532 out: 533 UnlockDisplay(dpy); 534 return psc->visuals != NULL; 535} 536 537static GLboolean 538getFBConfigs(__GLXscreenConfigs *psc, __GLXdisplayPrivate *priv, int screen) 539{ 540 xGLXGetFBConfigsReq *fb_req; 541 xGLXGetFBConfigsSGIXReq *sgi_req; 542 xGLXVendorPrivateWithReplyReq *vpreq; 543 xGLXGetFBConfigsReply reply; 544 Display *dpy = priv->dpy; 545 546 psc->serverGLXexts = 547 __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); 548 549 LockDisplay(dpy); 550 551 psc->configs = NULL; 552 if (atof(priv->serverGLXversion) >= 1.3) { 553 GetReq(GLXGetFBConfigs, fb_req); 554 fb_req->reqType = priv->majorOpcode; 555 fb_req->glxCode = X_GLXGetFBConfigs; 556 fb_req->screen = screen; 557 } 558 else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { 559 GetReqExtra(GLXVendorPrivateWithReply, 560 sz_xGLXGetFBConfigsSGIXReq + 561 sz_xGLXVendorPrivateWithReplyReq, vpreq); 562 sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; 563 sgi_req->reqType = priv->majorOpcode; 564 sgi_req->glxCode = X_GLXVendorPrivateWithReply; 565 sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; 566 sgi_req->screen = screen; 567 } 568 else 569 goto out; 570 571 if (!_XReply(dpy, (xReply *) & reply, 0, False)) 572 goto out; 573 574 psc->configs = createConfigsFromProperties(dpy, 575 reply.numFBConfigs, 576 reply.numAttribs * 2, 577 screen, GL_TRUE); 578 579 out: 580 UnlockDisplay(dpy); 581 return psc->configs != NULL; 582} 583 584_X_HIDDEN Bool 585glx_screen_init(__GLXscreenConfigs *psc, 586 int screen, __GLXdisplayPrivate * priv) 587{ 588 /* Initialize per screen dynamic client GLX extensions */ 589 psc->ext_list_first_time = GL_TRUE; 590 psc->scr = screen; 591 psc->dpy = priv->dpy; 592 593 getVisualConfigs(psc, priv, screen); 594 getFBConfigs(psc, priv, screen); 595 596 return GL_TRUE; 597} 598 599static __GLXscreenConfigs * 600createIndirectScreen() 601{ 602 __GLXscreenConfigs *psc; 603 604 psc = Xmalloc(sizeof *psc); 605 memset(psc, 0, sizeof *psc); 606 607 return psc; 608} 609 610static GLboolean 611AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) 612{ 613 __GLXscreenConfigs *psc; 614 GLint i, screens; 615 616 /* 617 ** First allocate memory for the array of per screen configs. 618 */ 619 screens = ScreenCount(dpy); 620 priv->screenConfigs = Xmalloc(screens * sizeof *priv->screenConfigs); 621 if (!priv->screenConfigs) { 622 return GL_FALSE; 623 } 624 625 priv->serverGLXversion = 626 __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); 627 if (priv->serverGLXversion == NULL) { 628 FreeScreenConfigs(priv); 629 return GL_FALSE; 630 } 631 632 for (i = 0; i < screens; i++) { 633 psc = createIndirectScreen(); 634 if (!psc) 635 return GL_FALSE; 636 glx_screen_init(psc, i, priv); 637 priv->screenConfigs[i] = psc; 638 } 639 640 SyncHandle(); 641 642 return GL_TRUE; 643} 644 645_X_HIDDEN __GLXdisplayPrivate * 646__glXInitialize(Display * dpy) 647{ 648 XExtDisplayInfo *info = __glXFindDisplay(dpy); 649 XExtData **privList, *private, *found; 650 __GLXdisplayPrivate *dpyPriv; 651 XEDataObject dataObj; 652 int major, minor; 653 654 if (!XextHasExtension(info)) 655 return NULL; 656 657 /* See if a display private already exists. If so, return it */ 658 dataObj.display = dpy; 659 privList = XEHeadOfExtensionList(dataObj); 660 found = XFindOnExtensionList(privList, info->codes->extension); 661 if (found) 662 return (__GLXdisplayPrivate *) found->private_data; 663 664 /* See if the versions are compatible */ 665 if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) 666 return NULL; 667 668 /* 669 ** Allocate memory for all the pieces needed for this buffer. 670 */ 671 private = (XExtData *) Xmalloc(sizeof(XExtData)); 672 if (!private) 673 return NULL; 674 dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate)); 675 if (!dpyPriv) { 676 Xfree(private); 677 return NULL; 678 } 679 680 /* 681 ** Init the display private and then read in the screen config 682 ** structures from the server. 683 */ 684 dpyPriv->majorOpcode = info->codes->major_opcode; 685 dpyPriv->majorVersion = major; 686 dpyPriv->minorVersion = minor; 687 dpyPriv->dpy = dpy; 688 689 dpyPriv->serverGLXvendor = NULL; 690 dpyPriv->serverGLXversion = NULL; 691 692 if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { 693 Xfree(dpyPriv); 694 Xfree(private); 695 return NULL; 696 } 697 698 /* 699 ** Fill in the private structure. This is the actual structure that 700 ** hangs off of the Display structure. Our private structure is 701 ** referred to by this structure. Got that? 702 */ 703 private->number = info->codes->extension; 704 private->next = 0; 705 private->free_private = __glXFreeDisplayPrivate; 706 private->private_data = (char *) dpyPriv; 707 XAddToExtensionList(privList, private); 708 709 return dpyPriv; 710} 711 712#endif /* GLX_DIRECT_RENDERING */ 713