xenocara/xserver/hw/dmx/dmx_glxvisuals.c

602 lines
19 KiB
C

/*
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice including the dates of first publication and
* either this permission notice or a reference to
* http://oss.sgi.com/projects/FreeB/
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of Silicon Graphics, Inc.
* shall not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization from
* Silicon Graphics, Inc.
*/
#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#include "dmx.h"
#include <GL/glx.h>
#include <GL/glxproto.h>
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
#include "dmx_glxvisuals.h"
__GLXvisualConfig *
GetGLXVisualConfigs(Display * dpy, int screen, int *nconfigs)
{
xGLXGetVisualConfigsReq *req;
xGLXGetVisualConfigsReply reply;
__GLXvisualConfig *config, *configs;
GLint i, j, nvisuals, nprops;
INT32 *props, *p;
int majorOpcode, dummy;
int num_good_visuals;
if (!XQueryExtension(dpy, "GLX", &majorOpcode, &dummy, &dummy)) {
return NULL;
}
/* Send the glXGetVisualConfigs request */
LockDisplay(dpy);
GetReq(GLXGetVisualConfigs, req);
req->reqType = majorOpcode;
req->glxCode = X_GLXGetVisualConfigs;
req->screen = screen;
if (!_XReply(dpy, (xReply *) & reply, 0, False)) {
/* Something is busted. Punt. */
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
nvisuals = (int) reply.numVisuals;
if (!nvisuals) {
/* This screen does not support GL rendering */
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
/* Check number of properties per visual */
nprops = (int) reply.numProps;
if (nprops < __GLX_MIN_CONFIG_PROPS) {
/* Huh? Not in protocol defined limits. Punt */
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
props = (INT32 *) Xmalloc(nprops * __GLX_SIZE_CARD32);
if (!props) {
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
/* Allocate memory for our config structure */
config = (__GLXvisualConfig *)
Xmalloc(nvisuals * sizeof(__GLXvisualConfig));
if (!config) {
free(props);
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
memset(config, 0, nvisuals * sizeof(__GLXvisualConfig));
configs = config;
num_good_visuals = 0;
/* Convert config structure into our format */
for (i = 0; i < nvisuals; i++) {
/* Read config structure */
_XRead(dpy, (char *) props, (nprops * __GLX_SIZE_CARD32));
/* fill in default values */
config->visualRating = GLX_NONE_EXT;
config->transparentPixel = GLX_NONE_EXT;
/* Copy in the first set of properties */
config->vid = props[0];
config->class = props[1];
config->rgba = (Bool) props[2];
config->redSize = props[3];
config->greenSize = props[4];
config->blueSize = props[5];
config->alphaSize = props[6];
config->accumRedSize = props[7];
config->accumGreenSize = props[8];
config->accumBlueSize = props[9];
config->accumAlphaSize = props[10];
config->doubleBuffer = (Bool) props[11];
config->stereo = (Bool) props[12];
config->bufferSize = props[13];
config->depthSize = props[14];
config->stencilSize = props[15];
config->auxBuffers = props[16];
config->level = props[17];
/* Process remaining properties */
p = &props[18];
for (j = __GLX_MIN_CONFIG_PROPS; j < nprops; j += 2) {
int property = *p++;
int value = *p++;
switch (property) {
case GLX_SAMPLES_SGIS:
config->multiSampleSize = value;
break;
case GLX_SAMPLE_BUFFERS_SGIS:
config->nMultiSampleBuffers = value;
break;
case GLX_TRANSPARENT_TYPE_EXT:
config->transparentPixel = value;
break;
case GLX_TRANSPARENT_INDEX_VALUE_EXT:
config->transparentIndex = value;
break;
case GLX_TRANSPARENT_RED_VALUE_EXT:
config->transparentRed = value;
break;
case GLX_TRANSPARENT_GREEN_VALUE_EXT:
config->transparentGreen = value;
break;
case GLX_TRANSPARENT_BLUE_VALUE_EXT:
config->transparentBlue = value;
break;
case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
config->transparentAlpha = value;
break;
case GLX_VISUAL_CAVEAT_EXT:
config->visualRating = value;
break;
/* visualSelectGroup is an internal used property */
case GLX_VISUAL_SELECT_GROUP_SGIX:
config->visualSelectGroup = value;
break;
default:
/* Ignore properties we don't recognize */
break;
}
} /* for j */
/*
// filter out overlay visuals (dmx does not support overlays)
*/
if (config->level == 0) {
config++;
num_good_visuals++;
}
} /* for i */
UnlockDisplay(dpy);
nvisuals = num_good_visuals;
config = configs;
for (i = 0; i < nvisuals; i++) {
/* XXX hack to fill-in mask info (need a better way to do this) */
{
XVisualInfo *vis, template;
int n;
template.screen = screen;
template.visualid = config->vid;
vis = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
&template, &n);
if (vis != NULL) {
config->redMask = vis->red_mask;
config->greenMask = vis->green_mask;
config->blueMask = vis->blue_mask;
config->alphaMask = 0; /* XXX */
free(vis);
}
}
config++;
} /* for i */
XFree(props);
SyncHandle();
*nconfigs = nvisuals;
return configs;
}
__GLXFBConfig *
GetGLXFBConfigs(Display * dpy, int glxMajorOpcode, int *nconfigs)
{
xGLXGetFBConfigsReq *req;
xGLXGetFBConfigsReply reply;
__GLXFBConfig *config, *fbconfigs;
GLint i, j, numFBConfigs, numAttribs;
INT32 *attrs, *p;
int screen = DefaultScreen(dpy);
int numValidConfigs = 0;
/* Send the glXGetFBConfigs request */
LockDisplay(dpy);
GetReq(GLXGetFBConfigs, req);
req->reqType = glxMajorOpcode;
req->glxCode = X_GLXGetFBConfigs;
req->screen = screen;
*nconfigs = 0;
if (!_XReply(dpy, (xReply *) & reply, 0, False)) {
/* Something is busted. Punt. */
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
numFBConfigs = (int) reply.numFBConfigs;
if (!numFBConfigs) {
/* This screen does not support GL rendering */
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
numAttribs = (int) reply.numAttribs;
if (!numAttribs) {
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
attrs = (INT32 *) Xmalloc(2 * numAttribs * __GLX_SIZE_CARD32);
if (!attrs) {
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
/* Allocate memory for our config structure */
config = (__GLXFBConfig *)
Xmalloc(numFBConfigs * sizeof(__GLXFBConfig));
if (!config) {
free(attrs);
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
memset(config, 0, numFBConfigs * sizeof(__GLXFBConfig));
fbconfigs = config;
/* Convert attribute list into our format */
for (i = 0; i < numFBConfigs; i++) {
/* Fill in default properties */
config->transparentType = GLX_NONE_EXT;
config->visualCaveat = GLX_NONE_EXT;
config->minRed = 0.;
config->maxRed = 1.;
config->minGreen = 0.;
config->maxGreen = 1.;
config->minBlue = 0.;
config->maxBlue = 1.;
config->minAlpha = 0.;
config->maxAlpha = 1.;
/* Read attribute list */
_XRead(dpy, (char *) attrs, (2 * numAttribs * __GLX_SIZE_CARD32));
p = attrs;
for (j = 0; j < numAttribs; j++) {
int attribute = *p++;
int value = *p++;
switch (attribute) {
/* core attributes */
case GLX_FBCONFIG_ID:
config->id = value;
break;
case GLX_BUFFER_SIZE:
config->indexBits = value;
break;
case GLX_LEVEL:
config->level = value;
break;
case GLX_DOUBLEBUFFER:
config->doubleBufferMode = value;
break;
case GLX_STEREO:
config->stereoMode = value;
break;
case GLX_AUX_BUFFERS:
config->maxAuxBuffers = value;
break;
case GLX_RED_SIZE:
config->redBits = value;
break;
case GLX_GREEN_SIZE:
config->greenBits = value;
break;
case GLX_BLUE_SIZE:
config->blueBits = value;
break;
case GLX_ALPHA_SIZE:
config->alphaBits = value;
break;
case GLX_DEPTH_SIZE:
config->depthBits = value;
break;
case GLX_STENCIL_SIZE:
config->stencilBits = value;
break;
case GLX_ACCUM_RED_SIZE:
config->accumRedBits = value;
break;
case GLX_ACCUM_GREEN_SIZE:
config->accumGreenBits = value;
break;
case GLX_ACCUM_BLUE_SIZE:
config->accumBlueBits = value;
break;
case GLX_ACCUM_ALPHA_SIZE:
config->accumAlphaBits = value;
break;
case GLX_RENDER_TYPE:
config->renderType = value;
break;
case GLX_DRAWABLE_TYPE:
config->drawableType = value;
break;
case GLX_X_VISUAL_TYPE:
config->visualType = value;
break;
case GLX_CONFIG_CAVEAT:
config->visualCaveat = value;
break;
case GLX_TRANSPARENT_TYPE:
config->transparentType = value;
break;
case GLX_TRANSPARENT_INDEX_VALUE:
config->transparentIndex = value;
break;
case GLX_TRANSPARENT_RED_VALUE:
config->transparentRed = value;
break;
case GLX_TRANSPARENT_GREEN_VALUE:
config->transparentGreen = value;
break;
case GLX_TRANSPARENT_BLUE_VALUE:
config->transparentBlue = value;
break;
case GLX_TRANSPARENT_ALPHA_VALUE:
config->transparentAlpha = value;
break;
case GLX_MAX_PBUFFER_WIDTH:
config->maxPbufferWidth = value;
break;
case GLX_MAX_PBUFFER_HEIGHT:
config->maxPbufferHeight = value;
break;
case GLX_MAX_PBUFFER_PIXELS:
config->maxPbufferPixels = value;
break;
case GLX_VISUAL_ID:
config->associatedVisualId = value;
break;
/* visualSelectGroup is an internal used property */
case GLX_VISUAL_SELECT_GROUP_SGIX:
config->visualSelectGroup = value;
break;
/* SGIS_multisample attributes */
case GLX_SAMPLES_SGIS:
config->multiSampleSize = value;
break;
case GLX_SAMPLE_BUFFERS_SGIS:
config->nMultiSampleBuffers = value;
break;
/* SGIX_pbuffer specific attributes */
case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
config->optimalPbufferWidth = value;
break;
case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
config->optimalPbufferHeight = value;
break;
default:
/* Ignore attributes we don't recognize */
break;
}
} /* for j */
/* Fill in derived values */
config->screen = screen;
config->rgbMode = config->renderType & GLX_RGBA_BIT;
config->colorIndexMode = !config->rgbMode;
config->haveAccumBuffer =
config->accumRedBits > 0 ||
config->accumGreenBits > 0 || config->accumBlueBits > 0;
/* Can't have alpha without color */
config->haveDepthBuffer = config->depthBits > 0;
config->haveStencilBuffer = config->stencilBits > 0;
/* overlay visuals are not valid for now */
if (!config->level) {
config++;
numValidConfigs++;
}
} /* for i */
UnlockDisplay(dpy);
config = fbconfigs;
for (i = 0; i < numValidConfigs; i++) {
/* XXX hack to fill-in mask info (need a better way to do this) */
if (config->associatedVisualId != 0) {
XVisualInfo *vis, template;
int n;
template.screen = screen;
template.visualid = config->associatedVisualId;
vis = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
&template, &n);
if (vis != NULL) {
config->redMask = (GLuint) vis->red_mask;
config->greenMask = (GLuint) vis->green_mask;
config->blueMask = (GLuint) vis->blue_mask;
config->alphaMask = 0; /* XXX */
free(vis);
}
}
config++;
} /* for i */
XFree(attrs);
SyncHandle();
*nconfigs = numValidConfigs;
return fbconfigs;
}
__GLXvisualConfig *
GetGLXVisualConfigsFromFBConfigs(__GLXFBConfig * fbconfigs, int nfbconfigs,
XVisualInfo * visuals, int nvisuals,
__GLXvisualConfig * glxConfigs,
int nGlxConfigs, int *nconfigs)
{
__GLXvisualConfig *configs = NULL;
int i;
if (!fbconfigs || !nfbconfigs || !nconfigs)
return NULL;
*nconfigs = 0;
/* Allocate memory for our config structure */
configs = (__GLXvisualConfig *)
Xmalloc(nfbconfigs * sizeof(__GLXvisualConfig));
if (!configs) {
return NULL;
}
memset(configs, 0, nfbconfigs * sizeof(__GLXvisualConfig));
for (i = 0; i < nfbconfigs; i++) {
__GLXFBConfig *fbcfg = &fbconfigs[i];
if (fbcfg->associatedVisualId > 0) {
__GLXvisualConfig *cfg = configs + (*nconfigs);
int j;
XVisualInfo *vinfo = NULL;
for (j = 0; j < nvisuals; j++) {
if (visuals[j].visualid == fbcfg->associatedVisualId) {
vinfo = &visuals[j];
break;
}
}
if (!vinfo)
continue;
/* skip 16 bit colormap visuals */
if (vinfo->depth == 16 &&
vinfo->class != TrueColor && vinfo->class != DirectColor) {
continue;
}
(*nconfigs)++;
/*
* if the same visualid exists in the glx configs,
* copy the glx attributes from the glx config
*/
for (j = 0; j < nGlxConfigs; j++) {
if (glxConfigs[j].vid == vinfo->visualid)
break;
}
if (j < nGlxConfigs) {
memcpy(cfg, &glxConfigs[j], sizeof(__GLXvisualConfig));
continue;
}
/*
* make glx attributes from the FB config attributes
*/
cfg->vid = fbcfg->associatedVisualId;
cfg->class = vinfo->class;
cfg->rgba = !(fbcfg->renderType & GLX_COLOR_INDEX_BIT_SGIX);
cfg->redSize = fbcfg->redBits;
cfg->greenSize = fbcfg->greenBits;
cfg->blueSize = fbcfg->blueBits;
cfg->alphaSize = fbcfg->alphaBits;
cfg->redMask = fbcfg->redMask;
cfg->greenMask = fbcfg->greenMask;
cfg->blueMask = fbcfg->blueMask;
cfg->alphaMask = fbcfg->alphaMask;
cfg->accumRedSize = fbcfg->accumRedBits;
cfg->accumGreenSize = fbcfg->accumGreenBits;
cfg->accumBlueSize = fbcfg->accumBlueBits;
cfg->accumAlphaSize = fbcfg->accumAlphaBits;
cfg->doubleBuffer = fbcfg->doubleBufferMode;
cfg->stereo = fbcfg->stereoMode;
if (vinfo->class == TrueColor || vinfo->class == DirectColor) {
cfg->bufferSize = (fbcfg->rgbMode ? (fbcfg->redBits +
fbcfg->greenBits +
fbcfg->blueBits +
fbcfg->alphaBits)
: fbcfg->indexBits);
}
else {
cfg->bufferSize = vinfo->depth;
}
cfg->depthSize = fbcfg->depthBits;
cfg->stencilSize = fbcfg->stencilBits;
cfg->auxBuffers = fbcfg->maxAuxBuffers;
cfg->level = fbcfg->level;
cfg->visualRating = fbcfg->visualCaveat;
cfg->transparentPixel = fbcfg->transparentType;
cfg->transparentRed = fbcfg->transparentRed;
cfg->transparentGreen = fbcfg->transparentGreen;
cfg->transparentBlue = fbcfg->transparentBlue;
cfg->transparentAlpha = fbcfg->transparentAlpha;
cfg->transparentIndex = fbcfg->transparentIndex;
cfg->multiSampleSize = fbcfg->multiSampleSize;
cfg->nMultiSampleBuffers = fbcfg->nMultiSampleBuffers;
cfg->visualSelectGroup = fbcfg->visualSelectGroup;
}
}
return configs;
}