From 7ba24c813c84a600f1a7b0357f1171986d6b99f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 7 Oct 2018 14:56:20 +0200 Subject: [PATCH] Platform: expose GL forward compatibility flag also in windowless apps. Similar change to the windowed apps, also resetting it when core context creation fails or when the workaround is applied. This change is not done for CGL, iOS and Windows EGL apps, as these are either GLES-only or, in case of macOS, such flag is not available. --- doc/changelog.dox | 7 +++ .../Platform/WindowlessEglApplication.cpp | 8 +++ .../Platform/WindowlessEglApplication.h | 54 +++++++++++++++++-- .../Platform/WindowlessGlxApplication.cpp | 13 ++++- .../Platform/WindowlessGlxApplication.h | 50 +++++++++++++++-- .../Platform/WindowlessWglApplication.cpp | 17 ++++-- .../Platform/WindowlessWglApplication.h | 51 ++++++++++++++++-- .../WindowlessWindowsEglApplication.h | 28 ++++++++++ 8 files changed, 213 insertions(+), 15 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index f92a88e62..999ba3f9c 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -143,6 +143,13 @@ See also: added @ref Platform::Sdl2Application::GLConfiguration::addFlags() "GLConfiguration::addFlags()" and @ref Platform::Sdl2Application::GLConfiguration::clearFlags() "GLConfiguration::clearFlags()" for easier flag handling +- Exposed enabled-by-default @ref Platform::WindowlessEglApplication::Configuration::Flag::ForwardCompatible "Configuration::Flag::ForwardCompatible" + flag in @ref Platform::WindowlessEglApplication, + @ref Platform::WindowlessGlxApplication and + @ref Platform::WindowlessWglApplication, + added @ref Platform::WindowlessEglApplication::Configuration::addFlags() "Configuration::addFlags()" + and @ref Platform::WindowlessEglApplication::Configuration::clearFlags() "Configuration::clearFlags()" + for easier flag handling @subsubsection changelog-latest-new-primitives Primitives library diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 8a7ae2f6d..058d05470 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -188,6 +188,14 @@ bool WindowlessEglContext::makeCurrent() { return false; } +WindowlessEglContext::Configuration::Configuration() + #ifndef MAGNUM_TARGET_GLES + : _flags{Flag::ForwardCompatible} + #elif !defined(MAGNUM_TARGET_WEBGL) + : _flags{} + #endif + {} + #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments): WindowlessEglApplication{arguments, Configuration{}} {} #endif diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index fcf001b97..ac18af82a 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -139,6 +139,16 @@ class WindowlessEglContext::Configuration { * @requires_gles Context flags are not available in WebGL. */ enum class Flag: int { + #ifndef MAGNUM_TARGET_GLES + /** + * Forward compatible context + * + * @requires_gl Core/compatibility profile distinction and forward + * compatibility applies only to desktop GL. + */ + ForwardCompatible = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR, + #endif + Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR /**< Create debug context */ }; @@ -149,13 +159,17 @@ class WindowlessEglContext::Configuration { * @requires_gles Context flags are not available in WebGL. */ #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; + typedef Containers::EnumSet Flags; #else typedef Containers::EnumSet Flags; #endif #endif - constexpr /*implicit*/ Configuration() {} + /*implicit*/ Configuration(); #ifndef MAGNUM_TARGET_WEBGL /** @@ -169,13 +183,43 @@ class WindowlessEglContext::Configuration { * @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. */ Configuration& 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() + * @requires_gles Context flags are not available in WebGL. + */ + Configuration& 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. + */ + Configuration& clearFlags(Flags flags) { + _flags &= ~flags; + return *this; + } #endif private: @@ -184,6 +228,10 @@ class WindowlessEglContext::Configuration { #endif }; +#ifndef MAGNUM_TARGET_WEBGL +CORRADE_ENUMSET_OPERATORS(WindowlessEglContext::Configuration::Flags) +#endif + /** @brief Windowless EGL application diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index a0c0f8502..a37f38898 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -85,7 +85,7 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 1, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB|GLint(configuration.flags()), + GLX_CONTEXT_FLAGS_ARB, GLint(configuration.flags()), #endif 0 }; @@ -130,7 +130,8 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura /* Destroy the core context and create a compatibility one */ glXDestroyContext(_display, _context); const GLint fallbackContextAttributes[] = { - GLX_CONTEXT_FLAGS_ARB, GLint(configuration.flags()), + /** @todo keep the fwcompat? */ + GLX_CONTEXT_FLAGS_ARB, GLint(configuration.flags() & ~Configuration::Flag::ForwardCompatible), 0 }; _context = glXCreateContextAttribsARB(_display, configs[0], nullptr, True, fallbackContextAttributes); @@ -180,6 +181,14 @@ bool WindowlessGlxContext::makeCurrent() { return false; } +WindowlessGlxContext::Configuration::Configuration(): + #ifndef MAGNUM_TARGET_GLES + _flags{Flag::ForwardCompatible} + #else + _flags{} + #endif + {} + #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments): WindowlessGlxApplication{arguments, Configuration{}} {} #endif diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 6c367b888..943d46a00 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -148,6 +148,16 @@ class WindowlessGlxContext::Configuration { * @see @ref Flags, @ref setFlags(), @ref Context::Flag */ enum class Flag: int { + #ifndef MAGNUM_TARGET_GLES + /** + * Forward compatible context + * + * @requires_gl Core/compatibility profile distinction and forward + * compatibility applies only to desktop GL. + */ + ForwardCompatible = GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + #endif + Debug = GLX_CONTEXT_DEBUG_BIT_ARB /**< Create debug context */ }; @@ -157,12 +167,16 @@ class WindowlessGlxContext::Configuration { * @see @ref setFlags(), @ref Context::Flags */ #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; + typedef Containers::EnumSet Flags; #else typedef Containers::EnumSet Flags; #endif - constexpr /*implicit*/ Configuration() {} + /*implicit*/ Configuration(); /** @brief Context flags */ Flags flags() const { return _flags; } @@ -171,17 +185,47 @@ class WindowlessGlxContext::Configuration { * @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() */ Configuration& 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() + */ + Configuration& 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() + */ + Configuration& clearFlags(Flags flags) { + _flags &= ~flags; + return *this; + } + private: Flags _flags; }; +CORRADE_ENUMSET_OPERATORS(WindowlessGlxContext::Configuration::Flags) + /** @brief Windowless GLX application diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index 414bdadf1..cebf80099 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -40,7 +40,6 @@ #define WGL_CONTEXT_FLAGS_ARB 0x2094 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 #define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 #endif @@ -137,7 +136,7 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 1, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, - WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB|GLint(configuration.flags()), + WGL_CONTEXT_FLAGS_ARB, GLint(configuration.flags()), #endif 0 }; @@ -149,7 +148,8 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G Warning() << "Platform::WindowlessWglContext: cannot create core context, falling back to compatibility context:" << GetLastError(); const int fallbackContextAttributes[] = { - WGL_CONTEXT_FLAGS_ARB, int(configuration.flags()), + /** @todo or keep the fwcompat? */ + WGL_CONTEXT_FLAGS_ARB, GLint(configuration.flags() & ~Configuration::Flag::ForwardCompatible), 0 }; _context = wglCreateContextAttribsARB(_deviceContext, nullptr, fallbackContextAttributes); @@ -184,7 +184,8 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G /* Destroy the core context and create a compatibility one */ wglDeleteContext(_context); const int fallbackContextAttributes[] = { - WGL_CONTEXT_FLAGS_ARB, int(configuration.flags()), + /** @todo or keep the fwcompat? */ + WGL_CONTEXT_FLAGS_ARB, GLint(configuration.flags() & ~Configuration::Flag::ForwardCompatible), 0 }; _context = wglCreateContextAttribsARB(_deviceContext, nullptr, fallbackContextAttributes); @@ -234,6 +235,14 @@ bool WindowlessWglContext::makeCurrent() { return false; } +WindowlessWglContext::Configuration::Configuration(): + #ifndef MAGNUM_TARGET_GLES + _flags{Flag::ForwardCompatible} + #else + _flags{} + #endif + {} + #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments): WindowlessWglApplication{arguments, Configuration{}} {} #endif diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index 1fb32dea2..07e59dbe0 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -46,6 +46,7 @@ /* Define stuff that we need because I can't be bothered with creating a new header just for a few defines */ #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 #endif namespace Magnum { namespace Platform { @@ -147,6 +148,16 @@ class WindowlessWglContext::Configuration { * @see @ref Flags, @ref setFlags(), @ref Context::Flag */ enum class Flag: int { + #ifndef MAGNUM_TARGET_GLES + /** + * Forward compatible context + * + * @requires_gl Core/compatibility profile distinction and forward + * compatibility applies only to desktop GL. + */ + ForwardCompatible = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + #endif + Debug = WGL_CONTEXT_DEBUG_BIT_ARB /**< Create debug context */ }; @@ -156,12 +167,16 @@ class WindowlessWglContext::Configuration { * @see @ref setFlags(), @ref Context::Flags */ #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; + typedef Containers::EnumSet Flags; #else typedef Containers::EnumSet Flags; #endif - constexpr /*implicit*/ Configuration() {} + /*implicit*/ Configuration(); /** @brief Context flags */ Flags flags() const { return _flags; } @@ -170,17 +185,47 @@ class WindowlessWglContext::Configuration { * @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() */ Configuration& 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() + */ + Configuration& 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() + */ + Configuration& clearFlags(Flags flags) { + _flags &= ~flags; + return *this; + } + private: Flags _flags; }; +CORRADE_ENUMSET_OPERATORS(WindowlessWglContext::Configuration::Flags) + /** @brief Windowless WGL application diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 628ae728d..33a226de5 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -164,10 +164,38 @@ class WindowlessWindowsEglContext::Configuration { 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() + */ + Configuration& 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() + */ + Configuration& clearFlags(Flags flags) { + _flags &= ~flags; + return *this; + } + private: Flags _flags; }; +CORRADE_ENUMSET_OPERATORS(WindowlessWindowsEglContext::Configuration::Flags) + /** @brief Windowless Windows/EGL application