From ba49dcea293a2506379cceafd38621feefe0103d Mon Sep 17 00:00:00 2001 From: Aaron Colwell <300262+acolwell@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:54:32 -0700 Subject: [PATCH] Add logic to capture/restore existing GL context. This fixes asserts in debug builds where Qt's GL context is set when a ScopedGLContext is created. This can happen when we have a project open and the user tries to open another project. When the event callback is dispatched, the Qt GL context is still set. The fix justs removes the assert and adds logic to save and restore any existing GL context that is set. --- Engine/OSGLContext_win.cpp | 33 +++++++++++++++++++++++++-------- Engine/OSGLContext_win.h | 2 ++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Engine/OSGLContext_win.cpp b/Engine/OSGLContext_win.cpp index b9b78ff28..2e994c3eb 100644 --- a/Engine/OSGLContext_win.cpp +++ b/Engine/OSGLContext_win.cpp @@ -57,6 +57,18 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; NATRON_NAMESPACE_ENTER +namespace { + +bool makeDCAndContextCurrent(HDC dc, HGLRC context) +{ + const OSGLContext_wgl_data* wglInfo = appPTR->getWGLData(); + + assert(wglInfo); + return wglInfo->MakeCurrent(dc, context); +} + +} // namespace + bool OSGLContext_win::extensionSupported(const char* extension, OSGLContext_wgl_data* data) @@ -96,6 +108,7 @@ OSGLContext_win::initWGLData(OSGLContext_wgl_data* wglInfo) wglInfo->CreateContext = (WGLCREATECONTEXT_T)GetProcAddress(wglInfo->instance, "wglCreateContext"); wglInfo->DeleteContext = (WGLDELETECONTEXT_T)GetProcAddress(wglInfo->instance, "wglDeleteContext"); wglInfo->GetCurrentContext = (WGLGETCURRENTCONTEXT_T)GetProcAddress(wglInfo->instance, "wglGetCurrentContext"); + wglInfo->GetCurrentDC = (WGLGETCURRENTDC_T)GetProcAddress(wglInfo->instance, "wglGetCurrentDC"); wglInfo->GetProcAddress = (WGLGETPROCADDRESS_T)GetProcAddress(wglInfo->instance, "wglGetProcAddress"); wglInfo->MakeCurrent = (WGLMAKECURRENT_T)GetProcAddress(wglInfo->instance, "wglMakeCurrent"); wglInfo->ShareLists = (WGLSHARELISTS_T)GetProcAddress(wglInfo->instance, "wglShareLists"); @@ -606,18 +619,16 @@ OSGLContext_win::~OSGLContext_win() bool OSGLContext_win::makeContextCurrent(const OSGLContext_win* context) { - const OSGLContext_wgl_data* wglInfo = appPTR->getWGLData(); - - assert(wglInfo); if (context) { - return wglInfo->MakeCurrent(context->_dc, context->_handle); + return makeDCAndContextCurrent(context->_dc, context->_handle); } else { - return wglInfo->MakeCurrent(0, 0); + return makeDCAndContextCurrent(0, 0); } } bool -OSGLContext_win::threadHasACurrentContext() { +OSGLContext_win::threadHasACurrentContext() +{ const OSGLContext_wgl_data* wglInfo = appPTR->getWGLData(); assert(wglInfo); return wglInfo->GetCurrentContext() != nullptr; @@ -722,7 +733,11 @@ namespace { class ScopedGLContext { public: ScopedGLContext(const GLRendererID& gid) { - assert(!OSGLContext_win::threadHasACurrentContext()); + const OSGLContext_wgl_data* wglInfo = appPTR->getWGLData(); + assert(wglInfo); + _oldDc = wglInfo->GetCurrentDC(); + _oldContext = wglInfo->GetCurrentContext(); + try { _context = std::make_unique(FramebufferConfig(), GLVersion.major, GLVersion.minor, false, gid, nullptr); } catch (const std::exception& e) { @@ -737,7 +752,7 @@ class ScopedGLContext { ~ScopedGLContext() { if (_context) { - OSGLContext_win::makeContextCurrent(nullptr); + makeDCAndContextCurrent(_oldDc, _oldContext); } } @@ -745,6 +760,8 @@ class ScopedGLContext { private: std::unique_ptr _context; + HDC _oldDc = nullptr; + HGLRC _oldContext = nullptr; }; } // namespace diff --git a/Engine/OSGLContext_win.h b/Engine/OSGLContext_win.h index 862f8f65d..85906aa57 100644 --- a/Engine/OSGLContext_win.h +++ b/Engine/OSGLContext_win.h @@ -91,6 +91,7 @@ typedef PROC (WINAPI * WGLGETPROCADDRESS_T)(LPCSTR); typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC, HGLRC); typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC, HGLRC); typedef HGLRC (WINAPI * WGLGETCURRENTCONTEXT_T)(); +typedef HDC (WINAPI * WGLGETCURRENTDC_T)(); ////////// https://www.opengl.org/registry/specs/NV/gpu_affinity.txt @@ -157,6 +158,7 @@ struct OSGLContext_wgl_data WGLCREATECONTEXT_T CreateContext; WGLDELETECONTEXT_T DeleteContext; WGLGETCURRENTCONTEXT_T GetCurrentContext; + WGLGETCURRENTDC_T GetCurrentDC; WGLGETPROCADDRESS_T GetProcAddress; WGLMAKECURRENT_T MakeCurrent; WGLSHARELISTS_T ShareLists;