From f63d0456766922ef596f3c7a35d6ada3c21fa58e Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 19 Apr 2020 15:28:59 +0200 Subject: [PATCH] OpenGL: Better handling for activation/desactivation --- .../Nazara/OpenGLRenderer/Wrapper/Context.hpp | 9 ++- .../Wrapper/Win32/WGLContext.hpp | 5 +- src/Nazara/OpenGLRenderer/Wrapper/Context.cpp | 39 +++++++++- .../Wrapper/Win32/WGLContext.cpp | 77 +++++++------------ 4 files changed, 76 insertions(+), 54 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp index 9dd6a868e..f808e5aa3 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp @@ -56,17 +56,24 @@ namespace Nz::GL NAZARA_OPENGLRENDERER_FOREACH_GLES_FUNC(NAZARA_OPENGLRENDERER_FUNC) #undef NAZARA_OPENGLRENDERER_FUNC + static const Context* GetCurrentContext(); + static bool SetCurrentContext(const Context* context); + protected: + virtual bool Activate() const = 0; + virtual void Desactivate() const = 0; virtual const Loader& GetLoader() = 0; virtual bool ImplementFallback(const std::string_view& function); - std::unordered_set m_supportedExtensions; + static void NotifyContextDestruction(Context* context); + ContextParams m_params; private: void GL_APIENTRY HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) const; + std::unordered_set m_supportedExtensions; }; } diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Win32/WGLContext.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Win32/WGLContext.hpp index 3280f7a28..7c300a92c 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Win32/WGLContext.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Win32/WGLContext.hpp @@ -31,8 +31,6 @@ namespace Nz::GL WGLContext(WGLContext&&) = delete; ~WGLContext(); - bool Activate() override; - bool Create(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext = nullptr); bool Create(const WGLContext* baseContext, const ContextParams& params, WindowHandle window, const WGLContext* shareContext = nullptr); void Destroy(); @@ -50,7 +48,8 @@ namespace Nz::GL bool CreateInternal(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext = nullptr); bool ImplementFallback(const std::string_view& function) override; - void Desactivate(); + bool Activate() const override; + void Desactivate() const override; const Loader& GetLoader() override; bool LoadWGLExt(); bool SetPixelFormat(); diff --git a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp index a431a9c72..5ef19ecf1 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp @@ -23,10 +23,10 @@ namespace Nz::GL const Loader& loader = GetLoader(); - auto LoadSymbol = [&](auto& func, const char* funcName) + auto LoadSymbol = [&](auto& func, const char* funcName, bool mandatory) { func = reinterpret_cast>(loader.LoadFunction(funcName)); - if (!func && !ImplementFallback(funcName) && !func) //< Not a mistake + if (!func && !ImplementFallback(funcName) && !func && mandatory) //< Not a mistake throw std::runtime_error("failed to load core function " + std::string(funcName)); }; @@ -114,6 +114,34 @@ namespace Nz::GL return true; } + const Context* Context::GetCurrentContext() + { + return s_currentContext; + } + + bool Context::SetCurrentContext(const Context* context) + { + const Context*& currentContext = s_currentContext; //< Pay TLS cost only once + if (currentContext == context) + return true; + + if (currentContext) + { + currentContext->Desactivate(); + currentContext = nullptr; + } + + if (context) + { + if (!context->Activate()) + return false; + + currentContext = context; + } + + return true; + } + bool Context::ImplementFallback(const std::string_view& function) { const Loader& loader = GetLoader(); @@ -135,6 +163,13 @@ namespace Nz::GL return false; } + void Context::NotifyContextDestruction(Context* context) + { + const Context*& currentContext = s_currentContext; //< Pay TLS cost only once + if (currentContext == context) + currentContext = nullptr; + } + void Context::HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) const { std::stringstream ss; diff --git a/src/Nazara/OpenGLRenderer/Wrapper/Win32/WGLContext.cpp b/src/Nazara/OpenGLRenderer/Wrapper/Win32/WGLContext.cpp index c354032db..d732a5da6 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/Win32/WGLContext.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/Win32/WGLContext.cpp @@ -12,8 +12,6 @@ namespace Nz::GL { - thread_local WGLContext* s_currentContext = nullptr; - GL::WGLContext::WGLContext(const WGLLoader& loader) : m_loader(loader) { @@ -24,30 +22,6 @@ namespace Nz::GL Destroy(); } - bool WGLContext::Activate() - { - WGLContext*& currentContext = s_currentContext; //< Pay TLS cost only once - if (currentContext) - { - if (currentContext == this) - return true; - - // Only one context can be activated per thread - currentContext->Desactivate(); - } - - bool succeeded = m_loader.wglMakeCurrent(m_deviceContext, m_handle); - if (!succeeded) - { - NazaraError("failed to activate context: " + Error::GetLastSystemError()); - return false; - } - - currentContext = this; - - return true; - } - bool WGLContext::Create(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext) { // Creating a context requires a device context, create window to get one @@ -79,9 +53,7 @@ namespace Nz::GL { if (m_handle) { - WGLContext*& currentContext = s_currentContext; //< Pay TLS cost only once - if (currentContext == this) - currentContext = nullptr; + NotifyContextDestruction(this); m_loader.wglDeleteContext(m_handle); m_handle = nullptr; @@ -139,8 +111,8 @@ namespace Nz::GL } std::array attributes = { - WGL_CONTEXT_MAJOR_VERSION_ARB, version.major, - WGL_CONTEXT_MINOR_VERSION_ARB, version.minor, + WGL_CONTEXT_MAJOR_VERSION_ARB, int(version.major), + WGL_CONTEXT_MINOR_VERSION_ARB, int(version.minor), WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB | WGL_CONTEXT_ES_PROFILE_BIT_EXT }; @@ -180,8 +152,8 @@ namespace Nz::GL } std::array attributes = { - WGL_CONTEXT_MAJOR_VERSION_ARB, version.major, - WGL_CONTEXT_MINOR_VERSION_ARB, version.minor, + WGL_CONTEXT_MAJOR_VERSION_ARB, int(version.major), + WGL_CONTEXT_MINOR_VERSION_ARB, int(version.minor), WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB }; @@ -243,22 +215,31 @@ namespace Nz::GL glClearDepthf = [](GLfloat depth) { - assert(s_currentContext); - s_currentContext->fallbacks.glClearDepth(depth); + const WGLContext* context = static_cast(GetCurrentContext()); + assert(context); + context->fallbacks.glClearDepth(depth); }; } return true; } - void WGLContext::Desactivate() + bool WGLContext::Activate() const { - WGLContext*& currentContext = s_currentContext; //< Pay TLS cost only once - if (currentContext == this) + bool succeeded = m_loader.wglMakeCurrent(m_deviceContext, m_handle); + if (!succeeded) { - m_loader.wglMakeCurrent(nullptr, nullptr); - currentContext = nullptr; + NazaraError("failed to activate context: " + Error::GetLastSystemError()); + return false; } + + return true; + } + + void WGLContext::Desactivate() const + { + assert(GetCurrentContext() == this); + m_loader.wglMakeCurrent(nullptr, nullptr); } const Loader& WGLContext::GetLoader() @@ -308,7 +289,7 @@ namespace Nz::GL int pixelFormat = 0; if (m_params.sampleCount > 1) { - WGLContext* currentContext = s_currentContext; //< Pay TLS cost only once + const WGLContext* currentContext = static_cast(GetCurrentContext()); //< Pay TLS cost only once if (currentContext) { // WGL_ARB_pixel_format and WGL_EXT_pixel_format are the same, except for the symbol @@ -320,13 +301,13 @@ namespace Nz::GL WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, - WGL_COLOR_BITS_ARB, (m_params.bitsPerPixel == 32) ? 24 : m_params.bitsPerPixel, - WGL_ALPHA_BITS_ARB, (m_params.bitsPerPixel == 32) ? 8 : 0, - WGL_DEPTH_BITS_ARB, m_params.depthBits, - WGL_STENCIL_BITS_ARB, m_params.stencilBits, - WGL_DOUBLE_BUFFER_ARB, (m_params.doubleBuffering) ? GL_TRUE : GL_FALSE, + WGL_COLOR_BITS_ARB, int((m_params.bitsPerPixel == 32) ? 24 : m_params.bitsPerPixel), + WGL_ALPHA_BITS_ARB, int((m_params.bitsPerPixel == 32) ? 8 : 0), + WGL_DEPTH_BITS_ARB, int(m_params.depthBits), + WGL_STENCIL_BITS_ARB, int(m_params.stencilBits), + WGL_DOUBLE_BUFFER_ARB, int((m_params.doubleBuffering) ? GL_TRUE : GL_FALSE), WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, - WGL_SAMPLES_ARB, m_params.sampleCount + WGL_SAMPLES_ARB, int(m_params.sampleCount) }; int& sampleCount = attributes[attributes.size() - 3]; @@ -344,7 +325,7 @@ namespace Nz::GL } while (sampleCount > 1); - if (m_params.sampleCount != sampleCount) + if (int(m_params.sampleCount) != sampleCount) NazaraWarning("couldn't find a pixel format matching " + std::to_string(m_params.sampleCount) + " sample count, using " + std::to_string(sampleCount) + " sample(s) instead"); m_params.sampleCount = sampleCount;