From 24138e2c604288b33e2587bf9ae235324f57e9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 1 Mar 2021 19:49:01 +0100 Subject: [PATCH] Platform: implement [GL]Configuration::Flag::NoError in all apps. Except CGL, iOS, AndroidApplication and AbstractXApplication which are either too crappy or don't have the needed scaffolding for specifying context flags yet. --- doc/changelog.dox | 6 ++ src/Magnum/Platform/GlfwApplication.h | 6 +- src/Magnum/Platform/Sdl2Application.cpp | 4 + src/Magnum/Platform/Sdl2Application.h | 15 ++++ .../Platform/WindowlessEglApplication.cpp | 88 ++++++++++++++----- .../Platform/WindowlessEglApplication.h | 11 +++ .../Platform/WindowlessGlxApplication.cpp | 53 ++++++++++- .../Platform/WindowlessGlxApplication.h | 10 +++ .../Platform/WindowlessWglApplication.cpp | 54 +++++++++++- .../Platform/WindowlessWglApplication.h | 10 +++ .../WindowlessWindowsEglApplication.cpp | 20 ++++- .../WindowlessWindowsEglApplication.h | 10 +++ 12 files changed, 256 insertions(+), 31 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index eaed80ba0..1db6285c2 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -119,6 +119,12 @@ See also: to all @cpp Platform::Windowless*Context @ce classes. Useful for transferring OpenGL contexts between threads, see also [mosra/magnum#495](https://github.com/mosra/magnum/pull/495). +- Implemented @relativeref{Platform::WindowlessEglApplication,Configuration::Flag::NoError} + in @ref Platform::WindowlessEglApplication, + @ref Platform::WindowlessGlxApplication, + @ref Platform::WindowlessWglApplication, + @ref Platform::WindowlessWindowsEglApplication and + @ref Platform::Sdl2Application @subsubsection changelog-latest-new-shaders Shaders library diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index 85fd42770..327511c4c 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -802,9 +802,9 @@ class GlfwApplication::GLConfiguration: public GL::Context::Configuration { #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(GLFW_CONTEXT_NO_ERROR) /** - * Specifies whether errors should be generated by the context. - * If enabled, situations that would have generated errors instead - * cause undefined behavior. + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. * * @note Supported since GLFW 3.2. */ diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 1552d9afc..37dfbf47d 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -470,6 +470,10 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf if((glFlags & GLConfiguration::Flag::GpuValidation) || (_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) glFlags |= GLConfiguration::Flag::Debug; + #if SDL_MAJOR_VERSION*1000 + SDL_MINOR_VERSION*100 + SDL_PATCHLEVEL >= 2006 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_NO_ERROR, glFlags >= GLConfiguration::Flag::NoError); + #endif + /* Set context version, if user-specified */ if(glConfiguration.version() != GL::Version::None) { Int major, minor; diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 4963f0a7f..34c8a53f5 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -1272,6 +1272,21 @@ class Sdl2Application::GLConfiguration: public GL::Context::Configuration { * @requires_gles Context flags are not available in WebGL. */ ResetIsolation = SDL_GL_CONTEXT_RESET_ISOLATION_FLAG, + + #if SDL_MAJOR_VERSION*1000 + SDL_MINOR_VERSION*100 + SDL_PATCHLEVEL >= 2006 || defined(DOXYGEN_GENERATING_OUTPUT) + /** + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. + * + * @note Available since SDL 2.0.6. + * @requires_gles Context flags are not available in WebGL. + * @m_since_latest + */ + /* Treated as a separate attribute and not a flag in SDL, thus + handling manually. */ + NoError = 1ull << 32, + #endif #endif /** diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index dbcf71e64..19140d96e 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -67,6 +67,10 @@ typedef void* EGLObjectKHR; typedef void* EGLLabelKHR; typedef void (APIENTRY *EGLDEBUGPROCKHR)(EGLenum error, const char* command, EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel, const char* message); #endif + +#ifndef EGL_KHR_create_context_no_error +#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3 +#endif #endif namespace Magnum { namespace Platform { @@ -310,10 +314,8 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G flags |= Configuration::Flag::Debug; #endif - #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_WEBGL) - const /* Is modified below to work around a SwiftShader limitation */ - #endif - EGLint attributes[] = { + /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ + EGLint attributes[7] = { EGL_CONTEXT_CLIENT_VERSION, #ifdef MAGNUM_TARGET_GLES #if defined(MAGNUM_TARGET_GLES2) || (defined(CORRADE_TARGET_EMSCRIPTEN) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ < 13824) @@ -330,22 +332,31 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G #else 3, #endif - #ifndef MAGNUM_TARGET_WEBGL - /* Needs to be last because we're zeroing this out for SwiftShader (see - below). - Also mask out the upper 32bits used for other flags. */ - EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu), - #endif + /* The rest is added optionally */ + EGL_NONE, EGL_NONE, /* EGL_CONTEXT_OPENGL_NO_ERROR_KHR */ + EGL_NONE, EGL_NONE, /* EGL_CONTEXT_FLAGS_KHR, need to be last */ EGL_NONE }; - #ifdef MAGNUM_TARGET_WEBGL - static_cast(configuration); - static_cast(magnumContext); - #endif + #ifndef MAGNUM_TARGET_WEBGL + std::size_t nextAttribute = 2; + CORRADE_INTERNAL_ASSERT(attributes[nextAttribute] == EGL_NONE); - #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) + if(flags & Configuration::Flag::NoError) { + attributes[nextAttribute++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR; + attributes[nextAttribute++] = true; + } + + /* Context flags need to be last because we're zeroing this out for + SwiftShader (see below). Also mask out the upper 32bits used for other + flags. */ + attributes[nextAttribute++] = EGL_CONTEXT_FLAGS_KHR; + attributes[nextAttribute++] = EGLint(UnsignedLong(flags) & 0xffffffffu); + + CORRADE_INTERNAL_ASSERT(nextAttribute < Containers::arraySize(attributes)); + + #ifdef MAGNUM_TARGET_GLES const Containers::StringView version = eglQueryString(_display, EGL_VERSION); /* SwiftShader 3.3.0.1 blows up on encountering EGL_CONTEXT_FLAGS_KHR with @@ -353,11 +364,17 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G flags, but instead checks for the whole value, so a combination won't work either: https://github.com/google/swiftshader/blob/5fb5e817a20d3e60f29f7338493f922b5ac9d7c4/src/OpenGL/libEGL/libEGL.cpp#L794-L8104 */ if(!(UnsignedLong(flags) & 0xffffffffu) && version.contains("SwiftShader"_s) && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-no-empty-egl-context-flags"_s))) { - auto& contextFlags = attributes[Containers::arraySize(attributes) - 3]; + auto& contextFlags = attributes[nextAttribute - 2]; CORRADE_INTERNAL_ASSERT(contextFlags == EGL_CONTEXT_FLAGS_KHR); contextFlags = EGL_NONE; } #endif + #endif + + #ifdef MAGNUM_TARGET_WEBGL + static_cast(configuration); + static_cast(magnumContext); + #endif _context = eglCreateContext(_display, config, #ifndef MAGNUM_TARGET_WEBGL @@ -372,15 +389,30 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G if(!_context) { Warning{} << "Platform::WindowlessEglContext: cannot create core context, falling back to compatibility context:" << Implementation::eglErrorString(eglGetError()); - const EGLint fallbackAttributes[] = { + /** @todo duplicated three times, do better */ + EGLint fallbackAttributes[5] = { /* Discard the ForwardCompatible flag for the fallback. Having it set makes the fallback context creation fail on Mesa's Zink (which is just 2.1) and I assume on others as well. Also mask out the upper 32bits used for other flags. */ EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + EGL_NONE, EGL_NONE, /* EGL_CONTEXT_OPENGL_NO_ERROR_KHR */ EGL_NONE }; + + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(fallbackAttributes[nextFallbackAttribute] == EGL_NONE); + + if(flags & Configuration::Flag::NoError) { + fallbackAttributes[nextFallbackAttribute++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR; + fallbackAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackAttributes)); + _context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes); /* Fall back to (forward compatible) GL 2.1 if we are on binary NVidia/AMD @@ -411,16 +443,30 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G { /* Destroy the core context and create a compatibility one */ eglDestroyContext(_display, _context); - const GLint fallbackAttributes[] = { + + /** @todo duplicated three times, do better */ + GLint fallbackAttributes[5] = { /* Discard the ForwardCompatible flag for the fallback. Compared to the above case of a 2.1 fallback it's not really needed here (AFAIK it works in both cases), but let's be - consistent. - - Also mask out the upper 32bits used for other flags. */ + consistent. Also mask out the upper 32bits used for other + flags. */ EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + EGL_NONE, EGL_NONE, /* EGL_CONTEXT_OPENGL_NO_ERROR_KHR */ EGL_NONE }; + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(fallbackAttributes[nextFallbackAttribute] == EGL_NONE); + + if(flags & Configuration::Flag::NoError) { + fallbackAttributes[nextFallbackAttribute++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR; + fallbackAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackAttributes)); + _context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes); } diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index ecbe7c116..afd1e3133 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -208,6 +208,17 @@ class WindowlessEglContext::Configuration: public GL::Context::Configuration { * @requires_gles Context flags are not available in WebGL. */ Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, + + /** + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. + * @requires_gles Context flags are not available in WebGL. + * @m_since_latest + */ + /* Treated as a separate attribute and not a flag in EGL, thus + handling manually. */ + NoError = 1ull << 32, #endif /** diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index 71e3e07db..cfeb65a74 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -32,6 +32,10 @@ #include "Magnum/GL/Version.h" +#ifndef GLX_ARB_create_context_no_error +#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3 +#endif + /* Saner way to define the insane Xlib macros (anyway, FUCK YOU XLIB) */ namespace { enum { None = 0, Success = 0 }; } @@ -113,8 +117,9 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; + /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ /* Optimistically choose core context first */ - const GLint contextAttributes[] = { + GLint contextAttributes[11] = { #ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES3 GLX_CONTEXT_MAJOR_VERSION_ARB, 3, @@ -134,9 +139,22 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura /* Mask out the upper 32bits used for other flags */ GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu), #endif + + /* The rest is added optionally */ + 0, 0, /* GLX_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + std::size_t nextAttribute = 8; + CORRADE_INTERNAL_ASSERT(!contextAttributes[nextAttribute]); + + if(flags & Configuration::Flag::NoError) { + contextAttributes[nextAttribute++] = GLX_CONTEXT_OPENGL_NO_ERROR_ARB; + contextAttributes[nextAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextAttribute < Containers::arraySize(contextAttributes)); + { XlibErrorHandler eh{_display}; _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, contextAttributes); @@ -153,15 +171,29 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura w << Debug::nospace << ":" << buffer; } - const GLint fallbackContextAttributes[] = { + /** @todo duplicated three times, do better */ + GLint fallbackContextAttributes[5] = { /* Discard the ForwardCompatible flag for the fallback. Having it set makes the fallback context creation fail on Mesa's Zink (which is just 2.1) and I assume on others as well. Also mask out the upper 32bits used for other flags. */ GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + 0, 0, /* GLX_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(!fallbackContextAttributes[nextFallbackAttribute]); + + if(flags & Configuration::Flag::NoError) { + fallbackContextAttributes[nextFallbackAttribute++] = GLX_CONTEXT_OPENGL_NO_ERROR_ARB; + fallbackContextAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackContextAttributes)); + { XlibErrorHandler eh{_display}; _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, fallbackContextAttributes); @@ -192,7 +224,9 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura { /* Destroy the core context and create a compatibility one */ glXDestroyContext(_display, _context); - const GLint fallbackContextAttributes[] = { + + /** @todo duplicated three times, do better */ + GLint fallbackContextAttributes[5] = { /* Discard the ForwardCompatible flag for the fallback. Compared to the above case of a 2.1 fallback it's not really needed here (AFAIK it works in both cases), but let's be @@ -200,8 +234,21 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura Also mask out the upper 32bits used for other flags. */ GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + 0, 0, /* GLX_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(!fallbackContextAttributes[nextFallbackAttribute]); + + if(flags & Configuration::Flag::NoError) { + fallbackContextAttributes[nextFallbackAttribute++] = GLX_CONTEXT_OPENGL_NO_ERROR_ARB; + fallbackContextAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackContextAttributes)); + { XlibErrorHandler eh{_display}; _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, fallbackContextAttributes); diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 158f19edf..d8fd54874 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -212,6 +212,16 @@ class WindowlessGlxContext::Configuration: public GL::Context::Configuration { */ Debug = GLX_CONTEXT_DEBUG_BIT_ARB, + /** + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. + * @m_since_latest + */ + /* Treated as a separate attribute and not a flag in GLX, thus + handling manually. */ + NoError = 1ull << 32, + /** * @copydoc GL::Context::Configuration::Flag::QuietLog * @m_since_latest diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index 13ad08dc5..da9466547 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -40,6 +40,10 @@ #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 #define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 + +#ifndef WGL_ARB_create_context_no_error +#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3 +#endif #endif namespace Magnum { namespace Platform { @@ -126,8 +130,9 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; + /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ /* Optimistically choose core context first */ - const GLint contextAttributes[] = { + GLint contextAttributes[11] = { #ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES3 WGL_CONTEXT_MAJOR_VERSION_ARB, 3, @@ -147,8 +152,22 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G /* Mask out the upper 32bits used for other flags */ WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu), #endif + + /* The rest is added optionally */ + 0, 0, /* WGL_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + + std::size_t nextAttribute = 8; + CORRADE_INTERNAL_ASSERT(!contextAttributes[nextAttribute]); + + if(flags & Configuration::Flag::NoError) { + contextAttributes[nextAttribute++] = WGL_CONTEXT_OPENGL_NO_ERROR_ARB; + contextAttributes[nextAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextAttribute < Containers::arraySize(contextAttributes)); + _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), contextAttributes); #ifndef MAGNUM_TARGET_GLES @@ -156,12 +175,26 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G if(!_context) { Warning() << "Platform::WindowlessWglContext: cannot create core context, falling back to compatibility context:" << GetLastError(); - const int fallbackContextAttributes[] = { + /** @todo duplicated three times, do better */ + GLint fallbackContextAttributes[5] = { /** @todo or keep the fwcompat? */ /* Mask out the upper 32bits used for other flags */ WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + 0, 0, /* WGL_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(!fallbackContextAttributes[nextFallbackAttribute]); + + if(flags & Configuration::Flag::NoError) { + fallbackContextAttributes[nextFallbackAttribute++] = WGL_CONTEXT_OPENGL_NO_ERROR_ARB; + fallbackContextAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackContextAttributes)); + _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes); /* Fall back to (forward compatible) GL 2.1 if we are on binary @@ -190,12 +223,27 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G { /* Destroy the core context and create a compatibility one */ wglDeleteContext(_context); - const int fallbackContextAttributes[] = { + + /** @todo duplicated three times, do better */ + GLint fallbackContextAttributes[5] = { /** @todo or keep the fwcompat? */ /* Mask out the upper 32bits used for other flags */ WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + 0, 0, /* WGL_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(!fallbackContextAttributes[nextFallbackAttribute]); + + if(flags & Configuration::Flag::NoError) { + fallbackContextAttributes[nextFallbackAttribute++] = WGL_CONTEXT_OPENGL_NO_ERROR_ARB; + fallbackContextAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackContextAttributes)); + _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes); } } diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index 067369fcc..d33436358 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -199,6 +199,16 @@ class WindowlessWglContext::Configuration: public GL::Context::Configuration { */ Debug = WGL_CONTEXT_DEBUG_BIT_ARB, + /** + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. + * @m_since_latest + */ + /* Treated as a separate attribute and not a flag in WGL, thus + handling manually. */ + NoError = 1ull << 32, + /** * @copydoc GL::Context::Configuration::Flag::QuietLog * @m_since_latest diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index 5eac49ebe..182656214 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -32,6 +32,10 @@ #include "Implementation/Egl.h" +#ifndef EGL_KHR_create_context_no_error +#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3 +#endif + namespace Magnum { namespace Platform { WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& configuration, GLContext* const magnumContext) { @@ -118,7 +122,8 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; - const EGLint attributes[] = { + /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ + EGLint attributes[7] = { #ifdef MAGNUM_TARGET_GLES EGL_CONTEXT_CLIENT_VERSION, #ifdef MAGNUM_TARGET_GLES3 @@ -131,9 +136,22 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co #endif /* Mask out the upper 32bits used for other flags */ EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu), + + /* The rest is added optionally */ + EGL_NONE, EGL_NONE, /* EGL_CONTEXT_OPENGL_NO_ERROR_KHR */ EGL_NONE }; + std::size_t nextAttribute = 4; + CORRADE_INTERNAL_ASSERT(attributes[nextAttribute] == EGL_NONE); + + if(flags & Configuration::Flag::NoError) { + attributes[nextAttribute++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR; + attributes[nextAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextAttribute < Containers::arraySize(attributes)); + if(!(_context = eglCreateContext(_display, config, configuration.sharedContext(), attributes))) { Error() << "Platform::WindowlessWindowsEglContext: cannot create EGL context:" << Implementation::eglErrorString(eglGetError()); return; diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 7268ad2b8..836b419b1 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -175,6 +175,16 @@ class WindowlessWindowsEglContext::Configuration: public GL::Context::Configurat */ Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, + /** + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. + * @m_since_latest + */ + /* Treated as a separate attribute and not a flag in EGL, thus + handling manually. */ + NoError = 1ull << 32, + /** * @copydoc GL::Context::Configuration::Flag::QuietLog * @m_since_latest