diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp index fce1b76342..5593afb88a 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp @@ -91,6 +91,44 @@ static bool contextHasTextureNpotFeature() class OpenGLContext::CachedImage : public CachedComponentImage, private ThreadPoolJob { + struct AreaAndScale + { + Rectangle area; + double scale; + + auto tie() const { return std::tie (area, scale); } + + auto operator== (const AreaAndScale& other) const { return tie() == other.tie(); } + auto operator!= (const AreaAndScale& other) const { return tie() != other.tie(); } + }; + + class LockedAreaAndScale + { + public: + auto get() const + { + const ScopedLock lock (mutex); + return data; + } + + template + void set (const AreaAndScale& d, Fn&& ifDifferent) + { + const auto old = [&] + { + const ScopedLock lock (mutex); + return std::exchange (data, d); + }(); + + if (old != d) + ifDifferent(); + } + + private: + CriticalSection mutex; + AreaAndScale data { {}, 1.0 }; + }; + public: CachedImage (OpenGLContext& c, Component& comp, const OpenGLPixelFormat& pixFormat, void* contextToShare) @@ -205,8 +243,10 @@ public: } //============================================================================== - bool ensureFrameBufferSize() + bool ensureFrameBufferSize (Rectangle viewportArea) { + JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED + auto fbW = cachedImageFrameBuffer.getWidth(); auto fbH = cachedImageFrameBuffer.getHeight(); @@ -276,10 +316,13 @@ public: doWorkWhileWaitingForLock (true); + const auto currentAreaAndScale = areaAndScale.get(); + const auto viewportArea = currentAreaAndScale.area; + if (context.renderer != nullptr) { glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight()); - context.currentRenderScale = scale; + context.currentRenderScale = currentAreaAndScale.scale; context.renderer->renderOpenGL(); clearGLError(); @@ -290,7 +333,7 @@ public: { if (isUpdating) { - paintComponent(); + paintComponent (currentAreaAndScale); if (! hasInitialised) return false; @@ -331,7 +374,7 @@ public: return [window backingScaleFactor]; } - return scale; + return areaAndScale.get().scale; }(); #else const auto displayScale = Desktop::getInstance().getDisplays().getDisplayForRect (component.getTopLevelComponent()->getScreenBounds())->scale; @@ -350,10 +393,9 @@ public: auto newScale = displayScale; #endif - if (scale != newScale || viewportArea != newArea) + areaAndScale.set ({ newArea, newScale }, [&] { - scale = newScale; - viewportArea = newArea; + // Transform is only accessed when the message manager is locked transform = AffineTransform::scale ((float) newArea.getWidth() / (float) localBounds.getWidth(), (float) newArea.getHeight() / (float) localBounds.getHeight()); @@ -361,7 +403,7 @@ public: if (canTriggerUpdate) invalidateAll(); - } + }); } } @@ -383,17 +425,19 @@ public: } } - void paintComponent() + void paintComponent (const AreaAndScale& currentAreaAndScale) { + JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED + // you mustn't set your own cached image object when attaching a GL context! jassert (get (component) == this); - if (! ensureFrameBufferSize()) + if (! ensureFrameBufferSize (currentAreaAndScale.area)) return; - RectangleList invalid (viewportArea); + RectangleList invalid (currentAreaAndScale.area); invalid.subtract (validArea); - validArea = viewportArea; + validArea = currentAreaAndScale.area; if (! invalid.isEmpty()) { @@ -580,7 +624,8 @@ public: bindVertexArray(); } - glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight()); + const auto currentViewportArea = areaAndScale.get().area; + glViewport (0, 0, currentViewportArea.getWidth(), currentViewportArea.getHeight()); nativeContext->setSwapInterval (1); @@ -710,10 +755,10 @@ public: Version openGLVersion; OpenGLFrameBuffer cachedImageFrameBuffer; RectangleList validArea; - Rectangle viewportArea, lastScreenBounds; - double scale = 1.0; + Rectangle lastScreenBounds; AffineTransform transform; GLuint vertexArrayObject = 0; + LockedAreaAndScale areaAndScale; StringArray associatedObjectNames; ReferenceCountedArray associatedObjects;