Would I be correct in thinking your animated component is a child of a background component that has setBufferedToImage (true) called on it? If I’m mistaken then everything below may be irrelevant, please let me know.
If a component has children then they will become part of the buffered image too, see the docs.
Setting this flag to true will cause the component to allocate an
internal buffer into which it paints itself and all its child components, so that
when asked to redraw itself, it can use this buffer rather than actually calling
the paint() method.
Parts of the buffer are invalidated when repaint() is called on this component
or its children. The buffer is then repainted at the next paint() callback.
When you mark the child component as opaque JUCE realises it only needs to update that part of the image, which means it only needs to redraw your animated component. When there is a transform applied there could be some interpolation between edges of components so it will need to draw the background component in order to properly update the image.
What you probably want to do, is to not add the animated component as a child component, instead add it as a sibling component.
If you can use the latest version of JUCE we actually have a demo of this in the DemoRunner under GUI >> ComponentDiagnosticsDemo. Once you select the demo you will be able to compare a number of components, select Expensive (buffered to image) with child and Expensive (buffered to image) with sibling. I’ve included a video below.
To go from child to sibling components it might look something like this…
Before
class AnimatedComponent : public juce::Component,
private juce::Timer
{
public:
AnimatedComponent()
{
startTimerHz (60);
}
~AnimatedComponent()
{
stopTimer();
}
void paint (juce::Graphics& g) override
{
// implement something that animates here
}
private:
void timerCallback() override
{
repaint();
}
};
class BackgroundComponent : public juce::Component
{
public:
BackgroundComponent()
{
addAndMakeVisible (animatedComponent);
setBufferedToImage (true);
}
void paint (juce::Graphics& g) override
{
// implement some expensive background drawing here
}
void resized() override
{
animatedComponent.setSize (/* set it's size to whatever here */);
}
private:
AnimatedComponent animatedComponent;
};
After
// Use the same AnimatedComponent class
class BackgroundComponent : public juce::Component
{
public:
BackgroundComponent()
{
// don't need to add a child component any more
setBufferedToImage (true);
}
void paint (juce::Graphics& g) override
{
// implement some expensive background drawing here
}
};
// this component will not implement any drawing
class ContainerComponent : public juce::Component
{
public:
ContainerComponent()
{
addAndMakeVisible (background);
// note because the animatedComponent is after the background,
// it will still be on top just as it would if it were a child of background
addAndMakeVisible (animatedComponent);
}
void resized() override
{
background.setBounds (getLocalBounds());
animatedComponent.setBounds (/* set it's size to whatever here */);
}
private:
BackgroundComponent background;
AnimatedComponent animatedComponent;
}
In the example above ContainerComponent would be acting like your BackgroundComponent does now. In general I recommend that components either
That is, there wouldn’t normally be any components that do both. This way when you call setBufferedToImage (true) on a component you shouldn’t have to worry about any child components because there won’t be any!
Also if you are able to check out the latest version of JUCE we’ve spent some time improving drawing performance around these kinds of areas. Something of note, if you have any components you are marking as opaque, if they are not actually obscuring other components entirely, then I suggest not marking them opaque any more. In general only use opaque when you measure it to be a performance boost (I realise you did in your case but once you make the changes suggested above I doubt you’ll see a performance boost any more).
Hope that helps.