| @@ -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; | |||