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#ifdef HAVE_DMX_CONFIG_H 32#include <dmx-config.h> 33#endif 34 35#include "dmx.h" 36#include <GL/glx.h> 37#include <GL/glxproto.h> 38#include <X11/extensions/Xext.h> 39#include <X11/extensions/extutil.h> 40 41#include "dmx_glxvisuals.h" 42 43__GLXvisualConfig *GetGLXVisualConfigs(Display *dpy, int screen, int *nconfigs) 44{ 45 xGLXGetVisualConfigsReq *req; 46 xGLXGetVisualConfigsReply reply; 47 __GLXvisualConfig *config, *configs; 48 GLint i, j, nvisuals, nprops; 49 INT32 *props, *p; 50 int majorOpcode, dummy; 51 int num_good_visuals; 52 53 if (!XQueryExtension(dpy, "GLX", &majorOpcode, &dummy, &dummy)) { 54 return NULL; 55 } 56 57 /* Send the glXGetVisualConfigs request */ 58 LockDisplay(dpy); 59 GetReq(GLXGetVisualConfigs,req); 60 req->reqType = majorOpcode; 61 req->glxCode = X_GLXGetVisualConfigs; 62 req->screen = screen; 63 if (!_XReply(dpy, (xReply*) &reply, 0, False)) { 64 /* Something is busted. Punt. */ 65 UnlockDisplay(dpy); 66 SyncHandle(); 67 return NULL; 68 } 69 70 nvisuals = (int)reply.numVisuals; 71 if (!nvisuals) { 72 /* This screen does not support GL rendering */ 73 UnlockDisplay(dpy); 74 SyncHandle(); 75 return NULL; 76 } 77 78 /* Check number of properties per visual */ 79 nprops = (int)reply.numProps; 80 if (nprops < __GLX_MIN_CONFIG_PROPS) { 81 /* Huh? Not in protocol defined limits. Punt */ 82 UnlockDisplay(dpy); 83 SyncHandle(); 84 return NULL; 85 } 86 props = (INT32*) Xmalloc(nprops * __GLX_SIZE_CARD32); 87 if (!props) { 88 UnlockDisplay(dpy); 89 SyncHandle(); 90 return NULL; 91 } 92 93 /* Allocate memory for our config structure */ 94 config = (__GLXvisualConfig*) 95 Xmalloc(nvisuals * sizeof(__GLXvisualConfig)); 96 if (!config) { 97 free(props); 98 UnlockDisplay(dpy); 99 SyncHandle(); 100 return NULL; 101 } 102 memset(config, 0, nvisuals * sizeof(__GLXvisualConfig)); 103 configs = config; 104 num_good_visuals = 0; 105 106 /* Convert config structure into our format */ 107 for (i=0; i<nvisuals; i++) { 108 109 /* Read config structure */ 110 _XRead(dpy, (char *)props, (nprops * __GLX_SIZE_CARD32)); 111 112 /* fill in default values */ 113 config->visualRating = GLX_NONE_EXT; 114 config->transparentPixel = GLX_NONE_EXT; 115 116 /* Copy in the first set of properties */ 117 config->vid = props[0]; 118 config->class = props[1]; 119 120 config->rgba = (Bool) props[2]; 121 122 config->redSize = props[3]; 123 config->greenSize = props[4]; 124 config->blueSize = props[5]; 125 config->alphaSize = props[6]; 126 127 config->accumRedSize = props[7]; 128 config->accumGreenSize = props[8]; 129 config->accumBlueSize = props[9]; 130 config->accumAlphaSize = props[10]; 131 132 config->doubleBuffer = (Bool) props[11]; 133 config->stereo = (Bool) props[12]; 134 135 config->bufferSize = props[13]; 136 config->depthSize = props[14]; 137 config->stencilSize = props[15]; 138 139 config->auxBuffers = props[16]; 140 config->level = props[17]; 141 142 /* Process remaining properties */ 143 p = &props[18]; 144 for (j=__GLX_MIN_CONFIG_PROPS; j<nprops; j+=2) { 145 int property = *p++; 146 int value = *p++; 147 148 switch (property) { 149 case GLX_SAMPLES_SGIS: 150 config->multiSampleSize = value; 151 break; 152 case GLX_SAMPLE_BUFFERS_SGIS: 153 config->nMultiSampleBuffers = value; 154 break; 155 156 case GLX_TRANSPARENT_TYPE_EXT: 157 config->transparentPixel = value; 158 break; 159 case GLX_TRANSPARENT_INDEX_VALUE_EXT: 160 config->transparentIndex = value; 161 break; 162 case GLX_TRANSPARENT_RED_VALUE_EXT: 163 config->transparentRed = value; 164 break; 165 case GLX_TRANSPARENT_GREEN_VALUE_EXT: 166 config->transparentGreen = value; 167 break; 168 case GLX_TRANSPARENT_BLUE_VALUE_EXT: 169 config->transparentBlue = value; 170 break; 171 case GLX_TRANSPARENT_ALPHA_VALUE_EXT: 172 config->transparentAlpha = value; 173 break; 174 175 case GLX_VISUAL_CAVEAT_EXT: 176 config->visualRating = value; 177 break; 178 179 /* visualSelectGroup is an internal used property */ 180 case GLX_VISUAL_SELECT_GROUP_SGIX: 181 config->visualSelectGroup = value; 182 break; 183 184 default : 185 /* Ignore properties we don't recognize */ 186 break; 187 } 188 } /* for j */ 189 190 /* 191 // filter out overlay visuals (dmx does not support overlays) 192 */ 193 if (config->level == 0) { 194 config++; 195 num_good_visuals++; 196 } 197 198 } /* for i */ 199 200 UnlockDisplay(dpy); 201 202 nvisuals = num_good_visuals; 203 204 config = configs; 205 for (i=0; i<nvisuals; i++) { 206 /* XXX hack to fill-in mask info (need a better way to do this) */ 207 { 208 XVisualInfo *vis, template; 209 int n; 210 211 template.screen = screen; 212 template.visualid = config->vid; 213 vis = XGetVisualInfo(dpy, VisualScreenMask|VisualIDMask, 214 &template, &n); 215 216 if (vis != NULL) { 217 config->redMask = vis->red_mask; 218 config->greenMask = vis->green_mask; 219 config->blueMask = vis->blue_mask; 220 config->alphaMask = 0; /* XXX */ 221 free(vis); 222 } 223 } 224 config++; 225 } /* for i */ 226 227 XFree(props); 228 SyncHandle(); 229 230 *nconfigs = nvisuals; 231 return configs; 232} 233 234 235__GLXFBConfig *GetGLXFBConfigs(Display *dpy, int glxMajorOpcode, int *nconfigs) 236{ 237 xGLXGetFBConfigsReq *req; 238 xGLXGetFBConfigsReply reply; 239 __GLXFBConfig *config, *fbconfigs; 240 GLint i, j, numFBConfigs, numAttribs; 241 INT32 *attrs, *p; 242 int screen = DefaultScreen( dpy ); 243 int numValidConfigs = 0; 244 245 /* Send the glXGetFBConfigs request */ 246 LockDisplay(dpy); 247 GetReq(GLXGetFBConfigs, req); 248 req->reqType = glxMajorOpcode; 249 req->glxCode = X_GLXGetFBConfigs; 250 req->screen = screen; 251 252 *nconfigs = 0; 253 254 if (!_XReply(dpy, (xReply*) &reply, 0, False)) { 255 /* Something is busted. Punt. */ 256 UnlockDisplay(dpy); 257 SyncHandle(); 258 return NULL; 259 } 260 261 numFBConfigs = (int)reply.numFBConfigs; 262 if (!numFBConfigs) { 263 /* This screen does not support GL rendering */ 264 UnlockDisplay(dpy); 265 SyncHandle(); 266 return NULL; 267 } 268 269 numAttribs = (int)reply.numAttribs; 270 if (!numAttribs) { 271 UnlockDisplay(dpy); 272 SyncHandle(); 273 return NULL; 274 } 275 276 attrs = (INT32*) Xmalloc(2*numAttribs * __GLX_SIZE_CARD32); 277 if (!attrs) { 278 UnlockDisplay(dpy); 279 SyncHandle(); 280 return NULL; 281 } 282 283 /* Allocate memory for our config structure */ 284 config = (__GLXFBConfig*) 285 Xmalloc(numFBConfigs * sizeof(__GLXFBConfig)); 286 if (!config) { 287 free(attrs); 288 UnlockDisplay(dpy); 289 SyncHandle(); 290 return NULL; 291 } 292 memset(config, 0, numFBConfigs * sizeof(__GLXFBConfig)); 293 fbconfigs = config; 294 295 /* Convert attribute list into our format */ 296 for (i=0; i<numFBConfigs; i++) { 297 298 /* Fill in default properties */ 299 config->transparentType = GLX_NONE_EXT; 300 config->visualCaveat = GLX_NONE_EXT; 301 config->minRed = 0.; 302 config->maxRed = 1.; 303 config->minGreen = 0.; 304 config->maxGreen = 1.; 305 config->minBlue = 0.; 306 config->maxBlue = 1.; 307 config->minAlpha = 0.; 308 config->maxAlpha = 1.; 309 310 /* Read attribute list */ 311 _XRead(dpy, (char *)attrs, (2*numAttribs * __GLX_SIZE_CARD32)); 312 313 p = attrs; 314 for (j=0; j<numAttribs; j++) { 315 int attribute = *p++; 316 int value = *p++; 317 318 switch (attribute) { 319 /* core attributes */ 320 case GLX_FBCONFIG_ID: 321 config->id = value; 322 break; 323 case GLX_BUFFER_SIZE: 324 config->indexBits = value; 325 break; 326 case GLX_LEVEL: 327 config->level = value; 328 break; 329 case GLX_DOUBLEBUFFER: 330 config->doubleBufferMode = value; 331 break; 332 case GLX_STEREO: 333 config->stereoMode = value; 334 break; 335 case GLX_AUX_BUFFERS: 336 config->maxAuxBuffers = value; 337 break; 338 case GLX_RED_SIZE: 339 config->redBits = value; 340 break; 341 case GLX_GREEN_SIZE: 342 config->greenBits = value; 343 break; 344 case GLX_BLUE_SIZE: 345 config->blueBits = value; 346 break; 347 case GLX_ALPHA_SIZE: 348 config->alphaBits = value; 349 break; 350 case GLX_DEPTH_SIZE: 351 config->depthBits = value; 352 break; 353 case GLX_STENCIL_SIZE: 354 config->stencilBits = value; 355 break; 356 case GLX_ACCUM_RED_SIZE: 357 config->accumRedBits = value; 358 break; 359 case GLX_ACCUM_GREEN_SIZE: 360 config->accumGreenBits = value; 361 break; 362 case GLX_ACCUM_BLUE_SIZE: 363 config->accumBlueBits = value; 364 break; 365 case GLX_ACCUM_ALPHA_SIZE: 366 config->accumAlphaBits = value; 367 break; 368 case GLX_RENDER_TYPE: 369 config->renderType = value; 370 break; 371 case GLX_DRAWABLE_TYPE: 372 config->drawableType = value; 373 break; 374 case GLX_X_VISUAL_TYPE: 375 config->visualType = value; 376 break; 377 case GLX_CONFIG_CAVEAT: 378 config->visualCaveat = value; 379 break; 380 case GLX_TRANSPARENT_TYPE: 381 config->transparentType = value; 382 break; 383 case GLX_TRANSPARENT_INDEX_VALUE: 384 config->transparentIndex = value; 385 break; 386 case GLX_TRANSPARENT_RED_VALUE: 387 config->transparentRed = value; 388 break; 389 case GLX_TRANSPARENT_GREEN_VALUE: 390 config->transparentGreen = value; 391 break; 392 case GLX_TRANSPARENT_BLUE_VALUE: 393 config->transparentBlue = value; 394 break; 395 case GLX_TRANSPARENT_ALPHA_VALUE: 396 config->transparentAlpha = value; 397 break; 398 case GLX_MAX_PBUFFER_WIDTH: 399 config->maxPbufferWidth = value; 400 break; 401 case GLX_MAX_PBUFFER_HEIGHT: 402 config->maxPbufferHeight = value; 403 break; 404 case GLX_MAX_PBUFFER_PIXELS: 405 config->maxPbufferPixels = value; 406 break; 407 case GLX_VISUAL_ID: 408 config->associatedVisualId = value; 409 break; 410 411 /* visualSelectGroup is an internal used property */ 412 case GLX_VISUAL_SELECT_GROUP_SGIX: 413 config->visualSelectGroup = value; 414 break; 415 416 /* SGIS_multisample attributes */ 417 case GLX_SAMPLES_SGIS: 418 config->multiSampleSize = value; 419 break; 420 case GLX_SAMPLE_BUFFERS_SGIS: 421 config->nMultiSampleBuffers = value; 422 break; 423 424 /* SGIX_pbuffer specific attributes */ 425 case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: 426 config->optimalPbufferWidth = value; 427 break; 428 case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: 429 config->optimalPbufferHeight = value; 430 break; 431 432 default: 433 /* Ignore attributes we don't recognize */ 434 break; 435 } 436 } /* for j */ 437 438 /* Fill in derived values */ 439 config->screen = screen; 440 441 config->rgbMode = config->renderType & GLX_RGBA_BIT; 442 config->colorIndexMode = !config->rgbMode; 443 444 config->haveAccumBuffer = 445 config->accumRedBits > 0 || 446 config->accumGreenBits > 0 || 447 config->accumBlueBits > 0; 448 /* Can't have alpha without color */ 449 450 config->haveDepthBuffer = config->depthBits > 0; 451 config->haveStencilBuffer = config->stencilBits > 0; 452 453 /* overlay visuals are not valid for now */ 454 if (!config->level) { 455 config++; 456 numValidConfigs++; 457 } 458 459 } /* for i */ 460 UnlockDisplay(dpy); 461 462 config = fbconfigs; 463 for (i=0; i<numValidConfigs; i++) { 464 465 /* XXX hack to fill-in mask info (need a better way to do this) */ 466 if (config->associatedVisualId != 0) { 467 XVisualInfo *vis, template; 468 int n; 469 470 template.screen = screen; 471 template.visualid = config->associatedVisualId; 472 vis = XGetVisualInfo(dpy, VisualScreenMask|VisualIDMask, 473 &template, &n); 474 475 if (vis != NULL) { 476 config->redMask = (GLuint)vis->red_mask; 477 config->greenMask = (GLuint)vis->green_mask; 478 config->blueMask = (GLuint)vis->blue_mask; 479 config->alphaMask = 0; /* XXX */ 480 free(vis); 481 } 482 } 483 484 config++; 485 } /* for i */ 486 487 XFree(attrs); 488 SyncHandle(); 489 490 *nconfigs = numValidConfigs; 491 return fbconfigs; 492} 493 494__GLXvisualConfig * 495GetGLXVisualConfigsFromFBConfigs(__GLXFBConfig *fbconfigs, int nfbconfigs, 496 XVisualInfo *visuals, int nvisuals, 497 __GLXvisualConfig *glxConfigs, int nGlxConfigs, 498 int *nconfigs) 499{ 500 __GLXvisualConfig *configs = NULL; 501 int i; 502 503 if (!fbconfigs || !nfbconfigs || !nconfigs) return NULL; 504 *nconfigs = 0; 505 506 /* Allocate memory for our config structure */ 507 configs = (__GLXvisualConfig*) 508 Xmalloc(nfbconfigs * sizeof(__GLXvisualConfig)); 509 if (!configs) { 510 return NULL; 511 } 512 memset(configs, 0, nfbconfigs * sizeof(__GLXvisualConfig)); 513 514 for (i=0; i<nfbconfigs; i++) { 515 __GLXFBConfig *fbcfg = &fbconfigs[i]; 516 517 if (fbcfg->associatedVisualId > 0) { 518 __GLXvisualConfig *cfg = configs + (*nconfigs); 519 int j; 520 XVisualInfo *vinfo = NULL; 521 522 for (j=0; j<nvisuals; j++) { 523 if (visuals[j].visualid == fbcfg->associatedVisualId) { 524 vinfo = &visuals[j]; 525 break; 526 } 527 } 528 if (!vinfo) continue; 529 530 /* skip 16 bit colormap visuals */ 531 if (vinfo->depth == 16 && 532 vinfo->class != TrueColor && 533 vinfo->class != DirectColor ) { 534 continue; 535 } 536 537 (*nconfigs)++; 538 539 /* 540 * if the same visualid exists in the glx configs, 541 * copy the glx attributes from the glx config 542 */ 543 for (j=0; j<nGlxConfigs; j++) { 544 if (glxConfigs[j].vid == vinfo->visualid) 545 break; 546 } 547 if (j < nGlxConfigs) { 548 memcpy(cfg, &glxConfigs[j], sizeof(__GLXvisualConfig) ); 549 continue; 550 } 551 552 /* 553 * make glx attributes from the FB config attributes 554 */ 555 cfg->vid = fbcfg->associatedVisualId; 556 cfg->class = vinfo->class; 557 cfg->rgba = !(fbcfg->renderType & GLX_COLOR_INDEX_BIT_SGIX); 558 cfg->redSize = fbcfg->redBits; 559 cfg->greenSize = fbcfg->greenBits; 560 cfg->blueSize = fbcfg->blueBits; 561 cfg->alphaSize = fbcfg->alphaBits; 562 cfg->redMask = fbcfg->redMask; 563 cfg->greenMask = fbcfg->greenMask; 564 cfg->blueMask = fbcfg->blueMask; 565 cfg->alphaMask = fbcfg->alphaMask; 566 cfg->accumRedSize = fbcfg->accumRedBits; 567 cfg->accumGreenSize = fbcfg->accumGreenBits; 568 cfg->accumBlueSize = fbcfg->accumBlueBits; 569 cfg->accumAlphaSize = fbcfg->accumAlphaBits; 570 cfg->doubleBuffer = fbcfg->doubleBufferMode; 571 cfg->stereo = fbcfg->stereoMode; 572 if (vinfo->class == TrueColor || vinfo->class == DirectColor) { 573 cfg->bufferSize = (fbcfg->rgbMode ? (fbcfg->redBits + 574 fbcfg->greenBits + 575 fbcfg->blueBits + 576 fbcfg->alphaBits) 577 : fbcfg->indexBits ); 578 } 579 else { 580 cfg->bufferSize = vinfo->depth; 581 } 582 cfg->depthSize = fbcfg->depthBits; 583 cfg->stencilSize = fbcfg->stencilBits; 584 cfg->auxBuffers = fbcfg->maxAuxBuffers; 585 cfg->level = fbcfg->level; 586 cfg->visualRating = fbcfg->visualCaveat; 587 cfg->transparentPixel = fbcfg->transparentType; 588 cfg->transparentRed = fbcfg->transparentRed; 589 cfg->transparentGreen = fbcfg->transparentGreen; 590 cfg->transparentBlue = fbcfg->transparentBlue; 591 cfg->transparentAlpha = fbcfg->transparentAlpha; 592 cfg->transparentIndex = fbcfg->transparentIndex; 593 cfg->multiSampleSize = fbcfg->multiSampleSize; 594 cfg->nMultiSampleBuffers = fbcfg->nMultiSampleBuffers; 595 cfg->visualSelectGroup = fbcfg->visualSelectGroup; 596 } 597 } 598 599 return configs; 600} 601 602