pkg://bzflag-debuginfo-2.0.8-22.x86_64.rpm:13305265/
usr/
src/
debug/
bzflag-2.0.8/
src/
platform/XVisual.cxx
info downloads
/* bzflag
* Copyright (c) 1993 - 2006 Tim Riker
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "XVisual.h"
#include <assert.h>
#include <string.h>
#include <GL/glx.h>
XVisual::XVisual(const XDisplay* _display) :
display(_display->getRep()),
attributeCount(0),
visual(NULL)
{
display->ref();
attributes[attributeCount] = None;
}
XVisual::~XVisual()
{
if (visual) XFree(visual);
display->unref();
}
// NOTE: to keep searching simple I cheat. All bool attributes
// are followed by GLX_USE_GL (which is a bool and ignored)
// so that interesting attributes always fall on even indices.
void XVisual::setLevel(int level)
{
int index = findAttribute(GLX_LEVEL);
if (index == -1) appendAttribute(GLX_LEVEL, level);
else editAttribute(index, level);
}
void XVisual::setDoubleBuffer(bool on)
{
int index = findAttribute(GLX_DOUBLEBUFFER);
if (!on) {
if (index != -1) removeAttribute(index);
}
else {
if (index == -1) appendAttribute(GLX_DOUBLEBUFFER, GLX_USE_GL);
}
}
void XVisual::setIndex(int minDepth)
{
int index = findAttribute(GLX_RGBA);
if (index != -1) removeAttribute(index);
index = findAttribute(GLX_BUFFER_SIZE);
if (index == -1) appendAttribute(GLX_BUFFER_SIZE, minDepth);
else editAttribute(index, minDepth);
}
void XVisual::setRGBA(int minRed, int minGreen,
int minBlue, int minAlpha)
{
int index = findAttribute(GLX_RGBA);
if (index == -1) appendAttribute(GLX_RGBA, GLX_USE_GL);
index = findAttribute(GLX_RED_SIZE);
if (index == -1) appendAttribute(GLX_RED_SIZE, minRed);
else editAttribute(index, minRed);
index = findAttribute(GLX_GREEN_SIZE);
if (index == -1) appendAttribute(GLX_GREEN_SIZE, minGreen);
else editAttribute(index, minGreen);
index = findAttribute(GLX_BLUE_SIZE);
if (index == -1) appendAttribute(GLX_BLUE_SIZE, minBlue);
else editAttribute(index, minBlue);
index = findAttribute(GLX_ALPHA_SIZE);
if (minAlpha == 0) {
if (index != -1) removeAttribute(index);
}
else if (index == -1) appendAttribute(GLX_ALPHA_SIZE, minAlpha);
else editAttribute(index, minAlpha);
}
void XVisual::setDepth(int minDepth)
{
int index = findAttribute(GLX_DEPTH_SIZE);
if (minDepth == 0) {
if (index != -1) removeAttribute(index);
}
else if (index == -1) appendAttribute(GLX_DEPTH_SIZE, minDepth);
else editAttribute(index, minDepth);
}
void XVisual::setStencil(int minDepth)
{
int index = findAttribute(GLX_STENCIL_SIZE);
if (minDepth == 0) {
if (index != -1) removeAttribute(index);
}
else if (index == -1) appendAttribute(GLX_STENCIL_SIZE, minDepth);
else editAttribute(index, minDepth);
}
void XVisual::setAccum(int minRed, int minGreen,
int minBlue, int minAlpha)
{
int index = findAttribute(GLX_ACCUM_RED_SIZE);
if (index == -1) appendAttribute(GLX_ACCUM_RED_SIZE, minRed);
else editAttribute(index, minRed);
index = findAttribute(GLX_ACCUM_GREEN_SIZE);
if (index == -1) appendAttribute(GLX_ACCUM_GREEN_SIZE, minGreen);
else editAttribute(index, minGreen);
index = findAttribute(GLX_ACCUM_BLUE_SIZE);
if (index == -1) appendAttribute(GLX_ACCUM_BLUE_SIZE, minBlue);
else editAttribute(index, minBlue);
index = findAttribute(GLX_ACCUM_ALPHA_SIZE);
if (index == -1) appendAttribute(GLX_ACCUM_ALPHA_SIZE, minAlpha);
else editAttribute(index, minAlpha);
}
void XVisual::setStereo(bool on)
{
int index = findAttribute(GLX_STEREO);
if (!on) {
if (index != -1) removeAttribute(index);
}
else {
if (index == -1) appendAttribute(GLX_STEREO, GLX_USE_GL);
}
}
void XVisual::setMultisample(int minSamples)
{
(void)minSamples; // quiet compiler if ifdef'd code not used
#if defined(GLX_SAMPLES_SGIS) && defined(GLX_SGIS_multisample)
int index = findAttribute(GLX_SAMPLES_SGIS);
if (index == -1) appendAttribute(GLX_SAMPLES_SGIS, minSamples);
else editAttribute(index, minSamples);
#endif
}
int XVisual::findAttribute(int attribute) const
{
for (int i = 0; i < attributeCount; i += 2)
if (attributes[i] == attribute)
return i;
return -1;
}
void XVisual::appendAttribute(int attribute, int value)
{
attributes[attributeCount] = attribute;
attributes[attributeCount+1] = value;
attributeCount += 2;
attributes[attributeCount] = None;
}
void XVisual::removeAttribute(int index)
{
attributeCount -= 2;
attributes[index] = attributes[attributeCount];
attributes[index+1] = attributes[attributeCount+1];
attributes[attributeCount] = None;
}
void XVisual::editAttribute(int index, int value)
{
attributes[index+1] = value;
}
bool XVisual::build()
{
if (!visual && getenv("MESA_RGB_VISUAL") == NULL) {
// check each available visual looking for the best match.
// we prefer deeper and dynamic (rather than static) visuals.
// first get the list of all visuals by making a template to
// match any visual on the screen and matching it.
const long visualMask = VisualScreenMask;
XVisualInfo visualTemplate;
visualTemplate.screen = display->getScreen();
int numVisuals;
XVisualInfo* visualList = XGetVisualInfo(display->getDisplay(),
visualMask,
&visualTemplate,
&numVisuals);
if (numVisuals > 0 && visualList != NULL) {
// no best visual so far
int bestVisual = -1;
int attrib;
// now check each visual
for (int i = 0; i < numVisuals; i++) {
// ignore visuals that aren't deep enough
if (visualList[i].depth < 8)
continue;
// ignore visuals that glX can't use
if (glXGetConfig(display->getDisplay(), visualList + i,
GLX_USE_GL, &attrib) != 0 ||
attrib == GL_FALSE)
continue;
// ignore visuals that don't satisfy our requirements
if (!matchRequirements(visualList + i))
continue;
// use visual if it's better than the existing one. some visual
// is always better than none at all.
if (bestVisual == -1) {
bestVisual = i;
continue;
}
// DirectColor is better than other visual classes, then
// PseudoColor, then TrueColor, then StaticColor, then GreyScale.
if (visualClassIsBetter(visualList[i].c_class,
visualList[bestVisual].c_class)) {
bestVisual = i;
continue;
}
// if visual class wasn't better and isn't the same then it
// must be worse.
if (visualList[i].c_class != visualList[bestVisual].c_class)
continue;
// deeper is better
if (visualList[i].depth > visualList[bestVisual].depth) {
bestVisual = i;
continue;
}
// not better
}
// save best visual, if one was found
if (bestVisual != -1) {
visual = XGetVisualInfo(display->getDisplay(),
VisualAllMask,
visualList + bestVisual,
&numVisuals);
if (numVisuals == 0)
visual = NULL;
}
// done with visuals
XFree(visualList);
}
}
// emergency backup plan -- let glXChooseVisual choose for us
if (!visual) {
visual = glXChooseVisual(display->getDisplay(),
display->getScreen(), attributes);
}
return visual != NULL;
}
bool XVisual::matchRequirements(XVisualInfo* v) const
{
// check RGBA, DOUBLEBUFFER, and STEREO
int value;
if (glXGetConfig(display->getDisplay(), v, GLX_RGBA, &value) != 0 ||
(findAttribute(GLX_RGBA) != -1) != value)
return false;
if (glXGetConfig(display->getDisplay(), v, GLX_DOUBLEBUFFER, &value) != 0 ||
(findAttribute(GLX_DOUBLEBUFFER) != -1) != value)
return false;
if (glXGetConfig(display->getDisplay(), v, GLX_STEREO, &value) != 0 ||
(findAttribute(GLX_STEREO) != -1) != value)
return false;
// check the rest
for (int i = 0; i < attributeCount; i += 2) {
// get value of desired attribute from visual
if (glXGetConfig(display->getDisplay(), v, attributes[i], &value) != 0)
return false;
// compare to desired value
switch (attributes[i]) {
case GLX_RGBA:
case GLX_DOUBLEBUFFER:
case GLX_STEREO:
// skip these
break;
case GLX_LEVEL:
if (value != attributes[i + 1])
return false;
break;
case GLX_BUFFER_SIZE:
case GLX_RED_SIZE:
case GLX_GREEN_SIZE:
case GLX_BLUE_SIZE:
case GLX_ALPHA_SIZE:
case GLX_DEPTH_SIZE:
case GLX_STENCIL_SIZE:
case GLX_ACCUM_RED_SIZE:
case GLX_ACCUM_GREEN_SIZE:
case GLX_ACCUM_BLUE_SIZE:
case GLX_ACCUM_ALPHA_SIZE:
#if defined(GLX_SAMPLES_SGIS) && defined(GLX_SGIS_multisample)
case GLX_SAMPLES_SGIS:
#endif
if (value < attributes[i + 1])
return false;
break;
default:
assert(0 && "unexpected GLX attribute");
}
}
return true;
}
bool XVisual::visualClassIsBetter(int a, int b)
{
// not better if the same
if (a == b)
return false;
// direct color is best
if (a == DirectColor)
return true;
if (b == DirectColor)
return false;
// then pseudo color (because we can adjust it)
if (a == PseudoColor)
return true;
if (b == PseudoColor)
return false;
// then true color
if (a == TrueColor)
return true;
if (b == TrueColor)
return false;
// then static color
if (a == StaticColor)
return true;
if (b == StaticColor)
return false;
// then gray scale
if (a == GrayScale)
return true;
return false;
}
XVisualInfo* XVisual::get()
{
if (!build()) return NULL;
return visual;
}
// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8