Browse Source

GL: introduce Context::Configuration mirroring --magnum-* arguments.

Disabling engine startup log or modifying enabled extensions /
workarounds from the application side was one of the common pain
points and this should *finally* solve the problem. This Configuration
is now inherited by the usual Platform::*Application::GLConfiguration /
Platform::Windowless*Application::Configuration classes people are used
to, so for the end user it's just as if these classes got a bunch new
options.

Having this, I also extended the ContextGLTest to verify that the
Configuration and command-line options do what's expected because that
hadn't automated tests until now. The test is mostly a copy of what I
did for Vulkan already, nothing special. Additionally all
Platform*ApplicationTest executables gained a new --quiet option to
verify that the GL::Context::Configuration subset gets correctly passed
from the Application code, because that's something we can't really
verify in an automated way.
euler-xxx
Vladimír Vondruš 5 years ago
parent
commit
fd1492f56b
  1. 15
      doc/changelog.dox
  2. 2
      doc/getting-started.dox
  3. 2
      doc/opengl-workarounds.dox
  4. 2
      doc/troubleshooting.dox
  5. 6
      src/Magnum/Audio/Context.h
  6. 75
      src/Magnum/GL/Context.cpp
  7. 291
      src/Magnum/GL/Context.h
  8. 4
      src/Magnum/GL/DebugOutput.h
  9. 23
      src/Magnum/GL/Implementation/driverSpecific.cpp
  10. 2
      src/Magnum/GL/OpenGLTester.h
  11. 125
      src/Magnum/GL/Test/ContextGLTest.cpp
  12. 227
      src/Magnum/GL/Test/ContextTest.cpp
  13. 2
      src/Magnum/Platform/AbstractXApplication.cpp
  14. 21
      src/Magnum/Platform/AbstractXApplication.h
  15. 2
      src/Magnum/Platform/AndroidApplication.cpp
  16. 21
      src/Magnum/Platform/AndroidApplication.h
  17. 7
      src/Magnum/Platform/EmscriptenApplication.cpp
  18. 44
      src/Magnum/Platform/EmscriptenApplication.h
  19. 42
      src/Magnum/Platform/GLContext.h
  20. 11
      src/Magnum/Platform/GlfwApplication.cpp
  21. 48
      src/Magnum/Platform/GlfwApplication.h
  22. 26
      src/Magnum/Platform/Sdl2Application.cpp
  23. 79
      src/Magnum/Platform/Sdl2Application.h
  24. 10
      src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp
  25. 12
      src/Magnum/Platform/Test/GlfwApplicationTest.cpp
  26. 6
      src/Magnum/Platform/Test/GlxApplicationTest.cpp
  27. 12
      src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp
  28. 16
      src/Magnum/Platform/Test/WindowlessCglApplicationTest.cpp
  29. 16
      src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp
  30. 16
      src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp
  31. 16
      src/Magnum/Platform/Test/WindowlessIosApplicationTest.cpp
  32. 16
      src/Magnum/Platform/Test/WindowlessWglApplicationTest.cpp
  33. 16
      src/Magnum/Platform/Test/WindowlessWindowsEglApplicationTest.cpp
  34. 7
      src/Magnum/Platform/Test/XEglApplicationTest.cpp
  35. 4
      src/Magnum/Platform/WindowlessCglApplication.cpp
  36. 23
      src/Magnum/Platform/WindowlessCglApplication.h
  37. 30
      src/Magnum/Platform/WindowlessEglApplication.cpp
  38. 70
      src/Magnum/Platform/WindowlessEglApplication.h
  39. 28
      src/Magnum/Platform/WindowlessGlxApplication.cpp
  40. 48
      src/Magnum/Platform/WindowlessGlxApplication.h
  41. 22
      src/Magnum/Platform/WindowlessIosApplication.h
  42. 22
      src/Magnum/Platform/WindowlessWglApplication.cpp
  43. 48
      src/Magnum/Platform/WindowlessWglApplication.h
  44. 5
      src/Magnum/Platform/WindowlessWindowsEglApplication.cpp
  45. 50
      src/Magnum/Platform/WindowlessWindowsEglApplication.h
  46. 2
      src/Magnum/Platform/gl-info.cpp
  47. 2
      src/Magnum/Text/fontconverter.cpp
  48. 2
      src/Magnum/TextureTools/distancefieldconverter.cpp

15
doc/changelog.dox

@ -49,6 +49,12 @@ See also:
@subsubsection changelog-latest-new-gl GL library @subsubsection changelog-latest-new-gl GL library
- New @ref GL::Context::Configuration class providing runtime alternatives to
the `--magnum-log`, `--magnum-gpu-validation`, `--magnum-disable-extensions`
and `--magnum-disable-workarounds` command line options. The class is then
inherited by all @ref Platform::Sdl2Application::GLConfiguration "Platform::*Application::GLConfiguration"
and @ref Platform::WindowlessEglApplication::Configuration "Platform::Windowless*Application::Configuration"
classes.
- Implemented @gl_extension{EXT,texture_norm16} and - Implemented @gl_extension{EXT,texture_norm16} and
@webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making @webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making
normalized 16-bit texture and renderbuffer formats available on all normalized 16-bit texture and renderbuffer formats available on all
@ -1412,7 +1418,8 @@ Released 2019-10-24, tagged as
(see the @cpp "swiftshader-broken-shader-vertex-id" @ce workaround in (see the @cpp "swiftshader-broken-shader-vertex-id" @ce workaround in
@ref opengl-workarounds for more information). This pseudo-extension can be @ref opengl-workarounds for more information). This pseudo-extension can be
also explicitly disabled using the usual `--magnum-disable-extensions` also explicitly disabled using the usual `--magnum-disable-extensions`
@ref GL-Context-command-line "command-line option" for testing purposes. @ref GL-Context-usage-command-line "command-line option" for testing
purposes.
- An assorted collection of workarounds for Intel Windows drivers "fixing" - An assorted collection of workarounds for Intel Windows drivers "fixing"
various issues related to @gl_extension{ARB,direct_state_access} by using a various issues related to @gl_extension{ARB,direct_state_access} by using a
non-DSA code path in the affected cases --- see non-DSA code path in the affected cases --- see
@ -1463,7 +1470,7 @@ Released 2019-10-24, tagged as
a defined output. On core and ES/WebGL contexts this is enabled implicitly, a defined output. On core and ES/WebGL contexts this is enabled implicitly,
but for example NVidia drivers have @cpp gl_PointCoord @ce undefined when but for example NVidia drivers have @cpp gl_PointCoord @ce undefined when
`GL_POINT_SPRITE` is not enabled on compatibility contexts. `GL_POINT_SPRITE` is not enabled on compatibility contexts.
- New `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" - New `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option"
and a corresponding environment variable to conveniently enable and a corresponding environment variable to conveniently enable
@gl_extension{KHR,debug} debug output. This flag also causes @gl_extension{KHR,debug} debug output. This flag also causes
@ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug" @ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug"
@ -1476,7 +1483,7 @@ Released 2019-10-24, tagged as
@ref GL::Buffer::setData() / @ref GL::Buffer::setSubData() for a succint @ref GL::Buffer::setData() / @ref GL::Buffer::setSubData() for a succint
upload of basic types upload of basic types
- Added an ability to use Magnum with multiple OpenGL contexts using - Added an ability to use Magnum with multiple OpenGL contexts using
@ref GL::Context::makeCurrent(), see @ref GL-Context-multiple for more @ref GL::Context::makeCurrent(), see @ref GL-Context-usage-multiple for more
information information
- @ref GL::AbstractFramebuffer::read(), @ref GL::Texture::image(), - @ref GL::AbstractFramebuffer::read(), @ref GL::Texture::image(),
@ref GL::Texture::subImage(), @ref GL::Texture::compressedImage(), @ref GL::Texture::subImage(), @ref GL::Texture::compressedImage(),
@ -1678,7 +1685,7 @@ Released 2019-10-24, tagged as
- @ref GL::OpenGLTester no longer implicitly enables @ref GL::DebugOutput as - @ref GL::OpenGLTester no longer implicitly enables @ref GL::DebugOutput as
it can be quite spammy when complex shaders or benchmarks are allowed. For it can be quite spammy when complex shaders or benchmarks are allowed. For
easier debugging, users are encouraged to use the new easier debugging, users are encouraged to use the new
`--magnum-gpu-validation` @ref GL-Context-command-line "command line option" `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command line option"
instead. instead.
- Added an ability to create @ref GL::DynamicAttribute directly from a - Added an ability to create @ref GL::DynamicAttribute directly from a
@ref GL::Attribute @ref GL::Attribute

2
doc/getting-started.dox

@ -282,7 +282,7 @@ Hello! This application is running on OpenGL 4.5 using GeForce GT 740M
@image html getting-started-blue.png width=410px @image html getting-started-blue.png width=410px
The barebones application accepts various @ref GL-Context-command-line "command-line arguments", The barebones application accepts various @ref GL-Context-usage-command-line "command-line arguments",
pass `--magnum-help` to see them all. Depending on your platform, these can pass `--magnum-help` to see them all. Depending on your platform, these can
adjust HiDPI scaling, enable GPU command validation or for example switch to a adjust HiDPI scaling, enable GPU command validation or for example switch to a
different GPU device. different GPU device.

2
doc/opengl-workarounds.dox

@ -49,7 +49,7 @@ Using driver workarounds:
These identifiers correspond to the strings in the listing below. For debugging These identifiers correspond to the strings in the listing below. For debugging
and diagnostic purposes it's possible to disable particular workarounds by and diagnostic purposes it's possible to disable particular workarounds by
passing their identifier string to the `--magnum-disable-workarounds` passing their identifier string to the `--magnum-disable-workarounds`
command-line option. See @ref GL-Context-command-line for more information. command-line option. See @ref GL-Context-usage-command-line for more information.
@m_class{m-console-wrap} @m_class{m-console-wrap}

2
doc/troubleshooting.dox

@ -54,7 +54,7 @@ or crashes on GL calls, you might want to try these things:
- Enable @ref GL::DebugOutput "debug output" to see more detailed errors, - Enable @ref GL::DebugOutput "debug output" to see more detailed errors,
warnings and performance hints. You can do that easily through the warnings and performance hints. You can do that easily through the
`--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option"
or an environment variable. or an environment variable.
- If you are on Mac, the native OpenGL implementation doesn't support - If you are on Mac, the native OpenGL implementation doesn't support
this. Instead you can manually verify that this. Instead you can manually verify that

6
src/Magnum/Audio/Context.h

@ -110,9 +110,9 @@ options passed to the application itself. Options that don't have this prefix
are completely ignored, see documentation of the are completely ignored, see documentation of the
@ref Utility-Arguments-delegating "Utility::Arguments" class for details. @ref Utility-Arguments-delegating "Utility::Arguments" class for details.
Moreover, `--magnum`-prefixed options unrelated to audio (such as those defined Moreover, `--magnum`-prefixed options unrelated to audio (such as those defined
by @ref GL-Context-command-line "GL::Context") are ignored as well. In order to by @ref GL-Context-usage-command-line "GL::Context") are ignored as well. In
provide a complete help and command-line argument diagnostic, you should order to provide a complete help and command-line argument diagnostic, you
instantiate this class *after* @ref GL::Context. should instantiate this class *after* @ref GL::Context.
*/ */
class MAGNUM_AUDIO_EXPORT Context { class MAGNUM_AUDIO_EXPORT Context {
public: public:

75
src/Magnum/GL/Context.cpp

@ -749,15 +749,40 @@ Context::~Context() {
if(currentContext == this) currentContext = nullptr; if(currentContext == this) currentContext = nullptr;
} }
void Context::create() { void Context::create(const Configuration& configuration) {
/* Hard exit if the context cannot be created */ /* Hard exit if the context cannot be created */
if(!tryCreate()) std::exit(1); if(!tryCreate(configuration)) std::exit(1);
} }
bool Context::tryCreate() { bool Context::tryCreate(const Configuration& configuration) {
CORRADE_ASSERT(_version == Version::None, CORRADE_ASSERT(_version == Version::None,
"Platform::Context::tryCreate(): context already created", false); "Platform::Context::tryCreate(): context already created", false);
/* Merge the configuration with parameters passed on the command line /
environment. For the log command-line gets a priority -- if it says
quiet, it'll override the verbose setting from the configuration; if
it says verbose, the quiet setting from the configuration will be
ignored */
if((configuration.flags() & Configuration::Flag::VerboseLog) && (_internalFlags & InternalFlag::DisplayInitializationLog))
_internalFlags |= InternalFlag::DisplayVerboseInitializationLog;
else if((configuration.flags() & Configuration::Flag::QuietLog) && !(_internalFlags >= InternalFlag::DisplayVerboseInitializationLog))
_internalFlags &= ~InternalFlag::DisplayInitializationLog;
/* GPU validation is enabled if either enables it */
if(configuration.flags() & Configuration::Flag::GpuValidation)
_internalFlags |= InternalFlag::GpuValidation;
/* Driver workarounds get merged. Not using disableDriverWorkaround() here
since the Configuration already contains the internal string views. */
for(const Containers::StringView workaround: configuration.disabledWorkarounds())
arrayAppend(_driverWorkarounds, Containers::InPlaceInit, workaround, true);
/* Extensions get merged also. Here we had the chance to force users to
give us the predefined extension types so no need to search for their
IDs */
for(const Extension& extension: configuration.disabledExtensions())
arrayAppend(_disabledExtensions, extension);
/* Load GL function pointers. Pass this instance to it so it can use it for /* Load GL function pointers. Pass this instance to it so it can use it for
potential driver-specific workarounds. */ potential driver-specific workarounds. */
if(_functionLoader) _functionLoader(*this); if(_functionLoader) _functionLoader(*this);
@ -1139,6 +1164,50 @@ void Context::resetState(const States states) {
#endif #endif
} }
Context::Configuration::Configuration() = default;
Context::Configuration::Configuration(const Configuration& other): _flags{other._flags} {
addDisabledWorkarounds(other._disabledWorkarounds);
addDisabledExtensions(other._disabledExtensions);
}
Context::Configuration::Configuration(Configuration&&) noexcept = default;
Context::Configuration::~Configuration() = default;
Context::Configuration& Context::Configuration::operator=(const Configuration& other) {
_flags = other._flags;
arrayResize(_disabledWorkarounds, 0);
/** @todo arrayClear(), ffs */
arrayResize(_disabledExtensions, Containers::NoInit, 0);
addDisabledWorkarounds(other._disabledWorkarounds);
addDisabledExtensions(other._disabledExtensions);
return *this;
}
Context::Configuration& Context::Configuration::operator=(Configuration&&) noexcept = default;
Containers::ArrayView<const Containers::StringView> Context::Configuration::disabledWorkarounds() const {
return _disabledWorkarounds;
}
Containers::ArrayView<const Extension> Context::Configuration::disabledExtensions() const {
return _disabledExtensions;
}
Context::Configuration& Context::Configuration::addDisabledWorkarounds(std::initializer_list<Containers::StringView> workarounds) {
return addDisabledWorkarounds(Containers::arrayView(workarounds));
}
Context::Configuration& Context::Configuration::addDisabledExtensions(Containers::ArrayView<const Extension> extensions) {
arrayAppend(_disabledExtensions, extensions);
return *this;
}
Context::Configuration& Context::Configuration::addDisabledExtensions(std::initializer_list<Extension> extensions) {
return addDisabledExtensions(Containers::arrayView(extensions));
}
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
Debug& operator<<(Debug& debug, const Context::Flag value) { Debug& operator<<(Debug& debug, const Context::Flag value) {

291
src/Magnum/GL/Context.h

@ -108,18 +108,32 @@ class MAGNUM_GL_EXPORT Extension {
@brief Magnum OpenGL context @brief Magnum OpenGL context
Provides access to OpenGL version and extension information and manages Provides access to OpenGL version and extension information and manages
Magnum's internal OpenGL state tracker. An instance available through Magnum's internal OpenGL state tracker.
@ref Context::current() is automatically created during construction of
`Platform::*Application` classes and you can safely assume the instance is @section GL-Context-usage Creating a context
available during the whole `*Application` lifetime. It's also possible to
create the context without using any `*Application` class using the In order to use any Magnum OpenGL functionality, an instance of this class has
to exist and be made current. If you use any `Platform::*Application` classes,
an instance available through @ref Context::current() is automatically created
during construction (or after @ref Platform::Sdl2Application::create() "Platform::*Application::create()"
/ @relativeref{Platform::Sdl2Application,tryCreate()} and you can safely assume
the instance is available during the whole `*Application` lifetime. It's also
possible to create the context without using any `*Application` class using the
@ref Platform::GLContext subclass, see @ref platform for more information. @ref Platform::GLContext subclass, see @ref platform for more information.
@section GL-Context-command-line Command-line options Various options can be passed using the @ref Configuration class, which is then
extended by various
@ref Platform::Sdl2Application::GLConfiguration "Platform::*Application::GLConfiguration"
and @ref Platform::WindowlessEglContext::Configuration "Platform::Windowless*Application::Configuration"
subclasses.
@subsection GL-Context-usage-command-line Command-line options
The context is configurable through command-line options, that are passed In addition to the @ref Configuration, the context is configurable through
either from the `Platform::*Application` classes or from the command-line options, that are passed either from the `Platform::*Application`
@ref Platform::GLContext class. Usage: classes or from the @ref Platform::GLContext class. In case an option is set in
both the @ref Configuration and on command-line / environment, the two are
combined together --- flags ORed together, lists joined. Usage:
@code{.sh} @code{.sh}
<application> [--magnum-help] [--magnum-disable-workarounds LIST] <application> [--magnum-help] [--magnum-disable-workarounds LIST]
@ -134,20 +148,23 @@ Arguments:
- `--magnum-help` --- display this help message and exit - `--magnum-help` --- display this help message and exit
- `--magnum-disable-workarounds LIST` --- driver workarounds to disable (see - `--magnum-disable-workarounds LIST` --- driver workarounds to disable (see
@ref opengl-workarounds for detailed info) (environment: @ref opengl-workarounds for detailed info) (environment:
`MAGNUM_DISABLE_WORKAROUNDS`) `MAGNUM_DISABLE_WORKAROUNDS`). Corresponds to
@ref Configuration::addDisabledWorkarounds().
- `--magnum-disable-extensions LIST` --- API extensions to disable - `--magnum-disable-extensions LIST` --- API extensions to disable
(environment: `MAGNUM_DISABLE_EXTENSIONS`) (environment: `MAGNUM_DISABLE_EXTENSIONS`). Corresponds to
@ref Configuration::addDisabledExtensions().
- `--magnum-gpu-validation off|on` --- GPU validation using - `--magnum-gpu-validation off|on` --- GPU validation using
@gl_extension{KHR,debug}, if present (environment: @gl_extension{KHR,debug}, if present (environment:
`MAGNUM_GPU_VALIDATION`) (default: `off`). This sets up @ref DebugOutput `MAGNUM_GPU_VALIDATION`) (default: `off`). This sets up @ref DebugOutput
callbacks and also causes callbacks and also causes
@ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug" @ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug"
to be enabled for context creation for both windowed and windowless to be enabled for context creation for both windowed and windowless
applications on supported platforms applications on supported platforms. Corresponds to
@ref Configuration::Flag::GpuValidation.
- `--magnum-log default|quiet|verbose` --- console logging - `--magnum-log default|quiet|verbose` --- console logging
(environment: `MAGNUM_LOG`) (default: `default`). If you need to suppress (environment: `MAGNUM_LOG`) (default: `default`). Corresponds to
the engine startup log from code, the recommended way is to redirect @ref Configuration::Flag::QuietLog and
@ref Utility-Debug-scoped-output "debug output to null" during context creation. @relativeref{Configuration::Flag,VerboseLog}.
Note that all options are prefixed with `--magnum-` to avoid conflicts with Note that all options are prefixed with `--magnum-` to avoid conflicts with
options passed to the application itself. Options that don't have this prefix options passed to the application itself. Options that don't have this prefix
@ -158,15 +175,7 @@ Particular application implementations add more options for DPI scaling or
GPU selection, see @ref Platform::Sdl2Application, @ref Platform::GlfwApplication GPU selection, see @ref Platform::Sdl2Application, @ref Platform::GlfwApplication
and @ref Platform::WindowlessEglApplication for details. and @ref Platform::WindowlessEglApplication for details.
@section GL-Context-multithreading Thread safety @subsection GL-Context-usage-multiple Using multiple OpenGL contexts
If Corrade is compiled with @ref CORRADE_BUILD_MULTITHREADED (the default), the
@ref hasCurrent() and @ref current() accessors are thread-local, matching the
OpenGL context thread locality. This might cause some performance penalties ---
if you are sure that you never need to have multiple independent thread-local
Magnum context, build Corrade with the option disabled.
@section GL-Context-multiple Using multiple OpenGL contexts
By default, Magnum assumes you have one OpenGL context active at all times, and By default, Magnum assumes you have one OpenGL context active at all times, and
all state tracking is done by the @ref Context instance that's associated with all state tracking is done by the @ref Context instance that's associated with
@ -187,9 +196,19 @@ Once all needed instances are created, switch between them right after making
the underlying GL context current: the underlying GL context current:
@snippet MagnumGL-framebuffer.cpp Context-makeCurrent @snippet MagnumGL-framebuffer.cpp Context-makeCurrent
@section GL-Context-multithreading Thread safety
If Corrade is compiled with @ref CORRADE_BUILD_MULTITHREADED (the default), the
@ref hasCurrent() and @ref current() accessors are thread-local, matching the
OpenGL context thread locality. This might cause some performance penalties ---
if you are sure that you never need to have multiple independent thread-local
Magnum context, build Corrade with the option disabled.
*/ */
class MAGNUM_GL_EXPORT Context { class MAGNUM_GL_EXPORT Context {
public: public:
class Configuration;
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
/** /**
* @brief Context flag * @brief Context flag
@ -204,7 +223,8 @@ class MAGNUM_GL_EXPORT Context {
* Debug context. Enabled automatically by @ref Platform windowed * Debug context. Enabled automatically by @ref Platform windowed
* and windowless application implementations if the * and windowless application implementations if the
* `--magnum-gpu-validation` * `--magnum-gpu-validation`
* @ref GL-Context-command-line "command-line option" is present. * @ref GL-Context-usage-command-line "command-line option" is
* present.
* @requires_gl43 Extension @gl_extension{KHR,debug} * @requires_gl43 Extension @gl_extension{KHR,debug}
* @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} /
* @gl_extension{KHR,debug} * @gl_extension{KHR,debug}
@ -485,7 +505,7 @@ class MAGNUM_GL_EXPORT Context {
* @m_since{2019,10} * @m_since{2019,10}
* *
* To be used when you need to manage multiple OpenGL contexts. See * To be used when you need to manage multiple OpenGL contexts. See
* @ref GL-Context-multiple for more information. * @ref GL-Context-usage-multiple for more information.
*/ */
static void makeCurrent(Context* context); static void makeCurrent(Context* context);
@ -693,8 +713,10 @@ class MAGNUM_GL_EXPORT Context {
* @brief Whether given extension is disabled * @brief Whether given extension is disabled
* *
* Can be used for detecting driver bug workarounds. Disabled * Can be used for detecting driver bug workarounds. Disabled
* extensions return `false` in @ref isExtensionSupported() even if * extensions return @cpp false @ce in @ref isExtensionSupported() even
* they are advertised as being supported by the driver. * if they are advertised as being supported by the driver.
* @see @ref Configuration::addDisabledExtensions(),
* @ref GL-Context-usage-command-line
*/ */
template<class E> bool isExtensionDisabled() const { template<class E> bool isExtensionDisabled() const {
return isExtensionDisabled<E>(version()); return isExtensionDisabled<E>(version());
@ -705,6 +727,8 @@ class MAGNUM_GL_EXPORT Context {
* *
* Similar to above, but can also check for extensions which are * Similar to above, but can also check for extensions which are
* disabled only for particular versions. * disabled only for particular versions.
* @see @ref Configuration::addDisabledExtensions(),
* @ref GL-Context-usage-command-line
*/ */
template<class E> bool isExtensionDisabled(Version version) const { template<class E> bool isExtensionDisabled(Version version) const {
static_assert(Implementation::IsExtension<E>::value, "expected an OpenGL extension"); static_assert(Implementation::IsExtension<E>::value, "expected an OpenGL extension");
@ -717,8 +741,11 @@ class MAGNUM_GL_EXPORT Context {
* @brief Whether given extension is disabled * @brief Whether given extension is disabled
* *
* Can be used e.g. for listing extensions available on current * Can be used e.g. for listing extensions available on current
* hardware, but for general usage prefer @ref isExtensionDisabled() const, * hardware, but for general usage prefer
* as it does most operations in compile time. * @ref isExtensionDisabled() const, as it does most operations at
* compile time.
* @see @ref Configuration::addDisabledExtensions(),
* @ref GL-Context-usage-command-line
*/ */
bool isExtensionDisabled(const Extension& extension) const { bool isExtensionDisabled(const Extension& extension) const {
return isVersionSupported(extension.requiredVersion()) && !isVersionSupported(_extensionRequiredVersion[extension.index()]); return isVersionSupported(extension.requiredVersion()) && !isVersionSupported(_extensionRequiredVersion[extension.index()]);
@ -786,8 +813,8 @@ class MAGNUM_GL_EXPORT Context {
explicit Context(NoCreateT, Utility::Arguments&& args, Int argc, const char** argv, void functionLoader(Context&)): Context{NoCreate, args, argc, argv, functionLoader} {} explicit Context(NoCreateT, Utility::Arguments&& args, Int argc, const char** argv, void functionLoader(Context&)): Context{NoCreate, args, argc, argv, functionLoader} {}
explicit Context(NoCreateT, Utility::Arguments& args, Int argc, const char** argv, void functionLoader(Context&)); explicit Context(NoCreateT, Utility::Arguments& args, Int argc, const char** argv, void functionLoader(Context&));
bool tryCreate(); bool tryCreate(const Configuration& configuration);
void create(); void create(const Configuration& configuration);
private: private:
#ifndef DOXYGEN_GENERATING_OUTPUT /* https://bugzilla.gnome.org/show_bug.cgi?id=776986 */ #ifndef DOXYGEN_GENERATING_OUTPUT /* https://bugzilla.gnome.org/show_bug.cgi?id=776986 */
@ -847,6 +874,206 @@ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::DetectedDriver value);
/** @debugoperatorclassenum{Context,Context::DetectedDrivers} */ /** @debugoperatorclassenum{Context,Context::DetectedDrivers} */
MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::DetectedDrivers value); MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::DetectedDrivers value);
/**
@brief Configuration
@m_since_latest
Affects how Magnum's context creation behaves. See @ref GL-Context-usage for
more information.
@see @ref Platform::GLContext::GLContext(),
@ref Platform::GLContext::create(),
@ref Platform::GLContext::tryCreate()
*/
class MAGNUM_GL_EXPORT Context::Configuration {
public:
/**
* @brief Context setup flag
*
* Flags affecting the actual GL context are merged with this enum in
* @ref Platform::Sdl2Application::GLConfiguration::Flag "Platform::*Application::GLConfiguration::Flag"
* and @ref Platform::WindowlessEglContext::Configuration::Flag "Platform::Windowless*Application::Configuration::Flag"
* and after context creation available through @ref Context::Flag /
* @ref Context::flags().
* @see @ref Flags, @ref setFlags()
*/
enum class Flag: UnsignedLong {
/* Keeping the 32-bit range reserved for actual GL context flags */
/**
* Print only warnings and errors instead of the usual startup log
* listing used extensions and workarounds. Ignored if
* @ref Flag::VerboseLog is set.
*
* Corresponds to the `--magnum-log quiet`
* @ref GL-Context-usage-command-line "command-line option".
*/
QuietLog = 1ull << 61,
/**
* Print additional information on startup in addition to the usual
* startup log that lists used extensions and workarounds. Has a
* precedence over @ref Flag::QuietLog.
*
* Corresponds to the `--magnum-log verbose`
* @ref GL-Context-usage-command-line "command-line option".
*/
VerboseLog = 1ull << 62,
/**
* Enable GPU validation, if available.
*
* Corresponds to the `--magnum-gou-validation on`
* @ref GL-Context-usage-command-line "command-line option".
*/
GpuValidation = 1ull << 63
};
/**
* @brief Context setup flags
*
* @see @ref setFlags(), @ref GL::Context::Flags
*/
typedef Containers::EnumSet<Flag> Flags;
/*implicit*/ Configuration();
/** @brief Copy constructor */
/* The class has to be copyable in order to make command-line and
configuration options easy to merge in application implementations
-- these make a mutable copy and add what arrived via command line */
Configuration(const Configuration& other);
/** @brief Move constructor */
Configuration(Configuration&&) noexcept;
~Configuration();
/** @brief Copy constructor */
Configuration& operator=(const Configuration& other);
/** @brief Move assignment */
Configuration& operator=(Configuration&&) noexcept;
/** @brief Context setup flags */
Flags flags() const { return _flags; }
/**
* @brief Set context setup flags
* @return Reference to self (for method chaining)
*
* By default no flags are set. Note that subclasses might have
* different flag defaults, see their documentation for more
* information. To avoid clearing default flags by accident, prefer to
* use @ref addFlags() and @ref clearFlags() instead.
*
* Particular @ref Flag values correspond to the `--magnum-log` and
* `--magnum-gpu-validation`
* @ref GL-Context-usage-command-line "command-line options".
*/
Configuration& setFlags(Flags flags) {
_flags = flags;
return *this;
}
/**
* @brief Add context setup 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 setup 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;
}
/** @brief Disabled driver workarounds */
Containers::ArrayView<const Containers::StringView> disabledWorkarounds() const;
/**
* @brief Add disabled driver workarounds
* @return Reference to self (for method chaining)
*
* Accepts strings from the list at @ref opengl-workarounds. Unknown
* workarounds are ignored with a warning. By default no workarounds
* are disabled.
*
* Corresponds to the `--magnum-disable-workarounds`
* @ref GL-Context-usage-command-line "command-line option".
*/
Configuration& addDisabledWorkarounds(Containers::ArrayView<const Containers::StringView> workarounds);
/** @overload */
Configuration& addDisabledWorkarounds(std::initializer_list<Containers::StringView> workarounds);
/** @brief Disabled extensions */
Containers::ArrayView<const Extension> disabledExtensions() const;
/**
* @brief Add disabled extensions
* @return Reference to self (for method chaining)
*
* By default no extensions are disabled, except for those disabled by
* driver workarounds.
*
* Corresponds to the `--magnum-disable-extensions`
* @ref GL-Context-usage-command-line "command-line option".
*/
Configuration& addDisabledExtensions(Containers::ArrayView<const Extension> extensions);
/** @overload */
Configuration& addDisabledExtensions(std::initializer_list<Extension> extensions);
/** @overload */
template<class ...E> Configuration& addDisabledExtensions() {
static_assert(Implementation::IsExtension<E...>::value, "expected only OpenGL extensions");
return addDisabledExtensions({E{}...});
}
private:
Flags _flags;
Containers::Array<Containers::StringView> _disabledWorkarounds;
Containers::Array<Extension> _disabledExtensions;
};
#ifndef DOXYGEN_GENERATING_OUTPUT
#define MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Type) \
Type& addDisabledWorkarounds(Containers::ArrayView<const Containers::StringView> workarounds) { \
GL::Context::Configuration::addDisabledWorkarounds(workarounds); \
return *this; \
} \
Type& addDisabledWorkarounds(std::initializer_list<Containers::StringView> workarounds) { \
GL::Context::Configuration::addDisabledWorkarounds(workarounds); \
return *this; \
} \
\
Type& addDisabledExtensions(Containers::ArrayView<const GL::Extension> extensions) { \
GL::Context::Configuration::addDisabledExtensions(extensions); \
return *this; \
} \
Type& addDisabledExtensions(std::initializer_list<GL::Extension> extensions) { \
GL::Context::Configuration::addDisabledExtensions(extensions); \
return *this; \
} \
template<class ...E> Type& addDisabledExtensions() { \
GL::Context::Configuration::addDisabledExtensions<E...>(); \
return *this; \
}
#endif
CORRADE_ENUMSET_OPERATORS(Context::Configuration::Flags)
/** @hideinitializer /** @hideinitializer
@brief Assert that given OpenGL version is supported @brief Assert that given OpenGL version is supported
@param version Version @param version Version

4
src/Magnum/GL/DebugOutput.h

@ -79,8 +79,8 @@ application itself by setting up message callback using @ref setCallback() or
@par Enabling debug output from the command line / environment @par Enabling debug output from the command line / environment
Apart from setting up the debug output callbacks manually, it's also Apart from setting up the debug output callbacks manually, it's also
possible to enable it conveniently using the `--magnum-gpu-validation` possible to enable it conveniently using the `--magnum-gpu-validation`
@ref GL-Context-command-line "command-line or environment option" --- ideal @ref GL-Context-usage-command-line "command-line or environment option" ---
for quick debugging of rendering issues. If you are using application ideal for quick debugging of rendering issues. If you are using application
classes from the @ref Platform namespace, this option also ensures that classes from the @ref Platform namespace, this option also ensures that
@ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug" @ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug"
is passed for context creation, both with windowed and windowless is passed for context creation, both with windowed and windowless

23
src/Magnum/GL/Implementation/driverSpecific.cpp

@ -616,4 +616,27 @@ void Context::setupDriverWorkarounds() {
#endif #endif
} }
Context::Configuration& Context::Configuration::addDisabledWorkarounds(Containers::ArrayView<const Containers::StringView> workarounds) {
arrayReserve(_disabledWorkarounds, _disabledWorkarounds.size() + workarounds.size());
for(const Containers::StringView workaround: workarounds) {
/* Find the workaround. Note that we'll add the found view to the array
and not the passed view, as the found view is guaranteed to stay in
scope */
const Containers::StringView found = findWorkaround(workaround);
/* Ignore unknown workarounds */
/** @todo this will probably cause false positives when both GL and
Vulkan is used together? */
if(found.isEmpty()) {
Warning{} << "GL::Context::Configuration::addDisabledWorkarounds(): unknown workaround" << workaround;
continue;
}
arrayAppend(_disabledWorkarounds, Containers::InPlaceInit, found);
}
return *this;
}
}} }}

2
src/Magnum/GL/OpenGLTester.h

@ -132,7 +132,7 @@ by default to make the test output more readable. Instead of relying on debug
output to report errors, the @ref MAGNUM_VERIFY_NO_GL_ERROR() macro should be output to report errors, the @ref MAGNUM_VERIFY_NO_GL_ERROR() macro should be
used to reliably check for errors regardless of platform support. For easier used to reliably check for errors regardless of platform support. For easier
debugging of OpenGL errors users are encuraged to use the debugging of OpenGL errors users are encuraged to use the
`--magnum-gpu-validation` @ref GL-Context-command-line "command line option", `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command line option",
which is supported here as well as in all other application implementations. which is supported here as well as in all other application implementations.
@section GL-OpenGLTester-benchmarks GPU time benchmarks @section GL-OpenGLTester-benchmarks GPU time benchmarks

125
src/Magnum/GL/Test/ContextGLTest.cpp

@ -24,6 +24,9 @@
*/ */
#include <algorithm> #include <algorithm>
#include <sstream>
#include <Corrade/Containers/ScopeGuard.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringView.h>
#include <Corrade/TestSuite/Compare/Numeric.h> #include <Corrade/TestSuite/Compare/Numeric.h>
@ -43,6 +46,8 @@ struct ContextGLTest: OpenGLTester {
void stringFlags(); void stringFlags();
void constructConfiguration();
void makeCurrent(); void makeCurrent();
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
@ -58,10 +63,89 @@ struct ContextGLTest: OpenGLTester {
void isExtensionDisabled(); void isExtensionDisabled();
}; };
using namespace Containers::Literals;
struct {
const char* name;
Containers::Optional<Extension> needsExtensionPresent, needsExtensionMissing;
Context::Configuration::Flags flags;
Containers::Array<Containers::StringView> disabledWorkarounds;
Containers::Array<Extension> disabledExtensions;
Containers::Array<const char*> args;
Containers::StringView logShouldContain, logShouldNotContain;
} ConstructConfigurationData[] {
{"default log", {}, {},
{},
{}, {}, {},
"Renderer: ", {}},
{"quiet", {}, {},
Context::Configuration::Flag::QuietLog,
{}, {}, {},
{}, "Renderer: "},
{"quiet on command line", {}, {}, {}, {}, {},
Containers::array({"", "--magnum-log", "quiet"}),
{}, "Renderer: "},
{"quiet and verbose", {}, {},
Context::Configuration::Flag::QuietLog|Context::Configuration::Flag::VerboseLog,
{}, {}, {},
/* Verbose has a precedence */
"Renderer: ", {}},
{"quiet and verbose on command line", {}, {},
Context::Configuration::Flag::QuietLog,
{}, {},
Containers::array({"", "--magnum-log", "verbose"}),
/* Command-line has a precedence */
"Renderer: ", {}},
{"verbose and quiet on command line", {}, {},
Context::Configuration::Flag::VerboseLog,
{}, {},
Containers::array({"", "--magnum-log", "quiet"}),
/* Command-line has a precedence */
{}, "Renderer: "},
#ifndef MAGNUM_TARGET_GLES
{"default workarounds", {}, {}, {}, {}, {}, {},
"\nUsing driver workarounds:\n no-layout-qualifiers-on-old-glsl\n", {}},
{"disabled workaround", {}, {}, {},
Containers::array({"no-layout-qualifiers-on-old-glsl"_s}), {}, {},
{}, "no-layout-qualifiers-on-old-glsl"},
{"disabled workaround on command line", {}, {}, {}, {}, {},
Containers::array({"", "--magnum-disable-workarounds", "no-layout-qualifiers-on-old-glsl"}),
{}, "no-layout-qualifiers-on-old-glsl"},
#endif
#ifndef MAGNUM_TARGET_GLES
{"default extensions ARB",
Extension{Extensions::ARB::texture_filter_anisotropic{}},
{}, {}, {}, {}, {},
" GL_ARB_texture_filter_anisotropic\n", {}},
#endif
{"default extensions EXT",
Extension{Extensions::EXT::texture_filter_anisotropic{}},
#ifndef MAGNUM_TARGET_GLES
Extension{Extensions::ARB::texture_filter_anisotropic{}},
#else
{},
#endif
{}, {}, {}, {},
" GL_EXT_texture_filter_anisotropic\n", {}},
{"disabled extension",
Extension{Extensions::EXT::texture_filter_anisotropic{}},
{}, {}, {},
Containers::array<Extension>({Extensions::EXT::texture_filter_anisotropic{}}), {},
"Disabling extensions:\n GL_EXT_texture_filter_anisotropic\n", {}},
{"disabled extension on command line",
Extension{Extensions::EXT::texture_filter_anisotropic{}},
{}, {}, {}, {},
Containers::array({"", "--magnum-disable-extensions", "GL_EXT_texture_filter_anisotropic"}),
"Disabling extensions:\n GL_EXT_texture_filter_anisotropic\n", {}},
};
ContextGLTest::ContextGLTest() { ContextGLTest::ContextGLTest() {
addTests({ addTests({&ContextGLTest::stringFlags});
&ContextGLTest::stringFlags,
addInstancedTests({&ContextGLTest::constructConfiguration},
Containers::arraySize(ConstructConfigurationData));
addTests({
&ContextGLTest::makeCurrent, &ContextGLTest::makeCurrent,
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
@ -116,6 +200,43 @@ void ContextGLTest::stringFlags() {
} }
} }
void ContextGLTest::constructConfiguration() {
auto&& data = ConstructConfigurationData[testCaseInstanceId()];
setTestCaseDescription(data.name);
if(std::getenv("MAGNUM_DISABLE_WORKAROUNDS"))
CORRADE_SKIP("Can't test with the MAGNUM_DISABLE_WORKAROUNDS environment variable set");
if(std::getenv("MAGNUM_DISABLE_EXTENSIONS"))
CORRADE_SKIP("Can't test with the MAGNUM_DISABLE_EXTENSIONS environment variable set");
CORRADE_VERIFY(Context::hasCurrent());
if(data.needsExtensionPresent && !Context::current().isExtensionSupported(*data.needsExtensionPresent))
CORRADE_SKIP(data.needsExtensionPresent->string() + std::string{" is not supported, skippping"});
if(data.needsExtensionMissing && Context::current().isExtensionSupported(*data.needsExtensionMissing))
CORRADE_SKIP(data.needsExtensionMissing->string() + std::string{" is supported, skippping"});
std::ostringstream out;
{
Context* current = &Context::current();
Context::makeCurrent(nullptr);
Containers::ScopeGuard resetCurrent{current, Context::makeCurrent};
Debug redirectOut{&out};
Platform::GLContext ctx{Int(data.args.size()), data.args, Context::Configuration{}
.setFlags(data.flags)
.addDisabledWorkarounds(data.disabledWorkarounds)
.addDisabledExtensions(data.disabledExtensions)
};
}
/** @todo TestSuite::Compare::StringContains / NotContains for proper diag */
if(!data.logShouldContain.isEmpty())
CORRADE_VERIFY(Containers::StringView{out.str()}.contains(data.logShouldContain));
if(!data.logShouldNotContain.isEmpty())
CORRADE_VERIFY(!Containers::StringView{out.str()}.contains(data.logShouldNotContain));
}
void ContextGLTest::makeCurrent() { void ContextGLTest::makeCurrent() {
CORRADE_VERIFY(Context::hasCurrent()); CORRADE_VERIFY(Context::hasCurrent());

227
src/Magnum/GL/Test/ContextTest.cpp

@ -25,7 +25,9 @@
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <Corrade/Containers/StringView.h>
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/Container.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
@ -39,6 +41,11 @@ struct ContextTest: TestSuite::Tester {
void isExtension(); void isExtension();
void configurationConstruct();
void configurationConstructUnknownWorkaround();
void configurationConstructCopy();
void configurationConstructMove();
void constructNoCreate(); void constructNoCreate();
void constructCopyMove(); void constructCopyMove();
@ -56,6 +63,11 @@ struct ContextTest: TestSuite::Tester {
ContextTest::ContextTest() { ContextTest::ContextTest() {
addTests({&ContextTest::isExtension, addTests({&ContextTest::isExtension,
&ContextTest::configurationConstruct,
&ContextTest::configurationConstructUnknownWorkaround,
&ContextTest::configurationConstructCopy,
&ContextTest::configurationConstructMove,
&ContextTest::constructNoCreate, &ContextTest::constructNoCreate,
&ContextTest::constructCopyMove, &ContextTest::constructCopyMove,
@ -71,7 +83,7 @@ ContextTest::ContextTest() {
} }
void ContextTest::isExtension() { void ContextTest::isExtension() {
CORRADE_VERIFY(Implementation::IsExtension<Extensions::KHR::debug>::value); CORRADE_VERIFY(Implementation::IsExtension<Extensions::EXT::texture_filter_anisotropic>::value);
CORRADE_VERIFY(!Implementation::IsExtension<Extension>::value); CORRADE_VERIFY(!Implementation::IsExtension<Extension>::value);
CORRADE_VERIFY(!Implementation::IsExtension<int>::value); CORRADE_VERIFY(!Implementation::IsExtension<int>::value);
@ -86,8 +98,9 @@ void ContextTest::isExtension() {
CORRADE_VERIFY(!Implementation::IsExtension<ALExtension>::value); CORRADE_VERIFY(!Implementation::IsExtension<ALExtension>::value);
} }
/* Variadic check (used in variadic addEnabledExtensions()), check that it /* Variadic check (used in variadic Configuration::addDisabledExtensions()),
properly fails for each occurence of a non-extension */ check that it properly fails for each occurence of a non-extension */
#ifndef MAGNUM_TARGET_WEBGL
CORRADE_VERIFY((Implementation::IsExtension< CORRADE_VERIFY((Implementation::IsExtension<
Extensions::KHR::debug, Extensions::KHR::debug,
Extensions::EXT::texture_filter_anisotropic, Extensions::EXT::texture_filter_anisotropic,
@ -104,11 +117,219 @@ void ContextTest::isExtension() {
Extensions::KHR::debug, Extensions::KHR::debug,
Extensions::EXT::texture_filter_anisotropic, Extensions::EXT::texture_filter_anisotropic,
Extension>::value)); Extension>::value));
#else
CORRADE_VERIFY((Implementation::IsExtension<
Extensions::OES::texture_float_linear,
Extensions::EXT::texture_filter_anisotropic,
Extensions::WEBGL::compressed_texture_s3tc>::value));
CORRADE_VERIFY(!(Implementation::IsExtension<
Extension,
Extensions::OES::texture_float_linear,
Extensions::EXT::texture_filter_anisotropic>::value));
CORRADE_VERIFY(!(Implementation::IsExtension<
Extensions::OES::texture_float_linear,
Extension,
Extensions::EXT::texture_filter_anisotropic>::value));
CORRADE_VERIFY(!(Implementation::IsExtension<
Extensions::OES::texture_float_linear,
Extensions::EXT::texture_filter_anisotropic,
Extension>::value));
#endif
/* Empty variadic list should return true */ /* Empty variadic list should return true */
CORRADE_VERIFY(Implementation::IsExtension<>::value); CORRADE_VERIFY(Implementation::IsExtension<>::value);
} }
void ContextTest::configurationConstruct() {
#ifndef MAGNUM_TARGET_GLES
const Containers::StringView a = "no-layout-qualifiers-on-old-glsl";
const Containers::StringView b = "nv-compressed-block-size-in-bits";
const Containers::StringView c = "nv-cubemap-inconsistent-compressed-image-size";
#elif !defined(MAGNUM_TARGET_WEBGL)
const Containers::StringView a = "swiftshader-no-empty-egl-context-flags";
const Containers::StringView b = "swiftshader-egl-context-needs-pbuffer";
const Containers::StringView c = "angle-chatty-shader-compiler";
#else
/* No general WebGL workarounds to test */
#endif
/* Deliberately not having the literals global to test that they get
converted to something else */
CORRADE_VERIFY(!(a.flags() & Containers::StringViewFlag::Global));
Context::Configuration configuration;
configuration
.setFlags(Context::Configuration::Flag::GpuValidation|
Context::Configuration::Flag::VerboseLog)
#ifndef MAGNUM_TARGET_WEBGL
.addDisabledWorkarounds({a, b})
.addDisabledWorkarounds({c})
#endif
#ifndef MAGNUM_TARGET_WEBGL
.addDisabledExtensions({Extensions::EXT::texture_filter_anisotropic{},
Extensions::KHR::debug{}})
.addDisabledExtensions<Extensions::KHR::robustness,
Extensions::KHR::texture_compression_astc_hdr>()
#else
.addDisabledExtensions({Extensions::EXT::texture_filter_anisotropic{},
Extensions::EXT::texture_compression_rgtc{}})
.addDisabledExtensions<Extensions::EXT::float_blend,
Extensions::OES::texture_float_linear>()
#endif
;
CORRADE_COMPARE(UnsignedLong(configuration.flags()), UnsignedLong(
Context::Configuration::Flag::GpuValidation|
Context::Configuration::Flag::VerboseLog));
/* The workaround strings should get interned */
#ifndef MAGNUM_TARGET_WEBGL
CORRADE_COMPARE_AS(configuration.disabledWorkarounds(),
Containers::arrayView({a, b, c}),
TestSuite::Compare::Container);
CORRADE_VERIFY(configuration.disabledWorkarounds()[0].data() != a.data());
CORRADE_VERIFY(configuration.disabledWorkarounds()[1].data() != b.data());
CORRADE_VERIFY(configuration.disabledWorkarounds()[2].data() != c.data());
CORRADE_COMPARE(configuration.disabledWorkarounds()[0].flags(),
Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated);
CORRADE_COMPARE(configuration.disabledWorkarounds()[1].flags(),
Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated);
CORRADE_COMPARE(configuration.disabledWorkarounds()[2].flags(),
Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated);
#endif
CORRADE_COMPARE(configuration.disabledExtensions().size(), 4);
#ifndef MAGNUM_TARGET_WEBGL
CORRADE_COMPARE(configuration.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index);
CORRADE_COMPARE(configuration.disabledExtensions()[1].index(), Extensions::KHR::debug::Index);
CORRADE_COMPARE(configuration.disabledExtensions()[2].index(), Extensions::KHR::robustness::Index);
CORRADE_COMPARE(configuration.disabledExtensions()[3].index(), Extensions::KHR::texture_compression_astc_hdr::Index);
#else
CORRADE_COMPARE(configuration.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index);
CORRADE_COMPARE(configuration.disabledExtensions()[1].index(), Extensions::EXT::texture_compression_rgtc::Index);
CORRADE_COMPARE(configuration.disabledExtensions()[2].index(), Extensions::EXT::float_blend::Index);
CORRADE_COMPARE(configuration.disabledExtensions()[3].index(), Extensions::OES::texture_float_linear::Index);
#endif
}
void ContextTest::configurationConstructUnknownWorkaround() {
Context::Configuration configuration;
/* Unknown workarounds should get ignored -- we're storing views on
internally known workaround strings to avoid allocations so there's no
other way */
std::ostringstream out;
Warning redirectWarning{&out};
configuration.addDisabledWorkarounds({"all-drivers-are-shit"});
CORRADE_VERIFY(configuration.disabledWorkarounds().empty());
CORRADE_COMPARE(out.str(), "GL::Context::Configuration::addDisabledWorkarounds(): unknown workaround all-drivers-are-shit\n");
}
void ContextTest::configurationConstructCopy() {
#ifndef MAGNUM_TARGET_GLES
Containers::StringView workaround = "no-layout-qualifiers-on-old-glsl";
Containers::StringView another = "nv-compressed-block-size-in-bits";
#elif !defined(MAGNUM_TARGET_WEBGL)
Containers::StringView workaround = "swiftshader-no-empty-egl-context-flags";
Containers::StringView another = "angle-chatty-shader-compiler";
#else
/* No general WebGL workarounds to test */
#endif
Context::Configuration a;
a.setFlags(Context::Configuration::Flag::VerboseLog)
#ifndef MAGNUM_TARGET_WEBGL
.addDisabledWorkarounds({workaround})
#endif
.addDisabledExtensions<Extensions::EXT::texture_filter_anisotropic>();
Context::Configuration b = a;
CORRADE_COMPARE(UnsignedLong(b.flags()), UnsignedLong(Context::Configuration::Flag::VerboseLog));
#ifndef MAGNUM_TARGET_WEBGL
CORRADE_COMPARE_AS(b.disabledWorkarounds(),
Containers::arrayView({workaround}),
TestSuite::Compare::Container);
#endif
CORRADE_COMPARE(b.disabledExtensions().size(), 1);
CORRADE_COMPARE(b.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index);
Context::Configuration c;
c.setFlags(Context::Configuration::Flag::QuietLog)
#ifndef MAGNUM_TARGET_WEBGL
.addDisabledWorkarounds({another})
.addDisabledExtensions<Extensions::KHR::debug>()
#else
.addDisabledExtensions<Extensions::OES::texture_float_linear>()
#endif
;
c = b;
CORRADE_COMPARE(UnsignedLong(c.flags()), UnsignedLong(Context::Configuration::Flag::VerboseLog));
#ifndef MAGNUM_TARGET_WEBGL
CORRADE_COMPARE_AS(c.disabledWorkarounds(),
Containers::arrayView({workaround}),
TestSuite::Compare::Container);
#endif
CORRADE_COMPARE(c.disabledExtensions().size(), 1);
CORRADE_COMPARE(c.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index);
}
void ContextTest::configurationConstructMove() {
#ifndef MAGNUM_TARGET_GLES
Containers::StringView workaround = "no-layout-qualifiers-on-old-glsl";
Containers::StringView another = "nv-compressed-block-size-in-bits";
#elif !defined(MAGNUM_TARGET_WEBGL)
Containers::StringView workaround = "swiftshader-no-empty-egl-context-flags";
Containers::StringView another = "angle-chatty-shader-compiler";
#else
/* No general WebGL workarounds to test */
#endif
Context::Configuration a;
a.setFlags(Context::Configuration::Flag::VerboseLog)
#ifndef MAGNUM_TARGET_WEBGL
.addDisabledWorkarounds({workaround})
#endif
.addDisabledExtensions<Extensions::EXT::texture_filter_anisotropic>();
Context::Configuration b = std::move(a);
CORRADE_COMPARE(UnsignedLong(b.flags()), UnsignedLong(Context::Configuration::Flag::VerboseLog));
CORRADE_VERIFY(a.disabledWorkarounds().empty());
CORRADE_VERIFY(a.disabledExtensions().empty());
#ifndef MAGNUM_TARGET_WEBGL
CORRADE_COMPARE_AS(b.disabledWorkarounds(),
Containers::arrayView({workaround}),
TestSuite::Compare::Container);
#endif
CORRADE_COMPARE(b.disabledExtensions().size(), 1);
CORRADE_COMPARE(b.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index);
Context::Configuration c;
c.setFlags(Context::Configuration::Flag::QuietLog)
#ifndef MAGNUM_TARGET_WEBGL
.addDisabledWorkarounds({another, another})
.addDisabledExtensions<Extensions::KHR::debug,
Extensions::KHR::debug>()
#else
.addDisabledExtensions<Extensions::OES::texture_float_linear,
Extensions::OES::texture_float_linear>()
#endif
;
c = std::move(b);
#ifndef MAGNUM_TARGET_WEBGL
CORRADE_COMPARE(b.disabledWorkarounds().size(), 2);
#endif
CORRADE_COMPARE(b.disabledExtensions().size(), 2);
CORRADE_COMPARE(UnsignedLong(c.flags()), UnsignedLong(Context::Configuration::Flag::VerboseLog));
#ifndef MAGNUM_TARGET_WEBGL
CORRADE_COMPARE_AS(c.disabledWorkarounds(),
Containers::arrayView({workaround}),
TestSuite::Compare::Container);
#endif
CORRADE_COMPARE(c.disabledExtensions().size(), 1);
CORRADE_COMPARE(c.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index);
}
void ContextTest::constructNoCreate() { void ContextTest::constructNoCreate() {
{ {
/* Shouldn't crash during construction, shouldn't attempt to access GL, /* Shouldn't crash during construction, shouldn't attempt to access GL,

2
src/Magnum/Platform/AbstractXApplication.cpp

@ -105,7 +105,7 @@ bool AbstractXApplication::tryCreate(const Configuration& configuration, const G
_contextHandler->makeCurrent(); _contextHandler->makeCurrent();
/* Return true if the initialization succeeds */ /* Return true if the initialization succeeds */
return _context->tryCreate(); return _context->tryCreate(glConfiguration);
} }
AbstractXApplication::~AbstractXApplication() { AbstractXApplication::~AbstractXApplication() {

21
src/Magnum/Platform/AbstractXApplication.h

@ -60,7 +60,7 @@ typedef int Bool;
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/GL/GL.h" #include "Magnum/GL/Context.h"
#include "Magnum/Math/Vector2.h" #include "Magnum/Math/Vector2.h"
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
@ -336,7 +336,7 @@ Double-buffered OpenGL context.
@ref Configuration, @ref create(), @ref tryCreate() @ref Configuration, @ref create(), @ref tryCreate()
@todo GLX_ARB_create_context_robustness/EGL_EXT_create_context_robustness @todo GLX_ARB_create_context_robustness/EGL_EXT_create_context_robustness
*/ */
class AbstractXApplication::GLConfiguration { class AbstractXApplication::GLConfiguration: public GL::Context::Configuration {
public: public:
explicit GLConfiguration(); explicit GLConfiguration();
~GLConfiguration(); ~GLConfiguration();
@ -350,6 +350,23 @@ class AbstractXApplication::GLConfiguration {
return *this; return *this;
} }
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
GLConfiguration& setFlags(Flags flags) {
GL::Context::Configuration::setFlags(flags);
return *this;
}
GLConfiguration& addFlags(Flags flags) {
GL::Context::Configuration::addFlags(flags);
return *this;
}
GLConfiguration& clearFlags(Flags flags) {
GL::Context::Configuration::clearFlags(flags);
return *this;
}
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration)
#endif
private: private:
GL::Version _version; GL::Version _version;
}; };

2
src/Magnum/Platform/AndroidApplication.cpp

@ -167,7 +167,7 @@ bool AndroidApplication::tryCreate(const Configuration& configuration, const GLC
CORRADE_INTERNAL_ASSERT_OUTPUT(eglMakeCurrent(_display, _surface, _surface, _glContext)); CORRADE_INTERNAL_ASSERT_OUTPUT(eglMakeCurrent(_display, _surface, _surface, _glContext));
/* Return true if the initialization succeeds */ /* Return true if the initialization succeeds */
return _context->tryCreate(); return _context->tryCreate(glConfiguration);
} }
Vector2i AndroidApplication::framebufferSize() const { Vector2i AndroidApplication::framebufferSize() const {

21
src/Magnum/Platform/AndroidApplication.h

@ -36,7 +36,7 @@
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/GL/GL.h" #include "Magnum/GL/Context.h"
#include "Magnum/Math/Vector4.h" #include "Magnum/Math/Vector4.h"
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
@ -448,7 +448,7 @@ Double-buffered RGBA canvas with depth and stencil buffers.
@see @ref AndroidApplication(), @ref Configuration, @ref create(), @see @ref AndroidApplication(), @ref Configuration, @ref create(),
@ref tryCreate() @ref tryCreate()
*/ */
class AndroidApplication::GLConfiguration { class AndroidApplication::GLConfiguration: public GL::Context::Configuration {
public: public:
/*implicit*/ GLConfiguration(); /*implicit*/ GLConfiguration();
@ -504,6 +504,23 @@ class AndroidApplication::GLConfiguration {
return *this; return *this;
} }
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
GLConfiguration& setFlags(Flags flags) {
GL::Context::Configuration::setFlags(flags);
return *this;
}
GLConfiguration& addFlags(Flags flags) {
GL::Context::Configuration::addFlags(flags);
return *this;
}
GLConfiguration& clearFlags(Flags flags) {
GL::Context::Configuration::clearFlags(flags);
return *this;
}
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration)
#endif
private: private:
Vector4i _colorBufferSize; Vector4i _colorBufferSize;
Int _depthBufferSize, _stencilBufferSize; Int _depthBufferSize, _stencilBufferSize;

7
src/Magnum/Platform/EmscriptenApplication.cpp

@ -450,7 +450,7 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration, const
setupAnimationFrame(!!(configuration.windowFlags() & Configuration::WindowFlag::AlwaysRequestAnimationFrame)); setupAnimationFrame(!!(configuration.windowFlags() & Configuration::WindowFlag::AlwaysRequestAnimationFrame));
/* Return true if the initialization succeeds */ /* Return true if the initialization succeeds */
return _context->tryCreate(); return _context->tryCreate(glConfiguration);
} }
#endif #endif
@ -770,7 +770,10 @@ void EmscriptenApplication::textInputEvent(TextInputEvent&) {}
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
EmscriptenApplication::GLConfiguration::GLConfiguration(): EmscriptenApplication::GLConfiguration::GLConfiguration():
_colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0}, _colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0},
_sampleCount{0} {} _sampleCount{0}
{
addFlags(Flag::EnableExtensionsByDefault);
}
#endif #endif
int EmscriptenApplication::exec() { int EmscriptenApplication::exec() {

44
src/Magnum/Platform/EmscriptenApplication.h

@ -40,7 +40,7 @@
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/GL/GL.h" #include "Magnum/GL/Context.h"
#include "Magnum/Math/Vector4.h" #include "Magnum/Math/Vector4.h"
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
@ -926,14 +926,15 @@ The created context is always with a double-buffered OpenGL context.
@see @ref EmscriptenApplication(), @ref Configuration, @ref create(), @see @ref EmscriptenApplication(), @ref Configuration, @ref create(),
@ref tryCreate() @ref tryCreate()
*/ */
class EmscriptenApplication::GLConfiguration { class EmscriptenApplication::GLConfiguration: public GL::Context::Configuration {
public: public:
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: Int { enum class Flag: UnsignedLong {
/** /**
* Premultiplied alpha. If set, the alpha channel of the rendering * Premultiplied alpha. If set, the alpha channel of the rendering
* context will be treated as representing premultiplied alpha * context will be treated as representing premultiplied alpha
@ -987,7 +988,25 @@ class EmscriptenApplication::GLConfiguration {
* Proxy content to main thread. For more details, see the * Proxy content to main thread. For more details, see the
* [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.proxyContextToMainThread). * [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.proxyContextToMainThread).
*/ */
ProxyContextToMainThread = 1 << 7 ProxyContextToMainThread = 1 << 7,
/**
* @copydoc GL::Context::Configuration::Flag::QuietLog
* @m_since_latest
*/
QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog),
/**
* @copydoc GL::Context::Configuration::Flag::VerboseLog
* @m_since_latest
*/
VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog),
/**
* @copydoc GL::Context::Configuration::Flag::GpuValidation
* @m_since_latest
*/
GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation)
}; };
/** /**
@ -1000,7 +1019,9 @@ class EmscriptenApplication::GLConfiguration {
/*implicit*/ GLConfiguration(); /*implicit*/ GLConfiguration();
/** @brief Context flags */ /** @brief Context flags */
Flags flags() const { return _flags; } Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/** /**
* @brief Set context flags * @brief Set context flags
@ -1012,7 +1033,7 @@ class EmscriptenApplication::GLConfiguration {
* @see @ref GL::Context::flags() * @see @ref GL::Context::flags()
*/ */
GLConfiguration& setFlags(Flags flags) { GLConfiguration& setFlags(Flags flags) {
_flags = flags; GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -1025,7 +1046,7 @@ class EmscriptenApplication::GLConfiguration {
* @see @ref clearFlags() * @see @ref clearFlags()
*/ */
GLConfiguration& addFlags(Flags flags) { GLConfiguration& addFlags(Flags flags) {
_flags |= flags; GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -1038,7 +1059,7 @@ class EmscriptenApplication::GLConfiguration {
* @see @ref addFlags() * @see @ref addFlags()
*/ */
GLConfiguration& clearFlags(Flags flags) { GLConfiguration& clearFlags(Flags flags) {
_flags &= ~flags; GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -1112,12 +1133,15 @@ class EmscriptenApplication::GLConfiguration {
return *this; return *this;
} }
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration)
#endif
private: private:
Vector4i _colorBufferSize; Vector4i _colorBufferSize;
Int _depthBufferSize, _stencilBufferSize; Int _depthBufferSize, _stencilBufferSize;
Int _sampleCount; Int _sampleCount;
Flags _flags{Flag::EnableExtensionsByDefault};
}; };
CORRADE_ENUMSET_OPERATORS(EmscriptenApplication::GLConfiguration::Flags) CORRADE_ENUMSET_OPERATORS(EmscriptenApplication::GLConfiguration::Flags)

42
src/Magnum/Platform/GLContext.h

@ -58,26 +58,29 @@ class GLContext: public GL::Context {
* @brief Constructor * @brief Constructor
* *
* Equivalent to calling @ref GLContext(NoCreateT, Int, const char**) * Equivalent to calling @ref GLContext(NoCreateT, Int, const char**)
* followed by @ref create(). * followed by @ref create(const Configuration&).
*/ */
explicit GLContext(Int argc, const char** argv): GLContext{NoCreate, argc, argv} { create(); } explicit GLContext(Int argc, const char** argv, const Configuration& configuration = {}): GLContext{NoCreate, argc, argv} {
create(configuration);
}
/** @overload */ /** @overload */
explicit GLContext(Int argc, char** argv): GLContext{argc, const_cast<const char**>(argv)} {} explicit GLContext(Int argc, char** argv, const Configuration& configuration = {}): GLContext{argc, const_cast<const char**>(argv), configuration} {}
/** @overload */ /** @overload */
explicit GLContext(Int argc, std::nullptr_t argv): GLContext{argc, static_cast<const char**>(argv)} {} explicit GLContext(Int argc, std::nullptr_t argv, const Configuration& configuration = {}): GLContext{argc, static_cast<const char**>(argv), configuration} {}
/** /**
* @brief Default constructor * @brief Default constructor
* *
* Equivalent to passing @cpp {0, nullptr} @ce to * Equivalent to passing @cpp {0, nullptr, configuration} @ce to
* @ref GLContext(Int, const char**). Even if the command-line options * @ref GLContext(Int, const char**, const Configuration&). Even if the
* are not propagated, it's still possible to affect the renderer * command-line options are not propagated, it's still possible to
* behavior from the environment. See @ref GL-Context-command-line for * affect the setup behavior from the environment or by passing a
* more information. * @relativeref{GL::Context,Configuration} instance. See
* @ref GL-Context-usage for more information.
*/ */
explicit GLContext(): GLContext{0, nullptr} {} explicit GLContext(const Configuration& configuration = {}): GLContext{0, nullptr, configuration} {}
/** /**
* @brief Construct without creating the context * @brief Construct without creating the context
@ -85,7 +88,7 @@ class GLContext: public GL::Context {
* Parses command-line arguments and sets @ref version() to * Parses command-line arguments and sets @ref version() to
* @ref GL::Version::None, everything else is left in an empty state. * @ref GL::Version::None, everything else is left in an empty state.
* Use @ref create() or @ref tryCreate() to create the context. * Use @ref create() or @ref tryCreate() to create the context.
* @see @ref GLContext(Int, const char**) * @see @ref GLContext(Int, const char**, const Configuration&)
*/ */
explicit GLContext(NoCreateT, Int argc, const char** argv): explicit GLContext(NoCreateT, Int argc, const char** argv):
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
@ -118,8 +121,9 @@ class GLContext: public GL::Context {
* Equivalent to passing @cpp {NoCreate, 0, nullptr} @ce to * Equivalent to passing @cpp {NoCreate, 0, nullptr} @ce to
* @ref GLContext(NoCreateT, Int, const char**). Even if the * @ref GLContext(NoCreateT, Int, const char**). Even if the
* command-line options are not propagated, it's still possible to * command-line options are not propagated, it's still possible to
* affect the renderer behavior from the environment. See * affect the renderer behavior from the environment or by passing
* @ref GL-Context-command-line for more information. * a @relativeref{GL::Context,Configuration} instance to @ref create()
* or @ref tryCreate(). See @ref GL-Context-usage for more information.
*/ */
explicit GLContext(NoCreateT): GLContext{NoCreate, 0, nullptr} {} explicit GLContext(NoCreateT): GLContext{NoCreate, 0, nullptr} {}
@ -133,13 +137,15 @@ class GLContext: public GL::Context {
* detected version is unsupported or any other error occurs, a message * detected version is unsupported or any other error occurs, a message
* is printed to output and the application exits. See @ref tryCreate() * is printed to output and the application exits. See @ref tryCreate()
* for an alternative. * for an alternative.
* @see @ref GLContext(Int, char**), @ref GL-Context-command-line, * @see @ref GLContext(Int, char**, const Configuration&),
* @fn_gl{Get} with @def_gl{MAJOR_VERSION}, * @ref GL-Context-usage, @fn_gl{Get} with @def_gl{MAJOR_VERSION},
* @def_gl{MINOR_VERSION}, @def_gl{CONTEXT_FLAGS}, * @def_gl{MINOR_VERSION}, @def_gl{CONTEXT_FLAGS},
* @def_gl{NUM_EXTENSIONS}, @fn_gl{GetString} with * @def_gl{NUM_EXTENSIONS}, @fn_gl{GetString} with
* @def_gl{EXTENSIONS} * @def_gl{EXTENSIONS}
*/ */
void create() { return GL::Context::create(); } void create(const Configuration& configuration = Configuration{}) {
return GL::Context::create(configuration);
}
/** /**
* @brief Try to create the context * @brief Try to create the context
@ -147,7 +153,9 @@ class GLContext: public GL::Context {
* Unlike @ref create(), instead of exiting prints a message to error * Unlike @ref create(), instead of exiting prints a message to error
* output and returns `false` on error. * output and returns `false` on error.
*/ */
bool tryCreate() { return GL::Context::tryCreate(); } bool tryCreate(const Configuration& configuration = Configuration{}) {
return GL::Context::tryCreate(configuration);
}
}; };
}} }}

11
src/Magnum/Platform/GlfwApplication.cpp

@ -578,7 +578,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf
glfwMakeContextCurrent(_window); glfwMakeContextCurrent(_window);
/* Destroy everything when the Magnum context creation fails */ /* Destroy everything when the Magnum context creation fails */
if(!_context->tryCreate()) { if(!_context->tryCreate(glConfiguration)) {
glfwDestroyWindow(_window); glfwDestroyWindow(_window);
_window = nullptr; _window = nullptr;
} }
@ -894,13 +894,12 @@ void GlfwApplication::stopTextInput() {
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
GlfwApplication::GLConfiguration::GLConfiguration(): GlfwApplication::GLConfiguration::GLConfiguration():
_colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0}, _colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0},
_sampleCount{0}, _version{GL::Version::None}, _sampleCount{0}, _version{GL::Version::None}, _srgbCapable{false}
{
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_flags{Flag::ForwardCompatible}, addFlags(Flag::ForwardCompatible);
#else
_flags{},
#endif #endif
_srgbCapable{false} {} }
GlfwApplication::GLConfiguration::~GLConfiguration() = default; GlfwApplication::GLConfiguration::~GLConfiguration() = default;
#endif #endif

48
src/Magnum/Platform/GlfwApplication.h

@ -43,7 +43,7 @@
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
#include "Magnum/GL/GL.h" #include "Magnum/GL/Context.h"
#endif #endif
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
@ -777,14 +777,15 @@ The created window is always with a double-buffered OpenGL context.
@see @ref GlfwApplication(), @ref create(), @ref tryCreate() @see @ref GlfwApplication(), @ref create(), @ref tryCreate()
*/ */
class GlfwApplication::GLConfiguration { class GlfwApplication::GLConfiguration: public GL::Context::Configuration {
public: public:
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedByte { enum class Flag: UnsignedLong {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* Forward compatible context * Forward compatible context
@ -807,13 +808,32 @@ class GlfwApplication::GLConfiguration {
#endif #endif
/** /**
* Debug context. Enabled automatically if the * Debug context. Enabled automatically if supported by the driver
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" * and the @ref Flag::GpuValidation flag is set or if the
* `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option"
* is present. * is present.
*/ */
Debug = 1 << 2, Debug = 1 << 2,
Stereo = 1 << 3 /**< Stereo rendering */ Stereo = 1 << 3, /**< Stereo rendering */
/**
* @copydoc GL::Context::Configuration::Flag::QuietLog
* @m_since_latest
*/
QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog),
/**
* @copydoc GL::Context::Configuration::Flag::VerboseLog
* @m_since_latest
*/
VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog),
/**
* @copydoc GL::Context::Configuration::Flag::GpuValidation
* @m_since_latest
*/
GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation)
}; };
/** /**
@ -827,7 +847,9 @@ class GlfwApplication::GLConfiguration {
~GLConfiguration(); ~GLConfiguration();
/** @brief Context flags */ /** @brief Context flags */
Flags flags() const { return _flags; } Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/** /**
* @brief Set context flags * @brief Set context flags
@ -839,7 +861,7 @@ class GlfwApplication::GLConfiguration {
* @see @ref GL::Context::flags() * @see @ref GL::Context::flags()
*/ */
GLConfiguration& setFlags(Flags flags) { GLConfiguration& setFlags(Flags flags) {
_flags = flags; GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -852,7 +874,7 @@ class GlfwApplication::GLConfiguration {
* @see @ref clearFlags() * @see @ref clearFlags()
*/ */
GLConfiguration& addFlags(Flags flags) { GLConfiguration& addFlags(Flags flags) {
_flags |= flags; GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -865,7 +887,7 @@ class GlfwApplication::GLConfiguration {
* @see @ref addFlags() * @see @ref addFlags()
*/ */
GLConfiguration& clearFlags(Flags flags) { GLConfiguration& clearFlags(Flags flags) {
_flags &= ~flags; GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -958,12 +980,16 @@ class GlfwApplication::GLConfiguration {
return *this; return *this;
} }
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration)
#endif
private: private:
Vector4i _colorBufferSize; Vector4i _colorBufferSize;
Int _depthBufferSize, _stencilBufferSize; Int _depthBufferSize, _stencilBufferSize;
Int _sampleCount; Int _sampleCount;
GL::Version _version; GL::Version _version;
Flags _flags;
bool _srgbCapable; bool _srgbCapable;
}; };

26
src/Magnum/Platform/Sdl2Application.cpp

@ -484,7 +484,8 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
#endif #endif
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glFlags)); /* Mask out the upper 32bits used for other flags */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(UnsignedLong(glFlags) & 0xffffffffu));
/* Request usable version otherwise */ /* Request usable version otherwise */
} else { } else {
@ -501,7 +502,8 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
#endif #endif
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glFlags)); /* Mask out the upper 32bits used for other flags */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(UnsignedLong(glFlags) & 0xffffffffu));
#else #else
/* For ES the major context version is compile-time constant */ /* For ES the major context version is compile-time constant */
#ifdef MAGNUM_TARGET_GLES3 #ifdef MAGNUM_TARGET_GLES3
@ -579,8 +581,10 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
/* Discard the ForwardCompatible flag for the fallback. Having it set /* Discard the ForwardCompatible flag for the fallback. Having it set
makes the fallback context creation fail on Mesa's Zink (which is makes the fallback context creation fail on Mesa's Zink (which is
just 2.1) and I assume on others as well. */ just 2.1) and I assume on others as well.
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glFlags) & int(~GLConfiguration::Flag::ForwardCompatible));
Also mask out the upper 32bits used for other flags. */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(UnsignedLong(glFlags & ~GLConfiguration::Flag::ForwardCompatible) & 0xffffffffu));
if(!(_window = SDL_CreateWindow(configuration.title().data(), if(!(_window = SDL_CreateWindow(configuration.title().data(),
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
@ -666,7 +670,7 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf
#endif #endif
/* Destroy everything also when the Magnum context creation fails */ /* Destroy everything also when the Magnum context creation fails */
if(!_context->tryCreate()) { if(!_context->tryCreate(glConfiguration)) {
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
SDL_GL_DeleteContext(_glContext); SDL_GL_DeleteContext(_glContext);
SDL_DestroyWindow(_window); SDL_DestroyWindow(_window);
@ -1184,15 +1188,13 @@ Sdl2Application::GLConfiguration::GLConfiguration():
_colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0}, _colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0},
_sampleCount(0) _sampleCount(0)
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
, _version(GL::Version::None), , _version{GL::Version::None}, _srgbCapable{false}
#ifndef MAGNUM_TARGET_GLES
_flags{Flag::ForwardCompatible},
#else
_flags{},
#endif #endif
_srgbCapable{false} {
#ifndef MAGNUM_TARGET_GLES
addFlags(Flag::ForwardCompatible);
#endif #endif
{} }
Sdl2Application::GLConfiguration::~GLConfiguration() = default; Sdl2Application::GLConfiguration::~GLConfiguration() = default;
#endif #endif

79
src/Magnum/Platform/Sdl2Application.h

@ -42,7 +42,7 @@
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
#include "Magnum/GL/GL.h" #include "Magnum/GL/Context.h"
#endif #endif
#ifdef CORRADE_TARGET_WINDOWS /* Windows version of SDL2 redefines main(), we don't want that */ #ifdef CORRADE_TARGET_WINDOWS /* Windows version of SDL2 redefines main(), we don't want that */
@ -1229,20 +1229,19 @@ The created window is always with a double-buffered OpenGL context.
@see @ref Sdl2Application(), @ref create(), @ref tryCreate() @see @ref Sdl2Application(), @ref create(), @ref tryCreate()
*/ */
class Sdl2Application::GLConfiguration { class Sdl2Application::GLConfiguration: public GL::Context::Configuration {
public: public:
#ifndef CORRADE_TARGET_EMSCRIPTEN
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
* @requires_gles Context flags are not available in WebGL.
*/ */
enum class Flag: int { enum class Flag: UnsignedLong {
#ifndef CORRADE_TARGET_EMSCRIPTEN
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* Forward compatible context * Forward compatible context.
*
* @requires_gl Core/compatibility profile distinction and forward * @requires_gl Core/compatibility profile distinction and forward
* compatibility applies only to desktop GL. * compatibility applies only to desktop GL.
*/ */
@ -1250,38 +1249,60 @@ class Sdl2Application::GLConfiguration {
#endif #endif
/** /**
* Debug context. Enabled automatically if the * Debug context. Enabled automatically if supported by the driver
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" * and the @ref Flag::GpuValidation flag is set or if the
* `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option"
* is present. * is present.
* @requires_gles Context flags are not available in WebGL.
*/ */
Debug = SDL_GL_CONTEXT_DEBUG_FLAG, Debug = SDL_GL_CONTEXT_DEBUG_FLAG,
/** Context with robust access */ /**
* Context with robust access.
* @requires_gles Context flags are not available in WebGL.
*/
RobustAccess = SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG, RobustAccess = SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG,
/** Context with reset isolation */ /**
ResetIsolation = SDL_GL_CONTEXT_RESET_ISOLATION_FLAG * Context with reset isolation.
* @requires_gles Context flags are not available in WebGL.
*/
ResetIsolation = SDL_GL_CONTEXT_RESET_ISOLATION_FLAG,
#endif
/**
* @copydoc GL::Context::Configuration::Flag::QuietLog
* @m_since_latest
*/
QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog),
/**
* @copydoc GL::Context::Configuration::Flag::VerboseLog
* @m_since_latest
*/
VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog),
/**
* @copydoc GL::Context::Configuration::Flag::GpuValidation
* @m_since_latest
*/
GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation)
}; };
/** /**
* @brief Context flags * @brief Context flags
* *
* @see @ref setFlags(), @ref GL::Context::Flags * @see @ref setFlags(), @ref GL::Context::Flags
* @requires_gles Context flags are not available in WebGL.
*/ */
typedef Containers::EnumSet<Flag> Flags; typedef Containers::EnumSet<Flag> Flags;
#endif
explicit GLConfiguration(); explicit GLConfiguration();
~GLConfiguration(); ~GLConfiguration();
#ifndef CORRADE_TARGET_EMSCRIPTEN /** @brief Context flags */
/** Flags flags() const {
* @brief Context flags return Flag(UnsignedLong(GL::Context::Configuration::flags()));
* }
* @requires_gles Context flags are not available in WebGL.
*/
Flags flags() const { return _flags; }
/** /**
* @brief Set context flags * @brief Set context flags
@ -1291,10 +1312,9 @@ class Sdl2Application::GLConfiguration {
* on OpenGL ES. To avoid clearing default flags by accident, prefer to * on OpenGL ES. To avoid clearing default flags by accident, prefer to
* use @ref addFlags() and @ref clearFlags() instead. * use @ref addFlags() and @ref clearFlags() instead.
* @see @ref GL::Context::flags() * @see @ref GL::Context::flags()
* @requires_gles Context flags are not available in WebGL.
*/ */
GLConfiguration& setFlags(Flags flags) { GLConfiguration& setFlags(Flags flags) {
_flags = flags; GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -1305,10 +1325,9 @@ class Sdl2Application::GLConfiguration {
* Unlike @ref setFlags(), ORs the flags with existing instead of * Unlike @ref setFlags(), ORs the flags with existing instead of
* replacing them. Useful for preserving the defaults. * replacing them. Useful for preserving the defaults.
* @see @ref clearFlags() * @see @ref clearFlags()
* @requires_gles Context flags are not available in WebGL.
*/ */
GLConfiguration& addFlags(Flags flags) { GLConfiguration& addFlags(Flags flags) {
_flags |= flags; GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -1319,13 +1338,13 @@ class Sdl2Application::GLConfiguration {
* Unlike @ref setFlags(), ANDs the inverse of @p flags with existing * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing
* instead of replacing them. Useful for removing default flags. * instead of replacing them. Useful for removing default flags.
* @see @ref addFlags() * @see @ref addFlags()
* @requires_gles Context flags are not available in WebGL.
*/ */
GLConfiguration& clearFlags(Flags flags) { GLConfiguration& clearFlags(Flags flags) {
_flags &= ~flags; GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
#ifndef CORRADE_TARGET_EMSCRIPTEN
/** /**
* @brief Context version * @brief Context version
* *
@ -1434,13 +1453,17 @@ class Sdl2Application::GLConfiguration {
} }
#endif #endif
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration)
#endif
private: private:
Vector4i _colorBufferSize; Vector4i _colorBufferSize;
Int _depthBufferSize, _stencilBufferSize; Int _depthBufferSize, _stencilBufferSize;
Int _sampleCount; Int _sampleCount;
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
GL::Version _version; GL::Version _version;
Flags _flags;
bool _srgbCapable; bool _srgbCapable;
#endif #endif
}; };

10
src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp

@ -153,6 +153,7 @@ EmscriptenApplicationTest::EmscriptenApplicationTest(const Arguments& arguments)
Utility::Arguments args; Utility::Arguments args;
args.addSkippedPrefix("magnum", "engine-specific options") args.addSkippedPrefix("magnum", "engine-specific options")
.addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after") .addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after")
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv); .parse(arguments.argc, arguments.argv);
/* Useful for bisecting Emscripten regressions, because they happen WAY TOO /* Useful for bisecting Emscripten regressions, because they happen WAY TOO
@ -167,9 +168,12 @@ EmscriptenApplicationTest::EmscriptenApplicationTest(const Arguments& arguments)
return; return;
} }
create(Configuration{}.setWindowFlags(Configuration::WindowFlag::Resizable) Configuration conf;
//, GLConfiguration{}.setFlags({}) conf.setWindowFlags(Configuration::WindowFlag::Resizable);
); if(args.isSet("quiet"))
create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog));
else
create(conf);
Debug{} << "window size" << windowSize() Debug{} << "window size" << windowSize()
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL

12
src/Magnum/Platform/Test/GlfwApplicationTest.cpp

@ -108,6 +108,9 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform::
.addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after") .addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after")
.addBooleanOption("borderless").setHelp("borderless", "no window decoration") .addBooleanOption("borderless").setHelp("borderless", "no window decoration")
.addBooleanOption("always-on-top").setHelp("always-on-top", "always on top") .addBooleanOption("always-on-top").setHelp("always-on-top", "always on top")
#ifdef MAGNUM_TARGET_GL
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
#endif
.parse(arguments.argc, arguments.argv); .parse(arguments.argc, arguments.argv);
if(args.isSet("exit-immediately")) { if(args.isSet("exit-immediately")) {
@ -123,7 +126,14 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform::
conf.addWindowFlags(Configuration::WindowFlag::Borderless); conf.addWindowFlags(Configuration::WindowFlag::Borderless);
if(args.isSet("always-on-top")) if(args.isSet("always-on-top"))
conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop); conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop);
create(conf); #ifdef MAGNUM_TARGET_GL
if(args.isSet("quiet")) {
create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog));
} else
#endif
{
create(conf);
}
/* For testing resize events */ /* For testing resize events */
Debug{} << "window size" << windowSize() Debug{} << "window size" << windowSize()

6
src/Magnum/Platform/Test/GlxApplicationTest.cpp

@ -42,6 +42,7 @@ GlxApplicationTest::GlxApplicationTest(const Arguments& arguments): Platform::Ap
Utility::Arguments args; Utility::Arguments args;
args.addSkippedPrefix("magnum", "engine-specific options") args.addSkippedPrefix("magnum", "engine-specific options")
.addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after") .addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after")
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv); .parse(arguments.argc, arguments.argv);
if(args.isSet("exit-immediately")) { if(args.isSet("exit-immediately")) {
@ -49,7 +50,10 @@ GlxApplicationTest::GlxApplicationTest(const Arguments& arguments): Platform::Ap
return; return;
} }
create(Configuration{}); if(args.isSet("quiet"))
create(Configuration{}, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog));
else
create();
} }
}}}} }}}}

12
src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp

@ -165,6 +165,9 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform::
.addBooleanOption("always-on-top").setHelp("always-on-top", "always on top") .addBooleanOption("always-on-top").setHelp("always-on-top", "always on top")
#endif #endif
#endif #endif
#ifdef MAGNUM_TARGET_GL
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
#endif
.parse(arguments.argc, arguments.argv); .parse(arguments.argc, arguments.argv);
if(args.isSet("exit-immediately")) { if(args.isSet("exit-immediately")) {
@ -184,7 +187,14 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform::
conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop); conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop);
#endif #endif
#endif #endif
create(conf); #ifdef MAGNUM_TARGET_GL
if(args.isSet("quiet")) {
create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog));
} else
#endif
{
create(conf);
}
/* For testing resize events */ /* For testing resize events */
Debug{} << "window size" << windowSize() Debug{} << "window size" << windowSize()

16
src/Magnum/Platform/Test/WindowlessCglApplicationTest.cpp

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessCglApplication.h" #include "Magnum/Platform/WindowlessCglApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace { namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessCglApplicationTest: Platform::WindowlessApplication { struct WindowlessCglApplicationTest: Platform::WindowlessApplication {
explicit WindowlessCglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} explicit WindowlessCglApplicationTest(const Arguments& arguments);
int exec() override { return 0; } int exec() override { return 0; }
}; };
WindowlessCglApplicationTest::WindowlessCglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} {
Utility::Arguments args;
args.addSkippedPrefix("magnum", "engine-specific options")
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv);
if(args.isSet("quiet"))
createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog));
else
createContext();
}
}}}} }}}}
MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessCglApplicationTest) MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessCglApplicationTest)

16
src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessEglApplication.h" #include "Magnum/Platform/WindowlessEglApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace { namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessEglApplicationTest: Platform::WindowlessApplication { struct WindowlessEglApplicationTest: Platform::WindowlessApplication {
explicit WindowlessEglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} explicit WindowlessEglApplicationTest(const Arguments& arguments);
int exec() override { return 0; } int exec() override { return 0; }
}; };
WindowlessEglApplicationTest::WindowlessEglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} {
Utility::Arguments args;
args.addSkippedPrefix("magnum", "engine-specific options")
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv);
if(args.isSet("quiet"))
createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog));
else
createContext();
}
}}}} }}}}
MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessEglApplicationTest) MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessEglApplicationTest)

16
src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessGlxApplication.h" #include "Magnum/Platform/WindowlessGlxApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace { namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessGlxApplicationTest: Platform::WindowlessApplication { struct WindowlessGlxApplicationTest: Platform::WindowlessApplication {
explicit WindowlessGlxApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} explicit WindowlessGlxApplicationTest(const Arguments& arguments);
int exec() override { return 0; } int exec() override { return 0; }
}; };
WindowlessGlxApplicationTest::WindowlessGlxApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} {
Utility::Arguments args;
args.addSkippedPrefix("magnum", "engine-specific options")
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv);
if(args.isSet("quiet"))
createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog));
else
createContext();
}
}}}} }}}}
MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessGlxApplicationTest) MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessGlxApplicationTest)

16
src/Magnum/Platform/Test/WindowlessIosApplicationTest.cpp

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessIosApplication.h" #include "Magnum/Platform/WindowlessIosApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace { namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessIosApplicationTest: Platform::WindowlessApplication { struct WindowlessIosApplicationTest: Platform::WindowlessApplication {
explicit WindowlessIosApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} explicit WindowlessIosApplicationTest(const Arguments& arguments);
int exec() override { return 0; } int exec() override { return 0; }
}; };
WindowlessIosApplicationTest::WindowlessIosApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} {
Utility::Arguments args;
args.addSkippedPrefix("magnum", "engine-specific options")
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv);
if(args.isSet("quiet"))
createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog));
else
createContext();
}
}}}} }}}}
MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessIosApplicationTest) MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessIosApplicationTest)

16
src/Magnum/Platform/Test/WindowlessWglApplicationTest.cpp

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessWglApplication.h" #include "Magnum/Platform/WindowlessWglApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace { namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessWglApplicationTest: Platform::WindowlessApplication { struct WindowlessWglApplicationTest: Platform::WindowlessApplication {
explicit WindowlessWglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} explicit WindowlessWglApplicationTest(const Arguments& arguments);
int exec() override { return 0; } int exec() override { return 0; }
}; };
WindowlessWglApplicationTest::WindowlessWglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} {
Utility::Arguments args;
args.addSkippedPrefix("magnum", "engine-specific options")
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv);
if(args.isSet("quiet"))
createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog));
else
createContext();
}
}}}} }}}}
MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessWglApplicationTest) MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessWglApplicationTest)

16
src/Magnum/Platform/Test/WindowlessWindowsEglApplicationTest.cpp

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessWindowsEglApplication.h" #include "Magnum/Platform/WindowlessWindowsEglApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace { namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessWindowsEglApplicationTest: Platform::WindowlessApplication { struct WindowlessWindowsEglApplicationTest: Platform::WindowlessApplication {
explicit WindowlessWindowsEglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} explicit WindowlessWindowsEglApplicationTest(const Arguments& arguments);
int exec() override { return 0; } int exec() override { return 0; }
}; };
WindowlessWindowsEglApplicationTest::WindowlessWindowsEglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} {
Utility::Arguments args;
args.addSkippedPrefix("magnum", "engine-specific options")
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv);
if(args.isSet("quiet"))
createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog));
else
createContext();
}
}}}} }}}}
MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessWindowsEglApplicationTest) MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessWindowsEglApplicationTest)

7
src/Magnum/Platform/Test/XEglApplicationTest.cpp

@ -42,6 +42,7 @@ XEglApplicationTest::XEglApplicationTest(const Arguments& arguments): Platform::
Utility::Arguments args; Utility::Arguments args;
args.addSkippedPrefix("magnum", "engine-specific options") args.addSkippedPrefix("magnum", "engine-specific options")
.addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after") .addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after")
.addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv); .parse(arguments.argc, arguments.argv);
if(args.isSet("exit-immediately")) { if(args.isSet("exit-immediately")) {
@ -49,10 +50,12 @@ XEglApplicationTest::XEglApplicationTest(const Arguments& arguments): Platform::
return; return;
} }
create(Configuration{}); if(args.isSet("quiet"))
create(Configuration{}, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog));
else
create();
} }
}}}} }}}}
MAGNUM_APPLICATION_MAIN(Magnum::Platform::Test::XEglApplicationTest) MAGNUM_APPLICATION_MAIN(Magnum::Platform::Test::XEglApplicationTest)

4
src/Magnum/Platform/WindowlessCglApplication.cpp

@ -36,7 +36,7 @@
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
WindowlessCglContext::WindowlessCglContext(const Configuration & configuration, GLContext*) { WindowlessCglContext::WindowlessCglContext(const Configuration& configuration, GLContext*) {
int formatCount; int formatCount;
CGLPixelFormatAttribute attributes32[] = { CGLPixelFormatAttribute attributes32[] = {
kCGLPFAAccelerated, kCGLPFAAccelerated,
@ -128,7 +128,7 @@ bool WindowlessCglApplication::tryCreateContext(const Configuration& configurati
CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessCglApplication::tryCreateContext(): context already created", false); CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessCglApplication::tryCreateContext(): context already created", false);
WindowlessCglContext glContext{configuration, _context.get()}; WindowlessCglContext glContext{configuration, _context.get()};
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration))
return false; return false;
_glContext = std::move(glContext); _glContext = std::move(glContext);

23
src/Magnum/Platform/WindowlessCglApplication.h

@ -39,7 +39,7 @@
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/GL/OpenGL.h" #include "Magnum/GL/Context.h"
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
@ -164,10 +164,8 @@ class WindowlessCglContext {
@ref WindowlessCglApplication::createContext(), @ref WindowlessCglApplication::createContext(),
@ref WindowlessCglApplication::tryCreateContext() @ref WindowlessCglApplication::tryCreateContext()
*/ */
class WindowlessCglContext::Configuration { class WindowlessCglContext::Configuration: public GL::Context::Configuration {
public: public:
constexpr /*implicit*/ Configuration() {}
/** /**
* @brief Create a shared context * @brief Create a shared context
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
@ -192,6 +190,23 @@ class WindowlessCglContext::Configuration {
*/ */
CGLContextObj sharedContext() const { return _sharedContext; } CGLContextObj sharedContext() const { return _sharedContext; }
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
Configuration& setFlags(Flags flags) {
GL::Context::Configuration::setFlags(flags);
return *this;
}
Configuration& addFlags(Flags flags) {
GL::Context::Configuration::addFlags(flags);
return *this;
}
Configuration& clearFlags(Flags flags) {
GL::Context::Configuration::clearFlags(flags);
return *this;
}
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration)
#endif
private: private:
CGLContextObj _sharedContext = nullptr; CGLContextObj _sharedContext = nullptr;
}; };

30
src/Magnum/Platform/WindowlessEglApplication.cpp

@ -328,8 +328,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
#endif #endif
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
/* Needs to be last because we're zeroing this out for SwiftShader (see /* Needs to be last because we're zeroing this out for SwiftShader (see
below) */ below).
EGL_CONTEXT_FLAGS_KHR, EGLint(flags),
Also mask out the upper 32bits used for other flags. */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu),
#endif #endif
EGL_NONE EGL_NONE
}; };
@ -369,8 +371,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
const EGLint fallbackAttributes[] = { const EGLint fallbackAttributes[] = {
/* 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.
EGL_CONTEXT_FLAGS_KHR, GLint(flags & ~Configuration::Flag::ForwardCompatible),
Also mask out the upper 32bits used for other flags. */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu),
EGL_NONE EGL_NONE
}; };
_context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes); _context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes);
@ -409,8 +413,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
/* 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.
EGL_CONTEXT_FLAGS_KHR, GLint(flags & ~Configuration::Flag::ForwardCompatible),
Also mask out the upper 32bits used for other flags. */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu),
EGL_NONE EGL_NONE
}; };
_context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes); _context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes);
@ -519,12 +525,14 @@ bool WindowlessEglContext::release() {
} }
WindowlessEglContext::Configuration::Configuration() WindowlessEglContext::Configuration::Configuration()
#ifndef MAGNUM_TARGET_WEBGL
: _device{}
#endif
{
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
: _flags{Flag::ForwardCompatible}, _device{} addFlags(Flag::ForwardCompatible);
#elif !defined(MAGNUM_TARGET_WEBGL)
: _flags{}, _device{}
#endif #endif
{} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments): WindowlessEglApplication{arguments, Configuration{}} {} WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments): WindowlessEglApplication{arguments, Configuration{}} {}
@ -574,7 +582,7 @@ bool WindowlessEglApplication::tryCreateContext(const Configuration& configurati
#endif #endif
WindowlessEglContext glContext{mergedConfiguration, _context.get()}; WindowlessEglContext glContext{mergedConfiguration, _context.get()};
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration))
return false; return false;
_glContext = std::move(glContext); _glContext = std::move(glContext);

70
src/Magnum/Platform/WindowlessEglApplication.h

@ -58,7 +58,7 @@ typedef int Bool;
#endif #endif
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/GL/OpenGL.h" #include "Magnum/GL/Context.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
@ -179,16 +179,16 @@ class WindowlessEglContext {
@ref WindowlessEglApplication::createContext(), @ref WindowlessEglApplication::createContext(),
@ref WindowlessEglApplication::tryCreateContext() @ref WindowlessEglApplication::tryCreateContext()
*/ */
class WindowlessEglContext::Configuration { class WindowlessEglContext::Configuration: public GL::Context::Configuration {
public: public:
#ifndef MAGNUM_TARGET_WEBGL
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
* @requires_gles Context flags are not available in WebGL.
*/ */
enum class Flag: int { enum class Flag: UnsignedLong {
#ifndef MAGNUM_TARGET_WEBGL
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* Forward compatible context * Forward compatible context
@ -200,31 +200,47 @@ class WindowlessEglContext::Configuration {
#endif #endif
/** /**
* Debug context. Enabled automatically if the * Debug context. Enabled automatically if supported by the driver
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" * and the @ref Flag::GpuValidation flag is set or if the
* `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option"
* is present. * is present.
* @requires_gles Context flags are not available in WebGL.
*/
Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR,
#endif
/**
* @copydoc GL::Context::Configuration::Flag::QuietLog
* @m_since_latest
*/
QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog),
/**
* @copydoc GL::Context::Configuration::Flag::VerboseLog
* @m_since_latest
*/
VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog),
/**
* @copydoc GL::Context::Configuration::Flag::GpuValidation
* @m_since_latest
*/ */
Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation)
}; };
/** /**
* @brief Context flags * @brief Context flags
* *
* @see @ref setFlags(), @ref Context::Flags * @see @ref setFlags(), @ref Context::Flags
* @requires_gles Context flags are not available in WebGL.
*/ */
typedef Containers::EnumSet<Flag> Flags; typedef Containers::EnumSet<Flag> Flags;
#endif
/*implicit*/ Configuration(); /*implicit*/ Configuration();
#ifndef MAGNUM_TARGET_WEBGL /** @brief Context flags */
/** Flags flags() const {
* @brief Context flags return Flag(UnsignedLong(GL::Context::Configuration::flags()));
* }
* @requires_gles Context flags are not available in WebGL.
*/
Flags flags() const { return _flags; }
/** /**
* @brief Set context flags * @brief Set context flags
@ -234,10 +250,9 @@ class WindowlessEglContext::Configuration {
* on OpenGL ES. To avoid clearing default flags by accident, prefer to * on OpenGL ES. To avoid clearing default flags by accident, prefer to
* use @ref addFlags() and @ref clearFlags() instead. * use @ref addFlags() and @ref clearFlags() instead.
* @see @ref GL::Context::flags() * @see @ref GL::Context::flags()
* @requires_gles Context flags are not available in WebGL.
*/ */
Configuration& setFlags(Flags flags) { Configuration& setFlags(Flags flags) {
_flags = flags; GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -248,10 +263,9 @@ class WindowlessEglContext::Configuration {
* Unlike @ref setFlags(), ORs the flags with existing instead of * Unlike @ref setFlags(), ORs the flags with existing instead of
* replacing them. Useful for preserving the defaults. * replacing them. Useful for preserving the defaults.
* @see @ref clearFlags() * @see @ref clearFlags()
* @requires_gles Context flags are not available in WebGL.
*/ */
Configuration& addFlags(Flags flags) { Configuration& addFlags(Flags flags) {
_flags |= flags; GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -262,13 +276,13 @@ class WindowlessEglContext::Configuration {
* Unlike @ref setFlags(), ANDs the inverse of @p flags with existing * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing
* instead of replacing them. Useful for removing default flags. * instead of replacing them. Useful for removing default flags.
* @see @ref addFlags() * @see @ref addFlags()
* @requires_gles Context flags are not available in WebGL.
*/ */
Configuration& clearFlags(Flags flags) { Configuration& clearFlags(Flags flags) {
_flags &= ~flags; GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_WEBGL
/** /**
* @brief Device ID to use * @brief Device ID to use
* @m_since{2019,10} * @m_since{2019,10}
@ -364,9 +378,13 @@ class WindowlessEglContext::Configuration {
EGLContext sharedContext() const { return _sharedContext; } EGLContext sharedContext() const { return _sharedContext; }
#endif #endif
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration)
#endif
private: private:
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
Flags _flags;
UnsignedInt _device; UnsignedInt _device;
/* Assumes that you can't have 2^32 - 1 GPUs */ /* Assumes that you can't have 2^32 - 1 GPUs */
UnsignedInt _cudaDevice = ~UnsignedInt{}; UnsignedInt _cudaDevice = ~UnsignedInt{};
@ -503,7 +521,7 @@ can override that either with @ref Configuration::setDevice() or using a
`--magnum-device` command-line option (and the `MAGNUM_DEVICE` environment `--magnum-device` command-line option (and the `MAGNUM_DEVICE` environment
variable). Unfortunately EGL doesn't provide any reasonable way to enumerate or variable). Unfortunately EGL doesn't provide any reasonable way to enumerate or
filter named devices, so the best you can do is checking reported device count filter named devices, so the best you can do is checking reported device count
printed by the `--magnum-log verbose` @ref GL-Context-command-line "command-line option", printed by the `--magnum-log verbose` @ref GL-Context-usage-command-line "command-line option",
and then going from `0` up to figure out the desired device ID. and then going from `0` up to figure out the desired device ID.
On systems with NVIDIA GPUs and CUDA, it's possible to directly select a On systems with NVIDIA GPUs and CUDA, it's possible to directly select a
@ -521,7 +539,7 @@ Systems running Mesa 19.2 (which has the above extensions) that also have
`libEGL_nvidia.so` installed (for example as a CUDA dependency) may fail `libEGL_nvidia.so` installed (for example as a CUDA dependency) may fail
to create the context with the following error (with additional output to create the context with the following error (with additional output
produced when the `--magnum-gpu-validation` produced when the `--magnum-gpu-validation`
@ref GL-Context-command-line "command-line option" is enabled): @ref GL-Context-usage-command-line "command-line option" is enabled):
@m_class{m-console-wrap} @m_class{m-console-wrap}

28
src/Magnum/Platform/WindowlessGlxApplication.cpp

@ -126,12 +126,14 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura
#endif #endif
GLX_CONTEXT_MINOR_VERSION_ARB, 0, GLX_CONTEXT_MINOR_VERSION_ARB, 0,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
GLX_CONTEXT_FLAGS_ARB, GLint(flags), /* Mask out the upper 32bits used for other flags */
GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu),
#else #else
GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 1, GLX_CONTEXT_MINOR_VERSION_ARB, 1,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
GLX_CONTEXT_FLAGS_ARB, GLint(flags), /* Mask out the upper 32bits used for other flags */
GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu),
#endif #endif
0 0
}; };
@ -155,8 +157,10 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura
const GLint fallbackContextAttributes[] = { const GLint fallbackContextAttributes[] = {
/* 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.
GLX_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible),
Also mask out the upper 32bits used for other flags. */
GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu),
0 0
}; };
{ {
@ -198,8 +202,10 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura
/* 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.
GLX_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible),
Also mask out the upper 32bits used for other flags. */
GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu),
0 0
}; };
{ {
@ -267,13 +273,11 @@ bool WindowlessGlxContext::release() {
return false; return false;
} }
WindowlessGlxContext::Configuration::Configuration(): WindowlessGlxContext::Configuration::Configuration() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_flags{Flag::ForwardCompatible} addFlags(Flag::ForwardCompatible);
#else
_flags{}
#endif #endif
{} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments): WindowlessGlxApplication{arguments, Configuration{}} {} WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments): WindowlessGlxApplication{arguments, Configuration{}} {}
@ -295,7 +299,7 @@ bool WindowlessGlxApplication::tryCreateContext(const Configuration& configurati
CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessGlxApplication::tryCreateContext(): context already created", false); CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessGlxApplication::tryCreateContext(): context already created", false);
WindowlessGlxContext glContext{configuration, _context.get()}; WindowlessGlxContext glContext{configuration, _context.get()};
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration))
return false; return false;
_glContext = std::move(glContext); _glContext = std::move(glContext);

48
src/Magnum/Platform/WindowlessGlxApplication.h

@ -39,7 +39,7 @@
/* Include our GL headers first to avoid conflicts */ /* Include our GL headers first to avoid conflicts */
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/GL/OpenGL.h" #include "Magnum/GL/Context.h"
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
#include <GL/glx.h> #include <GL/glx.h>
@ -185,14 +185,15 @@ class WindowlessGlxContext {
@ref WindowlessGlxApplication::createContext(), @ref WindowlessGlxApplication::createContext(),
@ref WindowlessGlxApplication::tryCreateContext() @ref WindowlessGlxApplication::tryCreateContext()
*/ */
class WindowlessGlxContext::Configuration { class WindowlessGlxContext::Configuration: public GL::Context::Configuration {
public: public:
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: int { enum class Flag: UnsignedLong {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* Forward compatible context * Forward compatible context
@ -204,11 +205,30 @@ class WindowlessGlxContext::Configuration {
#endif #endif
/** /**
* Debug context. Enabled automatically if the * Debug context. Enabled automatically if supported by the driver
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" * and the @ref Flag::GpuValidation flag is set or if the
* `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option"
* is present. * is present.
*/ */
Debug = GLX_CONTEXT_DEBUG_BIT_ARB Debug = GLX_CONTEXT_DEBUG_BIT_ARB,
/**
* @copydoc GL::Context::Configuration::Flag::QuietLog
* @m_since_latest
*/
QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog),
/**
* @copydoc GL::Context::Configuration::Flag::VerboseLog
* @m_since_latest
*/
VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog),
/**
* @copydoc GL::Context::Configuration::Flag::GpuValidation
* @m_since_latest
*/
GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation)
}; };
/** /**
@ -221,7 +241,9 @@ class WindowlessGlxContext::Configuration {
/*implicit*/ Configuration(); /*implicit*/ Configuration();
/** @brief Context flags */ /** @brief Context flags */
Flags flags() const { return _flags; } Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/** /**
* @brief Set context flags * @brief Set context flags
@ -233,7 +255,7 @@ class WindowlessGlxContext::Configuration {
* @see @ref GL::Context::flags() * @see @ref GL::Context::flags()
*/ */
Configuration& setFlags(Flags flags) { Configuration& setFlags(Flags flags) {
_flags = flags; GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -246,7 +268,7 @@ class WindowlessGlxContext::Configuration {
* @see @ref clearFlags() * @see @ref clearFlags()
*/ */
Configuration& addFlags(Flags flags) { Configuration& addFlags(Flags flags) {
_flags |= flags; GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -259,7 +281,7 @@ class WindowlessGlxContext::Configuration {
* @see @ref addFlags() * @see @ref addFlags()
*/ */
Configuration& clearFlags(Flags flags) { Configuration& clearFlags(Flags flags) {
_flags &= ~flags; GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -287,8 +309,12 @@ class WindowlessGlxContext::Configuration {
*/ */
GLXContext sharedContext() const { return _sharedContext; } GLXContext sharedContext() const { return _sharedContext; }
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration)
#endif
private: private:
Flags _flags;
GLXContext _sharedContext = nullptr; GLXContext _sharedContext = nullptr;
}; };

22
src/Magnum/Platform/WindowlessIosApplication.h

@ -37,7 +37,7 @@
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/GL/OpenGL.h" #include "Magnum/GL/Context.h"
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
#ifdef __OBJC__ #ifdef __OBJC__
@ -154,9 +154,25 @@ class WindowlessIosContext {
@ref WindowlessIosApplication::createContext(), @ref WindowlessIosApplication::createContext(),
@ref WindowlessIosApplication::tryCreateContext() @ref WindowlessIosApplication::tryCreateContext()
*/ */
class WindowlessIosContext::Configuration { class WindowlessIosContext::Configuration: public GL::Context::Configuration {
public: public:
constexpr /*implicit*/ Configuration() {} /* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
Configuration& setFlags(Flags flags) {
GL::Context::Configuration::setFlags(flags);
return *this;
}
Configuration& addFlags(Flags flags) {
GL::Context::Configuration::addFlags(flags);
return *this;
}
Configuration& clearFlags(Flags flags) {
GL::Context::Configuration::clearFlags(flags);
return *this;
}
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration)
#endif
}; };
/** /**

22
src/Magnum/Platform/WindowlessWglApplication.cpp

@ -139,12 +139,14 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G
#endif #endif
WGL_CONTEXT_MINOR_VERSION_ARB, 0, WGL_CONTEXT_MINOR_VERSION_ARB, 0,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_ES2_PROFILE_BIT_EXT, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_ES2_PROFILE_BIT_EXT,
WGL_CONTEXT_FLAGS_ARB, GLint(flags), /* Mask out the upper 32bits used for other flags */
WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu),
#else #else
WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 1, WGL_CONTEXT_MINOR_VERSION_ARB, 1,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
WGL_CONTEXT_FLAGS_ARB, GLint(flags), /* Mask out the upper 32bits used for other flags */
WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu),
#endif #endif
0 0
}; };
@ -157,7 +159,8 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G
const int fallbackContextAttributes[] = { const int fallbackContextAttributes[] = {
/** @todo or keep the fwcompat? */ /** @todo or keep the fwcompat? */
WGL_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible), /* Mask out the upper 32bits used for other flags */
WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu),
0 0
}; };
_context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes); _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes);
@ -196,7 +199,8 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G
wglDeleteContext(_context); wglDeleteContext(_context);
const int fallbackContextAttributes[] = { const int fallbackContextAttributes[] = {
/** @todo or keep the fwcompat? */ /** @todo or keep the fwcompat? */
WGL_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible), /* Mask out the upper 32bits used for other flags */
WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu),
0 0
}; };
_context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes); _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes);
@ -254,13 +258,11 @@ bool WindowlessWglContext::release() {
return false; return false;
} }
WindowlessWglContext::Configuration::Configuration(): WindowlessWglContext::Configuration::Configuration() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_flags{Flag::ForwardCompatible} addFlags(Flag::ForwardCompatible);
#else
_flags{}
#endif #endif
{} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments): WindowlessWglApplication{arguments, Configuration{}} {} WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments): WindowlessWglApplication{arguments, Configuration{}} {}
@ -282,7 +284,7 @@ bool WindowlessWglApplication::tryCreateContext(const Configuration& configurati
CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessWglApplication::tryCreateContext(): context already created", false); CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessWglApplication::tryCreateContext(): context already created", false);
WindowlessWglContext glContext{configuration, _context.get()}; WindowlessWglContext glContext{configuration, _context.get()};
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration))
return false; return false;
_glContext = std::move(glContext); _glContext = std::move(glContext);

48
src/Magnum/Platform/WindowlessWglApplication.h

@ -42,7 +42,7 @@
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/GL/OpenGL.h" #include "Magnum/GL/Context.h"
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
@ -172,14 +172,15 @@ class WindowlessWglContext {
@ref WindowlessWglApplication::createContext(), @ref WindowlessWglApplication::createContext(),
@ref WindowlessWglApplication::tryCreateContext() @ref WindowlessWglApplication::tryCreateContext()
*/ */
class WindowlessWglContext::Configuration { class WindowlessWglContext::Configuration: public GL::Context::Configuration {
public: public:
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: int { enum class Flag: UnsignedLong {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* Forward compatible context * Forward compatible context
@ -191,11 +192,30 @@ class WindowlessWglContext::Configuration {
#endif #endif
/** /**
* Debug context. Enabled automatically if the * Debug context. Enabled automatically if supported by the driver
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" * and the @ref Flag::GpuValidation flag is set or if the
* `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option"
* is present. * is present.
*/ */
Debug = WGL_CONTEXT_DEBUG_BIT_ARB Debug = WGL_CONTEXT_DEBUG_BIT_ARB,
/**
* @copydoc GL::Context::Configuration::Flag::QuietLog
* @m_since_latest
*/
QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog),
/**
* @copydoc GL::Context::Configuration::Flag::VerboseLog
* @m_since_latest
*/
VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog),
/**
* @copydoc GL::Context::Configuration::Flag::GpuValidation
* @m_since_latest
*/
GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation)
}; };
/** /**
@ -208,7 +228,9 @@ class WindowlessWglContext::Configuration {
/*implicit*/ Configuration(); /*implicit*/ Configuration();
/** @brief Context flags */ /** @brief Context flags */
Flags flags() const { return _flags; } Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/** /**
* @brief Set context flags * @brief Set context flags
@ -220,7 +242,7 @@ class WindowlessWglContext::Configuration {
* @see @ref GL::Context::flags() * @see @ref GL::Context::flags()
*/ */
Configuration& setFlags(Flags flags) { Configuration& setFlags(Flags flags) {
_flags = flags; GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -233,7 +255,7 @@ class WindowlessWglContext::Configuration {
* @see @ref clearFlags() * @see @ref clearFlags()
*/ */
Configuration& addFlags(Flags flags) { Configuration& addFlags(Flags flags) {
_flags |= flags; GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -246,7 +268,7 @@ class WindowlessWglContext::Configuration {
* @see @ref addFlags() * @see @ref addFlags()
*/ */
Configuration& clearFlags(Flags flags) { Configuration& clearFlags(Flags flags) {
_flags &= ~flags; GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -274,8 +296,12 @@ class WindowlessWglContext::Configuration {
*/ */
HGLRC sharedContext() const { return _sharedContext; } HGLRC sharedContext() const { return _sharedContext; }
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration)
#endif
private: private:
Flags _flags;
HGLRC _sharedContext = nullptr; HGLRC _sharedContext = nullptr;
}; };

5
src/Magnum/Platform/WindowlessWindowsEglApplication.cpp

@ -129,7 +129,8 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co
#error unsupported OpenGL ES version #error unsupported OpenGL ES version
#endif #endif
#endif #endif
EGL_CONTEXT_FLAGS_KHR, EGLint(flags), /* Mask out the upper 32bits used for other flags */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu),
EGL_NONE EGL_NONE
}; };
@ -201,7 +202,7 @@ bool WindowlessWindowsEglApplication::tryCreateContext(const Configuration& conf
CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWindowsEglApplication::tryCreateContext(): context already created", false); CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWindowsEglApplication::tryCreateContext(): context already created", false);
WindowlessWindowsEglContext glContext{configuration, _context.get()}; WindowlessWindowsEglContext glContext{configuration, _context.get()};
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration))
return false; return false;
_glContext = std::move(glContext); _glContext = std::move(glContext);

50
src/Magnum/Platform/WindowlessWindowsEglApplication.h

@ -44,7 +44,7 @@
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/GL/OpenGL.h" #include "Magnum/GL/Context.h"
#include "Magnum/Platform/Platform.h" #include "Magnum/Platform/Platform.h"
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
@ -158,20 +158,40 @@ class WindowlessWindowsEglContext {
@ref WindowlessWindowsEglApplication::createContext(), @ref WindowlessWindowsEglApplication::createContext(),
@ref WindowlessWindowsEglApplication::tryCreateContext() @ref WindowlessWindowsEglApplication::tryCreateContext()
*/ */
class WindowlessWindowsEglContext::Configuration { class WindowlessWindowsEglContext::Configuration: public GL::Context::Configuration {
public: public:
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: int { enum class Flag: UnsignedLong {
/** /**
* Debug context. Enabled automatically if the * Debug context. Enabled automatically if supported by the driver
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" * and the @ref Flag::GpuValidation flag is set or if the
* `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option"
* is present. * is present.
*/ */
Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR,
/**
* @copydoc GL::Context::Configuration::Flag::QuietLog
* @m_since_latest
*/
QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog),
/**
* @copydoc GL::Context::Configuration::Flag::VerboseLog
* @m_since_latest
*/
VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog),
/**
* @copydoc GL::Context::Configuration::Flag::GpuValidation
* @m_since_latest
*/
GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation)
}; };
/** /**
@ -181,10 +201,10 @@ class WindowlessWindowsEglContext::Configuration {
*/ */
typedef Containers::EnumSet<Flag> Flags; typedef Containers::EnumSet<Flag> Flags;
constexpr /*implicit*/ Configuration() {}
/** @brief Context flags */ /** @brief Context flags */
Flags flags() const { return _flags; } Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/** /**
* @brief Set context flags * @brief Set context flags
@ -195,7 +215,7 @@ class WindowlessWindowsEglContext::Configuration {
* @see @ref GL::Context::flags() * @see @ref GL::Context::flags()
*/ */
Configuration& setFlags(Flags flags) { Configuration& setFlags(Flags flags) {
_flags = flags; GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -208,7 +228,7 @@ class WindowlessWindowsEglContext::Configuration {
* @see @ref clearFlags() * @see @ref clearFlags()
*/ */
Configuration& addFlags(Flags flags) { Configuration& addFlags(Flags flags) {
_flags |= flags; GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -221,7 +241,7 @@ class WindowlessWindowsEglContext::Configuration {
* @see @ref addFlags() * @see @ref addFlags()
*/ */
Configuration& clearFlags(Flags flags) { Configuration& clearFlags(Flags flags) {
_flags &= ~flags; GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this; return *this;
} }
@ -249,8 +269,12 @@ class WindowlessWindowsEglContext::Configuration {
*/ */
EGLContext sharedContext() const { return _sharedContext; } EGLContext sharedContext() const { return _sharedContext; }
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration)
#endif
private: private:
Flags _flags;
EGLContext _sharedContext = EGL_NO_CONTEXT; EGLContext _sharedContext = EGL_NO_CONTEXT;
}; };

2
src/Magnum/Platform/gl-info.cpp

@ -118,7 +118,7 @@ Arguments:
- `--all-extensions` --- display extensions also for fully supported versions - `--all-extensions` --- display extensions also for fully supported versions
- `--limits` --- display also limits and implementation-defined values - `--limits` --- display also limits and implementation-defined values
- `--magnum-...` --- engine-specific options (see - `--magnum-...` --- engine-specific options (see
@ref GL-Context-command-line for details) @ref GL-Context-usage-command-line for details)
@subsection magnum-gl-info-usage-emscripten Usage on Emscripten @subsection magnum-gl-info-usage-emscripten Usage on Emscripten

2
src/Magnum/Text/fontconverter.cpp

@ -103,7 +103,7 @@ Arguments:
field computation will not be used. (default: `"256 256"`) field computation will not be used. (default: `"256 256"`)
- `--radius N` --- distance field computation radius (default: `24`) - `--radius N` --- distance field computation radius (default: `24`)
- `--magnum-...` --- engine-specific options (see - `--magnum-...` --- engine-specific options (see
@ref GL-Context-command-line for details) @ref GL-Context-usage-command-line for details)
The resulting font files can be then used as specified in the documentation of The resulting font files can be then used as specified in the documentation of
`converter` plugin. `converter` plugin.

2
src/Magnum/TextureTools/distancefieldconverter.cpp

@ -108,7 +108,7 @@ Arguments:
- `--output-size "X Y"` --- size of output image - `--output-size "X Y"` --- size of output image
- `--radius N` --- distance field computation radius - `--radius N` --- distance field computation radius
- `--magnum-...` --- engine-specific options (see - `--magnum-...` --- engine-specific options (see
@ref GL-Context-command-line for details) @ref GL-Context-usage-command-line for details)
Images with @ref PixelFormat::R8Unorm, @ref PixelFormat::RGB8Unorm or Images with @ref PixelFormat::R8Unorm, @ref PixelFormat::RGB8Unorm or
@ref PixelFormat::RGBA8Unorm are accepted on input. @ref PixelFormat::RGBA8Unorm are accepted on input.

Loading…
Cancel
Save