cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blob99362344417dd6b0fd395af365b165517679be6f
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.
5 #include "cc/scheduler/scheduler.h"
7 #include <string>
8 #include <vector>
10 #include "base/logging.h"
11 #include "base/memory/scoped_vector.h"
12 #include "cc/test/scheduler_test_common.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
17 EXPECT_EQ(expected_num_actions, client.num_actions_()); \
18 ASSERT_LT(action_index, client.num_actions_()); \
19 do { \
20 EXPECT_STREQ(action, client.Action(action_index)); \
21 for (int i = expected_num_actions; i < client.num_actions_(); ++i) \
22 ADD_FAILURE() << "Unexpected action: " << client.Action(i) << \
23 " with state:\n" << client.StateForAction(action_index); \
24 } while (false)
26 #define EXPECT_SINGLE_ACTION(action, client) \
27 EXPECT_ACTION(action, client, 0, 1)
29 namespace cc {
30 namespace {
32 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler) {
33 scheduler->DidCreateAndInitializeOutputSurface();
34 scheduler->SetNeedsCommit();
35 scheduler->FinishCommit();
36 // Go through the motions to draw the commit.
37 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
38 // We need another BeginFrame so scheduler calls SetNeedsBeginFrame(false).
39 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
40 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
43 class FakeSchedulerClient : public SchedulerClient {
44 public:
45 FakeSchedulerClient()
46 : needs_begin_frame_(false) {
47 Reset();
50 void Reset() {
51 actions_.clear();
52 states_.clear();
53 draw_will_happen_ = true;
54 swap_will_happen_if_draw_happens_ = true;
55 num_draws_ = 0;
58 Scheduler* CreateScheduler(const SchedulerSettings& settings) {
59 scheduler_ = Scheduler::Create(this, settings);
60 return scheduler_.get();
63 bool needs_begin_frame() { return needs_begin_frame_; }
64 int num_draws() const { return num_draws_; }
65 int num_actions_() const { return static_cast<int>(actions_.size()); }
66 const char* Action(int i) const { return actions_[i]; }
67 base::Value& StateForAction(int i) const { return *states_[i]; }
69 bool HasAction(const char* action) const {
70 for (size_t i = 0; i < actions_.size(); i++)
71 if (!strcmp(actions_[i], action))
72 return true;
73 return false;
76 void SetDrawWillHappen(bool draw_will_happen) {
77 draw_will_happen_ = draw_will_happen;
79 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
80 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
83 // Scheduler Implementation.
84 virtual void SetNeedsBeginFrameOnImplThread(bool enable) OVERRIDE {
85 actions_.push_back("SetNeedsBeginFrameOnImplThread");
86 states_.push_back(scheduler_->StateAsValue().release());
87 needs_begin_frame_ = enable;
89 virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE {
90 actions_.push_back("ScheduledActionSendBeginFrameToMainThread");
91 states_.push_back(scheduler_->StateAsValue().release());
93 virtual ScheduledActionDrawAndSwapResult
94 ScheduledActionDrawAndSwapIfPossible() OVERRIDE {
95 actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
96 states_.push_back(scheduler_->StateAsValue().release());
97 num_draws_++;
98 return ScheduledActionDrawAndSwapResult(draw_will_happen_,
99 draw_will_happen_ &&
100 swap_will_happen_if_draw_happens_);
102 virtual ScheduledActionDrawAndSwapResult ScheduledActionDrawAndSwapForced()
103 OVERRIDE {
104 actions_.push_back("ScheduledActionDrawAndSwapForced");
105 states_.push_back(scheduler_->StateAsValue().release());
106 return ScheduledActionDrawAndSwapResult(true,
107 swap_will_happen_if_draw_happens_);
109 virtual void ScheduledActionCommit() OVERRIDE {
110 actions_.push_back("ScheduledActionCommit");
111 states_.push_back(scheduler_->StateAsValue().release());
113 virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE {
114 actions_.push_back("ScheduledActionUpdateVisibleTiles");
115 states_.push_back(scheduler_->StateAsValue().release());
117 virtual void ScheduledActionActivatePendingTree() OVERRIDE {
118 actions_.push_back("ScheduledActionActivatePendingTree");
119 states_.push_back(scheduler_->StateAsValue().release());
121 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
122 actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
123 states_.push_back(scheduler_->StateAsValue().release());
125 virtual void ScheduledActionAcquireLayerTexturesForMainThread() OVERRIDE {
126 actions_.push_back("ScheduledActionAcquireLayerTexturesForMainThread");
127 states_.push_back(scheduler_->StateAsValue().release());
129 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
130 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
131 return base::TimeDelta();
133 virtual base::TimeDelta BeginFrameToCommitDurationEstimate() OVERRIDE {
134 return base::TimeDelta();
136 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
137 return base::TimeDelta();
140 protected:
141 bool needs_begin_frame_;
142 bool draw_will_happen_;
143 bool swap_will_happen_if_draw_happens_;
144 int num_draws_;
145 std::vector<const char*> actions_;
146 ScopedVector<base::Value> states_;
147 scoped_ptr<Scheduler> scheduler_;
150 TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginFrame) {
151 FakeSchedulerClient client;
152 SchedulerSettings default_scheduler_settings;
153 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
154 scheduler->SetCanStart();
155 scheduler->SetVisible(true);
156 scheduler->SetCanDraw(true);
158 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
159 client.Reset();
160 scheduler->DidCreateAndInitializeOutputSurface();
161 EXPECT_EQ(0, client.num_actions_());
164 TEST(SchedulerTest, RequestCommit) {
165 FakeSchedulerClient client;
166 SchedulerSettings default_scheduler_settings;
167 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
168 scheduler->SetCanStart();
169 scheduler->SetVisible(true);
170 scheduler->SetCanDraw(true);
172 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
173 InitializeOutputSurfaceAndFirstCommit(scheduler);
175 // SetNeedsCommit should begin the frame.
176 client.Reset();
177 scheduler->SetNeedsCommit();
178 EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
179 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
180 EXPECT_TRUE(client.needs_begin_frame());
181 client.Reset();
183 // FinishCommit should commit
184 scheduler->FinishCommit();
185 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
186 EXPECT_TRUE(client.needs_begin_frame());
187 client.Reset();
189 // BeginFrame should draw.
190 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
191 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
192 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
193 EXPECT_FALSE(client.needs_begin_frame());
194 client.Reset();
197 TEST(SchedulerTest, RequestCommitAfterBeginFrameSentToMainThread) {
198 FakeSchedulerClient client;
199 SchedulerSettings default_scheduler_settings;
200 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
201 scheduler->SetCanStart();
202 scheduler->SetVisible(true);
203 scheduler->SetCanDraw(true);
205 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
206 InitializeOutputSurfaceAndFirstCommit(scheduler);
207 client.Reset();
209 // SetNedsCommit should begin the frame.
210 scheduler->SetNeedsCommit();
211 EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
212 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
213 client.Reset();
215 // Now SetNeedsCommit again. Calling here means we need a second frame.
216 scheduler->SetNeedsCommit();
218 // Finish the commit for the first frame.
219 scheduler->FinishCommit();
220 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
221 client.Reset();
223 // Tick should draw but then begin another frame for the second commit.
224 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
225 EXPECT_TRUE(client.needs_begin_frame());
226 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
227 EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 1, 2);
228 client.Reset();
230 // Finish the second commit to go back to quiescent state and verify we no
231 // longer request BeginFrames.
232 scheduler->FinishCommit();
233 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
234 EXPECT_FALSE(client.needs_begin_frame());
237 TEST(SchedulerTest, TextureAcquisitionCausesCommitInsteadOfDraw) {
238 FakeSchedulerClient client;
239 SchedulerSettings default_scheduler_settings;
240 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
241 scheduler->SetCanStart();
242 scheduler->SetVisible(true);
243 scheduler->SetCanDraw(true);
244 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
246 InitializeOutputSurfaceAndFirstCommit(scheduler);
247 client.Reset();
248 scheduler->SetNeedsRedraw();
249 EXPECT_TRUE(scheduler->RedrawPending());
250 EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
251 EXPECT_TRUE(client.needs_begin_frame());
253 client.Reset();
254 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
255 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
256 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
257 EXPECT_FALSE(scheduler->RedrawPending());
258 EXPECT_FALSE(client.needs_begin_frame());
260 client.Reset();
261 scheduler->SetMainThreadNeedsLayerTextures();
262 EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
263 client);
265 // We should request a BeginFrame in anticipation of a draw.
266 client.Reset();
267 scheduler->SetNeedsRedraw();
268 EXPECT_TRUE(scheduler->RedrawPending());
269 EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
270 EXPECT_TRUE(client.needs_begin_frame());
272 // No draw happens since the textures are acquired by the main thread.
273 client.Reset();
274 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
275 EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
276 EXPECT_TRUE(scheduler->RedrawPending());
277 EXPECT_TRUE(client.needs_begin_frame());
279 scheduler->SetNeedsCommit();
280 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 0, 2);
281 EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 1, 2);
282 EXPECT_TRUE(client.needs_begin_frame());
284 // Commit will release the texture.
285 client.Reset();
286 scheduler->FinishCommit();
287 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
288 EXPECT_TRUE(scheduler->RedrawPending());
289 EXPECT_TRUE(client.needs_begin_frame());
291 // Now we can draw again after the commit happens.
292 client.Reset();
293 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
294 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
295 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
296 EXPECT_FALSE(scheduler->RedrawPending());
297 EXPECT_FALSE(client.needs_begin_frame());
298 client.Reset();
301 TEST(SchedulerTest, TextureAcquisitionCollision) {
302 FakeSchedulerClient client;
303 SchedulerSettings default_scheduler_settings;
304 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
305 scheduler->SetCanStart();
306 scheduler->SetVisible(true);
307 scheduler->SetCanDraw(true);
309 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
310 InitializeOutputSurfaceAndFirstCommit(scheduler);
312 client.Reset();
313 scheduler->SetNeedsCommit();
314 scheduler->SetMainThreadNeedsLayerTextures();
315 EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 3);
316 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 3);
317 EXPECT_ACTION(
318 "ScheduledActionAcquireLayerTexturesForMainThread", client, 2, 3);
319 client.Reset();
321 // Although the compositor cannot draw because textures are locked by main
322 // thread, we continue requesting SetNeedsBeginFrame in anticipation of the
323 // unlock.
324 EXPECT_TRUE(client.needs_begin_frame());
326 // Trigger the commit
327 scheduler->FinishCommit();
328 EXPECT_TRUE(client.needs_begin_frame());
329 client.Reset();
331 // Between commit and draw, texture acquisition for main thread delayed,
332 // and main thread blocks.
333 scheduler->SetMainThreadNeedsLayerTextures();
334 EXPECT_EQ(0, client.num_actions_());
335 client.Reset();
337 // No implicit commit is expected.
338 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
339 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
340 EXPECT_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
341 client,
344 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 2, 3);
345 client.Reset();
347 // Compositor not scheduled to draw because textures are locked by main
348 // thread.
349 EXPECT_FALSE(client.needs_begin_frame());
351 // Needs an explicit commit from the main thread.
352 scheduler->SetNeedsCommit();
353 EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
354 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
355 client.Reset();
357 // Trigger the commit
358 scheduler->FinishCommit();
359 EXPECT_TRUE(client.needs_begin_frame());
362 TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition) {
363 FakeSchedulerClient client;
364 SchedulerSettings default_scheduler_settings;
365 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
366 scheduler->SetCanStart();
367 scheduler->SetVisible(true);
368 scheduler->SetCanDraw(true);
370 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
371 client.Reset();
372 scheduler->DidCreateAndInitializeOutputSurface();
374 scheduler->SetNeedsCommit();
375 scheduler->FinishCommit();
376 scheduler->SetMainThreadNeedsLayerTextures();
377 scheduler->SetNeedsCommit();
378 client.Reset();
379 // Verify that pending texture acquisition fires when visibility
380 // is lost in order to avoid a deadlock.
381 scheduler->SetVisible(false);
382 EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
383 client);
384 client.Reset();
386 // Already sent a begin frame on this current frame, so wait.
387 scheduler->SetVisible(true);
388 EXPECT_EQ(0, client.num_actions_());
389 client.Reset();
391 // Regaining visibility with textures acquired by main thread while
392 // compositor is waiting for first draw should result in a request
393 // for a new frame in order to escape a deadlock.
394 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
395 EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
396 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
399 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
400 public:
401 virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE {}
402 virtual ScheduledActionDrawAndSwapResult
403 ScheduledActionDrawAndSwapIfPossible() OVERRIDE {
404 // Only SetNeedsRedraw the first time this is called
405 if (!num_draws_)
406 scheduler_->SetNeedsRedraw();
407 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
410 virtual ScheduledActionDrawAndSwapResult ScheduledActionDrawAndSwapForced()
411 OVERRIDE {
412 NOTREACHED();
413 return ScheduledActionDrawAndSwapResult(true, true);
416 virtual void ScheduledActionCommit() OVERRIDE {}
417 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
418 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
421 // Tests for two different situations:
422 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
423 // a ScheduledActionDrawAndSwap
424 // 2. the scheduler drawing twice inside a single tick
425 TEST(SchedulerTest, RequestRedrawInsideDraw) {
426 SchedulerClientThatsetNeedsDrawInsideDraw client;
427 SchedulerSettings default_scheduler_settings;
428 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
429 scheduler->SetCanStart();
430 scheduler->SetVisible(true);
431 scheduler->SetCanDraw(true);
432 InitializeOutputSurfaceAndFirstCommit(scheduler);
433 client.Reset();
435 scheduler->SetNeedsRedraw();
436 EXPECT_TRUE(scheduler->RedrawPending());
437 EXPECT_TRUE(client.needs_begin_frame());
438 EXPECT_EQ(0, client.num_draws());
440 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
441 EXPECT_EQ(1, client.num_draws());
442 EXPECT_TRUE(scheduler->RedrawPending());
443 EXPECT_TRUE(client.needs_begin_frame());
445 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
446 EXPECT_EQ(2, client.num_draws());
447 EXPECT_FALSE(scheduler->RedrawPending());
448 EXPECT_FALSE(client.needs_begin_frame());
451 // Test that requesting redraw inside a failed draw doesn't lose the request.
452 TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
453 SchedulerClientThatsetNeedsDrawInsideDraw client;
454 SchedulerSettings default_scheduler_settings;
455 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
456 scheduler->SetCanStart();
457 scheduler->SetVisible(true);
458 scheduler->SetCanDraw(true);
459 InitializeOutputSurfaceAndFirstCommit(scheduler);
460 client.Reset();
462 client.SetDrawWillHappen(false);
464 scheduler->SetNeedsRedraw();
465 EXPECT_TRUE(scheduler->RedrawPending());
466 EXPECT_TRUE(client.needs_begin_frame());
467 EXPECT_EQ(0, client.num_draws());
469 // Fail the draw.
470 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
471 EXPECT_EQ(1, client.num_draws());
473 // We have a commit pending and the draw failed, and we didn't lose the redraw
474 // request.
475 EXPECT_TRUE(scheduler->CommitPending());
476 EXPECT_TRUE(scheduler->RedrawPending());
477 EXPECT_TRUE(client.needs_begin_frame());
479 // Fail the draw again.
480 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
481 EXPECT_EQ(2, client.num_draws());
482 EXPECT_TRUE(scheduler->CommitPending());
483 EXPECT_TRUE(scheduler->RedrawPending());
484 EXPECT_TRUE(client.needs_begin_frame());
486 // Draw successfully.
487 client.SetDrawWillHappen(true);
488 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
489 EXPECT_EQ(3, client.num_draws());
490 EXPECT_TRUE(scheduler->CommitPending());
491 EXPECT_FALSE(scheduler->RedrawPending());
492 EXPECT_TRUE(client.needs_begin_frame());
495 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
496 public:
497 SchedulerClientThatSetNeedsCommitInsideDraw()
498 : set_needs_commit_on_next_draw_(false) {}
500 virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE {}
501 virtual ScheduledActionDrawAndSwapResult
502 ScheduledActionDrawAndSwapIfPossible() OVERRIDE {
503 // Only SetNeedsCommit the first time this is called
504 if (set_needs_commit_on_next_draw_) {
505 scheduler_->SetNeedsCommit();
506 set_needs_commit_on_next_draw_ = false;
508 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
511 virtual ScheduledActionDrawAndSwapResult ScheduledActionDrawAndSwapForced()
512 OVERRIDE {
513 NOTREACHED();
514 return ScheduledActionDrawAndSwapResult(true, true);
517 virtual void ScheduledActionCommit() OVERRIDE {}
518 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
519 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
521 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
523 private:
524 bool set_needs_commit_on_next_draw_;
527 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
528 // happen inside a ScheduledActionDrawAndSwap
529 TEST(SchedulerTest, RequestCommitInsideDraw) {
530 SchedulerClientThatSetNeedsCommitInsideDraw client;
531 SchedulerSettings default_scheduler_settings;
532 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
533 scheduler->SetCanStart();
534 scheduler->SetVisible(true);
535 scheduler->SetCanDraw(true);
536 InitializeOutputSurfaceAndFirstCommit(scheduler);
537 client.Reset();
539 scheduler->SetNeedsRedraw();
540 EXPECT_TRUE(scheduler->RedrawPending());
541 EXPECT_EQ(0, client.num_draws());
542 EXPECT_TRUE(client.needs_begin_frame());
544 client.SetNeedsCommitOnNextDraw();
545 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
546 EXPECT_EQ(1, client.num_draws());
547 EXPECT_TRUE(scheduler->CommitPending());
548 EXPECT_TRUE(client.needs_begin_frame());
549 scheduler->FinishCommit();
551 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
552 EXPECT_EQ(2, client.num_draws());;
553 EXPECT_FALSE(scheduler->RedrawPending());
554 EXPECT_FALSE(scheduler->CommitPending());
555 EXPECT_FALSE(client.needs_begin_frame());
558 // Tests that when a draw fails then the pending commit should not be dropped.
559 TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
560 SchedulerClientThatsetNeedsDrawInsideDraw client;
561 SchedulerSettings default_scheduler_settings;
562 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
563 scheduler->SetCanStart();
564 scheduler->SetVisible(true);
565 scheduler->SetCanDraw(true);
566 InitializeOutputSurfaceAndFirstCommit(scheduler);
567 client.Reset();
569 client.SetDrawWillHappen(false);
571 scheduler->SetNeedsRedraw();
572 EXPECT_TRUE(scheduler->RedrawPending());
573 EXPECT_TRUE(client.needs_begin_frame());
574 EXPECT_EQ(0, client.num_draws());
576 // Fail the draw.
577 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
578 EXPECT_EQ(1, client.num_draws());
580 // We have a commit pending and the draw failed, and we didn't lose the commit
581 // request.
582 EXPECT_TRUE(scheduler->CommitPending());
583 EXPECT_TRUE(scheduler->RedrawPending());
584 EXPECT_TRUE(client.needs_begin_frame());
586 // Fail the draw again.
587 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
588 EXPECT_EQ(2, client.num_draws());
589 EXPECT_TRUE(scheduler->CommitPending());
590 EXPECT_TRUE(scheduler->RedrawPending());
591 EXPECT_TRUE(client.needs_begin_frame());
593 // Draw successfully.
594 client.SetDrawWillHappen(true);
595 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
596 EXPECT_EQ(3, client.num_draws());
597 EXPECT_TRUE(scheduler->CommitPending());
598 EXPECT_FALSE(scheduler->RedrawPending());
599 EXPECT_TRUE(client.needs_begin_frame());
602 TEST(SchedulerTest, NoSwapWhenDrawFails) {
603 SchedulerClientThatSetNeedsCommitInsideDraw client;
604 SchedulerSettings default_scheduler_settings;
605 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
606 scheduler->SetCanStart();
607 scheduler->SetVisible(true);
608 scheduler->SetCanDraw(true);
609 InitializeOutputSurfaceAndFirstCommit(scheduler);
610 client.Reset();
612 scheduler->SetNeedsRedraw();
613 EXPECT_TRUE(scheduler->RedrawPending());
614 EXPECT_TRUE(client.needs_begin_frame());
615 EXPECT_EQ(0, client.num_draws());
617 // Draw successfully, this starts a new frame.
618 client.SetNeedsCommitOnNextDraw();
619 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
620 EXPECT_EQ(1, client.num_draws());
622 scheduler->SetNeedsRedraw();
623 EXPECT_TRUE(scheduler->RedrawPending());
624 EXPECT_TRUE(client.needs_begin_frame());
626 // Fail to draw, this should not start a frame.
627 client.SetDrawWillHappen(false);
628 client.SetNeedsCommitOnNextDraw();
629 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
630 EXPECT_EQ(2, client.num_draws());
633 TEST(SchedulerTest, NoSwapWhenSwapFailsDuringForcedCommit) {
634 FakeSchedulerClient client;
635 SchedulerSettings default_scheduler_settings;
636 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
638 // Tell the client that it will fail to swap.
639 client.SetDrawWillHappen(true);
640 client.SetSwapWillHappenIfDrawHappens(false);
642 // Get the compositor to do a ScheduledActionDrawAndSwapForced.
643 scheduler->SetCanDraw(true);
644 scheduler->SetNeedsRedraw();
645 scheduler->SetNeedsForcedRedraw();
646 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapForced"));
649 } // namespace
650 } // namespace cc