1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/viz/common/frame_sinks/begin_frame_source.h"
6
7 #include <stdint.h>
8
9 #include <memory>
10
11 #include "base/test/test_mock_time_task_runner.h"
12 #include "components/viz/test/begin_frame_args_test.h"
13 #include "components/viz/test/begin_frame_source_test.h"
14 #include "components/viz/test/fake_delay_based_time_source.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using testing::NiceMock;
19 using testing::_;
20
21 namespace viz {
22 namespace {
23
24 // Returns a fake TimeTicks based on the given microsecond offset.
TicksFromMicroseconds(int64_t micros)25 base::TimeTicks TicksFromMicroseconds(int64_t micros) {
26 return base::TimeTicks() + base::TimeDelta::FromMicroseconds(micros);
27 }
28
29 // BeginFrameSource testing ----------------------------------------------------
TEST(BeginFrameSourceTest,SourceIdsAreUnique)30 TEST(BeginFrameSourceTest, SourceIdsAreUnique) {
31 StubBeginFrameSource source1;
32 StubBeginFrameSource source2;
33 StubBeginFrameSource source3;
34 EXPECT_NE(source1.source_id(), source2.source_id());
35 EXPECT_NE(source1.source_id(), source3.source_id());
36 EXPECT_NE(source2.source_id(), source3.source_id());
37 }
38
39 class TestTaskRunner : public base::TestMockTimeTaskRunner {
40 public:
TestTaskRunner()41 TestTaskRunner()
42 : base::TestMockTimeTaskRunner(
43 base::TestMockTimeTaskRunner::Type::kStandalone) {
44 AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(1000));
45 }
46
FastForwardTo(base::TimeTicks end_time)47 void FastForwardTo(base::TimeTicks end_time) {
48 base::TimeDelta offset = end_time - NowTicks();
49 DCHECK_GE(offset, base::TimeDelta());
50 FastForwardBy(offset);
51 }
52
53 private:
54 ~TestTaskRunner() override = default; // Ref-counted.
55 DISALLOW_COPY_AND_ASSIGN(TestTaskRunner);
56 };
57
58 // BackToBackBeginFrameSource testing
59 // ------------------------------------------
60 class BackToBackBeginFrameSourceTest : public ::testing::Test {
61 protected:
62 static const int64_t kDeadline;
63 static const int64_t kInterval;
64
SetUp()65 void SetUp() override {
66 task_runner_ = base::MakeRefCounted<TestTaskRunner>();
67 std::unique_ptr<FakeDelayBasedTimeSource> time_source =
68 std::make_unique<FakeDelayBasedTimeSource>(
69 task_runner_->GetMockTickClock(), task_runner_.get());
70
71 delay_based_time_source_ = time_source.get();
72 source_.reset(new BackToBackBeginFrameSource(std::move(time_source)));
73 obs_ = std::make_unique<::testing::NiceMock<MockBeginFrameObserver>>();
74 }
75
TearDown()76 void TearDown() override { obs_.reset(); }
77
78 scoped_refptr<TestTaskRunner> task_runner_;
79 std::unique_ptr<BackToBackBeginFrameSource> source_;
80 std::unique_ptr<MockBeginFrameObserver> obs_;
81 FakeDelayBasedTimeSource* delay_based_time_source_; // Owned by |source_|.
82 };
83
84 const int64_t BackToBackBeginFrameSourceTest::kDeadline =
85 BeginFrameArgs::DefaultInterval().InMicroseconds();
86
87 const int64_t BackToBackBeginFrameSourceTest::kInterval =
88 BeginFrameArgs::DefaultInterval().InMicroseconds();
89
TEST_F(BackToBackBeginFrameSourceTest,AddObserverSendsBeginFrame)90 TEST_F(BackToBackBeginFrameSourceTest, AddObserverSendsBeginFrame) {
91 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
92 source_->AddObserver(obs_.get());
93 EXPECT_TRUE(task_runner_->HasPendingTask());
94 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
95 1000 + kDeadline, kInterval);
96 task_runner_->RunUntilIdle();
97
98 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1100,
99 1100 + kDeadline, kInterval);
100 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
101 source_->DidFinishFrame(obs_.get());
102 task_runner_->RunUntilIdle();
103 }
104
TEST_F(BackToBackBeginFrameSourceTest,RemoveObserverThenDidFinishFrameProducesNoFrame)105 TEST_F(BackToBackBeginFrameSourceTest,
106 RemoveObserverThenDidFinishFrameProducesNoFrame) {
107 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
108 source_->AddObserver(obs_.get());
109 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
110 1000 + kDeadline, kInterval);
111 task_runner_->RunUntilIdle();
112
113 source_->RemoveObserver(obs_.get());
114 source_->DidFinishFrame(obs_.get());
115
116 // Verify no BeginFrame is sent to |obs_|. There is a pending task in the
117 // task_runner_ as a BeginFrame was posted, but it gets aborted since |obs_|
118 // is removed.
119 task_runner_->RunUntilIdle();
120 EXPECT_FALSE(task_runner_->HasPendingTask());
121 }
122
TEST_F(BackToBackBeginFrameSourceTest,DidFinishFrameThenRemoveObserverProducesNoFrame)123 TEST_F(BackToBackBeginFrameSourceTest,
124 DidFinishFrameThenRemoveObserverProducesNoFrame) {
125 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
126 source_->AddObserver(obs_.get());
127 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
128 1000 + kDeadline, kInterval);
129 task_runner_->RunUntilIdle();
130
131 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
132 source_->DidFinishFrame(obs_.get());
133 source_->RemoveObserver(obs_.get());
134
135 // Task gets cancelled so it doesn't count as a pending task.
136 EXPECT_FALSE(task_runner_->HasPendingTask());
137 }
138
TEST_F(BackToBackBeginFrameSourceTest,TogglingObserverThenDidFinishFrameProducesCorrectFrame)139 TEST_F(BackToBackBeginFrameSourceTest,
140 TogglingObserverThenDidFinishFrameProducesCorrectFrame) {
141 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
142 source_->AddObserver(obs_.get());
143 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
144 1000 + kDeadline, kInterval);
145 task_runner_->RunUntilIdle();
146
147 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
148 source_->RemoveObserver(obs_.get());
149
150 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(10));
151 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
152 source_->AddObserver(obs_.get());
153
154 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(10));
155 source_->DidFinishFrame(obs_.get());
156
157 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(10));
158 // The begin frame is posted at the time when the observer was added,
159 // so it ignores changes to "now" afterward.
160 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1110,
161 1110 + kDeadline, kInterval);
162 EXPECT_TRUE(task_runner_->HasPendingTask());
163 task_runner_->RunUntilIdle();
164 }
165
TEST_F(BackToBackBeginFrameSourceTest,DidFinishFrameThenTogglingObserverProducesCorrectFrame)166 TEST_F(BackToBackBeginFrameSourceTest,
167 DidFinishFrameThenTogglingObserverProducesCorrectFrame) {
168 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
169 source_->AddObserver(obs_.get());
170 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
171 1000 + kDeadline, kInterval);
172 task_runner_->RunUntilIdle();
173
174 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
175 source_->DidFinishFrame(obs_.get());
176
177 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(10));
178 source_->RemoveObserver(obs_.get());
179
180 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(10));
181 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
182 source_->AddObserver(obs_.get());
183
184 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(10));
185 // Ticks at the time at which the observer was added, ignoring the
186 // last change to "now".
187 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1120,
188 1120 + kDeadline, kInterval);
189 EXPECT_TRUE(task_runner_->HasPendingTask());
190 task_runner_->RunUntilIdle();
191 }
192
TEST_F(BackToBackBeginFrameSourceTest,DidFinishFrameNoObserver)193 TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameNoObserver) {
194 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
195 source_->AddObserver(obs_.get());
196 source_->RemoveObserver(obs_.get());
197 source_->DidFinishFrame(obs_.get());
198 task_runner_->RunUntilIdle();
199 EXPECT_FALSE(task_runner_->HasPendingTask());
200 }
201
TEST_F(BackToBackBeginFrameSourceTest,DidFinishFrameMultipleCallsIdempotent)202 TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameMultipleCallsIdempotent) {
203 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
204 source_->AddObserver(obs_.get());
205 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
206 1000 + kDeadline, kInterval);
207 task_runner_->RunUntilIdle();
208
209 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
210 source_->DidFinishFrame(obs_.get());
211 source_->DidFinishFrame(obs_.get());
212 source_->DidFinishFrame(obs_.get());
213 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1100,
214 1100 + kDeadline, kInterval);
215 task_runner_->RunUntilIdle();
216
217 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
218 source_->DidFinishFrame(obs_.get());
219 source_->DidFinishFrame(obs_.get());
220 source_->DidFinishFrame(obs_.get());
221 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 1200,
222 1200 + kDeadline, kInterval);
223 task_runner_->RunUntilIdle();
224 }
225
TEST_F(BackToBackBeginFrameSourceTest,DelayInPostedTaskProducesCorrectFrame)226 TEST_F(BackToBackBeginFrameSourceTest, DelayInPostedTaskProducesCorrectFrame) {
227 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
228 source_->AddObserver(obs_.get());
229 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
230 1000 + kDeadline, kInterval);
231 task_runner_->RunUntilIdle();
232
233 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
234 source_->DidFinishFrame(obs_.get());
235 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(50));
236 // Ticks at the time the last frame finished, so ignores the last change to
237 // "now".
238 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1100,
239 1100 + kDeadline, kInterval);
240
241 EXPECT_TRUE(task_runner_->HasPendingTask());
242 task_runner_->RunUntilIdle();
243 }
244
TEST_F(BackToBackBeginFrameSourceTest,MultipleObserversSynchronized)245 TEST_F(BackToBackBeginFrameSourceTest, MultipleObserversSynchronized) {
246 NiceMock<MockBeginFrameObserver> obs1, obs2;
247
248 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, false);
249 source_->AddObserver(&obs1);
250 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false);
251 source_->AddObserver(&obs2);
252
253 EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 1, 1000, 1000 + kDeadline,
254 kInterval);
255 EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 1, 1000, 1000 + kDeadline,
256 kInterval);
257 task_runner_->RunUntilIdle();
258
259 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
260 source_->DidFinishFrame(&obs1);
261 source_->DidFinishFrame(&obs2);
262 EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 2, 1100, 1100 + kDeadline,
263 kInterval);
264 EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 2, 1100, 1100 + kDeadline,
265 kInterval);
266 task_runner_->RunUntilIdle();
267
268 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
269 source_->DidFinishFrame(&obs1);
270 source_->DidFinishFrame(&obs2);
271 EXPECT_TRUE(task_runner_->HasPendingTask());
272 source_->RemoveObserver(&obs1);
273 source_->RemoveObserver(&obs2);
274 task_runner_->RunUntilIdle();
275 }
276
TEST_F(BackToBackBeginFrameSourceTest,MultipleObserversInterleaved)277 TEST_F(BackToBackBeginFrameSourceTest, MultipleObserversInterleaved) {
278 NiceMock<MockBeginFrameObserver> obs1, obs2;
279
280 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, false);
281 source_->AddObserver(&obs1);
282 EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 1, 1000, 1000 + kDeadline,
283 kInterval);
284 task_runner_->RunUntilIdle();
285
286 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
287 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false);
288 source_->AddObserver(&obs2);
289 EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 2, 1100, 1100 + kDeadline,
290 kInterval);
291 task_runner_->RunUntilIdle();
292
293 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
294 source_->DidFinishFrame(&obs1);
295 EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 3, 1200, 1200 + kDeadline,
296 kInterval);
297 task_runner_->RunUntilIdle();
298
299 source_->DidFinishFrame(&obs1);
300 source_->RemoveObserver(&obs1);
301 // Removing all finished observers should disable the time source.
302 EXPECT_FALSE(delay_based_time_source_->Active());
303 // Finishing the frame for |obs1| posts a begin frame task, which will be
304 // aborted since |obs1| is removed. Clear that from the task runner.
305 task_runner_->RunUntilIdle();
306
307 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
308 source_->DidFinishFrame(&obs2);
309 EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 4, 1300, 1300 + kDeadline,
310 kInterval);
311 task_runner_->RunUntilIdle();
312
313 source_->DidFinishFrame(&obs2);
314 source_->RemoveObserver(&obs2);
315 }
316
TEST_F(BackToBackBeginFrameSourceTest,MultipleObserversAtOnce)317 TEST_F(BackToBackBeginFrameSourceTest, MultipleObserversAtOnce) {
318 NiceMock<MockBeginFrameObserver> obs1, obs2;
319
320 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, false);
321 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false);
322 source_->AddObserver(&obs1);
323 source_->AddObserver(&obs2);
324 EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 1, 1000, 1000 + kDeadline,
325 kInterval);
326 EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 1, 1000, 1000 + kDeadline,
327 kInterval);
328 task_runner_->RunUntilIdle();
329
330 // |obs1| finishes first.
331 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
332 source_->DidFinishFrame(&obs1);
333
334 // |obs2| finishes also, before getting to the newly posted begin frame.
335 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(100));
336 source_->DidFinishFrame(&obs2);
337
338 // Because the begin frame source already ticked when |obs1| finished,
339 // we see it as the frame time for both observers.
340 EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 2, 1100, 1100 + kDeadline,
341 kInterval);
342 EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 2, 1100, 1100 + kDeadline,
343 kInterval);
344 task_runner_->RunUntilIdle();
345
346 source_->DidFinishFrame(&obs1);
347 source_->RemoveObserver(&obs1);
348 source_->DidFinishFrame(&obs2);
349 source_->RemoveObserver(&obs2);
350 }
351
352 // DelayBasedBeginFrameSource testing
353 // ------------------------------------------
354 class DelayBasedBeginFrameSourceTest : public ::testing::Test {
355 public:
SetUp()356 void SetUp() override {
357 task_runner_ = base::MakeRefCounted<TestTaskRunner>();
358 std::unique_ptr<FakeDelayBasedTimeSource> time_source =
359 std::make_unique<FakeDelayBasedTimeSource>(
360 task_runner_->GetMockTickClock(), task_runner_.get());
361
362 time_source->SetTimebaseAndInterval(
363 base::TimeTicks(), base::TimeDelta::FromMicroseconds(10000));
364 source_ = std::make_unique<DelayBasedBeginFrameSource>(
365 std::move(time_source), BeginFrameSource::kNotRestartableId);
366 obs_.reset(new MockBeginFrameObserver);
367 }
368
TearDown()369 void TearDown() override { obs_.reset(); }
370
371 scoped_refptr<TestTaskRunner> task_runner_;
372 std::unique_ptr<DelayBasedBeginFrameSource> source_;
373 std::unique_ptr<MockBeginFrameObserver> obs_;
374 };
375
TEST_F(DelayBasedBeginFrameSourceTest,AddObserverCallsOnBeginFrameWithMissedTick)376 TEST_F(DelayBasedBeginFrameSourceTest,
377 AddObserverCallsOnBeginFrameWithMissedTick) {
378 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(9010));
379 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
380 EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 10000, 20000,
381 10000);
382 source_->AddObserver(obs_.get()); // Should cause the last tick to be sent
383 // No tasks should need to be run for this to occur.
384 }
385
TEST_F(DelayBasedBeginFrameSourceTest,AddObserverCallsCausesOnBeginFrame)386 TEST_F(DelayBasedBeginFrameSourceTest, AddObserverCallsCausesOnBeginFrame) {
387 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
388 EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 0, 10000,
389 10000);
390 source_->AddObserver(obs_.get());
391 EXPECT_EQ(TicksFromMicroseconds(10000),
392 task_runner_->NowTicks() + task_runner_->NextPendingTaskDelay());
393
394 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 10000, 20000, 10000);
395 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(9010));
396 task_runner_->RunUntilIdle();
397 }
398
TEST_F(DelayBasedBeginFrameSourceTest,BasicOperation)399 TEST_F(DelayBasedBeginFrameSourceTest, BasicOperation) {
400 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
401 EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 0, 10000,
402 10000);
403 source_->AddObserver(obs_.get());
404 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 10000, 20000, 10000);
405 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 20000, 30000, 10000);
406 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 4, 30000, 40000, 10000);
407 task_runner_->FastForwardTo(TicksFromMicroseconds(30001));
408
409 source_->RemoveObserver(obs_.get());
410 // No new frames....
411 task_runner_->FastForwardTo(TicksFromMicroseconds(60000));
412 }
413
TEST_F(DelayBasedBeginFrameSourceTest,VSyncChanges)414 TEST_F(DelayBasedBeginFrameSourceTest, VSyncChanges) {
415 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
416 EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 0, 10000,
417 10000);
418 source_->AddObserver(obs_.get());
419
420 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 10000, 20000, 10000);
421 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 20000, 30000, 10000);
422 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 4, 30000, 40000, 10000);
423 task_runner_->FastForwardTo(TicksFromMicroseconds(30001));
424
425 // Update the vsync information
426 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(27500),
427 base::TimeDelta::FromMicroseconds(10001));
428
429 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 5, 40000, 47502, 10001);
430 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 6, 47502, 57503, 10001);
431 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 7, 57503, 67504, 10001);
432 task_runner_->FastForwardTo(TicksFromMicroseconds(60000));
433 }
434
TEST_F(DelayBasedBeginFrameSourceTest,VSyncChangeTimebaseBeforeLastTick)435 TEST_F(DelayBasedBeginFrameSourceTest, VSyncChangeTimebaseBeforeLastTick) {
436 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
437 EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 0, 10000,
438 10000);
439 source_->AddObserver(obs_.get());
440
441 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 10000, 20000, 10000);
442 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 20000, 30000, 10000);
443 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 4, 30000, 40000, 10000);
444 task_runner_->FastForwardTo(TicksFromMicroseconds(30000));
445
446 // Update the vsync information such that timebase is before last tick time,
447 // and next tick happens within less than the new interval of the following
448 // tick (i.e. next_tick -> 40000, following_tick -> 41000)
449 // Begin frame won't be used at 41000 because this is a double-tick.
450 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(26000),
451 base::TimeDelta::FromMicroseconds(5000));
452 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 5, 40000, 41000, 5000);
453 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 7, 46000, 51000, 5000);
454 task_runner_->FastForwardTo(TicksFromMicroseconds(46000));
455
456 // Update the vsync information such that timebase is before last tick time,
457 // and next tick happens exactly one interval before the following tick
458 // tick (i.e. next_tick -> 51000, following_tick -> 60000)
459 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(42000),
460 base::TimeDelta::FromMicroseconds(9000));
461 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 8, 51000, 60000, 9000);
462 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 9, 60000, 69000, 9000);
463 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 10, 69000, 78000, 9000);
464 task_runner_->FastForwardTo(TicksFromMicroseconds(70000));
465 }
466
TEST_F(DelayBasedBeginFrameSourceTest,VSyncChangeTimebaseAfterNextTick)467 TEST_F(DelayBasedBeginFrameSourceTest, VSyncChangeTimebaseAfterNextTick) {
468 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
469 EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 0, 10000,
470 10000);
471 source_->AddObserver(obs_.get());
472
473 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 10000, 20000, 10000);
474 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 20000, 30000, 10000);
475 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 4, 30000, 40000, 10000);
476 task_runner_->FastForwardTo(TicksFromMicroseconds(30000));
477
478 // Update the vsync information such that timebase is after next tick time,
479 // and next tick happens within less than one interval of the new timebase
480 // Begin frame won't be used at 41000 because this is a double-tick.
481 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(41000),
482 base::TimeDelta::FromMicroseconds(5000));
483 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 5, 40000, 41000, 5000);
484 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 7, 46000, 51000, 5000);
485 task_runner_->FastForwardTo(TicksFromMicroseconds(46000));
486
487 // Update the vsync information such that timebase is after next tick time,
488 // and next tick happens exactly one interval before the new timebase
489 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(60000),
490 base::TimeDelta::FromMicroseconds(9000));
491 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 8, 51000, 60000, 9000);
492 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 9, 60000, 69000, 9000);
493 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 10, 69000, 78000, 9000);
494 task_runner_->FastForwardTo(TicksFromMicroseconds(70000));
495
496 // Update the vsync information such that timebase is after next tick time,
497 // and next tick happens more than one interval before the new timebase
498 // Begin frame won't be used at 80000 because this is a double-tick.
499 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(100000),
500 base::TimeDelta::FromMicroseconds(5000));
501 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 11, 78000, 80000, 5000);
502 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 13, 85000, 90000, 5000);
503 task_runner_->FastForwardTo(TicksFromMicroseconds(85000));
504 }
505
TEST_F(DelayBasedBeginFrameSourceTest,VSyncChangeTimebaseBetweenTicks)506 TEST_F(DelayBasedBeginFrameSourceTest, VSyncChangeTimebaseBetweenTicks) {
507 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
508 EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 0, 10000,
509 10000);
510 source_->AddObserver(obs_.get());
511
512 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 10000, 20000, 10000);
513 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 20000, 30000, 10000);
514 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 4, 30000, 40000, 10000);
515 task_runner_->FastForwardTo(TicksFromMicroseconds(30000));
516
517 // Update the vsync information such that timebase is between next tick time,
518 // and last tick time.
519 // Begin frame won't be used at 41000 because this is a double-tick.
520 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(35000),
521 base::TimeDelta::FromMicroseconds(6000));
522 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 5, 40000, 41000, 6000);
523 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 7, 47000, 53000, 6000);
524 task_runner_->FastForwardTo(TicksFromMicroseconds(47000));
525
526 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(49000),
527 base::TimeDelta::FromMicroseconds(10000));
528 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 8, 53000, 59000, 10000);
529 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 9, 59000, 69000, 10000);
530 EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 10, 69000, 79000, 10000);
531 task_runner_->FastForwardTo(TicksFromMicroseconds(70000));
532 }
533
TEST_F(DelayBasedBeginFrameSourceTest,MultipleObservers)534 TEST_F(DelayBasedBeginFrameSourceTest, MultipleObservers) {
535 NiceMock<MockBeginFrameObserver> obs1, obs2;
536
537 // Mock tick clock starts off at 1000.
538 task_runner_->FastForwardBy(base::TimeDelta::FromMicroseconds(9010));
539 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, false);
540 EXPECT_BEGIN_FRAME_USED_MISSED(obs1, source_->source_id(), 1, 10000, 20000,
541 10000);
542 source_->AddObserver(&obs1); // Should cause the last tick to be sent
543 // No tasks should need to be run for this to occur.
544
545 EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 2, 20000, 30000, 10000);
546 task_runner_->FastForwardBy(base::TimeDelta::FromMicroseconds(10000));
547
548 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false);
549 // Sequence number unchanged for missed frame with time of last normal frame.
550 EXPECT_BEGIN_FRAME_USED_MISSED(obs2, source_->source_id(), 2, 20000, 30000,
551 10000);
552 source_->AddObserver(&obs2); // Should cause the last tick to be sent
553 // No tasks should need to be run for this to occur.
554
555 EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 3, 30000, 40000, 10000);
556 EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 3, 30000, 40000, 10000);
557 task_runner_->FastForwardBy(base::TimeDelta::FromMicroseconds(10000));
558
559 source_->RemoveObserver(&obs1);
560
561 EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 4, 40000, 50000, 10000);
562 task_runner_->FastForwardBy(base::TimeDelta::FromMicroseconds(10000));
563
564 source_->RemoveObserver(&obs2);
565 task_runner_->FastForwardTo(TicksFromMicroseconds(50000));
566 EXPECT_FALSE(task_runner_->HasPendingTask());
567 }
568
TEST_F(DelayBasedBeginFrameSourceTest,DoubleTick)569 TEST_F(DelayBasedBeginFrameSourceTest, DoubleTick) {
570 NiceMock<MockBeginFrameObserver> obs;
571
572 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
573 EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_->source_id(), 1, 0, 10000, 10000);
574 source_->AddObserver(&obs);
575
576 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(5000),
577 base::TimeDelta::FromMicroseconds(10000));
578 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(4000));
579
580 // No begin frame received.
581 task_runner_->RunUntilIdle();
582
583 // Begin frame received.
584 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(10000),
585 base::TimeDelta::FromMicroseconds(10000));
586 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(5000));
587 EXPECT_BEGIN_FRAME_USED(obs, source_->source_id(), 2, 10000, 20000, 10000);
588 task_runner_->RunUntilIdle();
589 }
590
TEST_F(DelayBasedBeginFrameSourceTest,DoubleTickMissedFrame)591 TEST_F(DelayBasedBeginFrameSourceTest, DoubleTickMissedFrame) {
592 NiceMock<MockBeginFrameObserver> obs;
593
594 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
595 EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_->source_id(), 1, 0, 10000, 10000);
596 source_->AddObserver(&obs);
597 source_->RemoveObserver(&obs);
598
599 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(5000),
600 base::TimeDelta::FromMicroseconds(10000));
601 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(4000));
602
603 // No missed frame received.
604 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
605 // This does not cause a missed BeginFrame because of double ticking
606 // prevention. It does not produce a new sequence number.
607 source_->AddObserver(&obs);
608 source_->RemoveObserver(&obs);
609
610 // Missed frame received.
611 source_->OnUpdateVSyncParameters(TicksFromMicroseconds(10000),
612 base::TimeDelta::FromMicroseconds(10000));
613 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(5000));
614 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
615 // Sequence number is incremented again, because sufficient time has passed.
616 EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_->source_id(), 2, 10000, 20000,
617 10000);
618 source_->AddObserver(&obs);
619 source_->RemoveObserver(&obs);
620 }
621
TEST_F(DelayBasedBeginFrameSourceTest,MultipleArgsInSameInterval)622 TEST_F(DelayBasedBeginFrameSourceTest, MultipleArgsInSameInterval) {
623 NiceMock<MockBeginFrameObserver> obs;
624 NiceMock<MockBeginFrameObserver> obs2;
625
626 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
627 EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_->source_id(), 1, 0, 10000, 10000);
628 source_->AddObserver(&obs);
629 task_runner_->RunUntilIdle();
630
631 EXPECT_BEGIN_FRAME_USED(obs, source_->source_id(), 2, 10000, 20000, 10000);
632 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(9000));
633 task_runner_->RunUntilIdle();
634
635 // Sequence number should stay the same within same interval.
636 EXPECT_BEGIN_FRAME_USED_MISSED(obs2, source_->source_id(), 2, 10000, 20000,
637 10000);
638 source_->AddObserver(&obs2);
639
640 EXPECT_BEGIN_FRAME_USED(obs, source_->source_id(), 3, 20000, 30000, 10000);
641 EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 3, 20000, 30000, 10000);
642 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(10000));
643 task_runner_->RunUntilIdle();
644 }
645
TEST_F(DelayBasedBeginFrameSourceTest,ConsecutiveArgsDelayedByMultipleVsyncs)646 TEST_F(DelayBasedBeginFrameSourceTest, ConsecutiveArgsDelayedByMultipleVsyncs) {
647 NiceMock<MockBeginFrameObserver> obs;
648
649 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
650 EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_->source_id(), 1, 0, 10000, 10000);
651 source_->AddObserver(&obs);
652 task_runner_->RunUntilIdle();
653
654 EXPECT_BEGIN_FRAME_USED(obs, source_->source_id(), 2, 10000, 20000, 10000);
655 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(9000));
656 task_runner_->RunUntilIdle();
657 source_->RemoveObserver(&obs);
658
659 // New args created 8 intervals later.
660 // Sequence number should increase bt this much.
661 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
662 EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_->source_id(), 10, 90000, 100000,
663 10000);
664 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(80000));
665 source_->AddObserver(&obs);
666 }
667
668 // ExternalBeginFrameSource testing
669 // --------------------------------------------
670 class MockExternalBeginFrameSourceClient
671 : public ExternalBeginFrameSourceClient {
672 public:
673 MockExternalBeginFrameSourceClient() = default;
674 virtual ~MockExternalBeginFrameSourceClient() = default;
675
676 MOCK_METHOD1(OnNeedsBeginFrames, void(bool));
677 };
678
679 class ExternalBeginFrameSourceTest : public ::testing::Test {
680 public:
SetUp()681 void SetUp() override {
682 client_ = std::make_unique<MockExternalBeginFrameSourceClient>();
683 source_ = std::make_unique<ExternalBeginFrameSource>(
684 client_.get(), BeginFrameSource::kNotRestartableId);
685 obs_ = std::make_unique<MockBeginFrameObserver>();
686 }
687
TearDown()688 void TearDown() override {
689 client_.reset();
690 obs_.reset();
691 }
692
693 std::unique_ptr<MockExternalBeginFrameSourceClient> client_;
694 std::unique_ptr<ExternalBeginFrameSource> source_;
695 std::unique_ptr<MockBeginFrameObserver> obs_;
696 };
697
TEST_F(ExternalBeginFrameSourceTest,OnAnimateOnlyBeginFrameOptIn)698 TEST_F(ExternalBeginFrameSourceTest, OnAnimateOnlyBeginFrameOptIn) {
699 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
700 EXPECT_CALL((*client_), OnNeedsBeginFrames(true)).Times(1);
701 source_->AddObserver(obs_.get());
702
703 // By default, an observer doesn't receive animate_only BeginFrames.
704 BeginFrameArgs args = CreateBeginFrameArgsForTesting(
705 BEGINFRAME_FROM_HERE, 0, 2, TicksFromMicroseconds(10000));
706 args.animate_only = true;
707 source_->OnBeginFrame(args);
708
709 // When opting in, an observer receives animate_only BeginFrames.
710 args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 3,
711 TicksFromMicroseconds(10001));
712 args.animate_only = true;
713 EXPECT_CALL(*obs_, WantsAnimateOnlyBeginFrames())
714 .WillOnce(::testing::Return(true));
715 EXPECT_BEGIN_FRAME_ARGS_USED(*obs_, args);
716 source_->OnBeginFrame(args);
717
718 EXPECT_CALL((*client_), OnNeedsBeginFrames(false)).Times(1);
719 source_->RemoveObserver(obs_.get());
720 }
721
TEST_F(ExternalBeginFrameSourceTest,OnBeginFrameChecksBeginFrameContinuity)722 TEST_F(ExternalBeginFrameSourceTest, OnBeginFrameChecksBeginFrameContinuity) {
723 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
724 EXPECT_CALL((*client_), OnNeedsBeginFrames(true)).Times(1);
725 source_->AddObserver(obs_.get());
726
727 BeginFrameArgs args = CreateBeginFrameArgsForTesting(
728 BEGINFRAME_FROM_HERE, 0, 2, TicksFromMicroseconds(10000));
729 EXPECT_BEGIN_FRAME_ARGS_USED(*obs_, args);
730 source_->OnBeginFrame(args);
731
732 // Providing same args again to OnBeginFrame() should not notify observer.
733 source_->OnBeginFrame(args);
734
735 // Providing same args through a different ExternalBeginFrameSource also
736 // does not notify observer.
737 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
738 EXPECT_CALL((*client_), OnNeedsBeginFrames(true)).Times(1);
739 ExternalBeginFrameSource source2(client_.get());
740 source2.AddObserver(obs_.get());
741 source2.OnBeginFrame(args);
742
743 EXPECT_CALL((*client_), OnNeedsBeginFrames(false)).Times(2);
744 source_->RemoveObserver(obs_.get());
745 source2.RemoveObserver(obs_.get());
746 }
747
TEST_F(ExternalBeginFrameSourceTest,GetMissedBeginFrameArgs)748 TEST_F(ExternalBeginFrameSourceTest, GetMissedBeginFrameArgs) {
749 BeginFrameArgs args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0,
750 2, 10000, 10100, 100);
751 source_->OnBeginFrame(args);
752
753 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
754 EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, 0, 2, 10000, 10100, 100);
755 source_->AddObserver(obs_.get());
756 source_->RemoveObserver(obs_.get());
757
758 // Out of order frame_time. This might not be valid but still shouldn't
759 // cause a DCHECK in ExternalBeginFrameSource code.
760 args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, 9999, 10100,
761 101);
762 source_->OnBeginFrame(args);
763
764 EXPECT_CALL((*client_), OnNeedsBeginFrames(true)).Times(1);
765 EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
766 EXPECT_CALL(*obs_, OnBeginFrame(_)).Times(0);
767 source_->AddObserver(obs_.get());
768
769 EXPECT_CALL((*client_), OnNeedsBeginFrames(false)).Times(1);
770 source_->RemoveObserver(obs_.get());
771 }
772
773 // Tests that an observer which returns true from IsRoot is notified after
774 // observers which return false.
TEST_F(ExternalBeginFrameSourceTest,RootsNotifiedLast)775 TEST_F(ExternalBeginFrameSourceTest, RootsNotifiedLast) {
776 using ::testing::InSequence;
777
778 NiceMock<MockBeginFrameObserver> obs1, obs2;
779 source_->AddObserver(&obs1);
780 source_->AddObserver(&obs2);
781
782 {
783 BeginFrameArgs args = CreateBeginFrameArgsForTesting(
784 BEGINFRAME_FROM_HERE, 0, 1, 10000, 10100, 100);
785 // Set obs1 to root, obs2 to child.
786 EXPECT_CALL(obs1, IsRoot()).WillRepeatedly(::testing::Return(true));
787 EXPECT_CALL(obs2, IsRoot()).WillRepeatedly(::testing::Return(false));
788 {
789 // Ensure that OnBeginFrame delivers the calls in the right order.
790 InSequence s;
791 EXPECT_CALL(obs2, OnBeginFrame(args))
792 .WillOnce(::testing::SaveArg<0>(&(obs2.last_begin_frame_args)));
793 EXPECT_CALL(obs1, OnBeginFrame(args))
794 .WillOnce(::testing::SaveArg<0>(&(obs1.last_begin_frame_args)));
795 source_->OnBeginFrame(args);
796 }
797 }
798
799 {
800 BeginFrameArgs args = CreateBeginFrameArgsForTesting(
801 BEGINFRAME_FROM_HERE, 0, 2, 10001, 10101, 100);
802 // Set obs2 to root, obs1 to child.
803 EXPECT_CALL(obs1, IsRoot()).WillRepeatedly(::testing::Return(false));
804 EXPECT_CALL(obs2, IsRoot()).WillRepeatedly(::testing::Return(true));
805 {
806 // Ensure that OnBeginFrame delivers the calls in the right order.
807 InSequence s;
808 EXPECT_CALL(obs1, OnBeginFrame(args))
809 .WillOnce(::testing::SaveArg<0>(&(obs1.last_begin_frame_args)));
810 EXPECT_CALL(obs2, OnBeginFrame(args))
811 .WillOnce(::testing::SaveArg<0>(&(obs2.last_begin_frame_args)));
812 source_->OnBeginFrame(args);
813 }
814 }
815
816 source_->RemoveObserver(&obs1);
817 source_->RemoveObserver(&obs2);
818 }
819
820 } // namespace
821 } // namespace viz
822