9 #import "flutter/testing/testing.h"
22 - (instancetype)init {
23 if (
self = [super init]) {
29 - (void)tickWithTimestamp:(CFTimeInterval)timestamp
30 targetTimestamp:(CFTimeInterval)targetTimestamp {
31 [
self.delegate onDisplayLink:timestamp targetTimestamp:targetTimestamp];
46 EXPECT_TRUE(displayLink.
paused);
49 initWithDisplayLink:displayLink
50 block:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp,
54 EXPECT_FALSE(displayLink.
paused);
55 [displayLink tickWithTimestamp:CACurrentMediaTime()
56 targetTimestamp:CACurrentMediaTime() + 1.0 / 60.0];
57 EXPECT_TRUE(displayLink.
paused);
60 static void BusyWait(CFTimeInterval duration) {
61 CFTimeInterval start = CACurrentMediaTime();
62 while (CACurrentMediaTime() < start + duration) {
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;
79 initWithDisplayLink:displayLink
80 block:^(CFTimeInterval _timestamp, CFTimeInterval _targetTimestamp,
82 if (_baton == kWarmUpBaton) {
85 timestamp = _timestamp;
86 targetTimestamp = _targetTimestamp;
88 EXPECT_TRUE(CACurrentMediaTime() >= _timestamp - kTimerLatencyCompensation);
89 CFRunLoopStop(CFRunLoopGetCurrent());
95 CFTimeInterval now = CACurrentMediaTime();
97 [displayLink tickWithTimestamp:now + 0.5 * displayLink.nominalOutputRefreshPeriod
98 targetTimestamp:now + 2 * displayLink.nominalOutputRefreshPeriod];
99 EXPECT_EQ(displayLink.
paused, YES);
101 EXPECT_EQ(timestamp, 0);
106 CFTimeInterval expectedTimestamp = now + expectedDelay;
111 EXPECT_DOUBLE_EQ(timestamp, expectedTimestamp);
113 EXPECT_EQ(baton,
size_t(1));
126 const uintptr_t kWarmUpBaton = 0xFFFFFFFF;
129 CFTimeInterval timestamp;
130 CFTimeInterval targetTimestamp;
133 __block std::vector<Entry> entries;
136 initWithDisplayLink:displayLink
137 block:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp,
139 entries.push_back({timestamp, targetTimestamp, baton});
140 if (baton == kWarmUpBaton) {
143 EXPECT_TRUE(CACurrentMediaTime() >= timestamp - kTimerLatencyCompensation);
144 CFRunLoopStop(CFRunLoopGetCurrent());
147 __block CFTimeInterval expectedStartUntil;
152 [[NSRunLoop currentRunLoop] performBlock:^{
153 expectedStartUntil = CACurrentMediaTime();
157 CFTimeInterval now = CACurrentMediaTime();
159 [displayLink tickWithTimestamp:now + 0.5 * displayLink.nominalOutputRefreshPeriod
160 targetTimestamp:now + 2 * displayLink.nominalOutputRefreshPeriod];
161 EXPECT_EQ(displayLink.
paused, YES);
167 [displayLink tickWithTimestamp:now + 1.5 * displayLink.nominalOutputRefreshPeriod
168 targetTimestamp:now + 3 * displayLink.nominalOutputRefreshPeriod];
172 [displayLink tickWithTimestamp:now + 2.5 * displayLink.nominalOutputRefreshPeriod
173 targetTimestamp:now + 4 * displayLink.nominalOutputRefreshPeriod];
176 EXPECT_FALSE(displayLink.
paused);
178 [displayLink tickWithTimestamp:now + 3.5 * displayLink.nominalOutputRefreshPeriod
179 targetTimestamp:now + 5 * displayLink.nominalOutputRefreshPeriod];
181 CFTimeInterval start = CACurrentMediaTime();
182 while (!displayLink.
paused) {
184 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.02, NO);
185 if (CACurrentMediaTime() - start > 1.0) {
189 ASSERT_TRUE(displayLink.
paused);
191 EXPECT_EQ(entries.size(),
size_t(4));
194 EXPECT_TRUE(entries[0].timestamp <= expectedStartUntil);
195 EXPECT_TRUE(entries[0].targetTimestamp <= expectedStartUntil);
196 EXPECT_EQ(entries[0].baton, kWarmUpBaton);
200 EXPECT_EQ(entries[1].baton,
size_t(1));
203 EXPECT_EQ(entries[2].baton,
size_t(2));
206 EXPECT_EQ(entries[3].baton,
size_t(3));
static const CFTimeInterval kTimerLatencyCompensation
TEST_F(FlutterVSyncWaiterTest, RequestsInitialVSync)
static void BusyWait(CFTimeInterval duration)
void invalidate()
Invalidates the display link.
BOOL paused
Pauses and resumes the display link.
void ensureMainLoopInitialized()
void waitForVSync:(uintptr_t baton)
CFTimeInterval nominalOutputRefreshPeriod