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" 5 6 #include <string> 7 #include <vector> 8 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/begin_frame_args_test.h" 15 #include "cc/test/ordered_simple_task_runner.h" 16 #include "cc/test/scheduler_test_common.h" 17 #include "testing/gmock/include/gmock/gmock.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 20 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \ 21 do { \ 22 EXPECT_EQ(expected_num_actions, client.num_actions_()); \ 23 if (action_index >= 0) { \ 24 ASSERT_LT(action_index, client.num_actions_()) << scheduler; \ 25 EXPECT_STREQ(action, client.Action(action_index)); \ 26 } \ 27 for (int i = expected_num_actions; i < client.num_actions_(); ++i) \ 28 ADD_FAILURE() << "Unexpected action: " << client.Action(i) \ 29 << " with state:\n" << client.StateForAction(i); \ 30 } while (false) 31 32 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0) 33 34 #define EXPECT_SINGLE_ACTION(action, client) \ 35 EXPECT_ACTION(action, client, 0, 1) 36 37 namespace cc { 38 namespace { 39 40 class FakeSchedulerClient; 41 42 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler, 43 FakeSchedulerClient* client); 44 45 class TestScheduler : public Scheduler { 46 public: 47 static scoped_ptr<TestScheduler> Create( 48 SchedulerClient* client, 49 const SchedulerSettings& scheduler_settings, 50 int layer_tree_host_id, 51 const scoped_refptr<base::SingleThreadTaskRunner>& impl_task_runner) { 52 return make_scoped_ptr(new TestScheduler( 53 client, scheduler_settings, layer_tree_host_id, impl_task_runner)); 54 } 55 56 virtual ~TestScheduler() {} 57 58 bool IsBeginRetroFrameArgsEmpty() const { 59 return begin_retro_frame_args_.empty(); 60 } 61 62 bool IsSyntheticBeginFrameSourceActive() const { 63 return synthetic_begin_frame_source_->IsActive(); 64 } 65 66 private: 67 TestScheduler( 68 SchedulerClient* client, 69 const SchedulerSettings& scheduler_settings, 70 int layer_tree_host_id, 71 const scoped_refptr<base::SingleThreadTaskRunner> & impl_task_runner) 72 : Scheduler(client, 73 scheduler_settings, 74 layer_tree_host_id, 75 impl_task_runner) { 76 } 77 }; 78 79 class FakeSchedulerClient : public SchedulerClient { 80 public: 81 FakeSchedulerClient() 82 : needs_begin_frame_(false), 83 automatic_swap_ack_(true), 84 swap_contains_incomplete_tile_(false), 85 redraw_will_happen_if_update_visible_tiles_happens_(false) { 86 Reset(); 87 } 88 89 void Reset() { 90 actions_.clear(); 91 states_.clear(); 92 draw_will_happen_ = true; 93 swap_will_happen_if_draw_happens_ = true; 94 num_draws_ = 0; 95 log_anticipated_draw_time_change_ = false; 96 } 97 98 TestScheduler* CreateScheduler(const SchedulerSettings& settings) { 99 task_runner_ = new OrderedSimpleTaskRunner; 100 scheduler_ = TestScheduler::Create(this, settings, 0, task_runner_); 101 return scheduler_.get(); 102 } 103 104 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it 105 // for tests that do. 106 void set_log_anticipated_draw_time_change(bool log) { 107 log_anticipated_draw_time_change_ = log; 108 } 109 bool needs_begin_frame() { return needs_begin_frame_; } 110 int num_draws() const { return num_draws_; } 111 int num_actions_() const { return static_cast<int>(actions_.size()); } 112 const char* Action(int i) const { return actions_[i]; } 113 base::Value& StateForAction(int i) const { return *states_[i]; } 114 base::TimeTicks posted_begin_impl_frame_deadline() const { 115 return posted_begin_impl_frame_deadline_; 116 } 117 118 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; } 119 120 int ActionIndex(const char* action) const { 121 for (size_t i = 0; i < actions_.size(); i++) 122 if (!strcmp(actions_[i], action)) 123 return i; 124 return -1; 125 } 126 127 void SetSwapContainsIncompleteTile(bool contain) { 128 swap_contains_incomplete_tile_ = contain; 129 } 130 131 bool HasAction(const char* action) const { 132 return ActionIndex(action) >= 0; 133 } 134 135 void SetDrawWillHappen(bool draw_will_happen) { 136 draw_will_happen_ = draw_will_happen; 137 } 138 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) { 139 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens; 140 } 141 void SetAutomaticSwapAck(bool automatic_swap_ack) { 142 automatic_swap_ack_ = automatic_swap_ack; 143 } 144 void SetRedrawWillHappenIfUpdateVisibleTilesHappens(bool redraw) { 145 redraw_will_happen_if_update_visible_tiles_happens_ = redraw; 146 } 147 // SchedulerClient implementation. 148 virtual void SetNeedsBeginFrame(bool enable) OVERRIDE { 149 actions_.push_back("SetNeedsBeginFrame"); 150 states_.push_back(scheduler_->AsValue().release()); 151 needs_begin_frame_ = enable; 152 } 153 virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE { 154 actions_.push_back("WillBeginImplFrame"); 155 states_.push_back(scheduler_->AsValue().release()); 156 } 157 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE { 158 actions_.push_back("ScheduledActionSendBeginMainFrame"); 159 states_.push_back(scheduler_->AsValue().release()); 160 } 161 virtual void ScheduledActionAnimate() OVERRIDE { 162 actions_.push_back("ScheduledActionAnimate"); 163 states_.push_back(scheduler_->AsValue().release()); 164 } 165 virtual DrawResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE { 166 actions_.push_back("ScheduledActionDrawAndSwapIfPossible"); 167 states_.push_back(scheduler_->AsValue().release()); 168 num_draws_++; 169 DrawResult result = 170 draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS; 171 bool swap_will_happen = 172 draw_will_happen_ && swap_will_happen_if_draw_happens_; 173 if (swap_will_happen) { 174 scheduler_->DidSwapBuffers(); 175 if (swap_contains_incomplete_tile_) { 176 scheduler_->SetSwapUsedIncompleteTile(true); 177 swap_contains_incomplete_tile_ = false; 178 } else { 179 scheduler_->SetSwapUsedIncompleteTile(false); 180 } 181 182 if (automatic_swap_ack_) 183 scheduler_->DidSwapBuffersComplete(); 184 } 185 return result; 186 } 187 virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE { 188 actions_.push_back("ScheduledActionDrawAndSwapForced"); 189 states_.push_back(scheduler_->AsValue().release()); 190 return DRAW_SUCCESS; 191 } 192 virtual void ScheduledActionCommit() OVERRIDE { 193 actions_.push_back("ScheduledActionCommit"); 194 states_.push_back(scheduler_->AsValue().release()); 195 } 196 virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE { 197 actions_.push_back("ScheduledActionUpdateVisibleTiles"); 198 states_.push_back(scheduler_->AsValue().release()); 199 if (redraw_will_happen_if_update_visible_tiles_happens_) 200 scheduler_->SetNeedsRedraw(); 201 } 202 virtual void ScheduledActionActivatePendingTree() OVERRIDE { 203 actions_.push_back("ScheduledActionActivatePendingTree"); 204 states_.push_back(scheduler_->AsValue().release()); 205 } 206 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE { 207 actions_.push_back("ScheduledActionBeginOutputSurfaceCreation"); 208 states_.push_back(scheduler_->AsValue().release()); 209 } 210 virtual void ScheduledActionManageTiles() OVERRIDE { 211 actions_.push_back("ScheduledActionManageTiles"); 212 states_.push_back(scheduler_->AsValue().release()); 213 } 214 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE { 215 if (log_anticipated_draw_time_change_) 216 actions_.push_back("DidAnticipatedDrawTimeChange"); 217 } 218 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE { 219 return base::TimeDelta(); 220 } 221 virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE { 222 return base::TimeDelta(); 223 } 224 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE { 225 return base::TimeDelta(); 226 } 227 228 virtual void DidBeginImplFrameDeadline() OVERRIDE {} 229 230 protected: 231 bool needs_begin_frame_; 232 bool draw_will_happen_; 233 bool swap_will_happen_if_draw_happens_; 234 bool automatic_swap_ack_; 235 int num_draws_; 236 bool log_anticipated_draw_time_change_; 237 bool swap_contains_incomplete_tile_; 238 bool redraw_will_happen_if_update_visible_tiles_happens_; 239 base::TimeTicks posted_begin_impl_frame_deadline_; 240 std::vector<const char*> actions_; 241 ScopedVector<base::Value> states_; 242 scoped_ptr<TestScheduler> scheduler_; 243 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; 244 }; 245 246 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler, 247 FakeSchedulerClient* client) { 248 bool client_initiates_begin_frame = 249 scheduler->settings().begin_frame_scheduling_enabled && 250 scheduler->settings().throttle_frame_production; 251 252 scheduler->DidCreateAndInitializeOutputSurface(); 253 scheduler->SetNeedsCommit(); 254 scheduler->NotifyBeginMainFrameStarted(); 255 scheduler->NotifyReadyToCommit(); 256 if (scheduler->settings().impl_side_painting) 257 scheduler->NotifyReadyToActivate(); 258 // Go through the motions to draw the commit. 259 if (client_initiates_begin_frame) 260 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 261 else 262 client->task_runner().RunPendingTasks(); // Run posted BeginFrame. 263 264 // Run the posted deadline task. 265 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 266 client->task_runner().RunPendingTasks(); 267 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 268 269 // We need another BeginImplFrame so Scheduler calls 270 // SetNeedsBeginFrame(false). 271 if (client_initiates_begin_frame) 272 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 273 else 274 client->task_runner().RunPendingTasks(); // Run posted BeginFrame. 275 276 // Run the posted deadline task. 277 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 278 client->task_runner().RunPendingTasks(); 279 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 280 } 281 282 TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) { 283 FakeSchedulerClient client; 284 SchedulerSettings default_scheduler_settings; 285 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 286 scheduler->SetCanStart(); 287 scheduler->SetVisible(true); 288 scheduler->SetCanDraw(true); 289 290 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 291 client.Reset(); 292 scheduler->DidCreateAndInitializeOutputSurface(); 293 EXPECT_NO_ACTION(client); 294 } 295 296 TEST(SchedulerTest, RequestCommit) { 297 FakeSchedulerClient client; 298 SchedulerSettings scheduler_settings; 299 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 300 scheduler->SetCanStart(); 301 scheduler->SetVisible(true); 302 scheduler->SetCanDraw(true); 303 304 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 305 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 306 307 // SetNeedsCommit should begin the frame on the next BeginImplFrame. 308 client.Reset(); 309 scheduler->SetNeedsCommit(); 310 EXPECT_TRUE(client.needs_begin_frame()); 311 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 312 client.Reset(); 313 314 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 315 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 316 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 317 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 318 EXPECT_TRUE(client.needs_begin_frame()); 319 client.Reset(); 320 321 // If we don't swap on the deadline, we wait for the next BeginFrame. 322 client.task_runner().RunPendingTasks(); // Run posted deadline. 323 EXPECT_NO_ACTION(client); 324 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 325 EXPECT_TRUE(client.needs_begin_frame()); 326 client.Reset(); 327 328 // NotifyReadyToCommit should trigger the commit. 329 scheduler->NotifyBeginMainFrameStarted(); 330 scheduler->NotifyReadyToCommit(); 331 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 332 EXPECT_TRUE(client.needs_begin_frame()); 333 client.Reset(); 334 335 // BeginImplFrame should prepare the draw. 336 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 337 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 338 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 339 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 340 EXPECT_TRUE(client.needs_begin_frame()); 341 client.Reset(); 342 343 // BeginImplFrame deadline should draw. 344 client.task_runner().RunPendingTasks(); // Run posted deadline. 345 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); 346 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 347 EXPECT_TRUE(client.needs_begin_frame()); 348 client.Reset(); 349 350 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) 351 // to avoid excessive toggles. 352 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 353 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); 354 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 355 client.Reset(); 356 357 client.task_runner().RunPendingTasks(); // Run posted deadline. 358 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 359 EXPECT_FALSE(client.needs_begin_frame()); 360 client.Reset(); 361 } 362 363 TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { 364 FakeSchedulerClient client; 365 SchedulerSettings scheduler_settings; 366 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 367 scheduler->SetCanStart(); 368 scheduler->SetVisible(true); 369 scheduler->SetCanDraw(true); 370 371 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 372 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 373 client.Reset(); 374 375 // SetNeedsCommit should begin the frame. 376 scheduler->SetNeedsCommit(); 377 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 378 379 client.Reset(); 380 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 381 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 382 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 383 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 384 385 EXPECT_TRUE(client.needs_begin_frame()); 386 client.Reset(); 387 388 // Now SetNeedsCommit again. Calling here means we need a second commit. 389 scheduler->SetNeedsCommit(); 390 EXPECT_EQ(client.num_actions_(), 0); 391 client.Reset(); 392 393 // Finish the first commit. 394 scheduler->NotifyBeginMainFrameStarted(); 395 scheduler->NotifyReadyToCommit(); 396 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 397 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 398 client.Reset(); 399 client.task_runner().RunPendingTasks(); // Run posted deadline. 400 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); 401 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); 402 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 403 404 // Because we just swapped, the Scheduler should also request the next 405 // BeginImplFrame from the OutputSurface. 406 EXPECT_TRUE(client.needs_begin_frame()); 407 client.Reset(); 408 // Since another commit is needed, the next BeginImplFrame should initiate 409 // the second commit. 410 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 411 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 412 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 413 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 414 client.Reset(); 415 416 // Finishing the commit before the deadline should post a new deadline task 417 // to trigger the deadline early. 418 scheduler->NotifyBeginMainFrameStarted(); 419 scheduler->NotifyReadyToCommit(); 420 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 421 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 422 client.Reset(); 423 client.task_runner().RunPendingTasks(); // Run posted deadline. 424 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); 425 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); 426 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 427 EXPECT_TRUE(client.needs_begin_frame()); 428 client.Reset(); 429 430 // On the next BeginImplFrame, verify we go back to a quiescent state and 431 // no longer request BeginImplFrames. 432 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 433 client.task_runner().RunPendingTasks(); // Run posted deadline. 434 EXPECT_FALSE(client.needs_begin_frame()); 435 client.Reset(); 436 } 437 438 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient { 439 public: 440 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {} 441 virtual DrawResult ScheduledActionDrawAndSwapIfPossible() 442 OVERRIDE { 443 // Only SetNeedsRedraw the first time this is called 444 if (!num_draws_) 445 scheduler_->SetNeedsRedraw(); 446 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible(); 447 } 448 449 virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE { 450 NOTREACHED(); 451 return DRAW_SUCCESS; 452 } 453 454 virtual void ScheduledActionCommit() OVERRIDE {} 455 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {} 456 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {} 457 }; 458 459 // Tests for two different situations: 460 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside 461 // a ScheduledActionDrawAndSwap 462 // 2. the scheduler drawing twice inside a single tick 463 TEST(SchedulerTest, RequestRedrawInsideDraw) { 464 SchedulerClientThatsetNeedsDrawInsideDraw client; 465 SchedulerSettings default_scheduler_settings; 466 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 467 scheduler->SetCanStart(); 468 scheduler->SetVisible(true); 469 scheduler->SetCanDraw(true); 470 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 471 client.Reset(); 472 473 scheduler->SetNeedsRedraw(); 474 EXPECT_TRUE(scheduler->RedrawPending()); 475 EXPECT_TRUE(client.needs_begin_frame()); 476 EXPECT_EQ(0, client.num_draws()); 477 478 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 479 client.task_runner().RunPendingTasks(); // Run posted deadline. 480 EXPECT_EQ(1, client.num_draws()); 481 EXPECT_TRUE(scheduler->RedrawPending()); 482 EXPECT_TRUE(client.needs_begin_frame()); 483 484 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 485 client.task_runner().RunPendingTasks(); // Run posted deadline. 486 EXPECT_EQ(2, client.num_draws()); 487 EXPECT_FALSE(scheduler->RedrawPending()); 488 EXPECT_TRUE(client.needs_begin_frame()); 489 490 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't 491 // swap. 492 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 493 client.task_runner().RunPendingTasks(); // Run posted deadline. 494 EXPECT_EQ(2, client.num_draws()); 495 EXPECT_FALSE(scheduler->RedrawPending()); 496 EXPECT_FALSE(client.needs_begin_frame()); 497 } 498 499 // Test that requesting redraw inside a failed draw doesn't lose the request. 500 TEST(SchedulerTest, RequestRedrawInsideFailedDraw) { 501 SchedulerClientThatsetNeedsDrawInsideDraw client; 502 SchedulerSettings default_scheduler_settings; 503 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 504 scheduler->SetCanStart(); 505 scheduler->SetVisible(true); 506 scheduler->SetCanDraw(true); 507 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 508 client.Reset(); 509 510 client.SetDrawWillHappen(false); 511 512 scheduler->SetNeedsRedraw(); 513 EXPECT_TRUE(scheduler->RedrawPending()); 514 EXPECT_TRUE(client.needs_begin_frame()); 515 EXPECT_EQ(0, client.num_draws()); 516 517 // Fail the draw. 518 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 519 client.task_runner().RunPendingTasks(); // Run posted deadline. 520 EXPECT_EQ(1, client.num_draws()); 521 522 // We have a commit pending and the draw failed, and we didn't lose the redraw 523 // request. 524 EXPECT_TRUE(scheduler->CommitPending()); 525 EXPECT_TRUE(scheduler->RedrawPending()); 526 EXPECT_TRUE(client.needs_begin_frame()); 527 528 // Fail the draw again. 529 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 530 client.task_runner().RunPendingTasks(); // Run posted deadline. 531 EXPECT_EQ(2, client.num_draws()); 532 EXPECT_TRUE(scheduler->CommitPending()); 533 EXPECT_TRUE(scheduler->RedrawPending()); 534 EXPECT_TRUE(client.needs_begin_frame()); 535 536 // Draw successfully. 537 client.SetDrawWillHappen(true); 538 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 539 client.task_runner().RunPendingTasks(); // Run posted deadline. 540 EXPECT_EQ(3, client.num_draws()); 541 EXPECT_TRUE(scheduler->CommitPending()); 542 EXPECT_FALSE(scheduler->RedrawPending()); 543 EXPECT_TRUE(client.needs_begin_frame()); 544 } 545 546 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient { 547 public: 548 SchedulerClientThatSetNeedsCommitInsideDraw() 549 : set_needs_commit_on_next_draw_(false) {} 550 551 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {} 552 virtual DrawResult ScheduledActionDrawAndSwapIfPossible() 553 OVERRIDE { 554 // Only SetNeedsCommit the first time this is called 555 if (set_needs_commit_on_next_draw_) { 556 scheduler_->SetNeedsCommit(); 557 set_needs_commit_on_next_draw_ = false; 558 } 559 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible(); 560 } 561 562 virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE { 563 NOTREACHED(); 564 return DRAW_SUCCESS; 565 } 566 567 virtual void ScheduledActionCommit() OVERRIDE {} 568 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {} 569 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {} 570 571 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; } 572 573 private: 574 bool set_needs_commit_on_next_draw_; 575 }; 576 577 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that 578 // happen inside a ScheduledActionDrawAndSwap 579 TEST(SchedulerTest, RequestCommitInsideDraw) { 580 SchedulerClientThatSetNeedsCommitInsideDraw client; 581 SchedulerSettings default_scheduler_settings; 582 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 583 scheduler->SetCanStart(); 584 scheduler->SetVisible(true); 585 scheduler->SetCanDraw(true); 586 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 587 client.Reset(); 588 589 EXPECT_FALSE(client.needs_begin_frame()); 590 scheduler->SetNeedsRedraw(); 591 EXPECT_TRUE(scheduler->RedrawPending()); 592 EXPECT_EQ(0, client.num_draws()); 593 EXPECT_TRUE(client.needs_begin_frame()); 594 595 client.SetNeedsCommitOnNextDraw(); 596 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 597 client.SetNeedsCommitOnNextDraw(); 598 client.task_runner().RunPendingTasks(); // Run posted deadline. 599 EXPECT_EQ(1, client.num_draws()); 600 EXPECT_TRUE(scheduler->CommitPending()); 601 EXPECT_TRUE(client.needs_begin_frame()); 602 scheduler->NotifyBeginMainFrameStarted(); 603 scheduler->NotifyReadyToCommit(); 604 605 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 606 client.task_runner().RunPendingTasks(); // Run posted deadline. 607 EXPECT_EQ(2, client.num_draws()); 608 609 EXPECT_FALSE(scheduler->RedrawPending()); 610 EXPECT_FALSE(scheduler->CommitPending()); 611 EXPECT_TRUE(client.needs_begin_frame()); 612 613 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't 614 // swap. 615 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 616 client.task_runner().RunPendingTasks(); // Run posted deadline. 617 EXPECT_EQ(2, client.num_draws()); 618 EXPECT_FALSE(scheduler->RedrawPending()); 619 EXPECT_FALSE(scheduler->CommitPending()); 620 EXPECT_FALSE(client.needs_begin_frame()); 621 } 622 623 // Tests that when a draw fails then the pending commit should not be dropped. 624 TEST(SchedulerTest, RequestCommitInsideFailedDraw) { 625 SchedulerClientThatsetNeedsDrawInsideDraw client; 626 SchedulerSettings default_scheduler_settings; 627 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 628 scheduler->SetCanStart(); 629 scheduler->SetVisible(true); 630 scheduler->SetCanDraw(true); 631 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 632 client.Reset(); 633 634 client.SetDrawWillHappen(false); 635 636 scheduler->SetNeedsRedraw(); 637 EXPECT_TRUE(scheduler->RedrawPending()); 638 EXPECT_TRUE(client.needs_begin_frame()); 639 EXPECT_EQ(0, client.num_draws()); 640 641 // Fail the draw. 642 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 643 client.task_runner().RunPendingTasks(); // Run posted deadline. 644 EXPECT_EQ(1, client.num_draws()); 645 646 // We have a commit pending and the draw failed, and we didn't lose the commit 647 // request. 648 EXPECT_TRUE(scheduler->CommitPending()); 649 EXPECT_TRUE(scheduler->RedrawPending()); 650 EXPECT_TRUE(client.needs_begin_frame()); 651 652 // Fail the draw again. 653 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 654 655 client.task_runner().RunPendingTasks(); // Run posted deadline. 656 EXPECT_EQ(2, client.num_draws()); 657 EXPECT_TRUE(scheduler->CommitPending()); 658 EXPECT_TRUE(scheduler->RedrawPending()); 659 EXPECT_TRUE(client.needs_begin_frame()); 660 661 // Draw successfully. 662 client.SetDrawWillHappen(true); 663 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 664 client.task_runner().RunPendingTasks(); // Run posted deadline. 665 EXPECT_EQ(3, client.num_draws()); 666 EXPECT_TRUE(scheduler->CommitPending()); 667 EXPECT_FALSE(scheduler->RedrawPending()); 668 EXPECT_TRUE(client.needs_begin_frame()); 669 } 670 671 TEST(SchedulerTest, NoSwapWhenDrawFails) { 672 SchedulerClientThatSetNeedsCommitInsideDraw client; 673 SchedulerSettings default_scheduler_settings; 674 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 675 scheduler->SetCanStart(); 676 scheduler->SetVisible(true); 677 scheduler->SetCanDraw(true); 678 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 679 client.Reset(); 680 681 scheduler->SetNeedsRedraw(); 682 EXPECT_TRUE(scheduler->RedrawPending()); 683 EXPECT_TRUE(client.needs_begin_frame()); 684 EXPECT_EQ(0, client.num_draws()); 685 686 // Draw successfully, this starts a new frame. 687 client.SetNeedsCommitOnNextDraw(); 688 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 689 client.task_runner().RunPendingTasks(); // Run posted deadline. 690 EXPECT_EQ(1, client.num_draws()); 691 692 scheduler->SetNeedsRedraw(); 693 EXPECT_TRUE(scheduler->RedrawPending()); 694 EXPECT_TRUE(client.needs_begin_frame()); 695 696 // Fail to draw, this should not start a frame. 697 client.SetDrawWillHappen(false); 698 client.SetNeedsCommitOnNextDraw(); 699 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 700 client.task_runner().RunPendingTasks(); // Run posted deadline. 701 EXPECT_EQ(2, client.num_draws()); 702 } 703 704 class SchedulerClientNeedsManageTilesInDraw : public FakeSchedulerClient { 705 public: 706 virtual DrawResult ScheduledActionDrawAndSwapIfPossible() 707 OVERRIDE { 708 scheduler_->SetNeedsManageTiles(); 709 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible(); 710 } 711 }; 712 713 // Test manage tiles is independant of draws. 714 TEST(SchedulerTest, ManageTiles) { 715 SchedulerClientNeedsManageTilesInDraw client; 716 SchedulerSettings default_scheduler_settings; 717 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 718 scheduler->SetCanStart(); 719 scheduler->SetVisible(true); 720 scheduler->SetCanDraw(true); 721 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 722 723 // Request both draw and manage tiles. ManageTiles shouldn't 724 // be trigged until BeginImplFrame. 725 client.Reset(); 726 scheduler->SetNeedsManageTiles(); 727 scheduler->SetNeedsRedraw(); 728 EXPECT_TRUE(scheduler->RedrawPending()); 729 EXPECT_TRUE(scheduler->ManageTilesPending()); 730 EXPECT_TRUE(client.needs_begin_frame()); 731 EXPECT_EQ(0, client.num_draws()); 732 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles")); 733 EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible")); 734 735 // We have no immediate actions to perform, so the BeginImplFrame should post 736 // the deadline task. 737 client.Reset(); 738 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 739 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 740 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 741 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 742 743 // On the deadline, he actions should have occured in the right order. 744 client.Reset(); 745 client.task_runner().RunPendingTasks(); // Run posted deadline. 746 EXPECT_EQ(1, client.num_draws()); 747 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible")); 748 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles")); 749 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"), 750 client.ActionIndex("ScheduledActionManageTiles")); 751 EXPECT_FALSE(scheduler->RedrawPending()); 752 EXPECT_FALSE(scheduler->ManageTilesPending()); 753 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 754 755 // Request a draw. We don't need a ManageTiles yet. 756 client.Reset(); 757 scheduler->SetNeedsRedraw(); 758 EXPECT_TRUE(scheduler->RedrawPending()); 759 EXPECT_FALSE(scheduler->ManageTilesPending()); 760 EXPECT_TRUE(client.needs_begin_frame()); 761 EXPECT_EQ(0, client.num_draws()); 762 763 // We have no immediate actions to perform, so the BeginImplFrame should post 764 // the deadline task. 765 client.Reset(); 766 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 767 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 768 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 769 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 770 771 // Draw. The draw will trigger SetNeedsManageTiles, and 772 // then the ManageTiles action will be triggered after the Draw. 773 // Afterwards, neither a draw nor ManageTiles are pending. 774 client.Reset(); 775 client.task_runner().RunPendingTasks(); // Run posted deadline. 776 EXPECT_EQ(1, client.num_draws()); 777 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible")); 778 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles")); 779 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"), 780 client.ActionIndex("ScheduledActionManageTiles")); 781 EXPECT_FALSE(scheduler->RedrawPending()); 782 EXPECT_FALSE(scheduler->ManageTilesPending()); 783 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 784 785 // We need a BeginImplFrame where we don't swap to go idle. 786 client.Reset(); 787 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 788 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); 789 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 790 client.Reset(); 791 client.task_runner().RunPendingTasks(); // Run posted deadline. 792 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 793 EXPECT_FALSE(client.needs_begin_frame()); 794 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 795 EXPECT_EQ(0, client.num_draws()); 796 797 // Now trigger a ManageTiles outside of a draw. We will then need 798 // a begin-frame for the ManageTiles, but we don't need a draw. 799 client.Reset(); 800 EXPECT_FALSE(client.needs_begin_frame()); 801 scheduler->SetNeedsManageTiles(); 802 EXPECT_TRUE(client.needs_begin_frame()); 803 EXPECT_TRUE(scheduler->ManageTilesPending()); 804 EXPECT_FALSE(scheduler->RedrawPending()); 805 806 // BeginImplFrame. There will be no draw, only ManageTiles. 807 client.Reset(); 808 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 809 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); 810 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 811 client.Reset(); 812 client.task_runner().RunPendingTasks(); // Run posted deadline. 813 EXPECT_EQ(0, client.num_draws()); 814 EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible")); 815 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles")); 816 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 817 } 818 819 // Test that ManageTiles only happens once per frame. If an external caller 820 // initiates it, then the state machine should not ManageTiles on that frame. 821 TEST(SchedulerTest, ManageTilesOncePerFrame) { 822 FakeSchedulerClient client; 823 SchedulerSettings default_scheduler_settings; 824 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 825 scheduler->SetCanStart(); 826 scheduler->SetVisible(true); 827 scheduler->SetCanDraw(true); 828 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 829 830 // If DidManageTiles during a frame, then ManageTiles should not occur again. 831 scheduler->SetNeedsManageTiles(); 832 scheduler->SetNeedsRedraw(); 833 client.Reset(); 834 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 835 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 836 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 837 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 838 839 EXPECT_TRUE(scheduler->ManageTilesPending()); 840 scheduler->DidManageTiles(); // An explicit ManageTiles. 841 EXPECT_FALSE(scheduler->ManageTilesPending()); 842 843 client.Reset(); 844 client.task_runner().RunPendingTasks(); // Run posted deadline. 845 EXPECT_EQ(1, client.num_draws()); 846 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible")); 847 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles")); 848 EXPECT_FALSE(scheduler->RedrawPending()); 849 EXPECT_FALSE(scheduler->ManageTilesPending()); 850 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 851 852 // Next frame without DidManageTiles should ManageTiles with draw. 853 scheduler->SetNeedsManageTiles(); 854 scheduler->SetNeedsRedraw(); 855 client.Reset(); 856 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 857 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 858 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 859 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 860 861 client.Reset(); 862 client.task_runner().RunPendingTasks(); // Run posted deadline. 863 EXPECT_EQ(1, client.num_draws()); 864 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible")); 865 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles")); 866 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"), 867 client.ActionIndex("ScheduledActionManageTiles")); 868 EXPECT_FALSE(scheduler->RedrawPending()); 869 EXPECT_FALSE(scheduler->ManageTilesPending()); 870 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 871 scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles 872 873 // If we get another DidManageTiles within the same frame, we should 874 // not ManageTiles on the next frame. 875 scheduler->DidManageTiles(); // An explicit ManageTiles. 876 scheduler->SetNeedsManageTiles(); 877 scheduler->SetNeedsRedraw(); 878 client.Reset(); 879 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 880 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 881 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 882 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 883 884 EXPECT_TRUE(scheduler->ManageTilesPending()); 885 886 client.Reset(); 887 client.task_runner().RunPendingTasks(); // Run posted deadline. 888 EXPECT_EQ(1, client.num_draws()); 889 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible")); 890 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles")); 891 EXPECT_FALSE(scheduler->RedrawPending()); 892 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 893 894 // If we get another DidManageTiles, we should not ManageTiles on the next 895 // frame. This verifies we don't alternate calling ManageTiles once and twice. 896 EXPECT_TRUE(scheduler->ManageTilesPending()); 897 scheduler->DidManageTiles(); // An explicit ManageTiles. 898 EXPECT_FALSE(scheduler->ManageTilesPending()); 899 scheduler->SetNeedsManageTiles(); 900 scheduler->SetNeedsRedraw(); 901 client.Reset(); 902 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 903 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 904 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 905 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 906 907 EXPECT_TRUE(scheduler->ManageTilesPending()); 908 909 client.Reset(); 910 client.task_runner().RunPendingTasks(); // Run posted deadline. 911 EXPECT_EQ(1, client.num_draws()); 912 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible")); 913 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles")); 914 EXPECT_FALSE(scheduler->RedrawPending()); 915 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 916 917 // Next frame without DidManageTiles should ManageTiles with draw. 918 scheduler->SetNeedsManageTiles(); 919 scheduler->SetNeedsRedraw(); 920 client.Reset(); 921 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 922 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 923 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 924 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 925 926 client.Reset(); 927 client.task_runner().RunPendingTasks(); // Run posted deadline. 928 EXPECT_EQ(1, client.num_draws()); 929 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible")); 930 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles")); 931 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"), 932 client.ActionIndex("ScheduledActionManageTiles")); 933 EXPECT_FALSE(scheduler->RedrawPending()); 934 EXPECT_FALSE(scheduler->ManageTilesPending()); 935 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 936 scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles 937 } 938 939 TEST(SchedulerTest, ShouldUpdateVisibleTiles) { 940 FakeSchedulerClient client; 941 SchedulerSettings scheduler_settings; 942 scheduler_settings.impl_side_painting = true; 943 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 944 scheduler->SetCanStart(); 945 scheduler->SetVisible(true); 946 scheduler->SetCanDraw(true); 947 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 948 949 client.SetRedrawWillHappenIfUpdateVisibleTilesHappens(true); 950 951 // SetNeedsCommit should begin the frame. 952 client.Reset(); 953 scheduler->SetNeedsCommit(); 954 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 955 956 client.Reset(); 957 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 958 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 959 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 960 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 961 962 client.Reset(); 963 scheduler->NotifyBeginMainFrameStarted(); 964 scheduler->NotifyReadyToCommit(); 965 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 966 967 client.Reset(); 968 scheduler->NotifyReadyToActivate(); 969 EXPECT_SINGLE_ACTION("ScheduledActionActivatePendingTree", client); 970 971 client.Reset(); 972 client.SetSwapContainsIncompleteTile(true); 973 client.task_runner().RunPendingTasks(); // Run posted deadline. 974 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); 975 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); 976 EXPECT_FALSE(scheduler->RedrawPending()); 977 978 client.Reset(); 979 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 980 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); 981 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 982 983 client.Reset(); 984 client.task_runner().RunPendingTasks(); // Run posted deadline. 985 EXPECT_ACTION("ScheduledActionUpdateVisibleTiles", client, 0, 3); 986 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 3); 987 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 2, 3); 988 989 client.Reset(); 990 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 991 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); 992 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 993 994 // No more UpdateVisibleTiles(). 995 client.Reset(); 996 client.task_runner().RunPendingTasks(); // Run posted deadline. 997 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 998 EXPECT_FALSE(client.needs_begin_frame()); 999 } 1000 1001 TEST(SchedulerTest, TriggerBeginFrameDeadlineEarly) { 1002 SchedulerClientNeedsManageTilesInDraw client; 1003 SchedulerSettings default_scheduler_settings; 1004 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 1005 scheduler->SetCanStart(); 1006 scheduler->SetVisible(true); 1007 scheduler->SetCanDraw(true); 1008 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1009 1010 client.Reset(); 1011 scheduler->SetNeedsRedraw(); 1012 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 1013 1014 // The deadline should be zero since there is no work other than drawing 1015 // pending. 1016 EXPECT_EQ(base::TimeTicks(), client.posted_begin_impl_frame_deadline()); 1017 } 1018 1019 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient { 1020 public: 1021 SchedulerClientWithFixedEstimates( 1022 base::TimeDelta draw_duration, 1023 base::TimeDelta begin_main_frame_to_commit_duration, 1024 base::TimeDelta commit_to_activate_duration) 1025 : draw_duration_(draw_duration), 1026 begin_main_frame_to_commit_duration_( 1027 begin_main_frame_to_commit_duration), 1028 commit_to_activate_duration_(commit_to_activate_duration) {} 1029 1030 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE { 1031 return draw_duration_; 1032 } 1033 virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE { 1034 return begin_main_frame_to_commit_duration_; 1035 } 1036 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE { 1037 return commit_to_activate_duration_; 1038 } 1039 1040 private: 1041 base::TimeDelta draw_duration_; 1042 base::TimeDelta begin_main_frame_to_commit_duration_; 1043 base::TimeDelta commit_to_activate_duration_; 1044 }; 1045 1046 void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms, 1047 int64 commit_to_activate_estimate_in_ms, 1048 bool smoothness_takes_priority, 1049 bool should_send_begin_main_frame) { 1050 // Set up client with specified estimates (draw duration is set to 1). 1051 SchedulerClientWithFixedEstimates client( 1052 base::TimeDelta::FromMilliseconds(1), 1053 base::TimeDelta::FromMilliseconds( 1054 begin_main_frame_to_commit_estimate_in_ms), 1055 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms)); 1056 SchedulerSettings default_scheduler_settings; 1057 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 1058 scheduler->SetCanStart(); 1059 scheduler->SetVisible(true); 1060 scheduler->SetCanDraw(true); 1061 scheduler->SetSmoothnessTakesPriority(smoothness_takes_priority); 1062 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1063 1064 // Impl thread hits deadline before commit finishes. 1065 client.Reset(); 1066 scheduler->SetNeedsCommit(); 1067 EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode()); 1068 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 1069 EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode()); 1070 client.task_runner().RunPendingTasks(); // Run posted deadline. 1071 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode()); 1072 scheduler->NotifyBeginMainFrameStarted(); 1073 scheduler->NotifyReadyToCommit(); 1074 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode()); 1075 EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame")); 1076 1077 client.Reset(); 1078 scheduler->SetNeedsCommit(); 1079 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode()); 1080 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 1081 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode()); 1082 client.task_runner().RunPendingTasks(); // Run posted deadline. 1083 EXPECT_EQ(scheduler->MainThreadIsInHighLatencyMode(), 1084 should_send_begin_main_frame); 1085 EXPECT_EQ(client.HasAction("ScheduledActionSendBeginMainFrame"), 1086 should_send_begin_main_frame); 1087 } 1088 1089 TEST(SchedulerTest, 1090 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) { 1091 // Set up client so that estimates indicate that we can commit and activate 1092 // before the deadline (~8ms by default). 1093 MainFrameInHighLatencyMode(1, 1, false, false); 1094 } 1095 1096 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) { 1097 // Set up client so that estimates indicate that the commit cannot finish 1098 // before the deadline (~8ms by default). 1099 MainFrameInHighLatencyMode(10, 1, false, true); 1100 } 1101 1102 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) { 1103 // Set up client so that estimates indicate that the activate cannot finish 1104 // before the deadline (~8ms by default). 1105 MainFrameInHighLatencyMode(1, 10, false, true); 1106 } 1107 1108 TEST(SchedulerTest, NotSkipMainFrameInPreferSmoothnessMode) { 1109 // Set up client so that estimates indicate that we can commit and activate 1110 // before the deadline (~8ms by default), but also enable smoothness takes 1111 // priority mode. 1112 MainFrameInHighLatencyMode(1, 1, true, true); 1113 } 1114 1115 TEST(SchedulerTest, PollForCommitCompletion) { 1116 // Since we are simulating a long commit, set up a client with draw duration 1117 // estimates that prevent skipping main frames to get to low latency mode. 1118 SchedulerClientWithFixedEstimates client( 1119 base::TimeDelta::FromMilliseconds(1), 1120 base::TimeDelta::FromMilliseconds(32), 1121 base::TimeDelta::FromMilliseconds(32)); 1122 client.set_log_anticipated_draw_time_change(true); 1123 SchedulerSettings default_scheduler_settings; 1124 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings); 1125 1126 scheduler->SetCanDraw(true); 1127 scheduler->SetCanStart(); 1128 scheduler->SetVisible(true); 1129 scheduler->DidCreateAndInitializeOutputSurface(); 1130 1131 scheduler->SetNeedsCommit(); 1132 EXPECT_TRUE(scheduler->CommitPending()); 1133 scheduler->NotifyBeginMainFrameStarted(); 1134 scheduler->NotifyReadyToCommit(); 1135 scheduler->SetNeedsRedraw(); 1136 1137 BeginFrameArgs frame_args = CreateBeginFrameArgsForTesting(); 1138 frame_args.interval = base::TimeDelta::FromMilliseconds(1000); 1139 scheduler->BeginFrame(frame_args); 1140 1141 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1142 client.task_runner().RunPendingTasks(); // Run posted deadline. 1143 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1144 1145 scheduler->DidSwapBuffers(); 1146 scheduler->DidSwapBuffersComplete(); 1147 1148 // At this point, we've drawn a frame. Start another commit, but hold off on 1149 // the NotifyReadyToCommit for now. 1150 EXPECT_FALSE(scheduler->CommitPending()); 1151 scheduler->SetNeedsCommit(); 1152 scheduler->BeginFrame(frame_args); 1153 EXPECT_TRUE(scheduler->CommitPending()); 1154 1155 // Draw and swap the frame, but don't ack the swap to simulate the Browser 1156 // blocking on the renderer. 1157 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1158 client.task_runner().RunPendingTasks(); // Run posted deadline. 1159 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1160 scheduler->DidSwapBuffers(); 1161 1162 // Spin the event loop a few times and make sure we get more 1163 // DidAnticipateDrawTimeChange calls every time. 1164 int actions_so_far = client.num_actions_(); 1165 1166 // Does three iterations to make sure that the timer is properly repeating. 1167 for (int i = 0; i < 3; ++i) { 1168 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(), 1169 client.task_runner().NextPendingTaskDelay().InMicroseconds()) 1170 << *scheduler->AsValue(); 1171 client.task_runner().RunPendingTasks(); 1172 EXPECT_GT(client.num_actions_(), actions_so_far); 1173 EXPECT_STREQ(client.Action(client.num_actions_() - 1), 1174 "DidAnticipatedDrawTimeChange"); 1175 actions_so_far = client.num_actions_(); 1176 } 1177 1178 // Do the same thing after BeginMainFrame starts but still before activation. 1179 scheduler->NotifyBeginMainFrameStarted(); 1180 for (int i = 0; i < 3; ++i) { 1181 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(), 1182 client.task_runner().NextPendingTaskDelay().InMicroseconds()) 1183 << *scheduler->AsValue(); 1184 client.task_runner().RunPendingTasks(); 1185 EXPECT_GT(client.num_actions_(), actions_so_far); 1186 EXPECT_STREQ(client.Action(client.num_actions_() - 1), 1187 "DidAnticipatedDrawTimeChange"); 1188 actions_so_far = client.num_actions_(); 1189 } 1190 } 1191 1192 TEST(SchedulerTest, BeginRetroFrame) { 1193 FakeSchedulerClient client; 1194 SchedulerSettings scheduler_settings; 1195 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1196 scheduler->SetCanStart(); 1197 scheduler->SetVisible(true); 1198 scheduler->SetCanDraw(true); 1199 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1200 1201 // SetNeedsCommit should begin the frame on the next BeginImplFrame. 1202 client.Reset(); 1203 scheduler->SetNeedsCommit(); 1204 EXPECT_TRUE(client.needs_begin_frame()); 1205 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1206 client.Reset(); 1207 1208 // Create a BeginFrame with a long deadline to avoid race conditions. 1209 // This is the first BeginFrame, which will be handled immediately. 1210 BeginFrameArgs args = CreateBeginFrameArgsForTesting(); 1211 args.deadline += base::TimeDelta::FromHours(1); 1212 scheduler->BeginFrame(args); 1213 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1214 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1215 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1216 EXPECT_TRUE(client.needs_begin_frame()); 1217 client.Reset(); 1218 1219 // Queue BeginFrames while we are still handling the previous BeginFrame. 1220 args.frame_time += base::TimeDelta::FromSeconds(1); 1221 scheduler->BeginFrame(args); 1222 args.frame_time += base::TimeDelta::FromSeconds(1); 1223 scheduler->BeginFrame(args); 1224 1225 // If we don't swap on the deadline, we wait for the next BeginImplFrame. 1226 client.task_runner().RunPendingTasks(); // Run posted deadline. 1227 EXPECT_NO_ACTION(client); 1228 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1229 EXPECT_TRUE(client.needs_begin_frame()); 1230 client.Reset(); 1231 1232 // NotifyReadyToCommit should trigger the commit. 1233 scheduler->NotifyBeginMainFrameStarted(); 1234 scheduler->NotifyReadyToCommit(); 1235 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 1236 EXPECT_TRUE(client.needs_begin_frame()); 1237 client.Reset(); 1238 1239 // BeginImplFrame should prepare the draw. 1240 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. 1241 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1242 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 1243 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1244 EXPECT_TRUE(client.needs_begin_frame()); 1245 client.Reset(); 1246 1247 // BeginImplFrame deadline should draw. 1248 client.task_runner().RunPendingTasks(); // Run posted deadline. 1249 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); 1250 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1251 EXPECT_TRUE(client.needs_begin_frame()); 1252 client.Reset(); 1253 1254 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) 1255 // to avoid excessive toggles. 1256 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. 1257 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); 1258 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1259 client.Reset(); 1260 1261 client.task_runner().RunPendingTasks(); // Run posted deadline. 1262 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1263 EXPECT_FALSE(client.needs_begin_frame()); 1264 client.Reset(); 1265 } 1266 1267 TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) { 1268 FakeSchedulerClient client; 1269 SchedulerSettings scheduler_settings; 1270 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1271 scheduler->SetCanStart(); 1272 scheduler->SetVisible(true); 1273 scheduler->SetCanDraw(true); 1274 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1275 1276 // To test swap ack throttling, this test disables automatic swap acks. 1277 scheduler->SetMaxSwapsPending(1); 1278 client.SetAutomaticSwapAck(false); 1279 1280 // SetNeedsCommit should begin the frame on the next BeginImplFrame. 1281 client.Reset(); 1282 scheduler->SetNeedsCommit(); 1283 EXPECT_TRUE(client.needs_begin_frame()); 1284 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1285 client.Reset(); 1286 1287 // Create a BeginFrame with a long deadline to avoid race conditions. 1288 // This is the first BeginFrame, which will be handled immediately. 1289 BeginFrameArgs args = CreateBeginFrameArgsForTesting(); 1290 args.deadline += base::TimeDelta::FromHours(1); 1291 scheduler->BeginFrame(args); 1292 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1293 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1294 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1295 EXPECT_TRUE(client.needs_begin_frame()); 1296 client.Reset(); 1297 1298 // Queue BeginFrame while we are still handling the previous BeginFrame. 1299 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1300 args.frame_time += base::TimeDelta::FromSeconds(1); 1301 scheduler->BeginFrame(args); 1302 EXPECT_NO_ACTION(client); 1303 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1304 client.Reset(); 1305 1306 // NotifyReadyToCommit should trigger the pending commit and draw. 1307 scheduler->NotifyBeginMainFrameStarted(); 1308 scheduler->NotifyReadyToCommit(); 1309 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 1310 EXPECT_TRUE(client.needs_begin_frame()); 1311 client.Reset(); 1312 1313 // Swapping will put us into a swap throttled state. 1314 client.task_runner().RunPendingTasks(); // Run posted deadline. 1315 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); 1316 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); 1317 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1318 EXPECT_TRUE(client.needs_begin_frame()); 1319 client.Reset(); 1320 1321 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames 1322 // but not a BeginMainFrame or draw. 1323 scheduler->SetNeedsCommit(); 1324 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. 1325 EXPECT_ACTION("WillBeginImplFrame", client, 0, 1); 1326 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1327 EXPECT_TRUE(client.needs_begin_frame()); 1328 client.Reset(); 1329 1330 // Queue BeginFrame while we are still handling the previous BeginFrame. 1331 args.frame_time += base::TimeDelta::FromSeconds(1); 1332 scheduler->BeginFrame(args); 1333 EXPECT_NO_ACTION(client); 1334 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1335 EXPECT_TRUE(client.needs_begin_frame()); 1336 client.Reset(); 1337 1338 // Take us out of a swap throttled state. 1339 scheduler->DidSwapBuffersComplete(); 1340 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1); 1341 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1342 EXPECT_TRUE(client.needs_begin_frame()); 1343 client.Reset(); 1344 1345 // BeginImplFrame deadline should draw. 1346 scheduler->SetNeedsRedraw(); 1347 client.task_runner().RunPendingTasks(); // Run posted deadline. 1348 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); 1349 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); 1350 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1351 EXPECT_TRUE(client.needs_begin_frame()); 1352 client.Reset(); 1353 } 1354 1355 void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled, 1356 bool throttle_frame_production) { 1357 FakeSchedulerClient client; 1358 SchedulerSettings scheduler_settings; 1359 scheduler_settings.begin_frame_scheduling_enabled = 1360 begin_frame_scheduling_enabled; 1361 scheduler_settings.throttle_frame_production = throttle_frame_production; 1362 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1363 scheduler->SetCanStart(); 1364 scheduler->SetVisible(true); 1365 scheduler->SetCanDraw(true); 1366 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1367 1368 // SetNeedsCommit should begin the frame on the next BeginImplFrame 1369 // without calling SetNeedsBeginFrame. 1370 client.Reset(); 1371 scheduler->SetNeedsCommit(); 1372 EXPECT_FALSE(client.needs_begin_frame()); 1373 EXPECT_NO_ACTION(client); 1374 client.Reset(); 1375 1376 // When the client-driven BeginFrame are disabled, the scheduler posts it's 1377 // own BeginFrame tasks. 1378 client.task_runner().RunPendingTasks(); // Run posted BeginFrame. 1379 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1380 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1381 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1382 EXPECT_FALSE(client.needs_begin_frame()); 1383 client.Reset(); 1384 1385 // If we don't swap on the deadline, we wait for the next BeginFrame. 1386 client.task_runner().RunPendingTasks(); // Run posted deadline. 1387 EXPECT_NO_ACTION(client); 1388 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1389 EXPECT_FALSE(client.needs_begin_frame()); 1390 client.Reset(); 1391 1392 // NotifyReadyToCommit should trigger the commit. 1393 scheduler->NotifyBeginMainFrameStarted(); 1394 scheduler->NotifyReadyToCommit(); 1395 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 1396 EXPECT_FALSE(client.needs_begin_frame()); 1397 client.Reset(); 1398 1399 // BeginImplFrame should prepare the draw. 1400 client.task_runner().RunPendingTasks(); // Run posted BeginFrame. 1401 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1402 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 1403 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1404 EXPECT_FALSE(client.needs_begin_frame()); 1405 client.Reset(); 1406 1407 // BeginImplFrame deadline should draw. 1408 client.task_runner().RunPendingTasks(); // Run posted deadline. 1409 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); 1410 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1411 EXPECT_FALSE(client.needs_begin_frame()); 1412 client.Reset(); 1413 1414 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) 1415 // to avoid excessive toggles. 1416 client.task_runner().RunPendingTasks(); // Run posted BeginFrame. 1417 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); 1418 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1419 client.Reset(); 1420 1421 // Make sure SetNeedsBeginFrame isn't called on the client 1422 // when the BeginFrame is no longer needed. 1423 client.task_runner().RunPendingTasks(); // Run posted deadline. 1424 EXPECT_NO_ACTION(client); 1425 EXPECT_FALSE(client.needs_begin_frame()); 1426 client.Reset(); 1427 } 1428 1429 TEST(SchedulerTest, SyntheticBeginFrames) { 1430 bool begin_frame_scheduling_enabled = false; 1431 bool throttle_frame_production = true; 1432 BeginFramesNotFromClient(begin_frame_scheduling_enabled, 1433 throttle_frame_production); 1434 } 1435 1436 TEST(SchedulerTest, VSyncThrottlingDisabled) { 1437 bool begin_frame_scheduling_enabled = true; 1438 bool throttle_frame_production = false; 1439 BeginFramesNotFromClient(begin_frame_scheduling_enabled, 1440 throttle_frame_production); 1441 } 1442 1443 TEST(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) { 1444 bool begin_frame_scheduling_enabled = false; 1445 bool throttle_frame_production = false; 1446 BeginFramesNotFromClient(begin_frame_scheduling_enabled, 1447 throttle_frame_production); 1448 } 1449 1450 void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled, 1451 bool throttle_frame_production) { 1452 FakeSchedulerClient client; 1453 SchedulerSettings scheduler_settings; 1454 scheduler_settings.begin_frame_scheduling_enabled = 1455 begin_frame_scheduling_enabled; 1456 scheduler_settings.throttle_frame_production = throttle_frame_production; 1457 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1458 scheduler->SetCanStart(); 1459 scheduler->SetVisible(true); 1460 scheduler->SetCanDraw(true); 1461 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1462 1463 // To test swap ack throttling, this test disables automatic swap acks. 1464 scheduler->SetMaxSwapsPending(1); 1465 client.SetAutomaticSwapAck(false); 1466 1467 // SetNeedsCommit should begin the frame on the next BeginImplFrame. 1468 client.Reset(); 1469 scheduler->SetNeedsCommit(); 1470 EXPECT_FALSE(client.needs_begin_frame()); 1471 EXPECT_NO_ACTION(client); 1472 client.Reset(); 1473 1474 // Trigger the first BeginImplFrame and BeginMainFrame 1475 client.task_runner().RunPendingTasks(); // Run posted BeginFrame. 1476 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1477 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1478 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1479 EXPECT_FALSE(client.needs_begin_frame()); 1480 client.Reset(); 1481 1482 // NotifyReadyToCommit should trigger the pending commit and draw. 1483 scheduler->NotifyBeginMainFrameStarted(); 1484 scheduler->NotifyReadyToCommit(); 1485 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 1486 EXPECT_FALSE(client.needs_begin_frame()); 1487 client.Reset(); 1488 1489 // Swapping will put us into a swap throttled state. 1490 client.task_runner().RunPendingTasks(); // Run posted deadline. 1491 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); 1492 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); 1493 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1494 EXPECT_FALSE(client.needs_begin_frame()); 1495 client.Reset(); 1496 1497 // While swap throttled, BeginFrames should trigger BeginImplFrames, 1498 // but not a BeginMainFrame or draw. 1499 scheduler->SetNeedsCommit(); 1500 client.task_runner().RunPendingTasks(); // Run posted BeginFrame. 1501 EXPECT_ACTION("WillBeginImplFrame", client, 0, 1); 1502 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1503 EXPECT_FALSE(client.needs_begin_frame()); 1504 client.Reset(); 1505 1506 // Take us out of a swap throttled state. 1507 scheduler->DidSwapBuffersComplete(); 1508 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1); 1509 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1510 EXPECT_FALSE(client.needs_begin_frame()); 1511 client.Reset(); 1512 1513 // BeginImplFrame deadline should draw. 1514 scheduler->SetNeedsRedraw(); 1515 client.task_runner().RunPendingTasks(); // Run posted deadline. 1516 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); 1517 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); 1518 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1519 EXPECT_FALSE(client.needs_begin_frame()); 1520 client.Reset(); 1521 } 1522 1523 TEST(SchedulerTest, SyntheticBeginFrames_SwapThrottled) { 1524 bool begin_frame_scheduling_enabled = false; 1525 bool throttle_frame_production = true; 1526 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled, 1527 throttle_frame_production); 1528 } 1529 1530 TEST(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) { 1531 bool begin_frame_scheduling_enabled = true; 1532 bool throttle_frame_production = false; 1533 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled, 1534 throttle_frame_production); 1535 } 1536 1537 TEST(SchedulerTest, 1538 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) { 1539 bool begin_frame_scheduling_enabled = false; 1540 bool throttle_frame_production = false; 1541 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled, 1542 throttle_frame_production); 1543 } 1544 1545 TEST(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) { 1546 FakeSchedulerClient client; 1547 SchedulerSettings scheduler_settings; 1548 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1549 scheduler->SetCanStart(); 1550 scheduler->SetVisible(true); 1551 scheduler->SetCanDraw(true); 1552 1553 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 1554 client.Reset(); 1555 scheduler->DidCreateAndInitializeOutputSurface(); 1556 EXPECT_NO_ACTION(client); 1557 1558 scheduler->DidLoseOutputSurface(); 1559 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 1560 } 1561 1562 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) { 1563 FakeSchedulerClient client; 1564 SchedulerSettings scheduler_settings; 1565 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1566 scheduler->SetCanStart(); 1567 scheduler->SetVisible(true); 1568 scheduler->SetCanDraw(true); 1569 1570 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 1571 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1572 // SetNeedsCommit should begin the frame. 1573 client.Reset(); 1574 scheduler->SetNeedsCommit(); 1575 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1576 1577 client.Reset(); 1578 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 1579 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1580 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1581 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1582 1583 client.Reset(); 1584 scheduler->DidLoseOutputSurface(); 1585 // Do nothing when impl frame is in deadine pending state. 1586 EXPECT_NO_ACTION(client); 1587 1588 client.Reset(); 1589 scheduler->NotifyBeginMainFrameStarted(); 1590 scheduler->NotifyReadyToCommit(); 1591 EXPECT_ACTION("ScheduledActionCommit", client, 0, 1); 1592 1593 client.Reset(); 1594 client.task_runner().RunPendingTasks(); // Run posted deadline. 1595 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 1596 } 1597 1598 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency( 1599 bool impl_side_painting) { 1600 FakeSchedulerClient client; 1601 SchedulerSettings scheduler_settings; 1602 scheduler_settings.impl_side_painting = impl_side_painting; 1603 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1604 scheduler->SetCanStart(); 1605 scheduler->SetVisible(true); 1606 scheduler->SetCanDraw(true); 1607 1608 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 1609 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1610 1611 // SetNeedsCommit should begin the frame. 1612 client.Reset(); 1613 scheduler->SetNeedsCommit(); 1614 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1615 1616 client.Reset(); 1617 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 1618 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1619 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1620 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1621 1622 client.Reset(); 1623 scheduler->DidLoseOutputSurface(); 1624 // Do nothing when impl frame is in deadine pending state. 1625 EXPECT_NO_ACTION(client); 1626 1627 client.Reset(); 1628 client.task_runner().RunPendingTasks(); // Run posted deadline. 1629 // OnBeginImplFrameDeadline didn't schedule any actions because main frame is 1630 // not yet completed. 1631 EXPECT_NO_ACTION(client); 1632 1633 // BeginImplFrame is not started. 1634 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 1635 EXPECT_NO_ACTION(client); 1636 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1637 1638 client.Reset(); 1639 scheduler->NotifyBeginMainFrameStarted(); 1640 scheduler->NotifyReadyToCommit(); 1641 if (impl_side_painting) { 1642 EXPECT_ACTION("ScheduledActionCommit", client, 0, 3); 1643 EXPECT_ACTION("ScheduledActionActivatePendingTree", client, 1, 3); 1644 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 2, 3); 1645 } else { 1646 EXPECT_ACTION("ScheduledActionCommit", client, 0, 2); 1647 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2); 1648 } 1649 } 1650 1651 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) { 1652 bool impl_side_painting = false; 1653 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting); 1654 } 1655 1656 TEST(SchedulerTest, 1657 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) { 1658 bool impl_side_painting = true; 1659 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting); 1660 } 1661 1662 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting) { 1663 FakeSchedulerClient client; 1664 SchedulerSettings scheduler_settings; 1665 scheduler_settings.impl_side_painting = impl_side_painting; 1666 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1667 scheduler->SetCanStart(); 1668 scheduler->SetVisible(true); 1669 scheduler->SetCanDraw(true); 1670 1671 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 1672 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1673 1674 // SetNeedsCommit should begin the frame. 1675 client.Reset(); 1676 scheduler->SetNeedsCommit(); 1677 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1678 1679 client.Reset(); 1680 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 1681 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1682 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1683 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1684 1685 client.Reset(); 1686 scheduler->NotifyBeginMainFrameStarted(); 1687 scheduler->NotifyReadyToCommit(); 1688 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 1689 1690 client.Reset(); 1691 scheduler->DidLoseOutputSurface(); 1692 if (impl_side_painting) { 1693 // Pending tree should be forced to activate. 1694 EXPECT_SINGLE_ACTION("ScheduledActionActivatePendingTree", client); 1695 } else { 1696 // Do nothing when impl frame is in deadine pending state. 1697 EXPECT_NO_ACTION(client); 1698 } 1699 1700 client.Reset(); 1701 client.task_runner().RunPendingTasks(); // Run posted deadline. 1702 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 1703 } 1704 1705 TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) { 1706 DidLoseOutputSurfaceAfterReadyToCommit(false); 1707 } 1708 1709 TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) { 1710 DidLoseOutputSurfaceAfterReadyToCommit(true); 1711 } 1712 1713 TEST(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsManageTiles) { 1714 FakeSchedulerClient client; 1715 SchedulerSettings scheduler_settings; 1716 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1717 scheduler->SetCanStart(); 1718 scheduler->SetVisible(true); 1719 scheduler->SetCanDraw(true); 1720 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1721 1722 client.Reset(); 1723 scheduler->SetNeedsManageTiles(); 1724 scheduler->SetNeedsRedraw(); 1725 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1726 EXPECT_TRUE(client.needs_begin_frame()); 1727 1728 client.Reset(); 1729 scheduler->BeginFrame(CreateBeginFrameArgsForTesting()); 1730 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1731 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 1732 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1733 1734 client.Reset(); 1735 scheduler->DidLoseOutputSurface(); 1736 EXPECT_NO_ACTION(client); 1737 1738 client.Reset(); 1739 client.task_runner().RunPendingTasks(); // Run posted deadline. 1740 EXPECT_ACTION("ScheduledActionManageTiles", client, 0, 2); 1741 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2); 1742 } 1743 1744 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) { 1745 FakeSchedulerClient client; 1746 SchedulerSettings scheduler_settings; 1747 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1748 scheduler->SetCanStart(); 1749 scheduler->SetVisible(true); 1750 scheduler->SetCanDraw(true); 1751 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1752 1753 // SetNeedsCommit should begin the frame on the next BeginImplFrame. 1754 client.Reset(); 1755 scheduler->SetNeedsCommit(); 1756 EXPECT_TRUE(client.needs_begin_frame()); 1757 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1758 1759 // Create a BeginFrame with a long deadline to avoid race conditions. 1760 // This is the first BeginFrame, which will be handled immediately. 1761 client.Reset(); 1762 BeginFrameArgs args = CreateBeginFrameArgsForTesting(); 1763 args.deadline += base::TimeDelta::FromHours(1); 1764 scheduler->BeginFrame(args); 1765 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1766 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1767 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1768 EXPECT_TRUE(client.needs_begin_frame()); 1769 1770 // Queue BeginFrames while we are still handling the previous BeginFrame. 1771 args.frame_time += base::TimeDelta::FromSeconds(1); 1772 scheduler->BeginFrame(args); 1773 args.frame_time += base::TimeDelta::FromSeconds(1); 1774 scheduler->BeginFrame(args); 1775 1776 // If we don't swap on the deadline, we wait for the next BeginImplFrame. 1777 client.Reset(); 1778 client.task_runner().RunPendingTasks(); // Run posted deadline. 1779 EXPECT_NO_ACTION(client); 1780 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1781 EXPECT_TRUE(client.needs_begin_frame()); 1782 1783 // NotifyReadyToCommit should trigger the commit. 1784 client.Reset(); 1785 scheduler->NotifyBeginMainFrameStarted(); 1786 scheduler->NotifyReadyToCommit(); 1787 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 1788 EXPECT_TRUE(client.needs_begin_frame()); 1789 1790 client.Reset(); 1791 EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty()); 1792 scheduler->DidLoseOutputSurface(); 1793 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 1794 EXPECT_TRUE(client.needs_begin_frame()); 1795 EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty()); 1796 1797 // Posted BeginRetroFrame is aborted. 1798 client.Reset(); 1799 client.task_runner().RunPendingTasks(); 1800 EXPECT_NO_ACTION(client); 1801 } 1802 1803 TEST(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) { 1804 FakeSchedulerClient client; 1805 SchedulerSettings scheduler_settings; 1806 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1807 scheduler->SetCanStart(); 1808 scheduler->SetVisible(true); 1809 scheduler->SetCanDraw(true); 1810 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1811 1812 // SetNeedsCommit should begin the frame on the next BeginImplFrame. 1813 client.Reset(); 1814 scheduler->SetNeedsCommit(); 1815 EXPECT_TRUE(client.needs_begin_frame()); 1816 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1817 1818 // Create a BeginFrame with a long deadline to avoid race conditions. 1819 // This is the first BeginFrame, which will be handled immediately. 1820 client.Reset(); 1821 BeginFrameArgs args = CreateBeginFrameArgsForTesting(); 1822 args.deadline += base::TimeDelta::FromHours(1); 1823 scheduler->BeginFrame(args); 1824 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1825 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1826 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1827 EXPECT_TRUE(client.needs_begin_frame()); 1828 1829 // Queue BeginFrames while we are still handling the previous BeginFrame. 1830 args.frame_time += base::TimeDelta::FromSeconds(1); 1831 scheduler->BeginFrame(args); 1832 args.frame_time += base::TimeDelta::FromSeconds(1); 1833 scheduler->BeginFrame(args); 1834 1835 // If we don't swap on the deadline, we wait for the next BeginImplFrame. 1836 client.Reset(); 1837 client.task_runner().RunPendingTasks(); // Run posted deadline. 1838 EXPECT_NO_ACTION(client); 1839 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1840 EXPECT_TRUE(client.needs_begin_frame()); 1841 1842 // NotifyReadyToCommit should trigger the commit. 1843 client.Reset(); 1844 scheduler->NotifyBeginMainFrameStarted(); 1845 scheduler->NotifyReadyToCommit(); 1846 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 1847 EXPECT_TRUE(client.needs_begin_frame()); 1848 1849 // BeginImplFrame should prepare the draw. 1850 client.Reset(); 1851 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. 1852 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1853 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); 1854 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1855 EXPECT_TRUE(client.needs_begin_frame()); 1856 1857 client.Reset(); 1858 EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty()); 1859 scheduler->DidLoseOutputSurface(); 1860 EXPECT_NO_ACTION(client); 1861 EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty()); 1862 1863 // BeginImplFrame deadline should abort drawing. 1864 client.Reset(); 1865 client.task_runner().RunPendingTasks(); // Run posted deadline. 1866 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 1867 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1868 EXPECT_TRUE(client.needs_begin_frame()); 1869 1870 // No more BeginRetroFrame because BeginRetroFrame queue is cleared. 1871 client.Reset(); 1872 client.task_runner().RunPendingTasks(); 1873 EXPECT_NO_ACTION(client); 1874 } 1875 1876 TEST(SchedulerTest, 1877 StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource) { 1878 FakeSchedulerClient client; 1879 SchedulerSettings scheduler_settings; 1880 scheduler_settings.begin_frame_scheduling_enabled = false; 1881 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); 1882 scheduler->SetCanStart(); 1883 scheduler->SetVisible(true); 1884 scheduler->SetCanDraw(true); 1885 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1886 1887 // SetNeedsCommit should begin the frame on the next BeginImplFrame. 1888 client.Reset(); 1889 EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive()); 1890 scheduler->SetNeedsCommit(); 1891 EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive()); 1892 1893 client.Reset(); 1894 client.task_runner().RunPendingTasks(); // Run posted Tick. 1895 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1896 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1897 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1898 EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive()); 1899 1900 // NotifyReadyToCommit should trigger the commit. 1901 client.Reset(); 1902 scheduler->NotifyBeginMainFrameStarted(); 1903 scheduler->NotifyReadyToCommit(); 1904 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); 1905 EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive()); 1906 1907 client.Reset(); 1908 scheduler->DidLoseOutputSurface(); 1909 EXPECT_EQ(0, client.num_actions_()); 1910 EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive()); 1911 1912 client.Reset(); 1913 client.task_runner().RunPendingTasks(); // Run posted deadline. 1914 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); 1915 EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive()); 1916 } 1917 1918 } // namespace 1919 } // namespace cc 1920