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 #include "cc/scheduler/scheduler.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/time/time.h"
14 #include "cc/test/begin_frame_args_test.h"
15 #include "cc/test/ordered_simple_task_runner.h"
16 #include "cc/test/scheduler_test_common.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
22 EXPECT_EQ(expected_num_actions, client.num_actions_()); \
23 if (action_index >= 0) { \
24 ASSERT_LT(action_index, client.num_actions_()) << scheduler; \
25 EXPECT_STREQ(action, client.Action(action_index)); \
27 for (int i = expected_num_actions; i < client.num_actions_(); ++i) \
28 ADD_FAILURE() << "Unexpected action: " << client.Action(i) \
29 << " with state:\n" << client.StateForAction(i); \
32 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
34 #define EXPECT_SINGLE_ACTION(action, client) \
35 EXPECT_ACTION(action, client, 0, 1)
40 class FakeSchedulerClient
;
42 void InitializeOutputSurfaceAndFirstCommit(Scheduler
* scheduler
,
43 FakeSchedulerClient
* client
);
45 class TestScheduler
: public Scheduler
{
47 static scoped_ptr
<TestScheduler
> Create(
48 SchedulerClient
* client
,
49 const SchedulerSettings
& scheduler_settings
,
50 int layer_tree_host_id
,
51 const scoped_refptr
<base::SingleThreadTaskRunner
>& impl_task_runner
) {
52 return make_scoped_ptr(new TestScheduler(
53 client
, scheduler_settings
, layer_tree_host_id
, impl_task_runner
));
56 virtual ~TestScheduler() {}
58 bool IsBeginRetroFrameArgsEmpty() const {
59 return begin_retro_frame_args_
.empty();
62 bool IsSyntheticBeginFrameSourceActive() const {
63 return synthetic_begin_frame_source_
->IsActive();
68 SchedulerClient
* client
,
69 const SchedulerSettings
& scheduler_settings
,
70 int layer_tree_host_id
,
71 const scoped_refptr
<base::SingleThreadTaskRunner
> & impl_task_runner
)
79 class FakeSchedulerClient
: public SchedulerClient
{
82 : needs_begin_frame_(false),
83 automatic_swap_ack_(true),
84 swap_contains_incomplete_tile_(false),
85 redraw_will_happen_if_update_visible_tiles_happens_(false) {
92 draw_will_happen_
= true;
93 swap_will_happen_if_draw_happens_
= true;
95 log_anticipated_draw_time_change_
= false;
98 TestScheduler
* CreateScheduler(const SchedulerSettings
& settings
) {
99 task_runner_
= new OrderedSimpleTaskRunner
;
100 scheduler_
= TestScheduler::Create(this, settings
, 0, task_runner_
);
101 return scheduler_
.get();
104 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
105 // for tests that do.
106 void set_log_anticipated_draw_time_change(bool log
) {
107 log_anticipated_draw_time_change_
= log
;
109 bool needs_begin_frame() { return needs_begin_frame_
; }
110 int num_draws() const { return num_draws_
; }
111 int num_actions_() const { return static_cast<int>(actions_
.size()); }
112 const char* Action(int i
) const { return actions_
[i
]; }
113 base::Value
& StateForAction(int i
) const { return *states_
[i
]; }
114 base::TimeTicks
posted_begin_impl_frame_deadline() const {
115 return posted_begin_impl_frame_deadline_
;
118 OrderedSimpleTaskRunner
& task_runner() { return *task_runner_
; }
120 int ActionIndex(const char* action
) const {
121 for (size_t i
= 0; i
< actions_
.size(); i
++)
122 if (!strcmp(actions_
[i
], action
))
127 void SetSwapContainsIncompleteTile(bool contain
) {
128 swap_contains_incomplete_tile_
= contain
;
131 bool HasAction(const char* action
) const {
132 return ActionIndex(action
) >= 0;
135 void SetDrawWillHappen(bool draw_will_happen
) {
136 draw_will_happen_
= draw_will_happen
;
138 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens
) {
139 swap_will_happen_if_draw_happens_
= swap_will_happen_if_draw_happens
;
141 void SetAutomaticSwapAck(bool automatic_swap_ack
) {
142 automatic_swap_ack_
= automatic_swap_ack
;
144 void SetRedrawWillHappenIfUpdateVisibleTilesHappens(bool redraw
) {
145 redraw_will_happen_if_update_visible_tiles_happens_
= redraw
;
147 // SchedulerClient implementation.
148 virtual void SetNeedsBeginFrame(bool enable
) OVERRIDE
{
149 actions_
.push_back("SetNeedsBeginFrame");
150 states_
.push_back(scheduler_
->AsValue().release());
151 needs_begin_frame_
= enable
;
153 virtual void WillBeginImplFrame(const BeginFrameArgs
& args
) OVERRIDE
{
154 actions_
.push_back("WillBeginImplFrame");
155 states_
.push_back(scheduler_
->AsValue().release());
157 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE
{
158 actions_
.push_back("ScheduledActionSendBeginMainFrame");
159 states_
.push_back(scheduler_
->AsValue().release());
161 virtual void ScheduledActionAnimate() OVERRIDE
{
162 actions_
.push_back("ScheduledActionAnimate");
163 states_
.push_back(scheduler_
->AsValue().release());
165 virtual DrawResult
ScheduledActionDrawAndSwapIfPossible() OVERRIDE
{
166 actions_
.push_back("ScheduledActionDrawAndSwapIfPossible");
167 states_
.push_back(scheduler_
->AsValue().release());
170 draw_will_happen_
? DRAW_SUCCESS
: DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
;
171 bool swap_will_happen
=
172 draw_will_happen_
&& swap_will_happen_if_draw_happens_
;
173 if (swap_will_happen
) {
174 scheduler_
->DidSwapBuffers();
175 if (swap_contains_incomplete_tile_
) {
176 scheduler_
->SetSwapUsedIncompleteTile(true);
177 swap_contains_incomplete_tile_
= false;
179 scheduler_
->SetSwapUsedIncompleteTile(false);
182 if (automatic_swap_ack_
)
183 scheduler_
->DidSwapBuffersComplete();
187 virtual DrawResult
ScheduledActionDrawAndSwapForced() OVERRIDE
{
188 actions_
.push_back("ScheduledActionDrawAndSwapForced");
189 states_
.push_back(scheduler_
->AsValue().release());
192 virtual void ScheduledActionCommit() OVERRIDE
{
193 actions_
.push_back("ScheduledActionCommit");
194 states_
.push_back(scheduler_
->AsValue().release());
196 virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE
{
197 actions_
.push_back("ScheduledActionUpdateVisibleTiles");
198 states_
.push_back(scheduler_
->AsValue().release());
199 if (redraw_will_happen_if_update_visible_tiles_happens_
)
200 scheduler_
->SetNeedsRedraw();
202 virtual void ScheduledActionActivateSyncTree() OVERRIDE
{
203 actions_
.push_back("ScheduledActionActivateSyncTree");
204 states_
.push_back(scheduler_
->AsValue().release());
206 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE
{
207 actions_
.push_back("ScheduledActionBeginOutputSurfaceCreation");
208 states_
.push_back(scheduler_
->AsValue().release());
210 virtual void ScheduledActionManageTiles() OVERRIDE
{
211 actions_
.push_back("ScheduledActionManageTiles");
212 states_
.push_back(scheduler_
->AsValue().release());
214 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks
) OVERRIDE
{
215 if (log_anticipated_draw_time_change_
)
216 actions_
.push_back("DidAnticipatedDrawTimeChange");
218 virtual base::TimeDelta
DrawDurationEstimate() OVERRIDE
{
219 return base::TimeDelta();
221 virtual base::TimeDelta
BeginMainFrameToCommitDurationEstimate() OVERRIDE
{
222 return base::TimeDelta();
224 virtual base::TimeDelta
CommitToActivateDurationEstimate() OVERRIDE
{
225 return base::TimeDelta();
228 virtual void DidBeginImplFrameDeadline() OVERRIDE
{}
231 bool needs_begin_frame_
;
232 bool draw_will_happen_
;
233 bool swap_will_happen_if_draw_happens_
;
234 bool automatic_swap_ack_
;
236 bool log_anticipated_draw_time_change_
;
237 bool swap_contains_incomplete_tile_
;
238 bool redraw_will_happen_if_update_visible_tiles_happens_
;
239 base::TimeTicks posted_begin_impl_frame_deadline_
;
240 std::vector
<const char*> actions_
;
241 ScopedVector
<base::Value
> states_
;
242 scoped_ptr
<TestScheduler
> scheduler_
;
243 scoped_refptr
<OrderedSimpleTaskRunner
> task_runner_
;
246 void InitializeOutputSurfaceAndFirstCommit(Scheduler
* scheduler
,
247 FakeSchedulerClient
* client
) {
248 bool client_initiates_begin_frame
=
249 scheduler
->settings().begin_frame_scheduling_enabled
&&
250 scheduler
->settings().throttle_frame_production
;
252 scheduler
->DidCreateAndInitializeOutputSurface();
253 scheduler
->SetNeedsCommit();
254 scheduler
->NotifyBeginMainFrameStarted();
255 scheduler
->NotifyReadyToCommit();
256 if (scheduler
->settings().impl_side_painting
)
257 scheduler
->NotifyReadyToActivate();
258 // Go through the motions to draw the commit.
259 if (client_initiates_begin_frame
)
260 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
262 client
->task_runner().RunPendingTasks(); // Run posted BeginFrame.
264 // Run the posted deadline task.
265 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
266 client
->task_runner().RunPendingTasks();
267 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
269 // We need another BeginImplFrame so Scheduler calls
270 // SetNeedsBeginFrame(false).
271 if (client_initiates_begin_frame
)
272 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
274 client
->task_runner().RunPendingTasks(); // Run posted BeginFrame.
276 // Run the posted deadline task.
277 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
278 client
->task_runner().RunPendingTasks();
279 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
282 TEST(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
283 FakeSchedulerClient client
;
284 SchedulerSettings default_scheduler_settings
;
285 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
286 scheduler
->SetCanStart();
287 scheduler
->SetVisible(true);
288 scheduler
->SetCanDraw(true);
290 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
292 scheduler
->DidCreateAndInitializeOutputSurface();
293 EXPECT_NO_ACTION(client
);
296 TEST(SchedulerTest
, RequestCommit
) {
297 FakeSchedulerClient client
;
298 SchedulerSettings scheduler_settings
;
299 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
300 scheduler
->SetCanStart();
301 scheduler
->SetVisible(true);
302 scheduler
->SetCanDraw(true);
304 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
305 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
307 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
309 scheduler
->SetNeedsCommit();
310 EXPECT_TRUE(client
.needs_begin_frame());
311 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
314 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
315 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
316 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
317 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
318 EXPECT_TRUE(client
.needs_begin_frame());
321 // If we don't swap on the deadline, we wait for the next BeginFrame.
322 client
.task_runner().RunPendingTasks(); // Run posted deadline.
323 EXPECT_NO_ACTION(client
);
324 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
325 EXPECT_TRUE(client
.needs_begin_frame());
328 // NotifyReadyToCommit should trigger the commit.
329 scheduler
->NotifyBeginMainFrameStarted();
330 scheduler
->NotifyReadyToCommit();
331 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
332 EXPECT_TRUE(client
.needs_begin_frame());
335 // BeginImplFrame should prepare the draw.
336 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
337 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
338 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
339 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
340 EXPECT_TRUE(client
.needs_begin_frame());
343 // BeginImplFrame deadline should draw.
344 client
.task_runner().RunPendingTasks(); // Run posted deadline.
345 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 1);
346 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
347 EXPECT_TRUE(client
.needs_begin_frame());
350 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
351 // to avoid excessive toggles.
352 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
353 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
354 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
357 client
.task_runner().RunPendingTasks(); // Run posted deadline.
358 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
359 EXPECT_FALSE(client
.needs_begin_frame());
363 TEST(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
364 FakeSchedulerClient client
;
365 SchedulerSettings scheduler_settings
;
366 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
367 scheduler
->SetCanStart();
368 scheduler
->SetVisible(true);
369 scheduler
->SetCanDraw(true);
371 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
372 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
375 // SetNeedsCommit should begin the frame.
376 scheduler
->SetNeedsCommit();
377 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
380 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
381 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
382 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
383 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
385 EXPECT_TRUE(client
.needs_begin_frame());
388 // Now SetNeedsCommit again. Calling here means we need a second commit.
389 scheduler
->SetNeedsCommit();
390 EXPECT_EQ(client
.num_actions_(), 0);
393 // Finish the first commit.
394 scheduler
->NotifyBeginMainFrameStarted();
395 scheduler
->NotifyReadyToCommit();
396 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
397 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
399 client
.task_runner().RunPendingTasks(); // Run posted deadline.
400 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
401 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
402 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
404 // Because we just swapped, the Scheduler should also request the next
405 // BeginImplFrame from the OutputSurface.
406 EXPECT_TRUE(client
.needs_begin_frame());
408 // Since another commit is needed, the next BeginImplFrame should initiate
409 // the second commit.
410 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
411 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
412 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
413 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
416 // Finishing the commit before the deadline should post a new deadline task
417 // to trigger the deadline early.
418 scheduler
->NotifyBeginMainFrameStarted();
419 scheduler
->NotifyReadyToCommit();
420 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
421 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
423 client
.task_runner().RunPendingTasks(); // Run posted deadline.
424 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
425 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
426 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
427 EXPECT_TRUE(client
.needs_begin_frame());
430 // On the next BeginImplFrame, verify we go back to a quiescent state and
431 // no longer request BeginImplFrames.
432 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
433 client
.task_runner().RunPendingTasks(); // Run posted deadline.
434 EXPECT_FALSE(client
.needs_begin_frame());
438 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
440 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE
{}
441 virtual DrawResult
ScheduledActionDrawAndSwapIfPossible()
443 // Only SetNeedsRedraw the first time this is called
445 scheduler_
->SetNeedsRedraw();
446 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
449 virtual DrawResult
ScheduledActionDrawAndSwapForced() OVERRIDE
{
454 virtual void ScheduledActionCommit() OVERRIDE
{}
455 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE
{}
456 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks
) OVERRIDE
{}
459 // Tests for two different situations:
460 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
461 // a ScheduledActionDrawAndSwap
462 // 2. the scheduler drawing twice inside a single tick
463 TEST(SchedulerTest
, RequestRedrawInsideDraw
) {
464 SchedulerClientThatsetNeedsDrawInsideDraw client
;
465 SchedulerSettings default_scheduler_settings
;
466 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
467 scheduler
->SetCanStart();
468 scheduler
->SetVisible(true);
469 scheduler
->SetCanDraw(true);
470 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
473 scheduler
->SetNeedsRedraw();
474 EXPECT_TRUE(scheduler
->RedrawPending());
475 EXPECT_TRUE(client
.needs_begin_frame());
476 EXPECT_EQ(0, client
.num_draws());
478 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
479 client
.task_runner().RunPendingTasks(); // Run posted deadline.
480 EXPECT_EQ(1, client
.num_draws());
481 EXPECT_TRUE(scheduler
->RedrawPending());
482 EXPECT_TRUE(client
.needs_begin_frame());
484 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
485 client
.task_runner().RunPendingTasks(); // Run posted deadline.
486 EXPECT_EQ(2, client
.num_draws());
487 EXPECT_FALSE(scheduler
->RedrawPending());
488 EXPECT_TRUE(client
.needs_begin_frame());
490 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
492 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
493 client
.task_runner().RunPendingTasks(); // Run posted deadline.
494 EXPECT_EQ(2, client
.num_draws());
495 EXPECT_FALSE(scheduler
->RedrawPending());
496 EXPECT_FALSE(client
.needs_begin_frame());
499 // Test that requesting redraw inside a failed draw doesn't lose the request.
500 TEST(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
501 SchedulerClientThatsetNeedsDrawInsideDraw client
;
502 SchedulerSettings default_scheduler_settings
;
503 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
504 scheduler
->SetCanStart();
505 scheduler
->SetVisible(true);
506 scheduler
->SetCanDraw(true);
507 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
510 client
.SetDrawWillHappen(false);
512 scheduler
->SetNeedsRedraw();
513 EXPECT_TRUE(scheduler
->RedrawPending());
514 EXPECT_TRUE(client
.needs_begin_frame());
515 EXPECT_EQ(0, client
.num_draws());
518 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
519 client
.task_runner().RunPendingTasks(); // Run posted deadline.
520 EXPECT_EQ(1, client
.num_draws());
522 // We have a commit pending and the draw failed, and we didn't lose the redraw
524 EXPECT_TRUE(scheduler
->CommitPending());
525 EXPECT_TRUE(scheduler
->RedrawPending());
526 EXPECT_TRUE(client
.needs_begin_frame());
528 // Fail the draw again.
529 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
530 client
.task_runner().RunPendingTasks(); // Run posted deadline.
531 EXPECT_EQ(2, client
.num_draws());
532 EXPECT_TRUE(scheduler
->CommitPending());
533 EXPECT_TRUE(scheduler
->RedrawPending());
534 EXPECT_TRUE(client
.needs_begin_frame());
536 // Draw successfully.
537 client
.SetDrawWillHappen(true);
538 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
539 client
.task_runner().RunPendingTasks(); // Run posted deadline.
540 EXPECT_EQ(3, client
.num_draws());
541 EXPECT_TRUE(scheduler
->CommitPending());
542 EXPECT_FALSE(scheduler
->RedrawPending());
543 EXPECT_TRUE(client
.needs_begin_frame());
546 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
548 SchedulerClientThatSetNeedsCommitInsideDraw()
549 : set_needs_commit_on_next_draw_(false) {}
551 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE
{}
552 virtual DrawResult
ScheduledActionDrawAndSwapIfPossible()
554 // Only SetNeedsCommit the first time this is called
555 if (set_needs_commit_on_next_draw_
) {
556 scheduler_
->SetNeedsCommit();
557 set_needs_commit_on_next_draw_
= false;
559 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
562 virtual DrawResult
ScheduledActionDrawAndSwapForced() OVERRIDE
{
567 virtual void ScheduledActionCommit() OVERRIDE
{}
568 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE
{}
569 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks
) OVERRIDE
{}
571 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
574 bool set_needs_commit_on_next_draw_
;
577 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
578 // happen inside a ScheduledActionDrawAndSwap
579 TEST(SchedulerTest
, RequestCommitInsideDraw
) {
580 SchedulerClientThatSetNeedsCommitInsideDraw client
;
581 SchedulerSettings default_scheduler_settings
;
582 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
583 scheduler
->SetCanStart();
584 scheduler
->SetVisible(true);
585 scheduler
->SetCanDraw(true);
586 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
589 EXPECT_FALSE(client
.needs_begin_frame());
590 scheduler
->SetNeedsRedraw();
591 EXPECT_TRUE(scheduler
->RedrawPending());
592 EXPECT_EQ(0, client
.num_draws());
593 EXPECT_TRUE(client
.needs_begin_frame());
595 client
.SetNeedsCommitOnNextDraw();
596 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
597 client
.SetNeedsCommitOnNextDraw();
598 client
.task_runner().RunPendingTasks(); // Run posted deadline.
599 EXPECT_EQ(1, client
.num_draws());
600 EXPECT_TRUE(scheduler
->CommitPending());
601 EXPECT_TRUE(client
.needs_begin_frame());
602 scheduler
->NotifyBeginMainFrameStarted();
603 scheduler
->NotifyReadyToCommit();
605 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
606 client
.task_runner().RunPendingTasks(); // Run posted deadline.
607 EXPECT_EQ(2, client
.num_draws());
609 EXPECT_FALSE(scheduler
->RedrawPending());
610 EXPECT_FALSE(scheduler
->CommitPending());
611 EXPECT_TRUE(client
.needs_begin_frame());
613 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
615 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
616 client
.task_runner().RunPendingTasks(); // Run posted deadline.
617 EXPECT_EQ(2, client
.num_draws());
618 EXPECT_FALSE(scheduler
->RedrawPending());
619 EXPECT_FALSE(scheduler
->CommitPending());
620 EXPECT_FALSE(client
.needs_begin_frame());
623 // Tests that when a draw fails then the pending commit should not be dropped.
624 TEST(SchedulerTest
, RequestCommitInsideFailedDraw
) {
625 SchedulerClientThatsetNeedsDrawInsideDraw client
;
626 SchedulerSettings default_scheduler_settings
;
627 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
628 scheduler
->SetCanStart();
629 scheduler
->SetVisible(true);
630 scheduler
->SetCanDraw(true);
631 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
634 client
.SetDrawWillHappen(false);
636 scheduler
->SetNeedsRedraw();
637 EXPECT_TRUE(scheduler
->RedrawPending());
638 EXPECT_TRUE(client
.needs_begin_frame());
639 EXPECT_EQ(0, client
.num_draws());
642 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
643 client
.task_runner().RunPendingTasks(); // Run posted deadline.
644 EXPECT_EQ(1, client
.num_draws());
646 // We have a commit pending and the draw failed, and we didn't lose the commit
648 EXPECT_TRUE(scheduler
->CommitPending());
649 EXPECT_TRUE(scheduler
->RedrawPending());
650 EXPECT_TRUE(client
.needs_begin_frame());
652 // Fail the draw again.
653 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
655 client
.task_runner().RunPendingTasks(); // Run posted deadline.
656 EXPECT_EQ(2, client
.num_draws());
657 EXPECT_TRUE(scheduler
->CommitPending());
658 EXPECT_TRUE(scheduler
->RedrawPending());
659 EXPECT_TRUE(client
.needs_begin_frame());
661 // Draw successfully.
662 client
.SetDrawWillHappen(true);
663 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
664 client
.task_runner().RunPendingTasks(); // Run posted deadline.
665 EXPECT_EQ(3, client
.num_draws());
666 EXPECT_TRUE(scheduler
->CommitPending());
667 EXPECT_FALSE(scheduler
->RedrawPending());
668 EXPECT_TRUE(client
.needs_begin_frame());
671 TEST(SchedulerTest
, NoSwapWhenDrawFails
) {
672 SchedulerClientThatSetNeedsCommitInsideDraw client
;
673 SchedulerSettings default_scheduler_settings
;
674 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
675 scheduler
->SetCanStart();
676 scheduler
->SetVisible(true);
677 scheduler
->SetCanDraw(true);
678 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
681 scheduler
->SetNeedsRedraw();
682 EXPECT_TRUE(scheduler
->RedrawPending());
683 EXPECT_TRUE(client
.needs_begin_frame());
684 EXPECT_EQ(0, client
.num_draws());
686 // Draw successfully, this starts a new frame.
687 client
.SetNeedsCommitOnNextDraw();
688 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
689 client
.task_runner().RunPendingTasks(); // Run posted deadline.
690 EXPECT_EQ(1, client
.num_draws());
692 scheduler
->SetNeedsRedraw();
693 EXPECT_TRUE(scheduler
->RedrawPending());
694 EXPECT_TRUE(client
.needs_begin_frame());
696 // Fail to draw, this should not start a frame.
697 client
.SetDrawWillHappen(false);
698 client
.SetNeedsCommitOnNextDraw();
699 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
700 client
.task_runner().RunPendingTasks(); // Run posted deadline.
701 EXPECT_EQ(2, client
.num_draws());
704 class SchedulerClientNeedsManageTilesInDraw
: public FakeSchedulerClient
{
706 virtual DrawResult
ScheduledActionDrawAndSwapIfPossible()
708 scheduler_
->SetNeedsManageTiles();
709 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
713 // Test manage tiles is independant of draws.
714 TEST(SchedulerTest
, ManageTiles
) {
715 SchedulerClientNeedsManageTilesInDraw client
;
716 SchedulerSettings default_scheduler_settings
;
717 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
718 scheduler
->SetCanStart();
719 scheduler
->SetVisible(true);
720 scheduler
->SetCanDraw(true);
721 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
723 // Request both draw and manage tiles. ManageTiles shouldn't
724 // be trigged until BeginImplFrame.
726 scheduler
->SetNeedsManageTiles();
727 scheduler
->SetNeedsRedraw();
728 EXPECT_TRUE(scheduler
->RedrawPending());
729 EXPECT_TRUE(scheduler
->ManageTilesPending());
730 EXPECT_TRUE(client
.needs_begin_frame());
731 EXPECT_EQ(0, client
.num_draws());
732 EXPECT_FALSE(client
.HasAction("ScheduledActionManageTiles"));
733 EXPECT_FALSE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
735 // We have no immediate actions to perform, so the BeginImplFrame should post
736 // the deadline task.
738 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
739 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
740 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
741 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
743 // On the deadline, he actions should have occured in the right order.
745 client
.task_runner().RunPendingTasks(); // Run posted deadline.
746 EXPECT_EQ(1, client
.num_draws());
747 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
748 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
749 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
750 client
.ActionIndex("ScheduledActionManageTiles"));
751 EXPECT_FALSE(scheduler
->RedrawPending());
752 EXPECT_FALSE(scheduler
->ManageTilesPending());
753 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
755 // Request a draw. We don't need a ManageTiles yet.
757 scheduler
->SetNeedsRedraw();
758 EXPECT_TRUE(scheduler
->RedrawPending());
759 EXPECT_FALSE(scheduler
->ManageTilesPending());
760 EXPECT_TRUE(client
.needs_begin_frame());
761 EXPECT_EQ(0, client
.num_draws());
763 // We have no immediate actions to perform, so the BeginImplFrame should post
764 // the deadline task.
766 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
767 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
768 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
769 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
771 // Draw. The draw will trigger SetNeedsManageTiles, and
772 // then the ManageTiles action will be triggered after the Draw.
773 // Afterwards, neither a draw nor ManageTiles are pending.
775 client
.task_runner().RunPendingTasks(); // Run posted deadline.
776 EXPECT_EQ(1, client
.num_draws());
777 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
778 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
779 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
780 client
.ActionIndex("ScheduledActionManageTiles"));
781 EXPECT_FALSE(scheduler
->RedrawPending());
782 EXPECT_FALSE(scheduler
->ManageTilesPending());
783 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
785 // We need a BeginImplFrame where we don't swap to go idle.
787 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
788 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
789 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
791 client
.task_runner().RunPendingTasks(); // Run posted deadline.
792 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
793 EXPECT_FALSE(client
.needs_begin_frame());
794 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
795 EXPECT_EQ(0, client
.num_draws());
797 // Now trigger a ManageTiles outside of a draw. We will then need
798 // a begin-frame for the ManageTiles, but we don't need a draw.
800 EXPECT_FALSE(client
.needs_begin_frame());
801 scheduler
->SetNeedsManageTiles();
802 EXPECT_TRUE(client
.needs_begin_frame());
803 EXPECT_TRUE(scheduler
->ManageTilesPending());
804 EXPECT_FALSE(scheduler
->RedrawPending());
806 // BeginImplFrame. There will be no draw, only ManageTiles.
808 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
809 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
810 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
812 client
.task_runner().RunPendingTasks(); // Run posted deadline.
813 EXPECT_EQ(0, client
.num_draws());
814 EXPECT_FALSE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
815 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
816 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
819 // Test that ManageTiles only happens once per frame. If an external caller
820 // initiates it, then the state machine should not ManageTiles on that frame.
821 TEST(SchedulerTest
, ManageTilesOncePerFrame
) {
822 FakeSchedulerClient client
;
823 SchedulerSettings default_scheduler_settings
;
824 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
825 scheduler
->SetCanStart();
826 scheduler
->SetVisible(true);
827 scheduler
->SetCanDraw(true);
828 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
830 // If DidManageTiles during a frame, then ManageTiles should not occur again.
831 scheduler
->SetNeedsManageTiles();
832 scheduler
->SetNeedsRedraw();
834 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
835 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
836 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
837 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
839 EXPECT_TRUE(scheduler
->ManageTilesPending());
840 scheduler
->DidManageTiles(); // An explicit ManageTiles.
841 EXPECT_FALSE(scheduler
->ManageTilesPending());
844 client
.task_runner().RunPendingTasks(); // Run posted deadline.
845 EXPECT_EQ(1, client
.num_draws());
846 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
847 EXPECT_FALSE(client
.HasAction("ScheduledActionManageTiles"));
848 EXPECT_FALSE(scheduler
->RedrawPending());
849 EXPECT_FALSE(scheduler
->ManageTilesPending());
850 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
852 // Next frame without DidManageTiles should ManageTiles with draw.
853 scheduler
->SetNeedsManageTiles();
854 scheduler
->SetNeedsRedraw();
856 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
857 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
858 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
859 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
862 client
.task_runner().RunPendingTasks(); // Run posted deadline.
863 EXPECT_EQ(1, client
.num_draws());
864 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
865 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
866 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
867 client
.ActionIndex("ScheduledActionManageTiles"));
868 EXPECT_FALSE(scheduler
->RedrawPending());
869 EXPECT_FALSE(scheduler
->ManageTilesPending());
870 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
871 scheduler
->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
873 // If we get another DidManageTiles within the same frame, we should
874 // not ManageTiles on the next frame.
875 scheduler
->DidManageTiles(); // An explicit ManageTiles.
876 scheduler
->SetNeedsManageTiles();
877 scheduler
->SetNeedsRedraw();
879 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
880 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
881 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
882 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
884 EXPECT_TRUE(scheduler
->ManageTilesPending());
887 client
.task_runner().RunPendingTasks(); // Run posted deadline.
888 EXPECT_EQ(1, client
.num_draws());
889 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
890 EXPECT_FALSE(client
.HasAction("ScheduledActionManageTiles"));
891 EXPECT_FALSE(scheduler
->RedrawPending());
892 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
894 // If we get another DidManageTiles, we should not ManageTiles on the next
895 // frame. This verifies we don't alternate calling ManageTiles once and twice.
896 EXPECT_TRUE(scheduler
->ManageTilesPending());
897 scheduler
->DidManageTiles(); // An explicit ManageTiles.
898 EXPECT_FALSE(scheduler
->ManageTilesPending());
899 scheduler
->SetNeedsManageTiles();
900 scheduler
->SetNeedsRedraw();
902 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
903 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
904 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
905 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
907 EXPECT_TRUE(scheduler
->ManageTilesPending());
910 client
.task_runner().RunPendingTasks(); // Run posted deadline.
911 EXPECT_EQ(1, client
.num_draws());
912 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
913 EXPECT_FALSE(client
.HasAction("ScheduledActionManageTiles"));
914 EXPECT_FALSE(scheduler
->RedrawPending());
915 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
917 // Next frame without DidManageTiles should ManageTiles with draw.
918 scheduler
->SetNeedsManageTiles();
919 scheduler
->SetNeedsRedraw();
921 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
922 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
923 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
924 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
927 client
.task_runner().RunPendingTasks(); // Run posted deadline.
928 EXPECT_EQ(1, client
.num_draws());
929 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
930 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
931 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
932 client
.ActionIndex("ScheduledActionManageTiles"));
933 EXPECT_FALSE(scheduler
->RedrawPending());
934 EXPECT_FALSE(scheduler
->ManageTilesPending());
935 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
936 scheduler
->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
939 TEST(SchedulerTest
, ShouldUpdateVisibleTiles
) {
940 FakeSchedulerClient client
;
941 SchedulerSettings scheduler_settings
;
942 scheduler_settings
.impl_side_painting
= true;
943 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
944 scheduler
->SetCanStart();
945 scheduler
->SetVisible(true);
946 scheduler
->SetCanDraw(true);
947 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
949 client
.SetRedrawWillHappenIfUpdateVisibleTilesHappens(true);
951 // SetNeedsCommit should begin the frame.
953 scheduler
->SetNeedsCommit();
954 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
957 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
958 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
959 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
960 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
963 scheduler
->NotifyBeginMainFrameStarted();
964 scheduler
->NotifyReadyToCommit();
965 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
968 scheduler
->NotifyReadyToActivate();
969 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client
);
972 client
.SetSwapContainsIncompleteTile(true);
973 client
.task_runner().RunPendingTasks(); // Run posted deadline.
974 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
975 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
976 EXPECT_FALSE(scheduler
->RedrawPending());
979 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
980 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
981 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
984 client
.task_runner().RunPendingTasks(); // Run posted deadline.
985 EXPECT_ACTION("ScheduledActionUpdateVisibleTiles", client
, 0, 3);
986 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 3);
987 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 2, 3);
990 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
991 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
992 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
994 // No more UpdateVisibleTiles().
996 client
.task_runner().RunPendingTasks(); // Run posted deadline.
997 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
998 EXPECT_FALSE(client
.needs_begin_frame());
1001 TEST(SchedulerTest
, TriggerBeginFrameDeadlineEarly
) {
1002 SchedulerClientNeedsManageTilesInDraw client
;
1003 SchedulerSettings default_scheduler_settings
;
1004 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
1005 scheduler
->SetCanStart();
1006 scheduler
->SetVisible(true);
1007 scheduler
->SetCanDraw(true);
1008 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1011 scheduler
->SetNeedsRedraw();
1012 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1014 // The deadline should be zero since there is no work other than drawing
1016 EXPECT_EQ(base::TimeTicks(), client
.posted_begin_impl_frame_deadline());
1019 class SchedulerClientWithFixedEstimates
: public FakeSchedulerClient
{
1021 SchedulerClientWithFixedEstimates(
1022 base::TimeDelta draw_duration
,
1023 base::TimeDelta begin_main_frame_to_commit_duration
,
1024 base::TimeDelta commit_to_activate_duration
)
1025 : draw_duration_(draw_duration
),
1026 begin_main_frame_to_commit_duration_(
1027 begin_main_frame_to_commit_duration
),
1028 commit_to_activate_duration_(commit_to_activate_duration
) {}
1030 virtual base::TimeDelta
DrawDurationEstimate() OVERRIDE
{
1031 return draw_duration_
;
1033 virtual base::TimeDelta
BeginMainFrameToCommitDurationEstimate() OVERRIDE
{
1034 return begin_main_frame_to_commit_duration_
;
1036 virtual base::TimeDelta
CommitToActivateDurationEstimate() OVERRIDE
{
1037 return commit_to_activate_duration_
;
1041 base::TimeDelta draw_duration_
;
1042 base::TimeDelta begin_main_frame_to_commit_duration_
;
1043 base::TimeDelta commit_to_activate_duration_
;
1046 void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms
,
1047 int64 commit_to_activate_estimate_in_ms
,
1048 bool smoothness_takes_priority
,
1049 bool should_send_begin_main_frame
) {
1050 // Set up client with specified estimates (draw duration is set to 1).
1051 SchedulerClientWithFixedEstimates
client(
1052 base::TimeDelta::FromMilliseconds(1),
1053 base::TimeDelta::FromMilliseconds(
1054 begin_main_frame_to_commit_estimate_in_ms
),
1055 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms
));
1056 SchedulerSettings default_scheduler_settings
;
1057 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
1058 scheduler
->SetCanStart();
1059 scheduler
->SetVisible(true);
1060 scheduler
->SetCanDraw(true);
1061 scheduler
->SetSmoothnessTakesPriority(smoothness_takes_priority
);
1062 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1064 // Impl thread hits deadline before commit finishes.
1066 scheduler
->SetNeedsCommit();
1067 EXPECT_FALSE(scheduler
->MainThreadIsInHighLatencyMode());
1068 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1069 EXPECT_FALSE(scheduler
->MainThreadIsInHighLatencyMode());
1070 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1071 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1072 scheduler
->NotifyBeginMainFrameStarted();
1073 scheduler
->NotifyReadyToCommit();
1074 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1075 EXPECT_TRUE(client
.HasAction("ScheduledActionSendBeginMainFrame"));
1078 scheduler
->SetNeedsCommit();
1079 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1080 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1081 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1082 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1083 EXPECT_EQ(scheduler
->MainThreadIsInHighLatencyMode(),
1084 should_send_begin_main_frame
);
1085 EXPECT_EQ(client
.HasAction("ScheduledActionSendBeginMainFrame"),
1086 should_send_begin_main_frame
);
1090 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline
) {
1091 // Set up client so that estimates indicate that we can commit and activate
1092 // before the deadline (~8ms by default).
1093 MainFrameInHighLatencyMode(1, 1, false, false);
1096 TEST(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong
) {
1097 // Set up client so that estimates indicate that the commit cannot finish
1098 // before the deadline (~8ms by default).
1099 MainFrameInHighLatencyMode(10, 1, false, true);
1102 TEST(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong
) {
1103 // Set up client so that estimates indicate that the activate cannot finish
1104 // before the deadline (~8ms by default).
1105 MainFrameInHighLatencyMode(1, 10, false, true);
1108 TEST(SchedulerTest
, NotSkipMainFrameInPreferSmoothnessMode
) {
1109 // Set up client so that estimates indicate that we can commit and activate
1110 // before the deadline (~8ms by default), but also enable smoothness takes
1112 MainFrameInHighLatencyMode(1, 1, true, true);
1115 TEST(SchedulerTest
, PollForCommitCompletion
) {
1116 // Since we are simulating a long commit, set up a client with draw duration
1117 // estimates that prevent skipping main frames to get to low latency mode.
1118 SchedulerClientWithFixedEstimates
client(
1119 base::TimeDelta::FromMilliseconds(1),
1120 base::TimeDelta::FromMilliseconds(32),
1121 base::TimeDelta::FromMilliseconds(32));
1122 client
.set_log_anticipated_draw_time_change(true);
1123 SchedulerSettings default_scheduler_settings
;
1124 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
1126 scheduler
->SetCanDraw(true);
1127 scheduler
->SetCanStart();
1128 scheduler
->SetVisible(true);
1129 scheduler
->DidCreateAndInitializeOutputSurface();
1131 scheduler
->SetNeedsCommit();
1132 EXPECT_TRUE(scheduler
->CommitPending());
1133 scheduler
->NotifyBeginMainFrameStarted();
1134 scheduler
->NotifyReadyToCommit();
1135 scheduler
->SetNeedsRedraw();
1137 BeginFrameArgs frame_args
= CreateBeginFrameArgsForTesting();
1138 frame_args
.interval
= base::TimeDelta::FromMilliseconds(1000);
1139 scheduler
->BeginFrame(frame_args
);
1141 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1142 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1143 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1145 scheduler
->DidSwapBuffers();
1146 scheduler
->DidSwapBuffersComplete();
1148 // At this point, we've drawn a frame. Start another commit, but hold off on
1149 // the NotifyReadyToCommit for now.
1150 EXPECT_FALSE(scheduler
->CommitPending());
1151 scheduler
->SetNeedsCommit();
1152 scheduler
->BeginFrame(frame_args
);
1153 EXPECT_TRUE(scheduler
->CommitPending());
1155 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1156 // blocking on the renderer.
1157 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1158 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1159 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1160 scheduler
->DidSwapBuffers();
1162 // Spin the event loop a few times and make sure we get more
1163 // DidAnticipateDrawTimeChange calls every time.
1164 int actions_so_far
= client
.num_actions_();
1166 // Does three iterations to make sure that the timer is properly repeating.
1167 for (int i
= 0; i
< 3; ++i
) {
1168 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1169 client
.task_runner().NextPendingTaskDelay().InMicroseconds())
1170 << *scheduler
->AsValue();
1171 client
.task_runner().RunPendingTasks();
1172 EXPECT_GT(client
.num_actions_(), actions_so_far
);
1173 EXPECT_STREQ(client
.Action(client
.num_actions_() - 1),
1174 "DidAnticipatedDrawTimeChange");
1175 actions_so_far
= client
.num_actions_();
1178 // Do the same thing after BeginMainFrame starts but still before activation.
1179 scheduler
->NotifyBeginMainFrameStarted();
1180 for (int i
= 0; i
< 3; ++i
) {
1181 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1182 client
.task_runner().NextPendingTaskDelay().InMicroseconds())
1183 << *scheduler
->AsValue();
1184 client
.task_runner().RunPendingTasks();
1185 EXPECT_GT(client
.num_actions_(), actions_so_far
);
1186 EXPECT_STREQ(client
.Action(client
.num_actions_() - 1),
1187 "DidAnticipatedDrawTimeChange");
1188 actions_so_far
= client
.num_actions_();
1192 TEST(SchedulerTest
, BeginRetroFrame
) {
1193 FakeSchedulerClient client
;
1194 SchedulerSettings scheduler_settings
;
1195 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1196 scheduler
->SetCanStart();
1197 scheduler
->SetVisible(true);
1198 scheduler
->SetCanDraw(true);
1199 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1201 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1203 scheduler
->SetNeedsCommit();
1204 EXPECT_TRUE(client
.needs_begin_frame());
1205 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1208 // Create a BeginFrame with a long deadline to avoid race conditions.
1209 // This is the first BeginFrame, which will be handled immediately.
1210 BeginFrameArgs args
= CreateBeginFrameArgsForTesting();
1211 args
.deadline
+= base::TimeDelta::FromHours(1);
1212 scheduler
->BeginFrame(args
);
1213 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1214 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1215 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1216 EXPECT_TRUE(client
.needs_begin_frame());
1219 // Queue BeginFrames while we are still handling the previous BeginFrame.
1220 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1221 scheduler
->BeginFrame(args
);
1222 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1223 scheduler
->BeginFrame(args
);
1225 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1226 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1227 EXPECT_NO_ACTION(client
);
1228 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1229 EXPECT_TRUE(client
.needs_begin_frame());
1232 // NotifyReadyToCommit should trigger the commit.
1233 scheduler
->NotifyBeginMainFrameStarted();
1234 scheduler
->NotifyReadyToCommit();
1235 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1236 EXPECT_TRUE(client
.needs_begin_frame());
1239 // BeginImplFrame should prepare the draw.
1240 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1241 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1242 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1243 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1244 EXPECT_TRUE(client
.needs_begin_frame());
1247 // BeginImplFrame deadline should draw.
1248 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1249 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 1);
1250 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1251 EXPECT_TRUE(client
.needs_begin_frame());
1254 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1255 // to avoid excessive toggles.
1256 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1257 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1258 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1261 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1262 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1263 EXPECT_FALSE(client
.needs_begin_frame());
1267 TEST(SchedulerTest
, BeginRetroFrame_SwapThrottled
) {
1268 FakeSchedulerClient client
;
1269 SchedulerSettings scheduler_settings
;
1270 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1271 scheduler
->SetCanStart();
1272 scheduler
->SetVisible(true);
1273 scheduler
->SetCanDraw(true);
1274 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1276 // To test swap ack throttling, this test disables automatic swap acks.
1277 scheduler
->SetMaxSwapsPending(1);
1278 client
.SetAutomaticSwapAck(false);
1280 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1282 scheduler
->SetNeedsCommit();
1283 EXPECT_TRUE(client
.needs_begin_frame());
1284 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1287 // Create a BeginFrame with a long deadline to avoid race conditions.
1288 // This is the first BeginFrame, which will be handled immediately.
1289 BeginFrameArgs args
= CreateBeginFrameArgsForTesting();
1290 args
.deadline
+= base::TimeDelta::FromHours(1);
1291 scheduler
->BeginFrame(args
);
1292 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1293 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1294 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1295 EXPECT_TRUE(client
.needs_begin_frame());
1298 // Queue BeginFrame while we are still handling the previous BeginFrame.
1299 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1300 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1301 scheduler
->BeginFrame(args
);
1302 EXPECT_NO_ACTION(client
);
1303 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1306 // NotifyReadyToCommit should trigger the pending commit and draw.
1307 scheduler
->NotifyBeginMainFrameStarted();
1308 scheduler
->NotifyReadyToCommit();
1309 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1310 EXPECT_TRUE(client
.needs_begin_frame());
1313 // Swapping will put us into a swap throttled state.
1314 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1315 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1316 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1317 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1318 EXPECT_TRUE(client
.needs_begin_frame());
1321 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1322 // but not a BeginMainFrame or draw.
1323 scheduler
->SetNeedsCommit();
1324 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1325 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 1);
1326 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1327 EXPECT_TRUE(client
.needs_begin_frame());
1330 // Queue BeginFrame while we are still handling the previous BeginFrame.
1331 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1332 scheduler
->BeginFrame(args
);
1333 EXPECT_NO_ACTION(client
);
1334 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1335 EXPECT_TRUE(client
.needs_begin_frame());
1338 // Take us out of a swap throttled state.
1339 scheduler
->DidSwapBuffersComplete();
1340 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 1);
1341 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1342 EXPECT_TRUE(client
.needs_begin_frame());
1345 // BeginImplFrame deadline should draw.
1346 scheduler
->SetNeedsRedraw();
1347 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1348 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1349 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1350 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1351 EXPECT_TRUE(client
.needs_begin_frame());
1355 void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled
,
1356 bool throttle_frame_production
) {
1357 FakeSchedulerClient client
;
1358 SchedulerSettings scheduler_settings
;
1359 scheduler_settings
.begin_frame_scheduling_enabled
=
1360 begin_frame_scheduling_enabled
;
1361 scheduler_settings
.throttle_frame_production
= throttle_frame_production
;
1362 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1363 scheduler
->SetCanStart();
1364 scheduler
->SetVisible(true);
1365 scheduler
->SetCanDraw(true);
1366 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1368 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1369 // without calling SetNeedsBeginFrame.
1371 scheduler
->SetNeedsCommit();
1372 EXPECT_FALSE(client
.needs_begin_frame());
1373 EXPECT_NO_ACTION(client
);
1376 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1377 // own BeginFrame tasks.
1378 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1379 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1380 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1381 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1382 EXPECT_FALSE(client
.needs_begin_frame());
1385 // If we don't swap on the deadline, we wait for the next BeginFrame.
1386 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1387 EXPECT_NO_ACTION(client
);
1388 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1389 EXPECT_FALSE(client
.needs_begin_frame());
1392 // NotifyReadyToCommit should trigger the commit.
1393 scheduler
->NotifyBeginMainFrameStarted();
1394 scheduler
->NotifyReadyToCommit();
1395 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1396 EXPECT_FALSE(client
.needs_begin_frame());
1399 // BeginImplFrame should prepare the draw.
1400 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1401 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1402 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1403 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1404 EXPECT_FALSE(client
.needs_begin_frame());
1407 // BeginImplFrame deadline should draw.
1408 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1409 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 1);
1410 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1411 EXPECT_FALSE(client
.needs_begin_frame());
1414 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1415 // to avoid excessive toggles.
1416 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1417 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1418 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1421 // Make sure SetNeedsBeginFrame isn't called on the client
1422 // when the BeginFrame is no longer needed.
1423 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1424 EXPECT_NO_ACTION(client
);
1425 EXPECT_FALSE(client
.needs_begin_frame());
1429 // See: http://crbug.com/388901
1430 TEST(SchedulerTest
, DISABLED_SyntheticBeginFrames
) {
1431 bool begin_frame_scheduling_enabled
= false;
1432 bool throttle_frame_production
= true;
1433 BeginFramesNotFromClient(begin_frame_scheduling_enabled
,
1434 throttle_frame_production
);
1437 TEST(SchedulerTest
, VSyncThrottlingDisabled
) {
1438 bool begin_frame_scheduling_enabled
= true;
1439 bool throttle_frame_production
= false;
1440 BeginFramesNotFromClient(begin_frame_scheduling_enabled
,
1441 throttle_frame_production
);
1444 TEST(SchedulerTest
, SyntheticBeginFrames_And_VSyncThrottlingDisabled
) {
1445 bool begin_frame_scheduling_enabled
= false;
1446 bool throttle_frame_production
= false;
1447 BeginFramesNotFromClient(begin_frame_scheduling_enabled
,
1448 throttle_frame_production
);
1451 void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled
,
1452 bool throttle_frame_production
) {
1453 FakeSchedulerClient client
;
1454 SchedulerSettings scheduler_settings
;
1455 scheduler_settings
.begin_frame_scheduling_enabled
=
1456 begin_frame_scheduling_enabled
;
1457 scheduler_settings
.throttle_frame_production
= throttle_frame_production
;
1458 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1459 scheduler
->SetCanStart();
1460 scheduler
->SetVisible(true);
1461 scheduler
->SetCanDraw(true);
1462 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1464 // To test swap ack throttling, this test disables automatic swap acks.
1465 scheduler
->SetMaxSwapsPending(1);
1466 client
.SetAutomaticSwapAck(false);
1468 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1470 scheduler
->SetNeedsCommit();
1471 EXPECT_FALSE(client
.needs_begin_frame());
1472 EXPECT_NO_ACTION(client
);
1475 // Trigger the first BeginImplFrame and BeginMainFrame
1476 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1477 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1478 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1479 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1480 EXPECT_FALSE(client
.needs_begin_frame());
1483 // NotifyReadyToCommit should trigger the pending commit and draw.
1484 scheduler
->NotifyBeginMainFrameStarted();
1485 scheduler
->NotifyReadyToCommit();
1486 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1487 EXPECT_FALSE(client
.needs_begin_frame());
1490 // Swapping will put us into a swap throttled state.
1491 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1492 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1493 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1494 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1495 EXPECT_FALSE(client
.needs_begin_frame());
1498 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1499 // but not a BeginMainFrame or draw.
1500 scheduler
->SetNeedsCommit();
1501 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1502 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 1);
1503 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1504 EXPECT_FALSE(client
.needs_begin_frame());
1507 // Take us out of a swap throttled state.
1508 scheduler
->DidSwapBuffersComplete();
1509 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 1);
1510 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1511 EXPECT_FALSE(client
.needs_begin_frame());
1514 // BeginImplFrame deadline should draw.
1515 scheduler
->SetNeedsRedraw();
1516 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1517 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1518 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1519 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1520 EXPECT_FALSE(client
.needs_begin_frame());
1524 TEST(SchedulerTest
, SyntheticBeginFrames_SwapThrottled
) {
1525 bool begin_frame_scheduling_enabled
= false;
1526 bool throttle_frame_production
= true;
1527 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled
,
1528 throttle_frame_production
);
1531 TEST(SchedulerTest
, VSyncThrottlingDisabled_SwapThrottled
) {
1532 bool begin_frame_scheduling_enabled
= true;
1533 bool throttle_frame_production
= false;
1534 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled
,
1535 throttle_frame_production
);
1539 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled
) {
1540 bool begin_frame_scheduling_enabled
= false;
1541 bool throttle_frame_production
= false;
1542 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled
,
1543 throttle_frame_production
);
1546 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized
) {
1547 FakeSchedulerClient client
;
1548 SchedulerSettings scheduler_settings
;
1549 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1550 scheduler
->SetCanStart();
1551 scheduler
->SetVisible(true);
1552 scheduler
->SetCanDraw(true);
1554 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1556 scheduler
->DidCreateAndInitializeOutputSurface();
1557 EXPECT_NO_ACTION(client
);
1559 scheduler
->DidLoseOutputSurface();
1560 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1563 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStarted
) {
1564 FakeSchedulerClient client
;
1565 SchedulerSettings scheduler_settings
;
1566 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1567 scheduler
->SetCanStart();
1568 scheduler
->SetVisible(true);
1569 scheduler
->SetCanDraw(true);
1571 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1572 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1573 // SetNeedsCommit should begin the frame.
1575 scheduler
->SetNeedsCommit();
1576 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1579 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1580 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1581 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1582 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1585 scheduler
->DidLoseOutputSurface();
1586 // Do nothing when impl frame is in deadine pending state.
1587 EXPECT_NO_ACTION(client
);
1590 scheduler
->NotifyBeginMainFrameStarted();
1591 scheduler
->NotifyReadyToCommit();
1592 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 1);
1595 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1596 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1599 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1600 bool impl_side_painting
) {
1601 FakeSchedulerClient client
;
1602 SchedulerSettings scheduler_settings
;
1603 scheduler_settings
.impl_side_painting
= impl_side_painting
;
1604 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1605 scheduler
->SetCanStart();
1606 scheduler
->SetVisible(true);
1607 scheduler
->SetCanDraw(true);
1609 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1610 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1612 // SetNeedsCommit should begin the frame.
1614 scheduler
->SetNeedsCommit();
1615 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1618 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1619 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1620 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1621 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1624 scheduler
->DidLoseOutputSurface();
1625 // Do nothing when impl frame is in deadine pending state.
1626 EXPECT_NO_ACTION(client
);
1629 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1630 // OnBeginImplFrameDeadline didn't schedule any actions because main frame is
1631 // not yet completed.
1632 EXPECT_NO_ACTION(client
);
1634 // BeginImplFrame is not started.
1635 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1636 EXPECT_NO_ACTION(client
);
1637 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1640 scheduler
->NotifyBeginMainFrameStarted();
1641 scheduler
->NotifyReadyToCommit();
1642 if (impl_side_painting
) {
1643 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 3);
1644 EXPECT_ACTION("ScheduledActionActivateSyncTree", client
, 1, 3);
1645 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
, 2, 3);
1647 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 2);
1648 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
, 1, 2);
1652 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency
) {
1653 bool impl_side_painting
= false;
1654 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1658 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint
) {
1659 bool impl_side_painting
= true;
1660 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1663 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting
) {
1664 FakeSchedulerClient client
;
1665 SchedulerSettings scheduler_settings
;
1666 scheduler_settings
.impl_side_painting
= impl_side_painting
;
1667 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1668 scheduler
->SetCanStart();
1669 scheduler
->SetVisible(true);
1670 scheduler
->SetCanDraw(true);
1672 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1673 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1675 // SetNeedsCommit should begin the frame.
1677 scheduler
->SetNeedsCommit();
1678 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1681 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1682 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1683 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1684 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1687 scheduler
->NotifyBeginMainFrameStarted();
1688 scheduler
->NotifyReadyToCommit();
1689 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1692 scheduler
->DidLoseOutputSurface();
1693 if (impl_side_painting
) {
1694 // Sync tree should be forced to activate.
1695 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client
);
1697 // Do nothing when impl frame is in deadine pending state.
1698 EXPECT_NO_ACTION(client
);
1702 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1703 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1706 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommit
) {
1707 DidLoseOutputSurfaceAfterReadyToCommit(false);
1710 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting
) {
1711 DidLoseOutputSurfaceAfterReadyToCommit(true);
1714 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterSetNeedsManageTiles
) {
1715 FakeSchedulerClient client
;
1716 SchedulerSettings scheduler_settings
;
1717 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1718 scheduler
->SetCanStart();
1719 scheduler
->SetVisible(true);
1720 scheduler
->SetCanDraw(true);
1721 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1724 scheduler
->SetNeedsManageTiles();
1725 scheduler
->SetNeedsRedraw();
1726 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1727 EXPECT_TRUE(client
.needs_begin_frame());
1730 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1731 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1732 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1733 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1736 scheduler
->DidLoseOutputSurface();
1737 EXPECT_NO_ACTION(client
);
1740 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1741 EXPECT_ACTION("ScheduledActionManageTiles", client
, 0, 2);
1742 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
, 1, 2);
1745 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterBeginRetroFramePosted
) {
1746 FakeSchedulerClient client
;
1747 SchedulerSettings scheduler_settings
;
1748 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1749 scheduler
->SetCanStart();
1750 scheduler
->SetVisible(true);
1751 scheduler
->SetCanDraw(true);
1752 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1754 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1756 scheduler
->SetNeedsCommit();
1757 EXPECT_TRUE(client
.needs_begin_frame());
1758 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1760 // Create a BeginFrame with a long deadline to avoid race conditions.
1761 // This is the first BeginFrame, which will be handled immediately.
1763 BeginFrameArgs args
= CreateBeginFrameArgsForTesting();
1764 args
.deadline
+= base::TimeDelta::FromHours(1);
1765 scheduler
->BeginFrame(args
);
1766 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1767 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1768 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1769 EXPECT_TRUE(client
.needs_begin_frame());
1771 // Queue BeginFrames while we are still handling the previous BeginFrame.
1772 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1773 scheduler
->BeginFrame(args
);
1774 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1775 scheduler
->BeginFrame(args
);
1777 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1779 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1780 EXPECT_NO_ACTION(client
);
1781 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1782 EXPECT_TRUE(client
.needs_begin_frame());
1784 // NotifyReadyToCommit should trigger the commit.
1786 scheduler
->NotifyBeginMainFrameStarted();
1787 scheduler
->NotifyReadyToCommit();
1788 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1789 EXPECT_TRUE(client
.needs_begin_frame());
1792 EXPECT_FALSE(scheduler
->IsBeginRetroFrameArgsEmpty());
1793 scheduler
->DidLoseOutputSurface();
1794 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1795 EXPECT_TRUE(client
.needs_begin_frame());
1796 EXPECT_TRUE(scheduler
->IsBeginRetroFrameArgsEmpty());
1798 // Posted BeginRetroFrame is aborted.
1800 client
.task_runner().RunPendingTasks();
1801 EXPECT_NO_ACTION(client
);
1804 TEST(SchedulerTest
, DidLoseOutputSurfaceDuringBeginRetroFrameRunning
) {
1805 FakeSchedulerClient client
;
1806 SchedulerSettings scheduler_settings
;
1807 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1808 scheduler
->SetCanStart();
1809 scheduler
->SetVisible(true);
1810 scheduler
->SetCanDraw(true);
1811 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1813 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1815 scheduler
->SetNeedsCommit();
1816 EXPECT_TRUE(client
.needs_begin_frame());
1817 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1819 // Create a BeginFrame with a long deadline to avoid race conditions.
1820 // This is the first BeginFrame, which will be handled immediately.
1822 BeginFrameArgs args
= CreateBeginFrameArgsForTesting();
1823 args
.deadline
+= base::TimeDelta::FromHours(1);
1824 scheduler
->BeginFrame(args
);
1825 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1826 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1827 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1828 EXPECT_TRUE(client
.needs_begin_frame());
1830 // Queue BeginFrames while we are still handling the previous BeginFrame.
1831 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1832 scheduler
->BeginFrame(args
);
1833 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1834 scheduler
->BeginFrame(args
);
1836 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1838 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1839 EXPECT_NO_ACTION(client
);
1840 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1841 EXPECT_TRUE(client
.needs_begin_frame());
1843 // NotifyReadyToCommit should trigger the commit.
1845 scheduler
->NotifyBeginMainFrameStarted();
1846 scheduler
->NotifyReadyToCommit();
1847 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1848 EXPECT_TRUE(client
.needs_begin_frame());
1850 // BeginImplFrame should prepare the draw.
1852 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1853 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1854 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1855 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1856 EXPECT_TRUE(client
.needs_begin_frame());
1859 EXPECT_FALSE(scheduler
->IsBeginRetroFrameArgsEmpty());
1860 scheduler
->DidLoseOutputSurface();
1861 EXPECT_NO_ACTION(client
);
1862 EXPECT_TRUE(scheduler
->IsBeginRetroFrameArgsEmpty());
1864 // BeginImplFrame deadline should abort drawing.
1866 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1867 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1868 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1869 EXPECT_TRUE(client
.needs_begin_frame());
1871 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
1873 client
.task_runner().RunPendingTasks();
1874 EXPECT_NO_ACTION(client
);
1878 StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource
) {
1879 FakeSchedulerClient client
;
1880 SchedulerSettings scheduler_settings
;
1881 scheduler_settings
.begin_frame_scheduling_enabled
= false;
1882 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1883 scheduler
->SetCanStart();
1884 scheduler
->SetVisible(true);
1885 scheduler
->SetCanDraw(true);
1886 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1888 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1890 EXPECT_FALSE(scheduler
->IsSyntheticBeginFrameSourceActive());
1891 scheduler
->SetNeedsCommit();
1892 EXPECT_TRUE(scheduler
->IsSyntheticBeginFrameSourceActive());
1895 client
.task_runner().RunPendingTasks(); // Run posted Tick.
1896 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1897 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1898 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1899 EXPECT_TRUE(scheduler
->IsSyntheticBeginFrameSourceActive());
1901 // NotifyReadyToCommit should trigger the commit.
1903 scheduler
->NotifyBeginMainFrameStarted();
1904 scheduler
->NotifyReadyToCommit();
1905 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1906 EXPECT_TRUE(scheduler
->IsSyntheticBeginFrameSourceActive());
1909 scheduler
->DidLoseOutputSurface();
1910 EXPECT_EQ(0, client
.num_actions_());
1911 EXPECT_FALSE(scheduler
->IsSyntheticBeginFrameSourceActive());
1914 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1915 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1916 EXPECT_FALSE(scheduler
->IsSyntheticBeginFrameSourceActive());