I have two “flashing LEDs” - one in the upper left is a Tempo LED that blinks on the beat, while tiny ones in the lower right are Pattern LEDs that track the steps of a pattern through a step-editing grid.
As the Pattern LEDs are being driven by some subdivision of the tempo, they blink/change more often than the Tempo Led, like 4:1 as an example.
What happens is that when the the Tempo LED and a Pattern LED happen to execute a paint at the same time, even though one is in the upper left and one is in the lower right, they invalidate the entire large Rect between them, with them at the top/left and bot/right.
I gather this is a known issue since I have seen it mentioned in a few places, and indeed I finally figured out what was going on due to a mention in this thread:
I happen to have Buttons in that area that use a GlowEffect on the text, and hence are expensive to draw, which is not normally a problem as they’re just buttons that get painted when first displayed - except now every time these two LEDs line up, that area gets repainted and it makes a noticeable performance hit - which is why I started searching for the cause.
Is there any solution to this? I can see a few things to try:
- Optimize the drawing of all components in that area, and just live with it.
I tried using setBufferedToImage() on the button with the effect, and it helps - but the CPU usage still is more than double what it is if I simply disable one of the LEDs.
-
Try to delay one of them so they don’t happen at the exact same time. This actually works, but it seems hacky and problematic. And I may have other stuff blinking in the future.
-
I tried using JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS 1, according to this:
…but it changed nothing, even though I can see the modified code is being called.
=========
Furthermore, why does JUCE_ENABLE_REPAINT_DEBUGGING not work correctly? It doesn’t show what is happening at all!
I put some debug code in the same area of juce_ComponentPeer.cpp in ComponentPeer::handlePaint()
to display the clipBounds that supposedly get painted some color:
#if JUCE_ENABLE_REPAINT_DEBUGGING
#ifdef JUCE_IS_REPAINT_DEBUGGING_ACTIVE
if (JUCE_IS_REPAINT_DEBUGGING_ACTIVE)
#endif
{
// enabling this code will fill all areas that get repainted with a colour overlay, to show
// clearly when things are being repainted.
g.restoreState();
static Random rng;
g.fillAll (Colour ((uint8) rng.nextInt (255),
(uint8) rng.nextInt (255),
(uint8) rng.nextInt (255),
(uint8) 0x50));
// TEMP_FIX to display clipBounds that supposedly gets painted above
auto r = g.getClipBounds();
std::cerr << String::formatted("bounds x %03d, y %03d, w %03d, h %03d", r.getX(), r.getY(), r.getWidth(), r. getHeight()) << "\n";
}
#endif
This is the result, along with my stylized explanations:
And yet, the huge clipRegion does not color anything on the screen at all. If it did, I might not have had to spend all day figuring this out…