Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blob921b94af19f0d2e605434276663c7a8aab70d998
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 #include "cc/scheduler/scheduler.h"
6 #include <string>
7 #include <vector>
9 #include "base/logging.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/test/test_simple_task_runner.h"
14 #include "base/time/time.h"
15 #include "cc/test/scheduler_test_common.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
20 EXPECT_EQ(expected_num_actions, client.num_actions_()); \
21 ASSERT_LT(action_index, client.num_actions_()); \
22 do { \
23 EXPECT_STREQ(action, client.Action(action_index)); \
24 for (int i = expected_num_actions; i < client.num_actions_(); ++i) \
25 ADD_FAILURE() << "Unexpected action: " << client.Action(i) << \
26 " with state:\n" << client.StateForAction(action_index); \
27 } while (false)
29 #define EXPECT_SINGLE_ACTION(action, client) \
30 EXPECT_ACTION(action, client, 0, 1)
32 namespace cc {
33 namespace {
35 class FakeSchedulerClient;
37 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
38 FakeSchedulerClient* client);
40 class FakeSchedulerClient : public SchedulerClient {
41 public:
42 FakeSchedulerClient() : needs_begin_frame_(false), automatic_swap_ack_(true) {
43 Reset();
46 void Reset() {
47 actions_.clear();
48 states_.clear();
49 draw_will_happen_ = true;
50 swap_will_happen_if_draw_happens_ = true;
51 num_draws_ = 0;
52 log_anticipated_draw_time_change_ = false;
55 Scheduler* CreateScheduler(const SchedulerSettings& settings) {
56 task_runner_ = new base::TestSimpleTaskRunner;
57 scheduler_ = Scheduler::Create(this, settings, 0, task_runner_);
58 return scheduler_.get();
61 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
62 // for tests that do.
63 void set_log_anticipated_draw_time_change(bool log) {
64 log_anticipated_draw_time_change_ = log;
66 bool needs_begin_frame() { return needs_begin_frame_; }
67 int num_draws() const { return num_draws_; }
68 int num_actions_() const { return static_cast<int>(actions_.size()); }
69 const char* Action(int i) const { return actions_[i]; }
70 base::Value& StateForAction(int i) const { return *states_[i]; }
71 base::TimeTicks posted_begin_impl_frame_deadline() const {
72 return posted_begin_impl_frame_deadline_;
75 base::TestSimpleTaskRunner& task_runner() { return *task_runner_; }
77 int ActionIndex(const char* action) const {
78 for (size_t i = 0; i < actions_.size(); i++)
79 if (!strcmp(actions_[i], action))
80 return i;
81 return -1;
84 bool HasAction(const char* action) const {
85 return ActionIndex(action) >= 0;
88 void SetDrawWillHappen(bool draw_will_happen) {
89 draw_will_happen_ = draw_will_happen;
91 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
92 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
94 void SetAutomaticSwapAck(bool automatic_swap_ack) {
95 automatic_swap_ack_ = automatic_swap_ack;
98 // SchedulerClient implementation.
99 virtual void SetNeedsBeginFrame(bool enable) OVERRIDE {
100 actions_.push_back("SetNeedsBeginFrame");
101 states_.push_back(scheduler_->StateAsValue().release());
102 needs_begin_frame_ = enable;
104 virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
105 actions_.push_back("WillBeginImplFrame");
106 states_.push_back(scheduler_->StateAsValue().release());
108 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
109 actions_.push_back("ScheduledActionSendBeginMainFrame");
110 states_.push_back(scheduler_->StateAsValue().release());
112 virtual void ScheduledActionAnimate() OVERRIDE {
113 actions_.push_back("ScheduledActionAnimate");
114 states_.push_back(scheduler_->StateAsValue().release());
116 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
117 OVERRIDE {
118 actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
119 states_.push_back(scheduler_->StateAsValue().release());
120 num_draws_++;
121 bool did_readback = false;
122 DrawSwapReadbackResult::DrawResult result =
123 draw_will_happen_
124 ? DrawSwapReadbackResult::DRAW_SUCCESS
125 : DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
126 bool swap_will_happen =
127 draw_will_happen_ && swap_will_happen_if_draw_happens_;
128 if (swap_will_happen) {
129 scheduler_->DidSwapBuffers();
130 if (automatic_swap_ack_)
131 scheduler_->DidSwapBuffersComplete();
133 return DrawSwapReadbackResult(
134 result,
135 draw_will_happen_ && swap_will_happen_if_draw_happens_,
136 did_readback);
138 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
139 actions_.push_back("ScheduledActionDrawAndSwapForced");
140 states_.push_back(scheduler_->StateAsValue().release());
141 bool did_request_swap = swap_will_happen_if_draw_happens_;
142 bool did_readback = false;
143 return DrawSwapReadbackResult(
144 DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
146 virtual DrawSwapReadbackResult ScheduledActionDrawAndReadback() OVERRIDE {
147 actions_.push_back("ScheduledActionDrawAndReadback");
148 states_.push_back(scheduler_->StateAsValue().release());
149 bool did_request_swap = false;
150 bool did_readback = true;
151 return DrawSwapReadbackResult(
152 DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
154 virtual void ScheduledActionCommit() OVERRIDE {
155 actions_.push_back("ScheduledActionCommit");
156 states_.push_back(scheduler_->StateAsValue().release());
158 virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE {
159 actions_.push_back("ScheduledActionUpdateVisibleTiles");
160 states_.push_back(scheduler_->StateAsValue().release());
162 virtual void ScheduledActionActivatePendingTree() OVERRIDE {
163 actions_.push_back("ScheduledActionActivatePendingTree");
164 states_.push_back(scheduler_->StateAsValue().release());
166 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
167 actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
168 states_.push_back(scheduler_->StateAsValue().release());
170 virtual void ScheduledActionManageTiles() OVERRIDE {
171 actions_.push_back("ScheduledActionManageTiles");
172 states_.push_back(scheduler_->StateAsValue().release());
174 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {
175 if (log_anticipated_draw_time_change_)
176 actions_.push_back("DidAnticipatedDrawTimeChange");
178 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
179 return base::TimeDelta();
181 virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
182 return base::TimeDelta();
184 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
185 return base::TimeDelta();
188 virtual void DidBeginImplFrameDeadline() OVERRIDE {}
190 protected:
191 bool needs_begin_frame_;
192 bool draw_will_happen_;
193 bool swap_will_happen_if_draw_happens_;
194 bool automatic_swap_ack_;
195 int num_draws_;
196 bool log_anticipated_draw_time_change_;
197 base::TimeTicks posted_begin_impl_frame_deadline_;
198 std::vector<const char*> actions_;
199 ScopedVector<base::Value> states_;
200 scoped_ptr<Scheduler> scheduler_;
201 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
204 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
205 FakeSchedulerClient* client) {
206 bool client_initiates_begin_frame =
207 scheduler->settings().begin_frame_scheduling_enabled &&
208 scheduler->settings().throttle_frame_production;
210 scheduler->DidCreateAndInitializeOutputSurface();
211 scheduler->SetNeedsCommit();
212 scheduler->NotifyBeginMainFrameStarted();
213 scheduler->NotifyReadyToCommit();
214 // Go through the motions to draw the commit.
215 if (client_initiates_begin_frame)
216 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
217 else
218 client->task_runner().RunPendingTasks(); // Run posted BeginFrame.
220 // Run the posted deadline task.
221 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
222 client->task_runner().RunPendingTasks();
223 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
225 // We need another BeginImplFrame so Scheduler calls
226 // SetNeedsBeginFrame(false).
227 if (client_initiates_begin_frame)
228 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
229 else
230 client->task_runner().RunPendingTasks(); // Run posted BeginFrame.
232 // Run the posted deadline task.
233 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
234 client->task_runner().RunPendingTasks();
235 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
238 TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
239 FakeSchedulerClient client;
240 SchedulerSettings default_scheduler_settings;
241 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
242 scheduler->SetCanStart();
243 scheduler->SetVisible(true);
244 scheduler->SetCanDraw(true);
246 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
247 client.Reset();
248 scheduler->DidCreateAndInitializeOutputSurface();
249 EXPECT_EQ(0, client.num_actions_());
252 TEST(SchedulerTest, RequestCommit) {
253 FakeSchedulerClient client;
254 SchedulerSettings scheduler_settings;
255 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
256 scheduler->SetCanStart();
257 scheduler->SetVisible(true);
258 scheduler->SetCanDraw(true);
260 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
261 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
263 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
264 client.Reset();
265 scheduler->SetNeedsCommit();
266 EXPECT_TRUE(client.needs_begin_frame());
267 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
268 client.Reset();
270 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
271 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
272 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
273 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
274 EXPECT_TRUE(client.needs_begin_frame());
275 client.Reset();
277 // If we don't swap on the deadline, we wait for the next BeginFrame.
278 client.task_runner().RunPendingTasks(); // Run posted deadline.
279 EXPECT_EQ(0, client.num_actions_());
280 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
281 EXPECT_TRUE(client.needs_begin_frame());
282 client.Reset();
284 // NotifyReadyToCommit should trigger the commit.
285 scheduler->NotifyBeginMainFrameStarted();
286 scheduler->NotifyReadyToCommit();
287 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
288 EXPECT_TRUE(client.needs_begin_frame());
289 client.Reset();
291 // BeginImplFrame should prepare the draw.
292 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
293 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
294 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
295 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
296 EXPECT_TRUE(client.needs_begin_frame());
297 client.Reset();
299 // BeginImplFrame deadline should draw.
300 client.task_runner().RunPendingTasks(); // Run posted deadline.
301 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
302 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
303 EXPECT_TRUE(client.needs_begin_frame());
304 client.Reset();
306 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
307 // to avoid excessive toggles.
308 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
309 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
310 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
311 client.Reset();
313 client.task_runner().RunPendingTasks(); // Run posted deadline.
314 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
315 EXPECT_FALSE(client.needs_begin_frame());
316 client.Reset();
319 TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
320 FakeSchedulerClient client;
321 SchedulerSettings scheduler_settings;
322 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
323 scheduler->SetCanStart();
324 scheduler->SetVisible(true);
325 scheduler->SetCanDraw(true);
327 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
328 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
329 client.Reset();
331 // SetNeedsCommit should begin the frame.
332 scheduler->SetNeedsCommit();
333 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
335 client.Reset();
336 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
337 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
338 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
339 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
341 EXPECT_TRUE(client.needs_begin_frame());
342 client.Reset();
344 // Now SetNeedsCommit again. Calling here means we need a second commit.
345 scheduler->SetNeedsCommit();
346 EXPECT_EQ(client.num_actions_(), 0);
347 client.Reset();
349 // Finish the first commit.
350 scheduler->NotifyBeginMainFrameStarted();
351 scheduler->NotifyReadyToCommit();
352 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
353 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
354 client.Reset();
355 client.task_runner().RunPendingTasks(); // Run posted deadline.
356 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
357 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
358 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
360 // Because we just swapped, the Scheduler should also request the next
361 // BeginImplFrame from the OutputSurface.
362 EXPECT_TRUE(client.needs_begin_frame());
363 client.Reset();
364 // Since another commit is needed, the next BeginImplFrame should initiate
365 // the second commit.
366 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
367 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
368 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
369 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
370 client.Reset();
372 // Finishing the commit before the deadline should post a new deadline task
373 // to trigger the deadline early.
374 scheduler->NotifyBeginMainFrameStarted();
375 scheduler->NotifyReadyToCommit();
376 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
377 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
378 client.Reset();
379 client.task_runner().RunPendingTasks(); // Run posted deadline.
380 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
381 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
382 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
383 EXPECT_TRUE(client.needs_begin_frame());
384 client.Reset();
386 // On the next BeginImplFrame, verify we go back to a quiescent state and
387 // no longer request BeginImplFrames.
388 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
389 client.task_runner().RunPendingTasks(); // Run posted deadline.
390 EXPECT_FALSE(client.needs_begin_frame());
391 client.Reset();
394 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
395 public:
396 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
397 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
398 OVERRIDE {
399 // Only SetNeedsRedraw the first time this is called
400 if (!num_draws_)
401 scheduler_->SetNeedsRedraw();
402 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
405 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
406 NOTREACHED();
407 bool did_request_swap = true;
408 bool did_readback = false;
409 return DrawSwapReadbackResult(
410 DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
413 virtual void ScheduledActionCommit() OVERRIDE {}
414 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
415 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
418 // Tests for two different situations:
419 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
420 // a ScheduledActionDrawAndSwap
421 // 2. the scheduler drawing twice inside a single tick
422 TEST(SchedulerTest, RequestRedrawInsideDraw) {
423 SchedulerClientThatsetNeedsDrawInsideDraw client;
424 SchedulerSettings default_scheduler_settings;
425 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
426 scheduler->SetCanStart();
427 scheduler->SetVisible(true);
428 scheduler->SetCanDraw(true);
429 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
430 client.Reset();
432 scheduler->SetNeedsRedraw();
433 EXPECT_TRUE(scheduler->RedrawPending());
434 EXPECT_TRUE(client.needs_begin_frame());
435 EXPECT_EQ(0, client.num_draws());
437 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
438 client.task_runner().RunPendingTasks(); // Run posted deadline.
439 EXPECT_EQ(1, client.num_draws());
440 EXPECT_TRUE(scheduler->RedrawPending());
441 EXPECT_TRUE(client.needs_begin_frame());
443 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
444 client.task_runner().RunPendingTasks(); // Run posted deadline.
445 EXPECT_EQ(2, client.num_draws());
446 EXPECT_FALSE(scheduler->RedrawPending());
447 EXPECT_TRUE(client.needs_begin_frame());
449 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
450 // swap.
451 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
452 client.task_runner().RunPendingTasks(); // Run posted deadline.
453 EXPECT_EQ(2, client.num_draws());
454 EXPECT_FALSE(scheduler->RedrawPending());
455 EXPECT_FALSE(client.needs_begin_frame());
458 // Test that requesting redraw inside a failed draw doesn't lose the request.
459 TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
460 SchedulerClientThatsetNeedsDrawInsideDraw client;
461 SchedulerSettings default_scheduler_settings;
462 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
463 scheduler->SetCanStart();
464 scheduler->SetVisible(true);
465 scheduler->SetCanDraw(true);
466 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
467 client.Reset();
469 client.SetDrawWillHappen(false);
471 scheduler->SetNeedsRedraw();
472 EXPECT_TRUE(scheduler->RedrawPending());
473 EXPECT_TRUE(client.needs_begin_frame());
474 EXPECT_EQ(0, client.num_draws());
476 // Fail the draw.
477 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
478 client.task_runner().RunPendingTasks(); // Run posted deadline.
479 EXPECT_EQ(1, client.num_draws());
481 // We have a commit pending and the draw failed, and we didn't lose the redraw
482 // request.
483 EXPECT_TRUE(scheduler->CommitPending());
484 EXPECT_TRUE(scheduler->RedrawPending());
485 EXPECT_TRUE(client.needs_begin_frame());
487 // Fail the draw again.
488 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
489 client.task_runner().RunPendingTasks(); // Run posted deadline.
490 EXPECT_EQ(2, client.num_draws());
491 EXPECT_TRUE(scheduler->CommitPending());
492 EXPECT_TRUE(scheduler->RedrawPending());
493 EXPECT_TRUE(client.needs_begin_frame());
495 // Draw successfully.
496 client.SetDrawWillHappen(true);
497 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
498 client.task_runner().RunPendingTasks(); // Run posted deadline.
499 EXPECT_EQ(3, client.num_draws());
500 EXPECT_TRUE(scheduler->CommitPending());
501 EXPECT_FALSE(scheduler->RedrawPending());
502 EXPECT_TRUE(client.needs_begin_frame());
505 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
506 public:
507 SchedulerClientThatSetNeedsCommitInsideDraw()
508 : set_needs_commit_on_next_draw_(false) {}
510 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
511 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
512 OVERRIDE {
513 // Only SetNeedsCommit the first time this is called
514 if (set_needs_commit_on_next_draw_) {
515 scheduler_->SetNeedsCommit();
516 set_needs_commit_on_next_draw_ = false;
518 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
521 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
522 NOTREACHED();
523 bool did_request_swap = false;
524 bool did_readback = false;
525 return DrawSwapReadbackResult(
526 DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
529 virtual void ScheduledActionCommit() OVERRIDE {}
530 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
531 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
533 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
535 private:
536 bool set_needs_commit_on_next_draw_;
539 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
540 // happen inside a ScheduledActionDrawAndSwap
541 TEST(SchedulerTest, RequestCommitInsideDraw) {
542 SchedulerClientThatSetNeedsCommitInsideDraw client;
543 SchedulerSettings default_scheduler_settings;
544 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
545 scheduler->SetCanStart();
546 scheduler->SetVisible(true);
547 scheduler->SetCanDraw(true);
548 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
549 client.Reset();
551 EXPECT_FALSE(client.needs_begin_frame());
552 scheduler->SetNeedsRedraw();
553 EXPECT_TRUE(scheduler->RedrawPending());
554 EXPECT_EQ(0, client.num_draws());
555 EXPECT_TRUE(client.needs_begin_frame());
557 client.SetNeedsCommitOnNextDraw();
558 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
559 client.SetNeedsCommitOnNextDraw();
560 client.task_runner().RunPendingTasks(); // Run posted deadline.
561 EXPECT_EQ(1, client.num_draws());
562 EXPECT_TRUE(scheduler->CommitPending());
563 EXPECT_TRUE(client.needs_begin_frame());
564 scheduler->NotifyBeginMainFrameStarted();
565 scheduler->NotifyReadyToCommit();
567 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
568 client.task_runner().RunPendingTasks(); // Run posted deadline.
569 EXPECT_EQ(2, client.num_draws());
571 EXPECT_FALSE(scheduler->RedrawPending());
572 EXPECT_FALSE(scheduler->CommitPending());
573 EXPECT_TRUE(client.needs_begin_frame());
575 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
576 // swap.
577 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
578 client.task_runner().RunPendingTasks(); // Run posted deadline.
579 EXPECT_EQ(2, client.num_draws());
580 EXPECT_FALSE(scheduler->RedrawPending());
581 EXPECT_FALSE(scheduler->CommitPending());
582 EXPECT_FALSE(client.needs_begin_frame());
585 // Tests that when a draw fails then the pending commit should not be dropped.
586 TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
587 SchedulerClientThatsetNeedsDrawInsideDraw client;
588 SchedulerSettings default_scheduler_settings;
589 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
590 scheduler->SetCanStart();
591 scheduler->SetVisible(true);
592 scheduler->SetCanDraw(true);
593 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
594 client.Reset();
596 client.SetDrawWillHappen(false);
598 scheduler->SetNeedsRedraw();
599 EXPECT_TRUE(scheduler->RedrawPending());
600 EXPECT_TRUE(client.needs_begin_frame());
601 EXPECT_EQ(0, client.num_draws());
603 // Fail the draw.
604 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
605 client.task_runner().RunPendingTasks(); // Run posted deadline.
606 EXPECT_EQ(1, client.num_draws());
608 // We have a commit pending and the draw failed, and we didn't lose the commit
609 // request.
610 EXPECT_TRUE(scheduler->CommitPending());
611 EXPECT_TRUE(scheduler->RedrawPending());
612 EXPECT_TRUE(client.needs_begin_frame());
614 // Fail the draw again.
615 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
617 client.task_runner().RunPendingTasks(); // Run posted deadline.
618 EXPECT_EQ(2, client.num_draws());
619 EXPECT_TRUE(scheduler->CommitPending());
620 EXPECT_TRUE(scheduler->RedrawPending());
621 EXPECT_TRUE(client.needs_begin_frame());
623 // Draw successfully.
624 client.SetDrawWillHappen(true);
625 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
626 client.task_runner().RunPendingTasks(); // Run posted deadline.
627 EXPECT_EQ(3, client.num_draws());
628 EXPECT_TRUE(scheduler->CommitPending());
629 EXPECT_FALSE(scheduler->RedrawPending());
630 EXPECT_TRUE(client.needs_begin_frame());
633 TEST(SchedulerTest, NoSwapWhenDrawFails) {
634 SchedulerClientThatSetNeedsCommitInsideDraw client;
635 SchedulerSettings default_scheduler_settings;
636 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
637 scheduler->SetCanStart();
638 scheduler->SetVisible(true);
639 scheduler->SetCanDraw(true);
640 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
641 client.Reset();
643 scheduler->SetNeedsRedraw();
644 EXPECT_TRUE(scheduler->RedrawPending());
645 EXPECT_TRUE(client.needs_begin_frame());
646 EXPECT_EQ(0, client.num_draws());
648 // Draw successfully, this starts a new frame.
649 client.SetNeedsCommitOnNextDraw();
650 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
651 client.task_runner().RunPendingTasks(); // Run posted deadline.
652 EXPECT_EQ(1, client.num_draws());
654 scheduler->SetNeedsRedraw();
655 EXPECT_TRUE(scheduler->RedrawPending());
656 EXPECT_TRUE(client.needs_begin_frame());
658 // Fail to draw, this should not start a frame.
659 client.SetDrawWillHappen(false);
660 client.SetNeedsCommitOnNextDraw();
661 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
662 client.task_runner().RunPendingTasks(); // Run posted deadline.
663 EXPECT_EQ(2, client.num_draws());
666 TEST(SchedulerTest, NoSwapWhenSwapFailsDuringForcedCommit) {
667 FakeSchedulerClient client;
668 SchedulerSettings default_scheduler_settings;
669 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
671 // Tell the client that it will fail to swap.
672 client.SetDrawWillHappen(true);
673 client.SetSwapWillHappenIfDrawHappens(false);
675 // Get the compositor to do a ScheduledActionDrawAndReadback.
676 scheduler->SetCanDraw(true);
677 scheduler->SetNeedsRedraw();
678 scheduler->SetNeedsForcedCommitForReadback();
679 scheduler->NotifyBeginMainFrameStarted();
680 scheduler->NotifyReadyToCommit();
681 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
684 TEST(SchedulerTest, BackToBackReadbackAllowed) {
685 // Some clients call readbacks twice in a row before the replacement
686 // commit comes in. Make sure it is allowed.
687 FakeSchedulerClient client;
688 SchedulerSettings default_scheduler_settings;
689 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
691 // Get the compositor to do 2 ScheduledActionDrawAndReadbacks before
692 // the replacement commit comes in.
693 scheduler->SetCanDraw(true);
694 scheduler->SetNeedsRedraw();
695 scheduler->SetNeedsForcedCommitForReadback();
696 scheduler->NotifyBeginMainFrameStarted();
697 scheduler->NotifyReadyToCommit();
698 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
700 client.Reset();
701 scheduler->SetNeedsForcedCommitForReadback();
702 scheduler->NotifyBeginMainFrameStarted();
703 scheduler->NotifyReadyToCommit();
704 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
706 // The replacement commit comes in after 2 readbacks.
707 client.Reset();
708 scheduler->NotifyBeginMainFrameStarted();
709 scheduler->NotifyReadyToCommit();
713 class SchedulerClientNeedsManageTilesInDraw : public FakeSchedulerClient {
714 public:
715 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
716 OVERRIDE {
717 scheduler_->SetNeedsManageTiles();
718 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
722 // Test manage tiles is independant of draws.
723 TEST(SchedulerTest, ManageTiles) {
724 SchedulerClientNeedsManageTilesInDraw client;
725 SchedulerSettings default_scheduler_settings;
726 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
727 scheduler->SetCanStart();
728 scheduler->SetVisible(true);
729 scheduler->SetCanDraw(true);
730 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
732 // Request both draw and manage tiles. ManageTiles shouldn't
733 // be trigged until BeginImplFrame.
734 client.Reset();
735 scheduler->SetNeedsManageTiles();
736 scheduler->SetNeedsRedraw();
737 EXPECT_TRUE(scheduler->RedrawPending());
738 EXPECT_TRUE(scheduler->ManageTilesPending());
739 EXPECT_TRUE(client.needs_begin_frame());
740 EXPECT_EQ(0, client.num_draws());
741 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
742 EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
744 // We have no immediate actions to perform, so the BeginImplFrame should post
745 // the deadline task.
746 client.Reset();
747 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
748 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
749 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
750 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
752 // On the deadline, he actions should have occured in the right order.
753 client.Reset();
754 client.task_runner().RunPendingTasks(); // Run posted deadline.
755 EXPECT_EQ(1, client.num_draws());
756 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
757 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
758 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
759 client.ActionIndex("ScheduledActionManageTiles"));
760 EXPECT_FALSE(scheduler->RedrawPending());
761 EXPECT_FALSE(scheduler->ManageTilesPending());
762 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
764 // Request a draw. We don't need a ManageTiles yet.
765 client.Reset();
766 scheduler->SetNeedsRedraw();
767 EXPECT_TRUE(scheduler->RedrawPending());
768 EXPECT_FALSE(scheduler->ManageTilesPending());
769 EXPECT_TRUE(client.needs_begin_frame());
770 EXPECT_EQ(0, client.num_draws());
772 // We have no immediate actions to perform, so the BeginImplFrame should post
773 // the deadline task.
774 client.Reset();
775 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
776 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
777 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
778 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
780 // Draw. The draw will trigger SetNeedsManageTiles, and
781 // then the ManageTiles action will be triggered after the Draw.
782 // Afterwards, neither a draw nor ManageTiles are pending.
783 client.Reset();
784 client.task_runner().RunPendingTasks(); // Run posted deadline.
785 EXPECT_EQ(1, client.num_draws());
786 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
787 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
788 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
789 client.ActionIndex("ScheduledActionManageTiles"));
790 EXPECT_FALSE(scheduler->RedrawPending());
791 EXPECT_FALSE(scheduler->ManageTilesPending());
792 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
794 // We need a BeginImplFrame where we don't swap to go idle.
795 client.Reset();
796 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
797 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
798 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
799 client.Reset();
800 client.task_runner().RunPendingTasks(); // Run posted deadline.
801 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
802 EXPECT_FALSE(client.needs_begin_frame());
803 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
804 EXPECT_EQ(0, client.num_draws());
806 // Now trigger a ManageTiles outside of a draw. We will then need
807 // a begin-frame for the ManageTiles, but we don't need a draw.
808 client.Reset();
809 EXPECT_FALSE(client.needs_begin_frame());
810 scheduler->SetNeedsManageTiles();
811 EXPECT_TRUE(client.needs_begin_frame());
812 EXPECT_TRUE(scheduler->ManageTilesPending());
813 EXPECT_FALSE(scheduler->RedrawPending());
815 // BeginImplFrame. There will be no draw, only ManageTiles.
816 client.Reset();
817 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
818 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
819 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
820 client.Reset();
821 client.task_runner().RunPendingTasks(); // Run posted deadline.
822 EXPECT_EQ(0, client.num_draws());
823 EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
824 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
825 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
828 // Test that ManageTiles only happens once per frame. If an external caller
829 // initiates it, then the state machine should not ManageTiles on that frame.
830 TEST(SchedulerTest, ManageTilesOncePerFrame) {
831 FakeSchedulerClient client;
832 SchedulerSettings default_scheduler_settings;
833 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
834 scheduler->SetCanStart();
835 scheduler->SetVisible(true);
836 scheduler->SetCanDraw(true);
837 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
839 // If DidManageTiles during a frame, then ManageTiles should not occur again.
840 scheduler->SetNeedsManageTiles();
841 scheduler->SetNeedsRedraw();
842 client.Reset();
843 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
844 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
845 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
846 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
848 EXPECT_TRUE(scheduler->ManageTilesPending());
849 scheduler->DidManageTiles(); // An explicit ManageTiles.
850 EXPECT_FALSE(scheduler->ManageTilesPending());
852 client.Reset();
853 client.task_runner().RunPendingTasks(); // Run posted deadline.
854 EXPECT_EQ(1, client.num_draws());
855 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
856 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
857 EXPECT_FALSE(scheduler->RedrawPending());
858 EXPECT_FALSE(scheduler->ManageTilesPending());
859 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
861 // Next frame without DidManageTiles should ManageTiles with draw.
862 scheduler->SetNeedsManageTiles();
863 scheduler->SetNeedsRedraw();
864 client.Reset();
865 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
866 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
867 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
868 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
870 client.Reset();
871 client.task_runner().RunPendingTasks(); // Run posted deadline.
872 EXPECT_EQ(1, client.num_draws());
873 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
874 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
875 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
876 client.ActionIndex("ScheduledActionManageTiles"));
877 EXPECT_FALSE(scheduler->RedrawPending());
878 EXPECT_FALSE(scheduler->ManageTilesPending());
879 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
880 scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
882 // If we get another DidManageTiles within the same frame, we should
883 // not ManageTiles on the next frame.
884 scheduler->DidManageTiles(); // An explicit ManageTiles.
885 scheduler->SetNeedsManageTiles();
886 scheduler->SetNeedsRedraw();
887 client.Reset();
888 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
889 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
890 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
891 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
893 EXPECT_TRUE(scheduler->ManageTilesPending());
895 client.Reset();
896 client.task_runner().RunPendingTasks(); // Run posted deadline.
897 EXPECT_EQ(1, client.num_draws());
898 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
899 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
900 EXPECT_FALSE(scheduler->RedrawPending());
901 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
903 // If we get another DidManageTiles, we should not ManageTiles on the next
904 // frame. This verifies we don't alternate calling ManageTiles once and twice.
905 EXPECT_TRUE(scheduler->ManageTilesPending());
906 scheduler->DidManageTiles(); // An explicit ManageTiles.
907 EXPECT_FALSE(scheduler->ManageTilesPending());
908 scheduler->SetNeedsManageTiles();
909 scheduler->SetNeedsRedraw();
910 client.Reset();
911 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
912 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
913 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
914 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
916 EXPECT_TRUE(scheduler->ManageTilesPending());
918 client.Reset();
919 client.task_runner().RunPendingTasks(); // Run posted deadline.
920 EXPECT_EQ(1, client.num_draws());
921 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
922 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
923 EXPECT_FALSE(scheduler->RedrawPending());
924 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
926 // Next frame without DidManageTiles should ManageTiles with draw.
927 scheduler->SetNeedsManageTiles();
928 scheduler->SetNeedsRedraw();
929 client.Reset();
930 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
931 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
932 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
933 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
935 client.Reset();
936 client.task_runner().RunPendingTasks(); // Run posted deadline.
937 EXPECT_EQ(1, client.num_draws());
938 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
939 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
940 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
941 client.ActionIndex("ScheduledActionManageTiles"));
942 EXPECT_FALSE(scheduler->RedrawPending());
943 EXPECT_FALSE(scheduler->ManageTilesPending());
944 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
945 scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
948 TEST(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
949 SchedulerClientNeedsManageTilesInDraw client;
950 SchedulerSettings default_scheduler_settings;
951 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
952 scheduler->SetCanStart();
953 scheduler->SetVisible(true);
954 scheduler->SetCanDraw(true);
955 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
957 client.Reset();
958 scheduler->SetNeedsRedraw();
959 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
961 // The deadline should be zero since there is no work other than drawing
962 // pending.
963 EXPECT_EQ(base::TimeTicks(), client.posted_begin_impl_frame_deadline());
966 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
967 public:
968 SchedulerClientWithFixedEstimates(
969 base::TimeDelta draw_duration,
970 base::TimeDelta begin_main_frame_to_commit_duration,
971 base::TimeDelta commit_to_activate_duration)
972 : draw_duration_(draw_duration),
973 begin_main_frame_to_commit_duration_(
974 begin_main_frame_to_commit_duration),
975 commit_to_activate_duration_(commit_to_activate_duration) {}
977 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
978 return draw_duration_;
980 virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
981 return begin_main_frame_to_commit_duration_;
983 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
984 return commit_to_activate_duration_;
987 private:
988 base::TimeDelta draw_duration_;
989 base::TimeDelta begin_main_frame_to_commit_duration_;
990 base::TimeDelta commit_to_activate_duration_;
993 void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms,
994 int64 commit_to_activate_estimate_in_ms,
995 bool smoothness_takes_priority,
996 bool should_send_begin_main_frame) {
997 // Set up client with specified estimates (draw duration is set to 1).
998 SchedulerClientWithFixedEstimates client(
999 base::TimeDelta::FromMilliseconds(1),
1000 base::TimeDelta::FromMilliseconds(
1001 begin_main_frame_to_commit_estimate_in_ms),
1002 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
1003 SchedulerSettings default_scheduler_settings;
1004 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
1005 scheduler->SetCanStart();
1006 scheduler->SetVisible(true);
1007 scheduler->SetCanDraw(true);
1008 scheduler->SetSmoothnessTakesPriority(smoothness_takes_priority);
1009 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1011 // Impl thread hits deadline before commit finishes.
1012 client.Reset();
1013 scheduler->SetNeedsCommit();
1014 EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
1015 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
1016 EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
1017 client.task_runner().RunPendingTasks(); // Run posted deadline.
1018 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1019 scheduler->NotifyBeginMainFrameStarted();
1020 scheduler->NotifyReadyToCommit();
1021 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1022 EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
1024 client.Reset();
1025 scheduler->SetNeedsCommit();
1026 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1027 scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
1028 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1029 client.task_runner().RunPendingTasks(); // Run posted deadline.
1030 EXPECT_EQ(scheduler->MainThreadIsInHighLatencyMode(),
1031 should_send_begin_main_frame);
1032 EXPECT_EQ(client.HasAction("ScheduledActionSendBeginMainFrame"),
1033 should_send_begin_main_frame);
1036 TEST(SchedulerTest,
1037 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
1038 // Set up client so that estimates indicate that we can commit and activate
1039 // before the deadline (~8ms by default).
1040 MainFrameInHighLatencyMode(1, 1, false, false);
1043 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
1044 // Set up client so that estimates indicate that the commit cannot finish
1045 // before the deadline (~8ms by default).
1046 MainFrameInHighLatencyMode(10, 1, false, true);
1049 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
1050 // Set up client so that estimates indicate that the activate cannot finish
1051 // before the deadline (~8ms by default).
1052 MainFrameInHighLatencyMode(1, 10, false, true);
1055 TEST(SchedulerTest, NotSkipMainFrameInPreferSmoothnessMode) {
1056 // Set up client so that estimates indicate that we can commit and activate
1057 // before the deadline (~8ms by default), but also enable smoothness takes
1058 // priority mode.
1059 MainFrameInHighLatencyMode(1, 1, true, true);
1062 TEST(SchedulerTest, PollForCommitCompletion) {
1063 // Since we are simulating a long commit, set up a client with draw duration
1064 // estimates that prevent skipping main frames to get to low latency mode.
1065 SchedulerClientWithFixedEstimates client(
1066 base::TimeDelta::FromMilliseconds(1),
1067 base::TimeDelta::FromMilliseconds(32),
1068 base::TimeDelta::FromMilliseconds(32));
1069 client.set_log_anticipated_draw_time_change(true);
1070 SchedulerSettings default_scheduler_settings;
1071 Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
1073 scheduler->SetCanDraw(true);
1074 scheduler->SetCanStart();
1075 scheduler->SetVisible(true);
1076 scheduler->DidCreateAndInitializeOutputSurface();
1078 scheduler->SetNeedsCommit();
1079 EXPECT_TRUE(scheduler->CommitPending());
1080 scheduler->NotifyBeginMainFrameStarted();
1081 scheduler->NotifyReadyToCommit();
1082 scheduler->SetNeedsRedraw();
1084 BeginFrameArgs frame_args = BeginFrameArgs::CreateForTesting();
1085 frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
1086 scheduler->BeginFrame(frame_args);
1088 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1089 client.task_runner().RunPendingTasks(); // Run posted deadline.
1090 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1092 scheduler->DidSwapBuffers();
1093 scheduler->DidSwapBuffersComplete();
1095 // At this point, we've drawn a frame. Start another commit, but hold off on
1096 // the NotifyReadyToCommit for now.
1097 EXPECT_FALSE(scheduler->CommitPending());
1098 scheduler->SetNeedsCommit();
1099 scheduler->BeginFrame(frame_args);
1100 EXPECT_TRUE(scheduler->CommitPending());
1102 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1103 // blocking on the renderer.
1104 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1105 client.task_runner().RunPendingTasks(); // Run posted deadline.
1106 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1107 scheduler->DidSwapBuffers();
1109 // Spin the event loop a few times and make sure we get more
1110 // DidAnticipateDrawTimeChange calls every time.
1111 int actions_so_far = client.num_actions_();
1113 // Does three iterations to make sure that the timer is properly repeating.
1114 for (int i = 0; i < 3; ++i) {
1115 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1116 client.task_runner().NextPendingTaskDelay().InMicroseconds())
1117 << *scheduler->StateAsValue();
1118 client.task_runner().RunPendingTasks();
1119 EXPECT_GT(client.num_actions_(), actions_so_far);
1120 EXPECT_STREQ(client.Action(client.num_actions_() - 1),
1121 "DidAnticipatedDrawTimeChange");
1122 actions_so_far = client.num_actions_();
1125 // Do the same thing after BeginMainFrame starts but still before activation.
1126 scheduler->NotifyBeginMainFrameStarted();
1127 for (int i = 0; i < 3; ++i) {
1128 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1129 client.task_runner().NextPendingTaskDelay().InMicroseconds())
1130 << *scheduler->StateAsValue();
1131 client.task_runner().RunPendingTasks();
1132 EXPECT_GT(client.num_actions_(), actions_so_far);
1133 EXPECT_STREQ(client.Action(client.num_actions_() - 1),
1134 "DidAnticipatedDrawTimeChange");
1135 actions_so_far = client.num_actions_();
1139 TEST(SchedulerTest, BeginRetroFrame) {
1140 FakeSchedulerClient client;
1141 SchedulerSettings scheduler_settings;
1142 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
1143 scheduler->SetCanStart();
1144 scheduler->SetVisible(true);
1145 scheduler->SetCanDraw(true);
1146 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1148 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1149 client.Reset();
1150 scheduler->SetNeedsCommit();
1151 EXPECT_TRUE(client.needs_begin_frame());
1152 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1153 client.Reset();
1155 // Create a BeginFrame with a long deadline to avoid race conditions.
1156 // This is the first BeginFrame, which will be handled immediately.
1157 BeginFrameArgs args = BeginFrameArgs::CreateForTesting();
1158 args.deadline += base::TimeDelta::FromHours(1);
1159 scheduler->BeginFrame(args);
1160 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1161 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1162 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1163 EXPECT_TRUE(client.needs_begin_frame());
1164 client.Reset();
1166 // Queue BeginFrames while we are still handling the previous BeginFrame.
1167 args.frame_time += base::TimeDelta::FromSeconds(1);
1168 scheduler->BeginFrame(args);
1169 args.frame_time += base::TimeDelta::FromSeconds(1);
1170 scheduler->BeginFrame(args);
1172 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1173 client.task_runner().RunPendingTasks(); // Run posted deadline.
1174 EXPECT_EQ(0, client.num_actions_());
1175 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1176 EXPECT_TRUE(client.needs_begin_frame());
1177 client.Reset();
1179 // NotifyReadyToCommit should trigger the commit.
1180 scheduler->NotifyBeginMainFrameStarted();
1181 scheduler->NotifyReadyToCommit();
1182 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1183 EXPECT_TRUE(client.needs_begin_frame());
1184 client.Reset();
1186 // BeginImplFrame should prepare the draw.
1187 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1188 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1189 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1190 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1191 EXPECT_TRUE(client.needs_begin_frame());
1192 client.Reset();
1194 // BeginImplFrame deadline should draw.
1195 client.task_runner().RunPendingTasks(); // Run posted deadline.
1196 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
1197 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1198 EXPECT_TRUE(client.needs_begin_frame());
1199 client.Reset();
1201 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1202 // to avoid excessive toggles.
1203 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1204 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1205 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1206 client.Reset();
1208 client.task_runner().RunPendingTasks(); // Run posted deadline.
1209 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1210 EXPECT_FALSE(client.needs_begin_frame());
1211 client.Reset();
1214 TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) {
1215 FakeSchedulerClient client;
1216 SchedulerSettings scheduler_settings;
1217 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
1218 scheduler->SetCanStart();
1219 scheduler->SetVisible(true);
1220 scheduler->SetCanDraw(true);
1221 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1223 // To test swap ack throttling, this test disables automatic swap acks.
1224 scheduler->SetMaxSwapsPending(1);
1225 client.SetAutomaticSwapAck(false);
1227 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1228 client.Reset();
1229 scheduler->SetNeedsCommit();
1230 EXPECT_TRUE(client.needs_begin_frame());
1231 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1232 client.Reset();
1234 // Create a BeginFrame with a long deadline to avoid race conditions.
1235 // This is the first BeginFrame, which will be handled immediately.
1236 BeginFrameArgs args = BeginFrameArgs::CreateForTesting();
1237 args.deadline += base::TimeDelta::FromHours(1);
1238 scheduler->BeginFrame(args);
1239 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1240 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1241 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1242 EXPECT_TRUE(client.needs_begin_frame());
1243 client.Reset();
1245 // Queue BeginFrame while we are still handling the previous BeginFrame.
1246 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1247 args.frame_time += base::TimeDelta::FromSeconds(1);
1248 scheduler->BeginFrame(args);
1249 EXPECT_EQ(0, client.num_actions_());
1250 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1251 client.Reset();
1253 // NotifyReadyToCommit should trigger the pending commit and draw.
1254 scheduler->NotifyBeginMainFrameStarted();
1255 scheduler->NotifyReadyToCommit();
1256 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1257 EXPECT_TRUE(client.needs_begin_frame());
1258 client.Reset();
1260 // Swapping will put us into a swap throttled state.
1261 client.task_runner().RunPendingTasks(); // Run posted deadline.
1262 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1263 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1264 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1265 EXPECT_TRUE(client.needs_begin_frame());
1266 client.Reset();
1268 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1269 // but not a BeginMainFrame or draw.
1270 scheduler->SetNeedsCommit();
1271 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1272 EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
1273 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1274 EXPECT_TRUE(client.needs_begin_frame());
1275 client.Reset();
1277 // Queue BeginFrame while we are still handling the previous BeginFrame.
1278 args.frame_time += base::TimeDelta::FromSeconds(1);
1279 scheduler->BeginFrame(args);
1280 EXPECT_EQ(0, client.num_actions_());
1281 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1282 EXPECT_TRUE(client.needs_begin_frame());
1283 client.Reset();
1285 // Take us out of a swap throttled state.
1286 scheduler->DidSwapBuffersComplete();
1287 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
1288 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1289 EXPECT_TRUE(client.needs_begin_frame());
1290 client.Reset();
1292 // BeginImplFrame deadline should draw.
1293 scheduler->SetNeedsRedraw();
1294 client.task_runner().RunPendingTasks(); // Run posted deadline.
1295 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1296 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1297 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1298 EXPECT_TRUE(client.needs_begin_frame());
1299 client.Reset();
1302 void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled,
1303 bool throttle_frame_production) {
1304 FakeSchedulerClient client;
1305 SchedulerSettings scheduler_settings;
1306 scheduler_settings.begin_frame_scheduling_enabled =
1307 begin_frame_scheduling_enabled;
1308 scheduler_settings.throttle_frame_production = throttle_frame_production;
1309 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
1310 scheduler->SetCanStart();
1311 scheduler->SetVisible(true);
1312 scheduler->SetCanDraw(true);
1313 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1315 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1316 // without calling SetNeedsBeginFrame.
1317 client.Reset();
1318 scheduler->SetNeedsCommit();
1319 EXPECT_FALSE(client.needs_begin_frame());
1320 EXPECT_EQ(0, client.num_actions_());
1321 client.Reset();
1323 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1324 // own BeginFrame tasks.
1325 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1326 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1327 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1328 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1329 EXPECT_FALSE(client.needs_begin_frame());
1330 client.Reset();
1332 // If we don't swap on the deadline, we wait for the next BeginFrame.
1333 client.task_runner().RunPendingTasks(); // Run posted deadline.
1334 EXPECT_EQ(0, client.num_actions_());
1335 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1336 EXPECT_FALSE(client.needs_begin_frame());
1337 client.Reset();
1339 // NotifyReadyToCommit should trigger the commit.
1340 scheduler->NotifyBeginMainFrameStarted();
1341 scheduler->NotifyReadyToCommit();
1342 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1343 EXPECT_FALSE(client.needs_begin_frame());
1344 client.Reset();
1346 // BeginImplFrame should prepare the draw.
1347 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1348 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1349 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1350 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1351 EXPECT_FALSE(client.needs_begin_frame());
1352 client.Reset();
1354 // BeginImplFrame deadline should draw.
1355 client.task_runner().RunPendingTasks(); // Run posted deadline.
1356 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
1357 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1358 EXPECT_FALSE(client.needs_begin_frame());
1359 client.Reset();
1361 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1362 // to avoid excessive toggles.
1363 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1364 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1365 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1366 client.Reset();
1368 // Make sure SetNeedsBeginFrame isn't called on the client
1369 // when the BeginFrame is no longer needed.
1370 client.task_runner().RunPendingTasks(); // Run posted deadline.
1371 EXPECT_EQ(0, client.num_actions_());
1372 EXPECT_FALSE(client.needs_begin_frame());
1373 client.Reset();
1376 TEST(SchedulerTest, SyntheticBeginFrames) {
1377 bool begin_frame_scheduling_enabled = false;
1378 bool throttle_frame_production = true;
1379 BeginFramesNotFromClient(begin_frame_scheduling_enabled,
1380 throttle_frame_production);
1383 TEST(SchedulerTest, VSyncThrottlingDisabled) {
1384 bool begin_frame_scheduling_enabled = true;
1385 bool throttle_frame_production = false;
1386 BeginFramesNotFromClient(begin_frame_scheduling_enabled,
1387 throttle_frame_production);
1390 TEST(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
1391 bool begin_frame_scheduling_enabled = false;
1392 bool throttle_frame_production = false;
1393 BeginFramesNotFromClient(begin_frame_scheduling_enabled,
1394 throttle_frame_production);
1397 void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled,
1398 bool throttle_frame_production) {
1399 FakeSchedulerClient client;
1400 SchedulerSettings scheduler_settings;
1401 scheduler_settings.begin_frame_scheduling_enabled =
1402 begin_frame_scheduling_enabled;
1403 scheduler_settings.throttle_frame_production = throttle_frame_production;
1404 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
1405 scheduler->SetCanStart();
1406 scheduler->SetVisible(true);
1407 scheduler->SetCanDraw(true);
1408 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1410 // To test swap ack throttling, this test disables automatic swap acks.
1411 scheduler->SetMaxSwapsPending(1);
1412 client.SetAutomaticSwapAck(false);
1414 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1415 client.Reset();
1416 scheduler->SetNeedsCommit();
1417 EXPECT_FALSE(client.needs_begin_frame());
1418 EXPECT_EQ(0, client.num_actions_());
1419 client.Reset();
1421 // Trigger the first BeginImplFrame and BeginMainFrame
1422 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1423 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1424 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1425 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1426 EXPECT_FALSE(client.needs_begin_frame());
1427 client.Reset();
1429 // NotifyReadyToCommit should trigger the pending commit and draw.
1430 scheduler->NotifyBeginMainFrameStarted();
1431 scheduler->NotifyReadyToCommit();
1432 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1433 EXPECT_FALSE(client.needs_begin_frame());
1434 client.Reset();
1436 // Swapping will put us into a swap throttled state.
1437 client.task_runner().RunPendingTasks(); // Run posted deadline.
1438 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1439 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1440 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1441 EXPECT_FALSE(client.needs_begin_frame());
1442 client.Reset();
1444 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1445 // but not a BeginMainFrame or draw.
1446 scheduler->SetNeedsCommit();
1447 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1448 EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
1449 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1450 EXPECT_FALSE(client.needs_begin_frame());
1451 client.Reset();
1453 // Take us out of a swap throttled state.
1454 scheduler->DidSwapBuffersComplete();
1455 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
1456 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1457 EXPECT_FALSE(client.needs_begin_frame());
1458 client.Reset();
1460 // BeginImplFrame deadline should draw.
1461 scheduler->SetNeedsRedraw();
1462 client.task_runner().RunPendingTasks(); // Run posted deadline.
1463 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1464 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1465 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1466 EXPECT_FALSE(client.needs_begin_frame());
1467 client.Reset();
1470 TEST(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
1471 bool begin_frame_scheduling_enabled = false;
1472 bool throttle_frame_production = true;
1473 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
1474 throttle_frame_production);
1477 TEST(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
1478 bool begin_frame_scheduling_enabled = true;
1479 bool throttle_frame_production = false;
1480 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
1481 throttle_frame_production);
1484 TEST(SchedulerTest,
1485 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
1486 bool begin_frame_scheduling_enabled = false;
1487 bool throttle_frame_production = false;
1488 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
1489 throttle_frame_production);
1492 } // namespace
1493 } // namespace cc