Flutter macOS Embedder
FlutterVSyncWaiter Class Reference

#import <FlutterVSyncWaiter.h>

Inheritance diagram for FlutterVSyncWaiter:

Instance Methods

(instancetype) - initWithDisplayLink:block:
 
(void) - waitForVSync:
 
(void) - invalidate
 

Detailed Description

Definition at line 12 of file FlutterVSyncWaiter.h.

Method Documentation

◆ initWithDisplayLink:block:

- (instancetype) initWithDisplayLink: (FlutterDisplayLink*)  displayLink
block: (void(^)(CFTimeInterval timestamp, CFTimeInterval targetTimestamp, uintptr_t baton))  block 

Creates new waiter instance tied to provided NSView. This function must be called on the main thread.

Provided |block| will be invoked on main thread.

Definition at line 46 of file FlutterVSyncWaiter.mm.

49  :(FlutterDisplayLink*)displayLink
50  block:(void (^)(CFTimeInterval timestamp,
51  CFTimeInterval targetTimestamp,
52  uintptr_t baton))block {
53  FML_DCHECK([NSThread isMainThread]);
54  if (self = [super init]) {
55  _block = block;
56 
57  _displayLink = displayLink;
58  _displayLink.delegate = self;
59  // Get at least one callback to initialize _lastTargetTimestamp.
60  _displayLink.paused = NO;
61  _warmUpFrame = YES;
62  }
FlutterDisplayLink * _displayLink
void(^ _block)(CFTimeInterval, CFTimeInterval, uintptr_t)
BOOL _warmUpFrame

◆ invalidate

- (void) invalidate

Invalidates the waiter. This must be called on the main thread before the instance is deallocated.

Definition at line 46 of file FlutterVSyncWaiter.mm.

157  {
158  // It is possible that there is pending vsync request while the view for which
159  // this waiter belongs is being destroyed. In that case trigger the vsync
160  // immediately to avoid deadlock.
161  if (_pendingBaton.has_value()) {
162  CFTimeInterval now = CACurrentMediaTime();
163  _block(now, now, _pendingBaton.value());
164  _pendingBaton = std::nullopt;
165  }
166 
167  [_displayLink invalidate];

Referenced by TEST_F().

◆ waitForVSync:

- (void) waitForVSync: (uintptr_t)  baton

Schedules |baton| to be signaled on next display refresh. This function must be called on the main thread.

Definition at line 46 of file FlutterVSyncWaiter.mm.

100  :(uintptr_t)baton {
101  FML_DCHECK([NSThread isMainThread]);
102  // CVDisplayLink start -> callback latency is two frames, there is
103  // no need to delay the warm-up frame.
104  if (_warmUpFrame) {
105  _warmUpFrame = NO;
106  TRACE_VSYNC("WarmUpFrame", baton);
107  CFTimeInterval now = CACurrentMediaTime();
108  _block(now, now, baton);
109  return;
110  }
111 
112  if (_pendingBaton.has_value()) {
113  [FlutterLogger logWarning:@"Engine requested vsync while another was pending"];
114  _block(0, 0, *_pendingBaton);
115  _pendingBaton = std::nullopt;
116  }
117 
118  TRACE_VSYNC("VSyncRequest", _pendingBaton.value_or(0));
119 
120  CFTimeInterval tick_interval = _displayLink.nominalOutputRefreshPeriod;
121  if (_displayLink.paused || tick_interval == 0 || _lastTargetTimestamp == 0) {
122  // When starting display link the first notification will come in the middle
123  // of next frame, which would incur a whole frame period of latency.
124  // To avoid that, first vsync notification will be fired using a timer
125  // scheduled to fire where the next frame is expected to start.
126  // Also use a timer if display link does not belong to any display
127  // (nominalOutputRefreshPeriod being 0)
128 
129  // Start of the vsync interval.
130  CFTimeInterval start = CACurrentMediaTime();
131 
132  // Timer delay is calculated as the time to the next frame start.
133  CFTimeInterval delay = 0;
134 
135  if (tick_interval != 0 && _lastTargetTimestamp != 0) {
136  CFTimeInterval phase = fmod(_lastTargetTimestamp, tick_interval);
137  CFTimeInterval now = start;
138  start = now - (fmod(now, tick_interval)) + phase;
139  if (start < now) {
140  start += tick_interval;
141  }
142  delay = std::max(start - now - kTimerLatencyCompensation, 0.0);
143  }
144 
145  [FlutterRunLoop.mainRunLoop performAfterDelay:delay
146  block:^{
147  CFTimeInterval targetTime = start + tick_interval;
148  TRACE_VSYNC("SynthesizedInitialVSync", baton);
149  _block(start, targetTime, baton);
150  }];
151  _displayLink.paused = NO;
152  } else {
153  _pendingBaton = baton;
static const CFTimeInterval kTimerLatencyCompensation
#define TRACE_VSYNC(event_type, baton)
CFTimeInterval _lastTargetTimestamp

Referenced by TEST_F().


The documentation for this class was generated from the following files: