Made Windows and Unix pixel format selection more consistent with each other, fixed pixel format evaluation scoring formats with better settings equal to formats with worse settings.
This commit is contained in:
parent
bbe2c656e6
commit
ac3a5394ca
@ -340,12 +340,27 @@ GlContext::GlContext()
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing)
|
||||
int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing, bool accelerated)
|
||||
{
|
||||
return std::abs(static_cast<int>(bitsPerPixel - colorBits)) +
|
||||
std::abs(static_cast<int>(settings.depthBits - depthBits)) +
|
||||
std::abs(static_cast<int>(settings.stencilBits - stencilBits)) +
|
||||
std::abs(static_cast<int>(settings.antialiasingLevel - antialiasing));
|
||||
int colorDiff = static_cast<int>(bitsPerPixel) - colorBits;
|
||||
int depthDiff = static_cast<int>(settings.depthBits) - depthBits;
|
||||
int stencilDiff = static_cast<int>(settings.stencilBits) - stencilBits;
|
||||
int antialiasingDiff = static_cast<int>(settings.antialiasingLevel) - antialiasing;
|
||||
|
||||
// Weight sub-scores so that better settings don't score equally as bad as worse settings
|
||||
colorDiff *= ((colorDiff > 0) ? 100000 : 1);
|
||||
depthDiff *= ((depthDiff > 0) ? 100000 : 1);
|
||||
stencilDiff *= ((stencilDiff > 0) ? 100000 : 1);
|
||||
antialiasingDiff *= ((antialiasingDiff > 0) ? 100000 : 1);
|
||||
|
||||
// Aggregate the scores
|
||||
int score = std::abs(colorDiff) + std::abs(depthDiff) + std::abs(stencilDiff) + std::abs(antialiasingDiff);
|
||||
|
||||
// Make sure we prefer hardware acceleration over features
|
||||
if (!accelerated)
|
||||
score += 100000000;
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
|
@ -216,11 +216,12 @@ protected:
|
||||
/// \param depthBits Depth bits of the configuration to evaluate
|
||||
/// \param stencilBits Stencil bits of the configuration to evaluate
|
||||
/// \param antialiasing Antialiasing level of the configuration to evaluate
|
||||
/// \param accelerated Whether the pixel format is hardware accelerated
|
||||
///
|
||||
/// \return Score of the configuration
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing);
|
||||
static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing, bool accelerated);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
|
@ -308,17 +308,34 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
|
||||
XVisualInfo* visuals = XGetVisualInfo(display, 0, NULL, &count);
|
||||
if (visuals)
|
||||
{
|
||||
// There are no GLX versions prior to 1.0
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
|
||||
if (!glXQueryVersion(display, &major, &minor))
|
||||
err() << "Failed to query GLX version" << std::endl;
|
||||
|
||||
// Evaluate all the returned visuals, and pick the best one
|
||||
int bestScore = 0xFFFF;
|
||||
int bestScore = 0x7FFFFFFF;
|
||||
XVisualInfo bestVisual;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
// Check mandatory attributes
|
||||
int doubleBuffer;
|
||||
int useGL, doubleBuffer, rgba;
|
||||
glXGetConfig(display, &visuals[i], GLX_USE_GL, &useGL);
|
||||
glXGetConfig(display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer);
|
||||
if (!doubleBuffer)
|
||||
glXGetConfig(display, &visuals[i], GLX_RGBA, &rgba);
|
||||
if (!useGL || !doubleBuffer || !rgba)
|
||||
continue;
|
||||
|
||||
if (major > 1 || minor >= 3)
|
||||
{
|
||||
int drawableType;
|
||||
glXGetConfig(display, &visuals[i], GLX_DRAWABLE_TYPE, &drawableType);
|
||||
if (!(drawableType & GLX_WINDOW_BIT))
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract the components of the current visual
|
||||
int red, green, blue, alpha, depth, stencil, multiSampling, samples;
|
||||
glXGetConfig(display, &visuals[i], GLX_RED_SIZE, &red);
|
||||
@ -327,12 +344,30 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
|
||||
glXGetConfig(display, &visuals[i], GLX_ALPHA_SIZE, &alpha);
|
||||
glXGetConfig(display, &visuals[i], GLX_DEPTH_SIZE, &depth);
|
||||
glXGetConfig(display, &visuals[i], GLX_STENCIL_SIZE, &stencil);
|
||||
|
||||
if (sfglx_ext_ARB_multisample == sfglx_LOAD_SUCCEEDED)
|
||||
{
|
||||
glXGetConfig(display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
|
||||
glXGetConfig(display, &visuals[i], GLX_SAMPLES_ARB, &samples);
|
||||
}
|
||||
else
|
||||
{
|
||||
multiSampling = 0;
|
||||
samples = 0;
|
||||
}
|
||||
|
||||
bool accelerated = true;
|
||||
if (major > 1 || minor >= 3)
|
||||
{
|
||||
int caveat;
|
||||
glXGetConfig(display, &visuals[i], GLX_CONFIG_CAVEAT, &caveat);
|
||||
if (caveat == GLX_SLOW_CONFIG)
|
||||
accelerated = false;
|
||||
}
|
||||
|
||||
// Evaluate the visual
|
||||
int color = red + green + blue + alpha;
|
||||
int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0);
|
||||
int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0, accelerated);
|
||||
|
||||
// If it's better than the current best, make it the new best
|
||||
if (score < bestScore)
|
||||
|
@ -214,62 +214,71 @@ void WglContext::setVerticalSyncEnabled(bool enabled)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void WglContext::createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings)
|
||||
int WglContext::selectBestPixelFormat(HDC deviceContext, unsigned int bitsPerPixel, const ContextSettings& settings)
|
||||
{
|
||||
// Save the creation settings
|
||||
m_settings = settings;
|
||||
|
||||
// Make sure that extensions are initialized if this is not the shared context
|
||||
// The shared context is the context used to initialize the extensions
|
||||
if (shared)
|
||||
ensureExtensionsInit(m_deviceContext);
|
||||
|
||||
// Let's find a suitable pixel format -- first try with antialiasing
|
||||
// Let's find a suitable pixel format -- first try with wglChoosePixelFormatARB
|
||||
int bestFormat = 0;
|
||||
if (m_settings.antialiasingLevel > 0)
|
||||
{
|
||||
if ((sfwgl_ext_ARB_pixel_format == sfwgl_LOAD_SUCCEEDED) && (sfwgl_ext_ARB_multisample == sfwgl_LOAD_SUCCEEDED))
|
||||
if (sfwgl_ext_ARB_pixel_format == sfwgl_LOAD_SUCCEEDED)
|
||||
{
|
||||
// Define the basic attributes we want for our window
|
||||
int intAttributes[] =
|
||||
{
|
||||
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
||||
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
||||
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
|
||||
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
|
||||
WGL_SAMPLE_BUFFERS_ARB, (m_settings.antialiasingLevel ? 1 : 0),
|
||||
WGL_SAMPLES_ARB, static_cast<int>(m_settings.antialiasingLevel),
|
||||
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
|
||||
0, 0
|
||||
};
|
||||
|
||||
// Let's check how many formats are supporting our requirements
|
||||
int formats[128];
|
||||
int formats[256];
|
||||
UINT nbFormats;
|
||||
float floatAttributes[] = {0, 0};
|
||||
bool isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0;
|
||||
while ((!isValid || (nbFormats == 0)) && m_settings.antialiasingLevel > 0)
|
||||
{
|
||||
// Decrease the antialiasing level until we find a valid one
|
||||
m_settings.antialiasingLevel--;
|
||||
intAttributes[11] = m_settings.antialiasingLevel;
|
||||
isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0;
|
||||
}
|
||||
bool isValid = wglChoosePixelFormatARB(deviceContext, intAttributes, NULL, 256, formats, &nbFormats) != 0;
|
||||
|
||||
// Get the best format among the returned ones
|
||||
if (isValid && (nbFormats > 0))
|
||||
{
|
||||
int bestScore = 0xFFFF;
|
||||
int bestScore = 0x7FFFFFFF;
|
||||
for (UINT i = 0; i < nbFormats; ++i)
|
||||
{
|
||||
// Get the current format's attributes
|
||||
PIXELFORMATDESCRIPTOR attributes;
|
||||
attributes.nSize = sizeof(attributes);
|
||||
attributes.nVersion = 1;
|
||||
DescribePixelFormat(m_deviceContext, formats[i], sizeof(attributes), &attributes);
|
||||
// Extract the components of the current format
|
||||
int values[7];
|
||||
const int attributes[] =
|
||||
{
|
||||
WGL_RED_BITS_ARB,
|
||||
WGL_GREEN_BITS_ARB,
|
||||
WGL_BLUE_BITS_ARB,
|
||||
WGL_ALPHA_BITS_ARB,
|
||||
WGL_DEPTH_BITS_ARB,
|
||||
WGL_STENCIL_BITS_ARB,
|
||||
WGL_ACCELERATION_ARB
|
||||
};
|
||||
|
||||
if (!wglGetPixelFormatAttribivARB(deviceContext, formats[i], PFD_MAIN_PLANE, 7, attributes, values))
|
||||
{
|
||||
err() << "Failed to retrieve pixel format information: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
int sampleValues[2] = {0, 0};
|
||||
if (sfwgl_ext_ARB_multisample == sfwgl_LOAD_SUCCEEDED)
|
||||
{
|
||||
const int sampleAttributes[] =
|
||||
{
|
||||
WGL_SAMPLE_BUFFERS_ARB,
|
||||
WGL_SAMPLES_ARB
|
||||
};
|
||||
|
||||
if (!wglGetPixelFormatAttribivARB(deviceContext, formats[i], PFD_MAIN_PLANE, 2, sampleAttributes, sampleValues))
|
||||
{
|
||||
err() << "Failed to retrieve pixel format multisampling information: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate the current configuration
|
||||
int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits;
|
||||
int score = evaluateFormat(bitsPerPixel, m_settings, color, attributes.cDepthBits, attributes.cStencilBits, m_settings.antialiasingLevel);
|
||||
int color = values[0] + values[1] + values[2] + values[3];
|
||||
int score = evaluateFormat(bitsPerPixel, settings, color, values[4], values[5], sampleValues[0] ? sampleValues[1] : 0, values[6] == WGL_FULL_ACCELERATION_ARB);
|
||||
|
||||
// Keep it if it's better than the current best
|
||||
if (score < bestScore)
|
||||
@ -280,15 +289,8 @@ void WglContext::createContext(WglContext* shared, unsigned int bitsPerPixel, co
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// wglChoosePixelFormatARB not supported ; disabling antialiasing
|
||||
err() << "Antialiasing is not supported ; it will be disabled" << std::endl;
|
||||
m_settings.antialiasingLevel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Find a pixel format with no antialiasing, if not needed or not supported
|
||||
// Find a pixel format with ChoosePixelFormat, if wglChoosePixelFormatARB is not supported
|
||||
if (bestFormat == 0)
|
||||
{
|
||||
// Setup a pixel format descriptor from the rendering settings
|
||||
@ -300,27 +302,87 @@ void WglContext::createContext(WglContext* shared, unsigned int bitsPerPixel, co
|
||||
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
descriptor.iPixelType = PFD_TYPE_RGBA;
|
||||
descriptor.cColorBits = static_cast<BYTE>(bitsPerPixel);
|
||||
descriptor.cDepthBits = static_cast<BYTE>(m_settings.depthBits);
|
||||
descriptor.cStencilBits = static_cast<BYTE>(m_settings.stencilBits);
|
||||
descriptor.cDepthBits = static_cast<BYTE>(settings.depthBits);
|
||||
descriptor.cStencilBits = static_cast<BYTE>(settings.stencilBits);
|
||||
descriptor.cAlphaBits = bitsPerPixel == 32 ? 8 : 0;
|
||||
|
||||
// Get the pixel format that best matches our requirements
|
||||
bestFormat = ChoosePixelFormat(m_deviceContext, &descriptor);
|
||||
bestFormat = ChoosePixelFormat(deviceContext, &descriptor);
|
||||
}
|
||||
|
||||
return bestFormat;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void WglContext::createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings)
|
||||
{
|
||||
// Save the creation settings
|
||||
m_settings = settings;
|
||||
|
||||
// Make sure that extensions are initialized if this is not the shared context
|
||||
// The shared context is the context used to initialize the extensions
|
||||
if (shared)
|
||||
ensureExtensionsInit(m_deviceContext);
|
||||
|
||||
int bestFormat = selectBestPixelFormat(m_deviceContext, bitsPerPixel, settings);
|
||||
|
||||
if (bestFormat == 0)
|
||||
{
|
||||
err() << "Failed to find a suitable pixel format for device context: " << getErrorString(GetLastError()).toAnsiString() << std::endl
|
||||
<< "Cannot create OpenGL context" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the depth and stencil bits from the chosen format
|
||||
PIXELFORMATDESCRIPTOR actualFormat;
|
||||
actualFormat.nSize = sizeof(actualFormat);
|
||||
actualFormat.nVersion = 1;
|
||||
DescribePixelFormat(m_deviceContext, bestFormat, sizeof(actualFormat), &actualFormat);
|
||||
|
||||
if (sfwgl_ext_ARB_pixel_format == sfwgl_LOAD_SUCCEEDED)
|
||||
{
|
||||
const int attributes[] = {WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB};
|
||||
int values[2];
|
||||
|
||||
if (wglGetPixelFormatAttribivARB(m_deviceContext, bestFormat, PFD_MAIN_PLANE, 2, attributes, values))
|
||||
{
|
||||
m_settings.depthBits = values[0];
|
||||
m_settings.stencilBits = values[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to retrieve pixel format information: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
|
||||
m_settings.depthBits = actualFormat.cDepthBits;
|
||||
m_settings.stencilBits = actualFormat.cStencilBits;
|
||||
}
|
||||
|
||||
if (sfwgl_ext_ARB_multisample == sfwgl_LOAD_SUCCEEDED)
|
||||
{
|
||||
const int sampleAttributes[] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
|
||||
int sampleValues[2];
|
||||
|
||||
if (wglGetPixelFormatAttribivARB(m_deviceContext, bestFormat, PFD_MAIN_PLANE, 2, sampleAttributes, sampleValues))
|
||||
{
|
||||
m_settings.antialiasingLevel = sampleValues[0] ? sampleValues[1] : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to retrieve pixel format multisampling information: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
|
||||
m_settings.antialiasingLevel = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings.antialiasingLevel = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings.depthBits = actualFormat.cDepthBits;
|
||||
m_settings.stencilBits = actualFormat.cStencilBits;
|
||||
m_settings.antialiasingLevel = 0;
|
||||
}
|
||||
|
||||
// Set the chosen pixel format
|
||||
if (!SetPixelFormat(m_deviceContext, bestFormat, &actualFormat))
|
||||
|
@ -118,6 +118,18 @@ public:
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void setVerticalSyncEnabled(bool enabled);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Select the best pixel format for a given set of settings
|
||||
///
|
||||
/// \param deviceContext Device context
|
||||
/// \param bitsPerPixel Pixel depth, in bits per pixel
|
||||
/// \param settings Requested context settings
|
||||
///
|
||||
/// \return The best pixel format
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static int selectBestPixelFormat(HDC deviceContext, unsigned int bitsPerPixel, const ContextSettings& settings);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
Loading…
Reference in New Issue
Block a user