From 11a94c16a39c6bf63408171e032c454d5e945db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Jun 2019 16:39:03 +0200 Subject: [PATCH] GL: added Context::makeCurrent(). --- doc/changelog.dox | 3 +++ doc/snippets/MagnumGL-framebuffer.cpp | 29 ++++++++++++++++++++++++++ src/Magnum/GL/Context.cpp | 2 ++ src/Magnum/GL/Context.h | 30 +++++++++++++++++++++++++++ src/Magnum/GL/Test/ContextGLTest.cpp | 18 ++++++++++++++++ src/Magnum/GL/Test/ContextTest.cpp | 10 +++++++++ 6 files changed, 92 insertions(+) diff --git a/doc/changelog.dox b/doc/changelog.dox index 86c137708..e8cbd2520 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -122,6 +122,9 @@ See also: - It's now possible to pass @ref std::initializer_list to @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 + information @subsubsection changelog-latest-new-math Math library diff --git a/doc/snippets/MagnumGL-framebuffer.cpp b/doc/snippets/MagnumGL-framebuffer.cpp index 452d33cbc..33ad6f045 100644 --- a/doc/snippets/MagnumGL-framebuffer.cpp +++ b/doc/snippets/MagnumGL-framebuffer.cpp @@ -23,9 +23,11 @@ DEALINGS IN THE SOFTWARE. */ +#include "Magnum/GL/Buffer.h" #include "Magnum/GL/DefaultFramebuffer.h" #include "Magnum/GL/Framebuffer.h" #include "Magnum/Platform/Sdl2Application.h" +#include "Magnum/Platform/GLContext.h" using namespace Magnum; @@ -69,3 +71,30 @@ void drawEvent() override { } /* [Framebuffer-usage-draw] */ }; + +int main() { + +{ +SDL_Window* _window{}; +SDL_GLContext* _otherGLContext{}; +/* [Context-makeCurrent-nullptr] */ +Platform::GLContext context; + +SDL_GL_MakeCurrent(_window, _otherGLContext); // or other platform-specific API +Platform::GLContext::makeCurrent(nullptr); + +Platform::GLContext other; +/* [Context-makeCurrent-nullptr] */ + +/* [Context-makeCurrent] */ +Platform::GLContext::makeCurrent(&context); + +GL::Buffer a; // implicitly tied to `context` + +Platform::GLContext::makeCurrent(&other); + +GL::Buffer b; // implicitly tied to `other` +/* [Context-makeCurrent] */ +} + +} diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index 71320bf21..3f2a28acd 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -456,6 +456,8 @@ Context& Context::current() { return *currentContext; } +void Context::makeCurrent(Context* context) { currentContext = context; } + Context::Context(NoCreateT, Int argc, const char** argv, void functionLoader(Context&)): Context{NoCreate, Utility::Arguments{"magnum"}, argc, argv, functionLoader} {} Context::Context(NoCreateT, Utility::Arguments& args, Int argc, const char** argv, void functionLoader(Context&)): _functionLoader{functionLoader}, _version{Version::None} { diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index c4ba24112..64521e077 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -154,6 +154,28 @@ If Corrade is compiled with @ref CORRADE_BUILD_MULTITHREADED (the default), the OpenGL context thread locality. This might cause some performance penalties --- if you are sure that you never need to have multiple independent thread-local Magnum context, build Corrade with the option disabled. + +@section GL-Context-multiple Using multiple OpenGL contexts + +By default, Magnum assumes you have one OpenGL context active at all times, and +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-framebuffer.cpp Context-makeCurrent-nullptr + +Once all needed instances are created, switch between them right after making +the underlying GL context current: + +@snippet MagnumGL-framebuffer.cpp Context-makeCurrent */ class MAGNUM_GL_EXPORT Context { public: @@ -420,6 +442,14 @@ class MAGNUM_GL_EXPORT Context { */ static Context& current(); + /** + * @brief Make a context current + * + * To be used when you need to manage multiple OpenGL contexts. See + * @ref GL-Context-multiple for more information. + */ + static void makeCurrent(Context* context); + /** @brief Copying is not allowed */ Context(const Context&) = delete; diff --git a/src/Magnum/GL/Test/ContextGLTest.cpp b/src/Magnum/GL/Test/ContextGLTest.cpp index f2312291d..a53821494 100644 --- a/src/Magnum/GL/Test/ContextGLTest.cpp +++ b/src/Magnum/GL/Test/ContextGLTest.cpp @@ -38,6 +38,8 @@ namespace Magnum { namespace GL { namespace Test { namespace { struct ContextGLTest: OpenGLTester { explicit ContextGLTest(); + void makeCurrent(); + #ifndef CORRADE_TARGET_EMSCRIPTEN void multithreaded(); #endif @@ -53,6 +55,8 @@ struct ContextGLTest: OpenGLTester { ContextGLTest::ContextGLTest() { addTests({ + &ContextGLTest::makeCurrent, + #ifndef CORRADE_TARGET_EMSCRIPTEN &ContextGLTest::multithreaded, #endif @@ -66,6 +70,20 @@ ContextGLTest::ContextGLTest() { &ContextGLTest::isExtensionDisabled}); } +void ContextGLTest::makeCurrent() { + CORRADE_VERIFY(Context::hasCurrent()); + + Context& current = Context::current(); + Context::makeCurrent(nullptr); + + CORRADE_VERIFY(!Context::hasCurrent()); + + Context::makeCurrent(¤t); + + CORRADE_VERIFY(Context::hasCurrent()); + CORRADE_COMPARE(&Context::current(), ¤t); +} + #ifndef CORRADE_TARGET_EMSCRIPTEN void ContextGLTest::multithreaded() { CORRADE_VERIFY(Context::hasCurrent()); diff --git a/src/Magnum/GL/Test/ContextTest.cpp b/src/Magnum/GL/Test/ContextTest.cpp index c521f91a5..08436619f 100644 --- a/src/Magnum/GL/Test/ContextTest.cpp +++ b/src/Magnum/GL/Test/ContextTest.cpp @@ -38,6 +38,8 @@ struct ContextTest: TestSuite::Tester { void constructNoCreate(); void constructCopyMove(); + void makeCurrentNoOp(); + void extensions(); void debugFlag(); @@ -51,6 +53,8 @@ ContextTest::ContextTest() { addTests({&ContextTest::constructNoCreate, &ContextTest::constructCopyMove, + &ContextTest::makeCurrentNoOp, + &ContextTest::extensions, &ContextTest::debugFlag, @@ -82,6 +86,12 @@ void ContextTest::constructCopyMove() { CORRADE_VERIFY(!(std::is_assignable{})); } +void ContextTest::makeCurrentNoOp() { + CORRADE_VERIFY(!Context::hasCurrent()); + Context::makeCurrent(nullptr); + CORRADE_VERIFY(!Context::hasCurrent()); +} + void ContextTest::extensions() { const char* used[GL::Implementation::ExtensionCount]{};