Slider keeps getting redrawn


#1

For some reason, one of the sliders in my plugin keeps getting redrawn and I can’t figure out why. I’ve checked to see if the value is changing without my knowing but that’s not the case.

Are there any debugging steps I can take to find out why it’s getting redrawn?


#2

I had this problem and then noticed one of my components that is constantly repainting was not set to setOpaque(true).

Could it be something as easy as that?


#3

I just downloaded and ran Quartz Debug and turned on Flash Screen updates and that showed me that two little LED indicators I have on my panel which are updated at 30Hz are the cause. It looks like Quartz or JUCE is making a dirty rectangle bounding the two LEDs and a couple of sliders are in that bounding box, so they get redrawn as well.

What I don’t understand is why the dirty rectangle is so large (the rectangle enclosing both LEDs), considering that the LEDs are only 10x10 pixels.

Any ideas?


#4

I encountered a very similar issue last year, and nothing I have attempted so far has fixed it.

Apparently it is a shortcoming of CoreGraphics, as Jules explains in this thread:

I assume this is the problem you are encountering. I tried using the JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS macro but it didn’t reduce the number of unnecessary repaints - perhaps I am doing something wrong or misunderstanding.

This is a huge issue for me, as I have many sliders placed between meters in my plugin UI. They repaint so frequently that it spikes my CPU usage in macOSX. I have even considered a major UI redesign simply due to this issue, but it would be an unfortunate compromise. Everything works as it should on Windows.


#5

Use OpenGL renderer ?


#6

Can you quantify this? I have on average about 8 to 16 mixer channels with faders and meters in my plugin (with the ability to have many more) and I’m not seeing a huge CPU spike on MacOS – I see far more issues in Windows in Pro Tools with slow WM_PAINT updates… but overall my plugin has the lowest CPU use in comparison to similar other plugins in it’s class.

Rail


#7

Hi Rail

I will check on the mac I have again at some point, but it was very substantial. The CPU hit due to graphics far outweighed that of the audio processing. This was mostly due to the fact that I had a large input and output meter on either side of my plugin and a variety of sliders and knobs in between them. This resulted in all or most of the sliders being repainted every time the meters were repainted. My slider did include shadows which were very CPU intensive.

Also note, I was testing using Ableton Live. The CPU hit due to graphics does not register on the CPU meter within Live. I had to open the activity monitor and profile the plugin in order to get a full picture of the CPU usage.


#8

What’s your Timer set to? You can try changing the refresh rate

Rail


#9

I have experimented with different times, even going low enough for the meters to appear very unresponsive. Currently the Timer is set to 30 Hz. The issue is that the sliders keep getting redrawn when they really don’t need to be. My Windows version is working smoothly without any exaggerated CPU hit. As Jules stated in the thread I linked, it is a specific issue with macOSX.

I haven’t been able to work on it for a while now, but when I get time I will revisit some proposed solutions and attempt to fix it.


#10

Also note, I haven’t updated to the latest Juce code yet, but when I have a chance to download the latest development branch and retest I will report back.


#11

I’m on JUCE 4.0.2… the last version before they changed the MultiBus

In Live 9 it shows 3 to 4 percent and in Activity Monitor 37%

Try setting your meters to opaque, have them in their own Component, and when using repaint use a version which sets a subsection/rectangle.

I’ll PM you a video clip.

Rail


#13

Thanks Rail. I have done all of those things. The only one that helped in any way was only repainting the updated portions of the meters instead of the whole meter each time.

Have you profiled your code to see how often the sliders, buttons etc are repainted? Are they only repainted when they have been altered in some way or are there times when they repaint unnecessarily?


#14

Enabling JUCE_ENABLE_REPAINT_DEBUGGING in AppConfig.h, my meters are the only Components getting repainted. This is on MacOS 10.11.6

Rail


#15

JUCE_ENABLE_REPAINT_DEBUGGING is a bit more complicated than that because CoreGraphics keeps its own complex clipping region. This means that it may present the combined clip rect to JUCE, causing it to call all of the paint methods down to the the CoreGraphics calls, however CoreGraphics will only draw the actual pixels it knows internally are dirty. If you put DBG statements in component paint calls that lie in between you may well still see them being printed out.

Using JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS aims to reduce the number of paint calls simply caught up in the clipping rect but it then has the disadvantage of having to traverse the whole Component hierarchy etc. multiple times. This also has a cost associated with it.

This essentially means that you have to weigh up how much work is done in your own paint methods compared to how long CoreGraphics takes to perform the drawing routines. Minimising work done in paint routines that will never result in things actually getting drawn is one way to improve on this (e.g. use a GlyphArrangement rather than lots of drawText calls to essentially cache all the path calculations).

As always though, be sure to profile to avoid making your drawing code needlessly complex for very little benefit.


#16

true… we never asked how he’s actually drawing his meters. All my backgrounds and meters are cached Images and my Sliders don’t have any backgrounds to paint.

Rail


#17

My plugin shows the exact same when using JUCE_ENABLE_REPAINT_DEBUGGING. Only my meters are shown to be repainted. However when I profiled my plugin I noticed that the sliders in between the meters were also being repainted. Try using Quarts debug to see what regions are actually being repainted - my assumption would be the entire slider/meter region at the bottom of your app.

The repainting of my meters is cheap, but the sliders in between initially consumed a lot of CPU due to shadows etc - the thought being that they would only be repainted when altered. I have indeed tried to minimise the wrk done in these paint routines to reduce this cost. Still not close to ideal though.


#18

Try and build the paint graphics into Image objects… then just draw the Image in your paint(). I posted in another thread recently about doing that.

Rail


#19

For the sliders and buttons etc? Thank, I will try and find your post and give it a shot.


#20

Rail


#21

…and instead of lazy creating it in the paint you could move the drawing code for the background into the resize method (or call it from there)…
That way your background image fits always the bounds…