Skip to content

Commit

Permalink
Add support for sRGB capable framebuffers. (#175)
Browse files Browse the repository at this point in the history
  • Loading branch information
binary1248 committed Feb 21, 2016
1 parent fe9b9c0 commit 6284f4b
Show file tree
Hide file tree
Showing 12 changed files with 145 additions and 24 deletions.
7 changes: 5 additions & 2 deletions include/SFML/Window/ContextSettings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,17 @@ struct ContextSettings
/// \param major Major number of the context version
/// \param minor Minor number of the context version
/// \param attributes Attribute flags of the context
/// \param sRgb sRGB capable framebuffer
///
////////////////////////////////////////////////////////////
explicit ContextSettings(unsigned int depth = 0, unsigned int stencil = 0, unsigned int antialiasing = 0, unsigned int major = 1, unsigned int minor = 1, unsigned int attributes = Default) :
explicit ContextSettings(unsigned int depth = 0, unsigned int stencil = 0, unsigned int antialiasing = 0, unsigned int major = 1, unsigned int minor = 1, unsigned int attributes = Default, bool sRgb = false) :
depthBits (depth),
stencilBits (stencil),
antialiasingLevel(antialiasing),
majorVersion (major),
minorVersion (minor),
attributeFlags (attributes)
attributeFlags (attributes),
sRgbCapable (sRgb)
{
}

Expand All @@ -76,6 +78,7 @@ struct ContextSettings
unsigned int majorVersion; ///< Major number of the context version to create
unsigned int minorVersion; ///< Minor number of the context version to create
Uint32 attributeFlags; ///< The attribute flags to create the context with
bool sRgbCapable; ///< Whether the context framebuffer is sRGB capable
};

} // namespace sf
Expand Down
54 changes: 44 additions & 10 deletions src/SFML/Window/GlContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@
#define GL_CONTEXT_FLAGS 0x821E
#endif

#if !defined(GL_FRAMEBUFFER_SRGB)
#define GL_FRAMEBUFFER_SRGB 0x8DB9
#endif

#if !defined(GL_CONTEXT_FLAG_DEBUG_BIT)
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
#endif
Expand Down Expand Up @@ -176,7 +180,7 @@ void GlContext::globalInit()

// Create the shared context
sharedContext = new ContextType(NULL);
sharedContext->initialize();
sharedContext->initialize(ContextSettings());

// This call makes sure that:
// - the shared context is inactive (it must never be)
Expand Down Expand Up @@ -221,7 +225,7 @@ GlContext* GlContext::create()

// Create the context
GlContext* context = new ContextType(sharedContext);
context->initialize();
context->initialize(ContextSettings());

return context;
}
Expand All @@ -237,7 +241,7 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl*

// Create the context
GlContext* context = new ContextType(sharedContext, settings, owner, bitsPerPixel);
context->initialize();
context->initialize(settings);
context->checkSettings(settings);

return context;
Expand All @@ -254,7 +258,7 @@ GlContext* GlContext::create(const ContextSettings& settings, unsigned int width

// Create the context
GlContext* context = new ContextType(sharedContext, settings, width, height);
context->initialize();
context->initialize(settings);
context->checkSettings(settings);

return context;
Expand Down Expand Up @@ -346,7 +350,7 @@ GlContext::GlContext()


////////////////////////////////////////////////////////////
int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing, bool accelerated)
int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing, bool accelerated, bool sRgb)
{
int colorDiff = static_cast<int>(bitsPerPixel) - colorBits;
int depthDiff = static_cast<int>(settings.depthBits) - depthBits;
Expand All @@ -362,6 +366,10 @@ int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings&
// Aggregate the scores
int score = std::abs(colorDiff) + std::abs(depthDiff) + std::abs(stencilDiff) + std::abs(antialiasingDiff);

// If the user wants an sRGB capable format, try really hard to get one
if (settings.sRgbCapable && !sRgb)
score += 10000000;

// Make sure we prefer hardware acceleration over features
if (!accelerated)
score += 100000000;
Expand All @@ -371,7 +379,7 @@ int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings&


////////////////////////////////////////////////////////////
void GlContext::initialize()
void GlContext::initialize(const ContextSettings& requestedSettings)
{
// Activate the context
setActive(true);
Expand Down Expand Up @@ -468,9 +476,32 @@ void GlContext::initialize()
}
}

// Enable antialiasing if needed
if (m_settings.antialiasingLevel > 0)
// Enable anti-aliasing if requested by the user and supported
if ((requestedSettings.antialiasingLevel > 0) && (m_settings.antialiasingLevel > 0))
{
glEnable(GL_MULTISAMPLE);
}
else
{
m_settings.antialiasingLevel = 0;
}

// Enable sRGB if requested by the user and supported
if (requestedSettings.sRgbCapable && m_settings.sRgbCapable)
{
glEnable(GL_FRAMEBUFFER_SRGB);

// Check to see if the enable was successful
if (glIsEnabled(GL_FRAMEBUFFER_SRGB) == GL_FALSE)
{
err() << "Warning: Failed to enable GL_FRAMEBUFFER_SRGB" << std::endl;
m_settings.sRgbCapable = false;
}
}
else
{
m_settings.sRgbCapable = false;
}
}


Expand All @@ -496,10 +527,11 @@ void GlContext::checkSettings(const ContextSettings& requestedSettings)
int requestedVersion = requestedSettings.majorVersion * 10 + requestedSettings.minorVersion;

if ((m_settings.attributeFlags != requestedSettings.attributeFlags) ||
(version < requestedVersion) ||
(version < requestedVersion) ||
(m_settings.stencilBits < requestedSettings.stencilBits) ||
(m_settings.antialiasingLevel < requestedSettings.antialiasingLevel) ||
(m_settings.depthBits < requestedSettings.depthBits))
(m_settings.depthBits < requestedSettings.depthBits) ||
(!m_settings.sRgbCapable && requestedSettings.sRgbCapable))
{
err() << "Warning: The created OpenGL context does not fully meet the settings that were requested" << std::endl;
err() << "Requested: version = " << requestedSettings.majorVersion << "." << requestedSettings.minorVersion
Expand All @@ -509,6 +541,7 @@ void GlContext::checkSettings(const ContextSettings& requestedSettings)
<< std::boolalpha
<< " ; core = " << ((requestedSettings.attributeFlags & ContextSettings::Core) != 0)
<< " ; debug = " << ((requestedSettings.attributeFlags & ContextSettings::Debug) != 0)
<< " ; sRGB = " << requestedSettings.sRgbCapable
<< std::noboolalpha << std::endl;
err() << "Created: version = " << m_settings.majorVersion << "." << m_settings.minorVersion
<< " ; depth bits = " << m_settings.depthBits
Expand All @@ -517,6 +550,7 @@ void GlContext::checkSettings(const ContextSettings& requestedSettings)
<< std::boolalpha
<< " ; core = " << ((m_settings.attributeFlags & ContextSettings::Core) != 0)
<< " ; debug = " << ((m_settings.attributeFlags & ContextSettings::Debug) != 0)
<< " ; sRGB = " << m_settings.sRgbCapable
<< std::noboolalpha << std::endl;
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/SFML/Window/GlContext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,12 @@ class GlContext : NonCopyable
/// \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
/// \param sRgb Whether the pixel format is sRGB capable
///
/// \return Score of the configuration
///
////////////////////////////////////////////////////////////
static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing, bool accelerated);
static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing, bool accelerated, bool sRgb);

////////////////////////////////////////////////////////////
// Member data
Expand All @@ -232,9 +233,10 @@ class GlContext : NonCopyable

////////////////////////////////////////////////////////////
/// \brief Perform various initializations after the context construction
/// \param requestedSettings Requested settings during context creation
///
////////////////////////////////////////////////////////////
void initialize();
void initialize(const ContextSettings& requestedSettings);

////////////////////////////////////////////////////////////
/// \brief Check whether the context is compatible with the requested settings
Expand Down
3 changes: 3 additions & 0 deletions src/SFML/Window/OSX/SFContext.mm
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@

attrs.push_back((NSOpenGLPixelFormatAttribute)0); // end of array

// All OS X pixel formats are sRGB capable
m_settings.sRgbCapable = true;

// Create the pixel format.
NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attrs[0]];

Expand Down
25 changes: 22 additions & 3 deletions src/SFML/Window/Unix/GlxContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
continue;

// Extract the components of the current visual
int red, green, blue, alpha, depth, stencil, multiSampling, samples;
int red, green, blue, alpha, depth, stencil, multiSampling, samples, sRgb;
glXGetConfig(display, &visuals[i], GLX_RED_SIZE, &red);
glXGetConfig(display, &visuals[i], GLX_GREEN_SIZE, &green);
glXGetConfig(display, &visuals[i], GLX_BLUE_SIZE, &blue);
Expand All @@ -339,12 +339,21 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
samples = 0;
}

if ((sfglx_ext_EXT_framebuffer_sRGB == sfglx_LOAD_SUCCEEDED) || (sfglx_ext_ARB_framebuffer_sRGB == sfglx_LOAD_SUCCEEDED))
{
glXGetConfig(display, &visuals[i], GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &sRgb);
}
else
{
sRgb = 0;
}

// TODO: Replace this with proper acceleration detection
bool accelerated = true;

// Evaluate the visual
int color = red + green + blue + alpha;
int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0, accelerated);
int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0, accelerated, sRgb == True);

// If it's better than the current best, make it the new best
if (score < bestScore)
Expand Down Expand Up @@ -373,7 +382,7 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
void GlxContext::updateSettingsFromVisualInfo(XVisualInfo* visualInfo)
{
// Update the creation settings from the chosen format
int depth, stencil, multiSampling, samples;
int depth, stencil, multiSampling, samples, sRgb;
glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth);
glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE, &stencil);

Expand All @@ -388,9 +397,19 @@ void GlxContext::updateSettingsFromVisualInfo(XVisualInfo* visualInfo)
samples = 0;
}

if ((sfglx_ext_EXT_framebuffer_sRGB == sfglx_LOAD_SUCCEEDED) || (sfglx_ext_ARB_framebuffer_sRGB == sfglx_LOAD_SUCCEEDED))
{
glXGetConfig(m_display, visualInfo, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &sRgb);
}
else
{
sRgb = 0;
}

m_settings.depthBits = static_cast<unsigned int>(depth);
m_settings.stencilBits = static_cast<unsigned int>(stencil);
m_settings.antialiasingLevel = multiSampling ? samples : 0;
m_settings.sRgbCapable = (sRgb == True);
}


Expand Down
12 changes: 9 additions & 3 deletions src/SFML/Window/Unix/GlxExtensions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ static sf::GlFunctionPointer IntGetProcAddress(const char* name)
int sfglx_ext_EXT_swap_control = sfglx_LOAD_FAILED;
int sfglx_ext_MESA_swap_control = sfglx_LOAD_FAILED;
int sfglx_ext_SGI_swap_control = sfglx_LOAD_FAILED;
int sfglx_ext_EXT_framebuffer_sRGB = sfglx_LOAD_FAILED;
int sfglx_ext_ARB_framebuffer_sRGB = sfglx_LOAD_FAILED;
int sfglx_ext_ARB_multisample = sfglx_LOAD_FAILED;
int sfglx_ext_SGIX_pbuffer = sfglx_LOAD_FAILED;
int sfglx_ext_ARB_create_context = sfglx_LOAD_FAILED;
Expand Down Expand Up @@ -124,17 +126,19 @@ typedef struct sfglx_StrToExtMap_s
PFN_LOADFUNCPOINTERS LoadExtension;
} sfglx_StrToExtMap;

static sfglx_StrToExtMap ExtensionMap[7] = {
static sfglx_StrToExtMap ExtensionMap[9] = {
{"GLX_EXT_swap_control", &sfglx_ext_EXT_swap_control, Load_EXT_swap_control},
{"GLX_MESA_swap_control", &sfglx_ext_MESA_swap_control, Load_MESA_swap_control},
{"GLX_SGI_swap_control", &sfglx_ext_SGI_swap_control, Load_SGI_swap_control},
{"GLX_EXT_framebuffer_sRGB", &sfglx_ext_EXT_framebuffer_sRGB, NULL},
{"GLX_ARB_framebuffer_sRGB", &sfglx_ext_ARB_framebuffer_sRGB, NULL},
{"GLX_ARB_multisample", &sfglx_ext_ARB_multisample, NULL},
{"GLX_SGIX_pbuffer", &sfglx_ext_SGIX_pbuffer, Load_SGIX_pbuffer},
{"GLX_ARB_create_context", &sfglx_ext_ARB_create_context, Load_ARB_create_context},
{"GLX_ARB_create_context_profile", &sfglx_ext_ARB_create_context_profile, NULL},
{"GLX_ARB_create_context_profile", &sfglx_ext_ARB_create_context_profile, NULL}
};

static int g_extensionMapSize = 7;
static int g_extensionMapSize = 9;


static sfglx_StrToExtMap* FindExtEntry(const char* extensionName)
Expand All @@ -155,6 +159,8 @@ static void ClearExtensionVars(void)
sfglx_ext_EXT_swap_control = sfglx_LOAD_FAILED;
sfglx_ext_MESA_swap_control = sfglx_LOAD_FAILED;
sfglx_ext_SGI_swap_control = sfglx_LOAD_FAILED;
sfglx_ext_EXT_framebuffer_sRGB = sfglx_LOAD_FAILED;
sfglx_ext_ARB_framebuffer_sRGB = sfglx_LOAD_FAILED;
sfglx_ext_ARB_multisample = sfglx_LOAD_FAILED;
sfglx_ext_SGIX_pbuffer = sfglx_LOAD_FAILED;
sfglx_ext_ARB_create_context = sfglx_LOAD_FAILED;
Expand Down
6 changes: 6 additions & 0 deletions src/SFML/Window/Unix/GlxExtensions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ extern "C" {
extern int sfglx_ext_EXT_swap_control;
extern int sfglx_ext_MESA_swap_control;
extern int sfglx_ext_SGI_swap_control;
extern int sfglx_ext_EXT_framebuffer_sRGB;
extern int sfglx_ext_ARB_framebuffer_sRGB;
extern int sfglx_ext_ARB_multisample;
extern int sfglx_ext_SGIX_pbuffer;
extern int sfglx_ext_ARB_create_context;
Expand All @@ -152,6 +154,10 @@ extern int sfglx_ext_ARB_create_context_profile;
#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
#define GLX_SWAP_INTERVAL_EXT 0x20F1

#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2

#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2

#define GLX_SAMPLES_ARB 100001
#define GLX_SAMPLE_BUFFERS_ARB 100000

Expand Down
2 changes: 2 additions & 0 deletions src/SFML/Window/Unix/GlxExtensions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
EXT_swap_control
// MESA_swap_control
SGI_swap_control
EXT_framebuffer_sRGB
ARB_framebuffer_sRGB
GLX_ARB_multisample
GLX_SGIX_pbuffer
GLX_ARB_create_context
Expand Down
34 changes: 33 additions & 1 deletion src/SFML/Window/Win32/WglContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,18 @@ int WglContext::selectBestPixelFormat(HDC deviceContext, unsigned int bitsPerPix
}
}

int sRgbCapableValue = 0;
if ((sfwgl_ext_ARB_framebuffer_sRGB == sfwgl_LOAD_SUCCEEDED) || (sfwgl_ext_EXT_framebuffer_sRGB == sfwgl_LOAD_SUCCEEDED))
{
const int sRgbCapableAttribute = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;

if (!wglGetPixelFormatAttribivARB(deviceContext, formats[i], PFD_MAIN_PLANE, 1, &sRgbCapableAttribute, &sRgbCapableValue))
{
err() << "Failed to retrieve pixel format sRGB capability information: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
break;
}
}

if (pbuffer)
{
const int pbufferAttributes[] =
Expand All @@ -324,7 +336,7 @@ int WglContext::selectBestPixelFormat(HDC deviceContext, unsigned int bitsPerPix

// Evaluate the current configuration
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);
int score = evaluateFormat(bitsPerPixel, settings, color, values[4], values[5], sampleValues[0] ? sampleValues[1] : 0, values[6] == WGL_FULL_ACCELERATION_ARB, sRgbCapableValue == TRUE);

// Keep it if it's better than the current best
if (score < bestScore)
Expand Down Expand Up @@ -444,6 +456,26 @@ void WglContext::updateSettingsFromPixelFormat()
{
m_settings.antialiasingLevel = 0;
}

if ((sfwgl_ext_ARB_framebuffer_sRGB == sfwgl_LOAD_SUCCEEDED) || (sfwgl_ext_EXT_framebuffer_sRGB == sfwgl_LOAD_SUCCEEDED))
{
const int sRgbCapableAttribute = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
int sRgbCapableValue = 0;

if (wglGetPixelFormatAttribivARB(m_deviceContext, format, PFD_MAIN_PLANE, 1, &sRgbCapableAttribute, &sRgbCapableValue))
{
m_settings.sRgbCapable = (sRgbCapableValue == TRUE);
}
else
{
err() << "Failed to retrieve pixel format sRGB capability information: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
m_settings.sRgbCapable = false;
}
}
else
{
m_settings.sRgbCapable = false;
}
}
else
{
Expand Down
Loading

0 comments on commit 6284f4b

Please sign in to comment.