Slider keeps getting redrawn

Use OpenGL renderer ?

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

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.

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

Rail

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.

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.

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

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?

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

Rail

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.

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

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.

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

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

Rail

…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…

My background is drawn in the resize method and never repainted unnecessarily. It is the sliders and buttons that are repainted unnecessarily. Perhaps I am misunderstanding your comment?

Sorry, was only an addition to @Rail_Jon_Rogut’s suggestion for creating the background into an image. He didn’t say where to call his createNewBackground() method. There are two ways,

  1. in paint:

    if (getWidth() != m_Background.getWidth() || getHeight() != m_Background.getHeight())
    createNewBackground();

  2. in resized:

    createNewBackground();

because resized is only called when the bounds (probably) changed, you don’t need that check, if the size changed…
That was all, nothing important really :wink:

Edit: Checking the context again, completely my bad… sorry… you were talking about sliders, it belongs rather to the meters thread! Best ignore me :wink:

I see, sorry about that!

Just for clarification… My example is showing using the methodology for the background… This same approach can be used for any graphic element to reduce redrawing the same thing unnecessarily.

In my example case the createNewBackground() is actually called from when a new groove variation is selected and if the length of the groove is different to the previously loaded variation – it can actually be seen in use in the video I posted above around 0:12.

Cheers,

Rail