From 44816941fce7644083171ca8c5b98f0005de3061 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 25 Apr 2018 10:57:57 -0700 Subject: [PATCH] Fix debug assert in manipulating thread local data to store GL surfaces --- libraries/gl/src/gl/OffscreenGLCanvas.cpp | 45 +++++++++++++++++++---- libraries/gl/src/gl/OffscreenGLCanvas.h | 2 + 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp index 4a2c5fd7f7..91f7954943 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp +++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp @@ -17,15 +17,18 @@ #include #include #include +#include +#include #include #include #include +#include + #include "Context.h" #include "GLHelpers.h" #include "GLLogging.h" - OffscreenGLCanvas::OffscreenGLCanvas() : _context(new QOpenGLContext), _offscreenSurface(new QOffscreenSurface) @@ -33,6 +36,8 @@ OffscreenGLCanvas::OffscreenGLCanvas() : } OffscreenGLCanvas::~OffscreenGLCanvas() { + clearThreadContext(); + // A context with logging enabled needs to be current when it's destroyed _context->makeCurrent(_offscreenSurface); delete _context; @@ -117,25 +122,51 @@ QObject* OffscreenGLCanvas::getContextObject() { } void OffscreenGLCanvas::moveToThreadWithContext(QThread* thread) { + clearThreadContext(); moveToThread(thread); _context->moveToThread(thread); } -static const char* THREAD_CONTEXT_PROPERTY = "offscreenGlCanvas"; +struct ThreadContextStorage : public Dependency { + QThreadStorage> threadContext; +}; void OffscreenGLCanvas::setThreadContext() { - QThread::currentThread()->setProperty(THREAD_CONTEXT_PROPERTY, QVariant::fromValue(this)); + if (!DependencyManager::isSet()) { + DependencyManager::set(); + } + auto threadContextStorage = DependencyManager::get(); + QPointer p(this); + threadContextStorage->threadContext.setLocalData(p); +} + +void OffscreenGLCanvas::clearThreadContext() { + if (!DependencyManager::isSet()) { + return; + } + auto threadContextStorage = DependencyManager::get(); + if (!threadContextStorage->threadContext.hasLocalData()) { + return; + } + auto& threadContext = threadContextStorage->threadContext.localData(); + if (this != threadContext.operator OffscreenGLCanvas *()) { + return; + } + threadContextStorage->threadContext.setLocalData(nullptr); } bool OffscreenGLCanvas::restoreThreadContext() { // Restore the rendering context for this thread - auto threadCanvasVariant = QThread::currentThread()->property(THREAD_CONTEXT_PROPERTY); - if (!threadCanvasVariant.isValid()) { + if (!DependencyManager::isSet()) { return false; } - auto threadCanvasObject = qvariant_cast(threadCanvasVariant); - auto threadCanvas = static_cast(threadCanvasObject); + auto threadContextStorage = DependencyManager::get(); + if (!threadContextStorage->threadContext.hasLocalData()) { + return false; + } + + auto threadCanvas = threadContextStorage->threadContext.localData(); if (!threadCanvas) { return false; } diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.h b/libraries/gl/src/gl/OffscreenGLCanvas.h index ed644b98fb..a4960ae234 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.h +++ b/libraries/gl/src/gl/OffscreenGLCanvas.h @@ -39,6 +39,8 @@ private slots: void onMessageLogged(const QOpenGLDebugMessage &debugMessage); protected: + void clearThreadContext(); + std::once_flag _reportOnce; QOpenGLContext* _context{ nullptr }; QOffscreenSurface* _offscreenSurface{ nullptr };