Browse Source

NSViewComponentPeer: Use RAII to manage display link

v7.0.9
reuk 3 years ago
parent
commit
4b94c9b54a
1 changed files with 72 additions and 29 deletions
  1. +72
    -29
      modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm

+ 72
- 29
modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm View File

@@ -242,8 +242,8 @@ public:
~NSViewComponentPeer() override
{
CVDisplayLinkStop (displayLink);
dispatch_source_cancel (displaySource);
displayLink.reset();
dispatchSource.reset();
scopedObservers.clear();
@@ -1784,47 +1784,90 @@ private:
}
//==============================================================================
void onDisplaySourceCallback()
void updateCVDisplayLinkScreen()
{
setNeedsDisplayRectangles();
const auto viewDisplayID = (CGDirectDisplayID) [[window.screen.deviceDescription objectForKey: @"NSScreenNumber"] unsignedIntegerValue];
const auto result = CVDisplayLinkSetCurrentCGDisplay (displayLink->get(), viewDisplayID);
jassertquiet (result == kCVReturnSuccess);
}
void onDisplayLinkCallback()
void createCVDisplayLink()
{
dispatch_source_merge_data (displaySource, 1);
}
dispatchSource.reset (dispatch_source_create (DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue()));
dispatch_source_set_event_handler (dispatchSource.get(), ^(){ setNeedsDisplayRectangles(); });
static CVReturn displayLinkCallback (CVDisplayLinkRef, const CVTimeStamp*, const CVTimeStamp*,
CVOptionFlags, CVOptionFlags*, void* context)
{
static_cast<NSViewComponentPeer*> (context)->onDisplayLinkCallback();
return kCVReturnSuccess;
if (@available (macOS 10.12, *))
dispatch_activate (dispatchSource.get());
else
dispatch_resume (dispatchSource.get());
displayLink.emplace (this);
}
void updateCVDisplayLinkScreen()
struct DisplayLinkDestructor
{
auto viewDisplayID = (CGDirectDisplayID) [[window.screen.deviceDescription objectForKey: @"NSScreenNumber"] unsignedIntegerValue];
auto result = CVDisplayLinkSetCurrentCGDisplay (displayLink, viewDisplayID);
jassertquiet (result == kCVReturnSuccess);
}
void operator() (CVDisplayLinkRef ptr) const
{
if (ptr != nullptr)
CVDisplayLinkRelease (ptr);
}
};
void createCVDisplayLink()
class ScopedDisplayLink
{
displaySource = dispatch_source_create (DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
dispatch_source_set_event_handler (displaySource, ^(){ onDisplaySourceCallback(); });
dispatch_resume (displaySource);
public:
explicit ScopedDisplayLink (NSViewComponentPeer* owner)
{
const auto callback = [] (CVDisplayLinkRef,
const CVTimeStamp*,
const CVTimeStamp*,
CVOptionFlags,
CVOptionFlags*,
void* context) -> int
{
dispatch_source_merge_data (static_cast<NSViewComponentPeer*> (context)->dispatchSource.get(), 1);
return kCVReturnSuccess;
};
auto cvReturn = CVDisplayLinkCreateWithActiveCGDisplays (&displayLink);
jassertquiet (cvReturn == kCVReturnSuccess);
const auto callbackResult = CVDisplayLinkSetOutputCallback (link.get(), callback, owner);
jassertquiet (callbackResult == kCVReturnSuccess);
cvReturn = CVDisplayLinkSetOutputCallback (displayLink, &displayLinkCallback, this);
jassertquiet (cvReturn == kCVReturnSuccess);
const auto startResult = CVDisplayLinkStart (link.get());
jassertquiet (startResult == kCVReturnSuccess);
}
CVDisplayLinkStart (displayLink);
}
~ScopedDisplayLink()
{
CVDisplayLinkStop (link.get());
}
CVDisplayLinkRef get() const { return link.get(); }
private:
std::unique_ptr<std::remove_pointer_t<CVDisplayLinkRef>, DisplayLinkDestructor> link
{
[]
{
CVDisplayLinkRef ptr = nullptr;
const auto result = CVDisplayLinkCreateWithActiveCGDisplays (&ptr);
jassertquiet (result == kCVReturnSuccess);
jassertquiet (ptr != nullptr);
return ptr;
}()
};
};
struct DispatchSourceDestructor
{
void operator() (dispatch_source_t ptr) const
{
if (ptr != nullptr)
dispatch_source_cancel (ptr);
}
};
CVDisplayLinkRef displayLink = nullptr;
dispatch_source_t displaySource = nullptr;
Optional<ScopedDisplayLink> displayLink;
std::unique_ptr<std::remove_pointer_t<dispatch_source_t>, DispatchSourceDestructor> dispatchSource;
int numFramesToSkipMetalRenderer = 0;
std::unique_ptr<CoreGraphicsMetalLayerRenderer<NSView>> metalRenderer;


Loading…
Cancel
Save