9 #include "flutter/fml/logging.h"
10 #import "flutter/shell/platform/darwin/common/InternalFlutterSwiftCommon/InternalFlutterSwiftCommon.h"
11 #import "flutter/shell/platform/darwin/macos/InternalFlutterSwift/InternalFlutterSwift.h"
14 #if (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE)
15 #define VSYNC_TRACING_ENABLED 1
18 #if VSYNC_TRACING_ENABLED
19 #include <OSLog/OSLog.h>
23 #define TRACE_VSYNC(event_type, baton) \
25 os_log_t log = os_log_create("FlutterVSync", "PointsOfInterest"); \
26 os_signpost_event_emit(log, OS_SIGNPOST_ID_EXCLUSIVE, event_type, "baton %lx", baton); \
29 #define TRACE_VSYNC(event_type, baton) \
42 std::optional<std::uintptr_t> _pendingBaton;
44 void (^
_block)(CFTimeInterval, CFTimeInterval, uintptr_t);
50 block:(
void (^)(CFTimeInterval timestamp,
51 CFTimeInterval targetTimestamp,
52 uintptr_t baton))block {
53 FML_DCHECK([NSThread isMainThread]);
54 if (
self = [super init]) {
67 - (void)onDisplayLink:(CFTimeInterval)timestamp targetTimestamp:(CFTimeInterval)targetTimestamp {
78 CFTimeInterval minStart = targetTimestamp -
_displayLink.nominalOutputRefreshPeriod;
79 CFTimeInterval current = CACurrentMediaTime();
82 TRACE_VSYNC(
"DisplayLinkCallback-Original", _pendingBaton.value_or(0));
84 [FlutterRunLoop.mainRunLoop
85 performAfterDelay:remaining
87 if (!_pendingBaton.has_value()) {
88 TRACE_VSYNC("DisplayLinkPaused", size_t(0));
89 _displayLink.paused = YES;
92 TRACE_VSYNC("DisplayLinkCallback-Delayed", _pendingBaton.value_or(0));
93 _block(minStart, targetTimestamp, *_pendingBaton);
94 _pendingBaton = std::nullopt;
100 - (void)waitForVSync:(uintptr_t)baton {
101 FML_DCHECK([NSThread isMainThread]);
107 CFTimeInterval now = CACurrentMediaTime();
112 if (_pendingBaton.has_value()) {
113 [FlutterLogger logWarning:@"Engine requested vsync while another was pending"];
114 _block(0, 0, *_pendingBaton);
115 _pendingBaton = std::nullopt;
118 TRACE_VSYNC(
"VSyncRequest", _pendingBaton.value_or(0));
130 CFTimeInterval start = CACurrentMediaTime();
133 CFTimeInterval delay = 0;
137 CFTimeInterval now = start;
138 start = now - (fmod(now, tick_interval)) + phase;
140 start += tick_interval;
145 [FlutterRunLoop.mainRunLoop performAfterDelay:delay
147 CFTimeInterval targetTime = start + tick_interval;
148 TRACE_VSYNC("SynthesizedInitialVSync", baton);
149 _block(start, targetTime, baton);
153 _pendingBaton = baton;
161 if (_pendingBaton.has_value()) {
162 CFTimeInterval now = CACurrentMediaTime();
163 _block(now, now, _pendingBaton.value());
164 _pendingBaton = std::nullopt;
167 [_displayLink invalidate];
FlutterDisplayLink * _displayLink
static const CFTimeInterval kTimerLatencyCompensation
#define TRACE_VSYNC(event_type, baton)
CFTimeInterval _lastTargetTimestamp
void(^ _block)(CFTimeInterval, CFTimeInterval, uintptr_t)
CFTimeInterval nominalOutputRefreshPeriod
BOOL paused
Pauses and resumes the display link.
id< FlutterDisplayLinkDelegate > delegate