Make EGL pixel format selection follow the same procedure as the other context types and make OpenGL context version parsing more tolerant of garbage data. Fixes #2395
This commit is contained in:
parent
7004db1cd9
commit
6a3feda5ab
@ -263,15 +263,17 @@ bool RenderTextureImplFBO::create(const Vector2u& size, unsigned int textureId,
|
||||
static_cast<GLsizei>(size.x),
|
||||
static_cast<GLsizei>(size.y)));
|
||||
|
||||
m_stencil = true;
|
||||
|
||||
#else
|
||||
|
||||
m_stencil = false;
|
||||
|
||||
err() << "Impossible to create render texture (failed to create the attached depth/stencil buffer)"
|
||||
<< std::endl;
|
||||
return false;
|
||||
|
||||
#endif // SFML_OPENGL_ES
|
||||
|
||||
m_stencil = true;
|
||||
}
|
||||
else if (settings.depthBits)
|
||||
{
|
||||
@ -355,14 +357,16 @@ bool RenderTextureImplFBO::create(const Vector2u& size, unsigned int textureId,
|
||||
static_cast<GLsizei>(size.y)));
|
||||
}
|
||||
|
||||
m_multisample = true;
|
||||
|
||||
#else
|
||||
|
||||
m_multisample = false;
|
||||
|
||||
err() << "Impossible to create render texture (failed to create the multisample render buffers)" << std::endl;
|
||||
return false;
|
||||
|
||||
#endif // SFML_OPENGL_ES
|
||||
|
||||
m_multisample = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <SFML/Window/EglContext.hpp>
|
||||
#include <SFML/Window/WindowImpl.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <ostream>
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
@ -80,18 +81,27 @@ EGLDisplay getInitializedDisplay()
|
||||
////////////////////////////////////////////////////////////
|
||||
void ensureInit()
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = true;
|
||||
static std::once_flag flag;
|
||||
|
||||
// We don't check the return value since the extension
|
||||
// flags are cleared even if loading fails
|
||||
gladLoaderLoadEGL(EGL_NO_DISPLAY);
|
||||
std::call_once(flag,
|
||||
[]()
|
||||
{
|
||||
if (!gladLoaderLoadEGL(EGL_NO_DISPLAY))
|
||||
{
|
||||
// At this point, the failure is unrecoverable
|
||||
// Dump a message to the console and let the application terminate
|
||||
sf::err() << "Failed to load EGL entry points" << std::endl;
|
||||
|
||||
assert(false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Continue loading with a display
|
||||
gladLoaderLoadEGL(getInitializedDisplay());
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
} // namespace EglContextImpl
|
||||
} // namespace
|
||||
@ -287,67 +297,100 @@ EGLConfig EglContext::getBestConfig(EGLDisplay display, unsigned int bitsPerPixe
|
||||
{
|
||||
EglContextImpl::ensureInit();
|
||||
|
||||
// Set our video settings constraint
|
||||
const EGLint attributes[] =
|
||||
{EGL_BUFFER_SIZE,
|
||||
static_cast<EGLint>(bitsPerPixel),
|
||||
EGL_DEPTH_SIZE,
|
||||
static_cast<EGLint>(settings.depthBits),
|
||||
EGL_STENCIL_SIZE,
|
||||
static_cast<EGLint>(settings.stencilBits),
|
||||
EGL_SAMPLE_BUFFERS,
|
||||
settings.antialiasingLevel ? 1 : 0,
|
||||
EGL_SAMPLES,
|
||||
static_cast<EGLint>(settings.antialiasingLevel),
|
||||
EGL_SURFACE_TYPE,
|
||||
EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
|
||||
EGL_RENDERABLE_TYPE,
|
||||
EGL_OPENGL_ES_BIT,
|
||||
EGL_NONE};
|
||||
|
||||
// Determine the number of available configs
|
||||
EGLint configCount;
|
||||
EGLConfig configs[1];
|
||||
eglCheck(eglGetConfigs(display, nullptr, 0, &configCount));
|
||||
|
||||
// Ask EGL for the best config matching our video settings
|
||||
eglCheck(eglChooseConfig(display, attributes, configs, 1, &configCount));
|
||||
// Retrieve the list of available configs
|
||||
auto configs = std::make_unique<EGLConfig[]>(static_cast<std::size_t>(configCount));
|
||||
|
||||
// TODO: This should check EGL_CONFORMANT and pick the first conformant configuration.
|
||||
eglCheck(eglGetConfigs(display, configs.get(), configCount, &configCount));
|
||||
|
||||
return configs[0];
|
||||
// Evaluate all the returned configs, and pick the best one
|
||||
int bestScore = 0x7FFFFFFF;
|
||||
EGLConfig bestConfig{};
|
||||
|
||||
for (std::size_t i = 0; i < static_cast<std::size_t>(configCount); ++i)
|
||||
{
|
||||
// Check mandatory attributes
|
||||
int surfaceType;
|
||||
int renderableType;
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_SURFACE_TYPE, &surfaceType));
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_RENDERABLE_TYPE, &renderableType));
|
||||
if (!(surfaceType & (EGL_WINDOW_BIT | EGL_PBUFFER_BIT)) || !(renderableType & EGL_OPENGL_ES_BIT))
|
||||
continue;
|
||||
|
||||
// Extract the components of the current config
|
||||
int red;
|
||||
int green;
|
||||
int blue;
|
||||
int alpha;
|
||||
int depth;
|
||||
int stencil;
|
||||
int multiSampling;
|
||||
int samples;
|
||||
int caveat;
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &red));
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &green));
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &blue));
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &alpha));
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_DEPTH_SIZE, &depth));
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_STENCIL_SIZE, &stencil));
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_SAMPLE_BUFFERS, &multiSampling));
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_SAMPLES, &samples));
|
||||
eglCheck(eglGetConfigAttrib(display, configs[i], EGL_CONFIG_CAVEAT, &caveat));
|
||||
|
||||
// Evaluate the config
|
||||
int color = red + green + blue + alpha;
|
||||
int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0, caveat == EGL_NONE, false);
|
||||
|
||||
// If it's better than the current best, make it the new best
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
bestConfig = configs[i];
|
||||
}
|
||||
}
|
||||
|
||||
assert(bestScore < 0x7FFFFFFF);
|
||||
|
||||
return bestConfig;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void EglContext::updateSettings()
|
||||
{
|
||||
m_settings.majorVersion = 1;
|
||||
m_settings.minorVersion = 1;
|
||||
m_settings.attributeFlags = ContextSettings::Default;
|
||||
m_settings.depthBits = 0;
|
||||
m_settings.stencilBits = 0;
|
||||
m_settings.antialiasingLevel = 0;
|
||||
|
||||
EGLBoolean result = EGL_FALSE;
|
||||
EGLint tmp = 0;
|
||||
|
||||
// Update the internal context settings with the current config
|
||||
eglCheck(result = eglGetConfigAttrib(m_display, m_config, EGL_DEPTH_SIZE, &tmp));
|
||||
|
||||
if (result == EGL_FALSE)
|
||||
err() << "Failed to retrieve EGL_DEPTH_SIZE" << std::endl;
|
||||
|
||||
if (result != EGL_FALSE)
|
||||
m_settings.depthBits = static_cast<unsigned int>(tmp);
|
||||
|
||||
eglCheck(result = eglGetConfigAttrib(m_display, m_config, EGL_STENCIL_SIZE, &tmp));
|
||||
|
||||
if (result == EGL_FALSE)
|
||||
err() << "Failed to retrieve EGL_STENCIL_SIZE" << std::endl;
|
||||
|
||||
if (result != EGL_FALSE)
|
||||
m_settings.stencilBits = static_cast<unsigned int>(tmp);
|
||||
|
||||
eglCheck(result = eglGetConfigAttrib(m_display, m_config, EGL_SAMPLE_BUFFERS, &tmp));
|
||||
|
||||
if ((result != EGL_FALSE) && tmp)
|
||||
{
|
||||
eglCheck(result = eglGetConfigAttrib(m_display, m_config, EGL_SAMPLES, &tmp));
|
||||
|
||||
if (result == EGL_FALSE)
|
||||
err() << "Failed to retrieve EGL_SAMPLES" << std::endl;
|
||||
|
||||
if (result != EGL_FALSE)
|
||||
m_settings.antialiasingLevel = static_cast<unsigned int>(tmp);
|
||||
|
||||
m_settings.majorVersion = 1;
|
||||
m_settings.minorVersion = 1;
|
||||
m_settings.attributeFlags = ContextSettings::Default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -275,8 +275,6 @@ std::vector<std::string> extensions;
|
||||
// Load our extensions vector with the supported extensions
|
||||
void loadExtensions()
|
||||
{
|
||||
extensions.clear();
|
||||
|
||||
auto glGetErrorFunc = reinterpret_cast<glGetErrorFuncType>(sf::priv::GlContext::getFunction("glGetError"));
|
||||
auto glGetIntegervFunc = reinterpret_cast<glGetIntegervFuncType>(sf::priv::GlContext::getFunction("glGetIntegerv"));
|
||||
auto glGetStringFunc = reinterpret_cast<glGetStringFuncType>(sf::priv::GlContext::getFunction("glGetString"));
|
||||
@ -290,11 +288,14 @@ void loadExtensions()
|
||||
|
||||
auto glGetStringiFunc = reinterpret_cast<glGetStringiFuncType>(sf::priv::GlContext::getFunction("glGetStringi"));
|
||||
|
||||
if (glGetErrorFunc() == GL_INVALID_ENUM || !glGetStringiFunc)
|
||||
if (glGetErrorFunc() == GL_INVALID_ENUM || !majorVersion || !glGetStringiFunc)
|
||||
{
|
||||
// Try to load the < 3.0 way
|
||||
const char* extensionString = reinterpret_cast<const char*>(glGetStringFunc(GL_EXTENSIONS));
|
||||
assert(extensionString);
|
||||
|
||||
if (extensionString)
|
||||
{
|
||||
extensions.clear();
|
||||
|
||||
do
|
||||
{
|
||||
@ -306,6 +307,7 @@ void loadExtensions()
|
||||
extensions.emplace_back(extension, extensionString);
|
||||
} while (*extensionString++);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to load the >= 3.0 way
|
||||
@ -314,9 +316,13 @@ void loadExtensions()
|
||||
|
||||
if (numExtensions)
|
||||
{
|
||||
extensions.clear();
|
||||
|
||||
for (unsigned int i = 0; i < static_cast<unsigned int>(numExtensions); ++i)
|
||||
{
|
||||
const char* extensionString = reinterpret_cast<const char*>(glGetStringiFunc(GL_EXTENSIONS, i));
|
||||
|
||||
if (extensionString)
|
||||
extensions.emplace_back(extensionString);
|
||||
}
|
||||
}
|
||||
@ -807,7 +813,7 @@ void GlContext::initialize(const ContextSettings& requestedSettings)
|
||||
glGetIntegervFunc(GL_MAJOR_VERSION, &majorVersion);
|
||||
glGetIntegervFunc(GL_MINOR_VERSION, &minorVersion);
|
||||
|
||||
if (glGetErrorFunc() != GL_INVALID_ENUM)
|
||||
if ((glGetErrorFunc() != GL_INVALID_ENUM) && (majorVersion != 0))
|
||||
{
|
||||
m_settings.majorVersion = static_cast<unsigned int>(majorVersion);
|
||||
m_settings.minorVersion = static_cast<unsigned int>(minorVersion);
|
||||
|
Loading…
Reference in New Issue
Block a user