mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1232 lines
52 KiB
1232 lines
52 KiB
#ifndef Magnum_GL_Context_h |
|
#define Magnum_GL_Context_h |
|
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
copy of this software and associated documentation files (the "Software"), |
|
to deal in the Software without restriction, including without limitation |
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
and/or sell copies of the Software, and to permit persons to whom the |
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included |
|
in all copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
/** @file |
|
* @brief Class @ref Magnum::GL::Context, @ref Magnum::GL::Extension, macro @ref MAGNUM_ASSERT_GL_VERSION_SUPPORTED(), @ref MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED() |
|
*/ |
|
|
|
#include <cstdlib> |
|
#include <Corrade/Containers/Array.h> |
|
#include <Corrade/Containers/ArrayTuple.h> |
|
#include <Corrade/Containers/EnumSet.h> |
|
#include <Corrade/Containers/Optional.h> |
|
#include <Corrade/Containers/StaticArray.h> |
|
|
|
#include "Magnum/Magnum.h" |
|
#include "Magnum/Math/BitVector.h" |
|
#include "Magnum/Tags.h" |
|
#include "Magnum/GL/GL.h" |
|
#include "Magnum/GL/OpenGL.h" |
|
|
|
#include "Magnum/GL/visibility.h" |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/* For return types of Context::versionString() etc., which used to be a |
|
std::string. Not ideal for the return types, but at least something. */ |
|
#include <Corrade/Containers/StringStl.h> |
|
#endif |
|
|
|
namespace Magnum { |
|
|
|
namespace GL { |
|
|
|
namespace Implementation { |
|
struct ContextState; |
|
struct State; |
|
|
|
template<class...> class IsExtension; |
|
template<> class IsExtension<> { public: enum: bool { value = true }; }; |
|
CORRADE_HAS_TYPE(IsExtension<U>, decltype(T::Index)); |
|
template<class T, class U, class ...Args> class IsExtension<T, U, Args...> { |
|
/** @todo C++17: use &&... instead of all this */ |
|
public: enum: bool { value = IsExtension<T>::value && IsExtension<U, Args...>::value }; |
|
}; |
|
|
|
/* Context::Configuration::Flag, but because we need to use it inside |
|
Context before the Configuration class is defined, it has to be here */ |
|
enum class ContextConfigurationFlag: UnsignedLong { |
|
/* Keeping the 32-bit range reserved for actual GL context flags */ |
|
Windowless = 1ull << 59, |
|
QuietLog = 1ull << 60, |
|
VerboseLog = 1ull << 61, |
|
GpuValidation = 1ull << 62, |
|
GpuValidationNoError = 1ull << 63 |
|
}; |
|
typedef Containers::EnumSet<ContextConfigurationFlag> ContextConfigurationFlags; |
|
CORRADE_ENUMSET_OPERATORS(ContextConfigurationFlags) |
|
} |
|
|
|
/** |
|
@brief Run-time information about OpenGL extension |
|
|
|
Encapsulates runtime information about OpenGL extension, such as name string, |
|
minimal required OpenGL version and version in which the extension was adopted |
|
to core. |
|
|
|
See also @ref Extensions namespace, which contain compile-time information |
|
about OpenGL extensions. |
|
*/ |
|
class MAGNUM_GL_EXPORT Extension { |
|
public: |
|
/** @brief All extensions for given OpenGL version */ |
|
static Containers::ArrayView<const Extension> extensions(Version version); |
|
|
|
/** @brief Internal unique extension index */ |
|
constexpr std::size_t index() const { return _index; } |
|
|
|
/** @brief Minimal version required by this extension */ |
|
constexpr Version requiredVersion() const { return _requiredVersion; } |
|
|
|
/** @brief Version in which this extension was adopted to core */ |
|
constexpr Version coreVersion() const { return _coreVersion; } |
|
|
|
/** @brief Extension string */ |
|
constexpr const char* string() const { return _string; } |
|
|
|
/** @brief Construct from a compile-time extension */ |
|
template<class E, class = typename std::enable_if<Implementation::IsExtension<E>::value>::type> constexpr /*implicit*/ Extension(const E&): _index{E::Index}, _requiredVersion{E::requiredVersion()}, _coreVersion{E::coreVersion()}, _string{E::string()} {} |
|
|
|
private: |
|
std::size_t _index; |
|
Version _requiredVersion; |
|
Version _coreVersion; |
|
const char* _string; |
|
}; |
|
|
|
/** |
|
@brief Magnum OpenGL context |
|
|
|
Provides access to OpenGL version and extension information and manages |
|
Magnum's internal OpenGL state tracker. |
|
|
|
@m_class{m-note m-success} |
|
|
|
@par |
|
There's also the @ref magnum-gl-info "magnum-gl-info" tool that provides |
|
access to OpenGL version, extension and platform-specific limit information |
|
through a command line interface. |
|
|
|
@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. |
|
|
|
Various options can be passed using the @ref Configuration class, which is then |
|
extended by various |
|
@ref Platform::Sdl2Application::GLConfiguration "Platform::*Application::GLConfiguration" |
|
and @ref Platform::WindowlessEglContext::Configuration "Platform::Windowless*Application::Configuration" |
|
subclasses. |
|
|
|
@subsection GL-Context-usage-command-line Command-line options |
|
|
|
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] |
|
[--magnum-disable-extensions LIST] |
|
[--magnum-gpu-validation off|on] |
|
[--magnum-log default|quiet|verbose] ... |
|
@endcode |
|
|
|
Arguments: |
|
|
|
- `...` --- main application arguments (see `-h` or `--help` for details) |
|
- `--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`). Corresponds to |
|
@ref Configuration::addDisabledWorkarounds(). |
|
- `--magnum-disable-extensions LIST` --- API extensions to disable |
|
(environment: `MAGNUM_DISABLE_EXTENSIONS`). Corresponds to |
|
@ref Configuration::addDisabledExtensions(). |
|
- `--magnum-gpu-validation off|on|no-error` --- 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. Corresponds to |
|
@ref Configuration::Flag::GpuValidation / |
|
@ref Configuration::Flag::GpuValidationNoError. |
|
- `--magnum-log default|quiet|verbose` --- console logging |
|
(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 |
|
are completely ignored, see documentation of the |
|
@ref Utility-Arguments-delegating "Utility::Arguments" class for details. |
|
|
|
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. |
|
|
|
@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 |
|
it. When you are using multiple OpenGL contexts, each of them needs to have a |
|
corresponding @ref Context instance active at the same time, and you need to |
|
ensure you only access OpenGL objects that were created by the same context as |
|
is currently active. |
|
|
|
To prevent accidents in common cases, the @ref Context class expects that no |
|
other instance is active during its creation. In order to create additional |
|
instances for other OpenGL contexts, *first* you need to "unset" the current one |
|
with @ref makeCurrent() and *then* create another instance, which will then |
|
become implicitly active: |
|
|
|
@snippet MagnumGL-application.cpp Context-makeCurrent-nullptr |
|
|
|
Once all needed instances are created, switch between them right after making |
|
the underlying GL context current: |
|
|
|
@snippet MagnumGL-application.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 |
|
* |
|
* @see @ref Flags, @ref flags(), |
|
* @ref Platform::Sdl2Application::GLConfiguration::setFlags() "Platform::*Application::GLConfiguration::setFlags()" |
|
* @m_enum_values_as_keywords |
|
* @requires_gles Context flags are not available in WebGL. |
|
*/ |
|
enum class Flag: GLint { |
|
/** |
|
* Debug context. Enabled automatically by @ref Platform windowed |
|
* and windowless application implementations if the |
|
* @ref Configuration::Flag::GpuValidation flag is set or if the |
|
* `--magnum-gpu-validation` |
|
* @ref GL-Context-usage-command-line "command-line option" is |
|
* set to `on`. |
|
* @requires_gl43 Extension @gl_extension{KHR,debug} |
|
* @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / |
|
* @gl_extension{KHR,debug} |
|
*/ |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
Debug = GL_CONTEXT_FLAG_DEBUG_BIT, |
|
#else |
|
Debug = GL_CONTEXT_FLAG_DEBUG_BIT_KHR, |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
/** |
|
* Forward compatible context |
|
* @see @ref isCoreProfile() |
|
* @requires_gl Core/compatibility profile distinction and forward |
|
* compatibility applies only to desktop GL. |
|
*/ |
|
ForwardCompatible = GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT, |
|
#endif |
|
|
|
/** |
|
* Context without error reporting. Enabled automatically by |
|
* @ref Platform windowed and windowless application |
|
* implementations if the @ref Configuration::Flag::GpuValidationNoError |
|
* flag is set or if the `--magnum-gpu-validation` |
|
* @ref GL-Context-usage-command-line "command-line option" is |
|
* set to `no-error`. |
|
* @requires_gl46 Extension @gl_extension{KHR,no_error} |
|
* @requires_es_extension Extension @gl_extension{KHR,no_error} |
|
*/ |
|
#ifndef MAGNUM_TARGET_GLES |
|
NoError = GL_CONTEXT_FLAG_NO_ERROR_BIT, |
|
#else |
|
NoError = GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR, |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
/** |
|
* Context with robust access |
|
* @requires_gl45 Extension @gl_extension{KHR,robustness} or |
|
* @gl_extension{ARB,robustness} |
|
* @requires_gles32 Extension @gl_extension{KHR,robustness} or |
|
* @gl_extension{EXT,robustness} |
|
* @todo In ES2 available under glGetIntegerv(CONTEXT_ROBUST_ACCESS_EXT), |
|
* how to make it compatible? |
|
*/ |
|
RobustAccess = GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT |
|
#endif |
|
}; |
|
|
|
/** |
|
* @brief Context flags |
|
* |
|
* @see @ref flags() |
|
* @requires_gles Context flags are not available in WebGL. |
|
*/ |
|
typedef Containers::EnumSet<Flag> Flags; |
|
#endif |
|
|
|
/** |
|
* @brief State to reset |
|
* |
|
* @see @ref States, @ref resetState(), @ref opengl-state-tracking |
|
*/ |
|
enum class State: UnsignedInt { |
|
/** Reset tracked buffer-related bindings and state */ |
|
Buffers = 1 << 0, |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
/** |
|
* Unbind currently bound PBO. |
|
* |
|
* Not all third-party code is aware of PBOs, and if a PBO is bound |
|
* when Magnum transfers control to an unaware code, it can cause |
|
* various issues with textures. This is a similar, but rarer, |
|
* case to @ref State::MeshVao / @ref State::BindScratchVao. |
|
*/ |
|
UnbindPixelBuffer = 1 << 1, |
|
#endif |
|
|
|
/** Reset tracked framebuffer-related bindings and state */ |
|
Framebuffers = 1 << 2, |
|
|
|
/** Reset tracked mesh-related bindings */ |
|
Meshes = 1 << 3, |
|
|
|
/** |
|
* Unbind currently bound VAO. |
|
* |
|
* Magnum by default uses VAOs --- each time a @ref Mesh is drawn |
|
* or configured, its VAO is bound, but it is *not* unbound |
|
* afterwards to avoid needless state changes. This may introduce |
|
* problems when using third-party OpenGL code --- it may break |
|
* internal state of a mesh that was used the most recently. |
|
* Similar issue can happen the other way. Calling @ref resetState() |
|
* with @ref State::MeshVao included unbounds any currently bound |
|
* VAO to fix such case. |
|
*/ |
|
MeshVao = 1 << 4, |
|
|
|
/** |
|
* Bind a "scratch" VAO on core profile. |
|
* |
|
* Use if external code is not VAO-aware and would otherwise try to |
|
* enable vertex attributes on the default (zero) VAO, causing GL |
|
* errors. Meant to be used together with @ref State::MeshVao (or |
|
* @ref State::EnterExternal). |
|
* |
|
* Does nothing on compatibility profile and ES / WebGL platforms, |
|
* as using the default VAO is allowed there. |
|
*/ |
|
BindScratchVao = 1 << 5, |
|
|
|
/** Reset tracked pixel storage-related state */ |
|
PixelStorage = 1 << 6, |
|
|
|
/** Reset tracked renderer-related state */ |
|
Renderer = 1 << 7, |
|
|
|
/** Reset tracked shader-related bindings */ |
|
Shaders = 1 << 8, |
|
|
|
/** Reset tracked texture-related bindings and state */ |
|
Textures = 1 << 9, |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
/** Reset tracked transform feedback-related bindings */ |
|
TransformFeedback = 1 << 10, |
|
#endif |
|
|
|
/** |
|
* Reset state on entering section with external OpenGL code. |
|
* |
|
* Resets all state that could cause external code to accidentally |
|
* modify Magnum objects. This includes @ref State::MeshVao and |
|
* @ref State::UnbindPixelBuffer. In some pathological cases you |
|
* may want to enable @ref State::BindScratchVao as well. |
|
*/ |
|
EnterExternal = MeshVao |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
|UnbindPixelBuffer |
|
#endif |
|
, |
|
|
|
/** |
|
* Reset state on exiting section with external OpenGL code. |
|
* |
|
* Resets Magnum state tracker to avoid being confused by external |
|
* state changes. This resets all states, however |
|
* @ref State::UnbindPixelBuffer is excluded as Magnum's state |
|
* tracker will ensure no PBO is bound when calling related OpenGL |
|
* APIs. |
|
*/ |
|
ExitExternal = Buffers|Framebuffers|Meshes|MeshVao|PixelStorage|Renderer|Shaders|Textures |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
|TransformFeedback |
|
#endif |
|
}; |
|
|
|
/** |
|
* @brief States to reset |
|
* |
|
* @see @ref resetState() |
|
*/ |
|
typedef Containers::EnumSet<State> States; |
|
|
|
/** |
|
* @brief Detected driver |
|
* |
|
* On WebGL, if @webgl_extension{WEBGL,debug_renderer_info} is not |
|
* available and the browser doesn't report the real values through |
|
* @ref vendorString() and @ref rendererString(), driver detection can |
|
* be performed only for limited cases --- see documentation of |
|
* particular values for more information. |
|
* @see @ref DetectedDrivers, @ref detectedDriver() |
|
*/ |
|
enum class DetectedDriver: UnsignedShort { |
|
/** |
|
* Proprietary AMD desktop drivers on Windows and Linux. In |
|
* contrast, AMDGPU Mesa drivers report as |
|
* @ref DetectedDriver::Mesa instead. |
|
*/ |
|
Amd = 1 << 0, |
|
|
|
#if defined(MAGNUM_TARGET_GLES) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
/** |
|
* OpenGL ES implementation by ANGLE (translated to D3D), used by |
|
* browsers on Windows for WebGL. See also |
|
* @ref DetectedDriver::SwiftShader. On WebGL, if |
|
* @webgl_extension{WEBGL,debug_renderer_info} is not available, |
|
* the detection is attempted by checking for a presence of |
|
* @webgl_extension{ANGLE,instanced_arrays} on WebGL 1 (which may |
|
* also be implemented by other drivers than ANGLE) or |
|
* @webgl_extension{WEBGL,multi_draw} on WebGL 2 (which may not be |
|
* available yet on older ANGLE versions), and as a fallback by |
|
* checking if the line size range is just 1, which is always the |
|
* case on D3D but not always on GL. |
|
* @requires_gles ANGLE doesn't support desktop OpenGL contexts. |
|
*/ |
|
Angle = 1 << 1, |
|
#endif |
|
|
|
/** Intel desktop drivers on Windows */ |
|
IntelWindows = 1 << 2, |
|
|
|
/** |
|
* Mesa drivers on Windows and Linux. In particular, Intel, AMD |
|
* and NVidia Mesa drivers match as this. See also |
|
* @ref DetectedDriver::Svga3D. |
|
*/ |
|
Mesa = 1 << 3, |
|
|
|
/** Proprietary NVidia drivers on Windows and Linux */ |
|
NVidia = 1 << 4, |
|
|
|
/** |
|
* VMware guest GL driver SVGA3D, implemented using Mesa, both |
|
* Windows and Linux guests. See https://www.mesa3d.org/vmware-guest.html |
|
* for more information. Detected in combination with |
|
* @ref DetectedDriver::Mesa. |
|
*/ |
|
Svga3D = 1 << 5, |
|
|
|
#if defined(MAGNUM_TARGET_GLES) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
/** |
|
* [SwiftShader](https://github.com/google/swiftshader) software |
|
* renderer for OpenGL ES. Usually used by browsers in cases where |
|
* a GPU isn't available. See also @ref DetectedDriver::Angle. |
|
* @requires_gles SwiftShader doesn't support desktop OpenGL |
|
* contexts. |
|
* @m_since{2019,10} |
|
*/ |
|
SwiftShader = 1 << 6, |
|
#endif |
|
|
|
#if defined(CORRADE_TARGET_ANDROID) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
/** |
|
* ARM Mali drivers on OpenGL ES. |
|
* @partialsupport Available only on |
|
* @ref CORRADE_TARGET_ANDROID "Android". |
|
* @m_since{2019,10} |
|
*/ |
|
ArmMali = 1 << 7 |
|
#endif |
|
}; |
|
|
|
/** |
|
* @brief Detected drivers |
|
* |
|
* @see @ref detectedDriver() |
|
*/ |
|
typedef Containers::EnumSet<DetectedDriver> DetectedDrivers; |
|
|
|
/** |
|
* @brief Whether there is any current context |
|
* |
|
* If Corrade is built with @ref CORRADE_BUILD_MULTITHREADED, current |
|
* context is thread-local instead of global (the default). |
|
* @see @ref current() |
|
*/ |
|
static bool hasCurrent(); |
|
|
|
/** |
|
* @brief Current context |
|
* |
|
* Expect that there is current context. If Corrade is built with |
|
* @ref CORRADE_BUILD_MULTITHREADED, current context is thread-local |
|
* instead of global (the default). |
|
* @see @ref hasCurrent() |
|
*/ |
|
static Context& current(); |
|
|
|
/** |
|
* @brief Make a context current |
|
* @m_since{2019,10} |
|
* |
|
* To be used when you need to manage multiple OpenGL contexts. See |
|
* @ref GL-Context-usage-multiple for more information. |
|
*/ |
|
static void makeCurrent(Context* context); |
|
|
|
/** @brief Copying is not allowed */ |
|
Context(const Context&) = delete; |
|
|
|
/** @brief Move constructor */ |
|
Context(Context&& other) noexcept; |
|
|
|
~Context(); |
|
|
|
/** @brief Copying is not allowed */ |
|
Context& operator=(const Context&) = delete; |
|
|
|
/** @brief Move assignment is not allowed */ |
|
Context& operator=(Context&&) = delete; |
|
|
|
/** |
|
* @brief OpenGL version |
|
* |
|
* @see @ref versionString(), @ref shadingLanguageVersionString() |
|
*/ |
|
Version version() const { return _version; } |
|
|
|
/** |
|
* @brief Vendor string |
|
* |
|
* The result is *not* cached, repeated queries will result in repeated |
|
* OpenGL calls. The returned view is always |
|
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and |
|
* @relativeref{Corrade::Containers::StringViewFlag,Global}. In WebGL |
|
* the vendor string is implicitly masked away, use |
|
* @ref vendorStringUnmasked() to access the real vendor string, if |
|
* available. |
|
* @see @ref rendererString(), @fn_gl{GetString} with |
|
* @def_gl_keyword{VENDOR} |
|
*/ |
|
Containers::StringView vendorString() const; |
|
|
|
#if defined(MAGNUM_TARGET_WEBGL) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
/** |
|
* @brief Unmasked vendor string |
|
* @m_since_latest |
|
* |
|
* A WebGL counterpart to @ref vendorString() that returns the real |
|
* vendor string. If @webgl_extension{WEBGL,debug_renderer_info} is not |
|
* available, returns the same as @ref vendorString(). |
|
* |
|
* The result is *not* cached, repeated queries will result in repeated |
|
* OpenGL calls. The returned view is always |
|
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and |
|
* @relativeref{Corrade::Containers::StringViewFlag,Global}. |
|
* @see @ref rendererStringUnmasked(), @fn_gl{GetString} with |
|
* @def_gl_keyword{UNMASKED_VENDOR_WEBGL} |
|
* @requires_webgl_only Not available on desktop or ES builds. |
|
*/ |
|
Containers::StringView vendorStringUnmasked() const; |
|
#endif |
|
|
|
/** |
|
* @brief Renderer string |
|
* |
|
* The result is *not* cached, repeated queries will result in repeated |
|
* OpenGL calls. The returned view is always |
|
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and |
|
* @relativeref{Corrade::Containers::StringViewFlag,Global}. In WebGL |
|
* the renderer string is implicitly masked away, use |
|
* @ref rendererStringUnmasked() to access the real renderer string, if |
|
* available. |
|
* @see @ref vendorString(), @fn_gl{GetString} with |
|
* @def_gl_keyword{RENDERER} |
|
*/ |
|
Containers::StringView rendererString() const; |
|
|
|
#if defined(MAGNUM_TARGET_WEBGL) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
/** |
|
* @brief Unmasked renderer string |
|
* @m_since_latest |
|
* |
|
* A WebGL counterpart to @ref rendererString() that returns the real |
|
* renderer string. If @webgl_extension{WEBGL,debug_renderer_info} is |
|
* not available, returns the same as @ref rendererString(). |
|
* |
|
* The result is *not* cached, repeated queries will result in repeated |
|
* OpenGL calls. The returned view is always |
|
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and |
|
* @relativeref{Corrade::Containers::StringViewFlag,Global}. |
|
* @see @ref vendorStringUnmasked(), @fn_gl{GetString} with |
|
* @def_gl_keyword{UNMASKED_RENDERER_WEBGL} |
|
* @requires_webgl_only Not available on desktop or ES builds. |
|
*/ |
|
Containers::StringView rendererStringUnmasked() const; |
|
#endif |
|
|
|
/** |
|
* @brief Version string |
|
* |
|
* The result is *not* cached, repeated queries will result in repeated |
|
* OpenGL calls. The returned view is always |
|
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and |
|
* @relativeref{Corrade::Containers::StringViewFlag,Global}. |
|
* @see @ref shadingLanguageVersionString(), @ref version(), |
|
* @fn_gl{GetString} with @def_gl_keyword{VERSION} |
|
*/ |
|
Containers::StringView versionString() const; |
|
|
|
/** |
|
* @brief Shading language version string |
|
* |
|
* The result is *not* cached, repeated queries will result in repeated |
|
* OpenGL calls. The returned view is always |
|
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and |
|
* @relativeref{Corrade::Containers::StringViewFlag,Global}. |
|
* @see @ref versionString(), @ref version(), @fn_gl{GetString} with |
|
* @def_gl_keyword{SHADING_LANGUAGE_VERSION} |
|
*/ |
|
Containers::StringView shadingLanguageVersionString() const; |
|
|
|
/** |
|
* @brief Shading language version strings |
|
* |
|
* The result is *not* cached, repeated queries will result in repeated |
|
* OpenGL calls. The returned view is always |
|
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and |
|
* @relativeref{Corrade::Containers::StringViewFlag,Global}. |
|
* @see @ref versionString(), @ref version(), @fn_gl{Get} with |
|
* @def_gl_keyword{NUM_SHADING_LANGUAGE_VERSIONS}, @fn_gl{GetString} |
|
* with @def_gl_keyword{SHADING_LANGUAGE_VERSION} |
|
*/ |
|
Containers::Array<Containers::StringView> shadingLanguageVersionStrings() const; |
|
|
|
/** |
|
* @brief Extension strings |
|
* |
|
* The result is *not* cached, repeated queries will result in repeated |
|
* OpenGL calls. Note that this function returns list of all extensions |
|
* reported by the driver (even those not supported by Magnum), see |
|
* @ref supportedExtensions(), @ref Extension::extensions() or |
|
* @ref isExtensionSupported() for alternatives. The returned views are |
|
* always @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} |
|
* and @relativeref{Corrade::Containers::StringViewFlag,Global}. |
|
* @see @fn_gl{Get} with @def_gl_keyword{NUM_EXTENSIONS}, |
|
* @fn_gl{GetString} with @def_gl_keyword{EXTENSIONS} |
|
*/ |
|
Containers::Array<Containers::StringView> extensionStrings() const; |
|
|
|
#ifndef MAGNUM_TARGET_WEBGL |
|
/** |
|
* @brief Context flags |
|
* |
|
* @requires_gles Context flags are not available in WebGL. |
|
*/ |
|
Flags flags() const { return _flags; } |
|
#endif |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
* @brief Supported extensions |
|
* |
|
* The list contains only extensions from OpenGL versions newer than |
|
* the current. |
|
* @m_deprecated_since_latest Deprecated as it doesn't provide anything |
|
* that @ref extensionStrings(), @ref Extension::extensions() and |
|
* @ref isExtensionSupported() wouldn't provide already and only |
|
* causes extra overhead during context creation. |
|
*/ |
|
CORRADE_DEPRECATED("use extensionStrings(), Extension::extensions() and isExtensionSupported() instead") Containers::ArrayView<const Extension> supportedExtensions() const { |
|
return _supportedExtensions; |
|
} |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
/** |
|
* @brief Detect if current OpenGL context is a core profile |
|
* |
|
* The result is cached, repeated queries don't result in repeated |
|
* OpenGL calls. |
|
* @see @fn_gl{Get} with @def_gl_keyword{CORE_PROFILE_MASK}, |
|
* @ref Flag::ForwardCompatible |
|
* @requires_gl Core/compatibility profile distinction and forward |
|
* compatibility applies only to desktop GL. |
|
*/ |
|
bool isCoreProfile(); |
|
#endif |
|
|
|
/** |
|
* @brief Whether given OpenGL version is supported |
|
* |
|
* @see @ref supportedVersion(), @ref MAGNUM_ASSERT_GL_VERSION_SUPPORTED() |
|
*/ |
|
bool isVersionSupported(Version version) const; |
|
|
|
/** |
|
* @brief Get supported OpenGL version |
|
* |
|
* Returns first supported OpenGL version from passed list. Convenient |
|
* equivalent to subsequent @ref isVersionSupported() calls --- the two |
|
* following examples produce the same result: |
|
* |
|
* @snippet MagnumGL.cpp Context-supportedVersion |
|
* |
|
* If no version from the list is supported, returns lowest available |
|
* OpenGL version (@ref Version::GL210 for desktop OpenGL, |
|
* @ref Version::GLES200 for OpenGL ES). |
|
* @see @ref isExtensionSupported(Version) const |
|
*/ |
|
Version supportedVersion(std::initializer_list<Version> versions) const; |
|
|
|
/** |
|
* @brief Whether given extension is supported |
|
* |
|
* Extensions usable with this function are listed in the |
|
* @ref Extensions namespace in the @ref Magnum/GL/Extensions.h header |
|
* and in the @ref opengl-support "OpenGL support tables". Example |
|
* usage: |
|
* |
|
* @snippet MagnumGL.cpp Context-isExtensionSupported |
|
* |
|
* @see @ref isExtensionSupported(const Extension&) const, |
|
* @ref MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(), |
|
* @ref isExtensionDisabled() |
|
*/ |
|
template<class E> bool isExtensionSupported() const { |
|
return isExtensionSupported<E>(version()); |
|
} |
|
|
|
/** |
|
* @brief Whether given extension is supported in given version |
|
* |
|
* Similar to @ref isExtensionSupported(), but checks also that the |
|
* minimal required version of the extension is larger or equal to |
|
* @p version. Useful mainly in shader compilation when the decisions |
|
* depend on selected GLSL version, for example: |
|
* |
|
* @snippet MagnumGL.cpp Context-isExtensionSupported-version |
|
*/ |
|
template<class E> bool isExtensionSupported(Version version) const { |
|
static_assert(Implementation::IsExtension<E>::value, "expected an OpenGL extension"); |
|
return _extensionRequiredVersion[E::Index] <= version && _extensionStatus[E::Index]; |
|
} |
|
|
|
/** |
|
* @brief Whether given extension is supported |
|
* |
|
* Can be used e.g. for listing extensions available on current |
|
* hardware, but for general usage prefer @ref isExtensionSupported() const, |
|
* as it does most operations in compile time. |
|
* @see @ref supportedExtensions(), @ref Extension::extensions(), |
|
* @ref MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED() |
|
*/ |
|
bool isExtensionSupported(const Extension& extension) const { |
|
return isVersionSupported(_extensionRequiredVersion[extension.index()]) && _extensionStatus[extension.index()]; |
|
} |
|
|
|
/** |
|
* @brief Whether given extension is disabled |
|
* |
|
* Can be used for detecting driver bug workarounds. Disabled |
|
* 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()); |
|
} |
|
|
|
/** |
|
* @brief Whether given extension is disabled for given version |
|
* |
|
* 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"); |
|
/* The extension is advertised, but the minimal version has been |
|
increased */ |
|
return E::requiredVersion() <= version && _extensionRequiredVersion[E::Index] > version; |
|
} |
|
|
|
/** |
|
* @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 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()]); |
|
} |
|
|
|
/** |
|
* @brief Reset internal state tracker |
|
* |
|
* The engine internally tracks object bindings and other state to |
|
* avoid redundant OpenGL calls. In some cases (e.g. when non-Magnum |
|
* code makes GL calls) the internal tracker no longer reflects actual |
|
* state. Equivalently the third party code can cause accidental |
|
* modifications of Magnum objects. It's thus advised to call this |
|
* function as a barrier between Magnum code and third-party GL code. |
|
* |
|
* The default, when calling this function with no parameters, will |
|
* reset all state. That's the safest option, but may have considerable |
|
* performance impact when third-party and Magnum code is combined very |
|
* often. For greater control it's possible to reset only particular |
|
* states from the @ref State enum. |
|
* |
|
* See also @ref opengl-state-tracking for more information. |
|
*/ |
|
void resetState(States states = ~States{}); |
|
|
|
/** |
|
* @brief Detect driver |
|
* |
|
* Tries to detect driver using various OpenGL state queries. Once the |
|
* detection is done, the result is cached, repeated queries don't |
|
* result in repeated GL calls. Used primarily for enabling |
|
* driver-specific workarounds. |
|
*/ |
|
DetectedDrivers detectedDriver(); |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
private: |
|
#endif |
|
bool isDriverWorkaroundDisabled(Containers::StringView workaround); |
|
Implementation::State& state() { return *_state; } |
|
|
|
/* This function is called from MeshState constructor, which means the |
|
state() pointer is not ready yet so we have to pass it directly */ |
|
MAGNUM_GL_LOCAL bool isCoreProfileInternal(Implementation::ContextState& state); |
|
|
|
Implementation::ContextConfigurationFlags configurationFlags() const { return _configurationFlags; } |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
private: |
|
#else |
|
protected: |
|
#endif |
|
/* Made protected so it's possible to test the NoCreate constructor and |
|
also not needed to friend Platform::GLContext. */ |
|
explicit Context(NoCreateT, Int argc, const char* const* argv, void functionLoader(Context&)); |
|
explicit Context(NoCreateT, Utility::Arguments&& args, Int argc, const char* const* argv, void functionLoader(Context&)): Context{NoCreate, args, argc, argv, functionLoader} {} |
|
explicit Context(NoCreateT, Utility::Arguments& args, Int argc, const char* const* argv, void functionLoader(Context&)); |
|
|
|
bool tryCreate(const Configuration& configuration); |
|
void create(const Configuration& configuration); |
|
|
|
private: |
|
#ifndef DOXYGEN_GENERATING_OUTPUT /* https://bugzilla.gnome.org/show_bug.cgi?id=776986 */ |
|
friend Implementation::ContextState; |
|
#endif |
|
|
|
MAGNUM_GL_LOCAL void disableDriverWorkaround(Containers::StringView workaround); |
|
|
|
/* Defined in Implementation/driverSpecific.cpp */ |
|
MAGNUM_GL_LOCAL void setupDriverWorkarounds(); |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
MAGNUM_GL_LOCAL static bool isCoreProfileImplementationDefault(Context& self); |
|
MAGNUM_GL_LOCAL static bool isCoreProfileImplementationNV(Context& self); |
|
#endif |
|
|
|
void(*_functionLoader)(Context&){}; |
|
Version _version; |
|
#ifndef MAGNUM_TARGET_WEBGL |
|
Flags _flags; |
|
#endif |
|
|
|
Math::BitVector<Implementation::ExtensionCount> _extensionStatus; |
|
/* For all extensions that are marked as supported in _extensionStatus, |
|
this field contains the minimal required GL version the extension |
|
needs. Extensions that are disabled have None here. */ |
|
Containers::StaticArray<Implementation::ExtensionCount, Version> _extensionRequiredVersion; |
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
Containers::Array<Extension> _supportedExtensions; |
|
#endif |
|
|
|
Containers::ArrayTuple _stateData; |
|
Implementation::State* _state; |
|
|
|
Containers::Optional<DetectedDrivers> _detectedDrivers; |
|
|
|
/** @todo these are all needed only until the state gets created and |
|
then can be discarded -- what to do? we could avoid including |
|
Array altogether */ |
|
/* True means known and disabled, false means known */ |
|
Containers::Array<std::pair<Containers::StringView, bool>> _driverWorkarounds; |
|
Containers::Array<Extension> _disabledExtensions; |
|
Implementation::ContextConfigurationFlags _configurationFlags; |
|
}; |
|
|
|
#ifndef MAGNUM_TARGET_WEBGL |
|
CORRADE_ENUMSET_OPERATORS(Context::Flags) |
|
#endif |
|
CORRADE_ENUMSET_OPERATORS(Context::DetectedDrivers) |
|
CORRADE_ENUMSET_OPERATORS(Context::States) |
|
|
|
#ifndef MAGNUM_TARGET_WEBGL |
|
/** @debugoperatorclassenum{Context,Context::Flag} */ |
|
MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::Flag value); |
|
|
|
/** @debugoperatorclassenum{Context,Context::Flags} */ |
|
MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::Flags value); |
|
#endif |
|
|
|
/** @debugoperatorclassenum{Context,Context::DetectedDriver} */ |
|
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() |
|
*/ |
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
enum class Flag: UnsignedLong { |
|
/* Docs only, keep in sync with |
|
Implementation::ContextConfigurationFlag please */ |
|
|
|
/** |
|
* Treat the context as windowless, assume there's no default |
|
* framebuffer and thus don't initialize or touch |
|
* @ref defaultFramebuffer in any way. |
|
* |
|
* This flag is implicitly enabled in all |
|
* @ref Platform::WindowlessEglContext::Configuration "Platform::Windowless*Application::Configuration", |
|
* and, conversely, not possible to enable in any |
|
* @ref Platform::Sdl2Application::GLConfiguration::Flag "Platform::*Application::GLConfiguration". |
|
*/ |
|
Windowless = 1ull << 59, |
|
|
|
/** |
|
* 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 << 60, |
|
|
|
/** |
|
* 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 << 61, |
|
|
|
/** |
|
* Enable GPU validation, if available. Has a precedence over |
|
* @ref Flag::GpuValidationNoError. |
|
* |
|
* Corresponds to the `--magnum-gpu-validation on` |
|
* @ref GL-Context-usage-command-line "command-line option". |
|
*/ |
|
GpuValidation = 1ull << 62, |
|
|
|
/** |
|
* Enable a context without error reporting, if available. Ignored |
|
* if @ref Flag::GpuValidation is set. |
|
* |
|
* Corresponds to the `--magnum-gpu-validation no-error` |
|
* @ref GL-Context-usage-command-line "command-line option". |
|
*/ |
|
GpuValidationNoError = 1ull << 63 |
|
}; |
|
#else |
|
typedef Implementation::ContextConfigurationFlag Flag; |
|
#endif |
|
|
|
/** |
|
* @brief Context setup flags |
|
* |
|
* @see @ref setFlags(), @ref GL::Context::Flags |
|
*/ |
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
typedef Containers::EnumSet<Flag> Flags; |
|
#else |
|
typedef Implementation::ContextConfigurationFlags Flags; |
|
#endif |
|
|
|
/*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 |
|
|
|
/** @hideinitializer |
|
@brief Assert that given OpenGL version is supported |
|
@param version Version |
|
|
|
Useful for initial checks on availability of required features. |
|
|
|
By default, if assertion fails, an message is printed to error output and the |
|
application aborts. If `CORRADE_NO_ASSERT` is defined, this macro does nothing. |
|
Example usage: |
|
|
|
@snippet MagnumGL.cpp Context-MAGNUM_ASSERT_GL_VERSION_SUPPORTED |
|
|
|
@see @ref Magnum::GL::Context::isVersionSupported() "GL::Context::isVersionSupported()", |
|
@ref MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(), @ref CORRADE_ASSERT(), |
|
@ref CORRADE_INTERNAL_ASSERT() |
|
*/ |
|
#ifdef CORRADE_NO_ASSERT |
|
#define MAGNUM_ASSERT_GL_VERSION_SUPPORTED(version) do {} while(0) |
|
#else |
|
#define MAGNUM_ASSERT_GL_VERSION_SUPPORTED(version) \ |
|
do { \ |
|
if(!Magnum::GL::Context::current().isVersionSupported(version)) { \ |
|
Corrade::Utility::Error() << "Magnum: required version" << version << "is not supported"; \ |
|
std::abort(); \ |
|
} \ |
|
} while(0) |
|
#endif |
|
|
|
/** @hideinitializer |
|
@brief Assert that given OpenGL extension is supported |
|
@param extension Extension name (from the @ref Magnum::GL::Extensions "Extensions" |
|
namespace) |
|
|
|
Useful for initial checks on availability of required features. |
|
|
|
By default, if assertion fails, an message is printed to error output and the |
|
application aborts. If `CORRADE_NO_ASSERT` is defined, this macro does nothing. |
|
Example usage: |
|
|
|
@snippet MagnumGL.cpp Context-MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED |
|
|
|
@see @ref Magnum::GL::Context::isExtensionSupported() "Context::isExtensionSupported()", |
|
@ref MAGNUM_ASSERT_GL_VERSION_SUPPORTED(), @ref CORRADE_ASSERT(), |
|
@ref CORRADE_INTERNAL_ASSERT() |
|
*/ |
|
#ifdef CORRADE_NO_ASSERT |
|
#define MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(extension) do {} while(0) |
|
#else |
|
#define MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(extension) \ |
|
do { \ |
|
if(!Magnum::GL::Context::current().isExtensionSupported<extension>()) { \ |
|
Corrade::Utility::Error() << "Magnum: required extension" << extension::string() << "is not supported"; \ |
|
std::abort(); \ |
|
} \ |
|
} while(0) |
|
#endif |
|
|
|
}} |
|
|
|
#endif
|
|
|