1 // Copyright 2015 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/service/display/display_scheduler.h"
6
7 #include "base/check.h"
8 #include "base/stl_util.h"
9 #include "base/test/null_task_runner.h"
10 #include "base/test/simple_test_tick_clock.h"
11 #include "base/trace_event/trace_event.h"
12 #include "cc/test/scheduler_test_common.h"
13 #include "components/viz/common/frame_sinks/begin_frame_args.h"
14 #include "components/viz/common/surfaces/surface_info.h"
15 #include "components/viz/service/display/display.h"
16 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
17 #include "components/viz/test/begin_frame_args_test.h"
18 #include "components/viz/test/fake_external_begin_frame_source.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace viz {
22 namespace {
23
24 const int kMaxPendingSwaps = 1;
25
26 static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
27
28 class TestDisplayDamageTracker : public DisplayDamageTracker {
29 public:
30 using DisplayDamageTracker::DisplayDamageTracker;
31 ~TestDisplayDamageTracker() override = default;
32
SurfaceDamagedForTest(const SurfaceId & surface_id,const BeginFrameAck & ack,bool display_damaged)33 void SurfaceDamagedForTest(const SurfaceId& surface_id,
34 const BeginFrameAck& ack,
35 bool display_damaged) {
36 if (display_damaged)
37 undrawn_surfaces_.insert(surface_id);
38 ProcessSurfaceDamage(surface_id, ack, display_damaged);
39 }
ClearUndrawnSurfaces()40 void ClearUndrawnSurfaces() { undrawn_surfaces_.clear(); }
SetRootFrameMissingForTest(bool missing)41 void SetRootFrameMissingForTest(bool missing) {
42 SetRootFrameMissing(missing);
43 }
44
45 // DisplayDamageTracker overrides
SurfaceHasUnackedFrame(const SurfaceId & surface_id) const46 bool SurfaceHasUnackedFrame(const SurfaceId& surface_id) const override {
47 return base::Contains(undrawn_surfaces_, surface_id);
48 }
49
UpdateRootFrameMissing()50 void UpdateRootFrameMissing() override {
51 // We don't create actual surfaces, so make sure they are not missing
52 SetRootFrameMissing(false);
53 }
54
55 private:
56 std::set<SurfaceId> undrawn_surfaces_;
57 };
58
59 class FakeDisplaySchedulerClient : public DisplaySchedulerClient {
60 public:
FakeDisplaySchedulerClient(TestDisplayDamageTracker * damage_tracker)61 explicit FakeDisplaySchedulerClient(TestDisplayDamageTracker* damage_tracker)
62 : damage_tracker_(std::move(damage_tracker)),
63 draw_and_swap_count_(0),
64 next_draw_and_swap_fails_(false) {}
65
~FakeDisplaySchedulerClient()66 ~FakeDisplaySchedulerClient() override {}
67
DrawAndSwap(base::TimeTicks expected_display_time)68 bool DrawAndSwap(base::TimeTicks expected_display_time) override {
69 draw_and_swap_count_++;
70
71 bool success = !next_draw_and_swap_fails_;
72 next_draw_and_swap_fails_ = false;
73
74 if (success)
75 damage_tracker_->ClearUndrawnSurfaces();
76 return success;
77 }
78
DidFinishFrame(const BeginFrameAck & ack)79 void DidFinishFrame(const BeginFrameAck& ack) override {
80 last_begin_frame_ack_ = ack;
81 }
82
draw_and_swap_count() const83 int draw_and_swap_count() const { return draw_and_swap_count_; }
84
SetNextDrawAndSwapFails()85 void SetNextDrawAndSwapFails() { next_draw_and_swap_fails_ = true; }
86
last_begin_frame_ack()87 const BeginFrameAck& last_begin_frame_ack() { return last_begin_frame_ack_; }
88
89 protected:
90 TestDisplayDamageTracker* damage_tracker_ = nullptr;
91 int draw_and_swap_count_;
92 bool next_draw_and_swap_fails_;
93 BeginFrameAck last_begin_frame_ack_;
94 };
95
96 class TestDisplayScheduler : public DisplayScheduler {
97 public:
TestDisplayScheduler(DisplayDamageTracker * damage_tracker,BeginFrameSource * begin_frame_source,SurfaceManager * surface_manager,base::SingleThreadTaskRunner * task_runner,int max_pending_swaps,bool wait_for_all_surfaces_before_draw)98 TestDisplayScheduler(DisplayDamageTracker* damage_tracker,
99 BeginFrameSource* begin_frame_source,
100 SurfaceManager* surface_manager,
101 base::SingleThreadTaskRunner* task_runner,
102 int max_pending_swaps,
103 bool wait_for_all_surfaces_before_draw)
104 : DisplayScheduler(begin_frame_source,
105 task_runner,
106 max_pending_swaps,
107 wait_for_all_surfaces_before_draw),
108 scheduler_begin_frame_deadline_count_(0) {
109 SetDamageTracker(damage_tracker);
110 }
111
DesiredBeginFrameDeadlineTimeForTest()112 base::TimeTicks DesiredBeginFrameDeadlineTimeForTest() {
113 return DesiredBeginFrameDeadlineTime();
114 }
115
BeginFrameDeadlineForTest()116 void BeginFrameDeadlineForTest() {
117 // Ensure that any missed BeginFrames were handled by the scheduler. We need
118 // to run the scheduled task ourselves since the NullTaskRunner won't.
119 if (!missed_begin_frame_task_.IsCancelled())
120 missed_begin_frame_task_.callback().Run();
121 OnBeginFrameDeadline();
122 }
123
ScheduleBeginFrameDeadline()124 void ScheduleBeginFrameDeadline() override {
125 scheduler_begin_frame_deadline_count_++;
126 DisplayScheduler::ScheduleBeginFrameDeadline();
127 }
128
scheduler_begin_frame_deadline_count()129 int scheduler_begin_frame_deadline_count() {
130 return scheduler_begin_frame_deadline_count_;
131 }
132
inside_begin_frame_deadline_interval()133 bool inside_begin_frame_deadline_interval() {
134 return inside_begin_frame_deadline_interval_;
135 }
136
current_frame_time() const137 base::TimeTicks current_frame_time() const {
138 return current_begin_frame_args_.frame_time;
139 }
140
has_pending_surfaces()141 bool has_pending_surfaces() { return has_pending_surfaces_; }
142
is_swap_throttled() const143 bool is_swap_throttled() const {
144 return pending_swaps_ >= max_pending_swaps_;
145 }
146
147 protected:
148 int scheduler_begin_frame_deadline_count_;
149 };
150
151 class DisplaySchedulerTest : public testing::Test {
152 public:
DisplaySchedulerTest(bool wait_for_all_surfaces_before_draw=false)153 explicit DisplaySchedulerTest(bool wait_for_all_surfaces_before_draw = false)
154 : fake_begin_frame_source_(0.f, false),
155 task_runner_(new base::NullTaskRunner),
156 surface_manager_(nullptr, 4u),
157 resource_provider_(DisplayResourceProvider::kSoftware,
158 nullptr,
159 &shared_bitmap_manager_,
160 false),
161 aggregator_(&surface_manager_, &resource_provider_, false, false),
162 damage_tracker_(
163 std::make_unique<TestDisplayDamageTracker>(&surface_manager_,
164 &aggregator_)),
165 client_(damage_tracker_.get()),
166 scheduler_(damage_tracker_.get(),
167 &fake_begin_frame_source_,
168 &surface_manager_,
169 task_runner_.get(),
170 kMaxPendingSwaps,
171 wait_for_all_surfaces_before_draw) {
172 now_src_.Advance(base::TimeDelta::FromMicroseconds(10000));
173 scheduler_.SetClient(&client_);
174 }
175
~DisplaySchedulerTest()176 ~DisplaySchedulerTest() override {
177 }
178
SetUp()179 void SetUp() override { damage_tracker_->SetRootFrameMissingForTest(false); }
180
SetNewRootSurface(SurfaceId surface_id)181 void SetNewRootSurface(SurfaceId surface_id) {
182 damage_tracker_->SetNewRootSurface(surface_id);
183 }
184
AdvanceTimeAndBeginFrameForTest(const std::vector<SurfaceId> & observing_surfaces)185 void AdvanceTimeAndBeginFrameForTest(
186 const std::vector<SurfaceId>& observing_surfaces) {
187 now_src_.Advance(base::TimeDelta::FromMicroseconds(10000));
188 // FakeBeginFrameSource deals with |source_id| and |sequence_number|.
189 last_begin_frame_args_ = fake_begin_frame_source_.CreateBeginFrameArgs(
190 BEGINFRAME_FROM_HERE, &now_src_);
191 fake_begin_frame_source_.TestOnBeginFrame(last_begin_frame_args_);
192 for (const auto& surface_id : observing_surfaces) {
193 damage_tracker_->OnSurfaceDamageExpected(surface_id,
194 last_begin_frame_args_);
195 }
196 }
197
SurfaceDamaged(const SurfaceId & surface_id)198 void SurfaceDamaged(const SurfaceId& surface_id) {
199 damage_tracker_->SurfaceDamagedForTest(surface_id,
200 AckForCurrentBeginFrame(), true);
201 }
202
203 protected:
now_src()204 base::SimpleTestTickClock& now_src() { return now_src_; }
client()205 FakeDisplaySchedulerClient& client() { return client_; }
scheduler()206 DisplayScheduler& scheduler() { return scheduler_; }
AckForCurrentBeginFrame()207 BeginFrameAck AckForCurrentBeginFrame() {
208 DCHECK(last_begin_frame_args_.IsValid());
209 return BeginFrameAck(last_begin_frame_args_, true);
210 }
211
212 FakeExternalBeginFrameSource fake_begin_frame_source_;
213 BeginFrameArgs last_begin_frame_args_;
214
215 base::SimpleTestTickClock now_src_;
216 scoped_refptr<base::NullTaskRunner> task_runner_;
217 SurfaceManager surface_manager_;
218 ServerSharedBitmapManager shared_bitmap_manager_;
219 DisplayResourceProvider resource_provider_;
220 SurfaceAggregator aggregator_;
221 std::unique_ptr<TestDisplayDamageTracker> damage_tracker_;
222 FakeDisplaySchedulerClient client_;
223 TestDisplayScheduler scheduler_;
224 };
225
TEST_F(DisplaySchedulerTest,ResizeHasLateDeadlineUntilNewRootSurface)226 TEST_F(DisplaySchedulerTest, ResizeHasLateDeadlineUntilNewRootSurface) {
227 SurfaceId root_surface_id1(
228 kArbitraryFrameSinkId,
229 LocalSurfaceId(1, base::UnguessableToken::Create()));
230 SurfaceId root_surface_id2(
231 kArbitraryFrameSinkId,
232 LocalSurfaceId(2, base::UnguessableToken::Create()));
233 SurfaceId sid1(kArbitraryFrameSinkId,
234 LocalSurfaceId(3, base::UnguessableToken::Create()));
235 base::TimeTicks late_deadline;
236
237 scheduler_.SetVisible(true);
238
239 // Go trough an initial BeginFrame cycle with the root surface.
240 AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
241 SetNewRootSurface(root_surface_id1);
242 scheduler_.BeginFrameDeadlineForTest();
243
244 // Resize on the next begin frame cycle should cause the deadline to wait
245 // for a new root surface.
246 AdvanceTimeAndBeginFrameForTest({root_surface_id1});
247 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
248 SurfaceDamaged(sid1);
249 EXPECT_GT(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
250 damage_tracker_->DisplayResized();
251 EXPECT_EQ(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
252 damage_tracker_->OnSurfaceMarkedForDestruction(root_surface_id1);
253 SetNewRootSurface(root_surface_id2);
254 EXPECT_GE(now_src().NowTicks(),
255 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
256 scheduler_.BeginFrameDeadlineForTest();
257
258 // Verify deadline goes back to normal after resize.
259 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
260 AdvanceTimeAndBeginFrameForTest({root_surface_id2, sid1});
261 SurfaceDamaged(sid1);
262 EXPECT_GT(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
263 SurfaceDamaged(root_surface_id2);
264 EXPECT_GE(now_src().NowTicks(),
265 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
266 scheduler_.BeginFrameDeadlineForTest();
267 }
268
TEST_F(DisplaySchedulerTest,ResizeHasLateDeadlineUntilDamagedSurface)269 TEST_F(DisplaySchedulerTest, ResizeHasLateDeadlineUntilDamagedSurface) {
270 SurfaceId root_surface_id(
271 kArbitraryFrameSinkId,
272 LocalSurfaceId(1, base::UnguessableToken::Create()));
273 SurfaceId sid1(kArbitraryFrameSinkId,
274 LocalSurfaceId(2, base::UnguessableToken::Create()));
275 base::TimeTicks late_deadline;
276
277 scheduler_.SetVisible(true);
278
279 // Go trough an initial BeginFrame cycle with the root surface.
280 AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
281 SetNewRootSurface(root_surface_id);
282 scheduler_.BeginFrameDeadlineForTest();
283
284 // Resize on the next begin frame cycle should cause the deadline to wait
285 // for a new root surface.
286 AdvanceTimeAndBeginFrameForTest({root_surface_id});
287 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
288 SurfaceDamaged(sid1);
289 EXPECT_GT(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
290 damage_tracker_->DisplayResized();
291 EXPECT_EQ(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
292 SurfaceDamaged(root_surface_id);
293 EXPECT_GE(now_src().NowTicks(),
294 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
295 scheduler_.BeginFrameDeadlineForTest();
296
297 // Verify deadline goes back to normal after resize.
298 AdvanceTimeAndBeginFrameForTest({root_surface_id, sid1});
299 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
300 SurfaceDamaged(sid1);
301 EXPECT_GT(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
302 SurfaceDamaged(root_surface_id);
303 EXPECT_GE(now_src().NowTicks(),
304 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
305 scheduler_.BeginFrameDeadlineForTest();
306 }
307
TEST_F(DisplaySchedulerTest,SurfaceDamaged)308 TEST_F(DisplaySchedulerTest, SurfaceDamaged) {
309 SurfaceId root_surface_id(
310 kArbitraryFrameSinkId,
311 LocalSurfaceId(1, base::UnguessableToken::Create()));
312 SurfaceId sid1(kArbitraryFrameSinkId,
313 LocalSurfaceId(2, base::UnguessableToken::Create()));
314 SurfaceId sid2(kArbitraryFrameSinkId,
315 LocalSurfaceId(3, base::UnguessableToken::Create()));
316
317 scheduler_.SetVisible(true);
318 SetNewRootSurface(root_surface_id);
319 EXPECT_EQ(BeginFrameAck(), client_.last_begin_frame_ack());
320
321 // Set surface1 as active via SurfaceDamageExpected().
322 AdvanceTimeAndBeginFrameForTest({sid1});
323 EXPECT_EQ(BeginFrameAck(), client_.last_begin_frame_ack());
324
325 // Damage only from surface 2 (inactive) does not trigger deadline early.
326 SurfaceDamaged(sid2);
327 EXPECT_TRUE(scheduler_.has_pending_surfaces());
328 EXPECT_LT(now_src().NowTicks(),
329 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
330
331 // Damage from surface 1 triggers deadline early.
332 SurfaceDamaged(sid1);
333 EXPECT_FALSE(scheduler_.has_pending_surfaces());
334 EXPECT_GE(now_src().NowTicks(),
335 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
336 scheduler_.BeginFrameDeadlineForTest();
337 EXPECT_EQ(BeginFrameAck(last_begin_frame_args_, true),
338 client_.last_begin_frame_ack());
339
340 // Set both surface 1 and 2 as active via SurfaceDamageExpected().
341 AdvanceTimeAndBeginFrameForTest({sid1, sid2});
342
343 // Deadline doesn't trigger early until surface 1 and 2 are both damaged.
344 EXPECT_LT(now_src().NowTicks(),
345 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
346 SurfaceDamaged(sid1);
347 EXPECT_LT(now_src().NowTicks(),
348 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
349 SurfaceDamaged(sid2);
350 EXPECT_GE(now_src().NowTicks(),
351 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
352 scheduler_.BeginFrameDeadlineForTest();
353 EXPECT_EQ(BeginFrameAck(last_begin_frame_args_, true),
354 client_.last_begin_frame_ack());
355
356 // Surface damage with |!has_damage| triggers early deadline if other damage
357 // exists.
358 AdvanceTimeAndBeginFrameForTest({sid1, sid2});
359 EXPECT_LT(now_src().NowTicks(),
360 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
361 SurfaceDamaged(sid2);
362 EXPECT_LT(now_src().NowTicks(),
363 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
364 BeginFrameAck ack = AckForCurrentBeginFrame();
365 ack.has_damage = false;
366 damage_tracker_->SurfaceDamagedForTest(sid1, ack, false);
367 EXPECT_GE(now_src().NowTicks(),
368 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
369 scheduler_.BeginFrameDeadlineForTest();
370
371 // Surface damage with |!has_damage| does not trigger early deadline if no
372 // other damage exists.
373 AdvanceTimeAndBeginFrameForTest({sid1});
374 EXPECT_LT(now_src().NowTicks(),
375 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
376 ack = AckForCurrentBeginFrame();
377 ack.has_damage = false;
378 damage_tracker_->SurfaceDamagedForTest(sid1, ack, false);
379 EXPECT_LT(now_src().NowTicks(),
380 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
381 scheduler_.BeginFrameDeadlineForTest();
382 EXPECT_EQ(BeginFrameAck(last_begin_frame_args_, false),
383 client_.last_begin_frame_ack());
384
385 // System should be idle now.
386 AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
387 EXPECT_FALSE(scheduler_.inside_begin_frame_deadline_interval());
388
389 // Surface damage with |!display_damaged| does not affect needs_draw and
390 // scheduler stays idle.
391 damage_tracker_->SurfaceDamagedForTest(sid1, AckForCurrentBeginFrame(),
392 false);
393 EXPECT_FALSE(scheduler_.inside_begin_frame_deadline_interval());
394
395 // Deadline should trigger early if child surfaces are idle and
396 // we get damage on the root surface.
397 damage_tracker_->OnSurfaceDamageExpected(root_surface_id,
398 last_begin_frame_args_);
399 EXPECT_FALSE(scheduler_.inside_begin_frame_deadline_interval());
400 SurfaceDamaged(root_surface_id);
401 EXPECT_GE(now_src().NowTicks(),
402 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
403 scheduler_.BeginFrameDeadlineForTest();
404 }
405
406 class DisplaySchedulerWaitForAllSurfacesTest : public DisplaySchedulerTest {
407 public:
DisplaySchedulerWaitForAllSurfacesTest()408 DisplaySchedulerWaitForAllSurfacesTest()
409 : DisplaySchedulerTest(true /* wait_for_all_surfaces_before_draw */) {}
410 };
411
TEST_F(DisplaySchedulerWaitForAllSurfacesTest,WaitForAllSurfacesBeforeDraw)412 TEST_F(DisplaySchedulerWaitForAllSurfacesTest, WaitForAllSurfacesBeforeDraw) {
413 SurfaceId root_surface_id(
414 kArbitraryFrameSinkId,
415 LocalSurfaceId(1, base::UnguessableToken::Create()));
416 SurfaceId sid1(kArbitraryFrameSinkId,
417 LocalSurfaceId(2, base::UnguessableToken::Create()));
418 SurfaceId sid2(kArbitraryFrameSinkId,
419 LocalSurfaceId(3, base::UnguessableToken::Create()));
420
421 scheduler_.SetVisible(true);
422 SetNewRootSurface(root_surface_id);
423
424 // Set surface1 as active via SurfaceDamageExpected().
425 AdvanceTimeAndBeginFrameForTest({sid1});
426
427 // Deadline is blocked indefinitely until surface 1 is damaged.
428 EXPECT_EQ(base::TimeTicks::Max(),
429 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
430
431 // Damage only from surface 2 (inactive) does not change deadline.
432 SurfaceDamaged(sid2);
433 EXPECT_TRUE(scheduler_.has_pending_surfaces());
434 EXPECT_EQ(base::TimeTicks::Max(),
435 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
436
437 // Damage from surface 1 triggers deadline immediately.
438 SurfaceDamaged(sid1);
439 EXPECT_FALSE(scheduler_.has_pending_surfaces());
440 EXPECT_GE(now_src().NowTicks(),
441 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
442 scheduler_.BeginFrameDeadlineForTest();
443
444 // Surface damage with |!has_damage| triggers immediate deadline if other
445 // damage exists.
446 AdvanceTimeAndBeginFrameForTest({sid1, sid2});
447 EXPECT_EQ(base::TimeTicks::Max(),
448 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
449 SurfaceDamaged(sid2);
450 EXPECT_EQ(base::TimeTicks::Max(),
451 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
452 BeginFrameAck ack = AckForCurrentBeginFrame();
453 ack.has_damage = false;
454 damage_tracker_->SurfaceDamagedForTest(sid1, ack, false);
455 EXPECT_GE(now_src().NowTicks(),
456 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
457 scheduler_.BeginFrameDeadlineForTest();
458
459 // Surface damage with |!has_damage| also triggers immediate deadline even if
460 // no other damage exists.
461 AdvanceTimeAndBeginFrameForTest({sid1});
462 EXPECT_EQ(base::TimeTicks::Max(),
463 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
464 ack = AckForCurrentBeginFrame();
465 ack.has_damage = false;
466 damage_tracker_->SurfaceDamagedForTest(sid1, ack, false);
467 EXPECT_GE(now_src().NowTicks(),
468 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
469 // Stray BeginFrameAcks for older BeginFrames are ignored.
470 ack.frame_id.sequence_number--;
471 damage_tracker_->SurfaceDamagedForTest(sid1, ack, false);
472 // If the acknowledgment above was not ignored and instead updated the surface
473 // state for sid1, the surface would become a pending surface again, and the
474 // deadline would no longer be immediate. Since it is ignored, we are
475 // expecting the deadline to remain immedate.
476 EXPECT_GE(now_src().NowTicks(),
477 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
478 scheduler_.BeginFrameDeadlineForTest();
479
480 // System should be idle now because we had a frame without damage. Restore it
481 // to active state (DisplayScheduler observing BeginFrames) for the next test.
482 AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
483 EXPECT_FALSE(scheduler_.inside_begin_frame_deadline_interval());
484 SurfaceDamaged(sid1);
485 scheduler_.BeginFrameDeadlineForTest();
486
487 // BeginFrame without expected surface damage triggers immediate deadline.
488 AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
489 EXPECT_TRUE(scheduler_.inside_begin_frame_deadline_interval());
490 EXPECT_GE(now_src().NowTicks(),
491 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
492 scheduler_.BeginFrameDeadlineForTest();
493 }
494
TEST_F(DisplaySchedulerTest,OutputSurfaceLost)495 TEST_F(DisplaySchedulerTest, OutputSurfaceLost) {
496 SurfaceId root_surface_id(
497 kArbitraryFrameSinkId,
498 LocalSurfaceId(1, base::UnguessableToken::Create()));
499 SurfaceId sid1(kArbitraryFrameSinkId,
500 LocalSurfaceId(2, base::UnguessableToken::Create()));
501
502 scheduler_.SetVisible(true);
503 SetNewRootSurface(root_surface_id);
504
505 // DrawAndSwap normally.
506 AdvanceTimeAndBeginFrameForTest({sid1});
507 EXPECT_LT(now_src().NowTicks(),
508 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
509 EXPECT_EQ(0, client_.draw_and_swap_count());
510 SurfaceDamaged(sid1);
511 scheduler_.BeginFrameDeadlineForTest();
512 EXPECT_EQ(1, client_.draw_and_swap_count());
513
514 // Deadline triggers immediately on OutputSurfaceLost.
515 AdvanceTimeAndBeginFrameForTest({sid1});
516 EXPECT_LT(now_src().NowTicks(),
517 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
518 scheduler_.OutputSurfaceLost();
519 EXPECT_GE(now_src().NowTicks(),
520 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
521
522 // Deadline does not DrawAndSwap after OutputSurfaceLost.
523 EXPECT_EQ(1, client_.draw_and_swap_count());
524 SurfaceDamaged(sid1);
525 scheduler_.BeginFrameDeadlineForTest();
526 EXPECT_EQ(1, client_.draw_and_swap_count());
527 }
528
TEST_F(DisplaySchedulerTest,VisibleWithoutDamageNoTicks)529 TEST_F(DisplaySchedulerTest, VisibleWithoutDamageNoTicks) {
530 SurfaceId root_surface_id(
531 kArbitraryFrameSinkId,
532 LocalSurfaceId(1, base::UnguessableToken::Create()));
533
534 EXPECT_EQ(0u, fake_begin_frame_source_.num_observers());
535 scheduler_.SetVisible(true);
536
537 // When becoming visible, don't start listening for begin frames until there
538 // is some damage.
539 EXPECT_EQ(0u, fake_begin_frame_source_.num_observers());
540 SetNewRootSurface(root_surface_id);
541
542 EXPECT_EQ(1u, fake_begin_frame_source_.num_observers());
543 }
544
TEST_F(DisplaySchedulerTest,VisibleWithDamageTicks)545 TEST_F(DisplaySchedulerTest, VisibleWithDamageTicks) {
546 SurfaceId root_surface_id(
547 kArbitraryFrameSinkId,
548 LocalSurfaceId(1, base::UnguessableToken::Create()));
549 SurfaceId sid1(kArbitraryFrameSinkId,
550 LocalSurfaceId(2, base::UnguessableToken::Create()));
551
552 SetNewRootSurface(root_surface_id);
553
554 // When there is damage, start listening for begin frames once becoming
555 // visible.
556 EXPECT_EQ(0u, fake_begin_frame_source_.num_observers());
557 scheduler_.SetVisible(true);
558
559 EXPECT_EQ(1u, fake_begin_frame_source_.num_observers());
560 }
561
TEST_F(DisplaySchedulerTest,Visibility)562 TEST_F(DisplaySchedulerTest, Visibility) {
563 SurfaceId root_surface_id(
564 kArbitraryFrameSinkId,
565 LocalSurfaceId(1, base::UnguessableToken::Create()));
566 SurfaceId sid1(kArbitraryFrameSinkId,
567 LocalSurfaceId(2, base::UnguessableToken::Create()));
568
569 // Set the root surface.
570 SetNewRootSurface(root_surface_id);
571 scheduler_.SetVisible(true);
572 EXPECT_EQ(1u, fake_begin_frame_source_.num_observers());
573
574 // DrawAndSwap normally.
575 AdvanceTimeAndBeginFrameForTest({sid1});
576 EXPECT_LT(now_src().NowTicks(),
577 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
578 EXPECT_EQ(0, client_.draw_and_swap_count());
579 SurfaceDamaged(sid1);
580 scheduler_.BeginFrameDeadlineForTest();
581 EXPECT_EQ(1, client_.draw_and_swap_count());
582
583 AdvanceTimeAndBeginFrameForTest({sid1});
584 EXPECT_LT(now_src().NowTicks(),
585 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
586
587 // Become not visible.
588 scheduler_.SetVisible(false);
589
590 // It will stop listening for begin frames after the current deadline.
591 EXPECT_EQ(1u, fake_begin_frame_source_.num_observers());
592
593 // Deadline does not DrawAndSwap when not visible.
594 EXPECT_EQ(1, client_.draw_and_swap_count());
595 scheduler_.BeginFrameDeadlineForTest();
596 EXPECT_EQ(1, client_.draw_and_swap_count());
597 // Now it stops listening for begin frames.
598 EXPECT_EQ(0u, fake_begin_frame_source_.num_observers());
599
600 // Does not start listening for begin frames when becoming visible without
601 // damage.
602 scheduler_.SetVisible(true);
603 EXPECT_EQ(0u, fake_begin_frame_source_.num_observers());
604 scheduler_.SetVisible(false);
605
606 // Does not start listening for begin frames when damage arrives.
607 SurfaceDamaged(sid1);
608 EXPECT_EQ(0u, fake_begin_frame_source_.num_observers());
609
610 // But does when becoming visible with damage again.
611 scheduler_.SetVisible(true);
612 EXPECT_EQ(1u, fake_begin_frame_source_.num_observers());
613 }
614
TEST_F(DisplaySchedulerTest,ResizeCausesSwap)615 TEST_F(DisplaySchedulerTest, ResizeCausesSwap) {
616 SurfaceId root_surface_id(
617 kArbitraryFrameSinkId,
618 LocalSurfaceId(1, base::UnguessableToken::Create()));
619 SurfaceId sid1(kArbitraryFrameSinkId,
620 LocalSurfaceId(2, base::UnguessableToken::Create()));
621
622 scheduler_.SetVisible(true);
623 SetNewRootSurface(root_surface_id);
624
625 // DrawAndSwap normally.
626 AdvanceTimeAndBeginFrameForTest({sid1});
627 EXPECT_LT(now_src().NowTicks(),
628 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
629 EXPECT_EQ(0, client_.draw_and_swap_count());
630 SurfaceDamaged(sid1);
631 scheduler_.BeginFrameDeadlineForTest();
632 EXPECT_EQ(1, client_.draw_and_swap_count());
633
634 damage_tracker_->DisplayResized();
635 AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
636 // DisplayResizedd should trigger a swap to happen.
637 scheduler_.BeginFrameDeadlineForTest();
638 EXPECT_EQ(2, client_.draw_and_swap_count());
639 }
640
TEST_F(DisplaySchedulerTest,RootFrameMissing)641 TEST_F(DisplaySchedulerTest, RootFrameMissing) {
642 SurfaceId root_surface_id(
643 kArbitraryFrameSinkId,
644 LocalSurfaceId(1, base::UnguessableToken::Create()));
645 SurfaceId sid1(kArbitraryFrameSinkId,
646 LocalSurfaceId(2, base::UnguessableToken::Create()));
647 base::TimeTicks late_deadline;
648
649 scheduler_.SetVisible(true);
650 SetNewRootSurface(root_surface_id);
651
652 // DrawAndSwap normally.
653 AdvanceTimeAndBeginFrameForTest({sid1});
654 EXPECT_LT(now_src().NowTicks(),
655 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
656 EXPECT_EQ(0, client_.draw_and_swap_count());
657 SurfaceDamaged(sid1);
658 scheduler_.BeginFrameDeadlineForTest();
659 EXPECT_EQ(1, client_.draw_and_swap_count());
660
661 // Deadline triggers late while root frame is missing.
662 AdvanceTimeAndBeginFrameForTest({sid1});
663 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
664 SurfaceDamaged(sid1);
665 EXPECT_GT(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
666 damage_tracker_->SetRootFrameMissingForTest(true);
667 EXPECT_EQ(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
668
669 // Deadline does not DrawAndSwap while root frame is missing.
670 EXPECT_EQ(1, client_.draw_and_swap_count());
671 SurfaceDamaged(sid1);
672 scheduler_.BeginFrameDeadlineForTest();
673 EXPECT_EQ(1, client_.draw_and_swap_count());
674
675 // Deadline triggers normally when root frame is not missing.
676 AdvanceTimeAndBeginFrameForTest({sid1, root_surface_id});
677 EXPECT_FALSE(scheduler_.inside_begin_frame_deadline_interval());
678 SurfaceDamaged(sid1);
679
680 // The deadline is not updated because the display scheduler does not receive
681 // a BeginFrame while the root frame is missing.
682 EXPECT_EQ(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
683 damage_tracker_->SetRootFrameMissingForTest(false);
684 EXPECT_TRUE(scheduler_.inside_begin_frame_deadline_interval());
685 SurfaceDamaged(root_surface_id);
686 EXPECT_EQ(base::TimeTicks(),
687 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
688
689 EXPECT_EQ(1, client_.draw_and_swap_count());
690 scheduler_.BeginFrameDeadlineForTest();
691 EXPECT_EQ(2, client_.draw_and_swap_count());
692 }
693
TEST_F(DisplaySchedulerTest,DidSwapBuffers)694 TEST_F(DisplaySchedulerTest, DidSwapBuffers) {
695 SurfaceId root_surface_id(
696 kArbitraryFrameSinkId,
697 LocalSurfaceId(1, base::UnguessableToken::Create()));
698 SurfaceId sid1(kArbitraryFrameSinkId,
699 LocalSurfaceId(2, base::UnguessableToken::Create()));
700 SurfaceId sid2(kArbitraryFrameSinkId,
701 LocalSurfaceId(3, base::UnguessableToken::Create()));
702
703 scheduler_.SetVisible(true);
704 SetNewRootSurface(root_surface_id);
705
706 // Set surface 1 and 2 as active.
707 AdvanceTimeAndBeginFrameForTest({sid1, sid2});
708
709 // DrawAndSwap normally.
710 EXPECT_LT(now_src().NowTicks(),
711 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
712 EXPECT_EQ(0, client_.draw_and_swap_count());
713 SurfaceDamaged(sid1);
714 SurfaceDamaged(sid2);
715 scheduler_.BeginFrameDeadlineForTest();
716 EXPECT_EQ(1, client_.draw_and_swap_count());
717 scheduler_.DidSwapBuffers();
718
719 // Deadline triggers late when swap throttled.
720 AdvanceTimeAndBeginFrameForTest({sid1, sid2});
721 base::TimeTicks late_deadline =
722 now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
723 // Damage surface 1, but not surface 2 so we avoid triggering deadline
724 // early because all surfaces are ready.
725 SurfaceDamaged(sid1);
726 EXPECT_EQ(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
727
728 // Don't draw and swap in deadline while swap throttled.
729 EXPECT_EQ(1, client_.draw_and_swap_count());
730 scheduler_.BeginFrameDeadlineForTest();
731 EXPECT_EQ(1, client_.draw_and_swap_count());
732
733 // Deadline triggers normally once not swap throttled.
734 // Damage from previous BeginFrame should cary over, so don't damage again.
735 scheduler_.DidReceiveSwapBuffersAck();
736 AdvanceTimeAndBeginFrameForTest({sid2});
737 base::TimeTicks expected_deadline =
738 last_begin_frame_args_.deadline -
739 BeginFrameArgs::DefaultEstimatedDisplayDrawTime(
740 last_begin_frame_args_.interval);
741 EXPECT_EQ(expected_deadline,
742 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
743 // Still waiting for surface 2. Once it updates, deadline should trigger
744 // immediately again.
745 SurfaceDamaged(sid2);
746 EXPECT_EQ(base::TimeTicks(),
747 scheduler_.DesiredBeginFrameDeadlineTimeForTest());
748 // Draw and swap now that we aren't throttled.
749 EXPECT_EQ(1, client_.draw_and_swap_count());
750 scheduler_.BeginFrameDeadlineForTest();
751 EXPECT_EQ(2, client_.draw_and_swap_count());
752 }
753
754 // This test verfies that we try to reschedule the deadline
755 // after any event that may change what deadline we want.
TEST_F(DisplaySchedulerTest,ScheduleBeginFrameDeadline)756 TEST_F(DisplaySchedulerTest, ScheduleBeginFrameDeadline) {
757 SurfaceId root_surface_id(
758 kArbitraryFrameSinkId,
759 LocalSurfaceId(1, base::UnguessableToken::Create()));
760 SurfaceId sid1(kArbitraryFrameSinkId,
761 LocalSurfaceId(2, base::UnguessableToken::Create()));
762 int count = 1;
763 EXPECT_EQ(count, scheduler_.scheduler_begin_frame_deadline_count());
764
765 scheduler_.SetVisible(true);
766 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
767
768 scheduler_.SetVisible(true);
769 EXPECT_EQ(count, scheduler_.scheduler_begin_frame_deadline_count());
770
771 scheduler_.SetVisible(false);
772 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
773
774 // Set the root surface while not visible.
775 SetNewRootSurface(root_surface_id);
776 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
777
778 scheduler_.SetVisible(true);
779 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
780
781 // Set the root surface while visible.
782 SetNewRootSurface(root_surface_id);
783 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
784
785 AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
786 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
787
788 scheduler_.BeginFrameDeadlineForTest();
789 scheduler_.DidSwapBuffers();
790 AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
791 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
792
793 scheduler_.DidReceiveSwapBuffersAck();
794 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
795
796 damage_tracker_->DisplayResized();
797 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
798
799 SetNewRootSurface(root_surface_id);
800 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
801
802 SurfaceDamaged(sid1);
803 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
804
805 damage_tracker_->SetRootFrameMissingForTest(true);
806 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
807
808 scheduler_.OutputSurfaceLost();
809 EXPECT_EQ(++count, scheduler_.scheduler_begin_frame_deadline_count());
810 }
811
TEST_F(DisplaySchedulerTest,SetNeedsOneBeginFrame)812 TEST_F(DisplaySchedulerTest, SetNeedsOneBeginFrame) {
813 SurfaceId root_surface_id(
814 kArbitraryFrameSinkId,
815 LocalSurfaceId(1, base::UnguessableToken::Create()));
816
817 scheduler_.SetVisible(true);
818 SetNewRootSurface(root_surface_id);
819
820 // Make system idle.
821 AdvanceTimeAndBeginFrameForTest({root_surface_id});
822 SurfaceDamaged(root_surface_id);
823 scheduler_.BeginFrameDeadlineForTest();
824 AdvanceTimeAndBeginFrameForTest({root_surface_id});
825 scheduler_.BeginFrameDeadlineForTest();
826
827 AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
828 EXPECT_FALSE(scheduler_.inside_begin_frame_deadline_interval());
829
830 // SetNeedsOneBeginFrame should make DisplayScheduler active for just a single
831 // BeginFrame.
832 scheduler_.SetNeedsOneBeginFrame(false);
833 EXPECT_TRUE(scheduler_.inside_begin_frame_deadline_interval());
834 scheduler_.BeginFrameDeadlineForTest();
835 EXPECT_EQ(BeginFrameAck(last_begin_frame_args_, false),
836 client_.last_begin_frame_ack());
837
838 // System should be idle again.
839 AdvanceTimeAndBeginFrameForTest(std::vector<SurfaceId>());
840 EXPECT_FALSE(scheduler_.inside_begin_frame_deadline_interval());
841 }
842
TEST_F(DisplaySchedulerTest,GpuBusyNotifications)843 TEST_F(DisplaySchedulerTest, GpuBusyNotifications) {
844 SurfaceId root_surface_id(
845 kArbitraryFrameSinkId,
846 LocalSurfaceId(1, base::UnguessableToken::Create()));
847
848 scheduler_.SetVisible(true);
849 SetNewRootSurface(root_surface_id);
850
851 // Swap one frame, since max pending swaps is 1 it puts us in a swap throttled
852 // state.
853 AdvanceTimeAndBeginFrameForTest({root_surface_id});
854 EXPECT_EQ(scheduler_.current_frame_time(), last_begin_frame_args_.frame_time);
855 EXPECT_EQ(client().draw_and_swap_count(), 0);
856 SurfaceDamaged(root_surface_id);
857 scheduler_.BeginFrameDeadlineForTest();
858 EXPECT_EQ(client().draw_and_swap_count(), 1);
859 scheduler_.DidSwapBuffers();
860 EXPECT_TRUE(scheduler_.is_swap_throttled());
861
862 // The next vsync should not be blocked from the swap throttling.
863 EXPECT_FALSE(fake_begin_frame_source_.RequestCallbackOnGpuAvailable());
864
865 // Send the next vsync, after which vsyncs will be blocked on busy gpu.
866 EXPECT_TRUE(fake_begin_frame_source_.RequestCallbackOnGpuAvailable());
867
868 // Ack the pending swap buffers, we should no longer be marked gpu busy.
869 scheduler_.DidReceiveSwapBuffersAck();
870 EXPECT_FALSE(fake_begin_frame_source_.RequestCallbackOnGpuAvailable());
871 }
872
TEST_F(DisplaySchedulerTest,OnBeginFrameDeadlineNoClient)873 TEST_F(DisplaySchedulerTest, OnBeginFrameDeadlineNoClient) {
874 SurfaceId root_surface_id(
875 kArbitraryFrameSinkId,
876 LocalSurfaceId(1, base::UnguessableToken::Create()));
877
878 scheduler_.SetVisible(true);
879 SetNewRootSurface(root_surface_id);
880
881 AdvanceTimeAndBeginFrameForTest({root_surface_id});
882 SurfaceDamaged(root_surface_id);
883
884 // During teardown, we may get a BeginFrameDeadline while |client_| is null.
885 // This should not crash.
886 scheduler_.SetClient(nullptr);
887 scheduler_.BeginFrameDeadlineForTest();
888 }
889
890 } // namespace
891 } // namespace viz
892