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/scheduler_test_common.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
19 EXPECT_EQ(expected_num_actions, client.num_actions_()); \
20 ASSERT_LT(action_index, client.num_actions_()); \
22 EXPECT_STREQ(action, client.Action(action_index)); \
23 for (int i = expected_num_actions; i < client.num_actions_(); ++i) \
24 ADD_FAILURE() << "Unexpected action: " << client.Action(i) << \
25 " with state:\n" << client.StateForAction(action_index); \
28 #define EXPECT_SINGLE_ACTION(action, client) \
29 EXPECT_ACTION(action, client, 0, 1)
34 void InitializeOutputSurfaceAndFirstCommit(Scheduler
* scheduler
) {
35 scheduler
->DidCreateAndInitializeOutputSurface();
36 scheduler
->SetNeedsCommit();
37 scheduler
->FinishCommit();
38 // Go through the motions to draw the commit.
39 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
40 scheduler
->OnBeginImplFrameDeadline();
41 // We need another BeginImplFrame so Scheduler calls
42 // SetNeedsBeginImplFrame(false).
43 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
44 scheduler
->OnBeginImplFrameDeadline();
47 class FakeSchedulerClient
: public SchedulerClient
{
50 : needs_begin_impl_frame_(false) {
57 draw_will_happen_
= true;
58 swap_will_happen_if_draw_happens_
= true;
60 log_anticipated_draw_time_change_
= false;
63 Scheduler
* CreateScheduler(const SchedulerSettings
& settings
) {
64 scheduler_
= Scheduler::Create(this, settings
);
65 return scheduler_
.get();
68 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
70 void set_log_anticipated_draw_time_change(bool log
) {
71 log_anticipated_draw_time_change_
= log
;
73 bool needs_begin_impl_frame() { return needs_begin_impl_frame_
; }
74 int num_draws() const { return num_draws_
; }
75 int num_actions_() const { return static_cast<int>(actions_
.size()); }
76 const char* Action(int i
) const { return actions_
[i
]; }
77 base::Value
& StateForAction(int i
) const { return *states_
[i
]; }
79 int ActionIndex(const char* action
) const {
80 for (size_t i
= 0; i
< actions_
.size(); i
++)
81 if (!strcmp(actions_
[i
], action
))
86 bool HasAction(const char* action
) const {
87 return ActionIndex(action
) >= 0;
90 void SetDrawWillHappen(bool draw_will_happen
) {
91 draw_will_happen_
= draw_will_happen
;
93 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens
) {
94 swap_will_happen_if_draw_happens_
= swap_will_happen_if_draw_happens
;
97 // SchedulerClient implementation.
98 virtual void SetNeedsBeginImplFrame(bool enable
) OVERRIDE
{
99 actions_
.push_back("SetNeedsBeginImplFrame");
100 states_
.push_back(scheduler_
->StateAsValue().release());
101 needs_begin_impl_frame_
= enable
;
103 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE
{
104 actions_
.push_back("ScheduledActionSendBeginMainFrame");
105 states_
.push_back(scheduler_
->StateAsValue().release());
107 virtual DrawSwapReadbackResult
ScheduledActionDrawAndSwapIfPossible()
109 actions_
.push_back("ScheduledActionDrawAndSwapIfPossible");
110 states_
.push_back(scheduler_
->StateAsValue().release());
112 bool did_readback
= false;
113 return DrawSwapReadbackResult(
115 draw_will_happen_
&& swap_will_happen_if_draw_happens_
,
118 virtual DrawSwapReadbackResult
ScheduledActionDrawAndSwapForced() OVERRIDE
{
119 actions_
.push_back("ScheduledActionDrawAndSwapForced");
120 states_
.push_back(scheduler_
->StateAsValue().release());
121 bool did_draw
= true;
122 bool did_swap
= swap_will_happen_if_draw_happens_
;
123 bool did_readback
= false;
124 return DrawSwapReadbackResult(did_draw
, did_swap
, did_readback
);
126 virtual DrawSwapReadbackResult
ScheduledActionDrawAndReadback() OVERRIDE
{
127 actions_
.push_back("ScheduledActionDrawAndReadback");
128 states_
.push_back(scheduler_
->StateAsValue().release());
129 bool did_draw
= true;
130 bool did_swap
= false;
131 bool did_readback
= true;
132 return DrawSwapReadbackResult(did_draw
, did_swap
, did_readback
);
134 virtual void ScheduledActionCommit() OVERRIDE
{
135 actions_
.push_back("ScheduledActionCommit");
136 states_
.push_back(scheduler_
->StateAsValue().release());
138 virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE
{
139 actions_
.push_back("ScheduledActionUpdateVisibleTiles");
140 states_
.push_back(scheduler_
->StateAsValue().release());
142 virtual void ScheduledActionActivatePendingTree() OVERRIDE
{
143 actions_
.push_back("ScheduledActionActivatePendingTree");
144 states_
.push_back(scheduler_
->StateAsValue().release());
146 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE
{
147 actions_
.push_back("ScheduledActionBeginOutputSurfaceCreation");
148 states_
.push_back(scheduler_
->StateAsValue().release());
150 virtual void ScheduledActionAcquireLayerTexturesForMainThread() OVERRIDE
{
151 actions_
.push_back("ScheduledActionAcquireLayerTexturesForMainThread");
152 states_
.push_back(scheduler_
->StateAsValue().release());
154 virtual void ScheduledActionManageTiles() OVERRIDE
{
155 actions_
.push_back("ScheduledActionManageTiles");
156 states_
.push_back(scheduler_
->StateAsValue().release());
158 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks
) OVERRIDE
{
159 if (log_anticipated_draw_time_change_
)
160 actions_
.push_back("DidAnticipatedDrawTimeChange");
162 virtual base::TimeDelta
DrawDurationEstimate() OVERRIDE
{
163 return base::TimeDelta();
165 virtual base::TimeDelta
BeginMainFrameToCommitDurationEstimate() OVERRIDE
{
166 return base::TimeDelta();
168 virtual base::TimeDelta
CommitToActivateDurationEstimate() OVERRIDE
{
169 return base::TimeDelta();
172 virtual void PostBeginImplFrameDeadline(const base::Closure
& closure
,
173 base::TimeTicks deadline
) OVERRIDE
{
174 actions_
.push_back("PostBeginImplFrameDeadlineTask");
175 states_
.push_back(scheduler_
->StateAsValue().release());
178 virtual void DidBeginImplFrameDeadline() OVERRIDE
{}
181 bool needs_begin_impl_frame_
;
182 bool draw_will_happen_
;
183 bool swap_will_happen_if_draw_happens_
;
185 bool log_anticipated_draw_time_change_
;
186 std::vector
<const char*> actions_
;
187 ScopedVector
<base::Value
> states_
;
188 scoped_ptr
<Scheduler
> scheduler_
;
191 TEST(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
192 FakeSchedulerClient client
;
193 SchedulerSettings default_scheduler_settings
;
194 Scheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
195 scheduler
->SetCanStart();
196 scheduler
->SetVisible(true);
197 scheduler
->SetCanDraw(true);
199 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
201 scheduler
->DidCreateAndInitializeOutputSurface();
202 EXPECT_EQ(0, client
.num_actions_());
205 void RequestCommit(bool deadline_scheduling_enabled
) {
206 FakeSchedulerClient client
;
207 SchedulerSettings scheduler_settings
;
208 scheduler_settings
.deadline_scheduling_enabled
= deadline_scheduling_enabled
;
209 Scheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
210 scheduler
->SetCanStart();
211 scheduler
->SetVisible(true);
212 scheduler
->SetCanDraw(true);
214 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
215 InitializeOutputSurfaceAndFirstCommit(scheduler
);
217 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
219 scheduler
->SetNeedsCommit();
220 EXPECT_TRUE(client
.needs_begin_impl_frame());
221 if (deadline_scheduling_enabled
) {
222 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
224 EXPECT_EQ(client
.num_actions_(), 2);
225 EXPECT_TRUE(client
.HasAction("ScheduledActionSendBeginMainFrame"));
226 EXPECT_TRUE(client
.HasAction("SetNeedsBeginImplFrame"));
230 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
231 if (deadline_scheduling_enabled
) {
232 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 2);
233 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client
, 1, 2);
235 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
237 EXPECT_TRUE(client
.needs_begin_impl_frame());
240 // If we don't swap on the deadline, we need to request another
242 scheduler
->OnBeginImplFrameDeadline();
243 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
244 EXPECT_TRUE(client
.needs_begin_impl_frame());
247 // FinishCommit should commit
248 scheduler
->FinishCommit();
249 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
250 EXPECT_TRUE(client
.needs_begin_impl_frame());
253 // BeginImplFrame should prepare the draw.
254 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
255 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
256 EXPECT_TRUE(client
.needs_begin_impl_frame());
259 // BeginImplFrame deadline should draw.
260 scheduler
->OnBeginImplFrameDeadline();
261 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 2);
262 EXPECT_ACTION("SetNeedsBeginImplFrame", client
, 1, 2);
263 EXPECT_TRUE(client
.needs_begin_impl_frame());
266 // The following BeginImplFrame deadline should SetNeedsBeginImplFrame(false)
267 // to avoid excessive toggles.
268 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
269 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
272 scheduler
->OnBeginImplFrameDeadline();
273 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
274 EXPECT_FALSE(client
.needs_begin_impl_frame());
278 TEST(SchedulerTest
, RequestCommit
) {
279 bool deadline_scheduling_enabled
= false;
280 RequestCommit(deadline_scheduling_enabled
);
283 TEST(SchedulerTest
, RequestCommit_Deadline
) {
284 bool deadline_scheduling_enabled
= true;
285 RequestCommit(deadline_scheduling_enabled
);
288 void RequestCommitAfterBeginMainFrameSent(
289 bool deadline_scheduling_enabled
) {
290 FakeSchedulerClient client
;
291 SchedulerSettings scheduler_settings
;
292 scheduler_settings
.deadline_scheduling_enabled
= deadline_scheduling_enabled
;
293 Scheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
294 scheduler
->SetCanStart();
295 scheduler
->SetVisible(true);
296 scheduler
->SetCanDraw(true);
298 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
299 InitializeOutputSurfaceAndFirstCommit(scheduler
);
302 // SetNeedsCommit should begin the frame.
303 scheduler
->SetNeedsCommit();
304 if (deadline_scheduling_enabled
) {
305 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
307 EXPECT_EQ(client
.num_actions_(), 2);
308 EXPECT_TRUE(client
.HasAction("SetNeedsBeginImplFrame"));
309 EXPECT_TRUE(client
.HasAction("ScheduledActionSendBeginMainFrame"));
313 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
314 if (deadline_scheduling_enabled
) {
315 EXPECT_EQ(client
.num_actions_(), 2);
316 EXPECT_TRUE(client
.HasAction("ScheduledActionSendBeginMainFrame"));
317 EXPECT_TRUE(client
.HasAction("PostBeginImplFrameDeadlineTask"));
319 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
322 EXPECT_TRUE(client
.needs_begin_impl_frame());
325 // Now SetNeedsCommit again. Calling here means we need a second commit.
326 scheduler
->SetNeedsCommit();
327 EXPECT_EQ(client
.num_actions_(), 0);
330 // Finish the first commit.
331 scheduler
->FinishCommit();
332 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 2);
333 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client
, 1, 2);
335 scheduler
->OnBeginImplFrameDeadline();
336 if (deadline_scheduling_enabled
) {
337 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 2);
338 EXPECT_ACTION("SetNeedsBeginImplFrame", client
, 1, 2);
340 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 3);
341 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 3);
342 EXPECT_ACTION("SetNeedsBeginImplFrame", client
, 2, 3);
345 // Because we just swapped, the Scheduler should also request the next
346 // BeginImplFrame from the OutputSurface.
347 EXPECT_TRUE(client
.needs_begin_impl_frame());
350 // Since another commit is needed, the next BeginImplFrame should initiate
351 // the second commit.
352 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
353 if (deadline_scheduling_enabled
) {
354 EXPECT_EQ(client
.num_actions_(), 2);
355 EXPECT_TRUE(client
.HasAction("ScheduledActionSendBeginMainFrame"));
356 EXPECT_TRUE(client
.HasAction("PostBeginImplFrameDeadlineTask"));
358 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
362 // Finishing the commit before the deadline should post a new deadline task
363 // to trigger the deadline early.
364 scheduler
->FinishCommit();
365 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 2);
366 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client
, 1, 2);
368 scheduler
->OnBeginImplFrameDeadline();
369 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 2);
370 EXPECT_ACTION("SetNeedsBeginImplFrame", client
, 1, 2);
371 EXPECT_TRUE(client
.needs_begin_impl_frame());
374 // On the next BeginImplFrame, verify we go back to a quiescent state and
375 // no longer request BeginImplFrames.
376 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
377 scheduler
->OnBeginImplFrameDeadline();
378 EXPECT_FALSE(client
.needs_begin_impl_frame());
382 TEST(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
383 bool deadline_scheduling_enabled
= false;
384 RequestCommitAfterBeginMainFrameSent(deadline_scheduling_enabled
);
387 TEST(SchedulerTest
, RequestCommitAfterBeginMainFrameSent_Deadline
) {
388 bool deadline_scheduling_enabled
= true;
389 RequestCommitAfterBeginMainFrameSent(deadline_scheduling_enabled
);
392 void TextureAcquisitionCausesCommitInsteadOfDraw(
393 bool deadline_scheduling_enabled
) {
394 FakeSchedulerClient client
;
395 SchedulerSettings scheduler_settings
;
396 scheduler_settings
.deadline_scheduling_enabled
= deadline_scheduling_enabled
;
397 Scheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
398 scheduler
->SetCanStart();
399 scheduler
->SetVisible(true);
400 scheduler
->SetCanDraw(true);
401 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
403 InitializeOutputSurfaceAndFirstCommit(scheduler
);
405 scheduler
->SetNeedsRedraw();
406 EXPECT_TRUE(scheduler
->RedrawPending());
407 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
408 EXPECT_TRUE(client
.needs_begin_impl_frame());
411 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
412 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
414 scheduler
->OnBeginImplFrameDeadline();
415 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 2);
416 EXPECT_ACTION("SetNeedsBeginImplFrame", client
, 1, 2);
417 EXPECT_FALSE(scheduler
->RedrawPending());
418 EXPECT_TRUE(client
.needs_begin_impl_frame());
421 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
422 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
424 scheduler
->OnBeginImplFrameDeadline();
425 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
426 EXPECT_FALSE(scheduler
->RedrawPending());
427 EXPECT_FALSE(client
.needs_begin_impl_frame());
430 scheduler
->SetMainThreadNeedsLayerTextures();
431 EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
434 // We should request a BeginImplFrame in anticipation of a draw.
436 scheduler
->SetNeedsRedraw();
437 EXPECT_TRUE(scheduler
->RedrawPending());
438 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
439 EXPECT_TRUE(client
.needs_begin_impl_frame());
441 // No draw happens since the textures are acquired by the main thread.
443 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
444 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
446 scheduler
->OnBeginImplFrameDeadline();
447 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
448 EXPECT_TRUE(scheduler
->RedrawPending());
449 EXPECT_TRUE(client
.needs_begin_impl_frame());
452 scheduler
->SetNeedsCommit();
453 if (deadline_scheduling_enabled
) {
454 EXPECT_EQ(0, client
.num_actions_());
456 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client
);
460 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
461 if (deadline_scheduling_enabled
) {
462 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 2);
463 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client
, 1, 2);
465 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
468 // Commit will release the texture.
470 scheduler
->FinishCommit();
471 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 2);
472 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client
, 1, 2);
473 EXPECT_TRUE(scheduler
->RedrawPending());
475 // Now we can draw again after the commit happens.
477 scheduler
->OnBeginImplFrameDeadline();
478 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 2);
479 EXPECT_ACTION("SetNeedsBeginImplFrame", client
, 1, 2);
480 EXPECT_FALSE(scheduler
->RedrawPending());
481 EXPECT_TRUE(client
.needs_begin_impl_frame());
483 // Make sure we stop requesting BeginImplFrames if we don't swap.
485 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
486 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
488 scheduler
->OnBeginImplFrameDeadline();
489 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
490 EXPECT_FALSE(client
.needs_begin_impl_frame());
493 TEST(SchedulerTest
, TextureAcquisitionCausesCommitInsteadOfDraw
) {
494 bool deadline_scheduling_enabled
= false;
495 TextureAcquisitionCausesCommitInsteadOfDraw(deadline_scheduling_enabled
);
498 TEST(SchedulerTest
, TextureAcquisitionCausesCommitInsteadOfDraw_Deadline
) {
499 bool deadline_scheduling_enabled
= true;
500 TextureAcquisitionCausesCommitInsteadOfDraw(deadline_scheduling_enabled
);
503 void TextureAcquisitionCollision(bool deadline_scheduling_enabled
) {
504 FakeSchedulerClient client
;
505 SchedulerSettings scheduler_settings
;
506 scheduler_settings
.deadline_scheduling_enabled
= deadline_scheduling_enabled
;
507 Scheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
508 scheduler
->SetCanStart();
509 scheduler
->SetVisible(true);
510 scheduler
->SetCanDraw(true);
512 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
513 InitializeOutputSurfaceAndFirstCommit(scheduler
);
516 scheduler
->SetNeedsCommit();
517 if (deadline_scheduling_enabled
) {
518 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
520 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 2);
521 EXPECT_ACTION("SetNeedsBeginImplFrame", client
, 1, 2);
525 scheduler
->SetMainThreadNeedsLayerTextures();
526 EXPECT_SINGLE_ACTION(
527 "ScheduledActionAcquireLayerTexturesForMainThread", client
);
530 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
531 if (deadline_scheduling_enabled
) {
532 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 2);
533 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client
, 1, 2);
535 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
539 scheduler
->OnBeginImplFrameDeadline();
540 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
542 // Although the compositor cannot draw because textures are locked by main
543 // thread, we continue requesting SetNeedsBeginImplFrame in anticipation of
545 EXPECT_TRUE(client
.needs_begin_impl_frame());
547 // Trigger the commit
548 scheduler
->FinishCommit();
549 EXPECT_TRUE(client
.needs_begin_impl_frame());
551 // Between commit and draw, texture acquisition for main thread delayed,
552 // and main thread blocks.
554 scheduler
->SetMainThreadNeedsLayerTextures();
555 EXPECT_EQ(0, client
.num_actions_());
557 // No implicit commit is expected.
559 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
560 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
563 scheduler
->OnBeginImplFrameDeadline();
564 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 3);
566 "ScheduledActionAcquireLayerTexturesForMainThread", client
, 1, 3);
567 EXPECT_ACTION("SetNeedsBeginImplFrame", client
, 2, 3);
568 EXPECT_TRUE(client
.needs_begin_impl_frame());
570 // The compositor should not draw because textures are locked by main
573 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
574 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
576 scheduler
->OnBeginImplFrameDeadline();
577 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
578 EXPECT_FALSE(client
.needs_begin_impl_frame());
580 // The impl thread need an explicit commit from the main thread to lock
583 scheduler
->SetNeedsCommit();
584 if (deadline_scheduling_enabled
) {
585 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);
587 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 2);
588 EXPECT_ACTION("SetNeedsBeginImplFrame", client
, 1, 2);
590 EXPECT_TRUE(client
.needs_begin_impl_frame());
593 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
594 if (deadline_scheduling_enabled
) {
595 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 2);
596 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client
, 1, 2);
598 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
602 // Trigger the commit, which will trigger the deadline task early.
603 scheduler
->FinishCommit();
604 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 2);
605 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client
, 1, 2);
606 EXPECT_TRUE(client
.needs_begin_impl_frame());
609 // Verify we draw on the next BeginImplFrame deadline
610 scheduler
->OnBeginImplFrameDeadline();
611 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 2);
612 EXPECT_ACTION("SetNeedsBeginImplFrame", client
, 1, 2);
613 EXPECT_TRUE(client
.needs_begin_impl_frame());
617 TEST(SchedulerTest
, TextureAcquisitionCollision
) {
618 bool deadline_scheduling_enabled
= false;
619 TextureAcquisitionCollision(deadline_scheduling_enabled
);
622 TEST(SchedulerTest
, TextureAcquisitionCollision_Deadline
) {
623 bool deadline_scheduling_enabled
= true;
624 TextureAcquisitionCollision(deadline_scheduling_enabled
);
627 void VisibilitySwitchWithTextureAcquisition(bool deadline_scheduling_enabled
) {
628 FakeSchedulerClient client
;
629 SchedulerSettings scheduler_settings
;
630 scheduler_settings
.deadline_scheduling_enabled
= deadline_scheduling_enabled
;
631 Scheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
632 scheduler
->SetCanStart();
633 scheduler
->SetVisible(true);
634 scheduler
->SetCanDraw(true);
636 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
638 scheduler
->DidCreateAndInitializeOutputSurface();
640 scheduler
->SetNeedsCommit();
641 if (deadline_scheduling_enabled
) {
642 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
643 scheduler
->OnBeginImplFrameDeadline();
645 scheduler
->FinishCommit();
646 scheduler
->SetMainThreadNeedsLayerTextures();
647 scheduler
->SetNeedsCommit();
649 // Verify that pending texture acquisition fires when visibility
650 // is lost in order to avoid a deadlock.
651 scheduler
->SetVisible(false);
652 EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
656 scheduler
->SetVisible(true);
657 EXPECT_EQ(0, client
.num_actions_());
658 EXPECT_TRUE(client
.needs_begin_impl_frame());
660 // Regaining visibility with textures acquired by main thread while
661 // compositor is waiting for first draw should result in a request
662 // for a new frame in order to escape a deadlock.
664 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
665 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 0, 2);
666 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client
, 1, 2);
669 TEST(SchedulerTest
, VisibilitySwitchWithTextureAcquisition
) {
670 bool deadline_scheduling_enabled
= false;
671 VisibilitySwitchWithTextureAcquisition(deadline_scheduling_enabled
);
674 TEST(SchedulerTest
, VisibilitySwitchWithTextureAcquisition_Deadline
) {
675 bool deadline_scheduling_enabled
= true;
676 VisibilitySwitchWithTextureAcquisition(deadline_scheduling_enabled
);
679 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
681 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE
{}
682 virtual DrawSwapReadbackResult
ScheduledActionDrawAndSwapIfPossible()
684 // Only SetNeedsRedraw the first time this is called
686 scheduler_
->SetNeedsRedraw();
687 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
690 virtual DrawSwapReadbackResult
ScheduledActionDrawAndSwapForced() OVERRIDE
{
692 bool did_draw
= true;
693 bool did_swap
= true;
694 bool did_readback
= false;
695 return DrawSwapReadbackResult(did_draw
, did_swap
, did_readback
);
698 virtual void ScheduledActionCommit() OVERRIDE
{}
699 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE
{}
700 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks
) OVERRIDE
{}
703 // Tests for two different situations:
704 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
705 // a ScheduledActionDrawAndSwap
706 // 2. the scheduler drawing twice inside a single tick
707 TEST(SchedulerTest
, RequestRedrawInsideDraw
) {
708 SchedulerClientThatsetNeedsDrawInsideDraw client
;
709 SchedulerSettings default_scheduler_settings
;
710 Scheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
711 scheduler
->SetCanStart();
712 scheduler
->SetVisible(true);
713 scheduler
->SetCanDraw(true);
714 InitializeOutputSurfaceAndFirstCommit(scheduler
);
717 scheduler
->SetNeedsRedraw();
718 EXPECT_TRUE(scheduler
->RedrawPending());
719 EXPECT_TRUE(client
.needs_begin_impl_frame());
720 EXPECT_EQ(0, client
.num_draws());
722 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
723 scheduler
->OnBeginImplFrameDeadline();
724 EXPECT_EQ(1, client
.num_draws());
725 EXPECT_TRUE(scheduler
->RedrawPending());
726 EXPECT_TRUE(client
.needs_begin_impl_frame());
728 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
729 scheduler
->OnBeginImplFrameDeadline();
730 EXPECT_EQ(2, client
.num_draws());
731 EXPECT_FALSE(scheduler
->RedrawPending());
732 EXPECT_TRUE(client
.needs_begin_impl_frame());
734 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
736 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
737 scheduler
->OnBeginImplFrameDeadline();
738 EXPECT_EQ(2, client
.num_draws());
739 EXPECT_FALSE(scheduler
->RedrawPending());
740 EXPECT_FALSE(client
.needs_begin_impl_frame());
743 // Test that requesting redraw inside a failed draw doesn't lose the request.
744 TEST(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
745 SchedulerClientThatsetNeedsDrawInsideDraw client
;
746 SchedulerSettings default_scheduler_settings
;
747 Scheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
748 scheduler
->SetCanStart();
749 scheduler
->SetVisible(true);
750 scheduler
->SetCanDraw(true);
751 InitializeOutputSurfaceAndFirstCommit(scheduler
);
754 client
.SetDrawWillHappen(false);
756 scheduler
->SetNeedsRedraw();
757 EXPECT_TRUE(scheduler
->RedrawPending());
758 EXPECT_TRUE(client
.needs_begin_impl_frame());
759 EXPECT_EQ(0, client
.num_draws());
762 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
763 scheduler
->OnBeginImplFrameDeadline();
764 EXPECT_EQ(1, client
.num_draws());
766 // We have a commit pending and the draw failed, and we didn't lose the redraw
768 EXPECT_TRUE(scheduler
->CommitPending());
769 EXPECT_TRUE(scheduler
->RedrawPending());
770 EXPECT_TRUE(client
.needs_begin_impl_frame());
772 // Fail the draw again.
773 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
774 scheduler
->OnBeginImplFrameDeadline();
775 EXPECT_EQ(2, client
.num_draws());
776 EXPECT_TRUE(scheduler
->CommitPending());
777 EXPECT_TRUE(scheduler
->RedrawPending());
778 EXPECT_TRUE(client
.needs_begin_impl_frame());
780 // Draw successfully.
781 client
.SetDrawWillHappen(true);
782 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
783 scheduler
->OnBeginImplFrameDeadline();
784 EXPECT_EQ(3, client
.num_draws());
785 EXPECT_TRUE(scheduler
->CommitPending());
786 EXPECT_FALSE(scheduler
->RedrawPending());
787 EXPECT_TRUE(client
.needs_begin_impl_frame());
790 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
792 SchedulerClientThatSetNeedsCommitInsideDraw()
793 : set_needs_commit_on_next_draw_(false) {}
795 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE
{}
796 virtual DrawSwapReadbackResult
ScheduledActionDrawAndSwapIfPossible()
798 // Only SetNeedsCommit the first time this is called
799 if (set_needs_commit_on_next_draw_
) {
800 scheduler_
->SetNeedsCommit();
801 set_needs_commit_on_next_draw_
= false;
803 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
806 virtual DrawSwapReadbackResult
ScheduledActionDrawAndSwapForced() OVERRIDE
{
808 bool did_draw
= true;
809 bool did_swap
= false;
810 bool did_readback
= false;
811 return DrawSwapReadbackResult(did_draw
, did_swap
, did_readback
);
814 virtual void ScheduledActionCommit() OVERRIDE
{}
815 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE
{}
816 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks
) OVERRIDE
{}
818 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
821 bool set_needs_commit_on_next_draw_
;
824 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
825 // happen inside a ScheduledActionDrawAndSwap
826 TEST(SchedulerTest
, RequestCommitInsideDraw
) {
827 SchedulerClientThatSetNeedsCommitInsideDraw client
;
828 SchedulerSettings default_scheduler_settings
;
829 Scheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
830 scheduler
->SetCanStart();
831 scheduler
->SetVisible(true);
832 scheduler
->SetCanDraw(true);
833 InitializeOutputSurfaceAndFirstCommit(scheduler
);
836 EXPECT_FALSE(client
.needs_begin_impl_frame());
837 scheduler
->SetNeedsRedraw();
838 EXPECT_TRUE(scheduler
->RedrawPending());
839 EXPECT_EQ(0, client
.num_draws());
840 EXPECT_TRUE(client
.needs_begin_impl_frame());
842 client
.SetNeedsCommitOnNextDraw();
843 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
844 client
.SetNeedsCommitOnNextDraw();
845 scheduler
->OnBeginImplFrameDeadline();
846 EXPECT_EQ(1, client
.num_draws());
847 EXPECT_TRUE(scheduler
->CommitPending());
848 EXPECT_TRUE(client
.needs_begin_impl_frame());
849 scheduler
->FinishCommit();
851 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
852 scheduler
->OnBeginImplFrameDeadline();
853 EXPECT_EQ(2, client
.num_draws());
855 EXPECT_FALSE(scheduler
->RedrawPending());
856 EXPECT_FALSE(scheduler
->CommitPending());
857 EXPECT_TRUE(client
.needs_begin_impl_frame());
859 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
861 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
862 scheduler
->OnBeginImplFrameDeadline();
863 EXPECT_EQ(2, client
.num_draws());
864 EXPECT_FALSE(scheduler
->RedrawPending());
865 EXPECT_FALSE(scheduler
->CommitPending());
866 EXPECT_FALSE(client
.needs_begin_impl_frame());
869 // Tests that when a draw fails then the pending commit should not be dropped.
870 TEST(SchedulerTest
, RequestCommitInsideFailedDraw
) {
871 SchedulerClientThatsetNeedsDrawInsideDraw client
;
872 SchedulerSettings default_scheduler_settings
;
873 Scheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
874 scheduler
->SetCanStart();
875 scheduler
->SetVisible(true);
876 scheduler
->SetCanDraw(true);
877 InitializeOutputSurfaceAndFirstCommit(scheduler
);
880 client
.SetDrawWillHappen(false);
882 scheduler
->SetNeedsRedraw();
883 EXPECT_TRUE(scheduler
->RedrawPending());
884 EXPECT_TRUE(client
.needs_begin_impl_frame());
885 EXPECT_EQ(0, client
.num_draws());
888 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
889 scheduler
->OnBeginImplFrameDeadline();
890 EXPECT_EQ(1, client
.num_draws());
892 // We have a commit pending and the draw failed, and we didn't lose the commit
894 EXPECT_TRUE(scheduler
->CommitPending());
895 EXPECT_TRUE(scheduler
->RedrawPending());
896 EXPECT_TRUE(client
.needs_begin_impl_frame());
898 // Fail the draw again.
899 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
900 scheduler
->OnBeginImplFrameDeadline();
901 EXPECT_EQ(2, client
.num_draws());
902 EXPECT_TRUE(scheduler
->CommitPending());
903 EXPECT_TRUE(scheduler
->RedrawPending());
904 EXPECT_TRUE(client
.needs_begin_impl_frame());
906 // Draw successfully.
907 client
.SetDrawWillHappen(true);
908 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
909 scheduler
->OnBeginImplFrameDeadline();
910 EXPECT_EQ(3, client
.num_draws());
911 EXPECT_TRUE(scheduler
->CommitPending());
912 EXPECT_FALSE(scheduler
->RedrawPending());
913 EXPECT_TRUE(client
.needs_begin_impl_frame());
916 TEST(SchedulerTest
, NoSwapWhenDrawFails
) {
917 SchedulerClientThatSetNeedsCommitInsideDraw client
;
918 SchedulerSettings default_scheduler_settings
;
919 Scheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
920 scheduler
->SetCanStart();
921 scheduler
->SetVisible(true);
922 scheduler
->SetCanDraw(true);
923 InitializeOutputSurfaceAndFirstCommit(scheduler
);
926 scheduler
->SetNeedsRedraw();
927 EXPECT_TRUE(scheduler
->RedrawPending());
928 EXPECT_TRUE(client
.needs_begin_impl_frame());
929 EXPECT_EQ(0, client
.num_draws());
931 // Draw successfully, this starts a new frame.
932 client
.SetNeedsCommitOnNextDraw();
933 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
934 scheduler
->OnBeginImplFrameDeadline();
935 EXPECT_EQ(1, client
.num_draws());
937 scheduler
->SetNeedsRedraw();
938 EXPECT_TRUE(scheduler
->RedrawPending());
939 EXPECT_TRUE(client
.needs_begin_impl_frame());
941 // Fail to draw, this should not start a frame.
942 client
.SetDrawWillHappen(false);
943 client
.SetNeedsCommitOnNextDraw();
944 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
945 scheduler
->OnBeginImplFrameDeadline();
946 EXPECT_EQ(2, client
.num_draws());
949 TEST(SchedulerTest
, NoSwapWhenSwapFailsDuringForcedCommit
) {
950 FakeSchedulerClient client
;
951 SchedulerSettings default_scheduler_settings
;
952 Scheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
954 // Tell the client that it will fail to swap.
955 client
.SetDrawWillHappen(true);
956 client
.SetSwapWillHappenIfDrawHappens(false);
958 // Get the compositor to do a ScheduledActionDrawAndReadback.
959 scheduler
->SetCanDraw(true);
960 scheduler
->SetNeedsRedraw();
961 scheduler
->SetNeedsForcedCommitForReadback();
962 scheduler
->FinishCommit();
963 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndReadback"));
966 TEST(SchedulerTest
, BackToBackReadbackAllowed
) {
967 // Some clients call readbacks twice in a row before the replacement
968 // commit comes in. Make sure it is allowed.
969 FakeSchedulerClient client
;
970 SchedulerSettings default_scheduler_settings
;
971 Scheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
973 // Get the compositor to do 2 ScheduledActionDrawAndReadbacks before
974 // the replacement commit comes in.
975 scheduler
->SetCanDraw(true);
976 scheduler
->SetNeedsRedraw();
977 scheduler
->SetNeedsForcedCommitForReadback();
978 scheduler
->FinishCommit();
979 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndReadback"));
982 scheduler
->SetNeedsForcedCommitForReadback();
983 scheduler
->FinishCommit();
984 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndReadback"));
986 // The replacement commit comes in after 2 readbacks.
988 scheduler
->FinishCommit();
992 class SchedulerClientNeedsManageTilesInDraw
: public FakeSchedulerClient
{
994 virtual DrawSwapReadbackResult
ScheduledActionDrawAndSwapIfPossible()
996 scheduler_
->SetNeedsManageTiles();
997 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
1001 // Test manage tiles is independant of draws.
1002 TEST(SchedulerTest
, ManageTiles
) {
1003 SchedulerClientNeedsManageTilesInDraw client
;
1004 SchedulerSettings default_scheduler_settings
;
1005 Scheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
1006 scheduler
->SetCanStart();
1007 scheduler
->SetVisible(true);
1008 scheduler
->SetCanDraw(true);
1009 InitializeOutputSurfaceAndFirstCommit(scheduler
);
1011 // Request both draw and manage tiles. ManageTiles shouldn't
1012 // be trigged until BeginImplFrame.
1014 scheduler
->SetNeedsManageTiles();
1015 scheduler
->SetNeedsRedraw();
1016 EXPECT_TRUE(scheduler
->RedrawPending());
1017 EXPECT_TRUE(scheduler
->ManageTilesPending());
1018 EXPECT_TRUE(client
.needs_begin_impl_frame());
1019 EXPECT_EQ(0, client
.num_draws());
1020 EXPECT_FALSE(client
.HasAction("ScheduledActionManageTiles"));
1021 EXPECT_FALSE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1023 // We have no immediate actions to perform, so the BeginImplFrame should post
1024 // the deadline task.
1026 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1027 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
1029 // On the deadline, he actions should have occured in the right order.
1031 scheduler
->OnBeginImplFrameDeadline();
1032 EXPECT_EQ(1, client
.num_draws());
1033 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1034 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
1035 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1036 client
.ActionIndex("ScheduledActionManageTiles"));
1037 EXPECT_FALSE(scheduler
->RedrawPending());
1038 EXPECT_FALSE(scheduler
->ManageTilesPending());
1040 // Request a draw. We don't need a ManageTiles yet.
1042 scheduler
->SetNeedsRedraw();
1043 EXPECT_TRUE(scheduler
->RedrawPending());
1044 EXPECT_FALSE(scheduler
->ManageTilesPending());
1045 EXPECT_TRUE(client
.needs_begin_impl_frame());
1046 EXPECT_EQ(0, client
.num_draws());
1048 // We have no immediate actions to perform, so the BeginImplFrame should post
1049 // the deadline task.
1051 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1052 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
1054 // Draw. The draw will trigger SetNeedsManageTiles, and
1055 // then the ManageTiles action will be triggered after the Draw.
1056 // Afterwards, neither a draw nor ManageTiles are pending.
1058 scheduler
->OnBeginImplFrameDeadline();
1059 EXPECT_EQ(1, client
.num_draws());
1060 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1061 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
1062 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1063 client
.ActionIndex("ScheduledActionManageTiles"));
1064 EXPECT_FALSE(scheduler
->RedrawPending());
1065 EXPECT_FALSE(scheduler
->ManageTilesPending());
1067 // We need a BeginImplFrame where we don't swap to go idle.
1069 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1070 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
1072 scheduler
->OnBeginImplFrameDeadline();
1073 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client
);;
1074 EXPECT_EQ(0, client
.num_draws());
1076 // Now trigger a ManageTiles outside of a draw. We will then need
1077 // a begin-frame for the ManageTiles, but we don't need a draw.
1079 EXPECT_FALSE(client
.needs_begin_impl_frame());
1080 scheduler
->SetNeedsManageTiles();
1081 EXPECT_TRUE(client
.needs_begin_impl_frame());
1082 EXPECT_TRUE(scheduler
->ManageTilesPending());
1083 EXPECT_FALSE(scheduler
->RedrawPending());
1085 // BeginImplFrame. There will be no draw, only ManageTiles.
1087 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1088 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
1090 scheduler
->OnBeginImplFrameDeadline();
1091 EXPECT_EQ(0, client
.num_draws());
1092 EXPECT_FALSE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1093 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
1096 // Test that ManageTiles only happens once per frame. If an external caller
1097 // initiates it, then the state machine should not on that frame.
1098 TEST(SchedulerTest
, ManageTilesOncePerFrame
) {
1099 FakeSchedulerClient client
;
1100 SchedulerSettings default_scheduler_settings
;
1101 Scheduler
* scheduler
= client
.CreateScheduler(default_scheduler_settings
);
1102 scheduler
->SetCanStart();
1103 scheduler
->SetVisible(true);
1104 scheduler
->SetCanDraw(true);
1105 InitializeOutputSurfaceAndFirstCommit(scheduler
);
1107 // If DidManageTiles during a frame, then ManageTiles should not occur again.
1108 scheduler
->SetNeedsManageTiles();
1109 scheduler
->SetNeedsRedraw();
1111 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1112 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
1114 EXPECT_TRUE(scheduler
->ManageTilesPending());
1115 scheduler
->DidManageTiles();
1116 EXPECT_FALSE(scheduler
->ManageTilesPending());
1119 scheduler
->OnBeginImplFrameDeadline();
1120 EXPECT_EQ(1, client
.num_draws());
1121 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1122 EXPECT_FALSE(client
.HasAction("ScheduledActionManageTiles"));
1123 EXPECT_FALSE(scheduler
->RedrawPending());
1124 EXPECT_FALSE(scheduler
->ManageTilesPending());
1126 // Next frame without DidManageTiles should ManageTiles with draw.
1127 scheduler
->SetNeedsManageTiles();
1128 scheduler
->SetNeedsRedraw();
1130 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1131 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client
);
1134 scheduler
->OnBeginImplFrameDeadline();
1135 EXPECT_EQ(1, client
.num_draws());
1136 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1137 EXPECT_TRUE(client
.HasAction("ScheduledActionManageTiles"));
1138 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1139 client
.ActionIndex("ScheduledActionManageTiles"));
1140 EXPECT_FALSE(scheduler
->RedrawPending());
1141 EXPECT_FALSE(scheduler
->ManageTilesPending());
1144 class SchedulerClientWithFixedEstimates
: public FakeSchedulerClient
{
1146 SchedulerClientWithFixedEstimates(
1147 base::TimeDelta draw_duration
,
1148 base::TimeDelta begin_main_frame_to_commit_duration
,
1149 base::TimeDelta commit_to_activate_duration
)
1150 : draw_duration_(draw_duration
),
1151 begin_main_frame_to_commit_duration_(
1152 begin_main_frame_to_commit_duration
),
1153 commit_to_activate_duration_(commit_to_activate_duration
) {}
1155 virtual base::TimeDelta
DrawDurationEstimate() OVERRIDE
{
1156 return draw_duration_
;
1158 virtual base::TimeDelta
BeginMainFrameToCommitDurationEstimate() OVERRIDE
{
1159 return begin_main_frame_to_commit_duration_
;
1161 virtual base::TimeDelta
CommitToActivateDurationEstimate() OVERRIDE
{
1162 return commit_to_activate_duration_
;
1166 base::TimeDelta draw_duration_
;
1167 base::TimeDelta begin_main_frame_to_commit_duration_
;
1168 base::TimeDelta commit_to_activate_duration_
;
1171 void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms
,
1172 int64 commit_to_activate_estimate_in_ms
,
1173 bool should_send_begin_main_frame
) {
1174 // Set up client with specified estimates (draw duration is set to 1).
1175 SchedulerClientWithFixedEstimates
client(
1176 base::TimeDelta::FromMilliseconds(1),
1177 base::TimeDelta::FromMilliseconds(
1178 begin_main_frame_to_commit_estimate_in_ms
),
1179 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms
));
1180 SchedulerSettings scheduler_settings
;
1181 scheduler_settings
.deadline_scheduling_enabled
= true;
1182 scheduler_settings
.switch_to_low_latency_if_possible
= true;
1183 Scheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1184 scheduler
->SetCanStart();
1185 scheduler
->SetVisible(true);
1186 scheduler
->SetCanDraw(true);
1187 InitializeOutputSurfaceAndFirstCommit(scheduler
);
1189 // Impl thread hits deadline before commit finishes.
1191 scheduler
->SetNeedsCommit();
1192 EXPECT_FALSE(scheduler
->MainThreadIsInHighLatencyMode());
1193 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1194 EXPECT_FALSE(scheduler
->MainThreadIsInHighLatencyMode());
1195 scheduler
->OnBeginImplFrameDeadline();
1196 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1197 scheduler
->FinishCommit();
1198 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1199 EXPECT_TRUE(client
.HasAction("ScheduledActionSendBeginMainFrame"));
1202 scheduler
->SetNeedsCommit();
1203 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1204 scheduler
->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1205 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1206 scheduler
->OnBeginImplFrameDeadline();
1207 EXPECT_EQ(scheduler
->MainThreadIsInHighLatencyMode(),
1208 should_send_begin_main_frame
);
1209 EXPECT_EQ(client
.HasAction("ScheduledActionSendBeginMainFrame"),
1210 should_send_begin_main_frame
);
1214 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline
) {
1215 // Set up client so that estimates indicate that we can commit and activate
1216 // before the deadline (~8ms by default).
1217 MainFrameInHighLatencyMode(1, 1, false);
1220 TEST(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong
) {
1221 // Set up client so that estimates indicate that the commit cannot finish
1222 // before the deadline (~8ms by default).
1223 MainFrameInHighLatencyMode(10, 1, true);
1226 TEST(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong
) {
1227 // Set up client so that estimates indicate that the activate cannot finish
1228 // before the deadline (~8ms by default).
1229 MainFrameInHighLatencyMode(1, 10, true);
1232 void SpinForMillis(int millis
) {
1233 base::RunLoop run_loop
;
1234 base::MessageLoop::current()->PostDelayedTask(
1236 run_loop
.QuitClosure(),
1237 base::TimeDelta::FromMilliseconds(millis
));
1241 TEST(SchedulerTest
, PollForCommitCompletion
) {
1242 FakeSchedulerClient client
;
1243 client
.set_log_anticipated_draw_time_change(true);
1244 SchedulerSettings settings
= SchedulerSettings();
1245 settings
.throttle_frame_production
= false;
1246 Scheduler
* scheduler
= client
.CreateScheduler(settings
);
1248 scheduler
->SetCanDraw(true);
1249 scheduler
->SetCanStart();
1250 scheduler
->SetVisible(true);
1251 scheduler
->DidCreateAndInitializeOutputSurface();
1253 scheduler
->SetNeedsCommit();
1254 EXPECT_TRUE(scheduler
->CommitPending());
1255 scheduler
->FinishCommit();
1256 scheduler
->SetNeedsRedraw();
1257 BeginFrameArgs impl_frame_args
= BeginFrameArgs::CreateForTesting();
1258 const int interval
= 1;
1259 impl_frame_args
.interval
= base::TimeDelta::FromMilliseconds(interval
);
1260 scheduler
->BeginImplFrame(impl_frame_args
);
1261 scheduler
->OnBeginImplFrameDeadline();
1263 // At this point, we've drawn a frame. Start another commit, but hold off on
1264 // the FinishCommit for now.
1265 EXPECT_FALSE(scheduler
->CommitPending());
1266 scheduler
->SetNeedsCommit();
1267 EXPECT_TRUE(scheduler
->CommitPending());
1269 // Spin the event loop a few times and make sure we get more
1270 // DidAnticipateDrawTimeChange calls every time.
1271 int actions_so_far
= client
.num_actions_();
1273 // Does three iterations to make sure that the timer is properly repeating.
1274 for (int i
= 0; i
< 3; ++i
) {
1275 // Wait for 2x the frame interval to match
1276 // cc::Scheduler::advance_commit_state_timer_'s rate.
1277 SpinForMillis(interval
* 2);
1278 EXPECT_GT(client
.num_actions_(), actions_so_far
);
1279 EXPECT_STREQ(client
.Action(client
.num_actions_() - 1),
1280 "DidAnticipatedDrawTimeChange");
1281 actions_so_far
= client
.num_actions_();