Browse Source

GL,Platform: introduce GL::Context::Configuration::Flag::Windowless.

With this flag set (which is done implicitly for all windowless apps
and, conversely, not done for all windowed apps), the default
framebuffer state isn't touched in any way, which should avoid potential
race conditions with default framebuffer on another thread.
euler-xxx
Vladimír Vondruš 5 years ago
parent
commit
46df57f6d5
  1. 7
      doc/changelog.dox
  2. 12
      src/Magnum/GL/Context.cpp
  3. 14
      src/Magnum/GL/Context.h
  4. 19
      src/Magnum/GL/Framebuffer.cpp
  5. 4
      src/Magnum/Platform/AbstractXApplication.h
  6. 4
      src/Magnum/Platform/AndroidApplication.h
  7. 4
      src/Magnum/Platform/EmscriptenApplication.h
  8. 4
      src/Magnum/Platform/GlfwApplication.h
  9. 4
      src/Magnum/Platform/Sdl2Application.h
  10. 4
      src/Magnum/Platform/WindowlessCglApplication.cpp
  11. 6
      src/Magnum/Platform/WindowlessCglApplication.h
  12. 1
      src/Magnum/Platform/WindowlessEglApplication.cpp
  13. 4
      src/Magnum/Platform/WindowlessEglApplication.h
  14. 1
      src/Magnum/Platform/WindowlessGlxApplication.cpp
  15. 4
      src/Magnum/Platform/WindowlessGlxApplication.h
  16. 6
      src/Magnum/Platform/WindowlessIosApplication.h
  17. 4
      src/Magnum/Platform/WindowlessIosApplication.mm
  18. 1
      src/Magnum/Platform/WindowlessWglApplication.cpp
  19. 4
      src/Magnum/Platform/WindowlessWglApplication.h
  20. 4
      src/Magnum/Platform/WindowlessWindowsEglApplication.cpp
  21. 6
      src/Magnum/Platform/WindowlessWindowsEglApplication.h

7
doc/changelog.dox

@ -196,6 +196,13 @@ See also:
now advertised as a @cpp "intel-windows-chatty-shader-compiler" @ce now advertised as a @cpp "intel-windows-chatty-shader-compiler" @ce
workaround, instead of being done silently. See @ref opengl-workarounds for workaround, instead of being done silently. See @ref opengl-workarounds for
more information. more information.
- @ref Platform::WindowlessEglApplication "Platform::Windowless*Application"
instances no longer touch default framebuffer state in order to avoid
potential race conditions with a windowed context on another thread. This
is also exposed via a new @ref GL::Context::Configuration::Flag::Windowless
flag for integration with custom-created OpenGL contexts. See also
[mosra/magnum#493](https://github.com/mosra/magnum/pull/493) and
[mosra/magnum#494](https://github.com/mosra/magnum/pull/494).
@subsubsection changelog-latest-changes-math Math library @subsubsection changelog-latest-changes-math Math library

12
src/Magnum/GL/Context.cpp

@ -785,6 +785,10 @@ bool Context::tryCreate(const Configuration& configuration) {
if(configuration.flags() & Configuration::Flag::GpuValidation) if(configuration.flags() & Configuration::Flag::GpuValidation)
_configurationFlags |= Configuration::Flag::GpuValidation; _configurationFlags |= Configuration::Flag::GpuValidation;
/* Same for windowless */
if(configuration.flags() & Configuration::Flag::Windowless)
_configurationFlags |= Configuration::Flag::Windowless;
/* Driver workarounds get merged. Not using disableDriverWorkaround() here /* Driver workarounds get merged. Not using disableDriverWorkaround() here
since the Configuration already contains the internal string views. */ since the Configuration already contains the internal string views. */
for(const Containers::StringView workaround: configuration.disabledWorkarounds()) for(const Containers::StringView workaround: configuration.disabledWorkarounds())
@ -974,9 +978,13 @@ bool Context::tryCreate(const Configuration& configuration) {
if(!workaround.second) Debug(output) << " " << workaround.first; if(!workaround.second) Debug(output) << " " << workaround.first;
} }
/* Initialize functionality based on current OpenGL version and extensions */
/** @todo Get rid of these */ /** @todo Get rid of these */
DefaultFramebuffer::initializeContextBasedFunctionality(*this); /* Initialize functionality based on current OpenGL version and extensions.
If we are on a windowless context don't touch the default framebuffer
to avoid potential race conditions with default framebuffer on another
thread. */
if(!(_configurationFlags & Configuration::Flag::Windowless))
DefaultFramebuffer::initializeContextBasedFunctionality(*this);
Renderer::initializeContextBasedFunctionality(); Renderer::initializeContextBasedFunctionality();
/* Enable GPU validation, if requested */ /* Enable GPU validation, if requested */

14
src/Magnum/GL/Context.h

@ -70,6 +70,7 @@ namespace Implementation {
Context before the Configuration class is defined, it has to be here */ Context before the Configuration class is defined, it has to be here */
enum class ContextConfigurationFlag: UnsignedLong { enum class ContextConfigurationFlag: UnsignedLong {
/* Keeping the 32-bit range reserved for actual GL context flags */ /* Keeping the 32-bit range reserved for actual GL context flags */
Windowless = 1ull << 60,
QuietLog = 1ull << 61, QuietLog = 1ull << 61,
VerboseLog = 1ull << 62, VerboseLog = 1ull << 62,
GpuValidation = 1ull << 63 GpuValidation = 1ull << 63
@ -914,6 +915,19 @@ class MAGNUM_GL_EXPORT Context::Configuration {
/* Docs only, keep in sync with /* Docs only, keep in sync with
Implementation::ContextConfigurationFlag please */ Implementation::ContextConfigurationFlag please */
/**
* Treat the context as windowless, assume there's no default
* framebuffer and thus don't touch @ref defaultFramebuffer in any
* way. Useful for preventing race conditions when creating OpenGL
* contexts in background threads.
*
* 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 << 60,
/** /**
* Print only warnings and errors instead of the usual startup log * Print only warnings and errors instead of the usual startup log
* listing used extensions and workarounds. Ignored if * listing used extensions and workarounds. Ignored if

19
src/Magnum/GL/Framebuffer.cpp

@ -120,18 +120,23 @@ Framebuffer::~Framebuffer() {
if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return; if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return;
/* If bound, remove itself from state */ /* If bound, remove itself from state */
Implementation::FramebufferState& state = Context::current().state().framebuffer; Context& context = Context::current();
Implementation::FramebufferState& state = context.state().framebuffer;
if(state.readBinding == _id) state.readBinding = 0; if(state.readBinding == _id) state.readBinding = 0;
/* For draw binding reset also viewport */ /* For draw binding reset also viewport. Don't do that for windowless
contexts to avoid potential race conditions with default framebuffer on
another thread. */
if(state.drawBinding == _id) { if(state.drawBinding == _id) {
state.drawBinding = 0; state.drawBinding = 0;
/** if(!(context.configurationFlags() & Context::Configuration::Flag::Windowless)) {
* @todo Less ugly solution (need to call setViewportInternal() to /**
* reset the viewport to size of default framebuffer) * @todo Less ugly solution (need to call setViewportInternal() to
*/ * reset the viewport to size of default framebuffer)
defaultFramebuffer.bind(); */
defaultFramebuffer.bind();
}
} }
glDeleteFramebuffers(1, &_id); glDeleteFramebuffers(1, &_id);

4
src/Magnum/Platform/AbstractXApplication.h

@ -343,7 +343,9 @@ class AbstractXApplication::GLConfiguration: public GL::Context::Configuration {
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is not meant to be enabled for windowed apps.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {

4
src/Magnum/Platform/AndroidApplication.h

@ -456,7 +456,9 @@ class AndroidApplication::GLConfiguration: public GL::Context::Configuration {
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is not meant to be enabled for windowed apps.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {

4
src/Magnum/Platform/EmscriptenApplication.h

@ -942,7 +942,9 @@ class EmscriptenApplication::GLConfiguration: public GL::Context::Configuration
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is not meant to be enabled for windowed apps.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {

4
src/Magnum/Platform/GlfwApplication.h

@ -784,7 +784,9 @@ class GlfwApplication::GLConfiguration: public GL::Context::Configuration {
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is not meant to be enabled for windowed apps.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {

4
src/Magnum/Platform/Sdl2Application.h

@ -1236,7 +1236,9 @@ class Sdl2Application::GLConfiguration: public GL::Context::Configuration {
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is not meant to be enabled for windowed apps.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {

4
src/Magnum/Platform/WindowlessCglApplication.cpp

@ -105,6 +105,10 @@ bool WindowlessCglContext::release() {
return false; return false;
} }
WindowlessCglContext::Configuration::Configuration() {
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless);
}
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments): WindowlessCglApplication{arguments, Configuration{}} {} WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments): WindowlessCglApplication{arguments, Configuration{}} {}
#endif #endif

6
src/Magnum/Platform/WindowlessCglApplication.h

@ -166,7 +166,9 @@ class WindowlessCglContext::Configuration: public GL::Context::Configuration {
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is enabled implicitly by default.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {
@ -196,6 +198,8 @@ class WindowlessCglContext::Configuration: public GL::Context::Configuration {
*/ */
typedef Containers::EnumSet<Flag> Flags; typedef Containers::EnumSet<Flag> Flags;
/*implicit*/ Configuration();
/** @brief Context flags */ /** @brief Context flags */
Flags flags() const { Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags())); return Flag(UnsignedLong(GL::Context::Configuration::flags()));

1
src/Magnum/Platform/WindowlessEglApplication.cpp

@ -533,6 +533,7 @@ WindowlessEglContext::Configuration::Configuration()
: _device{} : _device{}
#endif #endif
{ {
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
addFlags(Flag::ForwardCompatible); addFlags(Flag::ForwardCompatible);
#endif #endif

4
src/Magnum/Platform/WindowlessEglApplication.h

@ -183,7 +183,9 @@ class WindowlessEglContext::Configuration: public GL::Context::Configuration {
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is enabled implicitly by default.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {

1
src/Magnum/Platform/WindowlessGlxApplication.cpp

@ -274,6 +274,7 @@ bool WindowlessGlxContext::release() {
} }
WindowlessGlxContext::Configuration::Configuration() { WindowlessGlxContext::Configuration::Configuration() {
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
addFlags(Flag::ForwardCompatible); addFlags(Flag::ForwardCompatible);
#endif #endif

4
src/Magnum/Platform/WindowlessGlxApplication.h

@ -188,7 +188,9 @@ class WindowlessGlxContext::Configuration: public GL::Context::Configuration {
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is enabled implicitly by default.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {

6
src/Magnum/Platform/WindowlessIosApplication.h

@ -157,7 +157,9 @@ class WindowlessIosContext::Configuration: public GL::Context::Configuration {
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is enabled implicitly by default.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {
@ -187,6 +189,8 @@ class WindowlessIosContext::Configuration: public GL::Context::Configuration {
*/ */
typedef Containers::EnumSet<Flag> Flags; typedef Containers::EnumSet<Flag> Flags;
/*implicit*/ Configuration();
/** @brief Context flags */ /** @brief Context flags */
Flags flags() const { Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags())); return Flag(UnsignedLong(GL::Context::Configuration::flags()));

4
src/Magnum/Platform/WindowlessIosApplication.mm

@ -82,6 +82,10 @@ bool WindowlessIosContext::release() {
return false; return false;
} }
WindowlessIosContext::Configuration::Configuration() {
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless);
}
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments): WindowlessIosApplication{arguments, Configuration{}} {} WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments): WindowlessIosApplication{arguments, Configuration{}} {}
#endif #endif

1
src/Magnum/Platform/WindowlessWglApplication.cpp

@ -259,6 +259,7 @@ bool WindowlessWglContext::release() {
} }
WindowlessWglContext::Configuration::Configuration() { WindowlessWglContext::Configuration::Configuration() {
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
addFlags(Flag::ForwardCompatible); addFlags(Flag::ForwardCompatible);
#endif #endif

4
src/Magnum/Platform/WindowlessWglApplication.h

@ -175,7 +175,9 @@ class WindowlessWglContext::Configuration: public GL::Context::Configuration {
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is enabled implicitly by default.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {

4
src/Magnum/Platform/WindowlessWindowsEglApplication.cpp

@ -182,6 +182,10 @@ bool WindowlessWindowsEglContext::release() {
return false; return false;
} }
WindowlessWindowsEglContext::Configuration::Configuration() {
GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless);
}
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments): WindowlessWindowsEglApplication{arguments, Configuration{}} {} WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments): WindowlessWindowsEglApplication{arguments, Configuration{}} {}
#endif #endif

6
src/Magnum/Platform/WindowlessWindowsEglApplication.h

@ -161,7 +161,9 @@ class WindowlessWindowsEglContext::Configuration: public GL::Context::Configurat
/** /**
* @brief Context flag * @brief Context flag
* *
* Includes also everything from @ref GL::Context::Configuration::Flag. * Includes also everything from @ref GL::Context::Configuration::Flag
* except for @relativeref{GL::Context::Configuration,Flag::Windowless},
* which is enabled implicitly by default.
* @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag
*/ */
enum class Flag: UnsignedLong { enum class Flag: UnsignedLong {
@ -199,6 +201,8 @@ class WindowlessWindowsEglContext::Configuration: public GL::Context::Configurat
*/ */
typedef Containers::EnumSet<Flag> Flags; typedef Containers::EnumSet<Flag> Flags;
/*implicit*/ Configuration();
/** @brief Context flags */ /** @brief Context flags */
Flags flags() const { Flags flags() const {
return Flag(UnsignedLong(GL::Context::Configuration::flags())); return Flag(UnsignedLong(GL::Context::Configuration::flags()));

Loading…
Cancel
Save