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"
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_()); \
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); \
26 #define EXPECT_SINGLE_ACTION(action, client) \
27 EXPECT_ACTION(action, client, 0, 1)
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
{
46 : needs_begin_frame_(false) {
53 draw_will_happen_
= true;
54 swap_will_happen_if_draw_happens_
= true;
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
))
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());
98 return ScheduledActionDrawAndSwapResult(draw_will_happen_
,
100 swap_will_happen_if_draw_happens_
);
102 virtual ScheduledActionDrawAndSwapResult
ScheduledActionDrawAndSwapForced()
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();
141 bool needs_begin_frame_
;
142 bool draw_will_happen_
;
143 bool swap_will_happen_if_draw_happens_
;
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
);
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.
177 scheduler
->SetNeedsCommit();
178 EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client
, 0, 2);
179 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client
, 1, 2);
180 EXPECT_TRUE(client
.needs_begin_frame());
183 // FinishCommit should commit
184 scheduler
->FinishCommit();
185 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
186 EXPECT_TRUE(client
.needs_begin_frame());
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());
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
);
209 // SetNedsCommit should begin the frame.
210 scheduler
->SetNeedsCommit();
211 EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client
, 0, 2);
212 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client
, 1, 2);
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
);
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);
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
);
248 scheduler
->SetNeedsRedraw();
249 EXPECT_TRUE(scheduler
->RedrawPending());
250 EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client
);
251 EXPECT_TRUE(client
.needs_begin_frame());
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());
261 scheduler
->SetMainThreadNeedsLayerTextures();
262 EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
265 // We should request a BeginFrame in anticipation of a draw.
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.
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.
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.
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());
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
);
313 scheduler
->SetNeedsCommit();
314 scheduler
->SetMainThreadNeedsLayerTextures();
315 EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client
, 0, 3);
316 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client
, 1, 3);
318 "ScheduledActionAcquireLayerTexturesForMainThread", client
, 2, 3);
321 // Although the compositor cannot draw because textures are locked by main
322 // thread, we continue requesting SetNeedsBeginFrame in anticipation of the
324 EXPECT_TRUE(client
.needs_begin_frame());
326 // Trigger the commit
327 scheduler
->FinishCommit();
328 EXPECT_TRUE(client
.needs_begin_frame());
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_());
337 // No implicit commit is expected.
338 scheduler
->BeginFrame(BeginFrameArgs::CreateForTesting());
339 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 3);
340 EXPECT_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
344 EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client
, 2, 3);
347 // Compositor not scheduled to draw because textures are locked by main
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);
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
);
372 scheduler
->DidCreateAndInitializeOutputSurface();
374 scheduler
->SetNeedsCommit();
375 scheduler
->FinishCommit();
376 scheduler
->SetMainThreadNeedsLayerTextures();
377 scheduler
->SetNeedsCommit();
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",
386 // Already sent a begin frame on this current frame, so wait.
387 scheduler
->SetVisible(true);
388 EXPECT_EQ(0, client
.num_actions_());
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
{
401 virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE
{}
402 virtual ScheduledActionDrawAndSwapResult
403 ScheduledActionDrawAndSwapIfPossible() OVERRIDE
{
404 // Only SetNeedsRedraw the first time this is called
406 scheduler_
->SetNeedsRedraw();
407 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
410 virtual ScheduledActionDrawAndSwapResult
ScheduledActionDrawAndSwapForced()
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
);
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
);
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());
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
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
{
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()
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; }
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
);
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
);
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());
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
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
);
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"));