NativeViewHost should query its native view for the current cursor
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blobfcd73a86d295b71012d34263b54bd03624e16c4e
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"
6 #include <string>
7 #include <vector>
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_()); \
21 do { \
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); \
26 } while (false)
28 #define EXPECT_SINGLE_ACTION(action, client) \
29 EXPECT_ACTION(action, client, 0, 1)
31 namespace cc {
32 namespace {
34 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler) {
35 scheduler->DidCreateAndInitializeOutputSurface();
36 scheduler->SetNeedsCommit();
37 scheduler->NotifyBeginMainFrameStarted();
38 scheduler->NotifyReadyToCommit();
39 // Go through the motions to draw the commit.
40 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
41 scheduler->OnBeginImplFrameDeadline();
42 // We need another BeginImplFrame so Scheduler calls
43 // SetNeedsBeginImplFrame(false).
44 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
45 scheduler->OnBeginImplFrameDeadline();
48 class FakeSchedulerClient : public SchedulerClient {
49 public:
50 FakeSchedulerClient()
51 : needs_begin_impl_frame_(false) {
52 Reset();
55 void Reset() {
56 actions_.clear();
57 states_.clear();
58 draw_will_happen_ = true;
59 swap_will_happen_if_draw_happens_ = true;
60 num_draws_ = 0;
61 log_anticipated_draw_time_change_ = false;
64 Scheduler* CreateScheduler(const SchedulerSettings& settings) {
65 scheduler_ = Scheduler::Create(this, settings, 0);
66 return scheduler_.get();
69 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
70 // for tests that do.
71 void set_log_anticipated_draw_time_change(bool log) {
72 log_anticipated_draw_time_change_ = log;
74 bool needs_begin_impl_frame() { return needs_begin_impl_frame_; }
75 int num_draws() const { return num_draws_; }
76 int num_actions_() const { return static_cast<int>(actions_.size()); }
77 const char* Action(int i) const { return actions_[i]; }
78 base::Value& StateForAction(int i) const { return *states_[i]; }
79 base::TimeTicks posted_begin_impl_frame_deadline() const {
80 return posted_begin_impl_frame_deadline_;
83 int ActionIndex(const char* action) const {
84 for (size_t i = 0; i < actions_.size(); i++)
85 if (!strcmp(actions_[i], action))
86 return i;
87 return -1;
90 bool HasAction(const char* action) const {
91 return ActionIndex(action) >= 0;
94 void SetDrawWillHappen(bool draw_will_happen) {
95 draw_will_happen_ = draw_will_happen;
97 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
98 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
101 // SchedulerClient implementation.
102 virtual void SetNeedsBeginImplFrame(bool enable) OVERRIDE {
103 actions_.push_back("SetNeedsBeginImplFrame");
104 states_.push_back(scheduler_->StateAsValue().release());
105 needs_begin_impl_frame_ = enable;
107 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
108 actions_.push_back("ScheduledActionSendBeginMainFrame");
109 states_.push_back(scheduler_->StateAsValue().release());
111 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
112 OVERRIDE {
113 actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
114 states_.push_back(scheduler_->StateAsValue().release());
115 num_draws_++;
116 bool did_readback = false;
117 DrawSwapReadbackResult::DrawResult result =
118 draw_will_happen_
119 ? DrawSwapReadbackResult::DRAW_SUCCESS
120 : DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
121 return DrawSwapReadbackResult(
122 result,
123 draw_will_happen_ && swap_will_happen_if_draw_happens_,
124 did_readback);
126 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
127 actions_.push_back("ScheduledActionDrawAndSwapForced");
128 states_.push_back(scheduler_->StateAsValue().release());
129 bool did_swap = swap_will_happen_if_draw_happens_;
130 bool did_readback = false;
131 return DrawSwapReadbackResult(
132 DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
134 virtual DrawSwapReadbackResult ScheduledActionDrawAndReadback() OVERRIDE {
135 actions_.push_back("ScheduledActionDrawAndReadback");
136 states_.push_back(scheduler_->StateAsValue().release());
137 bool did_swap = false;
138 bool did_readback = true;
139 return DrawSwapReadbackResult(
140 DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
142 virtual void ScheduledActionCommit() OVERRIDE {
143 actions_.push_back("ScheduledActionCommit");
144 states_.push_back(scheduler_->StateAsValue().release());
146 virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE {
147 actions_.push_back("ScheduledActionUpdateVisibleTiles");
148 states_.push_back(scheduler_->StateAsValue().release());
150 virtual void ScheduledActionActivatePendingTree() OVERRIDE {
151 actions_.push_back("ScheduledActionActivatePendingTree");
152 states_.push_back(scheduler_->StateAsValue().release());
154 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
155 actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
156 states_.push_back(scheduler_->StateAsValue().release());
158 virtual void ScheduledActionAcquireLayerTexturesForMainThread() OVERRIDE {
159 actions_.push_back("ScheduledActionAcquireLayerTexturesForMainThread");
160 states_.push_back(scheduler_->StateAsValue().release());
162 virtual void ScheduledActionManageTiles() OVERRIDE {
163 actions_.push_back("ScheduledActionManageTiles");
164 states_.push_back(scheduler_->StateAsValue().release());
166 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {
167 if (log_anticipated_draw_time_change_)
168 actions_.push_back("DidAnticipatedDrawTimeChange");
170 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
171 return base::TimeDelta();
173 virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
174 return base::TimeDelta();
176 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
177 return base::TimeDelta();
180 virtual void PostBeginImplFrameDeadline(const base::Closure& closure,
181 base::TimeTicks deadline) OVERRIDE {
182 actions_.push_back("PostBeginImplFrameDeadlineTask");
183 states_.push_back(scheduler_->StateAsValue().release());
184 posted_begin_impl_frame_deadline_ = deadline;
187 virtual void DidBeginImplFrameDeadline() OVERRIDE {}
189 protected:
190 bool needs_begin_impl_frame_;
191 bool draw_will_happen_;
192 bool swap_will_happen_if_draw_happens_;
193 int num_draws_;
194 bool log_anticipated_draw_time_change_;
195 base::TimeTicks posted_begin_impl_frame_deadline_;
196 std::vector<const char*> actions_;
197 ScopedVector<base::Value> states_;
198 scoped_ptr<Scheduler> scheduler_;
201 TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
202 FakeSchedulerClient client;
203 SchedulerSettings default_scheduler_settings;
204 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
205 scheduler->SetCanStart();
206 scheduler->SetVisible(true);
207 scheduler->SetCanDraw(true);
209 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
210 client.Reset();
211 scheduler->DidCreateAndInitializeOutputSurface();
212 EXPECT_EQ(0, client.num_actions_());
215 TEST(SchedulerTest, RequestCommit) {
216 FakeSchedulerClient client;
217 SchedulerSettings scheduler_settings;
218 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
219 scheduler->SetCanStart();
220 scheduler->SetVisible(true);
221 scheduler->SetCanDraw(true);
223 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
224 InitializeOutputSurfaceAndFirstCommit(scheduler);
226 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
227 client.Reset();
228 scheduler->SetNeedsCommit();
229 EXPECT_TRUE(client.needs_begin_impl_frame());
230 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
231 client.Reset();
233 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
234 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
235 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
236 EXPECT_TRUE(client.needs_begin_impl_frame());
237 client.Reset();
239 // If we don't swap on the deadline, we need to request another
240 // BeginImplFrame.
241 scheduler->OnBeginImplFrameDeadline();
242 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
243 EXPECT_TRUE(client.needs_begin_impl_frame());
244 client.Reset();
246 // NotifyReadyToCommit should trigger the commit.
247 scheduler->NotifyBeginMainFrameStarted();
248 scheduler->NotifyReadyToCommit();
249 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
250 EXPECT_TRUE(client.needs_begin_impl_frame());
251 client.Reset();
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());
257 client.Reset();
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());
264 client.Reset();
266 // The following BeginImplFrame deadline should SetNeedsBeginImplFrame(false)
267 // to avoid excessive toggles.
268 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
269 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
270 client.Reset();
272 scheduler->OnBeginImplFrameDeadline();
273 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
274 EXPECT_FALSE(client.needs_begin_impl_frame());
275 client.Reset();
278 TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
279 FakeSchedulerClient client;
280 SchedulerSettings scheduler_settings;
281 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
282 scheduler->SetCanStart();
283 scheduler->SetVisible(true);
284 scheduler->SetCanDraw(true);
286 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
287 InitializeOutputSurfaceAndFirstCommit(scheduler);
288 client.Reset();
290 // SetNeedsCommit should begin the frame.
291 scheduler->SetNeedsCommit();
292 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
294 client.Reset();
295 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
296 EXPECT_EQ(client.num_actions_(), 2);
297 EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
298 EXPECT_TRUE(client.HasAction("PostBeginImplFrameDeadlineTask"));
300 EXPECT_TRUE(client.needs_begin_impl_frame());
301 client.Reset();
303 // Now SetNeedsCommit again. Calling here means we need a second commit.
304 scheduler->SetNeedsCommit();
305 EXPECT_EQ(client.num_actions_(), 0);
306 client.Reset();
308 // Finish the first commit.
309 scheduler->NotifyBeginMainFrameStarted();
310 scheduler->NotifyReadyToCommit();
311 EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
312 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
313 client.Reset();
314 scheduler->OnBeginImplFrameDeadline();
315 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
316 EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
318 // Because we just swapped, the Scheduler should also request the next
319 // BeginImplFrame from the OutputSurface.
320 EXPECT_TRUE(client.needs_begin_impl_frame());
321 client.Reset();
323 // Since another commit is needed, the next BeginImplFrame should initiate
324 // the second commit.
325 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
326 EXPECT_EQ(client.num_actions_(), 2);
327 EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
328 EXPECT_TRUE(client.HasAction("PostBeginImplFrameDeadlineTask"));
329 client.Reset();
331 // Finishing the commit before the deadline should post a new deadline task
332 // to trigger the deadline early.
333 scheduler->NotifyBeginMainFrameStarted();
334 scheduler->NotifyReadyToCommit();
335 EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
336 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
337 client.Reset();
338 scheduler->OnBeginImplFrameDeadline();
339 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
340 EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
341 EXPECT_TRUE(client.needs_begin_impl_frame());
342 client.Reset();
344 // On the next BeginImplFrame, verify we go back to a quiescent state and
345 // no longer request BeginImplFrames.
346 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
347 scheduler->OnBeginImplFrameDeadline();
348 EXPECT_FALSE(client.needs_begin_impl_frame());
349 client.Reset();
352 TEST(SchedulerTest, TextureAcquisitionCausesCommitInsteadOfDraw) {
353 FakeSchedulerClient client;
354 SchedulerSettings scheduler_settings;
355 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
356 scheduler->SetCanStart();
357 scheduler->SetVisible(true);
358 scheduler->SetCanDraw(true);
359 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
361 InitializeOutputSurfaceAndFirstCommit(scheduler);
362 client.Reset();
363 scheduler->SetNeedsRedraw();
364 EXPECT_TRUE(scheduler->RedrawPending());
365 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
366 EXPECT_TRUE(client.needs_begin_impl_frame());
368 client.Reset();
369 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
370 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
371 client.Reset();
372 scheduler->OnBeginImplFrameDeadline();
373 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
374 EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
375 EXPECT_FALSE(scheduler->RedrawPending());
376 EXPECT_TRUE(client.needs_begin_impl_frame());
378 client.Reset();
379 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
380 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
381 client.Reset();
382 scheduler->OnBeginImplFrameDeadline();
383 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
384 EXPECT_FALSE(scheduler->RedrawPending());
385 EXPECT_FALSE(client.needs_begin_impl_frame());
387 client.Reset();
388 scheduler->SetMainThreadNeedsLayerTextures();
389 EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
390 client);
392 // We should request a BeginImplFrame in anticipation of a draw.
393 client.Reset();
394 scheduler->SetNeedsRedraw();
395 EXPECT_TRUE(scheduler->RedrawPending());
396 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
397 EXPECT_TRUE(client.needs_begin_impl_frame());
399 // No draw happens since the textures are acquired by the main thread.
400 client.Reset();
401 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
402 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
403 client.Reset();
404 scheduler->OnBeginImplFrameDeadline();
405 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
406 EXPECT_TRUE(scheduler->RedrawPending());
407 EXPECT_TRUE(client.needs_begin_impl_frame());
409 client.Reset();
410 scheduler->SetNeedsCommit();
411 EXPECT_EQ(0, client.num_actions_());
413 client.Reset();
414 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
415 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
416 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
418 // Commit will release the texture.
419 client.Reset();
420 scheduler->NotifyBeginMainFrameStarted();
421 scheduler->NotifyReadyToCommit();
422 EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
423 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
424 EXPECT_TRUE(scheduler->RedrawPending());
426 // Now we can draw again after the commit happens.
427 client.Reset();
428 scheduler->OnBeginImplFrameDeadline();
429 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
430 EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
431 EXPECT_FALSE(scheduler->RedrawPending());
432 EXPECT_TRUE(client.needs_begin_impl_frame());
434 // Make sure we stop requesting BeginImplFrames if we don't swap.
435 client.Reset();
436 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
437 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
438 client.Reset();
439 scheduler->OnBeginImplFrameDeadline();
440 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
441 EXPECT_FALSE(client.needs_begin_impl_frame());
444 TEST(SchedulerTest, TextureAcquisitionCollision) {
445 FakeSchedulerClient client;
446 SchedulerSettings scheduler_settings;
447 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
448 scheduler->SetCanStart();
449 scheduler->SetVisible(true);
450 scheduler->SetCanDraw(true);
452 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
453 InitializeOutputSurfaceAndFirstCommit(scheduler);
455 client.Reset();
456 scheduler->SetNeedsCommit();
457 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
459 client.Reset();
460 scheduler->SetMainThreadNeedsLayerTextures();
461 EXPECT_SINGLE_ACTION(
462 "ScheduledActionAcquireLayerTexturesForMainThread", client);
464 client.Reset();
465 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
466 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
467 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
469 client.Reset();
470 scheduler->OnBeginImplFrameDeadline();
471 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
473 // Although the compositor cannot draw because textures are locked by main
474 // thread, we continue requesting SetNeedsBeginImplFrame in anticipation of
475 // the unlock.
476 EXPECT_TRUE(client.needs_begin_impl_frame());
478 // Trigger the commit.
479 scheduler->NotifyBeginMainFrameStarted();
480 scheduler->NotifyReadyToCommit();
481 EXPECT_TRUE(client.needs_begin_impl_frame());
483 // Between commit and draw, texture acquisition for main thread delayed,
484 // and main thread blocks.
485 client.Reset();
486 scheduler->SetMainThreadNeedsLayerTextures();
487 EXPECT_EQ(0, client.num_actions_());
489 // No implicit commit is expected.
490 client.Reset();
491 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
492 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
494 client.Reset();
495 scheduler->OnBeginImplFrameDeadline();
496 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
497 EXPECT_ACTION(
498 "ScheduledActionAcquireLayerTexturesForMainThread", client, 1, 3);
499 EXPECT_ACTION("SetNeedsBeginImplFrame", client, 2, 3);
500 EXPECT_TRUE(client.needs_begin_impl_frame());
502 // The compositor should not draw because textures are locked by main
503 // thread.
504 client.Reset();
505 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
506 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
507 client.Reset();
508 scheduler->OnBeginImplFrameDeadline();
509 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
510 EXPECT_FALSE(client.needs_begin_impl_frame());
512 // The impl thread need an explicit commit from the main thread to lock
513 // the textures.
514 client.Reset();
515 scheduler->SetNeedsCommit();
516 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
517 EXPECT_TRUE(client.needs_begin_impl_frame());
519 client.Reset();
520 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
521 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
522 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
523 client.Reset();
525 // Trigger the commit, which will trigger the deadline task early.
526 scheduler->NotifyBeginMainFrameStarted();
527 scheduler->NotifyReadyToCommit();
528 EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
529 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
530 EXPECT_TRUE(client.needs_begin_impl_frame());
531 client.Reset();
533 // Verify we draw on the next BeginImplFrame deadline
534 scheduler->OnBeginImplFrameDeadline();
535 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
536 EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
537 EXPECT_TRUE(client.needs_begin_impl_frame());
538 client.Reset();
541 TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition) {
542 FakeSchedulerClient client;
543 SchedulerSettings scheduler_settings;
544 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
545 scheduler->SetCanStart();
546 scheduler->SetVisible(true);
547 scheduler->SetCanDraw(true);
549 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
550 client.Reset();
551 scheduler->DidCreateAndInitializeOutputSurface();
553 scheduler->SetNeedsCommit();
554 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
555 scheduler->OnBeginImplFrameDeadline();
556 scheduler->NotifyBeginMainFrameStarted();
557 scheduler->NotifyReadyToCommit();
558 scheduler->SetMainThreadNeedsLayerTextures();
559 scheduler->SetNeedsCommit();
560 client.Reset();
561 // Verify that pending texture acquisition fires when visibility
562 // is lost in order to avoid a deadlock.
563 scheduler->SetVisible(false);
564 EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
565 client);
567 client.Reset();
568 scheduler->SetVisible(true);
569 EXPECT_EQ(0, client.num_actions_());
570 EXPECT_TRUE(client.needs_begin_impl_frame());
572 // Regaining visibility with textures acquired by main thread while
573 // compositor is waiting for first draw should result in a request
574 // for a new frame in order to escape a deadlock.
575 client.Reset();
576 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
577 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
578 EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
581 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
582 public:
583 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
584 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
585 OVERRIDE {
586 // Only SetNeedsRedraw the first time this is called
587 if (!num_draws_)
588 scheduler_->SetNeedsRedraw();
589 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
592 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
593 NOTREACHED();
594 bool did_swap = true;
595 bool did_readback = false;
596 return DrawSwapReadbackResult(
597 DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
600 virtual void ScheduledActionCommit() OVERRIDE {}
601 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
602 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
605 // Tests for two different situations:
606 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
607 // a ScheduledActionDrawAndSwap
608 // 2. the scheduler drawing twice inside a single tick
609 TEST(SchedulerTest, RequestRedrawInsideDraw) {
610 SchedulerClientThatsetNeedsDrawInsideDraw client;
611 SchedulerSettings default_scheduler_settings;
612 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
613 scheduler->SetCanStart();
614 scheduler->SetVisible(true);
615 scheduler->SetCanDraw(true);
616 InitializeOutputSurfaceAndFirstCommit(scheduler);
617 client.Reset();
619 scheduler->SetNeedsRedraw();
620 EXPECT_TRUE(scheduler->RedrawPending());
621 EXPECT_TRUE(client.needs_begin_impl_frame());
622 EXPECT_EQ(0, client.num_draws());
624 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
625 scheduler->OnBeginImplFrameDeadline();
626 EXPECT_EQ(1, client.num_draws());
627 EXPECT_TRUE(scheduler->RedrawPending());
628 EXPECT_TRUE(client.needs_begin_impl_frame());
630 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
631 scheduler->OnBeginImplFrameDeadline();
632 EXPECT_EQ(2, client.num_draws());
633 EXPECT_FALSE(scheduler->RedrawPending());
634 EXPECT_TRUE(client.needs_begin_impl_frame());
636 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
637 // swap.
638 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
639 scheduler->OnBeginImplFrameDeadline();
640 EXPECT_EQ(2, client.num_draws());
641 EXPECT_FALSE(scheduler->RedrawPending());
642 EXPECT_FALSE(client.needs_begin_impl_frame());
645 // Test that requesting redraw inside a failed draw doesn't lose the request.
646 TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
647 SchedulerClientThatsetNeedsDrawInsideDraw client;
648 SchedulerSettings default_scheduler_settings;
649 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
650 scheduler->SetCanStart();
651 scheduler->SetVisible(true);
652 scheduler->SetCanDraw(true);
653 InitializeOutputSurfaceAndFirstCommit(scheduler);
654 client.Reset();
656 client.SetDrawWillHappen(false);
658 scheduler->SetNeedsRedraw();
659 EXPECT_TRUE(scheduler->RedrawPending());
660 EXPECT_TRUE(client.needs_begin_impl_frame());
661 EXPECT_EQ(0, client.num_draws());
663 // Fail the draw.
664 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
665 scheduler->OnBeginImplFrameDeadline();
666 EXPECT_EQ(1, client.num_draws());
668 // We have a commit pending and the draw failed, and we didn't lose the redraw
669 // request.
670 EXPECT_TRUE(scheduler->CommitPending());
671 EXPECT_TRUE(scheduler->RedrawPending());
672 EXPECT_TRUE(client.needs_begin_impl_frame());
674 // Fail the draw again.
675 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
676 scheduler->OnBeginImplFrameDeadline();
677 EXPECT_EQ(2, client.num_draws());
678 EXPECT_TRUE(scheduler->CommitPending());
679 EXPECT_TRUE(scheduler->RedrawPending());
680 EXPECT_TRUE(client.needs_begin_impl_frame());
682 // Draw successfully.
683 client.SetDrawWillHappen(true);
684 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
685 scheduler->OnBeginImplFrameDeadline();
686 EXPECT_EQ(3, client.num_draws());
687 EXPECT_TRUE(scheduler->CommitPending());
688 EXPECT_FALSE(scheduler->RedrawPending());
689 EXPECT_TRUE(client.needs_begin_impl_frame());
692 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
693 public:
694 SchedulerClientThatSetNeedsCommitInsideDraw()
695 : set_needs_commit_on_next_draw_(false) {}
697 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
698 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
699 OVERRIDE {
700 // Only SetNeedsCommit the first time this is called
701 if (set_needs_commit_on_next_draw_) {
702 scheduler_->SetNeedsCommit();
703 set_needs_commit_on_next_draw_ = false;
705 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
708 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
709 NOTREACHED();
710 bool did_swap = false;
711 bool did_readback = false;
712 return DrawSwapReadbackResult(
713 DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
716 virtual void ScheduledActionCommit() OVERRIDE {}
717 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
718 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
720 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
722 private:
723 bool set_needs_commit_on_next_draw_;
726 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
727 // happen inside a ScheduledActionDrawAndSwap
728 TEST(SchedulerTest, RequestCommitInsideDraw) {
729 SchedulerClientThatSetNeedsCommitInsideDraw client;
730 SchedulerSettings default_scheduler_settings;
731 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
732 scheduler->SetCanStart();
733 scheduler->SetVisible(true);
734 scheduler->SetCanDraw(true);
735 InitializeOutputSurfaceAndFirstCommit(scheduler);
736 client.Reset();
738 EXPECT_FALSE(client.needs_begin_impl_frame());
739 scheduler->SetNeedsRedraw();
740 EXPECT_TRUE(scheduler->RedrawPending());
741 EXPECT_EQ(0, client.num_draws());
742 EXPECT_TRUE(client.needs_begin_impl_frame());
744 client.SetNeedsCommitOnNextDraw();
745 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
746 client.SetNeedsCommitOnNextDraw();
747 scheduler->OnBeginImplFrameDeadline();
748 EXPECT_EQ(1, client.num_draws());
749 EXPECT_TRUE(scheduler->CommitPending());
750 EXPECT_TRUE(client.needs_begin_impl_frame());
751 scheduler->NotifyBeginMainFrameStarted();
752 scheduler->NotifyReadyToCommit();
754 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
755 scheduler->OnBeginImplFrameDeadline();
756 EXPECT_EQ(2, client.num_draws());
758 EXPECT_FALSE(scheduler->RedrawPending());
759 EXPECT_FALSE(scheduler->CommitPending());
760 EXPECT_TRUE(client.needs_begin_impl_frame());
762 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
763 // swap.
764 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
765 scheduler->OnBeginImplFrameDeadline();
766 EXPECT_EQ(2, client.num_draws());
767 EXPECT_FALSE(scheduler->RedrawPending());
768 EXPECT_FALSE(scheduler->CommitPending());
769 EXPECT_FALSE(client.needs_begin_impl_frame());
772 // Tests that when a draw fails then the pending commit should not be dropped.
773 TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
774 SchedulerClientThatsetNeedsDrawInsideDraw client;
775 SchedulerSettings default_scheduler_settings;
776 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
777 scheduler->SetCanStart();
778 scheduler->SetVisible(true);
779 scheduler->SetCanDraw(true);
780 InitializeOutputSurfaceAndFirstCommit(scheduler);
781 client.Reset();
783 client.SetDrawWillHappen(false);
785 scheduler->SetNeedsRedraw();
786 EXPECT_TRUE(scheduler->RedrawPending());
787 EXPECT_TRUE(client.needs_begin_impl_frame());
788 EXPECT_EQ(0, client.num_draws());
790 // Fail the draw.
791 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
792 scheduler->OnBeginImplFrameDeadline();
793 EXPECT_EQ(1, client.num_draws());
795 // We have a commit pending and the draw failed, and we didn't lose the commit
796 // request.
797 EXPECT_TRUE(scheduler->CommitPending());
798 EXPECT_TRUE(scheduler->RedrawPending());
799 EXPECT_TRUE(client.needs_begin_impl_frame());
801 // Fail the draw again.
802 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
803 scheduler->OnBeginImplFrameDeadline();
804 EXPECT_EQ(2, client.num_draws());
805 EXPECT_TRUE(scheduler->CommitPending());
806 EXPECT_TRUE(scheduler->RedrawPending());
807 EXPECT_TRUE(client.needs_begin_impl_frame());
809 // Draw successfully.
810 client.SetDrawWillHappen(true);
811 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
812 scheduler->OnBeginImplFrameDeadline();
813 EXPECT_EQ(3, client.num_draws());
814 EXPECT_TRUE(scheduler->CommitPending());
815 EXPECT_FALSE(scheduler->RedrawPending());
816 EXPECT_TRUE(client.needs_begin_impl_frame());
819 TEST(SchedulerTest, NoSwapWhenDrawFails) {
820 SchedulerClientThatSetNeedsCommitInsideDraw client;
821 SchedulerSettings default_scheduler_settings;
822 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
823 scheduler->SetCanStart();
824 scheduler->SetVisible(true);
825 scheduler->SetCanDraw(true);
826 InitializeOutputSurfaceAndFirstCommit(scheduler);
827 client.Reset();
829 scheduler->SetNeedsRedraw();
830 EXPECT_TRUE(scheduler->RedrawPending());
831 EXPECT_TRUE(client.needs_begin_impl_frame());
832 EXPECT_EQ(0, client.num_draws());
834 // Draw successfully, this starts a new frame.
835 client.SetNeedsCommitOnNextDraw();
836 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
837 scheduler->OnBeginImplFrameDeadline();
838 EXPECT_EQ(1, client.num_draws());
840 scheduler->SetNeedsRedraw();
841 EXPECT_TRUE(scheduler->RedrawPending());
842 EXPECT_TRUE(client.needs_begin_impl_frame());
844 // Fail to draw, this should not start a frame.
845 client.SetDrawWillHappen(false);
846 client.SetNeedsCommitOnNextDraw();
847 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
848 scheduler->OnBeginImplFrameDeadline();
849 EXPECT_EQ(2, client.num_draws());
852 TEST(SchedulerTest, NoSwapWhenSwapFailsDuringForcedCommit) {
853 FakeSchedulerClient client;
854 SchedulerSettings default_scheduler_settings;
855 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
857 // Tell the client that it will fail to swap.
858 client.SetDrawWillHappen(true);
859 client.SetSwapWillHappenIfDrawHappens(false);
861 // Get the compositor to do a ScheduledActionDrawAndReadback.
862 scheduler->SetCanDraw(true);
863 scheduler->SetNeedsRedraw();
864 scheduler->SetNeedsForcedCommitForReadback();
865 scheduler->NotifyBeginMainFrameStarted();
866 scheduler->NotifyReadyToCommit();
867 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
870 TEST(SchedulerTest, BackToBackReadbackAllowed) {
871 // Some clients call readbacks twice in a row before the replacement
872 // commit comes in. Make sure it is allowed.
873 FakeSchedulerClient client;
874 SchedulerSettings default_scheduler_settings;
875 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
877 // Get the compositor to do 2 ScheduledActionDrawAndReadbacks before
878 // the replacement commit comes in.
879 scheduler->SetCanDraw(true);
880 scheduler->SetNeedsRedraw();
881 scheduler->SetNeedsForcedCommitForReadback();
882 scheduler->NotifyBeginMainFrameStarted();
883 scheduler->NotifyReadyToCommit();
884 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
886 client.Reset();
887 scheduler->SetNeedsForcedCommitForReadback();
888 scheduler->NotifyBeginMainFrameStarted();
889 scheduler->NotifyReadyToCommit();
890 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
892 // The replacement commit comes in after 2 readbacks.
893 client.Reset();
894 scheduler->NotifyBeginMainFrameStarted();
895 scheduler->NotifyReadyToCommit();
899 class SchedulerClientNeedsManageTilesInDraw : public FakeSchedulerClient {
900 public:
901 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
902 OVERRIDE {
903 scheduler_->SetNeedsManageTiles();
904 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
908 // Test manage tiles is independant of draws.
909 TEST(SchedulerTest, ManageTiles) {
910 SchedulerClientNeedsManageTilesInDraw client;
911 SchedulerSettings default_scheduler_settings;
912 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
913 scheduler->SetCanStart();
914 scheduler->SetVisible(true);
915 scheduler->SetCanDraw(true);
916 InitializeOutputSurfaceAndFirstCommit(scheduler);
918 // Request both draw and manage tiles. ManageTiles shouldn't
919 // be trigged until BeginImplFrame.
920 client.Reset();
921 scheduler->SetNeedsManageTiles();
922 scheduler->SetNeedsRedraw();
923 EXPECT_TRUE(scheduler->RedrawPending());
924 EXPECT_TRUE(scheduler->ManageTilesPending());
925 EXPECT_TRUE(client.needs_begin_impl_frame());
926 EXPECT_EQ(0, client.num_draws());
927 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
928 EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
930 // We have no immediate actions to perform, so the BeginImplFrame should post
931 // the deadline task.
932 client.Reset();
933 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
934 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
936 // On the deadline, he actions should have occured in the right order.
937 client.Reset();
938 scheduler->OnBeginImplFrameDeadline();
939 EXPECT_EQ(1, client.num_draws());
940 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
941 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
942 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
943 client.ActionIndex("ScheduledActionManageTiles"));
944 EXPECT_FALSE(scheduler->RedrawPending());
945 EXPECT_FALSE(scheduler->ManageTilesPending());
947 // Request a draw. We don't need a ManageTiles yet.
948 client.Reset();
949 scheduler->SetNeedsRedraw();
950 EXPECT_TRUE(scheduler->RedrawPending());
951 EXPECT_FALSE(scheduler->ManageTilesPending());
952 EXPECT_TRUE(client.needs_begin_impl_frame());
953 EXPECT_EQ(0, client.num_draws());
955 // We have no immediate actions to perform, so the BeginImplFrame should post
956 // the deadline task.
957 client.Reset();
958 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
959 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
961 // Draw. The draw will trigger SetNeedsManageTiles, and
962 // then the ManageTiles action will be triggered after the Draw.
963 // Afterwards, neither a draw nor ManageTiles are pending.
964 client.Reset();
965 scheduler->OnBeginImplFrameDeadline();
966 EXPECT_EQ(1, client.num_draws());
967 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
968 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
969 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
970 client.ActionIndex("ScheduledActionManageTiles"));
971 EXPECT_FALSE(scheduler->RedrawPending());
972 EXPECT_FALSE(scheduler->ManageTilesPending());
974 // We need a BeginImplFrame where we don't swap to go idle.
975 client.Reset();
976 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
977 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
978 client.Reset();
979 scheduler->OnBeginImplFrameDeadline();
980 EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
981 EXPECT_EQ(0, client.num_draws());
983 // Now trigger a ManageTiles outside of a draw. We will then need
984 // a begin-frame for the ManageTiles, but we don't need a draw.
985 client.Reset();
986 EXPECT_FALSE(client.needs_begin_impl_frame());
987 scheduler->SetNeedsManageTiles();
988 EXPECT_TRUE(client.needs_begin_impl_frame());
989 EXPECT_TRUE(scheduler->ManageTilesPending());
990 EXPECT_FALSE(scheduler->RedrawPending());
992 // BeginImplFrame. There will be no draw, only ManageTiles.
993 client.Reset();
994 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
995 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
996 client.Reset();
997 scheduler->OnBeginImplFrameDeadline();
998 EXPECT_EQ(0, client.num_draws());
999 EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1000 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
1003 // Test that ManageTiles only happens once per frame. If an external caller
1004 // initiates it, then the state machine should not ManageTiles on that frame.
1005 TEST(SchedulerTest, ManageTilesOncePerFrame) {
1006 FakeSchedulerClient client;
1007 SchedulerSettings default_scheduler_settings;
1008 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
1009 scheduler->SetCanStart();
1010 scheduler->SetVisible(true);
1011 scheduler->SetCanDraw(true);
1012 InitializeOutputSurfaceAndFirstCommit(scheduler);
1014 // If DidManageTiles during a frame, then ManageTiles should not occur again.
1015 scheduler->SetNeedsManageTiles();
1016 scheduler->SetNeedsRedraw();
1017 client.Reset();
1018 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1019 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
1021 EXPECT_TRUE(scheduler->ManageTilesPending());
1022 scheduler->DidManageTiles(); // An explicit ManageTiles.
1023 EXPECT_FALSE(scheduler->ManageTilesPending());
1025 client.Reset();
1026 scheduler->OnBeginImplFrameDeadline();
1027 EXPECT_EQ(1, client.num_draws());
1028 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1029 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
1030 EXPECT_FALSE(scheduler->RedrawPending());
1031 EXPECT_FALSE(scheduler->ManageTilesPending());
1033 // Next frame without DidManageTiles should ManageTiles with draw.
1034 scheduler->SetNeedsManageTiles();
1035 scheduler->SetNeedsRedraw();
1036 client.Reset();
1037 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1038 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
1040 client.Reset();
1041 scheduler->OnBeginImplFrameDeadline();
1042 EXPECT_EQ(1, client.num_draws());
1043 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1044 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
1045 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1046 client.ActionIndex("ScheduledActionManageTiles"));
1047 EXPECT_FALSE(scheduler->RedrawPending());
1048 EXPECT_FALSE(scheduler->ManageTilesPending());
1049 scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
1051 // If we get another DidManageTiles within the same frame, we should
1052 // not ManageTiles on the next frame.
1053 scheduler->DidManageTiles(); // An explicit ManageTiles.
1054 scheduler->SetNeedsManageTiles();
1055 scheduler->SetNeedsRedraw();
1056 client.Reset();
1057 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1058 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
1060 EXPECT_TRUE(scheduler->ManageTilesPending());
1062 client.Reset();
1063 scheduler->OnBeginImplFrameDeadline();
1064 EXPECT_EQ(1, client.num_draws());
1065 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1066 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
1067 EXPECT_FALSE(scheduler->RedrawPending());
1069 // If we get another DidManageTiles, we should not ManageTiles on the next
1070 // frame. This verifies we don't alternate calling ManageTiles once and twice.
1071 EXPECT_TRUE(scheduler->ManageTilesPending());
1072 scheduler->DidManageTiles(); // An explicit ManageTiles.
1073 EXPECT_FALSE(scheduler->ManageTilesPending());
1074 scheduler->SetNeedsManageTiles();
1075 scheduler->SetNeedsRedraw();
1076 client.Reset();
1077 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1078 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
1080 EXPECT_TRUE(scheduler->ManageTilesPending());
1082 client.Reset();
1083 scheduler->OnBeginImplFrameDeadline();
1084 EXPECT_EQ(1, client.num_draws());
1085 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1086 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
1087 EXPECT_FALSE(scheduler->RedrawPending());
1089 // Next frame without DidManageTiles should ManageTiles with draw.
1090 scheduler->SetNeedsManageTiles();
1091 scheduler->SetNeedsRedraw();
1092 client.Reset();
1093 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1094 EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
1096 client.Reset();
1097 scheduler->OnBeginImplFrameDeadline();
1098 EXPECT_EQ(1, client.num_draws());
1099 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1100 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
1101 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1102 client.ActionIndex("ScheduledActionManageTiles"));
1103 EXPECT_FALSE(scheduler->RedrawPending());
1104 EXPECT_FALSE(scheduler->ManageTilesPending());
1105 scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
1108 TEST(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1109 SchedulerClientNeedsManageTilesInDraw client;
1110 SchedulerSettings default_scheduler_settings;
1111 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
1112 scheduler->SetCanStart();
1113 scheduler->SetVisible(true);
1114 scheduler->SetCanDraw(true);
1115 InitializeOutputSurfaceAndFirstCommit(scheduler);
1117 client.Reset();
1118 BeginFrameArgs impl_frame_args = BeginFrameArgs::CreateForTesting();
1119 scheduler->SetNeedsRedraw();
1120 scheduler->BeginImplFrame(impl_frame_args);
1122 // The deadline should be zero since there is no work other than drawing
1123 // pending.
1124 EXPECT_EQ(base::TimeTicks(), client.posted_begin_impl_frame_deadline());
1127 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
1128 public:
1129 SchedulerClientWithFixedEstimates(
1130 base::TimeDelta draw_duration,
1131 base::TimeDelta begin_main_frame_to_commit_duration,
1132 base::TimeDelta commit_to_activate_duration)
1133 : draw_duration_(draw_duration),
1134 begin_main_frame_to_commit_duration_(
1135 begin_main_frame_to_commit_duration),
1136 commit_to_activate_duration_(commit_to_activate_duration) {}
1138 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
1139 return draw_duration_;
1141 virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
1142 return begin_main_frame_to_commit_duration_;
1144 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
1145 return commit_to_activate_duration_;
1148 private:
1149 base::TimeDelta draw_duration_;
1150 base::TimeDelta begin_main_frame_to_commit_duration_;
1151 base::TimeDelta commit_to_activate_duration_;
1154 void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms,
1155 int64 commit_to_activate_estimate_in_ms,
1156 bool smoothness_takes_priority,
1157 bool should_send_begin_main_frame) {
1158 // Set up client with specified estimates (draw duration is set to 1).
1159 SchedulerClientWithFixedEstimates client(
1160 base::TimeDelta::FromMilliseconds(1),
1161 base::TimeDelta::FromMilliseconds(
1162 begin_main_frame_to_commit_estimate_in_ms),
1163 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
1164 SchedulerSettings default_scheduler_settings;
1165 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
1166 scheduler->SetCanStart();
1167 scheduler->SetVisible(true);
1168 scheduler->SetCanDraw(true);
1169 scheduler->SetSmoothnessTakesPriority(smoothness_takes_priority);
1170 InitializeOutputSurfaceAndFirstCommit(scheduler);
1172 // Impl thread hits deadline before commit finishes.
1173 client.Reset();
1174 scheduler->SetNeedsCommit();
1175 EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
1176 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1177 EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
1178 scheduler->OnBeginImplFrameDeadline();
1179 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1180 scheduler->NotifyBeginMainFrameStarted();
1181 scheduler->NotifyReadyToCommit();
1182 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1183 EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
1185 client.Reset();
1186 scheduler->SetNeedsCommit();
1187 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1188 scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1189 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1190 scheduler->OnBeginImplFrameDeadline();
1191 EXPECT_EQ(scheduler->MainThreadIsInHighLatencyMode(),
1192 should_send_begin_main_frame);
1193 EXPECT_EQ(client.HasAction("ScheduledActionSendBeginMainFrame"),
1194 should_send_begin_main_frame);
1197 TEST(SchedulerTest,
1198 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
1199 // Set up client so that estimates indicate that we can commit and activate
1200 // before the deadline (~8ms by default).
1201 MainFrameInHighLatencyMode(1, 1, false, false);
1204 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
1205 // Set up client so that estimates indicate that the commit cannot finish
1206 // before the deadline (~8ms by default).
1207 MainFrameInHighLatencyMode(10, 1, false, true);
1210 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
1211 // Set up client so that estimates indicate that the activate cannot finish
1212 // before the deadline (~8ms by default).
1213 MainFrameInHighLatencyMode(1, 10, false, true);
1216 TEST(SchedulerTest, NotSkipMainFrameInPreferSmoothnessMode) {
1217 // Set up client so that estimates indicate that we can commit and activate
1218 // before the deadline (~8ms by default), but also enable smoothness takes
1219 // priority mode.
1220 MainFrameInHighLatencyMode(1, 1, true, true);
1223 void SpinForMillis(int millis) {
1224 base::RunLoop run_loop;
1225 base::MessageLoop::current()->PostDelayedTask(
1226 FROM_HERE,
1227 run_loop.QuitClosure(),
1228 base::TimeDelta::FromMilliseconds(millis));
1229 run_loop.Run();
1232 TEST(SchedulerTest, PollForCommitCompletion) {
1233 // Since we are simulating a long commit, set up a client with draw duration
1234 // estimates that prevent skipping main frames to get to low latency mode.
1235 SchedulerClientWithFixedEstimates client(
1236 base::TimeDelta::FromMilliseconds(1),
1237 base::TimeDelta::FromMilliseconds(32),
1238 base::TimeDelta::FromMilliseconds(32));
1239 client.set_log_anticipated_draw_time_change(true);
1240 SchedulerSettings settings = SchedulerSettings();
1241 settings.throttle_frame_production = false;
1242 Scheduler* scheduler = client.CreateScheduler(settings);
1244 scheduler->SetCanDraw(true);
1245 scheduler->SetCanStart();
1246 scheduler->SetVisible(true);
1247 scheduler->DidCreateAndInitializeOutputSurface();
1249 scheduler->SetNeedsCommit();
1250 EXPECT_TRUE(scheduler->CommitPending());
1251 scheduler->NotifyBeginMainFrameStarted();
1252 scheduler->NotifyReadyToCommit();
1253 scheduler->SetNeedsRedraw();
1254 BeginFrameArgs impl_frame_args = BeginFrameArgs::CreateForTesting();
1255 const int interval = 1;
1256 impl_frame_args.interval = base::TimeDelta::FromMilliseconds(interval);
1257 scheduler->BeginImplFrame(impl_frame_args);
1258 scheduler->OnBeginImplFrameDeadline();
1260 // At this point, we've drawn a frame. Start another commit, but hold off on
1261 // the NotifyReadyToCommit for now.
1262 EXPECT_FALSE(scheduler->CommitPending());
1263 scheduler->SetNeedsCommit();
1264 EXPECT_TRUE(scheduler->CommitPending());
1266 // Spin the event loop a few times and make sure we get more
1267 // DidAnticipateDrawTimeChange calls every time.
1268 int actions_so_far = client.num_actions_();
1270 // Does three iterations to make sure that the timer is properly repeating.
1271 for (int i = 0; i < 3; ++i) {
1272 // Wait for 2x the frame interval to match
1273 // Scheduler::advance_commit_state_timer_'s rate.
1274 SpinForMillis(interval * 2);
1275 EXPECT_GT(client.num_actions_(), actions_so_far);
1276 EXPECT_STREQ(client.Action(client.num_actions_() - 1),
1277 "DidAnticipatedDrawTimeChange");
1278 actions_so_far = client.num_actions_();
1282 } // namespace
1283 } // namespace cc