5 #include "flutter/fml/logging.h"
10 #if (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE)
11 #define VSYNC_TRACING_ENABLED 1
14 #if VSYNC_TRACING_ENABLED
15 #include <OSLog/OSLog.h>
19 #define TRACE_VSYNC(event_type, baton) \
21 os_log_t log = os_log_create("FlutterVSync", "PointsOfInterest"); \
22 os_signpost_event_emit(log, OS_SIGNPOST_ID_EXCLUSIVE, event_type, "baton %lx", baton); \
25 #define TRACE_VSYNC(event_type, baton) \
38 std::optional<std::uintptr_t> _pendingBaton;
40 void (^
_block)(CFTimeInterval, CFTimeInterval, uintptr_t);
46 block:(
void (^)(CFTimeInterval timestamp,
47 CFTimeInterval targetTimestamp,
48 uintptr_t baton))block {
49 FML_DCHECK([NSThread isMainThread]);
50 if (
self = [super init]) {
63 - (void)onDisplayLink:(CFTimeInterval)timestamp targetTimestamp:(CFTimeInterval)targetTimestamp {
74 CFTimeInterval minStart = targetTimestamp -
_displayLink.nominalOutputRefreshPeriod;
75 CFTimeInterval current = CACurrentMediaTime();
78 TRACE_VSYNC(
"DisplayLinkCallback-Original", _pendingBaton.value_or(0));
82 if (!_pendingBaton.has_value()) {
83 TRACE_VSYNC("DisplayLinkPaused", size_t(0));
84 _displayLink.paused = YES;
87 TRACE_VSYNC("DisplayLinkCallback-Delayed", _pendingBaton.value_or(0));
88 _block(minStart, targetTimestamp, *_pendingBaton);
89 _pendingBaton = std::nullopt;
96 - (void)waitForVSync:(uintptr_t)baton {
97 FML_DCHECK([NSThread isMainThread]);
103 CFTimeInterval now = CACurrentMediaTime();
108 if (_pendingBaton.has_value()) {
109 FML_LOG(WARNING) <<
"Engine requested vsync while another was pending";
110 _block(0, 0, *_pendingBaton);
111 _pendingBaton = std::nullopt;
114 TRACE_VSYNC(
"VSyncRequest", _pendingBaton.value_or(0));
126 CFTimeInterval start = CACurrentMediaTime();
129 CFTimeInterval delay = 0;
133 CFTimeInterval now = start;
134 start = now - (fmod(now, tick_interval)) + phase;
136 start += tick_interval;
143 CFTimeInterval targetTimestamp = start + tick_interval;
144 TRACE_VSYNC("SynthesizedInitialVSync", baton);
145 _block(start, targetTimestamp, baton);
150 _pendingBaton = baton;
155 if (_pendingBaton.has_value()) {
156 FML_LOG(WARNING) <<
"Deallocating FlutterVSyncWaiter with a pending vsync";
161 dispatch_async(dispatch_get_main_queue(), ^{
FlutterDisplayLink * _displayLink
static const CFTimeInterval kTimerLatencyCompensation
#define TRACE_VSYNC(event_type, baton)
CFTimeInterval _lastTargetTimestamp
void(^ _block)(CFTimeInterval, CFTimeInterval, uintptr_t)
void invalidate()
Invalidates the display link.
CFTimeInterval nominalOutputRefreshPeriod
BOOL paused
Pauses and resumes the display link.
id< FlutterDisplayLinkDelegate > delegate
void performBlock:afterDelay:(void(^ block)(void),[afterDelay] NSTimeInterval delay)