Repaint() weirdness


#1

In my plugin a Timer is called every 20ms and repaints some component (VU Meter) with repaint(). On my IBook G4, this takes much CPU time. In fact, when the plugin is open as 5 instances, the CPU is at 80%.
What is weird about it, is that the CPU Time seems to be consumed by repaint() itself, no by the paint() method of the VU Meter Component. Even if I just return from the paint() method directly, it still takes the CPU time.
Is this normal (on Mac) ?


#2

If you return from paint(), it still paints the component, so all the stuff associated with getting an off-screen image, clearing it, calling the paint methods, copying it to the screen, etc still has to happen. That’s the slow bit on an old G4, not the painting itself.


#3

hmm ok. i see, is there no possibility to speed up things?


#4

The G4 is just slow when using the newer drawing methods needed in 10.4 and later. It used to be fast enough with quickdraw, but that’s deprecated now.


#5

Is it also normal that repaint() or paint() still takes as much CPU on a component if the component is not visible (has been set to hidden using setVisible(false) )?

Edit: seems rather impossible to me because flags.visibleFlag is checked by repaint(), but something is still taking CPU on OS X, perhaps it is the repainting of other components, I must check further.
What I also noticed, is that when I move my JUCE window out of the screen, the CPU usage goes up. I seems like everything that is painted outside of the screen takes more CPU on OSX !? In Windows it is just the contrary…


#6

That all sounds a bit strange, more likely you’re misinterpreting something, I’d say. On OSX though, if a window is off-screen I think it might all still get rendered, because the OS often keeps the whole thing in a buffer.


#7

I think I now know where the problem is: In my application I have different Mixer Channels. Those Mixer Channels contain some Level Meters, which are graphically updated every 20ms (timer callback calls repaint() ). I thought, that if a Mixer Channel is not visible (but still exists), repaint() on its child components will have no effect (just as if they would be not visible), since their parent is not visible and so they aren’t visible either.
But exactly this seems not to be true. It would be nice if repaint() would not only check if the component itself is invisible and then skip repainting, but also check if one of its ancestors is not visible and skip repainting.


#8

nope, it won’t repaint if it’s not entirely visible - check out juce_Component.cpp, line 1672.


#9

Doh! Yes, didn’t see that. Found out what it was anyway, the problem arised due to my modified Timer (OS X Timer based class), which always fired the Timers with no waiting (not like JUCE Timers that always wait before firing):

instead of (this is the correct version):

InstallEventLoopTimer(GetMainEventLoop(), kEventDurationMillisecond*milliseconds, kEventDurationMillisecond*milliseconds, timerUPP, (void*)timer,&ref);

Performance-wise, I don’t notice much difference between Windows and OS X (Intel) anymore on the same machine for my JUCE app.

BTW, I wanted to use the “Shark” Performance Analysis Tool in XCode, but it’s always grayed out, so I can’t choose it, even not in Debug config. Is there some special trick to activate it?