From 84eed04a59d475815f396bfc759c3d645312b8f9 Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 15 May 2025 19:18:54 +0100 Subject: [PATCH] Component: Add function to clear all cached image resources In the DemoRunner, switching to and fro between the Settings tab and the Demo tab displaying the OpenGL demo could lead to GL_INVALID_OPERATION errors. This is because closing the demo shuts down the GL context, destroying resources such as framebuffers. If any Image objects backed by framebuffers outlive the context, they will be invalidated. Component effect images are especially likely to hold onto invalid framebuffer references. With this change in place, images cached by Components will be invalidated when the attached GL context goes out of scope, and will be recreated when the new context is created. --- .../juce_gui_basics/components/juce_Component.cpp | 14 ++++++++++++++ .../juce_gui_basics/components/juce_Component.h | 3 +++ .../juce_gui_basics/detail/juce_ComponentHelpers.h | 3 +-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/modules/juce_gui_basics/components/juce_Component.cpp b/modules/juce_gui_basics/components/juce_Component.cpp index ebe96af1a6..de5d682ab6 100644 --- a/modules/juce_gui_basics/components/juce_Component.cpp +++ b/modules/juce_gui_basics/components/juce_Component.cpp @@ -247,6 +247,11 @@ public: effect->applyEffect (effectImage, g, scale, ignoreAlphaLevel ? 1.0f : c.getAlpha()); } + void releaseResources() + { + effectImage = {}; + } + private: Image effectImage; ImageEffectFilter* effect; @@ -613,6 +618,15 @@ void Component::setBufferedToImage (bool shouldBeBuffered) } } +void Component::invalidateCachedImageResources() +{ + if (cachedImage != nullptr) + cachedImage->releaseResources(); + + if (effectState != nullptr) + effectState->releaseResources(); +} + //============================================================================== void Component::reorderChildInternal (int sourceIndex, int destIndex) { diff --git a/modules/juce_gui_basics/components/juce_Component.h b/modules/juce_gui_basics/components/juce_Component.h index bcffc5653d..0543b3869a 100644 --- a/modules/juce_gui_basics/components/juce_Component.h +++ b/modules/juce_gui_basics/components/juce_Component.h @@ -2504,6 +2504,9 @@ public: */ CachedComponentImage* getCachedComponentImage() const noexcept { return cachedImage.get(); } + /** Invalidates cached images, both in the CachedComponentImage (if any) and the image effect state. */ + void invalidateCachedImageResources(); + /** Sets a flag to indicate whether mouse drag events on this Component should be ignored when it is inside a Viewport with drag-to-scroll functionality enabled. This is useful for Components such as sliders that should not move when their parent Viewport when dragged. diff --git a/modules/juce_gui_basics/detail/juce_ComponentHelpers.h b/modules/juce_gui_basics/detail/juce_ComponentHelpers.h index f63c11b12d..65b2e41978 100644 --- a/modules/juce_gui_basics/detail/juce_ComponentHelpers.h +++ b/modules/juce_gui_basics/detail/juce_ComponentHelpers.h @@ -237,8 +237,7 @@ struct ComponentHelpers static void releaseAllCachedImageResources (Component& c) { - if (auto* cached = c.getCachedComponentImage()) - cached->releaseResources(); + c.invalidateCachedImageResources(); for (auto* child : c.childComponentList) releaseAllCachedImageResources (*child);