| Flutter macOS Embedder |

Instance Methods | List of all members
FlutterVSyncWaiter Class Reference

`#import <FlutterVSyncWaiter.h>`

Inheritance diagram for FlutterVSyncWaiter:

## Instance Methods
(instancetype) | - initWithDisplayLink:block:
(void) | - waitForVSync:

## Detailed Description

Definition at line 8 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 same thread as -waitForVSync:.

Definition at line 45 of file FlutterVSyncWaiter.mm.

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

References _block, _displayLink, _warmUpFrame, FlutterDisplayLink::delegate, and FlutterDisplayLink::paused.

## ◆ waitForVSync:

- (void) waitForVSync: |  | (uintptr_t) | baton |

Schedules |baton| to be signaled on next display refresh. The block provided in the initializer will be invoked on same thread as this method (there must be a run loop associated with current thread).

Definition at line 108 of file FlutterVSyncWaiter.mm.

110 :(uintptr_t)baton {
111 // CVDisplayLink start -> callback latency is two frames, there is
112 // no need to delay the warm-up frame.
113 if (_warmUpFrame) {
114 _warmUpFrame = NO;
115 TRACE_VSYNC("WarmUpFrame", baton);
116 [[NSRunLoop currentRunLoop] performBlock:^{
117 CFTimeInterval now = CACurrentMediaTime();
118 _block(now, now, baton);
119 }];
120 return;
121 }
122
123 // RunLoop is accessed both from main thread and from the display link thread.
124 @synchronized(self) {
125 if (_runLoop == nil) {
126 _runLoop = [NSRunLoop currentRunLoop];
127 }
128 }
129
130 FML_DCHECK(_runLoop == [NSRunLoop currentRunLoop]);
131 if (_pendingBaton.has_value()) {
132 FML_LOG(WARNING) << "Engine requested vsync while another was pending";
133 _block(0, 0, *_pendingBaton);
134 _pendingBaton = std::nullopt;
135 }
136
137 TRACE_VSYNC("VSyncRequest", _pendingBaton.value_or(0));
138
139 CFTimeInterval tick_interval = _displayLink.nominalOutputRefreshPeriod;
140 if (_displayLink.paused || tick_interval == 0) {
141 // When starting display link the first notification will come in the middle
142 // of next frame, which would incur a whole frame period of latency.
143 // To avoid that, first vsync notification will be fired using a timer
144 // scheduled to fire where the next frame is expected to start.
145 // Also use a timer if display link does not belong to any display
146 // (nominalOutputRefreshPeriod being 0)
147
148 // Start of the vsync interval.
149 CFTimeInterval start = CACurrentMediaTime();
150
151 // Timer delay is calculated as the time to the next frame start.
152 CFTimeInterval delay = 0;
153
154 if (tick_interval != 0 && _lastTargetTimestamp != 0) {
155 CFTimeInterval phase = fmod(_lastTargetTimestamp, tick_interval);
156 CFTimeInterval now = start;
157 start = now - (fmod(now, tick_interval)) + phase;
158 if (start < now) {
159 start += tick_interval;
160 }
161 delay = std::max(start - now - kTimerLatencyCompensation, 0.0);
162 }
163
164 NSTimer* timer = [NSTimer timerWithTimeInterval:delay
165 repeats:NO
166 block:^(NSTimer* timer) {
167 CFTimeInterval targetTimestamp =
168 start + tick_interval;
169 TRACE_VSYNC("SynthesizedInitialVSync", baton);
170 _block(start, targetTimestamp, baton);
171 }];
172 [_runLoop addTimer:timer forMode:NSRunLoopCommonModes];
173 _displayLink.paused = NO;
174 } else {
175 _pendingBaton = baton;

References _block, _displayLink, _lastTargetTimestamp, _runLoop, _warmUpFrame, kTimerLatencyCompensation, FlutterDisplayLink::nominalOutputRefreshPeriod, FlutterDisplayLink::paused, and TRACE_VSYNC.

Referenced by TEST().

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

- shell/platform/darwin/macos/framework/Source/FlutterVSyncWaiter.h
- shell/platform/darwin/macos/framework/Source/FlutterVSyncWaiter.mm

_warmUpFrame
BOOL _warmUpFrame
Definition: FlutterVSyncWaiter.mm:42
_runLoop
NSRunLoop * _runLoop
Definition: FlutterVSyncWaiter.mm:40
kTimerLatencyCompensation
static const CFTimeInterval kTimerLatencyCompensation
Definition: FlutterVSyncWaiter.mm:34
FlutterDisplayLink::nominalOutputRefreshPeriod
CFTimeInterval nominalOutputRefreshPeriod
Definition: FlutterDisplayLink.h:33
FlutterDisplayLink
Definition: FlutterDisplayLink.h:15
FlutterDisplayLink::paused
BOOL paused
Pauses and resumes the display link. May be called from any thread.
Definition: FlutterDisplayLink.h:28
TRACE_VSYNC
#define TRACE_VSYNC(event_type, baton)
Definition: FlutterVSyncWaiter.mm:18
_displayLink
FlutterDisplayLink * _displayLink
Definition: FlutterVSyncWaiter.mm:36
FlutterDisplayLink::delegate
id< FlutterDisplayLinkDelegate > delegate
Definition: FlutterDisplayLink.h:25
_lastTargetTimestamp
CFTimeInterval _lastTargetTimestamp
Definition: FlutterVSyncWaiter.mm:41
_block
void(^ _block)(CFTimeInterval, CFTimeInterval, uintptr_t)