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/debug/trace_event.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/time/time.h"
15 #include "cc/test/begin_frame_args_test.h"
16 #include "cc/test/ordered_simple_task_runner.h"
17 #include "cc/test/scheduler_test_common.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
23 EXPECT_EQ(expected_num_actions, client.num_actions_()); \
24 if (action_index >= 0) { \
25 ASSERT_LT(action_index, client.num_actions_()) << scheduler; \
26 EXPECT_STREQ(action, client.Action(action_index)); \
28 for (int i = expected_num_actions; i < client.num_actions_(); ++i) \
29 ADD_FAILURE() << "Unexpected action: " << client.Action(i) \
30 << " with state:\n" << client.StateForAction(i); \
33 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
35 #define EXPECT_SINGLE_ACTION(action, client) \
36 EXPECT_ACTION(action, client, 0, 1)
41 class FakeSchedulerClient
;
43 void InitializeOutputSurfaceAndFirstCommit(Scheduler
* scheduler
,
44 FakeSchedulerClient
* client
);
46 class TestScheduler
: public Scheduler
{
48 static scoped_ptr
<TestScheduler
> Create(
49 SchedulerClient
* client
,
50 const SchedulerSettings
& scheduler_settings
,
51 int layer_tree_host_id
,
52 const scoped_refptr
<base::SingleThreadTaskRunner
>& impl_task_runner
) {
53 return make_scoped_ptr(new TestScheduler(
54 client
, scheduler_settings
, layer_tree_host_id
, impl_task_runner
));
57 virtual ~TestScheduler() {}
59 bool IsBeginRetroFrameArgsEmpty() const {
60 return begin_retro_frame_args_
.empty();
63 bool IsSyntheticBeginFrameSourceActive() const {
64 return synthetic_begin_frame_source_
->IsActive();
69 SchedulerClient
* client
,
70 const SchedulerSettings
& scheduler_settings
,
71 int layer_tree_host_id
,
72 const scoped_refptr
<base::SingleThreadTaskRunner
> & impl_task_runner
)
80 class FakeSchedulerClient
: public SchedulerClient
{
83 : needs_begin_frame_(false),
84 automatic_swap_ack_(true),
85 swap_contains_incomplete_tile_(false),
86 redraw_will_happen_if_update_visible_tiles_happens_(false) {
93 draw_will_happen_
= true;
94 swap_will_happen_if_draw_happens_
= true;
96 log_anticipated_draw_time_change_
= false;
99 TestScheduler
* CreateScheduler(const SchedulerSettings
& settings
) {
100 task_runner_
= new OrderedSimpleTaskRunner
;
101 scheduler_
= TestScheduler::Create(this, settings
, 0, task_runner_
);
102 return scheduler_
.get();
105 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
106 // for tests that do.
107 void set_log_anticipated_draw_time_change(bool log
) {
108 log_anticipated_draw_time_change_
= log
;
110 bool needs_begin_frame() { return needs_begin_frame_
; }
111 int num_draws() const { return num_draws_
; }
112 int num_actions_() const { return static_cast<int>(actions_
.size()); }
113 const char* Action(int i
) const { return actions_
[i
]; }
114 std::string
StateForAction(int i
) const { return states_
[i
]->ToString(); }
115 base::TimeTicks
posted_begin_impl_frame_deadline() const {
116 return posted_begin_impl_frame_deadline_
;
119 OrderedSimpleTaskRunner
& task_runner() { return *task_runner_
.get(); }
121 int ActionIndex(const char* action
) const {
122 for (size_t i
= 0; i
< actions_
.size(); i
++)
123 if (!strcmp(actions_
[i
], action
))
128 void SetSwapContainsIncompleteTile(bool contain
) {
129 swap_contains_incomplete_tile_
= contain
;
132 bool HasAction(const char* action
) const {
133 return ActionIndex(action
) >= 0;
136 void SetDrawWillHappen(bool draw_will_happen
) {
137 draw_will_happen_
= draw_will_happen
;
139 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens
) {
140 swap_will_happen_if_draw_happens_
= swap_will_happen_if_draw_happens
;
142 void SetAutomaticSwapAck(bool automatic_swap_ack
) {
143 automatic_swap_ack_
= automatic_swap_ack
;
145 void SetRedrawWillHappenIfUpdateVisibleTilesHappens(bool redraw
) {
146 redraw_will_happen_if_update_visible_tiles_happens_
= redraw
;
148 // SchedulerClient implementation.
149 virtual void SetNeedsBeginFrame(bool enable
) OVERRIDE
{
150 actions_
.push_back("SetNeedsBeginFrame");
151 states_
.push_back(scheduler_
->AsValue());
152 needs_begin_frame_
= enable
;
154 virtual void WillBeginImplFrame(const BeginFrameArgs
& args
) OVERRIDE
{
155 actions_
.push_back("WillBeginImplFrame");
156 states_
.push_back(scheduler_
->AsValue());
158 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE
{
159 actions_
.push_back("ScheduledActionSendBeginMainFrame");
160 states_
.push_back(scheduler_
->AsValue());
162 virtual void ScheduledActionAnimate() OVERRIDE
{
163 actions_
.push_back("ScheduledActionAnimate");
164 states_
.push_back(scheduler_
->AsValue());
166 virtual DrawResult
ScheduledActionDrawAndSwapIfPossible() OVERRIDE
{
167 actions_
.push_back("ScheduledActionDrawAndSwapIfPossible");
168 states_
.push_back(scheduler_
->AsValue());
171 draw_will_happen_
? DRAW_SUCCESS
: DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
;
172 bool swap_will_happen
=
173 draw_will_happen_
&& swap_will_happen_if_draw_happens_
;
174 if (swap_will_happen
) {
175 scheduler_
->DidSwapBuffers();
176 if (swap_contains_incomplete_tile_
) {
177 scheduler_
->SetSwapUsedIncompleteTile(true);
178 swap_contains_incomplete_tile_
= false;
180 scheduler_
->SetSwapUsedIncompleteTile(false);
183 if (automatic_swap_ack_
)
184 scheduler_
->DidSwapBuffersComplete();
188 virtual DrawResult
ScheduledActionDrawAndSwapForced() OVERRIDE
{
189 actions_
.push_back("ScheduledActionDrawAndSwapForced");
190 states_
.push_back(scheduler_
->AsValue());
193 virtual void ScheduledActionCommit() OVERRIDE
{
194 actions_
.push_back("ScheduledActionCommit");
195 states_
.push_back(scheduler_
->AsValue());
197 virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE
{
198 actions_
.push_back("ScheduledActionUpdateVisibleTiles");
199 states_
.push_back(scheduler_
->AsValue());
200 if (redraw_will_happen_if_update_visible_tiles_happens_
)
201 scheduler_
->SetNeedsRedraw();
203 virtual void ScheduledActionActivateSyncTree() OVERRIDE
{
204 actions_
.push_back("ScheduledActionActivateSyncTree");
205 states_
.push_back(scheduler_
->AsValue());
207 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE
{
208 actions_
.push_back("ScheduledActionBeginOutputSurfaceCreation");
209 states_
.push_back(scheduler_
->AsValue());
211 virtual void ScheduledActionManageTiles() OVERRIDE
{
212 actions_
.push_back("ScheduledActionManageTiles");
213 states_
.push_back(scheduler_
->AsValue());
215 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks
) OVERRIDE
{
216 if (log_anticipated_draw_time_change_
)
217 actions_
.push_back("DidAnticipatedDrawTimeChange");
219 virtual base::TimeDelta
DrawDurationEstimate() OVERRIDE
{
220 return base::TimeDelta();
222 virtual base::TimeDelta
BeginMainFrameToCommitDurationEstimate() OVERRIDE
{
223 return base::TimeDelta();
225 virtual base::TimeDelta
CommitToActivateDurationEstimate() OVERRIDE
{
226 return base::TimeDelta();
229 virtual void DidBeginImplFrameDeadline() OVERRIDE
{}
232 bool needs_begin_frame_
;
233 bool draw_will_happen_
;
234 bool swap_will_happen_if_draw_happens_
;
235 bool automatic_swap_ack_
;
237 bool log_anticipated_draw_time_change_
;
238 bool swap_contains_incomplete_tile_
;
239 bool redraw_will_happen_if_update_visible_tiles_happens_
;
240 base::TimeTicks posted_begin_impl_frame_deadline_
;
241 std::vector
<const char*> actions_
;
242 std::vector
<scoped_refptr
<base::debug::ConvertableToTraceFormat
> > states_
;
243 scoped_ptr
<TestScheduler
> scheduler_
;
244 scoped_refptr
<OrderedSimpleTaskRunner
> task_runner_
;
247 void InitializeOutputSurfaceAndFirstCommit(Scheduler
* scheduler
,
248 FakeSchedulerClient
* client
) {
249 bool client_initiates_begin_frame
=
250 scheduler
->settings().begin_frame_scheduling_enabled
&&
251 scheduler
->settings().throttle_frame_production
;
253 scheduler
->DidCreateAndInitializeOutputSurface();
254 scheduler
->SetNeedsCommit();
255 scheduler
->NotifyBeginMainFrameStarted();
256 scheduler
->NotifyReadyToCommit();
257 if (scheduler
->settings().impl_side_painting
)
258 scheduler
->NotifyReadyToActivate();
259 // Go through the motions to draw the commit.
260 if (client_initiates_begin_frame
)
261 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
263 client
->task_runner().RunPendingTasks(); // Run posted BeginFrame.
265 // Run the posted deadline task.
266 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
267 client
->task_runner().RunPendingTasks();
268 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
270 // We need another BeginImplFrame so Scheduler calls
271 // SetNeedsBeginFrame(false).
272 if (client_initiates_begin_frame
)
273 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
275 client
->task_runner().RunPendingTasks(); // Run posted BeginFrame.
277 // Run the posted deadline task.
278 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
279 client
->task_runner().RunPendingTasks();
280 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
283 TEST(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
284 FakeSchedulerClient client
;
285 SchedulerSettings default_scheduler_settings
;
286 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
287 scheduler
->SetCanStart();
288 scheduler
->SetVisible(true);
289 scheduler
->SetCanDraw(true);
291 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
293 scheduler
->DidCreateAndInitializeOutputSurface();
294 EXPECT_NO_ACTION(client
);
297 TEST(SchedulerTest
, RequestCommit
) {
298 FakeSchedulerClient client
;
299 SchedulerSettings scheduler_settings
;
300 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
301 scheduler
->SetCanStart();
302 scheduler
->SetVisible(true);
303 scheduler
->SetCanDraw(true);
305 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
306 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
308 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
310 scheduler
->SetNeedsCommit();
311 EXPECT_TRUE(client
.needs_begin_frame());
312 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
315 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
316 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
317 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
318 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
319 EXPECT_TRUE(client
.needs_begin_frame());
322 // If we don't swap on the deadline, we wait for the next BeginFrame.
323 client
.task_runner().RunPendingTasks(); // Run posted deadline.
324 EXPECT_NO_ACTION(client
);
325 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
326 EXPECT_TRUE(client
.needs_begin_frame());
329 // NotifyReadyToCommit should trigger the commit.
330 scheduler
->NotifyBeginMainFrameStarted();
331 scheduler
->NotifyReadyToCommit();
332 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
333 EXPECT_TRUE(client
.needs_begin_frame());
336 // BeginImplFrame should prepare the draw.
337 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
338 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
339 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
340 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
341 EXPECT_TRUE(client
.needs_begin_frame());
344 // BeginImplFrame deadline should draw.
345 client
.task_runner().RunPendingTasks(); // Run posted deadline.
346 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 1);
347 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
348 EXPECT_TRUE(client
.needs_begin_frame());
351 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
352 // to avoid excessive toggles.
353 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
354 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
355 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
358 client
.task_runner().RunPendingTasks(); // Run posted deadline.
359 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
360 EXPECT_FALSE(client
.needs_begin_frame());
364 TEST(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
365 FakeSchedulerClient client
;
366 SchedulerSettings scheduler_settings
;
367 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
368 scheduler
->SetCanStart();
369 scheduler
->SetVisible(true);
370 scheduler
->SetCanDraw(true);
372 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
373 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
376 // SetNeedsCommit should begin the frame.
377 scheduler
->SetNeedsCommit();
378 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
381 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
382 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
383 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
384 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
386 EXPECT_TRUE(client
.needs_begin_frame());
389 // Now SetNeedsCommit again. Calling here means we need a second commit.
390 scheduler
->SetNeedsCommit();
391 EXPECT_EQ(client
.num_actions_(), 0);
394 // Finish the first commit.
395 scheduler
->NotifyBeginMainFrameStarted();
396 scheduler
->NotifyReadyToCommit();
397 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
398 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
400 client
.task_runner().RunPendingTasks(); // Run posted deadline.
401 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
402 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
403 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
405 // Because we just swapped, the Scheduler should also request the next
406 // BeginImplFrame from the OutputSurface.
407 EXPECT_TRUE(client
.needs_begin_frame());
409 // Since another commit is needed, the next BeginImplFrame should initiate
410 // the second commit.
411 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
412 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
413 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
414 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
417 // Finishing the commit before the deadline should post a new deadline task
418 // to trigger the deadline early.
419 scheduler
->NotifyBeginMainFrameStarted();
420 scheduler
->NotifyReadyToCommit();
421 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
422 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
424 client
.task_runner().RunPendingTasks(); // Run posted deadline.
425 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
426 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
427 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
428 EXPECT_TRUE(client
.needs_begin_frame());
431 // On the next BeginImplFrame, verify we go back to a quiescent state and
432 // no longer request BeginImplFrames.
433 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
434 client
.task_runner().RunPendingTasks(); // Run posted deadline.
435 EXPECT_FALSE(client
.needs_begin_frame());
439 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
441 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE
{}
442 virtual DrawResult
ScheduledActionDrawAndSwapIfPossible()
444 // Only SetNeedsRedraw the first time this is called
446 scheduler_
->SetNeedsRedraw();
447 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
450 virtual DrawResult
ScheduledActionDrawAndSwapForced() OVERRIDE
{
455 virtual void ScheduledActionCommit() OVERRIDE
{}
456 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE
{}
457 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks
) OVERRIDE
{}
460 // Tests for two different situations:
461 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
462 // a ScheduledActionDrawAndSwap
463 // 2. the scheduler drawing twice inside a single tick
464 TEST(SchedulerTest
, RequestRedrawInsideDraw
) {
465 SchedulerClientThatsetNeedsDrawInsideDraw client
;
466 SchedulerSettings default_scheduler_settings
;
467 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
468 scheduler
->SetCanStart();
469 scheduler
->SetVisible(true);
470 scheduler
->SetCanDraw(true);
471 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
474 scheduler
->SetNeedsRedraw();
475 EXPECT_TRUE(scheduler
->RedrawPending());
476 EXPECT_TRUE(client
.needs_begin_frame());
477 EXPECT_EQ(0, client
.num_draws());
479 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
480 client
.task_runner().RunPendingTasks(); // Run posted deadline.
481 EXPECT_EQ(1, client
.num_draws());
482 EXPECT_TRUE(scheduler
->RedrawPending());
483 EXPECT_TRUE(client
.needs_begin_frame());
485 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
486 client
.task_runner().RunPendingTasks(); // Run posted deadline.
487 EXPECT_EQ(2, client
.num_draws());
488 EXPECT_FALSE(scheduler
->RedrawPending());
489 EXPECT_TRUE(client
.needs_begin_frame());
491 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
493 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
494 client
.task_runner().RunPendingTasks(); // Run posted deadline.
495 EXPECT_EQ(2, client
.num_draws());
496 EXPECT_FALSE(scheduler
->RedrawPending());
497 EXPECT_FALSE(client
.needs_begin_frame());
500 // Test that requesting redraw inside a failed draw doesn't lose the request.
501 TEST(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
502 SchedulerClientThatsetNeedsDrawInsideDraw client
;
503 SchedulerSettings default_scheduler_settings
;
504 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
505 scheduler
->SetCanStart();
506 scheduler
->SetVisible(true);
507 scheduler
->SetCanDraw(true);
508 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
511 client
.SetDrawWillHappen(false);
513 scheduler
->SetNeedsRedraw();
514 EXPECT_TRUE(scheduler
->RedrawPending());
515 EXPECT_TRUE(client
.needs_begin_frame());
516 EXPECT_EQ(0, client
.num_draws());
519 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
520 client
.task_runner().RunPendingTasks(); // Run posted deadline.
521 EXPECT_EQ(1, client
.num_draws());
523 // We have a commit pending and the draw failed, and we didn't lose the redraw
525 EXPECT_TRUE(scheduler
->CommitPending());
526 EXPECT_TRUE(scheduler
->RedrawPending());
527 EXPECT_TRUE(client
.needs_begin_frame());
529 // Fail the draw again.
530 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
531 client
.task_runner().RunPendingTasks(); // Run posted deadline.
532 EXPECT_EQ(2, client
.num_draws());
533 EXPECT_TRUE(scheduler
->CommitPending());
534 EXPECT_TRUE(scheduler
->RedrawPending());
535 EXPECT_TRUE(client
.needs_begin_frame());
537 // Draw successfully.
538 client
.SetDrawWillHappen(true);
539 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
540 client
.task_runner().RunPendingTasks(); // Run posted deadline.
541 EXPECT_EQ(3, client
.num_draws());
542 EXPECT_TRUE(scheduler
->CommitPending());
543 EXPECT_FALSE(scheduler
->RedrawPending());
544 EXPECT_TRUE(client
.needs_begin_frame());
547 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
549 SchedulerClientThatSetNeedsCommitInsideDraw()
550 : set_needs_commit_on_next_draw_(false) {}
552 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE
{}
553 virtual DrawResult
ScheduledActionDrawAndSwapIfPossible()
555 // Only SetNeedsCommit the first time this is called
556 if (set_needs_commit_on_next_draw_
) {
557 scheduler_
->SetNeedsCommit();
558 set_needs_commit_on_next_draw_
= false;
560 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
563 virtual DrawResult
ScheduledActionDrawAndSwapForced() OVERRIDE
{
568 virtual void ScheduledActionCommit() OVERRIDE
{}
569 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE
{}
570 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks
) OVERRIDE
{}
572 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
575 bool set_needs_commit_on_next_draw_
;
578 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
579 // happen inside a ScheduledActionDrawAndSwap
580 TEST(SchedulerTest
, RequestCommitInsideDraw
) {
581 SchedulerClientThatSetNeedsCommitInsideDraw client
;
582 SchedulerSettings default_scheduler_settings
;
583 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
584 scheduler
->SetCanStart();
585 scheduler
->SetVisible(true);
586 scheduler
->SetCanDraw(true);
587 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
590 EXPECT_FALSE(client
.needs_begin_frame());
591 scheduler
->SetNeedsRedraw();
592 EXPECT_TRUE(scheduler
->RedrawPending());
593 EXPECT_EQ(0, client
.num_draws());
594 EXPECT_TRUE(client
.needs_begin_frame());
596 client
.SetNeedsCommitOnNextDraw();
597 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
598 client
.SetNeedsCommitOnNextDraw();
599 client
.task_runner().RunPendingTasks(); // Run posted deadline.
600 EXPECT_EQ(1, client
.num_draws());
601 EXPECT_TRUE(scheduler
->CommitPending());
602 EXPECT_TRUE(client
.needs_begin_frame());
603 scheduler
->NotifyBeginMainFrameStarted();
604 scheduler
->NotifyReadyToCommit();
606 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
607 client
.task_runner().RunPendingTasks(); // Run posted deadline.
608 EXPECT_EQ(2, client
.num_draws());
610 EXPECT_FALSE(scheduler
->RedrawPending());
611 EXPECT_FALSE(scheduler
->CommitPending());
612 EXPECT_TRUE(client
.needs_begin_frame());
614 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
616 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
617 client
.task_runner().RunPendingTasks(); // Run posted deadline.
618 EXPECT_EQ(2, client
.num_draws());
619 EXPECT_FALSE(scheduler
->RedrawPending());
620 EXPECT_FALSE(scheduler
->CommitPending());
621 EXPECT_FALSE(client
.needs_begin_frame());
624 // Tests that when a draw fails then the pending commit should not be dropped.
625 TEST(SchedulerTest
, RequestCommitInsideFailedDraw
) {
626 SchedulerClientThatsetNeedsDrawInsideDraw client
;
627 SchedulerSettings default_scheduler_settings
;
628 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
629 scheduler
->SetCanStart();
630 scheduler
->SetVisible(true);
631 scheduler
->SetCanDraw(true);
632 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
635 client
.SetDrawWillHappen(false);
637 scheduler
->SetNeedsRedraw();
638 EXPECT_TRUE(scheduler
->RedrawPending());
639 EXPECT_TRUE(client
.needs_begin_frame());
640 EXPECT_EQ(0, client
.num_draws());
643 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
644 client
.task_runner().RunPendingTasks(); // Run posted deadline.
645 EXPECT_EQ(1, client
.num_draws());
647 // We have a commit pending and the draw failed, and we didn't lose the commit
649 EXPECT_TRUE(scheduler
->CommitPending());
650 EXPECT_TRUE(scheduler
->RedrawPending());
651 EXPECT_TRUE(client
.needs_begin_frame());
653 // Fail the draw again.
654 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
656 client
.task_runner().RunPendingTasks(); // Run posted deadline.
657 EXPECT_EQ(2, client
.num_draws());
658 EXPECT_TRUE(scheduler
->CommitPending());
659 EXPECT_TRUE(scheduler
->RedrawPending());
660 EXPECT_TRUE(client
.needs_begin_frame());
662 // Draw successfully.
663 client
.SetDrawWillHappen(true);
664 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
665 client
.task_runner().RunPendingTasks(); // Run posted deadline.
666 EXPECT_EQ(3, client
.num_draws());
667 EXPECT_TRUE(scheduler
->CommitPending());
668 EXPECT_FALSE(scheduler
->RedrawPending());
669 EXPECT_TRUE(client
.needs_begin_frame());
672 TEST(SchedulerTest
, NoSwapWhenDrawFails
) {
673 SchedulerClientThatSetNeedsCommitInsideDraw client
;
674 SchedulerSettings default_scheduler_settings
;
675 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
676 scheduler
->SetCanStart();
677 scheduler
->SetVisible(true);
678 scheduler
->SetCanDraw(true);
679 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
682 scheduler
->SetNeedsRedraw();
683 EXPECT_TRUE(scheduler
->RedrawPending());
684 EXPECT_TRUE(client
.needs_begin_frame());
685 EXPECT_EQ(0, client
.num_draws());
687 // Draw successfully, this starts a new frame.
688 client
.SetNeedsCommitOnNextDraw();
689 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
690 client
.task_runner().RunPendingTasks(); // Run posted deadline.
691 EXPECT_EQ(1, client
.num_draws());
693 scheduler
->SetNeedsRedraw();
694 EXPECT_TRUE(scheduler
->RedrawPending());
695 EXPECT_TRUE(client
.needs_begin_frame());
697 // Fail to draw, this should not start a frame.
698 client
.SetDrawWillHappen(false);
699 client
.SetNeedsCommitOnNextDraw();
700 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
701 client
.task_runner().RunPendingTasks(); // Run posted deadline.
702 EXPECT_EQ(2, client
.num_draws());
705 class SchedulerClientNeedsManageTilesInDraw
: public FakeSchedulerClient
{
707 virtual DrawResult
ScheduledActionDrawAndSwapIfPossible()
709 scheduler_
->SetNeedsManageTiles();
710 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
714 // Test manage tiles is independant of draws.
715 TEST(SchedulerTest
, ManageTiles
) {
716 SchedulerClientNeedsManageTilesInDraw client
;
717 SchedulerSettings default_scheduler_settings
;
718 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
719 scheduler
->SetCanStart();
720 scheduler
->SetVisible(true);
721 scheduler
->SetCanDraw(true);
722 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
724 // Request both draw and manage tiles. ManageTiles shouldn't
725 // be trigged until BeginImplFrame.
727 scheduler
->SetNeedsManageTiles();
728 scheduler
->SetNeedsRedraw();
729 EXPECT_TRUE(scheduler
->RedrawPending());
730 EXPECT_TRUE(scheduler
->ManageTilesPending());
731 EXPECT_TRUE(client
.needs_begin_frame());
732 EXPECT_EQ(0, client
.num_draws());
733 EXPECT_FALSE(client
.HasAction("ScheduledActionManageTiles"));
734 EXPECT_FALSE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
736 // We have no immediate actions to perform, so the BeginImplFrame should post
737 // the deadline task.
739 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
740 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
741 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
742 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
744 // On the deadline, he actions should have occured in the right order.
746 client
.task_runner().RunPendingTasks(); // Run posted deadline.
747 EXPECT_EQ(1, client
.num_draws());
748 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
749 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
750 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
751 client
.ActionIndex("ScheduledActionManageTiles"));
752 EXPECT_FALSE(scheduler
->RedrawPending());
753 EXPECT_FALSE(scheduler
->ManageTilesPending());
754 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
756 // Request a draw. We don't need a ManageTiles yet.
758 scheduler
->SetNeedsRedraw();
759 EXPECT_TRUE(scheduler
->RedrawPending());
760 EXPECT_FALSE(scheduler
->ManageTilesPending());
761 EXPECT_TRUE(client
.needs_begin_frame());
762 EXPECT_EQ(0, client
.num_draws());
764 // We have no immediate actions to perform, so the BeginImplFrame should post
765 // the deadline task.
767 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
768 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
769 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
770 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
772 // Draw. The draw will trigger SetNeedsManageTiles, and
773 // then the ManageTiles action will be triggered after the Draw.
774 // Afterwards, neither a draw nor ManageTiles are pending.
776 client
.task_runner().RunPendingTasks(); // Run posted deadline.
777 EXPECT_EQ(1, client
.num_draws());
778 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
779 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
780 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
781 client
.ActionIndex("ScheduledActionManageTiles"));
782 EXPECT_FALSE(scheduler
->RedrawPending());
783 EXPECT_FALSE(scheduler
->ManageTilesPending());
784 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
786 // We need a BeginImplFrame where we don't swap to go idle.
788 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
789 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
790 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
792 client
.task_runner().RunPendingTasks(); // Run posted deadline.
793 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
794 EXPECT_FALSE(client
.needs_begin_frame());
795 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
796 EXPECT_EQ(0, client
.num_draws());
798 // Now trigger a ManageTiles outside of a draw. We will then need
799 // a begin-frame for the ManageTiles, but we don't need a draw.
801 EXPECT_FALSE(client
.needs_begin_frame());
802 scheduler
->SetNeedsManageTiles();
803 EXPECT_TRUE(client
.needs_begin_frame());
804 EXPECT_TRUE(scheduler
->ManageTilesPending());
805 EXPECT_FALSE(scheduler
->RedrawPending());
807 // BeginImplFrame. There will be no draw, only ManageTiles.
809 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
810 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
811 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
813 client
.task_runner().RunPendingTasks(); // Run posted deadline.
814 EXPECT_EQ(0, client
.num_draws());
815 EXPECT_FALSE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
816 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
817 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
820 // Test that ManageTiles only happens once per frame. If an external caller
821 // initiates it, then the state machine should not ManageTiles on that frame.
822 TEST(SchedulerTest
, ManageTilesOncePerFrame
) {
823 FakeSchedulerClient client
;
824 SchedulerSettings default_scheduler_settings
;
825 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
826 scheduler
->SetCanStart();
827 scheduler
->SetVisible(true);
828 scheduler
->SetCanDraw(true);
829 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
831 // If DidManageTiles during a frame, then ManageTiles should not occur again.
832 scheduler
->SetNeedsManageTiles();
833 scheduler
->SetNeedsRedraw();
835 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
836 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
837 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
838 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
840 EXPECT_TRUE(scheduler
->ManageTilesPending());
841 scheduler
->DidManageTiles(); // An explicit ManageTiles.
842 EXPECT_FALSE(scheduler
->ManageTilesPending());
845 client
.task_runner().RunPendingTasks(); // Run posted deadline.
846 EXPECT_EQ(1, client
.num_draws());
847 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
848 EXPECT_FALSE(client
.HasAction("ScheduledActionManageTiles"));
849 EXPECT_FALSE(scheduler
->RedrawPending());
850 EXPECT_FALSE(scheduler
->ManageTilesPending());
851 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
853 // Next frame without DidManageTiles should ManageTiles with draw.
854 scheduler
->SetNeedsManageTiles();
855 scheduler
->SetNeedsRedraw();
857 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
858 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
859 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
860 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
863 client
.task_runner().RunPendingTasks(); // Run posted deadline.
864 EXPECT_EQ(1, client
.num_draws());
865 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
866 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
867 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
868 client
.ActionIndex("ScheduledActionManageTiles"));
869 EXPECT_FALSE(scheduler
->RedrawPending());
870 EXPECT_FALSE(scheduler
->ManageTilesPending());
871 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
872 scheduler
->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
874 // If we get another DidManageTiles within the same frame, we should
875 // not ManageTiles on the next frame.
876 scheduler
->DidManageTiles(); // An explicit ManageTiles.
877 scheduler
->SetNeedsManageTiles();
878 scheduler
->SetNeedsRedraw();
880 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
881 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
882 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
883 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
885 EXPECT_TRUE(scheduler
->ManageTilesPending());
888 client
.task_runner().RunPendingTasks(); // Run posted deadline.
889 EXPECT_EQ(1, client
.num_draws());
890 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
891 EXPECT_FALSE(client
.HasAction("ScheduledActionManageTiles"));
892 EXPECT_FALSE(scheduler
->RedrawPending());
893 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
895 // If we get another DidManageTiles, we should not ManageTiles on the next
896 // frame. This verifies we don't alternate calling ManageTiles once and twice.
897 EXPECT_TRUE(scheduler
->ManageTilesPending());
898 scheduler
->DidManageTiles(); // An explicit ManageTiles.
899 EXPECT_FALSE(scheduler
->ManageTilesPending());
900 scheduler
->SetNeedsManageTiles();
901 scheduler
->SetNeedsRedraw();
903 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
904 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
905 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
906 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
908 EXPECT_TRUE(scheduler
->ManageTilesPending());
911 client
.task_runner().RunPendingTasks(); // Run posted deadline.
912 EXPECT_EQ(1, client
.num_draws());
913 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
914 EXPECT_FALSE(client
.HasAction("ScheduledActionManageTiles"));
915 EXPECT_FALSE(scheduler
->RedrawPending());
916 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
918 // Next frame without DidManageTiles should ManageTiles with draw.
919 scheduler
->SetNeedsManageTiles();
920 scheduler
->SetNeedsRedraw();
922 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
923 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
924 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
925 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
928 client
.task_runner().RunPendingTasks(); // Run posted deadline.
929 EXPECT_EQ(1, client
.num_draws());
930 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
931 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
932 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
933 client
.ActionIndex("ScheduledActionManageTiles"));
934 EXPECT_FALSE(scheduler
->RedrawPending());
935 EXPECT_FALSE(scheduler
->ManageTilesPending());
936 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
937 scheduler
->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
940 TEST(SchedulerTest
, ShouldUpdateVisibleTiles
) {
941 FakeSchedulerClient client
;
942 SchedulerSettings scheduler_settings
;
943 scheduler_settings
.impl_side_painting
= true;
944 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
945 scheduler
->SetCanStart();
946 scheduler
->SetVisible(true);
947 scheduler
->SetCanDraw(true);
948 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
950 client
.SetRedrawWillHappenIfUpdateVisibleTilesHappens(true);
952 // SetNeedsCommit should begin the frame.
954 scheduler
->SetNeedsCommit();
955 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
958 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
959 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
960 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
961 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
964 scheduler
->NotifyBeginMainFrameStarted();
965 scheduler
->NotifyReadyToCommit();
966 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
969 scheduler
->NotifyReadyToActivate();
970 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client
);
973 client
.SetSwapContainsIncompleteTile(true);
974 client
.task_runner().RunPendingTasks(); // Run posted deadline.
975 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
976 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
977 EXPECT_FALSE(scheduler
->RedrawPending());
980 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
981 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
982 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
985 client
.task_runner().RunPendingTasks(); // Run posted deadline.
986 EXPECT_ACTION("ScheduledActionUpdateVisibleTiles", client
, 0, 3);
987 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 3);
988 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 2, 3);
991 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
992 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
993 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
995 // No more UpdateVisibleTiles().
997 client
.task_runner().RunPendingTasks(); // Run posted deadline.
998 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
999 EXPECT_FALSE(client
.needs_begin_frame());
1002 TEST(SchedulerTest
, TriggerBeginFrameDeadlineEarly
) {
1003 SchedulerClientNeedsManageTilesInDraw client
;
1004 SchedulerSettings default_scheduler_settings
;
1005 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
1006 scheduler
->SetCanStart();
1007 scheduler
->SetVisible(true);
1008 scheduler
->SetCanDraw(true);
1009 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1012 scheduler
->SetNeedsRedraw();
1013 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1015 // The deadline should be zero since there is no work other than drawing
1017 EXPECT_EQ(base::TimeTicks(), client
.posted_begin_impl_frame_deadline());
1020 class SchedulerClientWithFixedEstimates
: public FakeSchedulerClient
{
1022 SchedulerClientWithFixedEstimates(
1023 base::TimeDelta draw_duration
,
1024 base::TimeDelta begin_main_frame_to_commit_duration
,
1025 base::TimeDelta commit_to_activate_duration
)
1026 : draw_duration_(draw_duration
),
1027 begin_main_frame_to_commit_duration_(
1028 begin_main_frame_to_commit_duration
),
1029 commit_to_activate_duration_(commit_to_activate_duration
) {}
1031 virtual base::TimeDelta
DrawDurationEstimate() OVERRIDE
{
1032 return draw_duration_
;
1034 virtual base::TimeDelta
BeginMainFrameToCommitDurationEstimate() OVERRIDE
{
1035 return begin_main_frame_to_commit_duration_
;
1037 virtual base::TimeDelta
CommitToActivateDurationEstimate() OVERRIDE
{
1038 return commit_to_activate_duration_
;
1042 base::TimeDelta draw_duration_
;
1043 base::TimeDelta begin_main_frame_to_commit_duration_
;
1044 base::TimeDelta commit_to_activate_duration_
;
1047 void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms
,
1048 int64 commit_to_activate_estimate_in_ms
,
1049 bool impl_latency_takes_priority
,
1050 bool should_send_begin_main_frame
) {
1051 // Set up client with specified estimates (draw duration is set to 1).
1052 SchedulerClientWithFixedEstimates
client(
1053 base::TimeDelta::FromMilliseconds(1),
1054 base::TimeDelta::FromMilliseconds(
1055 begin_main_frame_to_commit_estimate_in_ms
),
1056 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms
));
1057 SchedulerSettings default_scheduler_settings
;
1058 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
1059 scheduler
->SetCanStart();
1060 scheduler
->SetVisible(true);
1061 scheduler
->SetCanDraw(true);
1062 scheduler
->SetImplLatencyTakesPriority(impl_latency_takes_priority
);
1063 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1065 // Impl thread hits deadline before commit finishes.
1067 scheduler
->SetNeedsCommit();
1068 EXPECT_FALSE(scheduler
->MainThreadIsInHighLatencyMode());
1069 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1070 EXPECT_FALSE(scheduler
->MainThreadIsInHighLatencyMode());
1071 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1072 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1073 scheduler
->NotifyBeginMainFrameStarted();
1074 scheduler
->NotifyReadyToCommit();
1075 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1076 EXPECT_TRUE(client
.HasAction("ScheduledActionSendBeginMainFrame"));
1079 scheduler
->SetNeedsCommit();
1080 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1081 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1082 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1083 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1084 EXPECT_EQ(scheduler
->MainThreadIsInHighLatencyMode(),
1085 should_send_begin_main_frame
);
1086 EXPECT_EQ(client
.HasAction("ScheduledActionSendBeginMainFrame"),
1087 should_send_begin_main_frame
);
1091 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline
) {
1092 // Set up client so that estimates indicate that we can commit and activate
1093 // before the deadline (~8ms by default).
1094 MainFrameInHighLatencyMode(1, 1, false, false);
1097 TEST(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong
) {
1098 // Set up client so that estimates indicate that the commit cannot finish
1099 // before the deadline (~8ms by default).
1100 MainFrameInHighLatencyMode(10, 1, false, true);
1103 TEST(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong
) {
1104 // Set up client so that estimates indicate that the activate cannot finish
1105 // before the deadline (~8ms by default).
1106 MainFrameInHighLatencyMode(1, 10, false, true);
1109 TEST(SchedulerTest
, NotSkipMainFrameInPreferImplLatencyMode
) {
1110 // Set up client so that estimates indicate that we can commit and activate
1111 // before the deadline (~8ms by default), but also enable impl latency takes
1113 MainFrameInHighLatencyMode(1, 1, true, true);
1116 TEST(SchedulerTest
, PollForCommitCompletion
) {
1117 // Since we are simulating a long commit, set up a client with draw duration
1118 // estimates that prevent skipping main frames to get to low latency mode.
1119 SchedulerClientWithFixedEstimates
client(
1120 base::TimeDelta::FromMilliseconds(1),
1121 base::TimeDelta::FromMilliseconds(32),
1122 base::TimeDelta::FromMilliseconds(32));
1123 client
.set_log_anticipated_draw_time_change(true);
1124 SchedulerSettings default_scheduler_settings
;
1125 TestScheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
1127 scheduler
->SetCanDraw(true);
1128 scheduler
->SetCanStart();
1129 scheduler
->SetVisible(true);
1130 scheduler
->DidCreateAndInitializeOutputSurface();
1132 scheduler
->SetNeedsCommit();
1133 EXPECT_TRUE(scheduler
->CommitPending());
1134 scheduler
->NotifyBeginMainFrameStarted();
1135 scheduler
->NotifyReadyToCommit();
1136 scheduler
->SetNeedsRedraw();
1138 BeginFrameArgs frame_args
= CreateBeginFrameArgsForTesting();
1139 frame_args
.interval
= base::TimeDelta::FromMilliseconds(1000);
1140 scheduler
->BeginFrame(frame_args
);
1142 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1143 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1144 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1146 scheduler
->DidSwapBuffers();
1147 scheduler
->DidSwapBuffersComplete();
1149 // At this point, we've drawn a frame. Start another commit, but hold off on
1150 // the NotifyReadyToCommit for now.
1151 EXPECT_FALSE(scheduler
->CommitPending());
1152 scheduler
->SetNeedsCommit();
1153 scheduler
->BeginFrame(frame_args
);
1154 EXPECT_TRUE(scheduler
->CommitPending());
1156 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1157 // blocking on the renderer.
1158 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1159 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1160 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1161 scheduler
->DidSwapBuffers();
1163 // Spin the event loop a few times and make sure we get more
1164 // DidAnticipateDrawTimeChange calls every time.
1165 int actions_so_far
= client
.num_actions_();
1167 // Does three iterations to make sure that the timer is properly repeating.
1168 for (int i
= 0; i
< 3; ++i
) {
1169 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1170 client
.task_runner().NextPendingTaskDelay().InMicroseconds())
1171 << scheduler
->AsValue()->ToString();
1172 client
.task_runner().RunPendingTasks();
1173 EXPECT_GT(client
.num_actions_(), actions_so_far
);
1174 EXPECT_STREQ(client
.Action(client
.num_actions_() - 1),
1175 "DidAnticipatedDrawTimeChange");
1176 actions_so_far
= client
.num_actions_();
1179 // Do the same thing after BeginMainFrame starts but still before activation.
1180 scheduler
->NotifyBeginMainFrameStarted();
1181 for (int i
= 0; i
< 3; ++i
) {
1182 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1183 client
.task_runner().NextPendingTaskDelay().InMicroseconds())
1184 << scheduler
->AsValue()->ToString();
1185 client
.task_runner().RunPendingTasks();
1186 EXPECT_GT(client
.num_actions_(), actions_so_far
);
1187 EXPECT_STREQ(client
.Action(client
.num_actions_() - 1),
1188 "DidAnticipatedDrawTimeChange");
1189 actions_so_far
= client
.num_actions_();
1193 TEST(SchedulerTest
, BeginRetroFrame
) {
1194 FakeSchedulerClient client
;
1195 SchedulerSettings scheduler_settings
;
1196 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1197 scheduler
->SetCanStart();
1198 scheduler
->SetVisible(true);
1199 scheduler
->SetCanDraw(true);
1200 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1202 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1204 scheduler
->SetNeedsCommit();
1205 EXPECT_TRUE(client
.needs_begin_frame());
1206 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1209 // Create a BeginFrame with a long deadline to avoid race conditions.
1210 // This is the first BeginFrame, which will be handled immediately.
1211 BeginFrameArgs args
= CreateBeginFrameArgsForTesting();
1212 args
.deadline
+= base::TimeDelta::FromHours(1);
1213 scheduler
->BeginFrame(args
);
1214 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1215 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1216 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1217 EXPECT_TRUE(client
.needs_begin_frame());
1220 // Queue BeginFrames while we are still handling the previous BeginFrame.
1221 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1222 scheduler
->BeginFrame(args
);
1223 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1224 scheduler
->BeginFrame(args
);
1226 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1227 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1228 EXPECT_NO_ACTION(client
);
1229 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1230 EXPECT_TRUE(client
.needs_begin_frame());
1233 // NotifyReadyToCommit should trigger the commit.
1234 scheduler
->NotifyBeginMainFrameStarted();
1235 scheduler
->NotifyReadyToCommit();
1236 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1237 EXPECT_TRUE(client
.needs_begin_frame());
1240 // BeginImplFrame should prepare the draw.
1241 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1242 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1243 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1244 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1245 EXPECT_TRUE(client
.needs_begin_frame());
1248 // BeginImplFrame deadline should draw.
1249 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1250 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 1);
1251 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1252 EXPECT_TRUE(client
.needs_begin_frame());
1255 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1256 // to avoid excessive toggles.
1257 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1258 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1259 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1262 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1263 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1264 EXPECT_FALSE(client
.needs_begin_frame());
1268 TEST(SchedulerTest
, BeginRetroFrame_SwapThrottled
) {
1269 FakeSchedulerClient client
;
1270 SchedulerSettings scheduler_settings
;
1271 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1272 scheduler
->SetCanStart();
1273 scheduler
->SetVisible(true);
1274 scheduler
->SetCanDraw(true);
1275 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1277 // To test swap ack throttling, this test disables automatic swap acks.
1278 scheduler
->SetMaxSwapsPending(1);
1279 client
.SetAutomaticSwapAck(false);
1281 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1283 scheduler
->SetNeedsCommit();
1284 EXPECT_TRUE(client
.needs_begin_frame());
1285 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1288 // Create a BeginFrame with a long deadline to avoid race conditions.
1289 // This is the first BeginFrame, which will be handled immediately.
1290 BeginFrameArgs args
= CreateBeginFrameArgsForTesting();
1291 args
.deadline
+= base::TimeDelta::FromHours(1);
1292 scheduler
->BeginFrame(args
);
1293 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1294 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1295 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1296 EXPECT_TRUE(client
.needs_begin_frame());
1299 // Queue BeginFrame while we are still handling the previous BeginFrame.
1300 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1301 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1302 scheduler
->BeginFrame(args
);
1303 EXPECT_NO_ACTION(client
);
1304 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1307 // NotifyReadyToCommit should trigger the pending commit and draw.
1308 scheduler
->NotifyBeginMainFrameStarted();
1309 scheduler
->NotifyReadyToCommit();
1310 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1311 EXPECT_TRUE(client
.needs_begin_frame());
1314 // Swapping will put us into a swap throttled state.
1315 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1316 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1317 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1318 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1319 EXPECT_TRUE(client
.needs_begin_frame());
1322 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1323 // but not a BeginMainFrame or draw.
1324 scheduler
->SetNeedsCommit();
1325 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1326 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 1);
1327 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1328 EXPECT_TRUE(client
.needs_begin_frame());
1331 // Queue BeginFrame while we are still handling the previous BeginFrame.
1332 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1333 scheduler
->BeginFrame(args
);
1334 EXPECT_NO_ACTION(client
);
1335 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1336 EXPECT_TRUE(client
.needs_begin_frame());
1339 // Take us out of a swap throttled state.
1340 scheduler
->DidSwapBuffersComplete();
1341 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 1);
1342 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1343 EXPECT_TRUE(client
.needs_begin_frame());
1346 // BeginImplFrame deadline should draw.
1347 scheduler
->SetNeedsRedraw();
1348 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1349 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1350 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1351 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1352 EXPECT_TRUE(client
.needs_begin_frame());
1356 void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled
,
1357 bool throttle_frame_production
) {
1358 FakeSchedulerClient client
;
1359 SchedulerSettings scheduler_settings
;
1360 scheduler_settings
.begin_frame_scheduling_enabled
=
1361 begin_frame_scheduling_enabled
;
1362 scheduler_settings
.throttle_frame_production
= throttle_frame_production
;
1363 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1364 scheduler
->SetCanStart();
1365 scheduler
->SetVisible(true);
1366 scheduler
->SetCanDraw(true);
1367 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1369 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1370 // without calling SetNeedsBeginFrame.
1372 scheduler
->SetNeedsCommit();
1373 EXPECT_FALSE(client
.needs_begin_frame());
1374 EXPECT_NO_ACTION(client
);
1377 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1378 // own BeginFrame tasks.
1379 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1380 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1381 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1382 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1383 EXPECT_FALSE(client
.needs_begin_frame());
1386 // If we don't swap on the deadline, we wait for the next BeginFrame.
1387 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1388 EXPECT_NO_ACTION(client
);
1389 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1390 EXPECT_FALSE(client
.needs_begin_frame());
1393 // NotifyReadyToCommit should trigger the commit.
1394 scheduler
->NotifyBeginMainFrameStarted();
1395 scheduler
->NotifyReadyToCommit();
1396 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1397 EXPECT_FALSE(client
.needs_begin_frame());
1400 // BeginImplFrame should prepare the draw.
1401 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1402 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1403 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1404 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1405 EXPECT_FALSE(client
.needs_begin_frame());
1408 // BeginImplFrame deadline should draw.
1409 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1410 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 1);
1411 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1412 EXPECT_FALSE(client
.needs_begin_frame());
1415 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1416 // to avoid excessive toggles.
1417 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1418 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1419 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1422 // Make sure SetNeedsBeginFrame isn't called on the client
1423 // when the BeginFrame is no longer needed.
1424 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1425 EXPECT_NO_ACTION(client
);
1426 EXPECT_FALSE(client
.needs_begin_frame());
1430 // See: http://crbug.com/380889
1431 TEST(SchedulerTest
, DISABLED_SyntheticBeginFrames
) {
1432 bool begin_frame_scheduling_enabled
= false;
1433 bool throttle_frame_production
= true;
1434 BeginFramesNotFromClient(begin_frame_scheduling_enabled
,
1435 throttle_frame_production
);
1438 TEST(SchedulerTest
, VSyncThrottlingDisabled
) {
1439 bool begin_frame_scheduling_enabled
= true;
1440 bool throttle_frame_production
= false;
1441 BeginFramesNotFromClient(begin_frame_scheduling_enabled
,
1442 throttle_frame_production
);
1445 // See: http://crbug.com/380889
1446 TEST(SchedulerTest
, DISABLED_SyntheticBeginFrames_And_VSyncThrottlingDisabled
) {
1447 bool begin_frame_scheduling_enabled
= false;
1448 bool throttle_frame_production
= false;
1449 BeginFramesNotFromClient(begin_frame_scheduling_enabled
,
1450 throttle_frame_production
);
1453 void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled
,
1454 bool throttle_frame_production
) {
1455 FakeSchedulerClient client
;
1456 SchedulerSettings scheduler_settings
;
1457 scheduler_settings
.begin_frame_scheduling_enabled
=
1458 begin_frame_scheduling_enabled
;
1459 scheduler_settings
.throttle_frame_production
= throttle_frame_production
;
1460 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1461 scheduler
->SetCanStart();
1462 scheduler
->SetVisible(true);
1463 scheduler
->SetCanDraw(true);
1464 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1466 // To test swap ack throttling, this test disables automatic swap acks.
1467 scheduler
->SetMaxSwapsPending(1);
1468 client
.SetAutomaticSwapAck(false);
1470 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1472 scheduler
->SetNeedsCommit();
1473 EXPECT_FALSE(client
.needs_begin_frame());
1474 EXPECT_NO_ACTION(client
);
1477 // Trigger the first BeginImplFrame and BeginMainFrame
1478 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1479 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1480 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1481 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1482 EXPECT_FALSE(client
.needs_begin_frame());
1485 // NotifyReadyToCommit should trigger the pending commit and draw.
1486 scheduler
->NotifyBeginMainFrameStarted();
1487 scheduler
->NotifyReadyToCommit();
1488 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1489 EXPECT_FALSE(client
.needs_begin_frame());
1492 // Swapping will put us into a swap throttled state.
1493 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1494 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1495 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1496 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1497 EXPECT_FALSE(client
.needs_begin_frame());
1500 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1501 // but not a BeginMainFrame or draw.
1502 scheduler
->SetNeedsCommit();
1503 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1504 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 1);
1505 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1506 EXPECT_FALSE(client
.needs_begin_frame());
1509 // Take us out of a swap throttled state.
1510 scheduler
->DidSwapBuffersComplete();
1511 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 1);
1512 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1513 EXPECT_FALSE(client
.needs_begin_frame());
1516 // BeginImplFrame deadline should draw.
1517 scheduler
->SetNeedsRedraw();
1518 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1519 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1520 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1521 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1522 EXPECT_FALSE(client
.needs_begin_frame());
1526 // See: http://crbug.com/380889
1527 TEST(SchedulerTest
, DISABLED_SyntheticBeginFrames_SwapThrottled
) {
1528 bool begin_frame_scheduling_enabled
= false;
1529 bool throttle_frame_production
= true;
1530 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled
,
1531 throttle_frame_production
);
1534 TEST(SchedulerTest
, VSyncThrottlingDisabled_SwapThrottled
) {
1535 bool begin_frame_scheduling_enabled
= true;
1536 bool throttle_frame_production
= false;
1537 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled
,
1538 throttle_frame_production
);
1541 // See: http://crbug.com/380889
1543 DISABLED_SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled
) {
1544 bool begin_frame_scheduling_enabled
= false;
1545 bool throttle_frame_production
= false;
1546 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled
,
1547 throttle_frame_production
);
1550 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized
) {
1551 FakeSchedulerClient client
;
1552 SchedulerSettings scheduler_settings
;
1553 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1554 scheduler
->SetCanStart();
1555 scheduler
->SetVisible(true);
1556 scheduler
->SetCanDraw(true);
1558 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1560 scheduler
->DidCreateAndInitializeOutputSurface();
1561 EXPECT_NO_ACTION(client
);
1563 scheduler
->DidLoseOutputSurface();
1564 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1567 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStarted
) {
1568 FakeSchedulerClient client
;
1569 SchedulerSettings scheduler_settings
;
1570 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1571 scheduler
->SetCanStart();
1572 scheduler
->SetVisible(true);
1573 scheduler
->SetCanDraw(true);
1575 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1576 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1577 // SetNeedsCommit should begin the frame.
1579 scheduler
->SetNeedsCommit();
1580 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1583 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1584 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1585 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1586 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1589 scheduler
->DidLoseOutputSurface();
1590 // Do nothing when impl frame is in deadine pending state.
1591 EXPECT_NO_ACTION(client
);
1594 scheduler
->NotifyBeginMainFrameStarted();
1595 scheduler
->NotifyReadyToCommit();
1596 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 1);
1599 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1600 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1603 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1604 bool impl_side_painting
) {
1605 FakeSchedulerClient client
;
1606 SchedulerSettings scheduler_settings
;
1607 scheduler_settings
.impl_side_painting
= impl_side_painting
;
1608 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1609 scheduler
->SetCanStart();
1610 scheduler
->SetVisible(true);
1611 scheduler
->SetCanDraw(true);
1613 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1614 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1616 // SetNeedsCommit should begin the frame.
1618 scheduler
->SetNeedsCommit();
1619 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1622 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1623 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1624 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1625 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1628 scheduler
->DidLoseOutputSurface();
1629 // Do nothing when impl frame is in deadine pending state.
1630 EXPECT_NO_ACTION(client
);
1633 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1634 // OnBeginImplFrameDeadline didn't schedule any actions because main frame is
1635 // not yet completed.
1636 EXPECT_NO_ACTION(client
);
1638 // BeginImplFrame is not started.
1639 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1640 EXPECT_NO_ACTION(client
);
1641 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1644 scheduler
->NotifyBeginMainFrameStarted();
1645 scheduler
->NotifyReadyToCommit();
1646 if (impl_side_painting
) {
1647 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 3);
1648 EXPECT_ACTION("ScheduledActionActivateSyncTree", client
, 1, 3);
1649 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
, 2, 3);
1651 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 2);
1652 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
, 1, 2);
1656 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency
) {
1657 bool impl_side_painting
= false;
1658 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1662 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint
) {
1663 bool impl_side_painting
= true;
1664 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1667 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting
) {
1668 FakeSchedulerClient client
;
1669 SchedulerSettings scheduler_settings
;
1670 scheduler_settings
.impl_side_painting
= impl_side_painting
;
1671 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1672 scheduler
->SetCanStart();
1673 scheduler
->SetVisible(true);
1674 scheduler
->SetCanDraw(true);
1676 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1677 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1679 // SetNeedsCommit should begin the frame.
1681 scheduler
->SetNeedsCommit();
1682 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1685 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1686 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1687 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1688 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1691 scheduler
->NotifyBeginMainFrameStarted();
1692 scheduler
->NotifyReadyToCommit();
1693 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1696 scheduler
->DidLoseOutputSurface();
1697 if (impl_side_painting
) {
1698 // Sync tree should be forced to activate.
1699 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client
);
1701 // Do nothing when impl frame is in deadine pending state.
1702 EXPECT_NO_ACTION(client
);
1706 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1707 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1710 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommit
) {
1711 DidLoseOutputSurfaceAfterReadyToCommit(false);
1714 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting
) {
1715 DidLoseOutputSurfaceAfterReadyToCommit(true);
1718 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterSetNeedsManageTiles
) {
1719 FakeSchedulerClient client
;
1720 SchedulerSettings scheduler_settings
;
1721 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1722 scheduler
->SetCanStart();
1723 scheduler
->SetVisible(true);
1724 scheduler
->SetCanDraw(true);
1725 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1728 scheduler
->SetNeedsManageTiles();
1729 scheduler
->SetNeedsRedraw();
1730 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1731 EXPECT_TRUE(client
.needs_begin_frame());
1734 scheduler
->BeginFrame(CreateBeginFrameArgsForTesting());
1735 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1736 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1737 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1740 scheduler
->DidLoseOutputSurface();
1741 EXPECT_NO_ACTION(client
);
1744 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1745 EXPECT_ACTION("ScheduledActionManageTiles", client
, 0, 2);
1746 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
, 1, 2);
1749 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterBeginRetroFramePosted
) {
1750 FakeSchedulerClient client
;
1751 SchedulerSettings scheduler_settings
;
1752 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1753 scheduler
->SetCanStart();
1754 scheduler
->SetVisible(true);
1755 scheduler
->SetCanDraw(true);
1756 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1758 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1760 scheduler
->SetNeedsCommit();
1761 EXPECT_TRUE(client
.needs_begin_frame());
1762 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1764 // Create a BeginFrame with a long deadline to avoid race conditions.
1765 // This is the first BeginFrame, which will be handled immediately.
1767 BeginFrameArgs args
= CreateBeginFrameArgsForTesting();
1768 args
.deadline
+= base::TimeDelta::FromHours(1);
1769 scheduler
->BeginFrame(args
);
1770 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1771 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1772 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1773 EXPECT_TRUE(client
.needs_begin_frame());
1775 // Queue BeginFrames while we are still handling the previous BeginFrame.
1776 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1777 scheduler
->BeginFrame(args
);
1778 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1779 scheduler
->BeginFrame(args
);
1781 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1783 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1784 EXPECT_NO_ACTION(client
);
1785 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1786 EXPECT_TRUE(client
.needs_begin_frame());
1788 // NotifyReadyToCommit should trigger the commit.
1790 scheduler
->NotifyBeginMainFrameStarted();
1791 scheduler
->NotifyReadyToCommit();
1792 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1793 EXPECT_TRUE(client
.needs_begin_frame());
1796 EXPECT_FALSE(scheduler
->IsBeginRetroFrameArgsEmpty());
1797 scheduler
->DidLoseOutputSurface();
1798 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1799 EXPECT_TRUE(client
.needs_begin_frame());
1800 EXPECT_TRUE(scheduler
->IsBeginRetroFrameArgsEmpty());
1802 // Posted BeginRetroFrame is aborted.
1804 client
.task_runner().RunPendingTasks();
1805 EXPECT_NO_ACTION(client
);
1808 TEST(SchedulerTest
, DidLoseOutputSurfaceDuringBeginRetroFrameRunning
) {
1809 FakeSchedulerClient client
;
1810 SchedulerSettings scheduler_settings
;
1811 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1812 scheduler
->SetCanStart();
1813 scheduler
->SetVisible(true);
1814 scheduler
->SetCanDraw(true);
1815 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1817 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1819 scheduler
->SetNeedsCommit();
1820 EXPECT_TRUE(client
.needs_begin_frame());
1821 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client
);
1823 // Create a BeginFrame with a long deadline to avoid race conditions.
1824 // This is the first BeginFrame, which will be handled immediately.
1826 BeginFrameArgs args
= CreateBeginFrameArgsForTesting();
1827 args
.deadline
+= base::TimeDelta::FromHours(1);
1828 scheduler
->BeginFrame(args
);
1829 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1830 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1831 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1832 EXPECT_TRUE(client
.needs_begin_frame());
1834 // Queue BeginFrames while we are still handling the previous BeginFrame.
1835 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1836 scheduler
->BeginFrame(args
);
1837 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1838 scheduler
->BeginFrame(args
);
1840 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1842 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1843 EXPECT_NO_ACTION(client
);
1844 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1845 EXPECT_TRUE(client
.needs_begin_frame());
1847 // NotifyReadyToCommit should trigger the commit.
1849 scheduler
->NotifyBeginMainFrameStarted();
1850 scheduler
->NotifyReadyToCommit();
1851 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1852 EXPECT_TRUE(client
.needs_begin_frame());
1854 // BeginImplFrame should prepare the draw.
1856 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1857 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1858 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1859 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1860 EXPECT_TRUE(client
.needs_begin_frame());
1863 EXPECT_FALSE(scheduler
->IsBeginRetroFrameArgsEmpty());
1864 scheduler
->DidLoseOutputSurface();
1865 EXPECT_NO_ACTION(client
);
1866 EXPECT_TRUE(scheduler
->IsBeginRetroFrameArgsEmpty());
1868 // BeginImplFrame deadline should abort drawing.
1870 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1871 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1872 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1873 EXPECT_TRUE(client
.needs_begin_frame());
1875 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
1877 client
.task_runner().RunPendingTasks();
1878 EXPECT_NO_ACTION(client
);
1881 // See: http://crbug.com/380889
1884 DISABLED_StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource
) {
1885 FakeSchedulerClient client
;
1886 SchedulerSettings scheduler_settings
;
1887 scheduler_settings
.begin_frame_scheduling_enabled
= false;
1888 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1889 scheduler
->SetCanStart();
1890 scheduler
->SetVisible(true);
1891 scheduler
->SetCanDraw(true);
1892 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1894 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1896 EXPECT_FALSE(scheduler
->IsSyntheticBeginFrameSourceActive());
1897 scheduler
->SetNeedsCommit();
1898 EXPECT_TRUE(scheduler
->IsSyntheticBeginFrameSourceActive());
1901 client
.task_runner().RunPendingTasks(); // Run posted Tick.
1902 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1903 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1904 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1905 EXPECT_TRUE(scheduler
->IsSyntheticBeginFrameSourceActive());
1907 // NotifyReadyToCommit should trigger the commit.
1909 scheduler
->NotifyBeginMainFrameStarted();
1910 scheduler
->NotifyReadyToCommit();
1911 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1912 EXPECT_TRUE(scheduler
->IsSyntheticBeginFrameSourceActive());
1915 scheduler
->DidLoseOutputSurface();
1916 EXPECT_EQ(0, client
.num_actions_());
1917 EXPECT_FALSE(scheduler
->IsSyntheticBeginFrameSourceActive());
1920 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1921 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1922 EXPECT_FALSE(scheduler
->IsSyntheticBeginFrameSourceActive());