From c5790609227924a0950810056683e91c12e156d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 7 Oct 2018 14:44:56 +0200 Subject: [PATCH] Platform: ability to override GL forward compatibility in SDL and GLFW. It's enabled by default, but it's possible to explicitly remove the flag to allow for using features that are not enabled otherwise (such as wide lines). To make the flag handling easier, there's now also new addFlags() and clearFlags() methods. --- doc/changelog.dox | 5 +++ src/Magnum/Platform/GlfwApplication.cpp | 16 ++++++-- src/Magnum/Platform/GlfwApplication.h | 40 ++++++++++++++++++- src/Magnum/Platform/Sdl2Application.cpp | 21 ++++++++-- src/Magnum/Platform/Sdl2Application.h | 51 +++++++++++++++++++++++-- 5 files changed, 123 insertions(+), 10 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 958ab8235..f92a88e62 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -138,6 +138,11 @@ See also: parameters consistent across the implementations. - Added numpad keys to @ref Platform::Sdl2Application::KeyEvent::Key, consistent with GLFW key mapping +- Exposed enabled-by-default @ref Platform::Sdl2Application::GLConfiguration::Flag::ForwardCompatible "GLConfiguration::Flag::ForwardCompatible" + flag in @ref Platform::Sdl2Application and @ref Platform::GlfwApplication, + added @ref Platform::Sdl2Application::GLConfiguration::addFlags() "GLConfiguration::addFlags()" + and @ref Platform::Sdl2Application::GLConfiguration::clearFlags() "GLConfiguration::clearFlags()" + for easier flag handling @subsubsection changelog-latest-new-primitives Primitives library diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 952c34695..f2139b633 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -339,7 +339,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf #ifndef MAGNUM_TARGET_GLES if(glConfiguration.version() >= GL::Version::GL320) { glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, flags >= GLConfiguration::Flag::ForwardCompatible); } #else glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); @@ -355,7 +355,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, flags >= GLConfiguration::Flag::ForwardCompatible); #else /* For ES the major context version is compile-time constant */ #ifdef MAGNUM_TARGET_GLES3 @@ -413,6 +413,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); + /** @todo or keep the fwcompat? */ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, false); _window = glfwCreateWindow(scaledWindowSize.x(), scaledWindowSize.y(), configuration.title().c_str(), monitor, nullptr); @@ -620,7 +621,13 @@ void GlfwApplication::textInputEvent(TextInputEvent&) {} #ifdef MAGNUM_TARGET_GL GlfwApplication::GLConfiguration::GLConfiguration(): _colorBufferSize{8, 8, 8, 0}, _depthBufferSize{24}, _stencilBufferSize{0}, - _sampleCount{0}, _version{GL::Version::None}, _srgbCapable{false} {} + _sampleCount{0}, _version{GL::Version::None}, + #ifndef MAGNUM_TARGET_GLES + _flags{Flag::ForwardCompatible}, + #else + _flags{}, + #endif + _srgbCapable{false} {} GlfwApplication::GLConfiguration::~GLConfiguration() = default; #endif @@ -632,6 +639,9 @@ GlfwApplication::Configuration::Configuration(): _dpiScalingPolicy{DpiScalingPolicy::Default}, _cursorMode{CursorMode::Normal} #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) + /* Deliberately not setting _flags to ForwardCompatible to avoid them + having higher priority over GLConfiguration flags, appending that flag + later */ , _sampleCount{0}, _version{GL::Version::None}, _srgbCapable{false} #endif {} diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index 38c687475..05e2c39ab 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -587,6 +587,16 @@ class GlfwApplication::GLConfiguration { * @see @ref Flags, @ref setFlags(), @ref Context::Flag */ enum class Flag: UnsignedByte { + #ifndef MAGNUM_TARGET_GLES + /** + * Forward compatible context + * + * @requires_gl Core/compatibility profile distinction and forward + * compatibility applies only to desktop GL. + */ + ForwardCompatible = 1 << 0, + #endif + #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(GLFW_CONTEXT_NO_ERROR) /** * Specifies whether errors should be generated by the context. @@ -619,13 +629,41 @@ class GlfwApplication::GLConfiguration { * @brief Set context flags * @return Reference to self (for method chaining) * - * Default is no flag. + * Default is @ref Flag::ForwardCompatible on desktop GL and no flags + * on OpenGL ES. + * @see @ref addFlags(), @ref clearFlags(), @ref GL::Context::flags() */ GLConfiguration& setFlags(Flags flags) { _flags = flags; return *this; } + /** + * @brief Add context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ORs the flags with existing instead of + * replacing them. Useful for preserving the defaults. + * @see @ref clearFlags() + */ + GLConfiguration& addFlags(Flags flags) { + _flags |= flags; + return *this; + } + + /** + * @brief Clear context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing + * instead of replacing them. Useful for removing default flags. + * @see @ref addFlags() + */ + GLConfiguration& clearFlags(Flags flags) { + _flags &= ~flags; + return *this; + } + /** @brief Context version */ GL::Version version() const { return _version; } diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 5b701f057..9406d11a6 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -272,8 +272,13 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf GLConfiguration glConfiguration{_glConfiguration}; CORRADE_IGNORE_DEPRECATED_PUSH #ifndef CORRADE_TARGET_EMSCRIPTEN + #ifndef MAGNUM_TARGET_GLES + if(configuration.flags() && glConfiguration.flags() == GLConfiguration::Flag::ForwardCompatible) + glConfiguration.setFlags(configuration.flags()|GLConfiguration::Flag::ForwardCompatible); + #else if(configuration.flags() && !glConfiguration.flags()) glConfiguration.setFlags(configuration.flags()); + #endif if(configuration.version() != GL::Version::None && glConfiguration.version() == GL::Version::None) glConfiguration.setVersion(configuration.version()); #endif @@ -343,7 +348,7 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); #endif SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glConfiguration.flags())|SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glConfiguration.flags())); #else /* For ES the major context version is compile-time constant */ #ifdef MAGNUM_TARGET_GLES3 @@ -416,7 +421,8 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glConfiguration.flags())); + /** @todo or keep the fwcompat? */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glConfiguration.flags() & ~GLConfiguration::Flag::ForwardCompatible)); if(!(_window = SDL_CreateWindow(configuration.title().data(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, @@ -839,7 +845,13 @@ Sdl2Application::GLConfiguration::GLConfiguration(): _colorBufferSize{8, 8, 8, 0}, _depthBufferSize{24}, _stencilBufferSize{0}, _sampleCount(0) #ifndef CORRADE_TARGET_EMSCRIPTEN - , _version(GL::Version::None), _srgbCapable{false} + , _version(GL::Version::None), + #ifndef MAGNUM_TARGET_GLES + _flags{Flag::ForwardCompatible}, + #else + _flags{}, + #endif + _srgbCapable{false} #endif {} @@ -859,6 +871,9 @@ Sdl2Application::Configuration::Configuration(): #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) , _sampleCount(0) #ifndef CORRADE_TARGET_EMSCRIPTEN + /* Deliberately not setting _flags to ForwardCompatible to avoid them + having higher priority over GLConfiguration flags, appending that flag + later */ , _version(GL::Version::None), _srgbCapable{false} #endif #endif diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 039dafa62..084b95065 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -981,7 +981,18 @@ class Sdl2Application::GLConfiguration { * @requires_gles Context flags are not available in WebGL. */ enum class Flag: int { - Debug = SDL_GL_CONTEXT_DEBUG_FLAG, /**< Create debug context */ + #ifndef MAGNUM_TARGET_GLES + /** + * Forward compatible context + * + * @requires_gl Core/compatibility profile distinction and forward + * compatibility applies only to desktop GL. + */ + ForwardCompatible = SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG, + #endif + + /** Create debug context */ + Debug = SDL_GL_CONTEXT_DEBUG_FLAG, /** Create context with robust access */ RobustAccess = SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG, @@ -998,7 +1009,11 @@ class Sdl2Application::GLConfiguration { */ #ifndef DOXYGEN_GENERATING_OUTPUT typedef Containers::EnumSet Flags; + SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG|SDL_GL_CONTEXT_RESET_ISOLATION_FLAG + #ifndef MAGNUM_TARGET_GLES + |SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG + #endif + > Flags; #else typedef Containers::EnumSet Flags; #endif @@ -1019,7 +1034,9 @@ class Sdl2Application::GLConfiguration { * @brief Set context flags * @return Reference to self (for method chaining) * - * Default is no flag. See also @ref GL::Context::flags(). + * Default is @ref Flag::ForwardCompatible on desktop GL and no flags + * on OpenGL ES. + * @see @ref addFlags(), @ref clearFlags(), @ref GL::Context::flags() * @requires_gles Context flags are not available in WebGL. */ GLConfiguration& setFlags(Flags flags) { @@ -1027,6 +1044,34 @@ class Sdl2Application::GLConfiguration { return *this; } + /** + * @brief Add context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ORs the flags with existing instead of + * replacing them. Useful for preserving the defaults. + * @see @ref clearFlags() + * @requires_gles Context flags are not available in WebGL. + */ + GLConfiguration& addFlags(Flags flags) { + _flags |= flags; + return *this; + } + + /** + * @brief Clear context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing + * instead of replacing them. Useful for removing default flags. + * @see @ref addFlags() + * @requires_gles Context flags are not available in WebGL. + */ + GLConfiguration& clearFlags(Flags flags) { + _flags &= ~flags; + return *this; + } + /** * @brief Context version *