Pull Request: Fix CoreGraphicsRenderer's performance for retina display

Hi, JUCE talent team.

I sent a PullRequest to your GitHub with the following content:

I found a code that is a performance bottleneck when running on Retina Display with CoreGraphicsRenderer.
Actually, since NSHighResolutionCapable is set to true in Info.plist on Retina compatible applications, CoreGraphics seems to automatically scale internal back buffers by scale factor (factor is x2).
However, as I have seen, I recognize that there is a problem that JUCE side is doing affine transformation (scale multiplication).
I think that this implementation is the cause of the following problems that have been posted by JUCE Forum.
Drawing images on MBP Retina is ultra-slow
On the other hand, when using SoftwareRenderer, the above scaling processing is necessary.
Based on the above, I propose an implementation that does not change displayScale value
when using CoreGraphicsRenderer.

This Pull Request dramatically improves graphics performance on retina displays, which has long been an issue.
When this Pull Request is merged, it leads to solving the problem in my project.
Please check.


Thanks for the PR!

Has it been the case since the beginning or something that was broken recently ?

Thank you for your checking!
On retina display, as far as I know, this makes our project run four times faster than before.

Just to clarify, the two use cases for the getPhysicalPixelScaleFactor() method are for CachedComponentImages and Graphics::strokePath (which is called a lot).

I’m hoping this creates some magic speedup but in my preliminary tests that’s not actually been the case. I think where this will speed things up is in path creation but there will be the same number of pixels actually being pushed around as before.

I’d been keen to hear others feedback on this as macOS graphics performance has been one of our biggest areas of complaint.

not sure why is that (I don’t have the time to look at it further atm, just wanted to report) but some widgets of my plugin are now blurry with that commit.
Most of the UI is perfectly fine, but certain labels/sliders now look just like on non-retina displays.

Are you using setBufferedToImage on those elements? (I’m guessing it’s related)

1 Like

yes, that’s it!


So this means that this change had an adverse effect on setBufferedToImage on retina displays - @ed95 FYI


Thanks @yairadix. @lalala are these just standard JUCE widgets? I’ve created an empty plug-in project with some sliders and buttons, calling setBufferedToImage (true) on some of them but I can’t see any difference on a 15-inch retina MacBook Pro running 10.14.3.

@ed95 i also noticed blurry components (Juce standard Labels and Own Buttons) on a component dialog i show with setVisible() inside the plugin without using setBufferedToImage(). Other “dialogs” seems to work right with the same elements. I will try to find out more when i have some more time. Maybe the components are not aligned to the pixels somehow because of dynamic position calculation. I just don’t understand why at the moment, because this should not be an issue on retinas anymore…

1 Like

to reproduce :

  • open projucer->open example-> DSPmodulePluginDemo
  • check VST (legacy), export and open the xcode project
  • add setBufferedToImage (true); at the begining of the DspModulePluginDemoAudioProcessorEditor constructor
  • build the vst2, and open in reaper.

I tested on a 15-inch retina MacBook Pro running 10.13
(note that I haven’t tried with application or other plugin format, or with any other host)

I tried according to your report in my environment.
My environment is macOS 10.14 Mojave and DAW is Studio One.
This is a screen shot.
What you can see from this image is as follows
・Buffered component is blurred.
・Unbuffered component is not blurred (combobox’s context menu is clear).

@ed95 I am glad if it becomes helpful.

If the buffering doesn’t take the scaling into account, then it is rendered at 100%, whereas the whole GUI is displayed at 125% (or even 150% or 200%), thus the bitmap gets scaled and looks blurry.

1 Like

@ed95 It also happens when you add an effect to a child component. I added a shadow to a child component with following code:

    this->shadow = new DropShadowEffect();

It renders clean again when i comment out the component effect. The effects maybe also use the same code like setBufferedToImage. Not sure. Hope this helps.


OK, I’m going to revert this for now as it’s clearly having some unintended side effects.


Okay, I will investigate again.
If a solution is found, share it.

1 Like