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 "cc/scheduler/scheduler.h"
6
7 #include <stddef.h>
8
9 #include <string>
10 #include <vector>
11
12 #include "base/auto_reset.h"
13 #include "base/bind.h"
14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/numerics/safe_conversions.h"
17 #include "base/run_loop.h"
18 #include "base/test/test_mock_time_task_runner.h"
19 #include "base/time/time.h"
20 #include "base/trace_event/trace_event.h"
21 #include "cc/metrics/begin_main_frame_metrics.h"
22 #include "cc/metrics/event_metrics.h"
23 #include "cc/test/scheduler_test_common.h"
24 #include "components/viz/common/frame_sinks/begin_frame_args.h"
25 #include "components/viz/test/begin_frame_args_test.h"
26 #include "components/viz/test/fake_delay_based_time_source.h"
27 #include "components/viz/test/fake_external_begin_frame_source.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30
31 #define EXPECT_ACTIONS(...) \
32 EXPECT_THAT(client_->Actions(), ::testing::ElementsAre(__VA_ARGS__))
33
34 #define EXPECT_NO_ACTION() EXPECT_THAT(client_->Actions(), ::testing::IsEmpty())
35
36 #define EXPECT_SCOPED(statements) \
37 { \
38 SCOPED_TRACE(""); \
39 statements; \
40 }
41
42 namespace cc {
43 namespace {
44
45 base::TimeDelta kSlowDuration = base::TimeDelta::FromSeconds(1);
46 base::TimeDelta kFastDuration = base::TimeDelta::FromMilliseconds(1);
47
48 class FakeSchedulerClient : public SchedulerClient,
49 public viz::FakeExternalBeginFrameSource::Client {
50 public:
FakeSchedulerClient()51 FakeSchedulerClient() { Reset(); }
52
Reset()53 void Reset() {
54 actions_.clear();
55 will_begin_impl_frame_causes_redraw_ = false;
56 will_begin_impl_frame_requests_one_begin_impl_frame_ = false;
57 invalidate_needs_redraw_ = true;
58 draw_will_happen_ = true;
59 swap_will_happen_if_draw_happens_ = true;
60 num_draws_ = 0;
61 last_begin_main_frame_args_ = viz::BeginFrameArgs();
62 last_begin_frame_ack_ = viz::BeginFrameAck();
63 }
64
set_scheduler(TestScheduler * scheduler)65 void set_scheduler(TestScheduler* scheduler) { scheduler_ = scheduler; }
66
needs_begin_frames()67 bool needs_begin_frames() { return scheduler_->begin_frames_expected(); }
num_draws() const68 int num_draws() const { return num_draws_; }
invalidate_needs_redraw() const69 bool invalidate_needs_redraw() const { return invalidate_needs_redraw_; }
Actions() const70 const std::vector<std::string> Actions() const {
71 return std::vector<std::string>(actions_.begin(), actions_.end());
72 }
posted_begin_impl_frame_deadline() const73 base::TimeTicks posted_begin_impl_frame_deadline() const {
74 return posted_begin_impl_frame_deadline_;
75 }
76
frame_interval() const77 base::TimeDelta frame_interval() const { return frame_interval_; }
78
ActionIndex(const char * action) const79 int ActionIndex(const char* action) const {
80 for (size_t i = 0; i < actions_.size(); i++)
81 if (!strcmp(actions_[i], action))
82 return base::checked_cast<int>(i);
83 return -1;
84 }
85
HasAction(const char * action) const86 bool HasAction(const char* action) const { return ActionIndex(action) >= 0; }
87
SetWillBeginImplFrameRequestsOneBeginImplFrame(bool request)88 void SetWillBeginImplFrameRequestsOneBeginImplFrame(bool request) {
89 will_begin_impl_frame_requests_one_begin_impl_frame_ = request;
90 }
SetWillBeginImplFrameCausesRedraw(bool causes_redraw)91 void SetWillBeginImplFrameCausesRedraw(bool causes_redraw) {
92 will_begin_impl_frame_causes_redraw_ = causes_redraw;
93 }
SetInvalidateNeedsRedraw(bool needs_redraw)94 void SetInvalidateNeedsRedraw(bool needs_redraw) {
95 invalidate_needs_redraw_ = needs_redraw;
96 }
SetDrawWillHappen(bool draw_will_happen)97 void SetDrawWillHappen(bool draw_will_happen) {
98 draw_will_happen_ = draw_will_happen;
99 }
SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens)100 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
101 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
102 }
SetAutomaticSubmitCompositorFrameAck(bool automatic_ack)103 void SetAutomaticSubmitCompositorFrameAck(bool automatic_ack) {
104 automatic_ack_ = automatic_ack;
105 }
SetWillBeginImplFrameMightHaveDamage(bool might_have_damage)106 void SetWillBeginImplFrameMightHaveDamage(bool might_have_damage) {
107 will_begin_impl_frame_might_have_damage_ = might_have_damage;
108 }
109 // SchedulerClient implementation.
WillBeginImplFrame(const viz::BeginFrameArgs & args)110 bool WillBeginImplFrame(const viz::BeginFrameArgs& args) override {
111 EXPECT_FALSE(inside_begin_impl_frame_);
112 EXPECT_FALSE(inside_action_);
113 base::AutoReset<bool> mark_inside(&inside_action_, true);
114 inside_begin_impl_frame_ = true;
115 PushAction("WillBeginImplFrame");
116 if (will_begin_impl_frame_requests_one_begin_impl_frame_)
117 scheduler_->SetNeedsOneBeginImplFrame();
118 if (will_begin_impl_frame_causes_redraw_)
119 scheduler_->SetNeedsRedraw();
120 return will_begin_impl_frame_might_have_damage_;
121 }
DidFinishImplFrame()122 void DidFinishImplFrame() override {
123 EXPECT_TRUE(inside_begin_impl_frame_);
124 EXPECT_FALSE(inside_action_);
125 base::AutoReset<bool> mark_inside(&inside_action_, true);
126 inside_begin_impl_frame_ = false;
127 }
DidNotProduceFrame(const viz::BeginFrameAck & ack,FrameSkippedReason reason)128 void DidNotProduceFrame(const viz::BeginFrameAck& ack,
129 FrameSkippedReason reason) override {
130 EXPECT_FALSE(inside_action_);
131 base::AutoReset<bool> mark_inside(&inside_action_, true);
132 last_begin_frame_ack_ = ack;
133 }
134
WillNotReceiveBeginFrame()135 void WillNotReceiveBeginFrame() override {}
136
ScheduledActionSendBeginMainFrame(const viz::BeginFrameArgs & args)137 void ScheduledActionSendBeginMainFrame(
138 const viz::BeginFrameArgs& args) override {
139 EXPECT_FALSE(inside_action_);
140 base::AutoReset<bool> mark_inside(&inside_action_, true);
141 PushAction("ScheduledActionSendBeginMainFrame");
142 last_begin_main_frame_args_ = args;
143 }
FrameIntervalUpdated(base::TimeDelta interval)144 void FrameIntervalUpdated(base::TimeDelta interval) override {
145 frame_interval_ = interval;
146 }
147
last_begin_main_frame_args()148 const viz::BeginFrameArgs& last_begin_main_frame_args() {
149 return last_begin_main_frame_args_;
150 }
151
last_begin_frame_ack()152 const viz::BeginFrameAck& last_begin_frame_ack() {
153 return last_begin_frame_ack_;
154 }
155
ScheduledActionDrawIfPossible()156 DrawResult ScheduledActionDrawIfPossible() override {
157 EXPECT_FALSE(inside_action_);
158 base::AutoReset<bool> mark_inside(&inside_action_, true);
159 PushAction("ScheduledActionDrawIfPossible");
160 num_draws_++;
161 DrawResult result =
162 draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
163 bool swap_will_happen =
164 draw_will_happen_ && swap_will_happen_if_draw_happens_;
165 if (swap_will_happen) {
166 last_begin_frame_ack_ = scheduler_->CurrentBeginFrameAckForActiveTree();
167 scheduler_->DidSubmitCompositorFrame(0, EventMetricsSet());
168
169 if (automatic_ack_)
170 scheduler_->DidReceiveCompositorFrameAck();
171 }
172 return result;
173 }
ScheduledActionDrawForced()174 DrawResult ScheduledActionDrawForced() override {
175 EXPECT_FALSE(inside_action_);
176 base::AutoReset<bool> mark_inside(&inside_action_, true);
177 PushAction("ScheduledActionDrawForced");
178 last_begin_frame_ack_ = scheduler_->CurrentBeginFrameAckForActiveTree();
179 return DRAW_SUCCESS;
180 }
ScheduledActionCommit()181 void ScheduledActionCommit() override {
182 EXPECT_FALSE(inside_action_);
183 base::AutoReset<bool> mark_inside(&inside_action_, true);
184 PushAction("ScheduledActionCommit");
185 scheduler_->DidCommit();
186 }
ScheduledActionActivateSyncTree()187 void ScheduledActionActivateSyncTree() override {
188 EXPECT_FALSE(inside_action_);
189 base::AutoReset<bool> mark_inside(&inside_action_, true);
190 PushAction("ScheduledActionActivateSyncTree");
191 }
ScheduledActionBeginLayerTreeFrameSinkCreation()192 void ScheduledActionBeginLayerTreeFrameSinkCreation() override {
193 EXPECT_FALSE(inside_action_);
194 base::AutoReset<bool> mark_inside(&inside_action_, true);
195 PushAction("ScheduledActionBeginLayerTreeFrameSinkCreation");
196 }
ScheduledActionPrepareTiles()197 void ScheduledActionPrepareTiles() override {
198 EXPECT_FALSE(inside_action_);
199 base::AutoReset<bool> mark_inside(&inside_action_, true);
200 PushAction("ScheduledActionPrepareTiles");
201 scheduler_->WillPrepareTiles();
202 scheduler_->DidPrepareTiles();
203 }
ScheduledActionInvalidateLayerTreeFrameSink(bool needs_redraw)204 void ScheduledActionInvalidateLayerTreeFrameSink(bool needs_redraw) override {
205 EXPECT_FALSE(inside_action_);
206 base::AutoReset<bool> mark_inside(&inside_action_, true);
207 invalidate_needs_redraw_ = needs_redraw;
208 actions_.push_back("ScheduledActionInvalidateLayerTreeFrameSink");
209 }
ScheduledActionPerformImplSideInvalidation()210 void ScheduledActionPerformImplSideInvalidation() override {
211 EXPECT_FALSE(inside_action_);
212 base::AutoReset<bool> mark_inside(&inside_action_, true);
213 PushAction("ScheduledActionPerformImplSideInvalidation");
214 }
215
SendBeginMainFrameNotExpectedSoon()216 void SendBeginMainFrameNotExpectedSoon() override {
217 EXPECT_FALSE(inside_action_);
218 base::AutoReset<bool> mark_inside(&inside_action_, true);
219 PushAction("SendBeginMainFrameNotExpectedSoon");
220 }
221
ScheduledActionBeginMainFrameNotExpectedUntil(base::TimeTicks time)222 void ScheduledActionBeginMainFrameNotExpectedUntil(
223 base::TimeTicks time) override {
224 EXPECT_FALSE(inside_action_);
225 base::AutoReset<bool> mark_inside(&inside_action_, true);
226 PushAction("ScheduledActionBeginMainFrameNotExpectedUntil");
227 }
228
IsInsideBeginImplFrame() const229 bool IsInsideBeginImplFrame() const { return inside_begin_impl_frame_; }
230
InsideBeginImplFrame(bool state)231 base::RepeatingCallback<bool(void)> InsideBeginImplFrame(bool state) {
232 return base::BindRepeating(
233 &FakeSchedulerClient::InsideBeginImplFrameCallback,
234 base::Unretained(this), state);
235 }
236
IsCurrentFrame(int last_frame_number) const237 bool IsCurrentFrame(int last_frame_number) const {
238 return scheduler_->current_frame_number() == last_frame_number;
239 }
240
FrameHasNotAdvancedCallback()241 base::RepeatingCallback<bool(void)> FrameHasNotAdvancedCallback() {
242 return base::BindRepeating(&FakeSchedulerClient::IsCurrentFrame,
243 base::Unretained(this),
244 scheduler_->current_frame_number());
245 }
246
PushAction(const char * description)247 void PushAction(const char* description) {
248 actions_.push_back(description);
249 }
250
251 // FakeExternalBeginFrameSource::Client implementation.
OnAddObserver(viz::BeginFrameObserver * obs)252 void OnAddObserver(viz::BeginFrameObserver* obs) override {
253 PushAction("AddObserver(this)");
254 }
OnRemoveObserver(viz::BeginFrameObserver * obs)255 void OnRemoveObserver(viz::BeginFrameObserver* obs) override {
256 PushAction("RemoveObserver(this)");
257 }
258
CompositedAnimationsCount() const259 size_t CompositedAnimationsCount() const override { return 0; }
MainThreadAnimationsCount() const260 size_t MainThreadAnimationsCount() const override { return 0; }
HasCustomPropertyAnimations() const261 bool HasCustomPropertyAnimations() const override { return false; }
CurrentFrameHadRAF() const262 bool CurrentFrameHadRAF() const override { return false; }
NextFrameHasPendingRAF() const263 bool NextFrameHasPendingRAF() const override { return false; }
264
265 protected:
InsideBeginImplFrameCallback(bool state)266 bool InsideBeginImplFrameCallback(bool state) {
267 return inside_begin_impl_frame_ == state;
268 }
269
270 bool inside_action_ = false;
271 bool inside_begin_impl_frame_ = false;
272 bool will_begin_impl_frame_causes_redraw_;
273 bool will_begin_impl_frame_requests_one_begin_impl_frame_;
274 bool invalidate_needs_redraw_ = true;
275 bool draw_will_happen_;
276 bool swap_will_happen_if_draw_happens_;
277 bool automatic_ack_ = true;
278 bool will_begin_impl_frame_might_have_damage_ = true;
279 int num_draws_;
280 viz::BeginFrameArgs last_begin_main_frame_args_;
281 viz::BeginFrameAck last_begin_frame_ack_;
282 base::TimeTicks posted_begin_impl_frame_deadline_;
283 std::vector<const char*> actions_;
284 TestScheduler* scheduler_ = nullptr;
285 base::TimeDelta frame_interval_;
286 };
287
288 enum BeginFrameSourceType {
289 EXTERNAL_BFS,
290 UNTHROTTLED_BFS,
291 THROTTLED_BFS,
292 };
293
294 class SchedulerTestTaskRunner : public base::TestMockTimeTaskRunner {
295 public:
SchedulerTestTaskRunner()296 SchedulerTestTaskRunner()
297 : base::TestMockTimeTaskRunner(
298 base::TestMockTimeTaskRunner::Type::kStandalone) {
299 AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(110000));
300 }
301
RunUntilTime(base::TimeTicks end_time)302 void RunUntilTime(base::TimeTicks end_time) {
303 FastForwardBy(end_time - NowTicks());
304 }
305
306 // Runs all tasks posted before this call.
RunPendingTasks()307 void RunPendingTasks() {
308 base::circular_deque<base::TestPendingTask> tasks = TakePendingTasks();
309 while (!tasks.empty()) {
310 base::TestPendingTask task = std::move(tasks.front());
311 tasks.pop_front();
312 // Set clock to the beginning of task and run it.
313 AdvanceMockTickClock(task.GetTimeToRun() - NowTicks());
314 std::move(task.task).Run();
315 }
316 }
317
318 // Runs tasks while condition is met.
319 // Condition is being checked when task exists and before it gets selected.
RunTasksWhile(base::RepeatingCallback<bool ()> condition)320 void RunTasksWhile(base::RepeatingCallback<bool()> condition) {
321 run_condition_ = condition;
322 FastForwardUntilNoTasksRemain();
323 run_condition_ = base::nullopt;
324 // We've moved all the pending tasks away to break the execution loop,
325 // now we should restore them.
326 while (!tasks_to_requeue_.empty()) {
327 base::TestPendingTask task = std::move(tasks_to_requeue_.front());
328 tasks_to_requeue_.pop_front();
329 PostDelayedTask(task.location, std::move(task.task),
330 task.GetTimeToRun() - NowTicks());
331 }
332 }
333
334 protected:
OnBeforeSelectingTask()335 void OnBeforeSelectingTask() override {
336 // Avoid potential infinite loops.
337 ASSERT_LT(++task_count_, 100u);
338
339 if (run_condition_ && HasPendingTask() && !run_condition_->Run()) {
340 // Execution will not continue because we move all the pending tasks away.
341 tasks_to_requeue_ = TakePendingTasks();
342 }
343 }
344
345 private:
346 ~SchedulerTestTaskRunner() override = default; // Ref-counted.
347
348 size_t task_count_ = 0u;
349 base::Optional<base::RepeatingCallback<bool()>> run_condition_;
350 base::circular_deque<base::TestPendingTask> tasks_to_requeue_;
351 };
352
353 class SchedulerTest : public testing::Test {
354 public:
SchedulerTest()355 SchedulerTest()
356 : task_runner_(base::MakeRefCounted<SchedulerTestTaskRunner>()),
357 fake_external_begin_frame_source_(nullptr),
358 fake_compositor_timing_history_(nullptr) {}
359
360 ~SchedulerTest() override = default;
361
362 protected:
CreateScheduler(BeginFrameSourceType bfs_type)363 TestScheduler* CreateScheduler(BeginFrameSourceType bfs_type) {
364 viz::BeginFrameSource* frame_source = nullptr;
365 unthrottled_frame_source_.reset(new viz::BackToBackBeginFrameSource(
366 std::make_unique<viz::FakeDelayBasedTimeSource>(
367 task_runner_->GetMockTickClock(), task_runner_.get())));
368 fake_external_begin_frame_source_.reset(
369 new viz::FakeExternalBeginFrameSource(1.0, false));
370 fake_external_begin_frame_source_->SetClient(client_.get());
371 synthetic_frame_source_ = std::make_unique<viz::DelayBasedBeginFrameSource>(
372 std::make_unique<viz::FakeDelayBasedTimeSource>(
373 task_runner_->GetMockTickClock(), task_runner_.get()),
374 viz::BeginFrameSource::kNotRestartableId);
375 switch (bfs_type) {
376 case EXTERNAL_BFS:
377 frame_source = fake_external_begin_frame_source_.get();
378 break;
379 case UNTHROTTLED_BFS:
380 frame_source = unthrottled_frame_source_.get();
381 break;
382 case THROTTLED_BFS:
383 frame_source = synthetic_frame_source_.get();
384 break;
385 }
386 DCHECK(frame_source);
387
388 std::unique_ptr<FakeCompositorTimingHistory>
389 fake_compositor_timing_history = FakeCompositorTimingHistory::Create(
390 scheduler_settings_.using_synchronous_renderer_compositor);
391 fake_compositor_timing_history_ = fake_compositor_timing_history.get();
392
393 scheduler_.reset(new TestScheduler(
394 task_runner_->GetMockTickClock(), client_.get(), scheduler_settings_, 0,
395 task_runner_.get(), std::move(fake_compositor_timing_history)));
396 client_->set_scheduler(scheduler_.get());
397 scheduler_->SetBeginFrameSource(frame_source);
398
399 // Use large estimates by default to avoid latency recovery in most tests.
400 fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
401
402 return scheduler_.get();
403 }
404
SetUpScheduler(BeginFrameSourceType bfs_type,std::unique_ptr<FakeSchedulerClient> client)405 void SetUpScheduler(BeginFrameSourceType bfs_type,
406 std::unique_ptr<FakeSchedulerClient> client) {
407 client_ = std::move(client);
408 CreateScheduler(bfs_type);
409 EXPECT_SCOPED(InitializeLayerTreeFrameSinkAndFirstCommit());
410 }
411
SetUpScheduler(BeginFrameSourceType bfs_type)412 void SetUpScheduler(BeginFrameSourceType bfs_type) {
413 SetUpScheduler(bfs_type, std::make_unique<FakeSchedulerClient>());
414 }
415
SetUpSchedulerWithNoLayerTreeFrameSink(BeginFrameSourceType bfs_type)416 void SetUpSchedulerWithNoLayerTreeFrameSink(BeginFrameSourceType bfs_type) {
417 client_ = std::make_unique<FakeSchedulerClient>();
418 CreateScheduler(bfs_type);
419 }
420
421 // As this function contains EXPECT macros, to allow debugging it should be
422 // called inside EXPECT_SCOPED like so;
423 // EXPECT_SCOPED(
424 // client.InitializeLayerTreeFrameSinkAndFirstCommit(scheduler));
InitializeLayerTreeFrameSinkAndFirstCommit()425 void InitializeLayerTreeFrameSinkAndFirstCommit() {
426 TRACE_EVENT0(
427 "cc", "SchedulerUnitTest::InitializeLayerTreeFrameSinkAndFirstCommit");
428 DCHECK(scheduler_);
429
430 // Check the client doesn't have any actions queued when calling this
431 // function.
432 EXPECT_NO_ACTION();
433 EXPECT_FALSE(scheduler_->begin_frames_expected());
434
435 // Start the initial LayerTreeFrameSink creation.
436 scheduler_->SetVisible(true);
437 scheduler_->SetCanDraw(true);
438 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
439
440 client_->Reset();
441
442 // We don't see anything happening until the first impl frame.
443 scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
444 scheduler_->SetNeedsBeginMainFrame();
445 EXPECT_TRUE(scheduler_->begin_frames_expected());
446 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
447 client_->Reset();
448
449 {
450 SCOPED_TRACE("Do first frame to commit after initialize.");
451 AdvanceFrame();
452
453 task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMilliseconds(1));
454 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
455 scheduler_->NotifyReadyToCommit(nullptr);
456 scheduler_->NotifyReadyToActivate();
457 scheduler_->NotifyReadyToDraw();
458
459 EXPECT_FALSE(scheduler_->CommitPending());
460
461 if (scheduler_settings_.using_synchronous_renderer_compositor) {
462 scheduler_->SetNeedsRedraw();
463 bool resourceless_software_draw = false;
464 bool skip_draw = false;
465 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
466 skip_draw);
467 } else {
468 // Run the posted deadline task.
469 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
470 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
471 }
472
473 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
474 }
475
476 client_->Reset();
477
478 {
479 SCOPED_TRACE(
480 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
481 AdvanceFrame();
482
483 if (!scheduler_settings_.using_synchronous_renderer_compositor) {
484 // Run the posted deadline task.
485 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
486 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
487 }
488
489 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
490 }
491
492 EXPECT_FALSE(scheduler_->begin_frames_expected());
493
494 if (scheduler_->begin_frame_source() ==
495 fake_external_begin_frame_source_.get()) {
496 // Expect the last viz::BeginFrameAck to be for last BeginFrame, which
497 // didn't cause damage.
498 uint64_t last_begin_frame_number =
499 fake_external_begin_frame_source_->next_begin_frame_number() - 1;
500 bool has_damage = false;
501 EXPECT_EQ(
502 viz::BeginFrameAck(fake_external_begin_frame_source_->source_id(),
503 last_begin_frame_number, has_damage),
504 client_->last_begin_frame_ack());
505 }
506
507 client_->Reset();
508 }
509
510 // As this function contains EXPECT macros, to allow debugging it should be
511 // called inside EXPECT_SCOPED like so;
512 // EXPECT_SCOPED(client.AdvanceFrame());
AdvanceFrame(bool animate_only=false)513 void AdvanceFrame(bool animate_only = false) {
514 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
515 "FakeSchedulerClient::AdvanceFrame");
516
517 // Send the next BeginFrame message if using an external source, otherwise
518 // it will be already in the task queue.
519 if (scheduler_->begin_frame_source() ==
520 fake_external_begin_frame_source_.get()) {
521 EXPECT_TRUE(scheduler_->begin_frames_expected());
522 // Run the deadline first if we're inside the previous frame.
523 if (client_->IsInsideBeginImplFrame())
524 task_runner_->RunPendingTasks();
525 SendNextBeginFrame(animate_only);
526 } else {
527 task_runner_->RunTasksWhile(client_->FrameHasNotAdvancedCallback());
528 }
529 }
530
SendNextBeginFrame(bool animate_only=false)531 viz::BeginFrameArgs SendNextBeginFrame(bool animate_only = false) {
532 DCHECK_EQ(scheduler_->begin_frame_source(),
533 fake_external_begin_frame_source_.get());
534 // Creep the time forward so that any viz::BeginFrameArgs is not equal to
535 // the last one otherwise we violate the viz::BeginFrameSource contract.
536 task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
537 viz::BeginFrameArgs args =
538 fake_external_begin_frame_source_->CreateBeginFrameArgs(
539 BEGINFRAME_FROM_HERE, task_runner_->GetMockTickClock());
540 args.animate_only = animate_only;
541 fake_external_begin_frame_source_->TestOnBeginFrame(args);
542 return args;
543 }
544
fake_external_begin_frame_source() const545 viz::FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
546 return fake_external_begin_frame_source_.get();
547 }
548
SetShouldDeferInvalidationForMainFrame(bool defer)549 void SetShouldDeferInvalidationForMainFrame(bool defer) {
550 // Set the CompositorTimingHistory so that main thread is identified to be
551 // fast or slow.
552 base::TimeDelta delta;
553 if (!defer)
554 delta = base::TimeDelta::FromSeconds(1);
555 fake_compositor_timing_history_
556 ->SetBeginMainFrameStartToReadyToCommitDurationEstimate(delta);
557 fake_compositor_timing_history_
558 ->SetBeginMainFrameQueueDurationCriticalEstimate(delta);
559 fake_compositor_timing_history_
560 ->SetBeginMainFrameQueueDurationNotCriticalEstimate(delta);
561 fake_compositor_timing_history_->SetDrawDurationEstimate(base::TimeDelta());
562 }
563
564 void AdvanceAndMissOneFrame();
565 void CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame);
566 void ImplFrameSkippedAfterLateAck(bool is_already_receiving_begin_frames,
567 bool receive_ack_before_deadline);
568 void ImplFrameNotSkippedAfterLateAck();
569 void BeginFramesNotFromClient(BeginFrameSourceType bfs_type);
570 void BeginFramesNotFromClient_IsDrawThrottled(BeginFrameSourceType bfs_type);
571 bool BeginMainFrameOnCriticalPath(TreePriority tree_priority,
572 ScrollHandlerState scroll_handler_state,
573 base::TimeDelta durations);
574
575 scoped_refptr<SchedulerTestTaskRunner> task_runner_;
576 std::unique_ptr<viz::FakeExternalBeginFrameSource>
577 fake_external_begin_frame_source_;
578 std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_frame_source_;
579 std::unique_ptr<viz::SyntheticBeginFrameSource> unthrottled_frame_source_;
580 SchedulerSettings scheduler_settings_;
581 std::unique_ptr<FakeSchedulerClient> client_;
582 std::unique_ptr<TestScheduler> scheduler_;
583 FakeCompositorTimingHistory* fake_compositor_timing_history_;
584 };
585
TEST_F(SchedulerTest,InitializeLayerTreeFrameSinkDoesNotBeginImplFrame)586 TEST_F(SchedulerTest, InitializeLayerTreeFrameSinkDoesNotBeginImplFrame) {
587 SetUpSchedulerWithNoLayerTreeFrameSink(EXTERNAL_BFS);
588 scheduler_->SetVisible(true);
589 scheduler_->SetCanDraw(true);
590
591 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
592 client_->Reset();
593 scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
594 EXPECT_NO_ACTION();
595 }
596
TEST_F(SchedulerTest,Stop)597 TEST_F(SchedulerTest, Stop) {
598 SetUpScheduler(EXTERNAL_BFS);
599
600 scheduler_->SetNeedsBeginMainFrame();
601 EXPECT_ACTIONS("AddObserver(this)");
602 client_->Reset();
603
604 // No scheduled actions are performed after Stop. WillBeginImplFrame is only
605 // a notification and not an action performed by the scheduler.
606 scheduler_->Stop();
607 EXPECT_SCOPED(AdvanceFrame());
608 EXPECT_ACTIONS("WillBeginImplFrame");
609 client_->Reset();
610 }
611
TEST_F(SchedulerTest,VideoNeedsBeginFrames)612 TEST_F(SchedulerTest, VideoNeedsBeginFrames) {
613 SetUpScheduler(EXTERNAL_BFS);
614
615 scheduler_->SetVideoNeedsBeginFrames(true);
616 EXPECT_ACTIONS("AddObserver(this)");
617 EXPECT_TRUE(scheduler_->begin_frames_expected());
618
619 client_->Reset();
620 EXPECT_SCOPED(AdvanceFrame());
621 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
622 // WillBeginImplFrame is responsible for sending BeginFrames to video.
623 EXPECT_ACTIONS("WillBeginImplFrame");
624
625 client_->Reset();
626 EXPECT_SCOPED(AdvanceFrame());
627 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
628 EXPECT_ACTIONS("WillBeginImplFrame");
629
630 client_->Reset();
631 scheduler_->SetVideoNeedsBeginFrames(false);
632 EXPECT_NO_ACTION();
633
634 client_->Reset();
635 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
636 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
637 EXPECT_ACTIONS("RemoveObserver(this)");
638 EXPECT_FALSE(scheduler_->begin_frames_expected());
639 }
640
TEST_F(SchedulerTest,RequestCommit)641 TEST_F(SchedulerTest, RequestCommit) {
642 SetUpScheduler(EXTERNAL_BFS);
643
644 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
645 scheduler_->SetNeedsBeginMainFrame();
646 EXPECT_ACTIONS("AddObserver(this)");
647 client_->Reset();
648
649 EXPECT_SCOPED(AdvanceFrame());
650 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
651 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
652 EXPECT_TRUE(scheduler_->begin_frames_expected());
653 client_->Reset();
654
655 // If we don't swap on the deadline, we wait for the next BeginFrame.
656 task_runner_->RunPendingTasks(); // Run posted deadline.
657 EXPECT_NO_ACTION();
658 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
659 EXPECT_TRUE(scheduler_->begin_frames_expected());
660 client_->Reset();
661
662 // NotifyReadyToCommit should trigger the commit.
663 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
664 scheduler_->NotifyReadyToCommit(nullptr);
665 EXPECT_ACTIONS("ScheduledActionCommit");
666 EXPECT_TRUE(scheduler_->begin_frames_expected());
667 client_->Reset();
668
669 // NotifyReadyToActivate should trigger the activation.
670 scheduler_->NotifyReadyToActivate();
671 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
672 EXPECT_TRUE(scheduler_->begin_frames_expected());
673 client_->Reset();
674
675 // BeginImplFrame should prepare the draw.
676 EXPECT_SCOPED(AdvanceFrame());
677 EXPECT_ACTIONS("WillBeginImplFrame");
678 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
679 EXPECT_TRUE(scheduler_->begin_frames_expected());
680 client_->Reset();
681
682 // BeginImplFrame deadline should draw.
683 task_runner_->RunPendingTasks(); // Run posted deadline.
684 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
685 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
686 EXPECT_TRUE(scheduler_->begin_frames_expected());
687 client_->Reset();
688
689 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
690 // to avoid excessive toggles.
691 EXPECT_SCOPED(AdvanceFrame());
692 EXPECT_ACTIONS("WillBeginImplFrame");
693 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
694 client_->Reset();
695
696 task_runner_->RunPendingTasks(); // Run posted deadline.
697 EXPECT_ACTIONS("RemoveObserver(this)");
698 client_->Reset();
699 }
700
TEST_F(SchedulerTest,RequestCommitAfterSetDeferBeginMainFrame)701 TEST_F(SchedulerTest, RequestCommitAfterSetDeferBeginMainFrame) {
702 SetUpScheduler(EXTERNAL_BFS);
703
704 scheduler_->SetDeferBeginMainFrame(true);
705
706 scheduler_->SetNeedsBeginMainFrame();
707 EXPECT_NO_ACTION();
708
709 client_->Reset();
710 task_runner_->RunPendingTasks();
711 // There are no pending tasks or actions.
712 EXPECT_NO_ACTION();
713 EXPECT_FALSE(scheduler_->begin_frames_expected());
714
715 client_->Reset();
716 scheduler_->SetDeferBeginMainFrame(false);
717 EXPECT_ACTIONS("AddObserver(this)");
718
719 // Start new BeginMainFrame after defer commit is off.
720 client_->Reset();
721 EXPECT_SCOPED(AdvanceFrame());
722 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
723 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
724 }
725
TEST_F(SchedulerTest,DeferBeginMainFrameWithRedraw)726 TEST_F(SchedulerTest, DeferBeginMainFrameWithRedraw) {
727 SetUpScheduler(EXTERNAL_BFS);
728
729 scheduler_->SetDeferBeginMainFrame(true);
730
731 scheduler_->SetNeedsBeginMainFrame();
732 EXPECT_NO_ACTION();
733
734 // The SetNeedsRedraw will override the SetDeferBeginMainFrame(true), to
735 // allow a begin frame to be needed.
736 client_->Reset();
737 scheduler_->SetNeedsRedraw();
738 EXPECT_ACTIONS("AddObserver(this)");
739
740 client_->Reset();
741 AdvanceFrame();
742 // BeginMainFrame is not sent during the defer commit is on.
743 EXPECT_ACTIONS("WillBeginImplFrame");
744
745 client_->Reset();
746 task_runner_->RunPendingTasks(); // Run posted deadline.
747 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
748 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
749 EXPECT_TRUE(scheduler_->begin_frames_expected());
750
751 client_->Reset();
752 AdvanceFrame();
753 EXPECT_ACTIONS("WillBeginImplFrame");
754 }
755
TEST_F(SchedulerTest,RequestCommitAfterBeginMainFrameSent)756 TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
757 SetUpScheduler(EXTERNAL_BFS);
758
759 // SetNeedsBeginMainFrame should begin the frame.
760 scheduler_->SetNeedsBeginMainFrame();
761 EXPECT_ACTIONS("AddObserver(this)");
762
763 client_->Reset();
764 EXPECT_SCOPED(AdvanceFrame());
765 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
766 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
767
768 EXPECT_TRUE(scheduler_->begin_frames_expected());
769 client_->Reset();
770
771 // Now SetNeedsBeginMainFrame again. Calling here means we need a second
772 // commit.
773 scheduler_->SetNeedsBeginMainFrame();
774 EXPECT_NO_ACTION();
775 client_->Reset();
776
777 // Finish the first commit.
778 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
779 scheduler_->NotifyReadyToCommit(nullptr);
780 EXPECT_ACTIONS("ScheduledActionCommit");
781 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
782 client_->Reset();
783
784 // Activate it.
785 scheduler_->NotifyReadyToActivate();
786 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
787 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
788 client_->Reset();
789
790 task_runner_->RunPendingTasks(); // Run posted deadline.
791 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
792 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
793
794 // Because we just swapped, the Scheduler should also request the next
795 // BeginImplFrame from the LayerTreeFrameSink.
796 EXPECT_TRUE(scheduler_->begin_frames_expected());
797 client_->Reset();
798 // Since another commit is needed, the next BeginImplFrame should initiate
799 // the second commit.
800 EXPECT_SCOPED(AdvanceFrame());
801 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
802 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
803 client_->Reset();
804
805 // Finishing the commit before the deadline should post a new deadline task
806 // to trigger the deadline early.
807 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
808 scheduler_->NotifyReadyToCommit(nullptr);
809 EXPECT_ACTIONS("ScheduledActionCommit");
810 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
811 client_->Reset();
812 scheduler_->NotifyReadyToActivate();
813 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
814 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
815 client_->Reset();
816 task_runner_->RunPendingTasks(); // Run posted deadline.
817 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
818 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
819 EXPECT_TRUE(scheduler_->begin_frames_expected());
820 client_->Reset();
821
822 // On the next BeginImplFrame, verify we go back to a quiescent state and
823 // no longer request BeginImplFrames.
824 EXPECT_SCOPED(AdvanceFrame());
825 task_runner_->RunPendingTasks(); // Run posted deadline.
826 EXPECT_FALSE(scheduler_->begin_frames_expected());
827 client_->Reset();
828 }
829
830 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
831 public:
SchedulerClientThatsetNeedsDrawInsideDraw()832 SchedulerClientThatsetNeedsDrawInsideDraw()
833 : FakeSchedulerClient(), request_redraws_(false) {}
834
SetRequestRedrawsInsideDraw(bool enable)835 void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; }
836
ScheduledActionDrawIfPossible()837 DrawResult ScheduledActionDrawIfPossible() override {
838 // Only SetNeedsRedraw the first time this is called
839 if (request_redraws_) {
840 scheduler_->SetNeedsRedraw();
841 }
842 return FakeSchedulerClient::ScheduledActionDrawIfPossible();
843 }
844
ScheduledActionDrawForced()845 DrawResult ScheduledActionDrawForced() override {
846 NOTREACHED();
847 return DRAW_SUCCESS;
848 }
849
850 private:
851 bool request_redraws_;
852 };
853
854 // Tests for two different situations:
855 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
856 // a ScheduledActionDraw
857 // 2. the scheduler drawing twice inside a single tick
TEST_F(SchedulerTest,RequestRedrawInsideDraw)858 TEST_F(SchedulerTest, RequestRedrawInsideDraw) {
859 SchedulerClientThatsetNeedsDrawInsideDraw* client =
860 new SchedulerClientThatsetNeedsDrawInsideDraw;
861 SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
862 client->SetRequestRedrawsInsideDraw(true);
863
864 scheduler_->SetNeedsRedraw();
865 EXPECT_TRUE(scheduler_->RedrawPending());
866 EXPECT_TRUE(client->needs_begin_frames());
867 EXPECT_EQ(0, client->num_draws());
868
869 EXPECT_SCOPED(AdvanceFrame());
870 task_runner_->RunPendingTasks(); // Run posted deadline.
871 EXPECT_EQ(1, client->num_draws());
872 EXPECT_TRUE(scheduler_->RedrawPending());
873 EXPECT_TRUE(client->needs_begin_frames());
874
875 client->SetRequestRedrawsInsideDraw(false);
876
877 EXPECT_SCOPED(AdvanceFrame());
878 task_runner_->RunPendingTasks(); // Run posted deadline.
879 EXPECT_EQ(2, client_->num_draws());
880 EXPECT_FALSE(scheduler_->RedrawPending());
881 EXPECT_TRUE(client->needs_begin_frames());
882
883 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
884 // swap.
885 EXPECT_SCOPED(AdvanceFrame());
886 task_runner_->RunPendingTasks(); // Run posted deadline.
887 EXPECT_EQ(2, client->num_draws());
888 EXPECT_FALSE(scheduler_->RedrawPending());
889 EXPECT_FALSE(client->needs_begin_frames());
890 }
891
892 // Test that requesting redraw inside a failed draw doesn't lose the request.
TEST_F(SchedulerTest,RequestRedrawInsideFailedDraw)893 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
894 SchedulerClientThatsetNeedsDrawInsideDraw* client =
895 new SchedulerClientThatsetNeedsDrawInsideDraw;
896 SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
897
898 client->SetRequestRedrawsInsideDraw(true);
899 client->SetDrawWillHappen(false);
900
901 scheduler_->SetNeedsRedraw();
902 EXPECT_TRUE(scheduler_->RedrawPending());
903 EXPECT_TRUE(client->needs_begin_frames());
904 EXPECT_EQ(0, client->num_draws());
905
906 // Fail the draw.
907 EXPECT_SCOPED(AdvanceFrame());
908 task_runner_->RunPendingTasks(); // Run posted deadline.
909 EXPECT_EQ(1, client->num_draws());
910
911 // We have a commit pending and the draw failed, and we didn't lose the redraw
912 // request.
913 EXPECT_TRUE(scheduler_->CommitPending());
914 EXPECT_TRUE(scheduler_->RedrawPending());
915 EXPECT_TRUE(client->needs_begin_frames());
916
917 client->SetRequestRedrawsInsideDraw(false);
918
919 // Fail the draw again.
920 EXPECT_SCOPED(AdvanceFrame());
921 task_runner_->RunPendingTasks(); // Run posted deadline.
922 EXPECT_EQ(2, client->num_draws());
923 EXPECT_TRUE(scheduler_->CommitPending());
924 EXPECT_TRUE(scheduler_->RedrawPending());
925 EXPECT_TRUE(client->needs_begin_frames());
926
927 // Draw successfully.
928 client->SetDrawWillHappen(true);
929 EXPECT_SCOPED(AdvanceFrame());
930 task_runner_->RunPendingTasks(); // Run posted deadline.
931 EXPECT_EQ(3, client->num_draws());
932 EXPECT_TRUE(scheduler_->CommitPending());
933 EXPECT_FALSE(scheduler_->RedrawPending());
934 EXPECT_TRUE(client->needs_begin_frames());
935 }
936
937 class SchedulerClientThatSetNeedsBeginMainFrameInsideDraw
938 : public FakeSchedulerClient {
939 public:
SchedulerClientThatSetNeedsBeginMainFrameInsideDraw()940 SchedulerClientThatSetNeedsBeginMainFrameInsideDraw()
941 : set_needs_commit_on_next_draw_(false) {}
942
ScheduledActionDrawIfPossible()943 DrawResult ScheduledActionDrawIfPossible() override {
944 // Only SetNeedsBeginMainFrame the first time this is called
945 if (set_needs_commit_on_next_draw_) {
946 scheduler_->SetNeedsBeginMainFrame();
947 set_needs_commit_on_next_draw_ = false;
948 }
949 return FakeSchedulerClient::ScheduledActionDrawIfPossible();
950 }
951
ScheduledActionDrawForced()952 DrawResult ScheduledActionDrawForced() override {
953 NOTREACHED();
954 return DRAW_SUCCESS;
955 }
956
SetNeedsBeginMainFrameOnNextDraw()957 void SetNeedsBeginMainFrameOnNextDraw() {
958 set_needs_commit_on_next_draw_ = true;
959 }
960
961 private:
962 bool set_needs_commit_on_next_draw_;
963 };
964
965 // Tests for the scheduler infinite-looping on SetNeedsBeginMainFrame requests
966 // that happen inside a ScheduledActionDraw
TEST_F(SchedulerTest,RequestCommitInsideDraw)967 TEST_F(SchedulerTest, RequestCommitInsideDraw) {
968 SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client =
969 new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw;
970 SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
971
972 EXPECT_FALSE(client->needs_begin_frames());
973 scheduler_->SetNeedsRedraw();
974 EXPECT_TRUE(scheduler_->RedrawPending());
975 EXPECT_EQ(0, client->num_draws());
976 EXPECT_TRUE(client->needs_begin_frames());
977
978 client->SetNeedsBeginMainFrameOnNextDraw();
979 EXPECT_SCOPED(AdvanceFrame());
980 client->SetNeedsBeginMainFrameOnNextDraw();
981 task_runner_->RunPendingTasks(); // Run posted deadline.
982 EXPECT_EQ(1, client->num_draws());
983 EXPECT_TRUE(scheduler_->CommitPending());
984 EXPECT_TRUE(client->needs_begin_frames());
985 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
986 scheduler_->NotifyReadyToCommit(nullptr);
987 scheduler_->NotifyReadyToActivate();
988
989 EXPECT_SCOPED(AdvanceFrame());
990 task_runner_->RunPendingTasks(); // Run posted deadline.
991 EXPECT_EQ(2, client->num_draws());
992
993 EXPECT_FALSE(scheduler_->RedrawPending());
994 EXPECT_FALSE(scheduler_->CommitPending());
995 EXPECT_TRUE(client->needs_begin_frames());
996
997 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
998 // swap.
999 EXPECT_SCOPED(AdvanceFrame());
1000 task_runner_->RunPendingTasks(); // Run posted deadline.
1001 EXPECT_EQ(2, client->num_draws());
1002 EXPECT_FALSE(scheduler_->RedrawPending());
1003 EXPECT_FALSE(scheduler_->CommitPending());
1004 EXPECT_FALSE(client->needs_begin_frames());
1005 }
1006
1007 // Tests that when a draw fails then the pending commit should not be dropped.
TEST_F(SchedulerTest,RequestCommitInsideFailedDraw)1008 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
1009 SchedulerClientThatsetNeedsDrawInsideDraw* client =
1010 new SchedulerClientThatsetNeedsDrawInsideDraw;
1011 SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1012
1013 client->SetDrawWillHappen(false);
1014
1015 scheduler_->SetNeedsRedraw();
1016 EXPECT_TRUE(scheduler_->RedrawPending());
1017 EXPECT_TRUE(client->needs_begin_frames());
1018 EXPECT_EQ(0, client->num_draws());
1019
1020 // Fail the draw.
1021 EXPECT_SCOPED(AdvanceFrame());
1022 task_runner_->RunPendingTasks(); // Run posted deadline.
1023 EXPECT_EQ(1, client->num_draws());
1024
1025 // We have a commit pending and the draw failed, and we didn't lose the commit
1026 // request.
1027 EXPECT_TRUE(scheduler_->CommitPending());
1028 EXPECT_TRUE(scheduler_->RedrawPending());
1029 EXPECT_TRUE(client->needs_begin_frames());
1030
1031 // Fail the draw again.
1032 EXPECT_SCOPED(AdvanceFrame());
1033
1034 task_runner_->RunPendingTasks(); // Run posted deadline.
1035 EXPECT_EQ(2, client->num_draws());
1036 EXPECT_TRUE(scheduler_->CommitPending());
1037 EXPECT_TRUE(scheduler_->RedrawPending());
1038 EXPECT_TRUE(client->needs_begin_frames());
1039
1040 // Draw successfully.
1041 client->SetDrawWillHappen(true);
1042 EXPECT_SCOPED(AdvanceFrame());
1043 task_runner_->RunPendingTasks(); // Run posted deadline.
1044 EXPECT_EQ(3, client->num_draws());
1045 EXPECT_TRUE(scheduler_->CommitPending());
1046 EXPECT_FALSE(scheduler_->RedrawPending());
1047 EXPECT_TRUE(client->needs_begin_frames());
1048 }
1049
TEST_F(SchedulerTest,NoSwapWhenDrawFails)1050 TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
1051 SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client =
1052 new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw;
1053 SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1054
1055 scheduler_->SetNeedsRedraw();
1056 EXPECT_TRUE(scheduler_->RedrawPending());
1057 EXPECT_TRUE(client->needs_begin_frames());
1058 EXPECT_EQ(0, client->num_draws());
1059
1060 // Draw successfully, this starts a new frame.
1061 client->SetNeedsBeginMainFrameOnNextDraw();
1062 EXPECT_SCOPED(AdvanceFrame());
1063 task_runner_->RunPendingTasks(); // Run posted deadline.
1064 EXPECT_EQ(1, client->num_draws());
1065
1066 scheduler_->SetNeedsRedraw();
1067 EXPECT_TRUE(scheduler_->RedrawPending());
1068 EXPECT_TRUE(client->needs_begin_frames());
1069
1070 // Fail to draw, this should not start a frame.
1071 client->SetDrawWillHappen(false);
1072 client->SetNeedsBeginMainFrameOnNextDraw();
1073 EXPECT_SCOPED(AdvanceFrame());
1074 task_runner_->RunPendingTasks(); // Run posted deadline.
1075 EXPECT_EQ(2, client->num_draws());
1076 }
1077
1078 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient {
1079 public:
ScheduledActionDrawIfPossible()1080 DrawResult ScheduledActionDrawIfPossible() override {
1081 scheduler_->SetNeedsPrepareTiles();
1082 return FakeSchedulerClient::ScheduledActionDrawIfPossible();
1083 }
1084 };
1085
1086 // Test prepare tiles is independant of draws.
TEST_F(SchedulerTest,PrepareTiles)1087 TEST_F(SchedulerTest, PrepareTiles) {
1088 SchedulerClientNeedsPrepareTilesInDraw* client =
1089 new SchedulerClientNeedsPrepareTilesInDraw;
1090 SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1091
1092 // Request both draw and prepare tiles. PrepareTiles shouldn't
1093 // be trigged until BeginImplFrame.
1094 client->Reset();
1095 scheduler_->SetNeedsPrepareTiles();
1096 scheduler_->SetNeedsRedraw();
1097 EXPECT_TRUE(scheduler_->RedrawPending());
1098 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1099 EXPECT_TRUE(client->needs_begin_frames());
1100 EXPECT_EQ(0, client->num_draws());
1101 EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles"));
1102 EXPECT_FALSE(client->HasAction("ScheduledActionDrawIfPossible"));
1103
1104 // We have no immediate actions to perform, so the BeginImplFrame should post
1105 // the deadline task.
1106 client->Reset();
1107 EXPECT_SCOPED(AdvanceFrame());
1108 EXPECT_ACTIONS("WillBeginImplFrame");
1109 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1110
1111 // On the deadline, the actions should have occured in the right order.
1112 client->Reset();
1113 task_runner_->RunPendingTasks(); // Run posted deadline.
1114 EXPECT_EQ(1, client->num_draws());
1115 EXPECT_TRUE(client->HasAction("ScheduledActionDrawIfPossible"));
1116 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1117 EXPECT_LT(client->ActionIndex("ScheduledActionDrawIfPossible"),
1118 client->ActionIndex("ScheduledActionPrepareTiles"));
1119 EXPECT_FALSE(scheduler_->RedrawPending());
1120 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1121 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1122
1123 // Request a draw. We don't need a PrepareTiles yet.
1124 client->Reset();
1125 scheduler_->SetNeedsRedraw();
1126 EXPECT_TRUE(scheduler_->RedrawPending());
1127 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1128 EXPECT_TRUE(client->needs_begin_frames());
1129 EXPECT_EQ(0, client->num_draws());
1130
1131 // We have no immediate actions to perform, so the BeginImplFrame should post
1132 // the deadline task.
1133 client->Reset();
1134 EXPECT_SCOPED(AdvanceFrame());
1135 EXPECT_ACTIONS("WillBeginImplFrame");
1136 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1137
1138 // Draw. The draw will trigger SetNeedsPrepareTiles, and
1139 // then the PrepareTiles action will be triggered after the Draw.
1140 // Afterwards, neither a draw nor PrepareTiles are pending.
1141 client->Reset();
1142 task_runner_->RunPendingTasks(); // Run posted deadline.
1143 EXPECT_EQ(1, client->num_draws());
1144 EXPECT_TRUE(client->HasAction("ScheduledActionDrawIfPossible"));
1145 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1146 EXPECT_LT(client->ActionIndex("ScheduledActionDrawIfPossible"),
1147 client->ActionIndex("ScheduledActionPrepareTiles"));
1148 EXPECT_FALSE(scheduler_->RedrawPending());
1149 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1150 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1151
1152 // We need a BeginImplFrame where we don't swap to go idle.
1153 client->Reset();
1154 EXPECT_SCOPED(AdvanceFrame());
1155 EXPECT_ACTIONS("WillBeginImplFrame");
1156 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1157 client->Reset();
1158 task_runner_->RunPendingTasks(); // Run posted deadline.
1159 EXPECT_ACTIONS("RemoveObserver(this)");
1160 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1161 EXPECT_EQ(0, client->num_draws());
1162
1163 // Now trigger a PrepareTiles outside of a draw. We will then need
1164 // a begin-frame for the PrepareTiles, but we don't need a draw.
1165 client->Reset();
1166 EXPECT_FALSE(client->needs_begin_frames());
1167 scheduler_->SetNeedsPrepareTiles();
1168 EXPECT_TRUE(client->needs_begin_frames());
1169 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1170 EXPECT_FALSE(scheduler_->RedrawPending());
1171
1172 // BeginImplFrame. There will be no draw, only PrepareTiles.
1173 client->Reset();
1174 EXPECT_SCOPED(AdvanceFrame());
1175 EXPECT_ACTIONS("WillBeginImplFrame");
1176 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1177 client->Reset();
1178 task_runner_->RunPendingTasks(); // Run posted deadline.
1179 EXPECT_EQ(0, client->num_draws());
1180 EXPECT_FALSE(client->HasAction("ScheduledActionDrawIfPossible"));
1181 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1182 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1183 }
1184
1185 // Test that PrepareTiles only happens once per frame. If an external caller
1186 // initiates it, then the state machine should not PrepareTiles on that frame.
TEST_F(SchedulerTest,PrepareTilesOncePerFrame)1187 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) {
1188 SetUpScheduler(EXTERNAL_BFS);
1189
1190 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1191 // again.
1192 scheduler_->SetNeedsPrepareTiles();
1193 scheduler_->SetNeedsRedraw();
1194 client_->Reset();
1195 EXPECT_SCOPED(AdvanceFrame());
1196 EXPECT_ACTIONS("WillBeginImplFrame");
1197 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1198
1199 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1200 scheduler_->WillPrepareTiles();
1201 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1202 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1203
1204 client_->Reset();
1205 task_runner_->RunPendingTasks(); // Run posted deadline.
1206 EXPECT_EQ(1, client_->num_draws());
1207 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1208 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1209 EXPECT_FALSE(scheduler_->RedrawPending());
1210 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1211 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1212
1213 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1214 scheduler_->SetNeedsPrepareTiles();
1215 scheduler_->SetNeedsRedraw();
1216 client_->Reset();
1217 EXPECT_SCOPED(AdvanceFrame());
1218 EXPECT_ACTIONS("WillBeginImplFrame");
1219 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1220
1221 client_->Reset();
1222 task_runner_->RunPendingTasks(); // Run posted deadline.
1223 EXPECT_EQ(1, client_->num_draws());
1224 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1225 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1226 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawIfPossible"),
1227 client_->ActionIndex("ScheduledActionPrepareTiles"));
1228 EXPECT_FALSE(scheduler_->RedrawPending());
1229 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1230 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1231
1232 // If we get another DidPrepareTiles within the same frame, we should
1233 // not PrepareTiles on the next frame.
1234 scheduler_->WillPrepareTiles();
1235 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1236 scheduler_->SetNeedsPrepareTiles();
1237 scheduler_->SetNeedsRedraw();
1238 client_->Reset();
1239 EXPECT_SCOPED(AdvanceFrame());
1240 EXPECT_ACTIONS("WillBeginImplFrame");
1241 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1242
1243 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1244
1245 client_->Reset();
1246 task_runner_->RunPendingTasks(); // Run posted deadline.
1247 EXPECT_EQ(1, client_->num_draws());
1248 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1249 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1250 EXPECT_FALSE(scheduler_->RedrawPending());
1251 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1252
1253 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1254 // frame. This verifies we don't alternate calling PrepareTiles once and
1255 // twice.
1256 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1257 scheduler_->WillPrepareTiles();
1258 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1259 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1260 scheduler_->SetNeedsPrepareTiles();
1261 scheduler_->SetNeedsRedraw();
1262 client_->Reset();
1263 EXPECT_SCOPED(AdvanceFrame());
1264 EXPECT_ACTIONS("WillBeginImplFrame");
1265 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1266
1267 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1268
1269 client_->Reset();
1270 task_runner_->RunPendingTasks(); // Run posted deadline.
1271 EXPECT_EQ(1, client_->num_draws());
1272 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1273 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1274 EXPECT_FALSE(scheduler_->RedrawPending());
1275 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1276
1277 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1278 scheduler_->SetNeedsPrepareTiles();
1279 scheduler_->SetNeedsRedraw();
1280 client_->Reset();
1281 EXPECT_SCOPED(AdvanceFrame());
1282 EXPECT_ACTIONS("WillBeginImplFrame");
1283 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1284
1285 client_->Reset();
1286 task_runner_->RunPendingTasks(); // Run posted deadline.
1287 EXPECT_EQ(1, client_->num_draws());
1288 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1289 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1290 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawIfPossible"),
1291 client_->ActionIndex("ScheduledActionPrepareTiles"));
1292 EXPECT_FALSE(scheduler_->RedrawPending());
1293 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1294 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1295 }
1296
TEST_F(SchedulerTest,DidPrepareTilesPreventsPrepareTilesForOneFrame)1297 TEST_F(SchedulerTest, DidPrepareTilesPreventsPrepareTilesForOneFrame) {
1298 std::unique_ptr<SchedulerClientNeedsPrepareTilesInDraw> client =
1299 base::WrapUnique(new SchedulerClientNeedsPrepareTilesInDraw);
1300 SetUpScheduler(EXTERNAL_BFS, std::move(client));
1301
1302 client_->Reset();
1303 scheduler_->SetNeedsRedraw();
1304 EXPECT_ACTIONS("AddObserver(this)");
1305
1306 client_->Reset();
1307 EXPECT_SCOPED(AdvanceFrame());
1308 EXPECT_ACTIONS("WillBeginImplFrame");
1309 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1310
1311 client_->Reset();
1312 task_runner_->RunPendingTasks(); // Run posted deadline.
1313 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1314 EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
1315 "ScheduledActionPrepareTiles");
1316
1317 // We don't want to hinder scheduled prepare tiles for more than one frame
1318 // even if we call unscheduled prepare tiles many times.
1319 for (int i = 0; i < 10; i++) {
1320 scheduler_->WillPrepareTiles();
1321 scheduler_->DidPrepareTiles();
1322 }
1323
1324 client_->Reset();
1325 scheduler_->SetNeedsRedraw();
1326 EXPECT_SCOPED(AdvanceFrame());
1327 EXPECT_ACTIONS("WillBeginImplFrame");
1328 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1329
1330 // No scheduled prepare tiles because we've already counted a prepare tiles in
1331 // between frames.
1332 client_->Reset();
1333 task_runner_->RunPendingTasks(); // Run posted deadline.
1334 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1335 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
1336
1337 client_->Reset();
1338 scheduler_->SetNeedsRedraw();
1339 EXPECT_SCOPED(AdvanceFrame());
1340 EXPECT_ACTIONS("WillBeginImplFrame");
1341 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1342
1343 // Resume scheduled prepare tiles.
1344 client_->Reset();
1345 task_runner_->RunPendingTasks(); // Run posted deadline.
1346 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1347 EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
1348 "ScheduledActionPrepareTiles");
1349 }
1350
TEST_F(SchedulerTest,TriggerBeginFrameDeadlineEarly)1351 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1352 SchedulerClientNeedsPrepareTilesInDraw* client =
1353 new SchedulerClientNeedsPrepareTilesInDraw;
1354 SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1355
1356 scheduler_->SetNeedsRedraw();
1357 EXPECT_SCOPED(AdvanceFrame());
1358
1359 // The deadline should be zero since there is no work other than drawing
1360 // pending.
1361 EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline());
1362 }
1363
TEST_F(SchedulerTest,WaitForReadyToDrawDoNotPostDeadline)1364 TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) {
1365 SchedulerClientNeedsPrepareTilesInDraw* client =
1366 new SchedulerClientNeedsPrepareTilesInDraw;
1367 scheduler_settings_.commit_to_active_tree = true;
1368 SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1369
1370 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
1371 scheduler_->SetNeedsBeginMainFrame();
1372 EXPECT_ACTIONS("AddObserver(this)");
1373 client_->Reset();
1374
1375 // Begin new frame.
1376 EXPECT_SCOPED(AdvanceFrame());
1377 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1378 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
1379
1380 client_->Reset();
1381 scheduler_->NotifyReadyToCommit(nullptr);
1382 EXPECT_ACTIONS("ScheduledActionCommit");
1383
1384 client_->Reset();
1385 scheduler_->NotifyReadyToActivate();
1386 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
1387
1388 // Scheduler won't post deadline in the mode.
1389 client_->Reset();
1390 task_runner_->RunPendingTasks(); // Try to run posted deadline.
1391 // There is no posted deadline.
1392 EXPECT_NO_ACTION();
1393
1394 // Scheduler received ready to draw signal, and posted deadline.
1395 scheduler_->NotifyReadyToDraw();
1396 client_->Reset();
1397 task_runner_->RunPendingTasks(); // Run posted deadline.
1398 EXPECT_EQ(1, client_->num_draws());
1399 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
1400 }
1401
TEST_F(SchedulerTest,WaitForReadyToDrawCancelledWhenLostLayerTreeFrameSink)1402 TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostLayerTreeFrameSink) {
1403 SchedulerClientNeedsPrepareTilesInDraw* client =
1404 new SchedulerClientNeedsPrepareTilesInDraw;
1405 scheduler_settings_.commit_to_active_tree = true;
1406 SetUpScheduler(EXTERNAL_BFS, base::WrapUnique(client));
1407
1408 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
1409 scheduler_->SetNeedsBeginMainFrame();
1410 EXPECT_ACTIONS("AddObserver(this)");
1411 client_->Reset();
1412
1413 // Begin new frame.
1414 EXPECT_SCOPED(AdvanceFrame());
1415 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1416 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
1417
1418 client_->Reset();
1419 scheduler_->NotifyReadyToCommit(nullptr);
1420 EXPECT_ACTIONS("ScheduledActionCommit");
1421
1422 client_->Reset();
1423 scheduler_->NotifyReadyToActivate();
1424 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
1425
1426 // Scheduler won't post deadline in the mode.
1427 client_->Reset();
1428 task_runner_->RunPendingTasks(); // Try to run posted deadline.
1429 // There is no posted deadline.
1430 EXPECT_NO_ACTION();
1431
1432 // Scheduler loses LayerTreeFrameSink, and stops waiting for ready to draw
1433 // signal.
1434 client_->Reset();
1435 scheduler_->DidLoseLayerTreeFrameSink();
1436 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1437 task_runner_->RunPendingTasks(); // Run posted deadline.
1438 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
1439 "RemoveObserver(this)");
1440 }
1441
AdvanceAndMissOneFrame()1442 void SchedulerTest::AdvanceAndMissOneFrame() {
1443 // Impl thread hits deadline before commit finishes.
1444 scheduler_->SetNeedsBeginMainFrame();
1445 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1446 EXPECT_SCOPED(AdvanceFrame());
1447 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1448 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1449 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1450 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1451 scheduler_->NotifyReadyToCommit(nullptr);
1452 scheduler_->NotifyReadyToActivate();
1453 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1454 "ScheduledActionSendBeginMainFrame", "ScheduledActionCommit",
1455 "ScheduledActionActivateSyncTree");
1456 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1457 client_->Reset();
1458 }
1459
CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame)1460 void SchedulerTest::CheckMainFrameSkippedAfterLateCommit(
1461 bool expect_send_begin_main_frame) {
1462 AdvanceAndMissOneFrame();
1463
1464 scheduler_->SetNeedsBeginMainFrame();
1465 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1466 EXPECT_SCOPED(AdvanceFrame());
1467 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1468 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1469 EXPECT_EQ(expect_send_begin_main_frame,
1470 scheduler_->MainThreadMissedLastDeadline());
1471 EXPECT_TRUE(client_->HasAction("WillBeginImplFrame"));
1472 EXPECT_EQ(expect_send_begin_main_frame,
1473 client_->HasAction("ScheduledActionSendBeginMainFrame"));
1474 }
1475
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateBeginFrame)1476 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateBeginFrame) {
1477 // If a begin frame is delivered extremely late (because the browser has
1478 // some contention), make sure that the main frame is not skipped even
1479 // if it can activate before the deadline.
1480 SetUpScheduler(EXTERNAL_BFS);
1481 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1482
1483 AdvanceAndMissOneFrame();
1484 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1485 scheduler_->SetNeedsBeginMainFrame();
1486
1487 // Advance frame and create a begin frame.
1488 task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
1489 viz::BeginFrameArgs args =
1490 fake_external_begin_frame_source_->CreateBeginFrameArgs(
1491 BEGINFRAME_FROM_HERE, task_runner_->GetMockTickClock());
1492
1493 // Deliver this begin frame super late.
1494 task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval() *
1495 100);
1496 fake_external_begin_frame_source_->TestOnBeginFrame(args);
1497
1498 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1499 EXPECT_EQ(true, scheduler_->MainThreadMissedLastDeadline());
1500 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
1501 "ScheduledActionDrawIfPossible");
1502 }
1503
TEST_F(SchedulerTest,FrameIntervalUpdated)1504 TEST_F(SchedulerTest, FrameIntervalUpdated) {
1505 // Verify that the SchedulerClient gets updates when the begin frame interval
1506 // changes.
1507 SetUpScheduler(EXTERNAL_BFS);
1508 constexpr uint64_t kSourceId = viz::BeginFrameArgs::kStartingSourceId;
1509 uint64_t sequence_number = viz::BeginFrameArgs::kStartingFrameNumber;
1510
1511 base::TimeDelta interval = base::TimeDelta::FromMicroseconds(
1512 base::Time::kMicrosecondsPerSecond / 120.0);
1513
1514 // Send BeginFrameArgs with 120hz refresh rate and confirm client gets update.
1515 scheduler_->SetNeedsRedraw();
1516 task_runner_->AdvanceMockTickClock(interval);
1517 viz::BeginFrameArgs args1 = viz::BeginFrameArgs::Create(
1518 BEGINFRAME_FROM_HERE, kSourceId, sequence_number++,
1519 task_runner_->NowTicks(), task_runner_->NowTicks() + interval, interval,
1520 viz::BeginFrameArgs::NORMAL);
1521 fake_external_begin_frame_source_->TestOnBeginFrame(args1);
1522 EXPECT_EQ(client_->frame_interval(), interval);
1523
1524 // Send another BeginFrameArgs with 120hz refresh rate that arrives late. Even
1525 // though the interval between begin frames arriving is bigger than |interval|
1526 // the client only hears the interval specified in BeginFrameArgs.
1527 scheduler_->SetNeedsRedraw();
1528 const base::TimeDelta late_delta = base::TimeDelta::FromMilliseconds(4);
1529 task_runner_->AdvanceMockTickClock(interval + late_delta);
1530 viz::BeginFrameArgs args2 = viz::BeginFrameArgs::Create(
1531 BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, args1.deadline,
1532 args1.deadline + interval, interval, viz::BeginFrameArgs::NORMAL);
1533 fake_external_begin_frame_source_->TestOnBeginFrame(args2);
1534 EXPECT_EQ(client_->frame_interval(), interval);
1535
1536 // Change the interval for 90hz refresh rate.
1537 interval = base::TimeDelta::FromMicroseconds(
1538 base::Time::kMicrosecondsPerSecond / 90.0);
1539
1540 // Send BeginFrameArgs with 90hz refresh rate and confirm client gets update.
1541 scheduler_->SetNeedsRedraw();
1542 task_runner_->AdvanceMockTickClock(args2.deadline - task_runner_->NowTicks());
1543 viz::BeginFrameArgs args3 = viz::BeginFrameArgs::Create(
1544 BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, args2.deadline,
1545 args2.deadline + interval, interval, viz::BeginFrameArgs::NORMAL);
1546 fake_external_begin_frame_source_->TestOnBeginFrame(args3);
1547 EXPECT_EQ(client_->frame_interval(), interval);
1548
1549 // Send BeginFrameArgs with zero interval. This isn't a valid interval and
1550 // client shouldn't find out about it.
1551 scheduler_->SetNeedsRedraw();
1552 task_runner_->AdvanceMockTickClock(interval);
1553 viz::BeginFrameArgs args4 = viz::BeginFrameArgs::Create(
1554 BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, args3.deadline,
1555 args3.deadline + interval, base::TimeDelta(),
1556 viz::BeginFrameArgs::NORMAL);
1557 fake_external_begin_frame_source_->TestOnBeginFrame(args4);
1558 EXPECT_EQ(client_->frame_interval(), interval);
1559 }
1560
TEST_F(SchedulerTest,MainFrameSkippedAfterLateCommit)1561 TEST_F(SchedulerTest, MainFrameSkippedAfterLateCommit) {
1562 SetUpScheduler(EXTERNAL_BFS);
1563 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1564
1565 bool expect_send_begin_main_frame = false;
1566 EXPECT_SCOPED(
1567 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1568 }
1569
1570 // Response times of BeginMainFrame's without the critical path flag set
1571 // should not affect whether we recover latency or not.
TEST_F(SchedulerTest,MainFrameSkippedAfterLateCommit_LongMainFrameQueueDurationNotCritical)1572 TEST_F(SchedulerTest,
1573 MainFrameSkippedAfterLateCommit_LongMainFrameQueueDurationNotCritical) {
1574 SetUpScheduler(EXTERNAL_BFS);
1575 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1576 fake_compositor_timing_history_
1577 ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
1578
1579 bool expect_send_begin_main_frame = false;
1580 EXPECT_SCOPED(
1581 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1582 }
1583
1584 // Response times of BeginMainFrame's with the critical path flag set
1585 // should affect whether we recover latency or not.
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommit_LongMainFrameQueueDurationCritical)1586 TEST_F(SchedulerTest,
1587 MainFrameNotSkippedAfterLateCommit_LongMainFrameQueueDurationCritical) {
1588 SetUpScheduler(EXTERNAL_BFS);
1589 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1590 fake_compositor_timing_history_
1591 ->SetBeginMainFrameQueueDurationCriticalEstimate(kSlowDuration);
1592 fake_compositor_timing_history_
1593 ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
1594
1595 bool expect_send_begin_main_frame = true;
1596 EXPECT_SCOPED(
1597 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1598 }
1599
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode)1600 TEST_F(SchedulerTest,
1601 MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode) {
1602 SetUpScheduler(EXTERNAL_BFS);
1603 scheduler_->SetTreePrioritiesAndScrollState(
1604 SMOOTHNESS_TAKES_PRIORITY,
1605 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
1606 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1607
1608 bool expect_send_begin_main_frame = true;
1609 EXPECT_SCOPED(
1610 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1611 }
1612
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong)1613 TEST_F(SchedulerTest,
1614 MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong) {
1615 SetUpScheduler(EXTERNAL_BFS);
1616 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1617 fake_compositor_timing_history_
1618 ->SetBeginMainFrameStartToReadyToCommitDurationEstimate(kSlowDuration);
1619
1620 bool expect_send_begin_main_frame = true;
1621 EXPECT_SCOPED(
1622 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1623 }
1624
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong)1625 TEST_F(SchedulerTest,
1626 MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong) {
1627 SetUpScheduler(EXTERNAL_BFS);
1628 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1629 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1630 kSlowDuration);
1631
1632 bool expect_send_begin_main_frame = true;
1633 EXPECT_SCOPED(
1634 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1635 }
1636
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong)1637 TEST_F(SchedulerTest,
1638 MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong) {
1639 SetUpScheduler(EXTERNAL_BFS);
1640 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1641 fake_compositor_timing_history_->SetActivateDurationEstimate(kSlowDuration);
1642
1643 bool expect_send_begin_main_frame = true;
1644 EXPECT_SCOPED(
1645 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1646 }
1647
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong)1648 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong) {
1649 SetUpScheduler(EXTERNAL_BFS);
1650 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1651 fake_compositor_timing_history_->SetDrawDurationEstimate(kSlowDuration);
1652
1653 bool expect_send_begin_main_frame = true;
1654 EXPECT_SCOPED(
1655 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1656 }
1657
1658 // If the BeginMainFrame aborts, it doesn't actually insert a frame into the
1659 // queue, which means there is no latency to recover.
TEST_F(SchedulerTest,MainFrameNotSkippedAfterLateBeginMainFrameAbort)1660 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateBeginMainFrameAbort) {
1661 SetUpScheduler(EXTERNAL_BFS);
1662
1663 // Use fast estimates so we think we can recover latency if needed.
1664 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1665
1666 // Impl thread hits deadline before BeginMainFrame aborts.
1667 scheduler_->SetNeedsBeginMainFrame();
1668 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1669 EXPECT_SCOPED(AdvanceFrame());
1670 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1671 "ScheduledActionSendBeginMainFrame");
1672 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1673 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1674 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1675 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1676 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1677
1678 // After aborting the frame, make sure we don't skip the
1679 // next BeginMainFrame.
1680 client_->Reset();
1681 scheduler_->BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
1682 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1683 scheduler_->SetNeedsBeginMainFrame();
1684 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1685 EXPECT_SCOPED(AdvanceFrame());
1686 EXPECT_TRUE(client_->HasAction("WillBeginImplFrame"));
1687 EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
1688 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1689 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1690 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1691 }
1692
1693 // If the BeginMainFrame aborts, it doesn't actually insert a frame into the
1694 // queue, which means there is no latency to recover.
TEST_F(SchedulerTest,MainFrameNotSkippedAfterCanDrawChanges)1695 TEST_F(SchedulerTest, MainFrameNotSkippedAfterCanDrawChanges) {
1696 SetUpScheduler(EXTERNAL_BFS);
1697
1698 // Use fast estimates so we think we can recover latency if needed.
1699 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1700
1701 // Impl thread hits deadline before BeginMainFrame aborts.
1702 scheduler_->SetNeedsBeginMainFrame();
1703 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1704 EXPECT_SCOPED(AdvanceFrame());
1705 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1706 "ScheduledActionSendBeginMainFrame");
1707 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1708 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1709 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1710 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1711 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1712
1713 // Make us abort the upcoming draw.
1714 client_->Reset();
1715 scheduler_->NotifyReadyToCommit(nullptr);
1716 scheduler_->NotifyReadyToActivate();
1717 EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree");
1718 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1719 scheduler_->SetCanDraw(false);
1720 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1721
1722 // Make CanDraw true after activation.
1723 client_->Reset();
1724 scheduler_->SetCanDraw(true);
1725 EXPECT_NO_ACTION();
1726 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1727
1728 // Make sure we don't skip the next BeginMainFrame.
1729 client_->Reset();
1730 scheduler_->SetNeedsBeginMainFrame();
1731 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1732 EXPECT_SCOPED(AdvanceFrame());
1733 EXPECT_TRUE(client_->HasAction("WillBeginImplFrame"));
1734 EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
1735 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1736 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1737 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1738 }
1739
TEST_F(SchedulerTest,MainFrameNotSkippedWhenNoTimingHistory)1740 TEST_F(SchedulerTest, MainFrameNotSkippedWhenNoTimingHistory) {
1741 SetUpScheduler(EXTERNAL_BFS);
1742
1743 // Use fast estimates so we think we can recover latency if needed.
1744 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1745
1746 // Impl thread hits deadline before BeginMainFrame commits.
1747 scheduler_->SetNeedsBeginMainFrame();
1748 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1749 EXPECT_SCOPED(AdvanceFrame());
1750 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1751 "ScheduledActionSendBeginMainFrame");
1752 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1753 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1754 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1755 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1756 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1757
1758 // Commit after the deadline.
1759 client_->Reset();
1760 scheduler_->NotifyReadyToCommit(nullptr);
1761 scheduler_->NotifyReadyToActivate();
1762 EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree");
1763 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1764
1765 // Clear the timing history. Make sure we don't skip the main frame until we
1766 // have history from at least one frame.
1767 client_->Reset();
1768 scheduler_->SetNeedsBeginMainFrame();
1769 scheduler_->ClearHistory();
1770 EXPECT_SCOPED(AdvanceFrame());
1771 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
1772 }
1773
ImplFrameSkippedAfterLateAck(bool is_already_receiving_begin_frames,bool receive_ack_before_deadline)1774 void SchedulerTest::ImplFrameSkippedAfterLateAck(
1775 bool is_already_receiving_begin_frames,
1776 bool receive_ack_before_deadline) {
1777 // To get into a high latency state, this test disables automatic swap acks.
1778 client_->SetAutomaticSubmitCompositorFrameAck(false);
1779
1780 // Draw and swap for first BeginFrame
1781 client_->Reset();
1782 scheduler_->SetNeedsBeginMainFrame();
1783 scheduler_->SetNeedsRedraw();
1784 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1785 SendNextBeginFrame();
1786 if (is_already_receiving_begin_frames) {
1787 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
1788 } else {
1789 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1790 "ScheduledActionSendBeginMainFrame");
1791 }
1792
1793 client_->Reset();
1794 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1795 scheduler_->NotifyReadyToCommit(nullptr);
1796 scheduler_->NotifyReadyToActivate();
1797 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1798 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1799 EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
1800 "ScheduledActionDrawIfPossible");
1801
1802 // Verify we skip every other frame if the swap ack consistently
1803 // comes back late.
1804 for (int i = 0; i < 10; i++) {
1805 // Not calling scheduler_->DidReceiveCompositorFrameAck() until after next
1806 // BeginImplFrame puts the impl thread in high latency mode.
1807 client_->Reset();
1808 scheduler_->SetNeedsBeginMainFrame();
1809 scheduler_->SetNeedsRedraw();
1810 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1811 SendNextBeginFrame();
1812 // Verify that we skip the BeginImplFrame
1813 EXPECT_NO_ACTION();
1814 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1815 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1816
1817 // Verify that we do not perform any actions after we are no longer
1818 // swap throttled.
1819 client_->Reset();
1820 if (receive_ack_before_deadline) {
1821 // It shouldn't matter if the swap ack comes back before the deadline...
1822 scheduler_->DidReceiveCompositorFrameAck();
1823 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1824 } else {
1825 // ... or after the deadline.
1826 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1827 scheduler_->DidReceiveCompositorFrameAck();
1828 }
1829 EXPECT_NO_ACTION();
1830
1831 // Verify that we start the next BeginImplFrame and continue normally
1832 // after having just skipped a BeginImplFrame.
1833 client_->Reset();
1834 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1835 SendNextBeginFrame();
1836 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
1837
1838 client_->Reset();
1839 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1840 scheduler_->NotifyReadyToCommit(nullptr);
1841 scheduler_->NotifyReadyToActivate();
1842 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1843 EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
1844 "ScheduledActionDrawIfPossible");
1845 }
1846 }
1847
TEST_F(SchedulerTest,ImplFrameSkippedAfterLateAck_FastEstimates_SubmitAckThenDeadline)1848 TEST_F(SchedulerTest,
1849 ImplFrameSkippedAfterLateAck_FastEstimates_SubmitAckThenDeadline) {
1850 SetUpScheduler(EXTERNAL_BFS);
1851 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1852
1853 bool is_already_receiving_begin_frames = false;
1854 bool receive_ack_before_deadline = true;
1855 EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
1856 receive_ack_before_deadline));
1857 }
1858
TEST_F(SchedulerTest,ImplFrameSkippedAfterLateAck_FastEstimates_DeadlineThenSubmitAck)1859 TEST_F(SchedulerTest,
1860 ImplFrameSkippedAfterLateAck_FastEstimates_DeadlineThenSubmitAck) {
1861 SetUpScheduler(EXTERNAL_BFS);
1862 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1863
1864 bool is_already_receiving_begin_frames = false;
1865 bool receive_ack_before_deadline = false;
1866 EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
1867 receive_ack_before_deadline));
1868 }
1869
TEST_F(SchedulerTest,ImplFrameSkippedAfterLateAck_LongMainFrameQueueDurationNotCritical)1870 TEST_F(SchedulerTest,
1871 ImplFrameSkippedAfterLateAck_LongMainFrameQueueDurationNotCritical) {
1872 SetUpScheduler(EXTERNAL_BFS);
1873 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
1874 fake_compositor_timing_history_
1875 ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
1876
1877 bool is_already_receiving_begin_frames = false;
1878 bool receive_ack_before_deadline = false;
1879 EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
1880 receive_ack_before_deadline));
1881 }
1882
TEST_F(SchedulerTest,ImplFrameSkippedAfterLateAck_ImplLatencyTakesPriority)1883 TEST_F(SchedulerTest, ImplFrameSkippedAfterLateAck_ImplLatencyTakesPriority) {
1884 SetUpScheduler(EXTERNAL_BFS);
1885
1886 // Even if every estimate related to the main thread is slow, we should
1887 // still expect to recover impl thread latency if the draw is fast and we
1888 // are in impl latency takes priority.
1889 client_->Reset();
1890 scheduler_->SetTreePrioritiesAndScrollState(
1891 SMOOTHNESS_TAKES_PRIORITY,
1892 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
1893 fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
1894 fake_compositor_timing_history_->SetDrawDurationEstimate(kFastDuration);
1895 EXPECT_ACTIONS("AddObserver(this)");
1896
1897 bool is_already_receiving_begin_frames = true;
1898 bool receive_ack_before_deadline = false;
1899 EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
1900 receive_ack_before_deadline));
1901 }
1902
TEST_F(SchedulerTest,ImplFrameSkippedAfterLateAck_OnlyImplSideUpdatesExpected)1903 TEST_F(SchedulerTest,
1904 ImplFrameSkippedAfterLateAck_OnlyImplSideUpdatesExpected) {
1905 // This tests that we recover impl thread latency when there are no commits.
1906 SetUpScheduler(EXTERNAL_BFS);
1907
1908 // To get into a high latency state, this test disables automatic swap acks.
1909 client_->SetAutomaticSubmitCompositorFrameAck(false);
1910
1911 // Even if every estimate related to the main thread is slow, we should
1912 // still expect to recover impl thread latency if there are no commits from
1913 // the main thread.
1914 fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
1915 fake_compositor_timing_history_->SetDrawDurationEstimate(kFastDuration);
1916
1917 // Draw and swap for first BeginFrame
1918 client_->Reset();
1919 scheduler_->SetNeedsRedraw();
1920 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1921 SendNextBeginFrame();
1922 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame");
1923
1924 client_->Reset();
1925 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1926 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1927 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
1928
1929 // Verify we skip every other frame if the swap ack consistently
1930 // comes back late.
1931 for (int i = 0; i < 10; i++) {
1932 // Not calling scheduler_->DidReceiveCompositorFrameAck() until after next
1933 // BeginImplFrame puts the impl thread in high latency mode.
1934 client_->Reset();
1935 scheduler_->SetNeedsRedraw();
1936 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1937 SendNextBeginFrame();
1938 // Verify that we skip the BeginImplFrame
1939 EXPECT_NO_ACTION();
1940 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1941 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1942
1943 // Verify that we do not perform any actions after we are no longer
1944 // swap throttled.
1945 client_->Reset();
1946 scheduler_->DidReceiveCompositorFrameAck();
1947 EXPECT_NO_ACTION();
1948
1949 // Verify that we start the next BeginImplFrame and continue normally
1950 // after having just skipped a BeginImplFrame.
1951 client_->Reset();
1952 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1953 SendNextBeginFrame();
1954 EXPECT_ACTIONS("WillBeginImplFrame");
1955
1956 client_->Reset();
1957 // Deadline should be immediate.
1958 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1959 task_runner_->RunUntilTime(task_runner_->NowTicks());
1960 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
1961 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
1962 }
1963 }
1964
ImplFrameNotSkippedAfterLateAck()1965 void SchedulerTest::ImplFrameNotSkippedAfterLateAck() {
1966 // To get into a high latency state, this test disables automatic swap acks.
1967 client_->SetAutomaticSubmitCompositorFrameAck(false);
1968
1969 // Draw and swap for first BeginFrame
1970 client_->Reset();
1971 scheduler_->SetNeedsBeginMainFrame();
1972 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1973 SendNextBeginFrame();
1974 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
1975 "ScheduledActionSendBeginMainFrame");
1976
1977 client_->Reset();
1978 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
1979 scheduler_->NotifyReadyToCommit(nullptr);
1980 scheduler_->NotifyReadyToActivate();
1981 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1982 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
1983 EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
1984 "ScheduledActionDrawIfPossible");
1985
1986 // Verify impl thread consistently operates in high latency mode
1987 // without skipping any frames.
1988 for (int i = 0; i < 10; i++) {
1989 // Not calling scheduler_->DidReceiveCompositorFrameAck() until after next
1990 // frame
1991 // puts the impl thread in high latency mode.
1992 client_->Reset();
1993 scheduler_->SetNeedsBeginMainFrame();
1994 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1995 SendNextBeginFrame();
1996 EXPECT_ACTIONS("WillBeginImplFrame");
1997 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
1998 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1999
2000 client_->Reset();
2001 scheduler_->DidReceiveCompositorFrameAck();
2002 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2003 scheduler_->NotifyReadyToCommit(nullptr);
2004 scheduler_->NotifyReadyToActivate();
2005 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2006
2007 // Verify that we don't skip the actions of the BeginImplFrame
2008 EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame", "ScheduledActionCommit",
2009 "ScheduledActionActivateSyncTree",
2010 "ScheduledActionDrawIfPossible");
2011 }
2012 }
2013
TEST_F(SchedulerTest,ImplFrameNotSkippedAfterLateAck_MainFrameQueueDurationCriticalTooLong)2014 TEST_F(SchedulerTest,
2015 ImplFrameNotSkippedAfterLateAck_MainFrameQueueDurationCriticalTooLong) {
2016 SetUpScheduler(EXTERNAL_BFS);
2017 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2018 fake_compositor_timing_history_
2019 ->SetBeginMainFrameQueueDurationCriticalEstimate(kSlowDuration);
2020 fake_compositor_timing_history_
2021 ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
2022 EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
2023 }
2024
TEST_F(SchedulerTest,ImplFrameNotSkippedAfterLateAck_CommitEstimateTooLong)2025 TEST_F(SchedulerTest, ImplFrameNotSkippedAfterLateAck_CommitEstimateTooLong) {
2026 SetUpScheduler(EXTERNAL_BFS);
2027 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2028 fake_compositor_timing_history_
2029 ->SetBeginMainFrameStartToReadyToCommitDurationEstimate(kSlowDuration);
2030 EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
2031 }
2032
TEST_F(SchedulerTest,ImplFrameNotSkippedAfterLateAck_ReadyToActivateEstimateTooLong)2033 TEST_F(SchedulerTest,
2034 ImplFrameNotSkippedAfterLateAck_ReadyToActivateEstimateTooLong) {
2035 SetUpScheduler(EXTERNAL_BFS);
2036 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2037 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
2038 kSlowDuration);
2039 EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
2040 }
2041
TEST_F(SchedulerTest,ImplFrameNotSkippedAfterLateAck_ActivateEstimateTooLong)2042 TEST_F(SchedulerTest, ImplFrameNotSkippedAfterLateAck_ActivateEstimateTooLong) {
2043 SetUpScheduler(EXTERNAL_BFS);
2044 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2045 fake_compositor_timing_history_->SetActivateDurationEstimate(kSlowDuration);
2046 EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
2047 }
2048
TEST_F(SchedulerTest,ImplFrameNotSkippedAfterLateAck_DrawEstimateTooLong)2049 TEST_F(SchedulerTest, ImplFrameNotSkippedAfterLateAck_DrawEstimateTooLong) {
2050 SetUpScheduler(EXTERNAL_BFS);
2051 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2052 fake_compositor_timing_history_->SetDrawDurationEstimate(kSlowDuration);
2053 EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
2054 }
2055
TEST_F(SchedulerTest,MainFrameThenImplFrameSkippedAfterLateCommitAndLateAck)2056 TEST_F(SchedulerTest, MainFrameThenImplFrameSkippedAfterLateCommitAndLateAck) {
2057 // Set up client with custom estimates.
2058 // This test starts off with expensive estimates to prevent latency recovery
2059 // initially, then lowers the estimates to enable it once both the main
2060 // and impl threads are in a high latency mode.
2061 SetUpScheduler(EXTERNAL_BFS);
2062 fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
2063
2064 // To get into a high latency state, this test disables automatic swap acks.
2065 client_->SetAutomaticSubmitCompositorFrameAck(false);
2066
2067 // Impl thread hits deadline before commit finishes to make
2068 // MainThreadMissedLastDeadline true
2069 client_->Reset();
2070 scheduler_->SetNeedsBeginMainFrame();
2071 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2072 EXPECT_SCOPED(AdvanceFrame());
2073 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2074 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2075 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2076 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2077 scheduler_->NotifyReadyToCommit(nullptr);
2078 scheduler_->NotifyReadyToActivate();
2079 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2080
2081 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
2082 "ScheduledActionSendBeginMainFrame", "ScheduledActionCommit",
2083 "ScheduledActionActivateSyncTree");
2084
2085 // Draw and swap for first commit, start second commit.
2086 client_->Reset();
2087 scheduler_->SetNeedsBeginMainFrame();
2088 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2089 EXPECT_SCOPED(AdvanceFrame());
2090 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2091 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2092 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2093 scheduler_->NotifyReadyToCommit(nullptr);
2094 scheduler_->NotifyReadyToActivate();
2095
2096 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2097 "ScheduledActionDrawIfPossible", "ScheduledActionCommit",
2098 "ScheduledActionActivateSyncTree");
2099
2100 // Don't call scheduler_->DidReceiveCompositorFrameAck() until after next
2101 // frame
2102 // to put the impl thread in a high latency mode.
2103 client_->Reset();
2104 scheduler_->SetNeedsBeginMainFrame();
2105 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2106 EXPECT_SCOPED(AdvanceFrame());
2107 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2108 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2109
2110 EXPECT_ACTIONS("WillBeginImplFrame");
2111 // Note: BeginMainFrame and swap are skipped here because of
2112 // swap ack backpressure, not because of latency recovery.
2113 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
2114 EXPECT_FALSE(client_->HasAction("ScheduledActionDrawIfPossible"));
2115 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2116
2117 // Lower estimates so that the scheduler will attempt latency recovery.
2118 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
2119
2120 // Now that both threads are in a high latency mode, make sure we
2121 // skip the BeginMainFrame, then the BeginImplFrame, but not both
2122 // at the same time.
2123
2124 // Verify we skip BeginMainFrame first.
2125 client_->Reset();
2126 // Previous commit request is still outstanding.
2127 EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
2128 EXPECT_TRUE(scheduler_->IsDrawThrottled());
2129 SendNextBeginFrame();
2130 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
2131 scheduler_->DidReceiveCompositorFrameAck();
2132 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2133
2134 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2135 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionDrawIfPossible");
2136
2137 // Verify we skip the BeginImplFrame second.
2138 client_->Reset();
2139 // Previous commit request is still outstanding.
2140 EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
2141 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2142 SendNextBeginFrame();
2143 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2144 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2145 scheduler_->DidReceiveCompositorFrameAck();
2146 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2147
2148 EXPECT_NO_ACTION();
2149
2150 // Then verify we operate in a low latency mode.
2151 client_->Reset();
2152 // Previous commit request is still outstanding.
2153 EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
2154 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2155 SendNextBeginFrame();
2156 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2157 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2158 scheduler_->NotifyReadyToCommit(nullptr);
2159 scheduler_->NotifyReadyToActivate();
2160 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2161 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2162 scheduler_->DidReceiveCompositorFrameAck();
2163 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
2164
2165 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2166 "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2167 "ScheduledActionDrawIfPossible");
2168 }
2169
BeginFramesNotFromClient(BeginFrameSourceType bfs_type)2170 void SchedulerTest::BeginFramesNotFromClient(BeginFrameSourceType bfs_type) {
2171 SetUpScheduler(bfs_type);
2172
2173 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame
2174 // without calling SetNeedsBeginFrame.
2175 scheduler_->SetNeedsBeginMainFrame();
2176 EXPECT_NO_ACTION();
2177 client_->Reset();
2178
2179 EXPECT_SCOPED(AdvanceFrame());
2180 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2181 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2182 client_->Reset();
2183
2184 // Can't run the deadline task because it can race with begin frame for the
2185 // SyntheticBFS case.
2186 EXPECT_SCOPED(AdvanceFrame());
2187 EXPECT_ACTIONS("WillBeginImplFrame");
2188 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2189 client_->Reset();
2190
2191 // NotifyReadyToCommit should trigger the commit.
2192 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2193 scheduler_->NotifyReadyToCommit(nullptr);
2194 EXPECT_ACTIONS("ScheduledActionCommit");
2195 client_->Reset();
2196
2197 // NotifyReadyToActivate should trigger the activation.
2198 scheduler_->NotifyReadyToActivate();
2199 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2200 client_->Reset();
2201
2202 // BeginImplFrame deadline should draw. The following BeginImplFrame deadline
2203 // should SetNeedsBeginFrame(false) to avoid excessive toggles.
2204 EXPECT_SCOPED(AdvanceFrame());
2205 EXPECT_ACTIONS("ScheduledActionDrawIfPossible", "WillBeginImplFrame");
2206 client_->Reset();
2207
2208 // Make sure SetNeedsBeginFrame isn't called on the client
2209 // when the BeginFrame is no longer needed.
2210 task_runner_->RunPendingTasks(); // Run posted deadline.
2211 EXPECT_NO_ACTION();
2212 client_->Reset();
2213 }
2214
TEST_F(SchedulerTest,SyntheticBeginFrames)2215 TEST_F(SchedulerTest, SyntheticBeginFrames) {
2216 BeginFramesNotFromClient(THROTTLED_BFS);
2217 }
2218
TEST_F(SchedulerTest,UnthrottledBeginFrames)2219 TEST_F(SchedulerTest, UnthrottledBeginFrames) {
2220 BeginFramesNotFromClient(UNTHROTTLED_BFS);
2221 }
2222
BeginFramesNotFromClient_IsDrawThrottled(BeginFrameSourceType bfs_type)2223 void SchedulerTest::BeginFramesNotFromClient_IsDrawThrottled(
2224 BeginFrameSourceType bfs_type) {
2225 SetUpScheduler(bfs_type);
2226
2227 // Set the draw duration estimate to zero so that deadlines are accurate.
2228 fake_compositor_timing_history_->SetDrawDurationEstimate(base::TimeDelta());
2229
2230 // To test swap ack throttling, this test disables automatic swap acks.
2231 client_->SetAutomaticSubmitCompositorFrameAck(false);
2232
2233 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2234 client_->Reset();
2235 scheduler_->SetNeedsBeginMainFrame();
2236 EXPECT_NO_ACTION();
2237 client_->Reset();
2238
2239 // Trigger the first BeginImplFrame and BeginMainFrame
2240 EXPECT_SCOPED(AdvanceFrame());
2241 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2242 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2243 client_->Reset();
2244
2245 // NotifyReadyToCommit should trigger the pending commit.
2246 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2247 scheduler_->NotifyReadyToCommit(nullptr);
2248 EXPECT_ACTIONS("ScheduledActionCommit");
2249 client_->Reset();
2250
2251 // NotifyReadyToActivate should trigger the activation and draw.
2252 scheduler_->NotifyReadyToActivate();
2253 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2254 client_->Reset();
2255
2256 // Swapping will put us into a swap throttled state.
2257 // Run posted deadline.
2258 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2259 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2260 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2261 client_->Reset();
2262
2263 // While swap throttled, BeginFrames should trigger BeginImplFrames,
2264 // but not a BeginMainFrame or draw.
2265 scheduler_->SetNeedsBeginMainFrame();
2266 scheduler_->SetNeedsRedraw();
2267 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
2268 EXPECT_ACTIONS("WillBeginImplFrame");
2269 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2270 client_->Reset();
2271
2272 base::TimeTicks before_deadline, after_deadline;
2273
2274 // The deadline is set to the regular deadline.
2275 before_deadline = task_runner_->NowTicks();
2276 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2277 after_deadline = task_runner_->NowTicks();
2278 // We can't do an equality comparison here because the scheduler uses a fudge
2279 // factor that's an internal implementation detail.
2280 EXPECT_GT(after_deadline, before_deadline);
2281 EXPECT_LT(after_deadline,
2282 before_deadline + viz::BeginFrameArgs::DefaultInterval());
2283 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2284 client_->Reset();
2285
2286 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
2287 EXPECT_ACTIONS("WillBeginImplFrame");
2288 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2289 client_->Reset();
2290
2291 // Take us out of a swap throttled state.
2292 scheduler_->DidReceiveCompositorFrameAck();
2293 EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame");
2294 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2295 client_->Reset();
2296
2297 // The deadline is set to the regular deadline.
2298 before_deadline = task_runner_->NowTicks();
2299 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2300 after_deadline = task_runner_->NowTicks();
2301 // We can't do an equality comparison here because the scheduler uses a fudge
2302 // factor that's an internal implementation detail.
2303 EXPECT_GT(after_deadline, before_deadline);
2304 EXPECT_LT(after_deadline,
2305 before_deadline + viz::BeginFrameArgs::DefaultInterval());
2306 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2307 client_->Reset();
2308 }
2309
TEST_F(SchedulerTest,SyntheticBeginFrames_IsDrawThrottled)2310 TEST_F(SchedulerTest, SyntheticBeginFrames_IsDrawThrottled) {
2311 BeginFramesNotFromClient_IsDrawThrottled(THROTTLED_BFS);
2312 }
2313
TEST_F(SchedulerTest,UnthrottledBeginFrames_IsDrawThrottled)2314 TEST_F(SchedulerTest, UnthrottledBeginFrames_IsDrawThrottled) {
2315 BeginFramesNotFromClient_IsDrawThrottled(UNTHROTTLED_BFS);
2316 }
2317
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkAfterLayerTreeFrameSinkIsInitialized)2318 TEST_F(SchedulerTest,
2319 DidLoseLayerTreeFrameSinkAfterLayerTreeFrameSinkIsInitialized) {
2320 SetUpSchedulerWithNoLayerTreeFrameSink(EXTERNAL_BFS);
2321
2322 scheduler_->SetVisible(true);
2323 scheduler_->SetCanDraw(true);
2324
2325 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
2326 client_->Reset();
2327 scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
2328 EXPECT_NO_ACTION();
2329
2330 scheduler_->DidLoseLayerTreeFrameSink();
2331 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
2332 }
2333
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkAfterBeginFrameStarted)2334 TEST_F(SchedulerTest, DidLoseLayerTreeFrameSinkAfterBeginFrameStarted) {
2335 SetUpScheduler(EXTERNAL_BFS);
2336
2337 // SetNeedsBeginMainFrame should begin the frame.
2338 scheduler_->SetNeedsBeginMainFrame();
2339 EXPECT_ACTIONS("AddObserver(this)");
2340
2341 client_->Reset();
2342 EXPECT_SCOPED(AdvanceFrame());
2343 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2344 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2345
2346 client_->Reset();
2347 scheduler_->DidLoseLayerTreeFrameSink();
2348 // RemoveObserver(this) is not called until the end of the frame.
2349 EXPECT_NO_ACTION();
2350
2351 client_->Reset();
2352 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2353 scheduler_->NotifyReadyToCommit(nullptr);
2354 EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree");
2355
2356 client_->Reset();
2357 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2358 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
2359 "RemoveObserver(this)");
2360 }
2361
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkAfterBeginFrameStartedWithHighLatency)2362 TEST_F(SchedulerTest,
2363 DidLoseLayerTreeFrameSinkAfterBeginFrameStartedWithHighLatency) {
2364 SetUpScheduler(EXTERNAL_BFS);
2365
2366 // SetNeedsBeginMainFrame should begin the frame.
2367 scheduler_->SetNeedsBeginMainFrame();
2368 EXPECT_ACTIONS("AddObserver(this)");
2369
2370 client_->Reset();
2371 EXPECT_SCOPED(AdvanceFrame());
2372 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2373 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2374
2375 client_->Reset();
2376 scheduler_->DidLoseLayerTreeFrameSink();
2377 // Do nothing when impl frame is in deadine pending state.
2378 EXPECT_NO_ACTION();
2379
2380 client_->Reset();
2381 // Run posted deadline.
2382 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2383 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2384 // OnBeginImplFrameDeadline didn't schedule LayerTreeFrameSink creation
2385 // because
2386 // main frame is not yet completed.
2387 EXPECT_ACTIONS("RemoveObserver(this)");
2388 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2389
2390 // BeginImplFrame is not started.
2391 client_->Reset();
2392 task_runner_->RunUntilTime(task_runner_->NowTicks() +
2393 base::TimeDelta::FromMilliseconds(10));
2394 EXPECT_NO_ACTION();
2395 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2396
2397 client_->Reset();
2398 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2399 scheduler_->NotifyReadyToCommit(nullptr);
2400 EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2401 "ScheduledActionBeginLayerTreeFrameSinkCreation");
2402 }
2403
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkAfterReadyToCommit)2404 TEST_F(SchedulerTest, DidLoseLayerTreeFrameSinkAfterReadyToCommit) {
2405 SetUpScheduler(EXTERNAL_BFS);
2406
2407 // SetNeedsBeginMainFrame should begin the frame.
2408 scheduler_->SetNeedsBeginMainFrame();
2409 EXPECT_ACTIONS("AddObserver(this)");
2410
2411 client_->Reset();
2412 EXPECT_SCOPED(AdvanceFrame());
2413 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2414 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2415
2416 client_->Reset();
2417 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2418 scheduler_->NotifyReadyToCommit(nullptr);
2419 EXPECT_ACTIONS("ScheduledActionCommit");
2420
2421 client_->Reset();
2422 scheduler_->DidLoseLayerTreeFrameSink();
2423 // Sync tree should be forced to activate.
2424 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2425
2426 // RemoveObserver(this) is not called until the end of the frame.
2427 client_->Reset();
2428 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2429 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
2430 "RemoveObserver(this)");
2431 }
2432
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkAfterSetNeedsPrepareTiles)2433 TEST_F(SchedulerTest, DidLoseLayerTreeFrameSinkAfterSetNeedsPrepareTiles) {
2434 SetUpScheduler(EXTERNAL_BFS);
2435
2436 scheduler_->SetNeedsPrepareTiles();
2437 scheduler_->SetNeedsRedraw();
2438 EXPECT_ACTIONS("AddObserver(this)");
2439
2440 client_->Reset();
2441 EXPECT_SCOPED(AdvanceFrame());
2442 EXPECT_ACTIONS("WillBeginImplFrame");
2443 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2444
2445 client_->Reset();
2446 scheduler_->DidLoseLayerTreeFrameSink();
2447 // RemoveObserver(this) is not called until the end of the frame.
2448 EXPECT_NO_ACTION();
2449
2450 client_->Reset();
2451 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2452 EXPECT_ACTIONS("ScheduledActionPrepareTiles",
2453 "ScheduledActionBeginLayerTreeFrameSinkCreation",
2454 "RemoveObserver(this)");
2455 }
2456
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkWithDelayBasedBeginFrameSource)2457 TEST_F(SchedulerTest, DidLoseLayerTreeFrameSinkWithDelayBasedBeginFrameSource) {
2458 SetUpScheduler(THROTTLED_BFS);
2459
2460 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2461 EXPECT_FALSE(scheduler_->begin_frames_expected());
2462 scheduler_->SetNeedsBeginMainFrame();
2463 EXPECT_TRUE(scheduler_->begin_frames_expected());
2464
2465 client_->Reset();
2466 AdvanceFrame();
2467 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2468 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2469 EXPECT_TRUE(scheduler_->begin_frames_expected());
2470
2471 // NotifyReadyToCommit should trigger the commit.
2472 client_->Reset();
2473 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2474 scheduler_->NotifyReadyToCommit(nullptr);
2475 EXPECT_ACTIONS("ScheduledActionCommit");
2476 EXPECT_TRUE(scheduler_->begin_frames_expected());
2477
2478 // NotifyReadyToActivate should trigger the activation.
2479 client_->Reset();
2480 scheduler_->NotifyReadyToActivate();
2481 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2482 EXPECT_TRUE(scheduler_->begin_frames_expected());
2483
2484 client_->Reset();
2485 scheduler_->DidLoseLayerTreeFrameSink();
2486 // RemoveObserver(this) is not called until the end of the frame.
2487 EXPECT_NO_ACTION();
2488 EXPECT_TRUE(scheduler_->begin_frames_expected());
2489
2490 client_->Reset();
2491 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2492 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
2493 EXPECT_FALSE(scheduler_->begin_frames_expected());
2494 }
2495
TEST_F(SchedulerTest,DidLoseLayerTreeFrameSinkWhenIdle)2496 TEST_F(SchedulerTest, DidLoseLayerTreeFrameSinkWhenIdle) {
2497 SetUpScheduler(EXTERNAL_BFS);
2498
2499 // SetNeedsBeginMainFrame should begin the frame.
2500 scheduler_->SetNeedsBeginMainFrame();
2501 EXPECT_ACTIONS("AddObserver(this)");
2502
2503 client_->Reset();
2504 EXPECT_SCOPED(AdvanceFrame());
2505 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2506 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2507
2508 client_->Reset();
2509 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2510 scheduler_->NotifyReadyToCommit(nullptr);
2511 EXPECT_ACTIONS("ScheduledActionCommit");
2512
2513 client_->Reset();
2514 scheduler_->NotifyReadyToActivate();
2515 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2516
2517 client_->Reset();
2518 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
2519 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2520
2521 // Idle time between BeginFrames.
2522 client_->Reset();
2523 scheduler_->DidLoseLayerTreeFrameSink();
2524 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
2525 "RemoveObserver(this)");
2526 }
2527
TEST_F(SchedulerTest,ScheduledActionActivateAfterBecomingInvisible)2528 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
2529 SetUpScheduler(EXTERNAL_BFS);
2530
2531 // SetNeedsBeginMainFrame should begin the frame.
2532 scheduler_->SetNeedsBeginMainFrame();
2533 EXPECT_ACTIONS("AddObserver(this)");
2534
2535 client_->Reset();
2536 EXPECT_SCOPED(AdvanceFrame());
2537 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2538 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2539
2540 client_->Reset();
2541 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2542 scheduler_->NotifyReadyToCommit(nullptr);
2543 EXPECT_ACTIONS("ScheduledActionCommit");
2544 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2545
2546 client_->Reset();
2547 scheduler_->SetVisible(false);
2548 task_runner_->RunPendingTasks(); // Run posted deadline.
2549
2550 // Sync tree should be forced to activate.
2551 EXPECT_ACTIONS("ScheduledActionActivateSyncTree", "RemoveObserver(this)");
2552 }
2553
TEST_F(SchedulerTest,ScheduledActionActivateAfterBeginFrameSourcePaused)2554 TEST_F(SchedulerTest, ScheduledActionActivateAfterBeginFrameSourcePaused) {
2555 SetUpScheduler(EXTERNAL_BFS);
2556
2557 // SetNeedsBeginMainFrame should begin the frame.
2558 scheduler_->SetNeedsBeginMainFrame();
2559 EXPECT_ACTIONS("AddObserver(this)");
2560
2561 client_->Reset();
2562 EXPECT_SCOPED(AdvanceFrame());
2563 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2564 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2565
2566 client_->Reset();
2567 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2568 scheduler_->NotifyReadyToCommit(nullptr);
2569 EXPECT_ACTIONS("ScheduledActionCommit");
2570 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2571
2572 client_->Reset();
2573 fake_external_begin_frame_source_->SetPaused(true);
2574 task_runner_->RunPendingTasks(); // Run posted deadline.
2575
2576 // Sync tree should be forced to activate.
2577 // Pausing the begin frame source aborts the draw. Then
2578 // ProactiveBeginFrameWanted is no longer true, so the scheduler stops
2579 // listening for begin frames.
2580 EXPECT_ACTIONS("ScheduledActionActivateSyncTree", "RemoveObserver(this)");
2581 }
2582
2583 // Tests to ensure frame sources can be successfully changed while drawing.
TEST_F(SchedulerTest,SwitchFrameSourceToUnthrottled)2584 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
2585 SetUpScheduler(EXTERNAL_BFS);
2586
2587 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2588 scheduler_->SetNeedsRedraw();
2589 EXPECT_ACTIONS("AddObserver(this)");
2590 client_->Reset();
2591
2592 EXPECT_SCOPED(AdvanceFrame());
2593 EXPECT_ACTIONS("WillBeginImplFrame");
2594 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2595 EXPECT_TRUE(scheduler_->begin_frames_expected());
2596 client_->Reset();
2597 task_runner_->RunPendingTasks(); // Run posted deadline.
2598 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2599 scheduler_->SetNeedsRedraw();
2600
2601 // Switch to an unthrottled frame source.
2602 scheduler_->SetBeginFrameSource(unthrottled_frame_source_.get());
2603 client_->Reset();
2604
2605 // Unthrottled frame source will immediately begin a new frame.
2606 task_runner_->RunPendingTasks(); // Run posted BeginFrame.
2607 EXPECT_ACTIONS("WillBeginImplFrame");
2608 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2609 client_->Reset();
2610
2611 // If we don't swap on the deadline, we wait for the next BeginFrame.
2612 task_runner_->RunPendingTasks(); // Run posted deadline.
2613 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2614 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2615 client_->Reset();
2616 }
2617
2618 // Tests to ensure frame sources can be successfully changed while a frame
2619 // deadline is pending.
TEST_F(SchedulerTest,SwitchFrameSourceToUnthrottledBeforeDeadline)2620 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
2621 SetUpScheduler(EXTERNAL_BFS);
2622
2623 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2624 scheduler_->SetNeedsRedraw();
2625 EXPECT_ACTIONS("AddObserver(this)");
2626 client_->Reset();
2627
2628 EXPECT_SCOPED(AdvanceFrame());
2629 EXPECT_ACTIONS("WillBeginImplFrame");
2630
2631 // Switch to an unthrottled frame source before the frame deadline is hit.
2632 scheduler_->SetBeginFrameSource(unthrottled_frame_source_.get());
2633 client_->Reset();
2634
2635 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2636 EXPECT_TRUE(scheduler_->begin_frames_expected());
2637 client_->Reset();
2638
2639 task_runner_->RunPendingTasks(); // Run posted deadline.
2640 EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
2641 // Unthrottled frame source will immediately begin a new frame.
2642 "WillBeginImplFrame");
2643 scheduler_->SetNeedsRedraw();
2644 client_->Reset();
2645
2646 task_runner_->RunPendingTasks(); // Run posted deadline.
2647 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2648 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2649 client_->Reset();
2650 }
2651
2652 // Tests to ensure that the active frame source can successfully be changed from
2653 // unthrottled to throttled.
TEST_F(SchedulerTest,SwitchFrameSourceToThrottled)2654 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
2655 SetUpScheduler(UNTHROTTLED_BFS);
2656
2657 scheduler_->SetNeedsRedraw();
2658 EXPECT_NO_ACTION();
2659 client_->Reset();
2660
2661 task_runner_->RunPendingTasks(); // Run posted BeginFrame.
2662 EXPECT_ACTIONS("WillBeginImplFrame");
2663 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2664 client_->Reset();
2665
2666 task_runner_->RunPendingTasks(); // Run posted deadline.
2667 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2668 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2669 client_->Reset();
2670
2671 // Switch to a throttled frame source.
2672 scheduler_->SetBeginFrameSource(fake_external_begin_frame_source_.get());
2673 client_->Reset();
2674
2675 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2676 scheduler_->SetNeedsRedraw();
2677 task_runner_->RunPendingTasks();
2678 EXPECT_NO_ACTION();
2679 client_->Reset();
2680
2681 EXPECT_SCOPED(AdvanceFrame());
2682 EXPECT_ACTIONS("WillBeginImplFrame");
2683 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2684 EXPECT_TRUE(scheduler_->begin_frames_expected());
2685 client_->Reset();
2686 task_runner_->RunPendingTasks(); // Run posted deadline.
2687 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2688 }
2689
TEST_F(SchedulerTest,SwitchFrameSourceToNullInsideDeadline)2690 TEST_F(SchedulerTest, SwitchFrameSourceToNullInsideDeadline) {
2691 SetUpScheduler(EXTERNAL_BFS);
2692
2693 scheduler_->SetNeedsRedraw();
2694 EXPECT_ACTIONS("AddObserver(this)");
2695 client_->Reset();
2696
2697 EXPECT_SCOPED(AdvanceFrame());
2698 EXPECT_ACTIONS("WillBeginImplFrame");
2699 client_->Reset();
2700
2701 // Switch to a null frame source.
2702 scheduler_->SetBeginFrameSource(nullptr);
2703 EXPECT_ACTIONS("RemoveObserver(this)");
2704 client_->Reset();
2705
2706 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2707 task_runner_->RunPendingTasks(); // Run posted deadline.
2708 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2709 EXPECT_FALSE(scheduler_->begin_frames_expected());
2710 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2711 client_->Reset();
2712
2713 // AdvanceFrame helper can't be used here because there's no deadline posted.
2714 scheduler_->SetNeedsRedraw();
2715 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2716 EXPECT_NO_ACTION();
2717 client_->Reset();
2718
2719 scheduler_->SetNeedsBeginMainFrame();
2720 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2721 EXPECT_NO_ACTION();
2722 client_->Reset();
2723
2724 // Switch back to the same source, make sure frames continue to be produced.
2725 scheduler_->SetBeginFrameSource(fake_external_begin_frame_source_.get());
2726 EXPECT_ACTIONS("AddObserver(this)");
2727 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
2728 client_->Reset();
2729
2730 EXPECT_SCOPED(AdvanceFrame());
2731 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2732 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2733 client_->Reset();
2734
2735 task_runner_->RunPendingTasks();
2736 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
2737 }
2738
2739 // This test maskes sure that switching a frame source when not observing
2740 // such as when not visible also works.
TEST_F(SchedulerTest,SwitchFrameSourceWhenNotObserving)2741 TEST_F(SchedulerTest, SwitchFrameSourceWhenNotObserving) {
2742 SetUpScheduler(EXTERNAL_BFS);
2743
2744 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2745 scheduler_->SetNeedsBeginMainFrame();
2746 EXPECT_ACTIONS("AddObserver(this)");
2747 client_->Reset();
2748
2749 // Begin new frame.
2750 EXPECT_SCOPED(AdvanceFrame());
2751 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2752 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2753
2754 client_->Reset();
2755 scheduler_->NotifyReadyToCommit(nullptr);
2756 EXPECT_ACTIONS("ScheduledActionCommit");
2757
2758 client_->Reset();
2759 scheduler_->NotifyReadyToActivate();
2760 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
2761
2762 // Scheduler loses LayerTreeFrameSink, and stops waiting for ready to draw
2763 // signal.
2764 client_->Reset();
2765 scheduler_->DidLoseLayerTreeFrameSink();
2766 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2767 task_runner_->RunPendingTasks();
2768 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
2769 "RemoveObserver(this)");
2770
2771 // Changing begin frame source doesn't do anything.
2772 // The unthrottled source doesn't print Add/RemoveObserver like the fake one.
2773 client_->Reset();
2774 scheduler_->SetBeginFrameSource(unthrottled_frame_source_.get());
2775 EXPECT_NO_ACTION();
2776
2777 client_->Reset();
2778 scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
2779 EXPECT_NO_ACTION();
2780
2781 client_->Reset();
2782 scheduler_->SetNeedsBeginMainFrame();
2783 EXPECT_NO_ACTION();
2784
2785 client_->Reset();
2786 EXPECT_SCOPED(AdvanceFrame());
2787 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
2788 }
2789
2790 // Tests to ensure that we send a ScheduledActionBeginMainFrameNotExpectedUntil
2791 // when expected.
TEST_F(SchedulerTest,ScheduledActionBeginMainFrameNotExpectedUntil)2792 TEST_F(SchedulerTest, ScheduledActionBeginMainFrameNotExpectedUntil) {
2793 SetUpScheduler(EXTERNAL_BFS);
2794
2795 scheduler_->SetNeedsRedraw();
2796 EXPECT_ACTIONS("AddObserver(this)");
2797 client_->Reset();
2798
2799 EXPECT_SCOPED(AdvanceFrame());
2800 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2801 task_runner_->RunPendingTasks();
2802 EXPECT_ACTIONS("WillBeginImplFrame",
2803 "ScheduledActionBeginMainFrameNotExpectedUntil",
2804 "ScheduledActionDrawIfPossible");
2805 }
2806
2807 // Tests to ensure that BeginMainFrameNotExpectedUntil is only sent once within
2808 // the same frame.
TEST_F(SchedulerTest,ScheduledActionBeginMainFrameNotExpectedUntilSentOnlyOncePerFrame)2809 TEST_F(SchedulerTest,
2810 ScheduledActionBeginMainFrameNotExpectedUntilSentOnlyOncePerFrame) {
2811 SetUpScheduler(EXTERNAL_BFS);
2812
2813 scheduler_->SetNeedsRedraw();
2814 EXPECT_ACTIONS("AddObserver(this)");
2815 client_->Reset();
2816
2817 EXPECT_SCOPED(AdvanceFrame());
2818 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2819 task_runner_->RunPendingTasks();
2820 EXPECT_ACTIONS("WillBeginImplFrame",
2821 "ScheduledActionBeginMainFrameNotExpectedUntil",
2822 "ScheduledActionDrawIfPossible");
2823 client_->Reset();
2824
2825 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(false);
2826 task_runner_->RunPendingTasks();
2827 EXPECT_NO_ACTION();
2828
2829 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2830 task_runner_->RunPendingTasks();
2831 EXPECT_NO_ACTION();
2832 }
2833
2834 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
TEST_F(SchedulerTest,SendBeginMainFrameNotExpectedSoon_Requested)2835 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon_Requested) {
2836 SetUpScheduler(EXTERNAL_BFS);
2837
2838 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2839 scheduler_->SetNeedsBeginMainFrame();
2840 EXPECT_ACTIONS("AddObserver(this)");
2841 client_->Reset();
2842
2843 // Trigger a frame draw.
2844 EXPECT_SCOPED(AdvanceFrame());
2845 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2846 scheduler_->NotifyReadyToCommit(nullptr);
2847 scheduler_->NotifyReadyToActivate();
2848 task_runner_->RunPendingTasks();
2849 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2850 "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2851 "ScheduledActionDrawIfPossible");
2852 client_->Reset();
2853
2854 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2855
2856 EXPECT_SCOPED(AdvanceFrame());
2857 EXPECT_ACTIONS("WillBeginImplFrame",
2858 "ScheduledActionBeginMainFrameNotExpectedUntil");
2859 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2860 client_->Reset();
2861
2862 // The BeginImplFrame deadline should SetNeedsBeginFrame(false) and send a
2863 // SendBeginMainFrameNotExpectedSoon.
2864 task_runner_->RunPendingTasks(); // Run posted deadline.
2865 EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon", "RemoveObserver(this)");
2866 client_->Reset();
2867 }
2868
2869 // Tests to ensure that we dont't send a BeginMainFrameNotExpectedSoon when
2870 // possible but not requested.
TEST_F(SchedulerTest,SendBeginMainFrameNotExpectedSoon_Unrequested)2871 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon_Unrequested) {
2872 SetUpScheduler(EXTERNAL_BFS);
2873
2874 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2875 scheduler_->SetNeedsBeginMainFrame();
2876 EXPECT_ACTIONS("AddObserver(this)");
2877 client_->Reset();
2878
2879 // Trigger a frame draw.
2880 EXPECT_SCOPED(AdvanceFrame());
2881 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2882 scheduler_->NotifyReadyToCommit(nullptr);
2883 scheduler_->NotifyReadyToActivate();
2884 task_runner_->RunPendingTasks();
2885 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2886 "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2887 "ScheduledActionDrawIfPossible");
2888 client_->Reset();
2889
2890 EXPECT_SCOPED(AdvanceFrame());
2891 EXPECT_ACTIONS("WillBeginImplFrame");
2892 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2893 client_->Reset();
2894
2895 // The BeginImplFrame deadline should SetNeedsBeginFrame(false), but doesn't
2896 // send a SendBeginMainFrameNotExpectedSoon as it's not been requested by the
2897 // main thread.
2898 task_runner_->RunPendingTasks(); // Run posted deadline.
2899 EXPECT_ACTIONS("RemoveObserver(this)");
2900 client_->Reset();
2901
2902 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2903
2904 EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon");
2905 }
2906
2907 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon only once per
2908 // frame.
TEST_F(SchedulerTest,SendBeginMainFrameNotExpectedSoonOnlyOncePerFrame)2909 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoonOnlyOncePerFrame) {
2910 SetUpScheduler(EXTERNAL_BFS);
2911
2912 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2913 scheduler_->SetNeedsBeginMainFrame();
2914 EXPECT_ACTIONS("AddObserver(this)");
2915 client_->Reset();
2916
2917 // Trigger a frame draw.
2918 EXPECT_SCOPED(AdvanceFrame());
2919 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2920 scheduler_->NotifyReadyToCommit(nullptr);
2921 scheduler_->NotifyReadyToActivate();
2922 task_runner_->RunPendingTasks();
2923 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2924 "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2925 "ScheduledActionDrawIfPossible");
2926 client_->Reset();
2927
2928 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2929
2930 EXPECT_SCOPED(AdvanceFrame());
2931 EXPECT_ACTIONS("WillBeginImplFrame",
2932 "ScheduledActionBeginMainFrameNotExpectedUntil");
2933 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2934 client_->Reset();
2935
2936 task_runner_->RunPendingTasks(); // Run posted deadline.
2937 EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon", "RemoveObserver(this)");
2938 client_->Reset();
2939
2940 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(false);
2941 EXPECT_NO_ACTION();
2942
2943 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2944 EXPECT_NO_ACTION();
2945 }
2946
2947 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon in situations
2948 // where the client doesn't want messages when we first stopped observing
2949 // BeginFrames but later does.
TEST_F(SchedulerTest,SendBeginMainFrameNotExpectedSoon_AlreadyIdle)2950 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon_AlreadyIdle) {
2951 SetUpScheduler(EXTERNAL_BFS);
2952
2953 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2954 scheduler_->SetNeedsBeginMainFrame();
2955 EXPECT_ACTIONS("AddObserver(this)");
2956 client_->Reset();
2957
2958 // Trigger a frame draw.
2959 EXPECT_SCOPED(AdvanceFrame());
2960 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
2961 scheduler_->NotifyReadyToCommit(nullptr);
2962 scheduler_->NotifyReadyToActivate();
2963 task_runner_->RunPendingTasks();
2964 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
2965 "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
2966 "ScheduledActionDrawIfPossible");
2967 client_->Reset();
2968
2969 EXPECT_SCOPED(AdvanceFrame());
2970 task_runner_->RunPendingTasks(); // Run posted deadline.
2971 EXPECT_ACTIONS("WillBeginImplFrame", "RemoveObserver(this)");
2972 client_->Reset();
2973
2974 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
2975 EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon");
2976 }
2977
2978 // This tests to ensure BeginMainFrameNotExpectedSoon is sent during idle
2979 // periods if (1) it initially wasn't sent because the message wasn't needed at
2980 // the time, and (2) the BeginMainFrameNotExpectedUntil was already sent in the
2981 // frame (crbug.com/893653).
TEST_F(SchedulerTest,SendBeginMainFrameNotExpectedSoonDuringIdleIfNeeded)2982 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoonDuringIdleIfNeeded) {
2983 SetUpScheduler(EXTERNAL_BFS);
2984
2985 scheduler_->SetNeedsRedraw();
2986 EXPECT_ACTIONS("AddObserver(this)");
2987 client_->Reset();
2988
2989 EXPECT_SCOPED(AdvanceFrame());
2990 task_runner_->RunPendingTasks();
2991 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionDrawIfPossible");
2992 client_->Reset();
2993
2994 EXPECT_SCOPED(AdvanceFrame());
2995 EXPECT_ACTIONS("WillBeginImplFrame");
2996 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
2997 client_->Reset();
2998
2999 // Toggle WantsBeginMainFrameNotExpected while inside BeginImplFrame. This
3000 // causes the BeginMainFrameNotExpectedUntil message to get sent and the
3001 // BeginMainFrameNotExpectedSoon message to be withheld.
3002 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
3003 EXPECT_ACTIONS("ScheduledActionBeginMainFrameNotExpectedUntil");
3004 client_->Reset();
3005 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(false);
3006 task_runner_->RunPendingTasks();
3007 EXPECT_ACTIONS("RemoveObserver(this)");
3008 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3009 client_->Reset();
3010
3011 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
3012 EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon");
3013 }
3014
3015 // This tests to ensure BeginMainFrameNotExpectedSoon is sent during idle
3016 // periods if (1) it initially wasn't sent because the message wasn't needed at
3017 // the time, and (2) |scheduler_|.visible() is false.
TEST_F(SchedulerTest,ScheduledActionBeginMainFrameNotSoonSentDuringIdleIfNeededNotVisible)3018 TEST_F(SchedulerTest,
3019 ScheduledActionBeginMainFrameNotSoonSentDuringIdleIfNeededNotVisible) {
3020 SetUpScheduler(EXTERNAL_BFS);
3021
3022 scheduler_->SetNeedsRedraw();
3023 EXPECT_ACTIONS("AddObserver(this)");
3024 client_->Reset();
3025
3026 EXPECT_SCOPED(AdvanceFrame());
3027 task_runner_->RunPendingTasks();
3028 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionDrawIfPossible");
3029 client_->Reset();
3030
3031 EXPECT_SCOPED(AdvanceFrame());
3032 EXPECT_ACTIONS("WillBeginImplFrame");
3033 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3034 client_->Reset();
3035
3036 scheduler_->SetVisible(false);
3037
3038 task_runner_->RunPendingTasks();
3039 EXPECT_ACTIONS("RemoveObserver(this)");
3040 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3041
3042 // The scheduler won't send BeginMainFrameNotExpectedUntil messages while not
3043 // visible, but it needs to send a BeginMainFrameNotExpectedSoon to let the
3044 // client know it's gone idle.
3045 client_->Reset();
3046 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
3047 EXPECT_ACTIONS("SendBeginMainFrameNotExpectedSoon");
3048 }
3049
TEST_F(SchedulerTest,SynchronousCompositorAnimation)3050 TEST_F(SchedulerTest, SynchronousCompositorAnimation) {
3051 scheduler_settings_.using_synchronous_renderer_compositor = true;
3052 SetUpScheduler(EXTERNAL_BFS);
3053
3054 scheduler_->SetNeedsOneBeginImplFrame();
3055 EXPECT_ACTIONS("AddObserver(this)");
3056 client_->Reset();
3057
3058 // Testing the case where animation ticks a fling scroll.
3059 client_->SetWillBeginImplFrameCausesRedraw(true);
3060 // The animation isn't done so it'll cause another tick in the future.
3061 client_->SetWillBeginImplFrameRequestsOneBeginImplFrame(true);
3062
3063 // Next vsync.
3064 AdvanceFrame();
3065 EXPECT_ACTIONS("WillBeginImplFrame",
3066 "ScheduledActionInvalidateLayerTreeFrameSink");
3067 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3068 client_->Reset();
3069
3070 // Android onDraw. This doesn't consume the single begin frame request.
3071 scheduler_->SetNeedsRedraw();
3072 bool resourceless_software_draw = false;
3073 bool skip_draw = false;
3074 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3075 skip_draw);
3076 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3077 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3078 client_->Reset();
3079
3080 // The animation inside of WillBeginImplFrame changes stuff on the screen, but
3081 // ends here, so does not cause another frame to happen.
3082 client_->SetWillBeginImplFrameCausesRedraw(true);
3083
3084 // Next vsync.
3085 AdvanceFrame();
3086 EXPECT_ACTIONS("WillBeginImplFrame",
3087 "ScheduledActionInvalidateLayerTreeFrameSink");
3088 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3089 client_->Reset();
3090
3091 // Android onDraw.
3092 scheduler_->SetNeedsRedraw();
3093 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3094 skip_draw);
3095 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3096 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3097 client_->Reset();
3098
3099 // Idle on next vsync, as the animation has completed.
3100 AdvanceFrame();
3101 EXPECT_ACTIONS("WillBeginImplFrame", "RemoveObserver(this)");
3102 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3103 client_->Reset();
3104 }
3105
TEST_F(SchedulerTest,SynchronousCompositorOnDrawDuringIdle)3106 TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) {
3107 scheduler_settings_.using_synchronous_renderer_compositor = true;
3108 SetUpScheduler(EXTERNAL_BFS);
3109
3110 scheduler_->SetNeedsRedraw();
3111 bool resourceless_software_draw = false;
3112 bool skip_draw = false;
3113 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3114 skip_draw);
3115 EXPECT_ACTIONS("AddObserver(this)", "ScheduledActionDrawIfPossible");
3116 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3117 client_->Reset();
3118
3119 // Idle on next vsync.
3120 AdvanceFrame();
3121 EXPECT_ACTIONS("WillBeginImplFrame", "RemoveObserver(this)");
3122 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3123 client_->Reset();
3124 }
3125
TEST_F(SchedulerTest,InvalidateLayerTreeFrameSinkWhenCannotDraw)3126 TEST_F(SchedulerTest, InvalidateLayerTreeFrameSinkWhenCannotDraw) {
3127 scheduler_settings_.using_synchronous_renderer_compositor = true;
3128 SetUpScheduler(EXTERNAL_BFS);
3129
3130 scheduler_->SetCanDraw(false);
3131
3132 scheduler_->SetNeedsRedraw();
3133 EXPECT_ACTIONS("AddObserver(this)");
3134 client_->Reset();
3135
3136 // Do not invalidate in next BeginFrame.
3137 EXPECT_SCOPED(AdvanceFrame());
3138 EXPECT_ACTIONS("WillBeginImplFrame");
3139 client_->Reset();
3140
3141 // Redraw is not cleared.
3142 EXPECT_TRUE(scheduler_->RedrawPending());
3143
3144 scheduler_->SetCanDraw(true);
3145
3146 // Do invalidate in next BeginFrame.
3147 EXPECT_SCOPED(AdvanceFrame());
3148 EXPECT_ACTIONS("WillBeginImplFrame",
3149 "ScheduledActionInvalidateLayerTreeFrameSink");
3150 client_->Reset();
3151
3152 bool resourceless_software_draw = false;
3153 bool skip_draw = false;
3154 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3155 skip_draw);
3156 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3157 EXPECT_FALSE(scheduler_->RedrawPending());
3158 }
3159
TEST_F(SchedulerTest,NeedsPrepareTilesInvalidates)3160 TEST_F(SchedulerTest, NeedsPrepareTilesInvalidates) {
3161 // This is to test that SetNeedsPrepareTiles causes invalidates even if
3162 // CanDraw is false.
3163 scheduler_settings_.using_synchronous_renderer_compositor = true;
3164 SetUpScheduler(EXTERNAL_BFS);
3165
3166 scheduler_->SetCanDraw(false);
3167
3168 scheduler_->SetNeedsPrepareTiles();
3169 EXPECT_ACTIONS("AddObserver(this)");
3170 client_->Reset();
3171
3172 // Do not invalidate in next BeginFrame.
3173 EXPECT_SCOPED(AdvanceFrame());
3174 EXPECT_ACTIONS("WillBeginImplFrame",
3175 "ScheduledActionInvalidateLayerTreeFrameSink");
3176 client_->Reset();
3177 }
3178
TEST_F(SchedulerTest,SetNeedsOneBeginImplFrame)3179 TEST_F(SchedulerTest, SetNeedsOneBeginImplFrame) {
3180 SetUpScheduler(EXTERNAL_BFS);
3181
3182 EXPECT_FALSE(scheduler_->begin_frames_expected());
3183
3184 // Request a frame, should kick the source.
3185 scheduler_->SetNeedsOneBeginImplFrame();
3186 EXPECT_ACTIONS("AddObserver(this)");
3187 client_->Reset();
3188
3189 // The incoming WillBeginImplFrame will request another one.
3190 client_->SetWillBeginImplFrameRequestsOneBeginImplFrame(true);
3191
3192 // Next vsync, the first requested frame happens.
3193 EXPECT_SCOPED(AdvanceFrame());
3194 EXPECT_ACTIONS("WillBeginImplFrame");
3195 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3196 client_->Reset();
3197
3198 // We don't request another frame here.
3199
3200 // Next vsync, the second requested frame happens (the one requested inside
3201 // the previous frame's begin impl frame step).
3202 EXPECT_SCOPED(AdvanceFrame());
3203 EXPECT_ACTIONS("WillBeginImplFrame");
3204 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3205 client_->Reset();
3206
3207 // End that frame's deadline.
3208 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
3209 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3210
3211 // Scheduler shuts down the source now that no begin frame is requested.
3212 EXPECT_ACTIONS("RemoveObserver(this)");
3213 }
3214
TEST_F(SchedulerTest,AbortEarlyIfNoDamage)3215 TEST_F(SchedulerTest, AbortEarlyIfNoDamage) {
3216 SetUpScheduler(EXTERNAL_BFS);
3217
3218 // WillBeginImplFrame will return false, so draws should never be scheduled
3219 // and client_->num_draws() should stay at 0.
3220 client_->SetWillBeginImplFrameMightHaveDamage(false);
3221
3222 scheduler_->SetNeedsRedraw();
3223 EXPECT_EQ(0, client_->num_draws());
3224 EXPECT_ACTIONS("AddObserver(this)");
3225
3226 EXPECT_SCOPED(AdvanceFrame());
3227 task_runner_->RunPendingTasks(); // Run posted deadline.
3228 // Should not try to schedule a draw. (ScheduledActionDrawIfPossible should
3229 // not appear.)
3230 // When the frame is aborted, the scheduler does not ask for a proactive begin
3231 // frame, so stop listening for begin frames.
3232 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
3233 "RemoveObserver(this)");
3234 EXPECT_EQ(0, client_->num_draws());
3235
3236 scheduler_->SetNeedsRedraw();
3237 EXPECT_SCOPED(AdvanceFrame());
3238 task_runner_->RunPendingTasks(); // Run posted deadline.
3239 EXPECT_EQ(0, client_->num_draws());
3240 }
3241
TEST_F(SchedulerTest,SkipDraw)3242 TEST_F(SchedulerTest, SkipDraw) {
3243 scheduler_settings_.using_synchronous_renderer_compositor = true;
3244 SetUpScheduler(EXTERNAL_BFS);
3245
3246 scheduler_->SetNeedsOneBeginImplFrame();
3247 EXPECT_ACTIONS("AddObserver(this)");
3248 client_->Reset();
3249
3250 client_->SetWillBeginImplFrameCausesRedraw(true);
3251
3252 // Next vsync.
3253 AdvanceFrame();
3254 EXPECT_ACTIONS("WillBeginImplFrame",
3255 "ScheduledActionInvalidateLayerTreeFrameSink");
3256 EXPECT_TRUE(client_->invalidate_needs_redraw());
3257 client_->Reset();
3258
3259 // Android onDraw. This doesn't consume the single begin frame request.
3260 scheduler_->SetNeedsPrepareTiles();
3261 bool resourceless_software_draw = false;
3262 bool skip_draw = false;
3263 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3264 skip_draw);
3265 EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
3266 "ScheduledActionPrepareTiles");
3267 client_->Reset();
3268
3269 // Next vsync.
3270 scheduler_->SetNeedsPrepareTiles();
3271 AdvanceFrame();
3272 EXPECT_ACTIONS("WillBeginImplFrame",
3273 "ScheduledActionInvalidateLayerTreeFrameSink");
3274 EXPECT_FALSE(client_->invalidate_needs_redraw());
3275 client_->Reset();
3276
3277 // Android onDraw.
3278 scheduler_->SetNeedsRedraw();
3279 scheduler_->SetNeedsPrepareTiles();
3280 client_->SetInvalidateNeedsRedraw(false);
3281 skip_draw = true;
3282 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3283 skip_draw);
3284 EXPECT_ACTIONS("ScheduledActionPrepareTiles");
3285 client_->Reset();
3286 }
3287
TEST_F(SchedulerTest,SynchronousCompositorCommitAndVerifyBeginFrameAcks)3288 TEST_F(SchedulerTest, SynchronousCompositorCommitAndVerifyBeginFrameAcks) {
3289 scheduler_settings_.using_synchronous_renderer_compositor = true;
3290 SetUpScheduler(EXTERNAL_BFS);
3291
3292 scheduler_->SetNeedsBeginMainFrame();
3293 EXPECT_ACTIONS("AddObserver(this)");
3294 client_->Reset();
3295
3296 // Next vsync.
3297 viz::BeginFrameArgs args = SendNextBeginFrame();
3298 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
3299 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3300
3301 bool has_damage = false;
3302 EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3303 client_->last_begin_frame_ack());
3304 client_->Reset();
3305
3306 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3307 EXPECT_NO_ACTION();
3308
3309 // Next vsync.
3310 args = SendNextBeginFrame();
3311 EXPECT_ACTIONS("WillBeginImplFrame");
3312 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3313
3314 has_damage = false;
3315 EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3316 client_->last_begin_frame_ack());
3317 client_->Reset();
3318
3319 scheduler_->NotifyReadyToCommit(nullptr);
3320 EXPECT_ACTIONS("ScheduledActionCommit");
3321 client_->Reset();
3322
3323 scheduler_->NotifyReadyToActivate();
3324 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
3325 client_->Reset();
3326
3327 // Next vsync.
3328 args = SendNextBeginFrame();
3329 EXPECT_ACTIONS("WillBeginImplFrame",
3330 "ScheduledActionInvalidateLayerTreeFrameSink");
3331 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3332
3333 // No damage, since not drawn yet.
3334 // TODO(eseckler): In the future, |has_damage = false| will prevent us from
3335 // filtering this ack (in CompositorExternalBeginFrameSource) and instead
3336 // forwarding the one attached to the later submitted CompositorFrame.
3337 has_damage = false;
3338 EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3339 client_->last_begin_frame_ack());
3340 client_->Reset();
3341
3342 // Android onDraw.
3343 scheduler_->SetNeedsRedraw();
3344 bool resourceless_software_draw = false;
3345 bool skip_draw = false;
3346 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3347 skip_draw);
3348 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3349 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3350 client_->Reset();
3351
3352 // Idle on next vsync.
3353 args = SendNextBeginFrame();
3354 EXPECT_ACTIONS("WillBeginImplFrame", "RemoveObserver(this)");
3355 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3356
3357 has_damage = false;
3358 EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3359 client_->last_begin_frame_ack());
3360 client_->Reset();
3361 }
3362
3363 class SchedulerClientSetNeedsPrepareTilesOnDraw : public FakeSchedulerClient {
3364 public:
SchedulerClientSetNeedsPrepareTilesOnDraw()3365 SchedulerClientSetNeedsPrepareTilesOnDraw() : FakeSchedulerClient() {}
3366
3367 protected:
ScheduledActionDrawIfPossible()3368 DrawResult ScheduledActionDrawIfPossible() override {
3369 scheduler_->SetNeedsPrepareTiles();
3370 return FakeSchedulerClient::ScheduledActionDrawIfPossible();
3371 }
3372 };
3373
TEST_F(SchedulerTest,SynchronousCompositorPrepareTilesOnDraw)3374 TEST_F(SchedulerTest, SynchronousCompositorPrepareTilesOnDraw) {
3375 scheduler_settings_.using_synchronous_renderer_compositor = true;
3376
3377 std::unique_ptr<FakeSchedulerClient> client =
3378 base::WrapUnique(new SchedulerClientSetNeedsPrepareTilesOnDraw);
3379 SetUpScheduler(EXTERNAL_BFS, std::move(client));
3380
3381 scheduler_->SetNeedsRedraw();
3382 EXPECT_ACTIONS("AddObserver(this)");
3383 client_->Reset();
3384
3385 // Next vsync.
3386 EXPECT_SCOPED(AdvanceFrame());
3387 EXPECT_ACTIONS("WillBeginImplFrame",
3388 "ScheduledActionInvalidateLayerTreeFrameSink");
3389 client_->Reset();
3390
3391 // Android onDraw.
3392 scheduler_->SetNeedsRedraw();
3393 bool resourceless_software_draw = false;
3394 bool skip_draw = false;
3395 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3396 skip_draw);
3397 EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
3398 "ScheduledActionPrepareTiles");
3399 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3400 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3401 client_->Reset();
3402
3403 // Android onDraw.
3404 scheduler_->SetNeedsRedraw();
3405 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3406 skip_draw);
3407 EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
3408 "ScheduledActionPrepareTiles");
3409 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3410 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3411 client_->Reset();
3412
3413 // Next vsync.
3414 EXPECT_SCOPED(AdvanceFrame());
3415 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3416 EXPECT_ACTIONS("WillBeginImplFrame", "RemoveObserver(this)");
3417 EXPECT_FALSE(scheduler_->begin_frames_expected());
3418 client_->Reset();
3419 }
3420
3421 // Synchronous compositor does not require the active tree to be drawn at least
3422 // once before the next activation. This test verifies two commit-activate
3423 // cycles without draw work correctly.
TEST_F(SchedulerTest,SynchronousCompositorAllowsActivateBeforeDraw)3424 TEST_F(SchedulerTest, SynchronousCompositorAllowsActivateBeforeDraw) {
3425 scheduler_settings_.using_synchronous_renderer_compositor = true;
3426
3427 std::unique_ptr<FakeSchedulerClient> client =
3428 base::WrapUnique(new SchedulerClientSetNeedsPrepareTilesOnDraw);
3429 SetUpScheduler(EXTERNAL_BFS, std::move(client));
3430
3431 scheduler_->SetNeedsRedraw();
3432 EXPECT_ACTIONS("AddObserver(this)");
3433 client_->Reset();
3434
3435 // Next vsync.
3436 scheduler_->SetNeedsBeginMainFrame();
3437 EXPECT_SCOPED(AdvanceFrame());
3438 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
3439 "ScheduledActionInvalidateLayerTreeFrameSink");
3440 client_->Reset();
3441
3442 // Commit and activate.
3443 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3444 scheduler_->NotifyReadyToCommit(nullptr);
3445 EXPECT_ACTIONS("ScheduledActionCommit");
3446 client_->Reset();
3447 scheduler_->NotifyReadyToActivate();
3448 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
3449 client_->Reset();
3450
3451 // No Draw.
3452
3453 // Next vsync.
3454 scheduler_->SetNeedsBeginMainFrame();
3455 EXPECT_SCOPED(AdvanceFrame());
3456 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
3457 "ScheduledActionInvalidateLayerTreeFrameSink");
3458 client_->Reset();
3459
3460 // Commit and activate.
3461 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3462 scheduler_->NotifyReadyToCommit(nullptr);
3463 EXPECT_ACTIONS("ScheduledActionCommit");
3464 client_->Reset();
3465 scheduler_->NotifyReadyToActivate();
3466 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
3467 client_->Reset();
3468 }
3469
TEST_F(SchedulerTest,SetNeedsRedrawFromWillBeginImplFrame)3470 TEST_F(SchedulerTest, SetNeedsRedrawFromWillBeginImplFrame) {
3471 client_ = std::make_unique<FakeSchedulerClient>();
3472 CreateScheduler(EXTERNAL_BFS);
3473
3474 scheduler_->SetVisible(true);
3475 scheduler_->SetCanDraw(true);
3476 client_->SetWillBeginImplFrameCausesRedraw(true);
3477
3478 scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
3479 scheduler_->SetNeedsBeginMainFrame();
3480
3481 AdvanceFrame();
3482 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
3483 "AddObserver(this)", "WillBeginImplFrame",
3484 "ScheduledActionSendBeginMainFrame");
3485 EXPECT_TRUE(scheduler_->RedrawPending());
3486 // WillBeginFrame calls Scheduler::SetNeedsRedraw, which could try to run
3487 // another action. If none of the EXPECT_FALSE(inside_action_)s in
3488 // FakeSchedulerClient fail, we know we didn't re-enter the scheduler.
3489 }
3490
TEST_F(SchedulerTest,SynchronousCompositorSendBeginMainFrameWhileIdle)3491 TEST_F(SchedulerTest, SynchronousCompositorSendBeginMainFrameWhileIdle) {
3492 scheduler_settings_.using_synchronous_renderer_compositor = true;
3493 SetUpScheduler(EXTERNAL_BFS);
3494
3495 scheduler_->SetNeedsRedraw();
3496 EXPECT_ACTIONS("AddObserver(this)");
3497 client_->Reset();
3498
3499 // Next vsync.
3500 EXPECT_SCOPED(AdvanceFrame());
3501 EXPECT_ACTIONS("WillBeginImplFrame",
3502 "ScheduledActionInvalidateLayerTreeFrameSink");
3503 client_->Reset();
3504
3505 // Android onDraw.
3506 scheduler_->SetNeedsRedraw();
3507 bool resourceless_software_draw = false;
3508 bool skip_draw = false;
3509 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3510 skip_draw);
3511 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3512 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3513 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3514 client_->Reset();
3515
3516 // Simulate SetNeedsBeginMainFrame due to input event.
3517 scheduler_->SetNeedsBeginMainFrame();
3518 EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame");
3519 client_->Reset();
3520
3521 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3522 scheduler_->NotifyReadyToCommit(nullptr);
3523 EXPECT_ACTIONS("ScheduledActionCommit");
3524 client_->Reset();
3525
3526 scheduler_->NotifyReadyToActivate();
3527 EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
3528 client_->Reset();
3529
3530 // Next vsync.
3531 EXPECT_SCOPED(AdvanceFrame());
3532 EXPECT_ACTIONS("WillBeginImplFrame",
3533 "ScheduledActionInvalidateLayerTreeFrameSink");
3534 client_->Reset();
3535
3536 // Android onDraw.
3537 scheduler_->SetNeedsRedraw();
3538 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3539 skip_draw);
3540 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3541 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3542 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3543 client_->Reset();
3544
3545 // Simulate SetNeedsBeginMainFrame due to input event.
3546 scheduler_->SetNeedsBeginMainFrame();
3547 EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame");
3548 client_->Reset();
3549 }
3550
TEST_F(SchedulerTest,SynchronousCompositorResourcelessOnDrawWhenInvisible)3551 TEST_F(SchedulerTest, SynchronousCompositorResourcelessOnDrawWhenInvisible) {
3552 scheduler_settings_.using_synchronous_renderer_compositor = true;
3553 SetUpScheduler(EXTERNAL_BFS);
3554
3555 scheduler_->SetVisible(false);
3556
3557 scheduler_->SetNeedsRedraw();
3558 bool resourceless_software_draw = true;
3559 bool skip_draw = false;
3560 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
3561 skip_draw);
3562 // SynchronousCompositor has to draw regardless of visibility.
3563 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3564 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3565 client_->Reset();
3566 }
3567
TEST_F(SchedulerTest,AuthoritativeVSyncInterval)3568 TEST_F(SchedulerTest, AuthoritativeVSyncInterval) {
3569 SetUpScheduler(THROTTLED_BFS);
3570 base::TimeDelta initial_interval = scheduler_->BeginImplFrameInterval();
3571 base::TimeDelta authoritative_interval =
3572 base::TimeDelta::FromMilliseconds(33);
3573
3574 scheduler_->SetNeedsBeginMainFrame();
3575 EXPECT_SCOPED(AdvanceFrame());
3576
3577 EXPECT_EQ(initial_interval, scheduler_->BeginImplFrameInterval());
3578
3579 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3580 scheduler_->NotifyReadyToCommit(nullptr);
3581 scheduler_->NotifyReadyToActivate();
3582 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
3583
3584 // Test changing the interval on the frame source external to the scheduler.
3585 synthetic_frame_source_->OnUpdateVSyncParameters(task_runner_->NowTicks(),
3586 authoritative_interval);
3587
3588 EXPECT_SCOPED(AdvanceFrame());
3589
3590 // At the next BeginFrame, authoritative interval is used instead of previous
3591 // interval.
3592 EXPECT_NE(initial_interval, scheduler_->BeginImplFrameInterval());
3593 EXPECT_EQ(authoritative_interval, scheduler_->BeginImplFrameInterval());
3594 }
3595
TEST_F(SchedulerTest,ImplLatencyTakesPriority)3596 TEST_F(SchedulerTest, ImplLatencyTakesPriority) {
3597 SetUpScheduler(THROTTLED_BFS);
3598
3599 scheduler_->SetTreePrioritiesAndScrollState(
3600 SMOOTHNESS_TAKES_PRIORITY,
3601 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
3602 scheduler_->SetCriticalBeginMainFrameToActivateIsFast(true);
3603 EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
3604 scheduler_->SetCriticalBeginMainFrameToActivateIsFast(false);
3605 EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
3606
3607 scheduler_->SetTreePrioritiesAndScrollState(
3608 SMOOTHNESS_TAKES_PRIORITY,
3609 ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER);
3610 scheduler_->SetCriticalBeginMainFrameToActivateIsFast(true);
3611 EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3612 scheduler_->SetCriticalBeginMainFrameToActivateIsFast(false);
3613 EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
3614
3615 scheduler_->SetTreePrioritiesAndScrollState(
3616 SAME_PRIORITY_FOR_BOTH_TREES,
3617 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
3618 scheduler_->SetCriticalBeginMainFrameToActivateIsFast(true);
3619 EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3620 scheduler_->SetCriticalBeginMainFrameToActivateIsFast(false);
3621 EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3622
3623 scheduler_->SetTreePrioritiesAndScrollState(
3624 SAME_PRIORITY_FOR_BOTH_TREES,
3625 ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER);
3626 scheduler_->SetCriticalBeginMainFrameToActivateIsFast(true);
3627 EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3628 scheduler_->SetCriticalBeginMainFrameToActivateIsFast(false);
3629 EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3630 }
3631
TEST_F(SchedulerTest,NoLayerTreeFrameSinkCreationWhileCommitPending)3632 TEST_F(SchedulerTest, NoLayerTreeFrameSinkCreationWhileCommitPending) {
3633 SetUpScheduler(THROTTLED_BFS);
3634
3635 // SetNeedsBeginMainFrame should begin the frame.
3636 scheduler_->SetNeedsBeginMainFrame();
3637 client_->Reset();
3638 EXPECT_SCOPED(AdvanceFrame());
3639 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
3640
3641 // Lose the LayerTreeFrameSink and trigger the deadline.
3642 client_->Reset();
3643 scheduler_->DidLoseLayerTreeFrameSink();
3644 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3645 EXPECT_NO_ACTION();
3646
3647 // The scheduler should not trigger the LayerTreeFrameSink creation till the
3648 // commit is aborted.
3649 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
3650 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3651 EXPECT_NO_ACTION();
3652
3653 // Abort the commit.
3654 client_->Reset();
3655 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3656 scheduler_->BeginMainFrameAborted(
3657 CommitEarlyOutReason::ABORTED_LAYER_TREE_FRAME_SINK_LOST);
3658 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
3659 }
3660
TEST_F(SchedulerTest,ImplSideInvalidationInsideImplFrame)3661 TEST_F(SchedulerTest, ImplSideInvalidationInsideImplFrame) {
3662 SetUpScheduler(EXTERNAL_BFS);
3663
3664 // Request an impl-side invalidation. Ensure that it runs before the deadline.
3665 bool needs_first_draw_on_activation = true;
3666 scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
3667 client_->Reset();
3668 EXPECT_SCOPED(AdvanceFrame());
3669 EXPECT_ACTIONS("WillBeginImplFrame",
3670 "ScheduledActionPerformImplSideInvalidation");
3671 }
3672
TEST_F(SchedulerTest,ImplSideInvalidationsMergedWithCommit)3673 TEST_F(SchedulerTest, ImplSideInvalidationsMergedWithCommit) {
3674 SetUpScheduler(EXTERNAL_BFS);
3675
3676 // Request a main frame and invalidation, the only action run should be
3677 // sending the main frame.
3678 SetShouldDeferInvalidationForMainFrame(true);
3679 scheduler_->SetNeedsBeginMainFrame();
3680 bool needs_first_draw_on_activation = true;
3681 scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
3682 client_->Reset();
3683 EXPECT_SCOPED(AdvanceFrame());
3684 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
3685
3686 // Respond with a commit. The scheduler should only perform the commit
3687 // actions since the impl-side invalidation request will be merged with the
3688 // commit.
3689 client_->Reset();
3690 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3691 scheduler_->NotifyReadyToCommit(nullptr);
3692 EXPECT_ACTIONS("ScheduledActionCommit");
3693 EXPECT_FALSE(scheduler_->needs_impl_side_invalidation());
3694 }
3695
TEST_F(SchedulerTest,AbortedCommitsTriggerImplSideInvalidations)3696 TEST_F(SchedulerTest, AbortedCommitsTriggerImplSideInvalidations) {
3697 SetUpScheduler(EXTERNAL_BFS);
3698
3699 // Request a main frame and invalidation, with a fast main thread so we wait
3700 // for it to respond.
3701 SetShouldDeferInvalidationForMainFrame(true);
3702 scheduler_->SetNeedsBeginMainFrame();
3703 bool needs_first_draw_on_activation = true;
3704 scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
3705 client_->Reset();
3706 EXPECT_SCOPED(AdvanceFrame());
3707 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
3708
3709 // Abort the main frame and request another one, the impl-side invalidations
3710 // should not be blocked on the main frame.
3711 client_->Reset();
3712 scheduler_->SetNeedsBeginMainFrame();
3713 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
3714 scheduler_->BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
3715 EXPECT_ACTIONS("ScheduledActionPerformImplSideInvalidation");
3716 }
3717
TEST_F(SchedulerTest,InvalidationNotBlockedOnMainFrame)3718 TEST_F(SchedulerTest, InvalidationNotBlockedOnMainFrame) {
3719 SetUpScheduler(EXTERNAL_BFS);
3720
3721 // Request a main frame and invalidation, with a slow main thread so the
3722 // invalidation is not blocked on a commit.
3723 SetShouldDeferInvalidationForMainFrame(false);
3724 scheduler_->SetNeedsBeginMainFrame();
3725 bool needs_first_draw_on_activation = true;
3726 scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
3727 client_->Reset();
3728 EXPECT_SCOPED(AdvanceFrame());
3729 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
3730 "ScheduledActionPerformImplSideInvalidation");
3731 }
3732
3733 // The three letters appeneded to each version of this test mean the following:s
3734 // tree_priority: B = both trees same priority; A = active tree priority;
3735 // scroll_handler_state: H = affects scroll handler; N = does not affect scroll
3736 // handler;
3737 // durations: F = fast durations; S = slow durations
BeginMainFrameOnCriticalPath(TreePriority tree_priority,ScrollHandlerState scroll_handler_state,base::TimeDelta durations)3738 bool SchedulerTest::BeginMainFrameOnCriticalPath(
3739 TreePriority tree_priority,
3740 ScrollHandlerState scroll_handler_state,
3741 base::TimeDelta durations) {
3742 SetUpScheduler(EXTERNAL_BFS);
3743 fake_compositor_timing_history_->SetAllEstimatesTo(durations);
3744 client_->Reset();
3745 scheduler_->SetTreePrioritiesAndScrollState(tree_priority,
3746 scroll_handler_state);
3747 scheduler_->SetNeedsBeginMainFrame();
3748 EXPECT_FALSE(client_->last_begin_main_frame_args().IsValid());
3749 EXPECT_SCOPED(AdvanceFrame());
3750 EXPECT_TRUE(client_->last_begin_main_frame_args().IsValid());
3751 return client_->last_begin_main_frame_args().on_critical_path;
3752 }
3753
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_BNF)3754 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_BNF) {
3755 EXPECT_TRUE(BeginMainFrameOnCriticalPath(
3756 SAME_PRIORITY_FOR_BOTH_TREES,
3757 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
3758 kFastDuration));
3759 }
3760
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_BNS)3761 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_BNS) {
3762 EXPECT_TRUE(BeginMainFrameOnCriticalPath(
3763 SAME_PRIORITY_FOR_BOTH_TREES,
3764 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
3765 kSlowDuration));
3766 }
3767
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_BHF)3768 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_BHF) {
3769 EXPECT_TRUE(BeginMainFrameOnCriticalPath(
3770 SAME_PRIORITY_FOR_BOTH_TREES,
3771 ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER, kFastDuration));
3772 }
3773
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_BHS)3774 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_BHS) {
3775 EXPECT_TRUE(BeginMainFrameOnCriticalPath(
3776 SAME_PRIORITY_FOR_BOTH_TREES,
3777 ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER, kSlowDuration));
3778 }
3779
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_ANF)3780 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_ANF) {
3781 EXPECT_FALSE(BeginMainFrameOnCriticalPath(
3782 SMOOTHNESS_TAKES_PRIORITY,
3783 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
3784 kFastDuration));
3785 }
3786
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_ANS)3787 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_ANS) {
3788 EXPECT_FALSE(BeginMainFrameOnCriticalPath(
3789 SMOOTHNESS_TAKES_PRIORITY,
3790 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
3791 kSlowDuration));
3792 }
3793
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_AHF)3794 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_AHF) {
3795 EXPECT_TRUE(BeginMainFrameOnCriticalPath(
3796 SMOOTHNESS_TAKES_PRIORITY,
3797 ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER, kFastDuration));
3798 }
3799
TEST_F(SchedulerTest,BeginMainFrameOnCriticalPath_AHS)3800 TEST_F(SchedulerTest, BeginMainFrameOnCriticalPath_AHS) {
3801 EXPECT_FALSE(BeginMainFrameOnCriticalPath(
3802 SMOOTHNESS_TAKES_PRIORITY,
3803 ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER, kSlowDuration));
3804 }
3805
TEST_F(SchedulerTest,BeginFrameAckForFinishedImplFrame)3806 TEST_F(SchedulerTest, BeginFrameAckForFinishedImplFrame) {
3807 // Sets up scheduler and sends two BeginFrames, both finished.
3808 SetUpScheduler(EXTERNAL_BFS);
3809
3810 // Run a successful redraw and verify that a new ack is sent.
3811 scheduler_->SetNeedsRedraw();
3812 client_->Reset();
3813
3814 viz::BeginFrameArgs args = SendNextBeginFrame();
3815 EXPECT_ACTIONS("WillBeginImplFrame");
3816 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3817 EXPECT_TRUE(scheduler_->begin_frames_expected());
3818 client_->Reset();
3819
3820 task_runner_->RunPendingTasks(); // Run posted deadline.
3821 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3822 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3823 EXPECT_TRUE(scheduler_->begin_frames_expected());
3824
3825 // Successful draw caused damage.
3826 bool has_damage = true;
3827 EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3828 client_->last_begin_frame_ack());
3829 client_->Reset();
3830
3831 // Request another redraw, but fail it. Verify that a new ack is sent.
3832 scheduler_->SetNeedsRedraw();
3833 client_->Reset();
3834
3835 args = SendNextBeginFrame();
3836 EXPECT_ACTIONS("WillBeginImplFrame");
3837 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3838 EXPECT_TRUE(scheduler_->begin_frames_expected());
3839 client_->Reset();
3840
3841 client_->SetDrawWillHappen(false);
3842 task_runner_->RunPendingTasks(); // Run posted deadline.
3843 EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
3844 // Failed draw triggers SendBeginMainFrame.
3845 "ScheduledActionSendBeginMainFrame");
3846 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3847 EXPECT_TRUE(scheduler_->begin_frames_expected());
3848
3849 // Failed draw: no damage.
3850 has_damage = false;
3851 EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3852 client_->last_begin_frame_ack());
3853 client_->Reset();
3854 }
3855
TEST_F(SchedulerTest,BeginFrameAckForSkippedImplFrame)3856 TEST_F(SchedulerTest, BeginFrameAckForSkippedImplFrame) {
3857 SetUpScheduler(EXTERNAL_BFS);
3858
3859 // To get into a high latency state, this test disables automatic swap acks.
3860 client_->SetAutomaticSubmitCompositorFrameAck(false);
3861 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
3862
3863 // Run a successful redraw that submits a compositor frame but doesn't receive
3864 // a swap ack. Verify that a viz::BeginFrameAck is sent for it.
3865 scheduler_->SetNeedsRedraw();
3866 client_->Reset();
3867
3868 viz::BeginFrameArgs args = SendNextBeginFrame();
3869 EXPECT_ACTIONS("WillBeginImplFrame");
3870 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3871 EXPECT_TRUE(scheduler_->begin_frames_expected());
3872 client_->Reset();
3873
3874 task_runner_->RunPendingTasks(); // Run posted deadline.
3875 EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
3876 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3877 EXPECT_TRUE(scheduler_->begin_frames_expected());
3878
3879 // Successful draw caused damage.
3880 bool has_damage = true;
3881 EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3882 client_->last_begin_frame_ack());
3883 client_->Reset();
3884
3885 // Request another redraw that will be skipped because the swap ack is still
3886 // missing. Verify that a new viz::BeginFrameAck is sent.
3887 scheduler_->SetNeedsRedraw();
3888 client_->Reset();
3889
3890 args = SendNextBeginFrame();
3891 EXPECT_NO_ACTION();
3892 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3893 EXPECT_TRUE(scheduler_->begin_frames_expected());
3894
3895 // Skipped draw: no damage.
3896 has_damage = false;
3897 EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3898 client_->last_begin_frame_ack());
3899 client_->Reset();
3900 }
3901
TEST_F(SchedulerTest,BeginFrameAckForBeginFrameBeforeLastDeadline)3902 TEST_F(SchedulerTest, BeginFrameAckForBeginFrameBeforeLastDeadline) {
3903 SetUpScheduler(EXTERNAL_BFS);
3904
3905 // Request tile preparation to schedule a proactive BeginFrame.
3906 scheduler_->SetNeedsPrepareTiles();
3907 client_->Reset();
3908
3909 SendNextBeginFrame();
3910 EXPECT_ACTIONS("WillBeginImplFrame");
3911 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3912 // Until tiles were prepared, further proactive BeginFrames are expected.
3913 EXPECT_TRUE(scheduler_->begin_frames_expected());
3914 client_->Reset();
3915
3916 // Send the next BeginFrame before the previous one's deadline was executed.
3917 // This should post the previous BeginFrame's deadline, during which tiles
3918 // will be prepared. As a result of that, no further BeginFrames will be
3919 // needed, and the new BeginFrame should be dropped.
3920 viz::BeginFrameArgs args = SendNextBeginFrame();
3921 task_runner_->RunPendingTasks(); // Run posted deadline.
3922 EXPECT_ACTIONS("ScheduledActionPrepareTiles", "RemoveObserver(this)");
3923 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3924 EXPECT_FALSE(scheduler_->begin_frames_expected());
3925
3926 // Latest ack should be for the dropped BeginFrame.
3927 bool has_damage = false;
3928 EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3929 client_->last_begin_frame_ack());
3930 client_->Reset();
3931 }
3932
TEST_F(SchedulerTest,BeginFrameAckForDroppedBeginFrame)3933 TEST_F(SchedulerTest, BeginFrameAckForDroppedBeginFrame) {
3934 SetUpScheduler(EXTERNAL_BFS);
3935
3936 // Request a single BeginFrame.
3937 scheduler_->SetNeedsOneBeginImplFrame();
3938 EXPECT_TRUE(scheduler_->begin_frames_expected());
3939 client_->Reset();
3940
3941 // First BeginFrame is handled by StateMachine.
3942 viz::BeginFrameArgs first_args = SendNextBeginFrame();
3943 EXPECT_ACTIONS("WillBeginImplFrame");
3944 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
3945 // State machine is no longer interested in BeginFrames, but scheduler is
3946 // still observing the source.
3947 EXPECT_TRUE(scheduler_->begin_frames_expected());
3948 EXPECT_FALSE(scheduler_->BeginFrameNeeded());
3949 client_->Reset();
3950
3951 // Send the next BeginFrame before the previous one's deadline was executed.
3952 // The BeginFrame should be dropped immediately, since the state machine is
3953 // not expecting any BeginFrames.
3954 viz::BeginFrameArgs second_args = SendNextBeginFrame();
3955 EXPECT_NO_ACTION();
3956
3957 // Latest ack should be for the dropped BeginFrame.
3958 bool has_damage = false;
3959 EXPECT_EQ(viz::BeginFrameAck(second_args, has_damage),
3960 client_->last_begin_frame_ack());
3961 client_->Reset();
3962
3963 task_runner_->RunPendingTasks(); // Run deadline of prior BeginFrame.
3964 EXPECT_ACTIONS("RemoveObserver(this)");
3965
3966 // We'd expect an out-of-order ack for the prior BeginFrame.
3967 has_damage = false;
3968 EXPECT_EQ(viz::BeginFrameAck(first_args, has_damage),
3969 client_->last_begin_frame_ack());
3970 client_->Reset();
3971 }
3972
TEST_F(SchedulerTest,BeginFrameAckForLateMissedBeginFrame)3973 TEST_F(SchedulerTest, BeginFrameAckForLateMissedBeginFrame) {
3974 SetUpScheduler(EXTERNAL_BFS);
3975
3976 scheduler_->SetNeedsRedraw();
3977 client_->Reset();
3978
3979 // Send a missed BeginFrame with a passed deadline.
3980 task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
3981 viz::BeginFrameArgs args =
3982 fake_external_begin_frame_source_->CreateBeginFrameArgs(
3983 BEGINFRAME_FROM_HERE, task_runner_->GetMockTickClock());
3984 args.type = viz::BeginFrameArgs::MISSED;
3985 task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
3986 EXPECT_GT(task_runner_->NowTicks(), args.deadline);
3987 fake_external_begin_frame_source_->TestOnBeginFrame(args);
3988 task_runner_->RunPendingTasks();
3989
3990 EXPECT_NO_ACTION();
3991 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
3992
3993 // Latest ack should be for the missed BeginFrame that was too late: no
3994 // damage.
3995 bool has_damage = false;
3996 EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
3997 client_->last_begin_frame_ack());
3998 client_->Reset();
3999 }
4000
TEST_F(SchedulerTest,CriticalBeginMainFrameToActivateIsFast)4001 TEST_F(SchedulerTest, CriticalBeginMainFrameToActivateIsFast) {
4002 SetUpScheduler(EXTERNAL_BFS);
4003
4004 scheduler_->SetNeedsRedraw();
4005 base::TimeDelta estimate_duration = base::TimeDelta::FromMilliseconds(1);
4006 fake_compositor_timing_history_->SetAllEstimatesTo(estimate_duration);
4007
4008 // If we have a scroll handler but the critical main frame is slow, we should
4009 // still prioritize impl thread latency.
4010 scheduler_->SetTreePrioritiesAndScrollState(
4011 SMOOTHNESS_TAKES_PRIORITY,
4012 ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER);
4013 scheduler_->SetNeedsRedraw();
4014 // An interval of 2ms makes sure that the main frame is considered slow.
4015 base::TimeDelta interval = base::TimeDelta::FromMilliseconds(2);
4016 task_runner_->AdvanceMockTickClock(interval);
4017 viz::BeginFrameArgs args = viz::BeginFrameArgs::Create(
4018 BEGINFRAME_FROM_HERE, 0u, 1u, task_runner_->NowTicks(),
4019 task_runner_->NowTicks() + interval, interval,
4020 viz::BeginFrameArgs::NORMAL);
4021 fake_external_begin_frame_source_->TestOnBeginFrame(args);
4022 EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
4023
4024 task_runner_->RunPendingTasks(); // Run posted deadline to finish the frame.
4025 ASSERT_FALSE(client_->IsInsideBeginImplFrame());
4026
4027 // Set an interval of 10ms. The bmf_to_activate_interval should be 1*4 = 4ms,
4028 // to account for queue + main_frame + pending_tree + activation durations.
4029 // With a draw time of 1ms and fudge factor of 1ms, the interval available for
4030 // the main frame to be activated is 8ms, so it should be considered fast.
4031 scheduler_->SetNeedsRedraw();
4032 interval = base::TimeDelta::FromMilliseconds(10);
4033 task_runner_->AdvanceMockTickClock(interval);
4034 args = viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, 0u, 2u,
4035 task_runner_->NowTicks(),
4036 task_runner_->NowTicks() + interval,
4037 interval, viz::BeginFrameArgs::NORMAL);
4038 fake_external_begin_frame_source_->TestOnBeginFrame(args);
4039 EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
4040
4041 task_runner_->RunPendingTasks(); // Run posted deadline to finish the frame.
4042 ASSERT_FALSE(client_->IsInsideBeginImplFrame());
4043
4044 // Increase the draw duration to decrease the time available for the main
4045 // frame. This should prioritize the impl thread.
4046 scheduler_->SetNeedsRedraw();
4047 fake_compositor_timing_history_->SetDrawDurationEstimate(
4048 base::TimeDelta::FromMilliseconds(7));
4049 task_runner_->AdvanceMockTickClock(interval);
4050 args = viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, 0u, 3u,
4051 task_runner_->NowTicks(),
4052 task_runner_->NowTicks() + interval,
4053 interval, viz::BeginFrameArgs::NORMAL);
4054 fake_external_begin_frame_source_->TestOnBeginFrame(args);
4055 EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
4056 }
4057
TEST_F(SchedulerTest,WaitForAllPipelineStagesUsesMissedBeginFrames)4058 TEST_F(SchedulerTest, WaitForAllPipelineStagesUsesMissedBeginFrames) {
4059 scheduler_settings_.wait_for_all_pipeline_stages_before_draw = true;
4060 client_ = std::make_unique<FakeSchedulerClient>();
4061 CreateScheduler(EXTERNAL_BFS);
4062
4063 // Initialize frame sink so that Scheduler and state machine need BeginFrames.
4064 scheduler_->SetVisible(true);
4065 scheduler_->SetCanDraw(true);
4066 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
4067 client_->Reset();
4068 scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
4069 scheduler_->SetNeedsBeginMainFrame();
4070 EXPECT_TRUE(scheduler_->begin_frames_expected());
4071 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
4072 client_->Reset();
4073
4074 // Uses MISSED BeginFrames even after the deadline has passed.
4075 base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
4076 task_runner_->AdvanceMockTickClock(interval);
4077 base::TimeTicks timestamp = task_runner_->NowTicks();
4078 // Deadline should have passed after this.
4079 task_runner_->AdvanceMockTickClock(interval * 2);
4080 viz::BeginFrameArgs args = viz::BeginFrameArgs::Create(
4081 BEGINFRAME_FROM_HERE, 0u, 1u, timestamp, timestamp + interval, interval,
4082 viz::BeginFrameArgs::MISSED);
4083 fake_external_begin_frame_source_->TestOnBeginFrame(args);
4084 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
4085 }
4086
TEST_F(SchedulerTest,WaitForAllPipelineStagesAlwaysObservesBeginFrames)4087 TEST_F(SchedulerTest, WaitForAllPipelineStagesAlwaysObservesBeginFrames) {
4088 scheduler_settings_.wait_for_all_pipeline_stages_before_draw = true;
4089 client_ = std::make_unique<FakeSchedulerClient>();
4090 CreateScheduler(EXTERNAL_BFS);
4091
4092 // Initialize frame sink, request a main frame but defer commits, so that
4093 // state machine is idle.
4094 scheduler_->SetVisible(true);
4095 scheduler_->SetCanDraw(true);
4096 EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
4097 client_->Reset();
4098 scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
4099 scheduler_->SetDeferBeginMainFrame(true);
4100 scheduler_->SetNeedsBeginMainFrame();
4101 EXPECT_TRUE(scheduler_->begin_frames_expected());
4102 EXPECT_FALSE(client_->IsInsideBeginImplFrame());
4103 client_->Reset();
4104
4105 // In full-pipe mode, the SchedulerStateMachine always wants BeginFrames, even
4106 // if it is otherwise idle.
4107 EXPECT_TRUE(scheduler_->begin_frames_expected());
4108 EXPECT_TRUE(scheduler_->BeginFrameNeeded());
4109
4110 // Scheduler begins a frame even if otherwise idle.
4111 base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
4112 task_runner_->AdvanceMockTickClock(interval);
4113 base::TimeTicks timestamp = task_runner_->NowTicks();
4114 viz::BeginFrameArgs args = viz::BeginFrameArgs::Create(
4115 BEGINFRAME_FROM_HERE, 0u, 1u, timestamp, timestamp + interval, interval,
4116 viz::BeginFrameArgs::NORMAL);
4117 fake_external_begin_frame_source_->TestOnBeginFrame(args);
4118 EXPECT_ACTIONS("WillBeginImplFrame");
4119 EXPECT_TRUE(client_->IsInsideBeginImplFrame());
4120 client_->Reset();
4121
4122 // BeginFrame deadline is not blocked because commits are deferred.
4123 task_runner_->RunPendingTasks();
4124 EXPECT_ACTIONS();
4125 EXPECT_TRUE(!client_->IsInsideBeginImplFrame());
4126 client_->Reset();
4127 }
4128
TEST_F(SchedulerTest,CriticalBeginMainFrameIsFast_CommitEstimateSlow)4129 TEST_F(SchedulerTest, CriticalBeginMainFrameIsFast_CommitEstimateSlow) {
4130 SetUpScheduler(EXTERNAL_BFS);
4131 scheduler_->SetNeedsBeginMainFrame();
4132 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4133 fake_compositor_timing_history_->SetCommitDurationEstimate(kSlowDuration);
4134 EXPECT_SCOPED(AdvanceFrame());
4135 EXPECT_FALSE(scheduler_->state_machine()
4136 .critical_begin_main_frame_to_activate_is_fast());
4137 }
4138
TEST_F(SchedulerTest,CriticalBeginMainFrameIsFast_CommitEstimateFast)4139 TEST_F(SchedulerTest, CriticalBeginMainFrameIsFast_CommitEstimateFast) {
4140 SetUpScheduler(EXTERNAL_BFS);
4141 scheduler_->SetNeedsBeginMainFrame();
4142 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4143 EXPECT_SCOPED(AdvanceFrame());
4144 EXPECT_TRUE(scheduler_->state_machine()
4145 .critical_begin_main_frame_to_activate_is_fast());
4146 }
4147
TEST_F(SchedulerTest,ShouldDeferInvalidation_AllEstimatesFast)4148 TEST_F(SchedulerTest, ShouldDeferInvalidation_AllEstimatesFast) {
4149 SetUpScheduler(EXTERNAL_BFS);
4150 scheduler_->SetNeedsBeginMainFrame();
4151 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4152 EXPECT_SCOPED(AdvanceFrame());
4153 EXPECT_TRUE(scheduler_->state_machine()
4154 .should_defer_invalidation_for_fast_main_frame());
4155 }
4156
TEST_F(SchedulerTest,ShouldDeferInvalidation_BMFStartToReadyToCommitSlow)4157 TEST_F(SchedulerTest, ShouldDeferInvalidation_BMFStartToReadyToCommitSlow) {
4158 SetUpScheduler(EXTERNAL_BFS);
4159 scheduler_->SetNeedsBeginMainFrame();
4160 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4161 fake_compositor_timing_history_
4162 ->SetBeginMainFrameStartToReadyToCommitDurationEstimate(kSlowDuration);
4163 EXPECT_SCOPED(AdvanceFrame());
4164 EXPECT_FALSE(scheduler_->state_machine()
4165 .should_defer_invalidation_for_fast_main_frame());
4166 }
4167
TEST_F(SchedulerTest,ShouldDeferInvalidation_BMFQueueDurationCriticalSlow)4168 TEST_F(SchedulerTest, ShouldDeferInvalidation_BMFQueueDurationCriticalSlow) {
4169 SetUpScheduler(EXTERNAL_BFS);
4170 scheduler_->SetNeedsBeginMainFrame();
4171 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4172 fake_compositor_timing_history_
4173 ->SetBeginMainFrameQueueDurationCriticalEstimate(kSlowDuration);
4174 EXPECT_SCOPED(AdvanceFrame());
4175 EXPECT_FALSE(scheduler_->state_machine()
4176 .should_defer_invalidation_for_fast_main_frame());
4177 }
4178
TEST_F(SchedulerTest,ShouldDeferInvalidation_BMFQueueDurationNotCriticalSlow)4179 TEST_F(SchedulerTest, ShouldDeferInvalidation_BMFQueueDurationNotCriticalSlow) {
4180 SetUpScheduler(EXTERNAL_BFS);
4181 scheduler_->SetNeedsBeginMainFrame();
4182 scheduler_->SetTreePrioritiesAndScrollState(
4183 TreePriority::SMOOTHNESS_TAKES_PRIORITY,
4184 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
4185 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4186 fake_compositor_timing_history_
4187 ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
4188 EXPECT_SCOPED(AdvanceFrame());
4189 EXPECT_FALSE(scheduler_->state_machine()
4190 .should_defer_invalidation_for_fast_main_frame());
4191 }
4192
TEST_F(SchedulerTest,SlowMainThreadButEstimatedFastTriggersInvalidations)4193 TEST_F(SchedulerTest, SlowMainThreadButEstimatedFastTriggersInvalidations) {
4194 SetUpScheduler(EXTERNAL_BFS);
4195 scheduler_->SetNeedsBeginMainFrame();
4196 scheduler_->SetNeedsImplSideInvalidation(true);
4197 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4198
4199 // Main thread is estimated fast, invalidation will be deferred.
4200 client_->Reset();
4201 EXPECT_SCOPED(AdvanceFrame());
4202 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
4203
4204 // Draw deadline.
4205 client_->Reset();
4206 task_runner_->RunPendingTasks();
4207 EXPECT_ACTIONS();
4208
4209 // Next frame. The invalidation should not be throttled.
4210 client_->Reset();
4211 EXPECT_SCOPED(AdvanceFrame());
4212 EXPECT_ACTIONS("WillBeginImplFrame",
4213 "ScheduledActionPerformImplSideInvalidation");
4214 }
4215
TEST_F(SchedulerTest,SlowMainThreadRasterButEstimatedFastDoesNotTriggersInvalidations)4216 TEST_F(SchedulerTest,
4217 SlowMainThreadRasterButEstimatedFastDoesNotTriggersInvalidations) {
4218 SetUpScheduler(EXTERNAL_BFS);
4219 scheduler_->SetNeedsBeginMainFrame();
4220 scheduler_->SetNeedsImplSideInvalidation(true);
4221 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4222
4223 // Main thread is estimated fast, invalidation will be deferred.
4224 client_->Reset();
4225 EXPECT_SCOPED(AdvanceFrame());
4226 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
4227
4228 // Commit before deadline but not ready to activate.
4229 client_->Reset();
4230 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
4231 scheduler_->NotifyReadyToCommit(nullptr);
4232 EXPECT_ACTIONS("ScheduledActionCommit");
4233
4234 // Draw deadline.
4235 client_->Reset();
4236 task_runner_->RunPendingTasks();
4237 EXPECT_ACTIONS();
4238
4239 // Next frame. The invalidation should still be throttled.
4240 client_->Reset();
4241 EXPECT_SCOPED(AdvanceFrame());
4242 EXPECT_ACTIONS("WillBeginImplFrame");
4243 }
4244
TEST_F(SchedulerTest,SynchronousCompositorImplSideInvalidation)4245 TEST_F(SchedulerTest, SynchronousCompositorImplSideInvalidation) {
4246 // Synchronous compositor doesn't have a deadline and our heuristics can't
4247 // work. We should never be prioritizing impl-side invalidations over main
4248 // frames.
4249 scheduler_settings_.using_synchronous_renderer_compositor = true;
4250 SetUpScheduler(EXTERNAL_BFS);
4251
4252 fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
4253 scheduler_->SetNeedsBeginMainFrame();
4254 const bool needs_first_draw_on_activation = true;
4255 scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
4256 client_->Reset();
4257 EXPECT_SCOPED(AdvanceFrame());
4258 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
4259 }
4260
TEST_F(SchedulerTest,DontSkipMainFrameAfterClearingHistory)4261 TEST_F(SchedulerTest, DontSkipMainFrameAfterClearingHistory) {
4262 // Set up a fast estimate for the main frame and make it miss the deadline.
4263 scheduler_settings_.main_frame_before_activation_enabled = true;
4264 SetUpScheduler(EXTERNAL_BFS);
4265 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4266 client_->Reset();
4267 scheduler_->SetNeedsBeginMainFrame();
4268 EXPECT_SCOPED(AdvanceFrame());
4269 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
4270 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
4271 "ScheduledActionSendBeginMainFrame");
4272
4273 // Now commit during the second frame, since the main thread missed the last
4274 // deadline but we have a fast estimate, we would want to skip the next main
4275 // frame.
4276 client_->Reset();
4277 EXPECT_SCOPED(AdvanceFrame());
4278 scheduler_->SetNeedsBeginMainFrame();
4279 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
4280 scheduler_->NotifyReadyToCommit(nullptr);
4281 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionCommit");
4282
4283 // But during the commit, the history is cleared. So the main frame should not
4284 // be skipped.
4285 client_->Reset();
4286 scheduler_->ClearHistory();
4287 EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame");
4288 }
4289
TEST_F(SchedulerTest,NoInvalidationForAnimateOnlyFrames)4290 TEST_F(SchedulerTest, NoInvalidationForAnimateOnlyFrames) {
4291 SetUpScheduler(EXTERNAL_BFS);
4292 fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
4293 client_->Reset();
4294 scheduler_->SetNeedsImplSideInvalidation(true);
4295
4296 bool animate_only = true;
4297 EXPECT_SCOPED(AdvanceFrame(animate_only));
4298 EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame");
4299 client_->Reset();
4300 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
4301 EXPECT_ACTIONS();
4302
4303 // Now send a frame which requires full updates.
4304 animate_only = false;
4305 EXPECT_SCOPED(AdvanceFrame(animate_only));
4306 EXPECT_ACTIONS("WillBeginImplFrame",
4307 "ScheduledActionPerformImplSideInvalidation");
4308 client_->Reset();
4309 task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
4310 EXPECT_ACTIONS();
4311 }
4312
TEST_F(SchedulerTest,SendEarlyDidNotProduceFrameIfIdle)4313 TEST_F(SchedulerTest, SendEarlyDidNotProduceFrameIfIdle) {
4314 SetUpScheduler(EXTERNAL_BFS);
4315 scheduler_->SetNeedsBeginMainFrame();
4316
4317 client_->Reset();
4318 EXPECT_SCOPED(AdvanceFrame());
4319 EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
4320 auto begin_main_frame_args = client_->last_begin_main_frame_args();
4321 EXPECT_NE(client_->last_begin_frame_ack().frame_id.sequence_number,
4322 begin_main_frame_args.frame_id.sequence_number);
4323
4324 client_->Reset();
4325 scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
4326 // Request a new commit before finishing the current one to simulate behavior
4327 // seen in certain OOPIF renderers.
4328 scheduler_->SetNeedsBeginMainFrame();
4329 scheduler_->BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
4330 EXPECT_EQ(client_->last_begin_frame_ack().frame_id.sequence_number,
4331 begin_main_frame_args.frame_id.sequence_number);
4332 }
4333
4334 } // namespace
4335 } // namespace cc
4336