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