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