Browse Source

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.
euler-xxx
Vladimír Vondruš 5 years ago
parent
commit
24138e2c60
  1. 6
      doc/changelog.dox
  2. 6
      src/Magnum/Platform/GlfwApplication.h
  3. 4
      src/Magnum/Platform/Sdl2Application.cpp
  4. 15
      src/Magnum/Platform/Sdl2Application.h
  5. 88
      src/Magnum/Platform/WindowlessEglApplication.cpp
  6. 11
      src/Magnum/Platform/WindowlessEglApplication.h
  7. 53
      src/Magnum/Platform/WindowlessGlxApplication.cpp
  8. 10
      src/Magnum/Platform/WindowlessGlxApplication.h
  9. 54
      src/Magnum/Platform/WindowlessWglApplication.cpp
  10. 10
      src/Magnum/Platform/WindowlessWglApplication.h
  11. 20
      src/Magnum/Platform/WindowlessWindowsEglApplication.cpp
  12. 10
      src/Magnum/Platform/WindowlessWindowsEglApplication.h

6
doc/changelog.dox

@ -119,6 +119,12 @@ See also:
to all @cpp Platform::Windowless*Context @ce classes. Useful for to all @cpp Platform::Windowless*Context @ce classes. Useful for
transferring OpenGL contexts between threads, see also transferring OpenGL contexts between threads, see also
[mosra/magnum#495](https://github.com/mosra/magnum/pull/495). [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 @subsubsection changelog-latest-new-shaders Shaders library

6
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) #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(GLFW_CONTEXT_NO_ERROR)
/** /**
* Specifies whether errors should be generated by the context. * Context without error reporting. Might result in better
* If enabled, situations that would have generated errors instead * performance, but situations that would have generated errors
* cause undefined behavior. * instead cause undefined behavior.
* *
* @note Supported since GLFW 3.2. * @note Supported since GLFW 3.2.
*/ */

4
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)) if((glFlags & GLConfiguration::Flag::GpuValidation) || (_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation))
glFlags |= GLConfiguration::Flag::Debug; 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 */ /* Set context version, if user-specified */
if(glConfiguration.version() != GL::Version::None) { if(glConfiguration.version() != GL::Version::None) {
Int major, minor; Int major, minor;

15
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. * @requires_gles Context flags are not available in WebGL.
*/ */
ResetIsolation = SDL_GL_CONTEXT_RESET_ISOLATION_FLAG, 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 #endif
/** /**

88
src/Magnum/Platform/WindowlessEglApplication.cpp

@ -67,6 +67,10 @@ typedef void* EGLObjectKHR;
typedef void* EGLLabelKHR; typedef void* EGLLabelKHR;
typedef void (APIENTRY *EGLDEBUGPROCKHR)(EGLenum error, const char* command, EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel, const char* message); typedef void (APIENTRY *EGLDEBUGPROCKHR)(EGLenum error, const char* command, EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel, const char* message);
#endif #endif
#ifndef EGL_KHR_create_context_no_error
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3
#endif
#endif #endif
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
@ -310,10 +314,8 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
flags |= Configuration::Flag::Debug; flags |= Configuration::Flag::Debug;
#endif #endif
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_WEBGL) /** @todo needs a growable DynamicArray with disabled alloc or somesuch */
const /* Is modified below to work around a SwiftShader limitation */ EGLint attributes[7] = {
#endif
EGLint attributes[] = {
EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION,
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
#if defined(MAGNUM_TARGET_GLES2) || (defined(CORRADE_TARGET_EMSCRIPTEN) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ < 13824) #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 #else
3, 3,
#endif #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. */ /* The rest is added optionally */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu), EGL_NONE, EGL_NONE, /* EGL_CONTEXT_OPENGL_NO_ERROR_KHR */
#endif EGL_NONE, EGL_NONE, /* EGL_CONTEXT_FLAGS_KHR, need to be last */
EGL_NONE EGL_NONE
}; };
#ifdef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
static_cast<void>(configuration); std::size_t nextAttribute = 2;
static_cast<void>(magnumContext); CORRADE_INTERNAL_ASSERT(attributes[nextAttribute] == EGL_NONE);
#endif
#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); const Containers::StringView version = eglQueryString(_display, EGL_VERSION);
/* SwiftShader 3.3.0.1 blows up on encountering EGL_CONTEXT_FLAGS_KHR with /* 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 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 */ 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))) { 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); CORRADE_INTERNAL_ASSERT(contextFlags == EGL_CONTEXT_FLAGS_KHR);
contextFlags = EGL_NONE; contextFlags = EGL_NONE;
} }
#endif #endif
#endif
#ifdef MAGNUM_TARGET_WEBGL
static_cast<void>(configuration);
static_cast<void>(magnumContext);
#endif
_context = eglCreateContext(_display, config, _context = eglCreateContext(_display, config,
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
@ -372,15 +389,30 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
if(!_context) { if(!_context) {
Warning{} << "Platform::WindowlessEglContext: cannot create core context, falling back to compatibility context:" << Implementation::eglErrorString(eglGetError()); 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 /* Discard the ForwardCompatible flag for the fallback. Having it
set makes the fallback context creation fail on Mesa's Zink set makes the fallback context creation fail on Mesa's Zink
(which is just 2.1) and I assume on others as well. (which is just 2.1) and I assume on others as well.
Also mask out the upper 32bits used for other flags. */ Also mask out the upper 32bits used for other flags. */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), 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 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); _context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes);
/* Fall back to (forward compatible) GL 2.1 if we are on binary NVidia/AMD /* 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 */ /* Destroy the core context and create a compatibility one */
eglDestroyContext(_display, _context); eglDestroyContext(_display, _context);
const GLint fallbackAttributes[] = {
/** @todo duplicated three times, do better */
GLint fallbackAttributes[5] = {
/* Discard the ForwardCompatible flag for the fallback. /* Discard the ForwardCompatible flag for the fallback.
Compared to the above case of a 2.1 fallback it's not really 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 needed here (AFAIK it works in both cases), but let's be
consistent. consistent. Also mask out the upper 32bits used for other
flags. */
Also mask out the upper 32bits used for other flags. */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), 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 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); _context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes);
} }

11
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. * @requires_gles Context flags are not available in WebGL.
*/ */
Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, 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 #endif
/** /**

53
src/Magnum/Platform/WindowlessGlxApplication.cpp

@ -32,6 +32,10 @@
#include "Magnum/GL/Version.h" #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) */ /* Saner way to define the insane Xlib macros (anyway, FUCK YOU XLIB) */
namespace { enum { None = 0, Success = 0 }; } 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)) if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation))
flags |= Configuration::Flag::Debug; flags |= Configuration::Flag::Debug;
/** @todo needs a growable DynamicArray with disabled alloc or somesuch */
/* Optimistically choose core context first */ /* Optimistically choose core context first */
const GLint contextAttributes[] = { GLint contextAttributes[11] = {
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
#ifdef MAGNUM_TARGET_GLES3 #ifdef MAGNUM_TARGET_GLES3
GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
@ -134,9 +139,22 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura
/* Mask out the upper 32bits used for other flags */ /* Mask out the upper 32bits used for other flags */
GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu), GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu),
#endif #endif
/* The rest is added optionally */
0, 0, /* GLX_CONTEXT_OPENGL_NO_ERROR_ARB */
0 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}; XlibErrorHandler eh{_display};
_context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, contextAttributes); _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, contextAttributes);
@ -153,15 +171,29 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura
w << Debug::nospace << ":" << buffer; 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 /* Discard the ForwardCompatible flag for the fallback. Having it
set makes the fallback context creation fail on Mesa's Zink set makes the fallback context creation fail on Mesa's Zink
(which is just 2.1) and I assume on others as well. (which is just 2.1) and I assume on others as well.
Also mask out the upper 32bits used for other flags. */ Also mask out the upper 32bits used for other flags. */
GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), 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 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}; XlibErrorHandler eh{_display};
_context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, fallbackContextAttributes); _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 */ /* Destroy the core context and create a compatibility one */
glXDestroyContext(_display, _context); glXDestroyContext(_display, _context);
const GLint fallbackContextAttributes[] = {
/** @todo duplicated three times, do better */
GLint fallbackContextAttributes[5] = {
/* Discard the ForwardCompatible flag for the fallback. /* Discard the ForwardCompatible flag for the fallback.
Compared to the above case of a 2.1 fallback it's not really 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 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. */ Also mask out the upper 32bits used for other flags. */
GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), 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 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}; XlibErrorHandler eh{_display};
_context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, fallbackContextAttributes); _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, fallbackContextAttributes);

10
src/Magnum/Platform/WindowlessGlxApplication.h

@ -212,6 +212,16 @@ class WindowlessGlxContext::Configuration: public GL::Context::Configuration {
*/ */
Debug = GLX_CONTEXT_DEBUG_BIT_ARB, 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 * @copydoc GL::Context::Configuration::Flag::QuietLog
* @m_since_latest * @m_since_latest

54
src/Magnum/Platform/WindowlessWglApplication.cpp

@ -40,6 +40,10 @@
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 #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 #endif
namespace Magnum { namespace Platform { 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)) if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation))
flags |= Configuration::Flag::Debug; flags |= Configuration::Flag::Debug;
/** @todo needs a growable DynamicArray with disabled alloc or somesuch */
/* Optimistically choose core context first */ /* Optimistically choose core context first */
const GLint contextAttributes[] = { GLint contextAttributes[11] = {
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
#ifdef MAGNUM_TARGET_GLES3 #ifdef MAGNUM_TARGET_GLES3
WGL_CONTEXT_MAJOR_VERSION_ARB, 3, 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 */ /* Mask out the upper 32bits used for other flags */
WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu), WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu),
#endif #endif
/* The rest is added optionally */
0, 0, /* WGL_CONTEXT_OPENGL_NO_ERROR_ARB */
0 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); _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), contextAttributes);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -156,12 +175,26 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G
if(!_context) { if(!_context) {
Warning() << "Platform::WindowlessWglContext: cannot create core context, falling back to compatibility context:" << GetLastError(); 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? */ /** @todo or keep the fwcompat? */
/* Mask out the upper 32bits used for other flags */ /* Mask out the upper 32bits used for other flags */
WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), 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 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); _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes);
/* Fall back to (forward compatible) GL 2.1 if we are on binary /* 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 */ /* Destroy the core context and create a compatibility one */
wglDeleteContext(_context); wglDeleteContext(_context);
const int fallbackContextAttributes[] = {
/** @todo duplicated three times, do better */
GLint fallbackContextAttributes[5] = {
/** @todo or keep the fwcompat? */ /** @todo or keep the fwcompat? */
/* Mask out the upper 32bits used for other flags */ /* Mask out the upper 32bits used for other flags */
WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), 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 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); _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes);
} }
} }

10
src/Magnum/Platform/WindowlessWglApplication.h

@ -199,6 +199,16 @@ class WindowlessWglContext::Configuration: public GL::Context::Configuration {
*/ */
Debug = WGL_CONTEXT_DEBUG_BIT_ARB, 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 * @copydoc GL::Context::Configuration::Flag::QuietLog
* @m_since_latest * @m_since_latest

20
src/Magnum/Platform/WindowlessWindowsEglApplication.cpp

@ -32,6 +32,10 @@
#include "Implementation/Egl.h" #include "Implementation/Egl.h"
#ifndef EGL_KHR_create_context_no_error
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3
#endif
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& configuration, GLContext* const magnumContext) { 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)) if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation))
flags |= Configuration::Flag::Debug; flags |= Configuration::Flag::Debug;
const EGLint attributes[] = { /** @todo needs a growable DynamicArray with disabled alloc or somesuch */
EGLint attributes[7] = {
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION,
#ifdef MAGNUM_TARGET_GLES3 #ifdef MAGNUM_TARGET_GLES3
@ -131,9 +136,22 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co
#endif #endif
/* Mask out the upper 32bits used for other flags */ /* Mask out the upper 32bits used for other flags */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu), 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 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))) { if(!(_context = eglCreateContext(_display, config, configuration.sharedContext(), attributes))) {
Error() << "Platform::WindowlessWindowsEglContext: cannot create EGL context:" << Implementation::eglErrorString(eglGetError()); Error() << "Platform::WindowlessWindowsEglContext: cannot create EGL context:" << Implementation::eglErrorString(eglGetError());
return; return;

10
src/Magnum/Platform/WindowlessWindowsEglApplication.h

@ -175,6 +175,16 @@ class WindowlessWindowsEglContext::Configuration: public GL::Context::Configurat
*/ */
Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, 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 * @copydoc GL::Context::Configuration::Flag::QuietLog
* @m_since_latest * @m_since_latest

Loading…
Cancel
Save