| Flutter macOS Embedder |

Classes | Functions | Variables
FlutterVSyncWaiterTest.mm File Reference
`#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDisplayLink.h"`
`#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterRunLoop.h"`
`#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterVSyncWaiter.h"`
`#import "flutter/testing/testing.h"`

Go to the source code of this file.

## Classes
class | TestDisplayLink
class | FlutterVSyncWaiterTest

## Functions
| TEST_F (FlutterVSyncWaiterTest, RequestsInitialVSync)
static void | BusyWait (CFTimeInterval duration)
| TEST_F (FlutterVSyncWaiterTest, FirstVSyncIsSynthesized)
| TEST_F (FlutterVSyncWaiterTest, VSyncWorks)

## Variables
static const CFTimeInterval | kTimerLatencyCompensation = 0.001

## Function Documentation

## ◆ BusyWait()

static void BusyWait | ( | CFTimeInterval | duration | ) |
| static

Definition at line 60 of file FlutterVSyncWaiterTest.mm.

60 {
61 CFTimeInterval start = CACurrentMediaTime();
62 while (CACurrentMediaTime() < start + duration) {
63 }
64 }

Referenced by TEST_F().

## ◆ TEST_F() [1/3]

TEST_F | ( | FlutterVSyncWaiterTest | ,
|  | FirstVSyncIsSynthesized |
| ) |  |

Definition at line 69 of file FlutterVSyncWaiterTest.mm.

69 {
70 TestDisplayLink* displayLink = [[TestDisplayLink alloc] init];
71 displayLink.nominalOutputRefreshPeriod = 1.0 / 60.0;
72
73 auto test = [&](CFTimeInterval waitDuration, CFTimeInterval expectedDelay) {
74 __block CFTimeInterval timestamp = 0;
75 __block CFTimeInterval targetTimestamp = 0;
76 __block size_t baton = 0;
77 const uintptr_t kWarmUpBaton = 0xFFFFFFFF;
78 FlutterVSyncWaiter* waiter = [[FlutterVSyncWaiter alloc]
79 initWithDisplayLink:displayLink
80 block:^(CFTimeInterval _timestamp, CFTimeInterval _targetTimestamp,
81 uintptr_t _baton) {
82 if (_baton == kWarmUpBaton) {
83 return;
84 }
85 timestamp = _timestamp;
86 targetTimestamp = _targetTimestamp;
87 baton = _baton;
88 EXPECT_TRUE(CACurrentMediaTime() >= _timestamp - kTimerLatencyCompensation);
89 CFRunLoopStop(CFRunLoopGetCurrent());
90 }];
91
92 [waiter waitForVSync:kWarmUpBaton];
93
94 // Reference vsync to setup phase.
95 CFTimeInterval now = CACurrentMediaTime();
96 // CVDisplayLink callback is called one and a half frame before the target.
97 [displayLink tickWithTimestamp:now + 0.5 * displayLink.nominalOutputRefreshPeriod
98 targetTimestamp:now + 2 * displayLink.nominalOutputRefreshPeriod];
99 EXPECT_EQ(displayLink.paused, YES);
100 // Vsync was not requested yet, block should not have been called.
101 EXPECT_EQ(timestamp, 0);
102
103 BusyWait(waitDuration);
104
105 // Synthesized vsync should come in 1/60th of a second after the first.
106 CFTimeInterval expectedTimestamp = now + expectedDelay;
107 [waiter waitForVSync:1];
108
109 CFRunLoopRun();
110
111 EXPECT_DOUBLE_EQ(timestamp, expectedTimestamp);
112 EXPECT_DOUBLE_EQ(targetTimestamp, expectedTimestamp + displayLink.nominalOutputRefreshPeriod);
113 EXPECT_EQ(baton, size_t(1));
114 };
115
116 // First argument if the wait duration after reference vsync.
117 // Second argument is the expected delay between reference vsync and synthesized vsync.
118 test(0.005, displayLink.nominalOutputRefreshPeriod);
119 test(0.025, 2 * displayLink.nominalOutputRefreshPeriod);
120 test(0.040, 3 * displayLink.nominalOutputRefreshPeriod);
121 }
kTimerLatencyCompensation
static const CFTimeInterval kTimerLatencyCompensation
Definition: FlutterVSyncWaiterTest.mm:67
BusyWait
static void BusyWait(CFTimeInterval duration)
Definition: FlutterVSyncWaiterTest.mm:60
FlutterDisplayLink::paused
BOOL paused
Pauses and resumes the display link.
Definition: FlutterDisplayLink.h:30
FlutterVSyncWaiter
Definition: FlutterVSyncWaiter.h:9
TestDisplayLink
Definition: FlutterVSyncWaiterTest.mm:12
TestDisplayLink::nominalOutputRefreshPeriod
CFTimeInterval nominalOutputRefreshPeriod
Definition: FlutterVSyncWaiterTest.mm:13

References BusyWait(), TestDisplayLink::nominalOutputRefreshPeriod, FlutterDisplayLink::paused, and FlutterVSyncWaiter::waitForVSync:.

## ◆ TEST_F() [2/3]

TEST_F | ( | FlutterVSyncWaiterTest | ,
|  | RequestsInitialVSync |
| ) |  |

Definition at line 44 of file FlutterVSyncWaiterTest.mm.

44 {
45 TestDisplayLink* displayLink = [[TestDisplayLink alloc] init];
46 EXPECT_TRUE(displayLink.paused);
47 // When created waiter requests a reference vsync to determine vsync phase.
48 FlutterVSyncWaiter* waiter = [[FlutterVSyncWaiter alloc]
49 initWithDisplayLink:displayLink
50 block:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp,
51 uintptr_t baton){
52 }];
53 (void)waiter;
54 EXPECT_FALSE(displayLink.paused);
55 [displayLink tickWithTimestamp:CACurrentMediaTime()
56 targetTimestamp:CACurrentMediaTime() + 1.0 / 60.0];
57 EXPECT_TRUE(displayLink.paused);
58 }

References FlutterDisplayLink::paused.

## ◆ TEST_F() [3/3]

TEST_F | ( | FlutterVSyncWaiterTest | ,
|  | VSyncWorks |
| ) |  |

Definition at line 123 of file FlutterVSyncWaiterTest.mm.

123 {
124 TestDisplayLink* displayLink = [[TestDisplayLink alloc] init];
125 displayLink.nominalOutputRefreshPeriod = 1.0 / 60.0;
126 const uintptr_t kWarmUpBaton = 0xFFFFFFFF;
127
128 struct Entry {
129 CFTimeInterval timestamp;
130 CFTimeInterval targetTimestamp;
131 size_t baton;
132 };
133 __block std::vector<Entry> entries;
134
135 FlutterVSyncWaiter* waiter = [[FlutterVSyncWaiter alloc]
136 initWithDisplayLink:displayLink
137 block:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp,
138 uintptr_t baton) {
139 entries.push_back({timestamp, targetTimestamp, baton});
140 if (baton == kWarmUpBaton) {
141 return;
142 }
143 EXPECT_TRUE(CACurrentMediaTime() >= timestamp - kTimerLatencyCompensation);
144 CFRunLoopStop(CFRunLoopGetCurrent());
145 }];
146
147 __block CFTimeInterval expectedStartUntil;
148 // Warm up tick is scheduled immediately in a scheduled block. Schedule another
149 // block here to determine the maximum time when the warm up tick should be
150 // scheduled.
151 [waiter waitForVSync:kWarmUpBaton];
152 [[NSRunLoop currentRunLoop] performBlock:^{
153 expectedStartUntil = CACurrentMediaTime();
154 }];
155
156 // Reference vsync to setup phase.
157 CFTimeInterval now = CACurrentMediaTime();
158 // CVDisplayLink callback is called one and a half frame before the target.
159 [displayLink tickWithTimestamp:now + 0.5 * displayLink.nominalOutputRefreshPeriod
160 targetTimestamp:now + 2 * displayLink.nominalOutputRefreshPeriod];
161 EXPECT_EQ(displayLink.paused, YES);
162
163 [waiter waitForVSync:1];
164 CFRunLoopRun();
165
166 [waiter waitForVSync:2];
167 [displayLink tickWithTimestamp:now + 1.5 * displayLink.nominalOutputRefreshPeriod
168 targetTimestamp:now + 3 * displayLink.nominalOutputRefreshPeriod];
169 CFRunLoopRun();
170
171 [waiter waitForVSync:3];
172 [displayLink tickWithTimestamp:now + 2.5 * displayLink.nominalOutputRefreshPeriod
173 targetTimestamp:now + 4 * displayLink.nominalOutputRefreshPeriod];
174 CFRunLoopRun();
175
176 EXPECT_FALSE(displayLink.paused);
177 // Vsync without baton should pause the display link.
178 [displayLink tickWithTimestamp:now + 3.5 * displayLink.nominalOutputRefreshPeriod
179 targetTimestamp:now + 5 * displayLink.nominalOutputRefreshPeriod];
180
181 CFTimeInterval start = CACurrentMediaTime();
182 while (!displayLink.paused) {
183 // Make sure to run the timer scheduled in display link callback.
184 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.02, NO);
185 if (CACurrentMediaTime() - start > 1.0) {
186 break;
187 }
188 }
189 ASSERT_TRUE(displayLink.paused);
190
191 EXPECT_EQ(entries.size(), size_t(4));
192
193 // Warm up frame should be presented as soon as possible.
194 EXPECT_TRUE(entries[0].timestamp <= expectedStartUntil);
195 EXPECT_TRUE(entries[0].targetTimestamp <= expectedStartUntil);
196 EXPECT_EQ(entries[0].baton, kWarmUpBaton);
197
198 EXPECT_DOUBLE_EQ(entries[1].timestamp, now + displayLink.nominalOutputRefreshPeriod);
199 EXPECT_DOUBLE_EQ(entries[1].targetTimestamp, now + 2 * displayLink.nominalOutputRefreshPeriod);
200 EXPECT_EQ(entries[1].baton, size_t(1));
201 EXPECT_DOUBLE_EQ(entries[2].timestamp, now + 2 * displayLink.nominalOutputRefreshPeriod);
202 EXPECT_DOUBLE_EQ(entries[2].targetTimestamp, now + 3 * displayLink.nominalOutputRefreshPeriod);
203 EXPECT_EQ(entries[2].baton, size_t(2));
204 EXPECT_DOUBLE_EQ(entries[3].timestamp, now + 3 * displayLink.nominalOutputRefreshPeriod);
205 EXPECT_DOUBLE_EQ(entries[3].targetTimestamp, now + 4 * displayLink.nominalOutputRefreshPeriod);
206 EXPECT_EQ(entries[3].baton, size_t(3));
207 }

References TestDisplayLink::nominalOutputRefreshPeriod, FlutterDisplayLink::paused, and FlutterVSyncWaiter::waitForVSync:.

## Variable Documentation

## ◆ kTimerLatencyCompensation

const CFTimeInterval kTimerLatencyCompensation = 0.001
| static

Definition at line 67 of file FlutterVSyncWaiterTest.mm.