Home | History | Annotate | Line # | Download | only in dmx
      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 *
    495 GetGLXVisualConfigsFromFBConfigs(__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