From 4d1203d66e5c8fc145b5455a2bc92f50fad36622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Brard?= Date: Wed, 8 Apr 2020 16:00:20 +0200 Subject: [PATCH] Platform: added shared context support to windowless applications. --- .../Platform/WindowlessCglApplication.cpp | 4 +-- .../Platform/WindowlessCglApplication.h | 25 ++++++++++++++++++ .../Platform/WindowlessEglApplication.cpp | 9 ++++++- .../Platform/WindowlessEglApplication.h | 26 +++++++++++++++++++ .../Platform/WindowlessGlxApplication.cpp | 6 ++--- .../Platform/WindowlessGlxApplication.h | 23 ++++++++++++++++ .../Platform/WindowlessWglApplication.cpp | 6 ++--- .../Platform/WindowlessWglApplication.h | 23 ++++++++++++++++ .../WindowlessWindowsEglApplication.cpp | 2 +- .../WindowlessWindowsEglApplication.h | 23 ++++++++++++++++ 10 files changed, 137 insertions(+), 10 deletions(-) diff --git a/src/Magnum/Platform/WindowlessCglApplication.cpp b/src/Magnum/Platform/WindowlessCglApplication.cpp index d6085932e..34eea525b 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.cpp +++ b/src/Magnum/Platform/WindowlessCglApplication.cpp @@ -35,7 +35,7 @@ namespace Magnum { namespace Platform { -WindowlessCglContext::WindowlessCglContext(const Configuration&, GLContext*) { +WindowlessCglContext::WindowlessCglContext(const Configuration & configuration, GLContext*) { int formatCount; CGLPixelFormatAttribute attributes32[] = { kCGLPFAAccelerated, @@ -68,7 +68,7 @@ WindowlessCglContext::WindowlessCglContext(const Configuration&, GLContext*) { } } - if(CGLCreateContext(_pixelFormat, nullptr, &_context) != kCGLNoError) + if(CGLCreateContext(_pixelFormat, configuration.sharedContext(), &_context) != kCGLNoError) Error() << "Platform::WindowlessCglContext: cannot create context"; } diff --git a/src/Magnum/Platform/WindowlessCglApplication.h b/src/Magnum/Platform/WindowlessCglApplication.h index 112d1f347..6d453a6ef 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.h +++ b/src/Magnum/Platform/WindowlessCglApplication.h @@ -142,6 +142,31 @@ class WindowlessCglContext { class WindowlessCglContext::Configuration { public: constexpr /*implicit*/ Configuration() {} + + /** + * @brief Create a shared context + * @return Reference to self (for method chaining) + * @m_since_latest + * + * When set, the created context will share a subset of OpenGL objects + * with @p context, instead of being independent. Many caveats and + * limitations apply to shared OpenGL contexts, please consult the + * OpenGL specification for details. Default is @cpp nullptr @ce, i.e. + * no sharing. + */ + Configuration& setSharedContext(CGLContextObj context) { + _sharedContext = context; + return *this; + } + + /** + * @brief Shared context + * @m_since_latest + */ + CGLContextObj sharedContext() const { return _sharedContext; } + + private: + CGLContextObj _sharedContext = nullptr; }; /** diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index e83ce1dbd..1d156633f 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -273,7 +273,14 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G } #endif - if(!(_context = eglCreateContext(_display, config, EGL_NO_CONTEXT, attributes))) { + if(!(_context = eglCreateContext(_display, config, + #ifndef MAGNUM_TARGET_WEBGL + configuration.sharedContext(), + #else + EGL_NO_CONTEXT, + #endif + attributes))) + { Error() << "Platform::WindowlessEglApplication::tryCreateContext(): cannot create EGL context:" << Implementation::eglErrorString(eglGetError()); return; } diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index 0cde69813..af0681dd9 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -255,12 +255,38 @@ class WindowlessEglContext::Configuration { _device = id; return *this; } + + /** + * @brief Create a shared context + * @return Reference to self (for method chaining) + * @m_since_latest + * + * When set, the created context will share a subset of OpenGL objects + * with @p context, instead of being independent. Many caveats and + * limitations apply to shared OpenGL contexts, please consult the + * OpenGL specification for details. Default is `EGL_NO_CONTEXT`, i.e. + * no sharing. + * @requires_gles Context sharing is not available in WebGL. + */ + Configuration& setSharedContext(EGLContext context) { + _sharedContext = context; + return *this; + } + + /** + * @brief Shared context + * @m_since_latest + * + * @requires_gles Context sharing is not available in WebGL. + */ + EGLContext sharedContext() const { return _sharedContext; } #endif private: #ifndef MAGNUM_TARGET_WEBGL Flags _flags; UnsignedInt _device; + EGLContext _sharedContext = EGL_NO_CONTEXT; #endif }; diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index eeca032d4..574f5795d 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -94,7 +94,7 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura #endif 0 }; - _context = glXCreateContextAttribsARB(_display, configs[0], nullptr, True, contextAttributes); + _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, contextAttributes); #ifndef MAGNUM_TARGET_GLES /* Fall back to (forward compatible) GL 2.1 if core context creation fails */ @@ -105,7 +105,7 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura GLX_CONTEXT_FLAGS_ARB, GLint(flags), 0 }; - _context = glXCreateContextAttribsARB(_display, configs[0], nullptr, True, fallbackContextAttributes); + _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, fallbackContextAttributes); /* Fall back to (forward compatible) GL 2.1 if we are on binary NVidia/AMD drivers on Linux. Instead of creating forward-compatible context with @@ -142,7 +142,7 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura GLX_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible), 0 }; - _context = glXCreateContextAttribsARB(_display, configs[0], nullptr, True, fallbackContextAttributes); + _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, fallbackContextAttributes); } /* Revert back the old context */ diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 6d1ebca2f..792cbd99e 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -239,8 +239,31 @@ class WindowlessGlxContext::Configuration { return *this; } + /** + * @brief Create a shared context + * @return Reference to self (for method chaining) + * @m_since_latest + * + * When set, the created context will share a subset of OpenGL objects + * with @p context, instead of being independent. Many caveats and + * limitations apply to shared OpenGL contexts, please consult the + * OpenGL specification for details. Default is @cpp nullptr @ce, i.e. + * no sharing. + */ + Configuration& setSharedContext(GLXContext ctx) { + _sharedContext = ctx; + return *this; + } + + /** + * @brief Shared context + * @m_since_latest + */ + GLXContext sharedContext() const { return _sharedContext; } + private: Flags _flags; + GLXContext _sharedContext = nullptr; }; CORRADE_ENUMSET_OPERATORS(WindowlessGlxContext::Configuration::Flags) diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index 4bab6654b..b3606ca27 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -145,7 +145,7 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G #endif 0 }; - _context = wglCreateContextAttribsARB(_deviceContext, nullptr, contextAttributes); + _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), contextAttributes); #ifndef MAGNUM_TARGET_GLES /* Fall back to (forward compatible) GL 2.1 if core context creation fails */ @@ -157,7 +157,7 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G WGL_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible), 0 }; - _context = wglCreateContextAttribsARB(_deviceContext, nullptr, fallbackContextAttributes); + _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes); /* Fall back to (forward compatible) GL 2.1 if we are on binary NVidia/AMD/Intel drivers on Windows. Instead of creating forward-compatible @@ -196,7 +196,7 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G WGL_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible), 0 }; - _context = wglCreateContextAttribsARB(_deviceContext, nullptr, fallbackContextAttributes); + _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes); } } #endif diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index f3c461075..f63040df7 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -233,8 +233,31 @@ class WindowlessWglContext::Configuration { return *this; } + /** + * @brief Create a shared context + * @return Reference to self (for method chaining) + * @m_since_latest + * + * When set, the created context will share a subset of OpenGL objects + * with @p context, instead of being independent. Many caveats and + * limitations apply to shared OpenGL contexts, please consult the + * OpenGL specification for details. Default is @cpp nullptr @ce, i.e. + * no sharing. + */ + Configuration& setSharedContext(HGLRC context) { + _sharedContext = context; + return *this; + } + + /** + * @brief Shared context + * @m_since_latest + */ + HGLRC sharedContext() const { return _sharedContext; } + private: Flags _flags; + HGLRC _sharedContext = nullptr; }; CORRADE_ENUMSET_OPERATORS(WindowlessWglContext::Configuration::Flags) diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index 67d57fa15..04434740e 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -130,7 +130,7 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co EGL_NONE }; - if(!(_context = eglCreateContext(_display, config, EGL_NO_CONTEXT, attributes))) { + if(!(_context = eglCreateContext(_display, config, configuration.sharedContext(), attributes))) { Error() << "Platform::WindowlessWindowsEglContext: cannot create EGL context:" << Implementation::eglErrorString(eglGetError()); return; } diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 02a04410f..baae48b0e 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -203,8 +203,31 @@ class WindowlessWindowsEglContext::Configuration { return *this; } + /** + * @brief Create a shared context + * @return Reference to self (for method chaining) + * @m_since_latest + * + * When set, the created context will share a subset of OpenGL objects + * with @p context, instead of being independent. Many caveats and + * limitations apply to shared OpenGL contexts, please consult the + * OpenGL specification for details. Default is `EGL_NO_CONTEXT`, i.e. + * no sharing. + */ + Configuration& setSharedContext(EGLContext context) { + _sharedContext = context; + return *this; + } + + /** + * @brief Shared context + * @m_since_latest + */ + EGLContext sharedContext() const { return _sharedContext; } + private: Flags _flags; + EGLContext _sharedContext = EGL_NO_CONTEXT; }; CORRADE_ENUMSET_OPERATORS(WindowlessWindowsEglContext::Configuration::Flags)