From 4fc958bcdabb6c702a74efea7f0efa60332215e7 Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 22 Sep 2022 12:40:54 +0100 Subject: [PATCH] NSViewComponentPeer: Avoid allocating a std::function on every frame --- .../native/juce_mac_NSViewComponentPeer.mm | 53 +++++++++++++++---- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm index c5aba97506..87c7a4d3e8 100644 --- a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm @@ -1612,6 +1612,47 @@ private: // avoid unnecessarily duplicating display-link threads. SharedResourcePointer sharedDisplayLinks; + class AsyncRepainter : private AsyncUpdater + { + public: + explicit AsyncRepainter (NSViewComponentPeer& o) : owner (o) {} + ~AsyncRepainter() override { cancelPendingUpdate(); } + + void markUpdated (const CGDirectDisplayID x) + { + { + const std::scoped_lock lock { mutex }; + + if (std::find (backgroundDisplays.cbegin(), backgroundDisplays.cend(), x) == backgroundDisplays.cend()) + backgroundDisplays.push_back (x); + } + + triggerAsyncUpdate(); + } + + private: + void handleAsyncUpdate() override + { + { + const std::scoped_lock lock { mutex }; + mainThreadDisplays = backgroundDisplays; + backgroundDisplays.clear(); + } + + for (const auto& display : mainThreadDisplays) + if (auto* peerView = owner.view) + if (auto* peerWindow = [peerView window]) + if (display == ScopedDisplayLink::getDisplayIdForScreen ([peerWindow screen])) + owner.setNeedsDisplayRectangles(); + } + + NSViewComponentPeer& owner; + std::mutex mutex; + std::vector backgroundDisplays, mainThreadDisplays; + }; + + AsyncRepainter asyncRepainter { *this }; + /* Creates a function object that can be called from an arbitrary thread (probably a CVLink thread). When called, this function object will trigger a call to setNeedsDisplayRectangles as soon as possible on the main thread, for any peers currently on the provided NSScreen. @@ -1620,17 +1661,7 @@ private: { sharedDisplayLinks->registerFactory ([this] (CGDirectDisplayID display) { - return [peerRef = WeakReference { this }, display] - { - MessageManager::callAsync ([peerRef, display] - { - if (auto* peer = peerRef.get()) - if (auto* peerView = peer->view) - if (auto* peerWindow = [peerView window]) - if (display == ScopedDisplayLink::getDisplayIdForScreen ([peerWindow screen])) - peer->setNeedsDisplayRectangles(); - }); - }; + return [this, display] { asyncRepainter.markUpdated (display); }; }) };