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. 10
      src/Magnum/Platform/Test/GlfwApplicationTest.cpp
  26. 6
      src/Magnum/Platform/Test/GlxApplicationTest.cpp
  27. 10
      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. 2
      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
- 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
@webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making
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
@ref opengl-workarounds for more information). This pseudo-extension can be
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"
various issues related to @gl_extension{ARB,direct_state_access} by using a
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,
but for example NVidia drivers have @cpp gl_PointCoord @ce undefined when
`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
@gl_extension{KHR,debug} debug output. This flag also causes
@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
upload of basic types
- 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
- @ref GL::AbstractFramebuffer::read(), @ref GL::Texture::image(),
@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
it can be quite spammy when complex shaders or benchmarks are allowed. For
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.
- Added an ability to create @ref GL::DynamicAttribute directly from a
@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
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
adjust HiDPI scaling, enable GPU command validation or for example switch to a
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
and diagnostic purposes it's possible to disable particular workarounds by
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}

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,
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.
- If you are on Mac, the native OpenGL implementation doesn't support
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
@ref Utility-Arguments-delegating "Utility::Arguments" class for details.
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
provide a complete help and command-line argument diagnostic, you should
instantiate this class *after* @ref GL::Context.
by @ref GL-Context-usage-command-line "GL::Context") are ignored as well. In
order to provide a complete help and command-line argument diagnostic, you
should instantiate this class *after* @ref GL::Context.
*/
class MAGNUM_AUDIO_EXPORT Context {
public:

75
src/Magnum/GL/Context.cpp

@ -749,15 +749,40 @@ Context::~Context() {
if(currentContext == this) currentContext = nullptr;
}
void Context::create() {
void Context::create(const Configuration& configuration) {
/* 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,
"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
potential driver-specific workarounds. */
if(_functionLoader) _functionLoader(*this);
@ -1139,6 +1164,50 @@ void Context::resetState(const States states) {
#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 MAGNUM_TARGET_WEBGL
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
Provides access to OpenGL version and extension information and manages
Magnum's internal OpenGL state tracker. An instance available through
@ref Context::current() is automatically created during construction of
`Platform::*Application` classes 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
Magnum's internal OpenGL state tracker.
@section GL-Context-usage Creating a context
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.
@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.
The context is configurable through command-line options, that are passed
either from the `Platform::*Application` classes or from the
@ref Platform::GLContext class. Usage:
@subsection GL-Context-usage-command-line Command-line options
In addition to the @ref Configuration, the context is configurable through
command-line options, that are passed either from the `Platform::*Application`
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}
<application> [--magnum-help] [--magnum-disable-workarounds LIST]
@ -134,20 +148,23 @@ Arguments:
- `--magnum-help` --- display this help message and exit
- `--magnum-disable-workarounds LIST` --- driver workarounds to disable (see
@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
(environment: `MAGNUM_DISABLE_EXTENSIONS`)
(environment: `MAGNUM_DISABLE_EXTENSIONS`). Corresponds to
@ref Configuration::addDisabledExtensions().
- `--magnum-gpu-validation off|on` --- GPU validation using
@gl_extension{KHR,debug}, if present (environment:
`MAGNUM_GPU_VALIDATION`) (default: `off`). This sets up @ref DebugOutput
callbacks and also causes
@ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug"
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
(environment: `MAGNUM_LOG`) (default: `default`). If you need to suppress
the engine startup log from code, the recommended way is to redirect
@ref Utility-Debug-scoped-output "debug output to null" during context creation.
(environment: `MAGNUM_LOG`) (default: `default`). Corresponds to
@ref Configuration::Flag::QuietLog and
@relativeref{Configuration::Flag,VerboseLog}.
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
@ -158,15 +175,7 @@ Particular application implementations add more options for DPI scaling or
GPU selection, see @ref Platform::Sdl2Application, @ref Platform::GlfwApplication
and @ref Platform::WindowlessEglApplication for details.
@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.
@section GL-Context-multiple Using multiple OpenGL contexts
@subsection GL-Context-usage-multiple Using multiple OpenGL contexts
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
@ -187,9 +196,19 @@ Once all needed instances are created, switch between them right after making
the underlying GL context current:
@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 {
public:
class Configuration;
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Context flag
@ -204,7 +223,8 @@ class MAGNUM_GL_EXPORT Context {
* Debug context. Enabled automatically by @ref Platform windowed
* and windowless application implementations if the
* `--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_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} /
* @gl_extension{KHR,debug}
@ -485,7 +505,7 @@ class MAGNUM_GL_EXPORT Context {
* @m_since{2019,10}
*
* 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);
@ -693,8 +713,10 @@ class MAGNUM_GL_EXPORT Context {
* @brief Whether given extension is disabled
*
* Can be used for detecting driver bug workarounds. Disabled
* extensions return `false` in @ref isExtensionSupported() even if
* they are advertised as being supported by the driver.
* extensions return @cpp false @ce in @ref isExtensionSupported() even
* 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 {
return isExtensionDisabled<E>(version());
@ -705,6 +727,8 @@ class MAGNUM_GL_EXPORT Context {
*
* Similar to above, but can also check for extensions which are
* disabled only for particular versions.
* @see @ref Configuration::addDisabledExtensions(),
* @ref GL-Context-usage-command-line
*/
template<class E> bool isExtensionDisabled(Version version) const {
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
*
* Can be used e.g. for listing extensions available on current
* hardware, but for general usage prefer @ref isExtensionDisabled() const,
* as it does most operations in compile time.
* hardware, but for general usage prefer
* @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 {
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&));
bool tryCreate();
void create();
bool tryCreate(const Configuration& configuration);
void create(const Configuration& configuration);
private:
#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} */
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
@brief Assert that given OpenGL version is supported
@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
Apart from setting up the debug output callbacks manually, it's also
possible to enable it conveniently using the `--magnum-gpu-validation`
@ref GL-Context-command-line "command-line or environment option" --- ideal
for quick debugging of rendering issues. If you are using application
@ref GL-Context-usage-command-line "command-line or environment option" ---
ideal for quick debugging of rendering issues. If you are using application
classes from the @ref Platform namespace, this option also ensures that
@ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug"
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
}
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
used to reliably check for errors regardless of platform support. For easier
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.
@section GL-OpenGLTester-benchmarks GPU time benchmarks

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

@ -24,6 +24,9 @@
*/
#include <algorithm>
#include <sstream>
#include <Corrade/Containers/ScopeGuard.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/TestSuite/Compare/Numeric.h>
@ -43,6 +46,8 @@ struct ContextGLTest: OpenGLTester {
void stringFlags();
void constructConfiguration();
void makeCurrent();
#ifndef CORRADE_TARGET_EMSCRIPTEN
@ -58,10 +63,89 @@ struct ContextGLTest: OpenGLTester {
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() {
addTests({
&ContextGLTest::stringFlags,
addTests({&ContextGLTest::stringFlags});
addInstancedTests({&ContextGLTest::constructConfiguration},
Containers::arraySize(ConstructConfigurationData));
addTests({
&ContextGLTest::makeCurrent,
#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() {
CORRADE_VERIFY(Context::hasCurrent());

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

@ -25,7 +25,9 @@
#include <set>
#include <sstream>
#include <Corrade/Containers/StringView.h>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/Container.h>
#include <Corrade/Utility/DebugStl.h>
#include "Magnum/GL/Context.h"
@ -39,6 +41,11 @@ struct ContextTest: TestSuite::Tester {
void isExtension();
void configurationConstruct();
void configurationConstructUnknownWorkaround();
void configurationConstructCopy();
void configurationConstructMove();
void constructNoCreate();
void constructCopyMove();
@ -56,6 +63,11 @@ struct ContextTest: TestSuite::Tester {
ContextTest::ContextTest() {
addTests({&ContextTest::isExtension,
&ContextTest::configurationConstruct,
&ContextTest::configurationConstructUnknownWorkaround,
&ContextTest::configurationConstructCopy,
&ContextTest::configurationConstructMove,
&ContextTest::constructNoCreate,
&ContextTest::constructCopyMove,
@ -71,7 +83,7 @@ ContextTest::ContextTest() {
}
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<int>::value);
@ -86,8 +98,9 @@ void ContextTest::isExtension() {
CORRADE_VERIFY(!Implementation::IsExtension<ALExtension>::value);
}
/* Variadic check (used in variadic addEnabledExtensions()), check that it
properly fails for each occurence of a non-extension */
/* Variadic check (used in variadic Configuration::addDisabledExtensions()),
check that it properly fails for each occurence of a non-extension */
#ifndef MAGNUM_TARGET_WEBGL
CORRADE_VERIFY((Implementation::IsExtension<
Extensions::KHR::debug,
Extensions::EXT::texture_filter_anisotropic,
@ -104,11 +117,219 @@ void ContextTest::isExtension() {
Extensions::KHR::debug,
Extensions::EXT::texture_filter_anisotropic,
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 */
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() {
{
/* 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();
/* Return true if the initialization succeeds */
return _context->tryCreate();
return _context->tryCreate(glConfiguration);
}
AbstractXApplication::~AbstractXApplication() {

21
src/Magnum/Platform/AbstractXApplication.h

@ -60,7 +60,7 @@ typedef int Bool;
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/GL/GL.h"
#include "Magnum/GL/Context.h"
#include "Magnum/Math/Vector2.h"
#include "Magnum/Platform/Platform.h"
@ -336,7 +336,7 @@ Double-buffered OpenGL context.
@ref Configuration, @ref create(), @ref tryCreate()
@todo GLX_ARB_create_context_robustness/EGL_EXT_create_context_robustness
*/
class AbstractXApplication::GLConfiguration {
class AbstractXApplication::GLConfiguration: public GL::Context::Configuration {
public:
explicit GLConfiguration();
~GLConfiguration();
@ -350,6 +350,23 @@ class AbstractXApplication::GLConfiguration {
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:
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));
/* Return true if the initialization succeeds */
return _context->tryCreate();
return _context->tryCreate(glConfiguration);
}
Vector2i AndroidApplication::framebufferSize() const {

21
src/Magnum/Platform/AndroidApplication.h

@ -36,7 +36,7 @@
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/GL/GL.h"
#include "Magnum/GL/Context.h"
#include "Magnum/Math/Vector4.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(),
@ref tryCreate()
*/
class AndroidApplication::GLConfiguration {
class AndroidApplication::GLConfiguration: public GL::Context::Configuration {
public:
/*implicit*/ GLConfiguration();
@ -504,6 +504,23 @@ class AndroidApplication::GLConfiguration {
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:
Vector4i _colorBufferSize;
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));
/* Return true if the initialization succeeds */
return _context->tryCreate();
return _context->tryCreate(glConfiguration);
}
#endif
@ -770,7 +770,10 @@ void EmscriptenApplication::textInputEvent(TextInputEvent&) {}
#ifdef MAGNUM_TARGET_GL
EmscriptenApplication::GLConfiguration::GLConfiguration():
_colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0},
_sampleCount{0} {}
_sampleCount{0}
{
addFlags(Flag::EnableExtensionsByDefault);
}
#endif
int EmscriptenApplication::exec() {

44
src/Magnum/Platform/EmscriptenApplication.h

@ -40,7 +40,7 @@
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/GL/GL.h"
#include "Magnum/GL/Context.h"
#include "Magnum/Math/Vector4.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(),
@ref tryCreate()
*/
class EmscriptenApplication::GLConfiguration {
class EmscriptenApplication::GLConfiguration: public GL::Context::Configuration {
public:
/**
* @brief Context flag
*
* Includes also everything from @ref GL::Context::Configuration::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
* 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
* [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();
/** @brief Context flags */
Flags flags() const { return _flags; }
Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/**
* @brief Set context flags
@ -1012,7 +1033,7 @@ class EmscriptenApplication::GLConfiguration {
* @see @ref GL::Context::flags()
*/
GLConfiguration& setFlags(Flags flags) {
_flags = flags;
GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -1025,7 +1046,7 @@ class EmscriptenApplication::GLConfiguration {
* @see @ref clearFlags()
*/
GLConfiguration& addFlags(Flags flags) {
_flags |= flags;
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -1038,7 +1059,7 @@ class EmscriptenApplication::GLConfiguration {
* @see @ref addFlags()
*/
GLConfiguration& clearFlags(Flags flags) {
_flags &= ~flags;
GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -1112,12 +1133,15 @@ class EmscriptenApplication::GLConfiguration {
return *this;
}
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration)
#endif
private:
Vector4i _colorBufferSize;
Int _depthBufferSize, _stencilBufferSize;
Int _sampleCount;
Flags _flags{Flag::EnableExtensionsByDefault};
};
CORRADE_ENUMSET_OPERATORS(EmscriptenApplication::GLConfiguration::Flags)

42
src/Magnum/Platform/GLContext.h

@ -58,26 +58,29 @@ class GLContext: public GL::Context {
* @brief Constructor
*
* 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 */
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 */
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
*
* Equivalent to passing @cpp {0, nullptr} @ce to
* @ref GLContext(Int, const char**). Even if the command-line options
* are not propagated, it's still possible to affect the renderer
* behavior from the environment. See @ref GL-Context-command-line for
* more information.
* Equivalent to passing @cpp {0, nullptr, configuration} @ce to
* @ref GLContext(Int, const char**, const Configuration&). Even if the
* command-line options are not propagated, it's still possible to
* affect the setup behavior from the environment or by passing a
* @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
@ -85,7 +88,7 @@ class GLContext: public GL::Context {
* Parses command-line arguments and sets @ref version() to
* @ref GL::Version::None, everything else is left in an empty state.
* 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):
#ifndef CORRADE_TARGET_EMSCRIPTEN
@ -118,8 +121,9 @@ class GLContext: public GL::Context {
* Equivalent to passing @cpp {NoCreate, 0, nullptr} @ce to
* @ref GLContext(NoCreateT, Int, const char**). Even if the
* command-line options are not propagated, it's still possible to
* affect the renderer behavior from the environment. See
* @ref GL-Context-command-line for more information.
* affect the renderer behavior from the environment or by passing
* 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} {}
@ -133,13 +137,15 @@ class GLContext: public GL::Context {
* detected version is unsupported or any other error occurs, a message
* is printed to output and the application exits. See @ref tryCreate()
* for an alternative.
* @see @ref GLContext(Int, char**), @ref GL-Context-command-line,
* @fn_gl{Get} with @def_gl{MAJOR_VERSION},
* @see @ref GLContext(Int, char**, const Configuration&),
* @ref GL-Context-usage, @fn_gl{Get} with @def_gl{MAJOR_VERSION},
* @def_gl{MINOR_VERSION}, @def_gl{CONTEXT_FLAGS},
* @def_gl{NUM_EXTENSIONS}, @fn_gl{GetString} with
* @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
@ -147,7 +153,9 @@ class GLContext: public GL::Context {
* Unlike @ref create(), instead of exiting prints a message to 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);
/* Destroy everything when the Magnum context creation fails */
if(!_context->tryCreate()) {
if(!_context->tryCreate(glConfiguration)) {
glfwDestroyWindow(_window);
_window = nullptr;
}
@ -894,13 +894,12 @@ void GlfwApplication::stopTextInput() {
#ifdef MAGNUM_TARGET_GL
GlfwApplication::GLConfiguration::GLConfiguration():
_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
_flags{Flag::ForwardCompatible},
#else
_flags{},
addFlags(Flag::ForwardCompatible);
#endif
_srgbCapable{false} {}
}
GlfwApplication::GLConfiguration::~GLConfiguration() = default;
#endif

48
src/Magnum/Platform/GlfwApplication.h

@ -43,7 +43,7 @@
#include "Magnum/Platform/Platform.h"
#ifdef MAGNUM_TARGET_GL
#include "Magnum/GL/GL.h"
#include "Magnum/GL/Context.h"
#endif
#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()
*/
class GlfwApplication::GLConfiguration {
class GlfwApplication::GLConfiguration: public GL::Context::Configuration {
public:
/**
* @brief Context flag
*
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/
enum class Flag: UnsignedByte {
enum class Flag: UnsignedLong {
#ifndef MAGNUM_TARGET_GLES
/**
* Forward compatible context
@ -807,13 +808,32 @@ class GlfwApplication::GLConfiguration {
#endif
/**
* Debug context. Enabled automatically if the
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option"
* Debug context. Enabled automatically if supported by the driver
* 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.
*/
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();
/** @brief Context flags */
Flags flags() const { return _flags; }
Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/**
* @brief Set context flags
@ -839,7 +861,7 @@ class GlfwApplication::GLConfiguration {
* @see @ref GL::Context::flags()
*/
GLConfiguration& setFlags(Flags flags) {
_flags = flags;
GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -852,7 +874,7 @@ class GlfwApplication::GLConfiguration {
* @see @ref clearFlags()
*/
GLConfiguration& addFlags(Flags flags) {
_flags |= flags;
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -865,7 +887,7 @@ class GlfwApplication::GLConfiguration {
* @see @ref addFlags()
*/
GLConfiguration& clearFlags(Flags flags) {
_flags &= ~flags;
GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -958,12 +980,16 @@ class GlfwApplication::GLConfiguration {
return *this;
}
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration)
#endif
private:
Vector4i _colorBufferSize;
Int _depthBufferSize, _stencilBufferSize;
Int _sampleCount;
GL::Version _version;
Flags _flags;
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);
#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 */
} else {
@ -501,7 +502,8 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
#endif
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glFlags));
/* Mask out the upper 32bits used for other flags */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(UnsignedLong(glFlags) & 0xffffffffu));
#else
/* For ES the major context version is compile-time constant */
#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);
/* Discard the ForwardCompatible flag for the fallback. Having it set
makes the fallback context creation fail on Mesa's Zink (which is
just 2.1) and I assume on others as well. */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glFlags) & int(~GLConfiguration::Flag::ForwardCompatible));
just 2.1) and I assume on others as well.
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(),
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
@ -666,7 +670,7 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf
#endif
/* Destroy everything also when the Magnum context creation fails */
if(!_context->tryCreate()) {
if(!_context->tryCreate(glConfiguration)) {
#ifndef CORRADE_TARGET_EMSCRIPTEN
SDL_GL_DeleteContext(_glContext);
SDL_DestroyWindow(_window);
@ -1184,15 +1188,13 @@ Sdl2Application::GLConfiguration::GLConfiguration():
_colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0},
_sampleCount(0)
#ifndef CORRADE_TARGET_EMSCRIPTEN
, _version(GL::Version::None),
#ifndef MAGNUM_TARGET_GLES
_flags{Flag::ForwardCompatible},
#else
_flags{},
, _version{GL::Version::None}, _srgbCapable{false}
#endif
_srgbCapable{false}
{
#ifndef MAGNUM_TARGET_GLES
addFlags(Flag::ForwardCompatible);
#endif
{}
}
Sdl2Application::GLConfiguration::~GLConfiguration() = default;
#endif

79
src/Magnum/Platform/Sdl2Application.h

@ -42,7 +42,7 @@
#include "Magnum/Platform/Platform.h"
#ifdef MAGNUM_TARGET_GL
#include "Magnum/GL/GL.h"
#include "Magnum/GL/Context.h"
#endif
#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()
*/
class Sdl2Application::GLConfiguration {
class Sdl2Application::GLConfiguration: public GL::Context::Configuration {
public:
#ifndef CORRADE_TARGET_EMSCRIPTEN
/**
* @brief Context flag
*
* Includes also everything from @ref GL::Context::Configuration::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
/**
* Forward compatible context
*
* Forward compatible context.
* @requires_gl Core/compatibility profile distinction and forward
* compatibility applies only to desktop GL.
*/
@ -1250,38 +1249,60 @@ class Sdl2Application::GLConfiguration {
#endif
/**
* Debug context. Enabled automatically if the
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option"
* Debug context. Enabled automatically if supported by the driver
* 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.
* @requires_gles Context flags are not available in WebGL.
*/
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,
/** 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
*
* @see @ref setFlags(), @ref GL::Context::Flags
* @requires_gles Context flags are not available in WebGL.
*/
typedef Containers::EnumSet<Flag> Flags;
#endif
explicit GLConfiguration();
~GLConfiguration();
#ifndef CORRADE_TARGET_EMSCRIPTEN
/**
* @brief Context flags
*
* @requires_gles Context flags are not available in WebGL.
*/
Flags flags() const { return _flags; }
/** @brief Context flags */
Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/**
* @brief Set context flags
@ -1291,10 +1312,9 @@ class Sdl2Application::GLConfiguration {
* on OpenGL ES. To avoid clearing default flags by accident, prefer to
* use @ref addFlags() and @ref clearFlags() instead.
* @see @ref GL::Context::flags()
* @requires_gles Context flags are not available in WebGL.
*/
GLConfiguration& setFlags(Flags flags) {
_flags = flags;
GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -1305,10 +1325,9 @@ class Sdl2Application::GLConfiguration {
* Unlike @ref setFlags(), ORs the flags with existing instead of
* replacing them. Useful for preserving the defaults.
* @see @ref clearFlags()
* @requires_gles Context flags are not available in WebGL.
*/
GLConfiguration& addFlags(Flags flags) {
_flags |= flags;
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -1319,13 +1338,13 @@ class Sdl2Application::GLConfiguration {
* Unlike @ref setFlags(), ANDs the inverse of @p flags with existing
* instead of replacing them. Useful for removing default flags.
* @see @ref addFlags()
* @requires_gles Context flags are not available in WebGL.
*/
GLConfiguration& clearFlags(Flags flags) {
_flags &= ~flags;
GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
#ifndef CORRADE_TARGET_EMSCRIPTEN
/**
* @brief Context version
*
@ -1434,13 +1453,17 @@ class Sdl2Application::GLConfiguration {
}
#endif
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration)
#endif
private:
Vector4i _colorBufferSize;
Int _depthBufferSize, _stencilBufferSize;
Int _sampleCount;
#ifndef CORRADE_TARGET_EMSCRIPTEN
GL::Version _version;
Flags _flags;
bool _srgbCapable;
#endif
};

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

@ -153,6 +153,7 @@ EmscriptenApplicationTest::EmscriptenApplicationTest(const Arguments& arguments)
Utility::Arguments args;
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("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv);
/* Useful for bisecting Emscripten regressions, because they happen WAY TOO
@ -167,9 +168,12 @@ EmscriptenApplicationTest::EmscriptenApplicationTest(const Arguments& arguments)
return;
}
create(Configuration{}.setWindowFlags(Configuration::WindowFlag::Resizable)
//, GLConfiguration{}.setFlags({})
);
Configuration conf;
conf.setWindowFlags(Configuration::WindowFlag::Resizable);
if(args.isSet("quiet"))
create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog));
else
create(conf);
Debug{} << "window size" << windowSize()
#ifdef MAGNUM_TARGET_GL

10
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("borderless").setHelp("borderless", "no window decoration")
.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);
if(args.isSet("exit-immediately")) {
@ -123,7 +126,14 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform::
conf.addWindowFlags(Configuration::WindowFlag::Borderless);
if(args.isSet("always-on-top"))
conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop);
#ifdef MAGNUM_TARGET_GL
if(args.isSet("quiet")) {
create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog));
} else
#endif
{
create(conf);
}
/* For testing resize events */
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;
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("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv);
if(args.isSet("exit-immediately")) {
@ -49,7 +50,10 @@ GlxApplicationTest::GlxApplicationTest(const Arguments& arguments): Platform::Ap
return;
}
create(Configuration{});
if(args.isSet("quiet"))
create(Configuration{}, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog));
else
create();
}
}}}}

10
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")
#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);
if(args.isSet("exit-immediately")) {
@ -184,7 +187,14 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform::
conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop);
#endif
#endif
#ifdef MAGNUM_TARGET_GL
if(args.isSet("quiet")) {
create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog));
} else
#endif
{
create(conf);
}
/* For testing resize events */
Debug{} << "window size" << windowSize()

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

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessCglApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessCglApplicationTest: Platform::WindowlessApplication {
explicit WindowlessCglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {}
explicit WindowlessCglApplicationTest(const Arguments& arguments);
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)

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

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessEglApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessEglApplicationTest: Platform::WindowlessApplication {
explicit WindowlessEglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {}
explicit WindowlessEglApplicationTest(const Arguments& arguments);
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)

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

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessGlxApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessGlxApplicationTest: Platform::WindowlessApplication {
explicit WindowlessGlxApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {}
explicit WindowlessGlxApplicationTest(const Arguments& arguments);
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)

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

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessIosApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessIosApplicationTest: Platform::WindowlessApplication {
explicit WindowlessIosApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {}
explicit WindowlessIosApplicationTest(const Arguments& arguments);
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)

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

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessWglApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessWglApplicationTest: Platform::WindowlessApplication {
explicit WindowlessWglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {}
explicit WindowlessWglApplicationTest(const Arguments& arguments);
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)

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

@ -23,15 +23,29 @@
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/Utility/Arguments.h>
#include "Magnum/Platform/WindowlessWindowsEglApplication.h"
namespace Magnum { namespace Platform { namespace Test { namespace {
struct WindowlessWindowsEglApplicationTest: Platform::WindowlessApplication {
explicit WindowlessWindowsEglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {}
explicit WindowlessWindowsEglApplicationTest(const Arguments& arguments);
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)

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

@ -42,6 +42,7 @@ XEglApplicationTest::XEglApplicationTest(const Arguments& arguments): Platform::
Utility::Arguments args;
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("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead")
.parse(arguments.argc, arguments.argv);
if(args.isSet("exit-immediately")) {
@ -49,10 +50,12 @@ XEglApplicationTest::XEglApplicationTest(const Arguments& arguments): Platform::
return;
}
create(Configuration{});
if(args.isSet("quiet"))
create(Configuration{}, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog));
else
create();
}
}}}}
MAGNUM_APPLICATION_MAIN(Magnum::Platform::Test::XEglApplicationTest)

2
src/Magnum/Platform/WindowlessCglApplication.cpp

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

23
src/Magnum/Platform/WindowlessCglApplication.h

@ -39,7 +39,7 @@
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/GL/OpenGL.h"
#include "Magnum/GL/Context.h"
#include "Magnum/Platform/Platform.h"
#ifndef DOXYGEN_GENERATING_OUTPUT
@ -164,10 +164,8 @@ class WindowlessCglContext {
@ref WindowlessCglApplication::createContext(),
@ref WindowlessCglApplication::tryCreateContext()
*/
class WindowlessCglContext::Configuration {
class WindowlessCglContext::Configuration: public GL::Context::Configuration {
public:
constexpr /*implicit*/ Configuration() {}
/**
* @brief Create a shared context
* @return Reference to self (for method chaining)
@ -192,6 +190,23 @@ class WindowlessCglContext::Configuration {
*/
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:
CGLContextObj _sharedContext = nullptr;
};

30
src/Magnum/Platform/WindowlessEglApplication.cpp

@ -328,8 +328,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
#endif
#ifndef MAGNUM_TARGET_WEBGL
/* Needs to be last because we're zeroing this out for SwiftShader (see
below) */
EGL_CONTEXT_FLAGS_KHR, EGLint(flags),
below).
Also mask out the upper 32bits used for other flags. */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu),
#endif
EGL_NONE
};
@ -369,8 +371,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
const EGLint fallbackAttributes[] = {
/* Discard the ForwardCompatible flag for the fallback. Having it
set makes the fallback context creation fail on Mesa's Zink
(which is just 2.1) and I assume on others as well. */
EGL_CONTEXT_FLAGS_KHR, GLint(flags & ~Configuration::Flag::ForwardCompatible),
(which is just 2.1) and I assume on others as well.
Also mask out the upper 32bits used for other flags. */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu),
EGL_NONE
};
_context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes);
@ -409,8 +413,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
/* Discard the ForwardCompatible flag for the fallback.
Compared to the above case of a 2.1 fallback it's not really
needed here (AFAIK it works in both cases), but let's be
consistent. */
EGL_CONTEXT_FLAGS_KHR, GLint(flags & ~Configuration::Flag::ForwardCompatible),
consistent.
Also mask out the upper 32bits used for other flags. */
EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu),
EGL_NONE
};
_context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes);
@ -519,12 +525,14 @@ bool WindowlessEglContext::release() {
}
WindowlessEglContext::Configuration::Configuration()
#ifndef MAGNUM_TARGET_WEBGL
: _device{}
#endif
{
#ifndef MAGNUM_TARGET_GLES
: _flags{Flag::ForwardCompatible}, _device{}
#elif !defined(MAGNUM_TARGET_WEBGL)
: _flags{}, _device{}
addFlags(Flag::ForwardCompatible);
#endif
{}
}
#ifndef DOXYGEN_GENERATING_OUTPUT
WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments): WindowlessEglApplication{arguments, Configuration{}} {}
@ -574,7 +582,7 @@ bool WindowlessEglApplication::tryCreateContext(const Configuration& configurati
#endif
WindowlessEglContext glContext{mergedConfiguration, _context.get()};
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate())
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration))
return false;
_glContext = std::move(glContext);

70
src/Magnum/Platform/WindowlessEglApplication.h

@ -58,7 +58,7 @@ typedef int Bool;
#endif
#include "Magnum/Magnum.h"
#include "Magnum/GL/OpenGL.h"
#include "Magnum/GL/Context.h"
#include "Magnum/Tags.h"
#include "Magnum/Platform/Platform.h"
@ -179,16 +179,16 @@ class WindowlessEglContext {
@ref WindowlessEglApplication::createContext(),
@ref WindowlessEglApplication::tryCreateContext()
*/
class WindowlessEglContext::Configuration {
class WindowlessEglContext::Configuration: public GL::Context::Configuration {
public:
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Context flag
*
* Includes also everything from @ref GL::Context::Configuration::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
/**
* Forward compatible context
@ -200,31 +200,47 @@ class WindowlessEglContext::Configuration {
#endif
/**
* Debug context. Enabled automatically if the
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option"
* Debug context. Enabled automatically if supported by the driver
* 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.
* @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
*
* @see @ref setFlags(), @ref Context::Flags
* @requires_gles Context flags are not available in WebGL.
*/
typedef Containers::EnumSet<Flag> Flags;
#endif
/*implicit*/ Configuration();
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Context flags
*
* @requires_gles Context flags are not available in WebGL.
*/
Flags flags() const { return _flags; }
/** @brief Context flags */
Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/**
* @brief Set context flags
@ -234,10 +250,9 @@ class WindowlessEglContext::Configuration {
* on OpenGL ES. To avoid clearing default flags by accident, prefer to
* use @ref addFlags() and @ref clearFlags() instead.
* @see @ref GL::Context::flags()
* @requires_gles Context flags are not available in WebGL.
*/
Configuration& setFlags(Flags flags) {
_flags = flags;
GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -248,10 +263,9 @@ class WindowlessEglContext::Configuration {
* Unlike @ref setFlags(), ORs the flags with existing instead of
* replacing them. Useful for preserving the defaults.
* @see @ref clearFlags()
* @requires_gles Context flags are not available in WebGL.
*/
Configuration& addFlags(Flags flags) {
_flags |= flags;
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -262,13 +276,13 @@ class WindowlessEglContext::Configuration {
* Unlike @ref setFlags(), ANDs the inverse of @p flags with existing
* instead of replacing them. Useful for removing default flags.
* @see @ref addFlags()
* @requires_gles Context flags are not available in WebGL.
*/
Configuration& clearFlags(Flags flags) {
_flags &= ~flags;
GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Device ID to use
* @m_since{2019,10}
@ -364,9 +378,13 @@ class WindowlessEglContext::Configuration {
EGLContext sharedContext() const { return _sharedContext; }
#endif
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration)
#endif
private:
#ifndef MAGNUM_TARGET_WEBGL
Flags _flags;
UnsignedInt _device;
/* Assumes that you can't have 2^32 - 1 GPUs */
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
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
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.
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
to create the context with the following error (with additional output
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}

28
src/Magnum/Platform/WindowlessGlxApplication.cpp

@ -126,12 +126,14 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura
#endif
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
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
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
GLX_CONTEXT_FLAGS_ARB, GLint(flags),
/* Mask out the upper 32bits used for other flags */
GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu),
#endif
0
};
@ -155,8 +157,10 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura
const GLint fallbackContextAttributes[] = {
/* Discard the ForwardCompatible flag for the fallback. Having it
set makes the fallback context creation fail on Mesa's Zink
(which is just 2.1) and I assume on others as well. */
GLX_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible),
(which is just 2.1) and I assume on others as well.
Also mask out the upper 32bits used for other flags. */
GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu),
0
};
{
@ -198,8 +202,10 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura
/* Discard the ForwardCompatible flag for the fallback.
Compared to the above case of a 2.1 fallback it's not really
needed here (AFAIK it works in both cases), but let's be
consistent. */
GLX_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible),
consistent.
Also mask out the upper 32bits used for other flags. */
GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu),
0
};
{
@ -267,13 +273,11 @@ bool WindowlessGlxContext::release() {
return false;
}
WindowlessGlxContext::Configuration::Configuration():
WindowlessGlxContext::Configuration::Configuration() {
#ifndef MAGNUM_TARGET_GLES
_flags{Flag::ForwardCompatible}
#else
_flags{}
addFlags(Flag::ForwardCompatible);
#endif
{}
}
#ifndef DOXYGEN_GENERATING_OUTPUT
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);
WindowlessGlxContext glContext{configuration, _context.get()};
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate())
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration))
return false;
_glContext = std::move(glContext);

48
src/Magnum/Platform/WindowlessGlxApplication.h

@ -39,7 +39,7 @@
/* Include our GL headers first to avoid conflicts */
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/GL/OpenGL.h"
#include "Magnum/GL/Context.h"
#include "Magnum/Platform/Platform.h"
#include <GL/glx.h>
@ -185,14 +185,15 @@ class WindowlessGlxContext {
@ref WindowlessGlxApplication::createContext(),
@ref WindowlessGlxApplication::tryCreateContext()
*/
class WindowlessGlxContext::Configuration {
class WindowlessGlxContext::Configuration: public GL::Context::Configuration {
public:
/**
* @brief Context flag
*
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/
enum class Flag: int {
enum class Flag: UnsignedLong {
#ifndef MAGNUM_TARGET_GLES
/**
* Forward compatible context
@ -204,11 +205,30 @@ class WindowlessGlxContext::Configuration {
#endif
/**
* Debug context. Enabled automatically if the
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option"
* Debug context. Enabled automatically if supported by the driver
* 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.
*/
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();
/** @brief Context flags */
Flags flags() const { return _flags; }
Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/**
* @brief Set context flags
@ -233,7 +255,7 @@ class WindowlessGlxContext::Configuration {
* @see @ref GL::Context::flags()
*/
Configuration& setFlags(Flags flags) {
_flags = flags;
GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -246,7 +268,7 @@ class WindowlessGlxContext::Configuration {
* @see @ref clearFlags()
*/
Configuration& addFlags(Flags flags) {
_flags |= flags;
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -259,7 +281,7 @@ class WindowlessGlxContext::Configuration {
* @see @ref addFlags()
*/
Configuration& clearFlags(Flags flags) {
_flags &= ~flags;
GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -287,8 +309,12 @@ class WindowlessGlxContext::Configuration {
*/
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:
Flags _flags;
GLXContext _sharedContext = nullptr;
};

22
src/Magnum/Platform/WindowlessIosApplication.h

@ -37,7 +37,7 @@
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/GL/OpenGL.h"
#include "Magnum/GL/Context.h"
#include "Magnum/Platform/Platform.h"
#ifdef __OBJC__
@ -154,9 +154,25 @@ class WindowlessIosContext {
@ref WindowlessIosApplication::createContext(),
@ref WindowlessIosApplication::tryCreateContext()
*/
class WindowlessIosContext::Configuration {
class WindowlessIosContext::Configuration: public GL::Context::Configuration {
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
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
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
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 1,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
WGL_CONTEXT_FLAGS_ARB, GLint(flags),
/* Mask out the upper 32bits used for other flags */
WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu),
#endif
0
};
@ -157,7 +159,8 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G
const int fallbackContextAttributes[] = {
/** @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
};
_context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes);
@ -196,7 +199,8 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G
wglDeleteContext(_context);
const int fallbackContextAttributes[] = {
/** @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
};
_context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes);
@ -254,13 +258,11 @@ bool WindowlessWglContext::release() {
return false;
}
WindowlessWglContext::Configuration::Configuration():
WindowlessWglContext::Configuration::Configuration() {
#ifndef MAGNUM_TARGET_GLES
_flags{Flag::ForwardCompatible}
#else
_flags{}
addFlags(Flag::ForwardCompatible);
#endif
{}
}
#ifndef DOXYGEN_GENERATING_OUTPUT
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);
WindowlessWglContext glContext{configuration, _context.get()};
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate())
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration))
return false;
_glContext = std::move(glContext);

48
src/Magnum/Platform/WindowlessWglApplication.h

@ -42,7 +42,7 @@
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/GL/OpenGL.h"
#include "Magnum/GL/Context.h"
#include "Magnum/Platform/Platform.h"
#ifndef DOXYGEN_GENERATING_OUTPUT
@ -172,14 +172,15 @@ class WindowlessWglContext {
@ref WindowlessWglApplication::createContext(),
@ref WindowlessWglApplication::tryCreateContext()
*/
class WindowlessWglContext::Configuration {
class WindowlessWglContext::Configuration: public GL::Context::Configuration {
public:
/**
* @brief Context flag
*
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/
enum class Flag: int {
enum class Flag: UnsignedLong {
#ifndef MAGNUM_TARGET_GLES
/**
* Forward compatible context
@ -191,11 +192,30 @@ class WindowlessWglContext::Configuration {
#endif
/**
* Debug context. Enabled automatically if the
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option"
* Debug context. Enabled automatically if supported by the driver
* 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.
*/
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();
/** @brief Context flags */
Flags flags() const { return _flags; }
Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/**
* @brief Set context flags
@ -220,7 +242,7 @@ class WindowlessWglContext::Configuration {
* @see @ref GL::Context::flags()
*/
Configuration& setFlags(Flags flags) {
_flags = flags;
GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -233,7 +255,7 @@ class WindowlessWglContext::Configuration {
* @see @ref clearFlags()
*/
Configuration& addFlags(Flags flags) {
_flags |= flags;
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -246,7 +268,7 @@ class WindowlessWglContext::Configuration {
* @see @ref addFlags()
*/
Configuration& clearFlags(Flags flags) {
_flags &= ~flags;
GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -274,8 +296,12 @@ class WindowlessWglContext::Configuration {
*/
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:
Flags _flags;
HGLRC _sharedContext = nullptr;
};

5
src/Magnum/Platform/WindowlessWindowsEglApplication.cpp

@ -129,7 +129,8 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co
#error unsupported OpenGL ES version
#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
};
@ -201,7 +202,7 @@ bool WindowlessWindowsEglApplication::tryCreateContext(const Configuration& conf
CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWindowsEglApplication::tryCreateContext(): context already created", false);
WindowlessWindowsEglContext glContext{configuration, _context.get()};
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate())
if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration))
return false;
_glContext = std::move(glContext);

50
src/Magnum/Platform/WindowlessWindowsEglApplication.h

@ -44,7 +44,7 @@
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/GL/OpenGL.h"
#include "Magnum/GL/Context.h"
#include "Magnum/Platform/Platform.h"
namespace Magnum { namespace Platform {
@ -158,20 +158,40 @@ class WindowlessWindowsEglContext {
@ref WindowlessWindowsEglApplication::createContext(),
@ref WindowlessWindowsEglApplication::tryCreateContext()
*/
class WindowlessWindowsEglContext::Configuration {
class WindowlessWindowsEglContext::Configuration: public GL::Context::Configuration {
public:
/**
* @brief Context flag
*
* Includes also everything from @ref GL::Context::Configuration::Flag.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/
enum class Flag: int {
enum class Flag: UnsignedLong {
/**
* Debug context. Enabled automatically if the
* `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option"
* Debug context. Enabled automatically if supported by the driver
* 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.
*/
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;
constexpr /*implicit*/ Configuration() {}
/** @brief Context flags */
Flags flags() const { return _flags; }
Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags()));
}
/**
* @brief Set context flags
@ -195,7 +215,7 @@ class WindowlessWindowsEglContext::Configuration {
* @see @ref GL::Context::flags()
*/
Configuration& setFlags(Flags flags) {
_flags = flags;
GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -208,7 +228,7 @@ class WindowlessWindowsEglContext::Configuration {
* @see @ref clearFlags()
*/
Configuration& addFlags(Flags flags) {
_flags |= flags;
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -221,7 +241,7 @@ class WindowlessWindowsEglContext::Configuration {
* @see @ref addFlags()
*/
Configuration& clearFlags(Flags flags) {
_flags &= ~flags;
GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags)));
return *this;
}
@ -249,8 +269,12 @@ class WindowlessWindowsEglContext::Configuration {
*/
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:
Flags _flags;
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
- `--limits` --- display also limits and implementation-defined values
- `--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

2
src/Magnum/Text/fontconverter.cpp

@ -103,7 +103,7 @@ Arguments:
field computation will not be used. (default: `"256 256"`)
- `--radius N` --- distance field computation radius (default: `24`)
- `--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
`converter` plugin.

2
src/Magnum/TextureTools/distancefieldconverter.cpp

@ -108,7 +108,7 @@ Arguments:
- `--output-size "X Y"` --- size of output image
- `--radius N` --- distance field computation radius
- `--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
@ref PixelFormat::RGBA8Unorm are accepted on input.

Loading…
Cancel
Save