diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp index caea4df965..ccb4a7fabd 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp @@ -186,12 +186,22 @@ public: { renderThread->remove (this); - if ((state.fetch_and (~StateFlags::initialised) & StateFlags::initialised) != 0) - { - context.makeActive(); - shutdownOnThread(); - OpenGLContext::deactivateCurrentContext(); - } + if ((state.fetch_and (~StateFlags::initialised) & StateFlags::initialised) == 0) + return; + + ScopedContextActivator activator; + activator.activate (context); + + if (context.renderer != nullptr) + context.renderer->openGLContextClosing(); + + if (vertexArrayObject != 0) + context.extensions.glDeleteVertexArrays (1, &vertexArrayObject); + + associatedObjectNames.clear(); + associatedObjects.clear(); + cachedImageFrameBuffer.release(); + nativeContext->shutdownOnRenderThread(); } void resume() @@ -375,12 +385,12 @@ public: abortScope = true; } - if (! contextActivator.activate (context)) - return RenderStatus::noWork; - { NativeContext::Locker locker (*nativeContext); + if (! contextActivator.activate (context)) + return RenderStatus::noWork; + JUCE_CHECK_OPENGL_ERROR doWorkWhileWaitingForLock (contextActivator); @@ -416,7 +426,7 @@ public: } } - nativeContext->swapBuffers(); + bufferSwapper.swap(); return RenderStatus::nominal; } @@ -520,9 +530,6 @@ public: paintOwner (*g); JUCE_CHECK_OPENGL_ERROR } - - if (! context.isActive()) - context.makeActive(); } JUCE_CHECK_OPENGL_ERROR @@ -667,20 +674,6 @@ public: return InitResult::success; } - void shutdownOnThread() - { - if (context.renderer != nullptr) - context.renderer->openGLContextClosing(); - - if (vertexArrayObject != 0) - context.extensions.glDeleteVertexArrays (1, &vertexArrayObject); - - associatedObjectNames.clear(); - associatedObjects.clear(); - cachedImageFrameBuffer.release(); - nativeContext->shutdownOnRenderThread(); - } - /* Returns true if the context requires a non-zero vertex array object (VAO) to be bound. If the context is a compatibility context, we can just pretend that VAOs don't exist, @@ -840,7 +833,6 @@ public: case RenderStatus::nominal: result = RenderStatus::nominal; break; case RenderStatus::messageThreadAborted: return RenderStatus::messageThreadAborted; } - } return result; @@ -950,6 +942,49 @@ public: #endif } + //============================================================================== + class BufferSwapper : private AsyncUpdater + { + public: + explicit BufferSwapper (CachedImage& img) + : image (img) {} + + ~BufferSwapper() override + { + cancelPendingUpdate(); + } + + void swap() + { + static const auto swapBuffersOnMainThread = [] + { + const auto os = SystemStats::getOperatingSystemType(); + + if ((os & SystemStats::MacOSX) != 0) + return (os != SystemStats::MacOSX && os < SystemStats::MacOSX_10_14); + + return false; + }(); + + if (swapBuffersOnMainThread && ! MessageManager::getInstance()->isThisTheMessageThread()) + triggerAsyncUpdate(); + else + image.nativeContext->swapBuffers(); + } + + private: + void handleAsyncUpdate() override + { + ScopedContextActivator activator; + activator.activate (image.context); + + NativeContext::Locker locker (*image.nativeContext); + image.nativeContext->swapBuffers(); + } + + CachedImage& image; + }; + //============================================================================== friend class NativeContext; std::unique_ptr nativeContext; @@ -977,6 +1012,7 @@ public: #endif bool textureNpotSupported = false; std::chrono::steady_clock::time_point lastMMLockReleaseTime{}; + BufferSwapper bufferSwapper { *this }; #if JUCE_MAC NSView* getCurrentView() const @@ -1055,9 +1091,6 @@ public: pendingDestruction = 1 << 2, initialised = 1 << 3, - // Flags that may change state after each frame - transient = pendingRender | paintComponents, - // Flags that should retain their state after each frame persistent = initialised | pendingDestruction };