OLD | NEW |
| (Empty) |
1 // Copyright 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/scheduler/scheduler.h" | |
6 | |
7 #include <string> | |
8 #include <vector> | |
9 | |
10 #include "base/logging.h" | |
11 #include "base/memory/scoped_vector.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/run_loop.h" | |
14 #include "base/time/time.h" | |
15 #include "base/trace_event/trace_event.h" | |
16 #include "cc/test/begin_frame_args_test.h" | |
17 #include "cc/test/ordered_simple_task_runner.h" | |
18 #include "cc/test/scheduler_test_common.h" | |
19 #include "testing/gmock/include/gmock/gmock.h" | |
20 #include "testing/gtest/include/gtest/gtest.h" | |
21 | |
22 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \ | |
23 do { \ | |
24 EXPECT_EQ(expected_num_actions, client->num_actions_()); \ | |
25 if (action_index >= 0) { \ | |
26 ASSERT_LT(action_index, client->num_actions_()) << scheduler_.get(); \ | |
27 EXPECT_STREQ(action, client->Action(action_index)); \ | |
28 } \ | |
29 for (int i = expected_num_actions; i < client->num_actions_(); ++i) \ | |
30 ADD_FAILURE() << "Unexpected action: " << client->Action(i) \ | |
31 << " with state:\n" << client->StateForAction(i); \ | |
32 } while (false) | |
33 | |
34 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0) | |
35 | |
36 #define EXPECT_SINGLE_ACTION(action, client) \ | |
37 EXPECT_ACTION(action, client, 0, 1) | |
38 | |
39 #define EXPECT_SCOPED(statements) \ | |
40 { \ | |
41 SCOPED_TRACE(""); \ | |
42 statements; \ | |
43 } | |
44 | |
45 namespace cc { | |
46 namespace { | |
47 | |
48 class FakeSchedulerClient : public SchedulerClient { | |
49 public: | |
50 FakeSchedulerClient() | |
51 : automatic_swap_ack_(true), | |
52 begin_frame_is_sent_to_children_(false), | |
53 scheduler_(nullptr) { | |
54 Reset(); | |
55 } | |
56 | |
57 void Reset() { | |
58 actions_.clear(); | |
59 states_.clear(); | |
60 draw_will_happen_ = true; | |
61 swap_will_happen_if_draw_happens_ = true; | |
62 num_draws_ = 0; | |
63 log_anticipated_draw_time_change_ = false; | |
64 begin_frame_is_sent_to_children_ = false; | |
65 } | |
66 | |
67 void set_scheduler(TestScheduler* scheduler) { scheduler_ = scheduler; } | |
68 | |
69 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it | |
70 // for tests that do. | |
71 void set_log_anticipated_draw_time_change(bool log) { | |
72 log_anticipated_draw_time_change_ = log; | |
73 } | |
74 bool needs_begin_frames() { | |
75 return scheduler_->frame_source().NeedsBeginFrames(); | |
76 } | |
77 int num_draws() const { return num_draws_; } | |
78 int num_actions_() const { return static_cast<int>(actions_.size()); } | |
79 const char* Action(int i) const { return actions_[i]; } | |
80 std::string StateForAction(int i) const { return states_[i]->ToString(); } | |
81 base::TimeTicks posted_begin_impl_frame_deadline() const { | |
82 return posted_begin_impl_frame_deadline_; | |
83 } | |
84 | |
85 int ActionIndex(const char* action) const { | |
86 for (size_t i = 0; i < actions_.size(); i++) | |
87 if (!strcmp(actions_[i], action)) | |
88 return i; | |
89 return -1; | |
90 } | |
91 | |
92 bool HasAction(const char* action) const { | |
93 return ActionIndex(action) >= 0; | |
94 } | |
95 | |
96 void SetDrawWillHappen(bool draw_will_happen) { | |
97 draw_will_happen_ = draw_will_happen; | |
98 } | |
99 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) { | |
100 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens; | |
101 } | |
102 void SetAutomaticSwapAck(bool automatic_swap_ack) { | |
103 automatic_swap_ack_ = automatic_swap_ack; | |
104 } | |
105 // SchedulerClient implementation. | |
106 void WillBeginImplFrame(const BeginFrameArgs& args) override { | |
107 PushAction("WillBeginImplFrame"); | |
108 } | |
109 void ScheduledActionSendBeginMainFrame() override { | |
110 PushAction("ScheduledActionSendBeginMainFrame"); | |
111 } | |
112 void ScheduledActionAnimate() override { | |
113 PushAction("ScheduledActionAnimate"); | |
114 } | |
115 DrawResult ScheduledActionDrawAndSwapIfPossible() override { | |
116 PushAction("ScheduledActionDrawAndSwapIfPossible"); | |
117 num_draws_++; | |
118 DrawResult result = | |
119 draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS; | |
120 bool swap_will_happen = | |
121 draw_will_happen_ && swap_will_happen_if_draw_happens_; | |
122 if (swap_will_happen) { | |
123 scheduler_->DidSwapBuffers(); | |
124 | |
125 if (automatic_swap_ack_) | |
126 scheduler_->DidSwapBuffersComplete(); | |
127 } | |
128 return result; | |
129 } | |
130 DrawResult ScheduledActionDrawAndSwapForced() override { | |
131 PushAction("ScheduledActionDrawAndSwapForced"); | |
132 return DRAW_SUCCESS; | |
133 } | |
134 void ScheduledActionCommit() override { PushAction("ScheduledActionCommit"); } | |
135 void ScheduledActionActivateSyncTree() override { | |
136 PushAction("ScheduledActionActivateSyncTree"); | |
137 } | |
138 void ScheduledActionBeginOutputSurfaceCreation() override { | |
139 PushAction("ScheduledActionBeginOutputSurfaceCreation"); | |
140 } | |
141 void ScheduledActionPrepareTiles() override { | |
142 PushAction("ScheduledActionPrepareTiles"); | |
143 } | |
144 void DidAnticipatedDrawTimeChange(base::TimeTicks) override { | |
145 if (log_anticipated_draw_time_change_) | |
146 PushAction("DidAnticipatedDrawTimeChange"); | |
147 } | |
148 base::TimeDelta DrawDurationEstimate() override { return base::TimeDelta(); } | |
149 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override { | |
150 return base::TimeDelta(); | |
151 } | |
152 base::TimeDelta CommitToActivateDurationEstimate() override { | |
153 return base::TimeDelta(); | |
154 } | |
155 | |
156 void DidBeginImplFrameDeadline() override {} | |
157 | |
158 void SendBeginFramesToChildren(const BeginFrameArgs& args) override { | |
159 begin_frame_is_sent_to_children_ = true; | |
160 } | |
161 | |
162 void SendBeginMainFrameNotExpectedSoon() override { | |
163 PushAction("SendBeginMainFrameNotExpectedSoon"); | |
164 } | |
165 | |
166 base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) { | |
167 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback, | |
168 base::Unretained(this), | |
169 state); | |
170 } | |
171 | |
172 bool begin_frame_is_sent_to_children() const { | |
173 return begin_frame_is_sent_to_children_; | |
174 } | |
175 | |
176 void PushAction(const char* description) { | |
177 actions_.push_back(description); | |
178 states_.push_back(scheduler_->AsValue()); | |
179 } | |
180 | |
181 protected: | |
182 bool ImplFrameDeadlinePendingCallback(bool state) { | |
183 return scheduler_->BeginImplFrameDeadlinePending() == state; | |
184 } | |
185 | |
186 bool draw_will_happen_; | |
187 bool swap_will_happen_if_draw_happens_; | |
188 bool automatic_swap_ack_; | |
189 int num_draws_; | |
190 bool log_anticipated_draw_time_change_; | |
191 bool begin_frame_is_sent_to_children_; | |
192 base::TimeTicks posted_begin_impl_frame_deadline_; | |
193 std::vector<const char*> actions_; | |
194 std::vector<scoped_refptr<base::trace_event::ConvertableToTraceFormat>> | |
195 states_; | |
196 TestScheduler* scheduler_; | |
197 }; | |
198 | |
199 class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn { | |
200 public: | |
201 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client) | |
202 : client_(client) {} | |
203 ~FakeExternalBeginFrameSource() override {} | |
204 | |
205 void OnNeedsBeginFramesChange(bool needs_begin_frames) override { | |
206 if (needs_begin_frames) { | |
207 client_->PushAction("SetNeedsBeginFrames(true)"); | |
208 } else { | |
209 client_->PushAction("SetNeedsBeginFrames(false)"); | |
210 } | |
211 } | |
212 | |
213 void TestOnBeginFrame(const BeginFrameArgs& args) { | |
214 return CallOnBeginFrame(args); | |
215 } | |
216 | |
217 private: | |
218 FakeSchedulerClient* client_; | |
219 }; | |
220 | |
221 class SchedulerTest : public testing::Test { | |
222 public: | |
223 SchedulerTest() | |
224 : now_src_(TestNowSource::Create()), | |
225 task_runner_(new OrderedSimpleTaskRunner(now_src_, true)), | |
226 fake_external_begin_frame_source_(nullptr) { | |
227 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval() | |
228 now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100)); | |
229 // Fail if we need to run 100 tasks in a row. | |
230 task_runner_->SetRunTaskLimit(100); | |
231 } | |
232 | |
233 ~SchedulerTest() override {} | |
234 | |
235 protected: | |
236 TestScheduler* CreateScheduler() { | |
237 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source; | |
238 if (scheduler_settings_.use_external_begin_frame_source) { | |
239 fake_external_begin_frame_source.reset( | |
240 new FakeExternalBeginFrameSource(client_.get())); | |
241 fake_external_begin_frame_source_ = | |
242 fake_external_begin_frame_source.get(); | |
243 } | |
244 scheduler_ = TestScheduler::Create(now_src_, client_.get(), | |
245 scheduler_settings_, 0, task_runner_, | |
246 fake_external_begin_frame_source.Pass()); | |
247 DCHECK(scheduler_); | |
248 client_->set_scheduler(scheduler_.get()); | |
249 return scheduler_.get(); | |
250 } | |
251 | |
252 void CreateSchedulerAndInitSurface() { | |
253 CreateScheduler(); | |
254 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit()); | |
255 } | |
256 | |
257 void SetUpScheduler(bool initSurface) { | |
258 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface); | |
259 } | |
260 | |
261 void SetUpScheduler(scoped_ptr<FakeSchedulerClient> client, | |
262 bool initSurface) { | |
263 client_ = client.Pass(); | |
264 if (initSurface) | |
265 CreateSchedulerAndInitSurface(); | |
266 else | |
267 CreateScheduler(); | |
268 } | |
269 | |
270 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; } | |
271 TestNowSource* now_src() { return now_src_.get(); } | |
272 | |
273 // As this function contains EXPECT macros, to allow debugging it should be | |
274 // called inside EXPECT_SCOPED like so; | |
275 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler)); | |
276 void InitializeOutputSurfaceAndFirstCommit() { | |
277 TRACE_EVENT0("cc", | |
278 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit"); | |
279 DCHECK(scheduler_); | |
280 | |
281 // Check the client doesn't have any actions queued when calling this | |
282 // function. | |
283 EXPECT_NO_ACTION(client_); | |
284 EXPECT_FALSE(client_->needs_begin_frames()); | |
285 | |
286 // Start the initial output surface creation. | |
287 EXPECT_FALSE(scheduler_->CanStart()); | |
288 scheduler_->SetCanStart(); | |
289 scheduler_->SetVisible(true); | |
290 scheduler_->SetCanDraw(true); | |
291 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_); | |
292 | |
293 client_->Reset(); | |
294 | |
295 // We don't see anything happening until the first impl frame. | |
296 scheduler_->DidCreateAndInitializeOutputSurface(); | |
297 scheduler_->SetNeedsCommit(); | |
298 EXPECT_TRUE(client_->needs_begin_frames()); | |
299 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
300 client_->Reset(); | |
301 | |
302 { | |
303 SCOPED_TRACE("Do first frame to commit after initialize."); | |
304 AdvanceFrame(); | |
305 | |
306 scheduler_->NotifyBeginMainFrameStarted(); | |
307 scheduler_->NotifyReadyToCommitThenActivateIfNeeded(); | |
308 | |
309 // Run the posted deadline task. | |
310 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
311 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
312 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
313 | |
314 EXPECT_FALSE(scheduler_->CommitPending()); | |
315 } | |
316 | |
317 client_->Reset(); | |
318 | |
319 { | |
320 SCOPED_TRACE( | |
321 "Run second frame so Scheduler calls SetNeedsBeginFrame(false)."); | |
322 AdvanceFrame(); | |
323 | |
324 // Run the posted deadline task. | |
325 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
326 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
327 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
328 } | |
329 | |
330 EXPECT_FALSE(client_->needs_begin_frames()); | |
331 client_->Reset(); | |
332 } | |
333 | |
334 // As this function contains EXPECT macros, to allow debugging it should be | |
335 // called inside EXPECT_SCOPED like so; | |
336 // EXPECT_SCOPED(client.AdvanceFrame()); | |
337 void AdvanceFrame() { | |
338 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), | |
339 "FakeSchedulerClient::AdvanceFrame"); | |
340 // Consume any previous deadline first, if no deadline is currently | |
341 // pending, ImplFrameDeadlinePending will return false straight away and we | |
342 // will run no tasks. | |
343 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
344 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
345 | |
346 // Send the next BeginFrame message if using an external source, otherwise | |
347 // it will be already in the task queue. | |
348 if (scheduler_->settings().use_external_begin_frame_source && | |
349 scheduler_->FrameProductionThrottled()) { | |
350 SendNextBeginFrame(); | |
351 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
352 } | |
353 | |
354 // Then run tasks until new deadline is scheduled. | |
355 EXPECT_TRUE( | |
356 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(false))); | |
357 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
358 } | |
359 | |
360 void SendNextBeginFrame() { | |
361 DCHECK(scheduler_->settings().use_external_begin_frame_source); | |
362 // Creep the time forward so that any BeginFrameArgs is not equal to the | |
363 // last one otherwise we violate the BeginFrameSource contract. | |
364 now_src_->AdvanceNow(BeginFrameArgs::DefaultInterval()); | |
365 fake_external_begin_frame_source_->TestOnBeginFrame( | |
366 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src())); | |
367 } | |
368 | |
369 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const { | |
370 return fake_external_begin_frame_source_; | |
371 } | |
372 | |
373 void MainFrameInHighLatencyMode( | |
374 int64 begin_main_frame_to_commit_estimate_in_ms, | |
375 int64 commit_to_activate_estimate_in_ms, | |
376 bool impl_latency_takes_priority, | |
377 bool should_send_begin_main_frame); | |
378 void BeginFramesNotFromClient(bool use_external_begin_frame_source, | |
379 bool throttle_frame_production); | |
380 void BeginFramesNotFromClient_SwapThrottled( | |
381 bool use_external_begin_frame_source, | |
382 bool throttle_frame_production); | |
383 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency( | |
384 bool impl_side_painting); | |
385 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting); | |
386 | |
387 scoped_refptr<TestNowSource> now_src_; | |
388 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; | |
389 FakeExternalBeginFrameSource* fake_external_begin_frame_source_; | |
390 SchedulerSettings scheduler_settings_; | |
391 scoped_ptr<FakeSchedulerClient> client_; | |
392 scoped_ptr<TestScheduler> scheduler_; | |
393 }; | |
394 | |
395 TEST_F(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) { | |
396 scheduler_settings_.use_external_begin_frame_source = true; | |
397 SetUpScheduler(false); | |
398 scheduler_->SetCanStart(); | |
399 scheduler_->SetVisible(true); | |
400 scheduler_->SetCanDraw(true); | |
401 | |
402 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_); | |
403 client_->Reset(); | |
404 scheduler_->DidCreateAndInitializeOutputSurface(); | |
405 EXPECT_NO_ACTION(client_); | |
406 } | |
407 | |
408 TEST_F(SchedulerTest, SendBeginFramesToChildren) { | |
409 scheduler_settings_.use_external_begin_frame_source = true; | |
410 SetUpScheduler(true); | |
411 | |
412 EXPECT_FALSE(client_->begin_frame_is_sent_to_children()); | |
413 scheduler_->SetNeedsCommit(); | |
414 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
415 EXPECT_TRUE(client_->needs_begin_frames()); | |
416 | |
417 scheduler_->SetChildrenNeedBeginFrames(true); | |
418 | |
419 client_->Reset(); | |
420 EXPECT_SCOPED(AdvanceFrame()); | |
421 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); | |
422 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
423 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
424 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
425 EXPECT_TRUE(client_->needs_begin_frames()); | |
426 } | |
427 | |
428 TEST_F(SchedulerTest, SendBeginFramesToChildrenWithoutCommit) { | |
429 scheduler_settings_.use_external_begin_frame_source = true; | |
430 SetUpScheduler(true); | |
431 | |
432 EXPECT_FALSE(client_->needs_begin_frames()); | |
433 scheduler_->SetChildrenNeedBeginFrames(true); | |
434 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
435 EXPECT_TRUE(client_->needs_begin_frames()); | |
436 | |
437 client_->Reset(); | |
438 EXPECT_SCOPED(AdvanceFrame()); | |
439 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); | |
440 } | |
441 | |
442 TEST_F(SchedulerTest, RequestCommit) { | |
443 scheduler_settings_.use_external_begin_frame_source = true; | |
444 SetUpScheduler(true); | |
445 | |
446 // SetNeedsCommit should begin the frame on the next BeginImplFrame. | |
447 scheduler_->SetNeedsCommit(); | |
448 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
449 client_->Reset(); | |
450 | |
451 EXPECT_SCOPED(AdvanceFrame()); | |
452 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
453 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
454 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
455 EXPECT_TRUE(client_->needs_begin_frames()); | |
456 client_->Reset(); | |
457 | |
458 // If we don't swap on the deadline, we wait for the next BeginFrame. | |
459 task_runner().RunPendingTasks(); // Run posted deadline. | |
460 EXPECT_NO_ACTION(client_); | |
461 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
462 EXPECT_TRUE(client_->needs_begin_frames()); | |
463 client_->Reset(); | |
464 | |
465 // NotifyReadyToCommit should trigger the commit. | |
466 scheduler_->NotifyBeginMainFrameStarted(); | |
467 scheduler_->NotifyReadyToCommit(); | |
468 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
469 EXPECT_TRUE(client_->needs_begin_frames()); | |
470 client_->Reset(); | |
471 | |
472 // BeginImplFrame should prepare the draw. | |
473 EXPECT_SCOPED(AdvanceFrame()); | |
474 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
475 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
476 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
477 EXPECT_TRUE(client_->needs_begin_frames()); | |
478 client_->Reset(); | |
479 | |
480 // BeginImplFrame deadline should draw. | |
481 task_runner().RunPendingTasks(); // Run posted deadline. | |
482 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); | |
483 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
484 EXPECT_TRUE(client_->needs_begin_frames()); | |
485 client_->Reset(); | |
486 | |
487 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) | |
488 // to avoid excessive toggles. | |
489 EXPECT_SCOPED(AdvanceFrame()); | |
490 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); | |
491 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
492 client_->Reset(); | |
493 | |
494 task_runner().RunPendingTasks(); // Run posted deadline. | |
495 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); | |
496 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); | |
497 client_->Reset(); | |
498 } | |
499 | |
500 TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) { | |
501 scheduler_settings_.use_external_begin_frame_source = true; | |
502 SetUpScheduler(true); | |
503 | |
504 scheduler_->SetDeferCommits(true); | |
505 | |
506 scheduler_->SetNeedsCommit(); | |
507 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
508 | |
509 client_->Reset(); | |
510 AdvanceFrame(); | |
511 // BeginMainFrame is not sent during the defer commit is on. | |
512 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); | |
513 | |
514 client_->Reset(); | |
515 task_runner().RunPendingTasks(); // Run posted deadline. | |
516 // There is no posted deadline. | |
517 EXPECT_NO_ACTION(client_); | |
518 EXPECT_TRUE(client_->needs_begin_frames()); | |
519 | |
520 client_->Reset(); | |
521 scheduler_->SetDeferCommits(false); | |
522 EXPECT_NO_ACTION(client_); | |
523 | |
524 // Start new BeginMainFrame after defer commit is off. | |
525 client_->Reset(); | |
526 AdvanceFrame(); | |
527 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
528 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
529 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
530 } | |
531 | |
532 TEST_F(SchedulerTest, DeferCommitWithRedraw) { | |
533 scheduler_settings_.use_external_begin_frame_source = true; | |
534 SetUpScheduler(true); | |
535 | |
536 scheduler_->SetDeferCommits(true); | |
537 | |
538 scheduler_->SetNeedsCommit(); | |
539 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
540 | |
541 client_->Reset(); | |
542 scheduler_->SetNeedsRedraw(); | |
543 EXPECT_NO_ACTION(client_); | |
544 | |
545 client_->Reset(); | |
546 AdvanceFrame(); | |
547 // BeginMainFrame is not sent during the defer commit is on. | |
548 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
549 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
550 | |
551 client_->Reset(); | |
552 task_runner().RunPendingTasks(); // Run posted deadline. | |
553 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); | |
554 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
555 EXPECT_TRUE(client_->needs_begin_frames()); | |
556 | |
557 client_->Reset(); | |
558 AdvanceFrame(); | |
559 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); | |
560 } | |
561 | |
562 TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { | |
563 scheduler_settings_.use_external_begin_frame_source = true; | |
564 SetUpScheduler(true); | |
565 | |
566 // SetNeedsCommit should begin the frame. | |
567 scheduler_->SetNeedsCommit(); | |
568 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
569 | |
570 client_->Reset(); | |
571 EXPECT_SCOPED(AdvanceFrame()); | |
572 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
573 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
574 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
575 | |
576 EXPECT_TRUE(client_->needs_begin_frames()); | |
577 client_->Reset(); | |
578 | |
579 // Now SetNeedsCommit again. Calling here means we need a second commit. | |
580 scheduler_->SetNeedsCommit(); | |
581 EXPECT_EQ(client_->num_actions_(), 0); | |
582 client_->Reset(); | |
583 | |
584 // Finish the first commit. | |
585 scheduler_->NotifyBeginMainFrameStarted(); | |
586 scheduler_->NotifyReadyToCommit(); | |
587 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
588 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
589 client_->Reset(); | |
590 task_runner().RunPendingTasks(); // Run posted deadline. | |
591 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); | |
592 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); | |
593 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
594 | |
595 // Because we just swapped, the Scheduler should also request the next | |
596 // BeginImplFrame from the OutputSurface. | |
597 EXPECT_TRUE(client_->needs_begin_frames()); | |
598 client_->Reset(); | |
599 // Since another commit is needed, the next BeginImplFrame should initiate | |
600 // the second commit. | |
601 EXPECT_SCOPED(AdvanceFrame()); | |
602 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
603 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
604 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
605 client_->Reset(); | |
606 | |
607 // Finishing the commit before the deadline should post a new deadline task | |
608 // to trigger the deadline early. | |
609 scheduler_->NotifyBeginMainFrameStarted(); | |
610 scheduler_->NotifyReadyToCommit(); | |
611 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
612 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
613 client_->Reset(); | |
614 task_runner().RunPendingTasks(); // Run posted deadline. | |
615 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); | |
616 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); | |
617 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
618 EXPECT_TRUE(client_->needs_begin_frames()); | |
619 client_->Reset(); | |
620 | |
621 // On the next BeginImplFrame, verify we go back to a quiescent state and | |
622 // no longer request BeginImplFrames. | |
623 EXPECT_SCOPED(AdvanceFrame()); | |
624 task_runner().RunPendingTasks(); // Run posted deadline. | |
625 EXPECT_FALSE(client_->needs_begin_frames()); | |
626 client_->Reset(); | |
627 } | |
628 | |
629 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient { | |
630 public: | |
631 SchedulerClientThatsetNeedsDrawInsideDraw() | |
632 : FakeSchedulerClient(), request_redraws_(false) {} | |
633 | |
634 void ScheduledActionSendBeginMainFrame() override {} | |
635 | |
636 void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; } | |
637 | |
638 DrawResult ScheduledActionDrawAndSwapIfPossible() override { | |
639 // Only SetNeedsRedraw the first time this is called | |
640 if (request_redraws_) { | |
641 scheduler_->SetNeedsRedraw(); | |
642 } | |
643 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible(); | |
644 } | |
645 | |
646 DrawResult ScheduledActionDrawAndSwapForced() override { | |
647 NOTREACHED(); | |
648 return DRAW_SUCCESS; | |
649 } | |
650 | |
651 void ScheduledActionCommit() override {} | |
652 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {} | |
653 | |
654 private: | |
655 bool request_redraws_; | |
656 }; | |
657 | |
658 // Tests for two different situations: | |
659 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside | |
660 // a ScheduledActionDrawAndSwap | |
661 // 2. the scheduler drawing twice inside a single tick | |
662 TEST_F(SchedulerTest, RequestRedrawInsideDraw) { | |
663 SchedulerClientThatsetNeedsDrawInsideDraw* client = | |
664 new SchedulerClientThatsetNeedsDrawInsideDraw; | |
665 scheduler_settings_.use_external_begin_frame_source = true; | |
666 SetUpScheduler(make_scoped_ptr(client).Pass(), true); | |
667 client->SetRequestRedrawsInsideDraw(true); | |
668 | |
669 scheduler_->SetNeedsRedraw(); | |
670 EXPECT_TRUE(scheduler_->RedrawPending()); | |
671 EXPECT_TRUE(client->needs_begin_frames()); | |
672 EXPECT_EQ(0, client->num_draws()); | |
673 | |
674 EXPECT_SCOPED(AdvanceFrame()); | |
675 task_runner().RunPendingTasks(); // Run posted deadline. | |
676 EXPECT_EQ(1, client->num_draws()); | |
677 EXPECT_TRUE(scheduler_->RedrawPending()); | |
678 EXPECT_TRUE(client->needs_begin_frames()); | |
679 | |
680 client->SetRequestRedrawsInsideDraw(false); | |
681 | |
682 EXPECT_SCOPED(AdvanceFrame()); | |
683 task_runner().RunPendingTasks(); // Run posted deadline. | |
684 EXPECT_EQ(2, client_->num_draws()); | |
685 EXPECT_FALSE(scheduler_->RedrawPending()); | |
686 EXPECT_TRUE(client->needs_begin_frames()); | |
687 | |
688 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't | |
689 // swap. | |
690 EXPECT_SCOPED(AdvanceFrame()); | |
691 task_runner().RunPendingTasks(); // Run posted deadline. | |
692 EXPECT_EQ(2, client->num_draws()); | |
693 EXPECT_FALSE(scheduler_->RedrawPending()); | |
694 EXPECT_FALSE(client->needs_begin_frames()); | |
695 } | |
696 | |
697 // Test that requesting redraw inside a failed draw doesn't lose the request. | |
698 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) { | |
699 SchedulerClientThatsetNeedsDrawInsideDraw* client = | |
700 new SchedulerClientThatsetNeedsDrawInsideDraw; | |
701 scheduler_settings_.use_external_begin_frame_source = true; | |
702 SetUpScheduler(make_scoped_ptr(client).Pass(), true); | |
703 | |
704 client->SetRequestRedrawsInsideDraw(true); | |
705 client->SetDrawWillHappen(false); | |
706 | |
707 scheduler_->SetNeedsRedraw(); | |
708 EXPECT_TRUE(scheduler_->RedrawPending()); | |
709 EXPECT_TRUE(client->needs_begin_frames()); | |
710 EXPECT_EQ(0, client->num_draws()); | |
711 | |
712 // Fail the draw. | |
713 EXPECT_SCOPED(AdvanceFrame()); | |
714 task_runner().RunPendingTasks(); // Run posted deadline. | |
715 EXPECT_EQ(1, client->num_draws()); | |
716 | |
717 // We have a commit pending and the draw failed, and we didn't lose the redraw | |
718 // request. | |
719 EXPECT_TRUE(scheduler_->CommitPending()); | |
720 EXPECT_TRUE(scheduler_->RedrawPending()); | |
721 EXPECT_TRUE(client->needs_begin_frames()); | |
722 | |
723 client->SetRequestRedrawsInsideDraw(false); | |
724 | |
725 // Fail the draw again. | |
726 EXPECT_SCOPED(AdvanceFrame()); | |
727 task_runner().RunPendingTasks(); // Run posted deadline. | |
728 EXPECT_EQ(2, client->num_draws()); | |
729 EXPECT_TRUE(scheduler_->CommitPending()); | |
730 EXPECT_TRUE(scheduler_->RedrawPending()); | |
731 EXPECT_TRUE(client->needs_begin_frames()); | |
732 | |
733 // Draw successfully. | |
734 client->SetDrawWillHappen(true); | |
735 EXPECT_SCOPED(AdvanceFrame()); | |
736 task_runner().RunPendingTasks(); // Run posted deadline. | |
737 EXPECT_EQ(3, client->num_draws()); | |
738 EXPECT_TRUE(scheduler_->CommitPending()); | |
739 EXPECT_FALSE(scheduler_->RedrawPending()); | |
740 EXPECT_TRUE(client->needs_begin_frames()); | |
741 } | |
742 | |
743 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient { | |
744 public: | |
745 SchedulerClientThatSetNeedsCommitInsideDraw() | |
746 : set_needs_commit_on_next_draw_(false) {} | |
747 | |
748 void ScheduledActionSendBeginMainFrame() override {} | |
749 DrawResult ScheduledActionDrawAndSwapIfPossible() override { | |
750 // Only SetNeedsCommit the first time this is called | |
751 if (set_needs_commit_on_next_draw_) { | |
752 scheduler_->SetNeedsCommit(); | |
753 set_needs_commit_on_next_draw_ = false; | |
754 } | |
755 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible(); | |
756 } | |
757 | |
758 DrawResult ScheduledActionDrawAndSwapForced() override { | |
759 NOTREACHED(); | |
760 return DRAW_SUCCESS; | |
761 } | |
762 | |
763 void ScheduledActionCommit() override {} | |
764 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {} | |
765 | |
766 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; } | |
767 | |
768 private: | |
769 bool set_needs_commit_on_next_draw_; | |
770 }; | |
771 | |
772 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that | |
773 // happen inside a ScheduledActionDrawAndSwap | |
774 TEST_F(SchedulerTest, RequestCommitInsideDraw) { | |
775 SchedulerClientThatSetNeedsCommitInsideDraw* client = | |
776 new SchedulerClientThatSetNeedsCommitInsideDraw; | |
777 | |
778 scheduler_settings_.use_external_begin_frame_source = true; | |
779 SetUpScheduler(make_scoped_ptr(client).Pass(), true); | |
780 | |
781 EXPECT_FALSE(client->needs_begin_frames()); | |
782 scheduler_->SetNeedsRedraw(); | |
783 EXPECT_TRUE(scheduler_->RedrawPending()); | |
784 EXPECT_EQ(0, client->num_draws()); | |
785 EXPECT_TRUE(client->needs_begin_frames()); | |
786 | |
787 client->SetNeedsCommitOnNextDraw(); | |
788 EXPECT_SCOPED(AdvanceFrame()); | |
789 client->SetNeedsCommitOnNextDraw(); | |
790 task_runner().RunPendingTasks(); // Run posted deadline. | |
791 EXPECT_EQ(1, client->num_draws()); | |
792 EXPECT_TRUE(scheduler_->CommitPending()); | |
793 EXPECT_TRUE(client->needs_begin_frames()); | |
794 scheduler_->NotifyBeginMainFrameStarted(); | |
795 scheduler_->NotifyReadyToCommit(); | |
796 | |
797 EXPECT_SCOPED(AdvanceFrame()); | |
798 task_runner().RunPendingTasks(); // Run posted deadline. | |
799 EXPECT_EQ(2, client->num_draws()); | |
800 | |
801 EXPECT_FALSE(scheduler_->RedrawPending()); | |
802 EXPECT_FALSE(scheduler_->CommitPending()); | |
803 EXPECT_TRUE(client->needs_begin_frames()); | |
804 | |
805 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't | |
806 // swap. | |
807 EXPECT_SCOPED(AdvanceFrame()); | |
808 task_runner().RunPendingTasks(); // Run posted deadline. | |
809 EXPECT_EQ(2, client->num_draws()); | |
810 EXPECT_FALSE(scheduler_->RedrawPending()); | |
811 EXPECT_FALSE(scheduler_->CommitPending()); | |
812 EXPECT_FALSE(client->needs_begin_frames()); | |
813 } | |
814 | |
815 // Tests that when a draw fails then the pending commit should not be dropped. | |
816 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) { | |
817 SchedulerClientThatsetNeedsDrawInsideDraw* client = | |
818 new SchedulerClientThatsetNeedsDrawInsideDraw; | |
819 scheduler_settings_.use_external_begin_frame_source = true; | |
820 SetUpScheduler(make_scoped_ptr(client).Pass(), true); | |
821 | |
822 client->SetDrawWillHappen(false); | |
823 | |
824 scheduler_->SetNeedsRedraw(); | |
825 EXPECT_TRUE(scheduler_->RedrawPending()); | |
826 EXPECT_TRUE(client->needs_begin_frames()); | |
827 EXPECT_EQ(0, client->num_draws()); | |
828 | |
829 // Fail the draw. | |
830 EXPECT_SCOPED(AdvanceFrame()); | |
831 task_runner().RunPendingTasks(); // Run posted deadline. | |
832 EXPECT_EQ(1, client->num_draws()); | |
833 | |
834 // We have a commit pending and the draw failed, and we didn't lose the commit | |
835 // request. | |
836 EXPECT_TRUE(scheduler_->CommitPending()); | |
837 EXPECT_TRUE(scheduler_->RedrawPending()); | |
838 EXPECT_TRUE(client->needs_begin_frames()); | |
839 | |
840 // Fail the draw again. | |
841 EXPECT_SCOPED(AdvanceFrame()); | |
842 | |
843 task_runner().RunPendingTasks(); // Run posted deadline. | |
844 EXPECT_EQ(2, client->num_draws()); | |
845 EXPECT_TRUE(scheduler_->CommitPending()); | |
846 EXPECT_TRUE(scheduler_->RedrawPending()); | |
847 EXPECT_TRUE(client->needs_begin_frames()); | |
848 | |
849 // Draw successfully. | |
850 client->SetDrawWillHappen(true); | |
851 EXPECT_SCOPED(AdvanceFrame()); | |
852 task_runner().RunPendingTasks(); // Run posted deadline. | |
853 EXPECT_EQ(3, client->num_draws()); | |
854 EXPECT_TRUE(scheduler_->CommitPending()); | |
855 EXPECT_FALSE(scheduler_->RedrawPending()); | |
856 EXPECT_TRUE(client->needs_begin_frames()); | |
857 } | |
858 | |
859 TEST_F(SchedulerTest, NoSwapWhenDrawFails) { | |
860 SchedulerClientThatSetNeedsCommitInsideDraw* client = | |
861 new SchedulerClientThatSetNeedsCommitInsideDraw; | |
862 scheduler_settings_.use_external_begin_frame_source = true; | |
863 SetUpScheduler(make_scoped_ptr(client).Pass(), true); | |
864 | |
865 scheduler_->SetNeedsRedraw(); | |
866 EXPECT_TRUE(scheduler_->RedrawPending()); | |
867 EXPECT_TRUE(client->needs_begin_frames()); | |
868 EXPECT_EQ(0, client->num_draws()); | |
869 | |
870 // Draw successfully, this starts a new frame. | |
871 client->SetNeedsCommitOnNextDraw(); | |
872 EXPECT_SCOPED(AdvanceFrame()); | |
873 task_runner().RunPendingTasks(); // Run posted deadline. | |
874 EXPECT_EQ(1, client->num_draws()); | |
875 | |
876 scheduler_->SetNeedsRedraw(); | |
877 EXPECT_TRUE(scheduler_->RedrawPending()); | |
878 EXPECT_TRUE(client->needs_begin_frames()); | |
879 | |
880 // Fail to draw, this should not start a frame. | |
881 client->SetDrawWillHappen(false); | |
882 client->SetNeedsCommitOnNextDraw(); | |
883 EXPECT_SCOPED(AdvanceFrame()); | |
884 task_runner().RunPendingTasks(); // Run posted deadline. | |
885 EXPECT_EQ(2, client->num_draws()); | |
886 } | |
887 | |
888 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient { | |
889 public: | |
890 DrawResult ScheduledActionDrawAndSwapIfPossible() override { | |
891 scheduler_->SetNeedsPrepareTiles(); | |
892 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible(); | |
893 } | |
894 }; | |
895 | |
896 // Test prepare tiles is independant of draws. | |
897 TEST_F(SchedulerTest, PrepareTiles) { | |
898 SchedulerClientNeedsPrepareTilesInDraw* client = | |
899 new SchedulerClientNeedsPrepareTilesInDraw; | |
900 scheduler_settings_.use_external_begin_frame_source = true; | |
901 SetUpScheduler(make_scoped_ptr(client).Pass(), true); | |
902 | |
903 // Request both draw and prepare tiles. PrepareTiles shouldn't | |
904 // be trigged until BeginImplFrame. | |
905 client->Reset(); | |
906 scheduler_->SetNeedsPrepareTiles(); | |
907 scheduler_->SetNeedsRedraw(); | |
908 EXPECT_TRUE(scheduler_->RedrawPending()); | |
909 EXPECT_TRUE(scheduler_->PrepareTilesPending()); | |
910 EXPECT_TRUE(client->needs_begin_frames()); | |
911 EXPECT_EQ(0, client->num_draws()); | |
912 EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles")); | |
913 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
914 | |
915 // We have no immediate actions to perform, so the BeginImplFrame should post | |
916 // the deadline task. | |
917 client->Reset(); | |
918 EXPECT_SCOPED(AdvanceFrame()); | |
919 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); | |
920 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); | |
921 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
922 | |
923 // On the deadline, he actions should have occured in the right order. | |
924 client->Reset(); | |
925 task_runner().RunPendingTasks(); // Run posted deadline. | |
926 EXPECT_EQ(1, client->num_draws()); | |
927 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
928 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles")); | |
929 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"), | |
930 client->ActionIndex("ScheduledActionPrepareTiles")); | |
931 EXPECT_FALSE(scheduler_->RedrawPending()); | |
932 EXPECT_FALSE(scheduler_->PrepareTilesPending()); | |
933 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
934 | |
935 // Request a draw. We don't need a PrepareTiles yet. | |
936 client->Reset(); | |
937 scheduler_->SetNeedsRedraw(); | |
938 EXPECT_TRUE(scheduler_->RedrawPending()); | |
939 EXPECT_FALSE(scheduler_->PrepareTilesPending()); | |
940 EXPECT_TRUE(client->needs_begin_frames()); | |
941 EXPECT_EQ(0, client->num_draws()); | |
942 | |
943 // We have no immediate actions to perform, so the BeginImplFrame should post | |
944 // the deadline task. | |
945 client->Reset(); | |
946 EXPECT_SCOPED(AdvanceFrame()); | |
947 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); | |
948 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); | |
949 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
950 | |
951 // Draw. The draw will trigger SetNeedsPrepareTiles, and | |
952 // then the PrepareTiles action will be triggered after the Draw. | |
953 // Afterwards, neither a draw nor PrepareTiles are pending. | |
954 client->Reset(); | |
955 task_runner().RunPendingTasks(); // Run posted deadline. | |
956 EXPECT_EQ(1, client->num_draws()); | |
957 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
958 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles")); | |
959 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"), | |
960 client->ActionIndex("ScheduledActionPrepareTiles")); | |
961 EXPECT_FALSE(scheduler_->RedrawPending()); | |
962 EXPECT_FALSE(scheduler_->PrepareTilesPending()); | |
963 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
964 | |
965 // We need a BeginImplFrame where we don't swap to go idle. | |
966 client->Reset(); | |
967 EXPECT_SCOPED(AdvanceFrame()); | |
968 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); | |
969 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
970 client->Reset(); | |
971 task_runner().RunPendingTasks(); // Run posted deadline. | |
972 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); | |
973 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); | |
974 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
975 EXPECT_EQ(0, client->num_draws()); | |
976 | |
977 // Now trigger a PrepareTiles outside of a draw. We will then need | |
978 // a begin-frame for the PrepareTiles, but we don't need a draw. | |
979 client->Reset(); | |
980 EXPECT_FALSE(client->needs_begin_frames()); | |
981 scheduler_->SetNeedsPrepareTiles(); | |
982 EXPECT_TRUE(client->needs_begin_frames()); | |
983 EXPECT_TRUE(scheduler_->PrepareTilesPending()); | |
984 EXPECT_FALSE(scheduler_->RedrawPending()); | |
985 | |
986 // BeginImplFrame. There will be no draw, only PrepareTiles. | |
987 client->Reset(); | |
988 EXPECT_SCOPED(AdvanceFrame()); | |
989 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); | |
990 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
991 client->Reset(); | |
992 task_runner().RunPendingTasks(); // Run posted deadline. | |
993 EXPECT_EQ(0, client->num_draws()); | |
994 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
995 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles")); | |
996 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
997 } | |
998 | |
999 // Test that PrepareTiles only happens once per frame. If an external caller | |
1000 // initiates it, then the state machine should not PrepareTiles on that frame. | |
1001 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) { | |
1002 scheduler_settings_.use_external_begin_frame_source = true; | |
1003 SetUpScheduler(true); | |
1004 | |
1005 // If DidPrepareTiles during a frame, then PrepareTiles should not occur | |
1006 // again. | |
1007 scheduler_->SetNeedsPrepareTiles(); | |
1008 scheduler_->SetNeedsRedraw(); | |
1009 client_->Reset(); | |
1010 EXPECT_SCOPED(AdvanceFrame()); | |
1011 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1012 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1013 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1014 | |
1015 EXPECT_TRUE(scheduler_->PrepareTilesPending()); | |
1016 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles. | |
1017 EXPECT_FALSE(scheduler_->PrepareTilesPending()); | |
1018 | |
1019 client_->Reset(); | |
1020 task_runner().RunPendingTasks(); // Run posted deadline. | |
1021 EXPECT_EQ(1, client_->num_draws()); | |
1022 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
1023 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles")); | |
1024 EXPECT_FALSE(scheduler_->RedrawPending()); | |
1025 EXPECT_FALSE(scheduler_->PrepareTilesPending()); | |
1026 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1027 | |
1028 // Next frame without DidPrepareTiles should PrepareTiles with draw. | |
1029 scheduler_->SetNeedsPrepareTiles(); | |
1030 scheduler_->SetNeedsRedraw(); | |
1031 client_->Reset(); | |
1032 EXPECT_SCOPED(AdvanceFrame()); | |
1033 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1034 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1035 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1036 | |
1037 client_->Reset(); | |
1038 task_runner().RunPendingTasks(); // Run posted deadline. | |
1039 EXPECT_EQ(1, client_->num_draws()); | |
1040 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
1041 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles")); | |
1042 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"), | |
1043 client_->ActionIndex("ScheduledActionPrepareTiles")); | |
1044 EXPECT_FALSE(scheduler_->RedrawPending()); | |
1045 EXPECT_FALSE(scheduler_->PrepareTilesPending()); | |
1046 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1047 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles | |
1048 | |
1049 // If we get another DidPrepareTiles within the same frame, we should | |
1050 // not PrepareTiles on the next frame. | |
1051 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles. | |
1052 scheduler_->SetNeedsPrepareTiles(); | |
1053 scheduler_->SetNeedsRedraw(); | |
1054 client_->Reset(); | |
1055 EXPECT_SCOPED(AdvanceFrame()); | |
1056 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1057 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1058 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1059 | |
1060 EXPECT_TRUE(scheduler_->PrepareTilesPending()); | |
1061 | |
1062 client_->Reset(); | |
1063 task_runner().RunPendingTasks(); // Run posted deadline. | |
1064 EXPECT_EQ(1, client_->num_draws()); | |
1065 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
1066 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles")); | |
1067 EXPECT_FALSE(scheduler_->RedrawPending()); | |
1068 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1069 | |
1070 // If we get another DidPrepareTiles, we should not PrepareTiles on the next | |
1071 // frame. This verifies we don't alternate calling PrepareTiles once and | |
1072 // twice. | |
1073 EXPECT_TRUE(scheduler_->PrepareTilesPending()); | |
1074 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles. | |
1075 EXPECT_FALSE(scheduler_->PrepareTilesPending()); | |
1076 scheduler_->SetNeedsPrepareTiles(); | |
1077 scheduler_->SetNeedsRedraw(); | |
1078 client_->Reset(); | |
1079 EXPECT_SCOPED(AdvanceFrame()); | |
1080 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1081 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1082 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1083 | |
1084 EXPECT_TRUE(scheduler_->PrepareTilesPending()); | |
1085 | |
1086 client_->Reset(); | |
1087 task_runner().RunPendingTasks(); // Run posted deadline. | |
1088 EXPECT_EQ(1, client_->num_draws()); | |
1089 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
1090 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles")); | |
1091 EXPECT_FALSE(scheduler_->RedrawPending()); | |
1092 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1093 | |
1094 // Next frame without DidPrepareTiles should PrepareTiles with draw. | |
1095 scheduler_->SetNeedsPrepareTiles(); | |
1096 scheduler_->SetNeedsRedraw(); | |
1097 client_->Reset(); | |
1098 EXPECT_SCOPED(AdvanceFrame()); | |
1099 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1100 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1101 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1102 | |
1103 client_->Reset(); | |
1104 task_runner().RunPendingTasks(); // Run posted deadline. | |
1105 EXPECT_EQ(1, client_->num_draws()); | |
1106 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
1107 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles")); | |
1108 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"), | |
1109 client_->ActionIndex("ScheduledActionPrepareTiles")); | |
1110 EXPECT_FALSE(scheduler_->RedrawPending()); | |
1111 EXPECT_FALSE(scheduler_->PrepareTilesPending()); | |
1112 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1113 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles | |
1114 } | |
1115 | |
1116 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) { | |
1117 SchedulerClientNeedsPrepareTilesInDraw* client = | |
1118 new SchedulerClientNeedsPrepareTilesInDraw; | |
1119 scheduler_settings_.use_external_begin_frame_source = true; | |
1120 SetUpScheduler(make_scoped_ptr(client).Pass(), true); | |
1121 | |
1122 scheduler_->SetNeedsRedraw(); | |
1123 EXPECT_SCOPED(AdvanceFrame()); | |
1124 | |
1125 // The deadline should be zero since there is no work other than drawing | |
1126 // pending. | |
1127 EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline()); | |
1128 } | |
1129 | |
1130 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient { | |
1131 public: | |
1132 SchedulerClientWithFixedEstimates( | |
1133 base::TimeDelta draw_duration, | |
1134 base::TimeDelta begin_main_frame_to_commit_duration, | |
1135 base::TimeDelta commit_to_activate_duration) | |
1136 : draw_duration_(draw_duration), | |
1137 begin_main_frame_to_commit_duration_( | |
1138 begin_main_frame_to_commit_duration), | |
1139 commit_to_activate_duration_(commit_to_activate_duration) {} | |
1140 | |
1141 base::TimeDelta DrawDurationEstimate() override { return draw_duration_; } | |
1142 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override { | |
1143 return begin_main_frame_to_commit_duration_; | |
1144 } | |
1145 base::TimeDelta CommitToActivateDurationEstimate() override { | |
1146 return commit_to_activate_duration_; | |
1147 } | |
1148 | |
1149 private: | |
1150 base::TimeDelta draw_duration_; | |
1151 base::TimeDelta begin_main_frame_to_commit_duration_; | |
1152 base::TimeDelta commit_to_activate_duration_; | |
1153 }; | |
1154 | |
1155 void SchedulerTest::MainFrameInHighLatencyMode( | |
1156 int64 begin_main_frame_to_commit_estimate_in_ms, | |
1157 int64 commit_to_activate_estimate_in_ms, | |
1158 bool impl_latency_takes_priority, | |
1159 bool should_send_begin_main_frame) { | |
1160 // Set up client with specified estimates (draw duration is set to 1). | |
1161 SchedulerClientWithFixedEstimates* client = | |
1162 new SchedulerClientWithFixedEstimates( | |
1163 base::TimeDelta::FromMilliseconds(1), | |
1164 base::TimeDelta::FromMilliseconds( | |
1165 begin_main_frame_to_commit_estimate_in_ms), | |
1166 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms)); | |
1167 | |
1168 scheduler_settings_.use_external_begin_frame_source = true; | |
1169 SetUpScheduler(make_scoped_ptr(client).Pass(), true); | |
1170 | |
1171 scheduler_->SetImplLatencyTakesPriority(impl_latency_takes_priority); | |
1172 | |
1173 // Impl thread hits deadline before commit finishes. | |
1174 scheduler_->SetNeedsCommit(); | |
1175 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1176 EXPECT_SCOPED(AdvanceFrame()); | |
1177 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1178 task_runner().RunPendingTasks(); // Run posted deadline. | |
1179 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1180 scheduler_->NotifyBeginMainFrameStarted(); | |
1181 scheduler_->NotifyReadyToCommit(); | |
1182 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1183 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame")); | |
1184 | |
1185 client->Reset(); | |
1186 scheduler_->SetNeedsCommit(); | |
1187 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1188 EXPECT_SCOPED(AdvanceFrame()); | |
1189 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1190 task_runner().RunPendingTasks(); // Run posted deadline. | |
1191 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(), | |
1192 should_send_begin_main_frame); | |
1193 EXPECT_EQ(client->HasAction("ScheduledActionSendBeginMainFrame"), | |
1194 should_send_begin_main_frame); | |
1195 } | |
1196 | |
1197 TEST_F(SchedulerTest, | |
1198 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) { | |
1199 // Set up client so that estimates indicate that we can commit and activate | |
1200 // before the deadline (~8ms by default). | |
1201 MainFrameInHighLatencyMode(1, 1, false, false); | |
1202 } | |
1203 | |
1204 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) { | |
1205 // Set up client so that estimates indicate that the commit cannot finish | |
1206 // before the deadline (~8ms by default). | |
1207 MainFrameInHighLatencyMode(10, 1, false, true); | |
1208 } | |
1209 | |
1210 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) { | |
1211 // Set up client so that estimates indicate that the activate cannot finish | |
1212 // before the deadline (~8ms by default). | |
1213 MainFrameInHighLatencyMode(1, 10, false, true); | |
1214 } | |
1215 | |
1216 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { | |
1217 // Set up client so that estimates indicate that we can commit and activate | |
1218 // before the deadline (~8ms by default), but also enable impl latency takes | |
1219 // priority mode. | |
1220 MainFrameInHighLatencyMode(1, 1, true, true); | |
1221 } | |
1222 | |
1223 TEST_F(SchedulerTest, PollForCommitCompletion) { | |
1224 // Since we are simulating a long commit, set up a client with draw duration | |
1225 // estimates that prevent skipping main frames to get to low latency mode. | |
1226 SchedulerClientWithFixedEstimates* client = | |
1227 new SchedulerClientWithFixedEstimates( | |
1228 base::TimeDelta::FromMilliseconds(1), | |
1229 base::TimeDelta::FromMilliseconds(32), | |
1230 base::TimeDelta::FromMilliseconds(32)); | |
1231 scheduler_settings_.use_external_begin_frame_source = true; | |
1232 SetUpScheduler(make_scoped_ptr(client).Pass(), true); | |
1233 | |
1234 client->set_log_anticipated_draw_time_change(true); | |
1235 | |
1236 BeginFrameArgs frame_args = | |
1237 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); | |
1238 frame_args.interval = base::TimeDelta::FromMilliseconds(1000); | |
1239 | |
1240 // At this point, we've drawn a frame. Start another commit, but hold off on | |
1241 // the NotifyReadyToCommit for now. | |
1242 EXPECT_FALSE(scheduler_->CommitPending()); | |
1243 scheduler_->SetNeedsCommit(); | |
1244 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args); | |
1245 EXPECT_TRUE(scheduler_->CommitPending()); | |
1246 | |
1247 // Draw and swap the frame, but don't ack the swap to simulate the Browser | |
1248 // blocking on the renderer. | |
1249 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1250 task_runner().RunPendingTasks(); // Run posted deadline. | |
1251 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1252 scheduler_->DidSwapBuffers(); | |
1253 | |
1254 // Spin the event loop a few times and make sure we get more | |
1255 // DidAnticipateDrawTimeChange calls every time. | |
1256 int actions_so_far = client->num_actions_(); | |
1257 | |
1258 // Does three iterations to make sure that the timer is properly repeating. | |
1259 for (int i = 0; i < 3; ++i) { | |
1260 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(), | |
1261 task_runner().DelayToNextTaskTime().InMicroseconds()) | |
1262 << scheduler_->AsValue()->ToString(); | |
1263 task_runner().RunPendingTasks(); | |
1264 EXPECT_GT(client->num_actions_(), actions_so_far); | |
1265 EXPECT_STREQ(client->Action(client->num_actions_() - 1), | |
1266 "DidAnticipatedDrawTimeChange"); | |
1267 actions_so_far = client->num_actions_(); | |
1268 } | |
1269 | |
1270 // Do the same thing after BeginMainFrame starts but still before activation. | |
1271 scheduler_->NotifyBeginMainFrameStarted(); | |
1272 for (int i = 0; i < 3; ++i) { | |
1273 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(), | |
1274 task_runner().DelayToNextTaskTime().InMicroseconds()) | |
1275 << scheduler_->AsValue()->ToString(); | |
1276 task_runner().RunPendingTasks(); | |
1277 EXPECT_GT(client->num_actions_(), actions_so_far); | |
1278 EXPECT_STREQ(client->Action(client->num_actions_() - 1), | |
1279 "DidAnticipatedDrawTimeChange"); | |
1280 actions_so_far = client->num_actions_(); | |
1281 } | |
1282 } | |
1283 | |
1284 TEST_F(SchedulerTest, BeginRetroFrame) { | |
1285 scheduler_settings_.use_external_begin_frame_source = true; | |
1286 SetUpScheduler(true); | |
1287 | |
1288 // SetNeedsCommit should begin the frame on the next BeginImplFrame. | |
1289 scheduler_->SetNeedsCommit(); | |
1290 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
1291 client_->Reset(); | |
1292 | |
1293 // Create a BeginFrame with a long deadline to avoid race conditions. | |
1294 // This is the first BeginFrame, which will be handled immediately. | |
1295 BeginFrameArgs args = | |
1296 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); | |
1297 args.deadline += base::TimeDelta::FromHours(1); | |
1298 fake_external_begin_frame_source()->TestOnBeginFrame(args); | |
1299 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1300 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1301 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1302 EXPECT_TRUE(client_->needs_begin_frames()); | |
1303 client_->Reset(); | |
1304 | |
1305 // Queue BeginFrames while we are still handling the previous BeginFrame. | |
1306 args.frame_time += base::TimeDelta::FromSeconds(1); | |
1307 fake_external_begin_frame_source()->TestOnBeginFrame(args); | |
1308 args.frame_time += base::TimeDelta::FromSeconds(1); | |
1309 fake_external_begin_frame_source()->TestOnBeginFrame(args); | |
1310 | |
1311 // If we don't swap on the deadline, we wait for the next BeginImplFrame. | |
1312 task_runner().RunPendingTasks(); // Run posted deadline. | |
1313 EXPECT_NO_ACTION(client_); | |
1314 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1315 EXPECT_TRUE(client_->needs_begin_frames()); | |
1316 client_->Reset(); | |
1317 | |
1318 // NotifyReadyToCommit should trigger the commit. | |
1319 scheduler_->NotifyBeginMainFrameStarted(); | |
1320 scheduler_->NotifyReadyToCommit(); | |
1321 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
1322 EXPECT_TRUE(client_->needs_begin_frames()); | |
1323 client_->Reset(); | |
1324 | |
1325 // BeginImplFrame should prepare the draw. | |
1326 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. | |
1327 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1328 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1329 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1330 EXPECT_TRUE(client_->needs_begin_frames()); | |
1331 client_->Reset(); | |
1332 | |
1333 // BeginImplFrame deadline should draw. | |
1334 task_runner().RunPendingTasks(); // Run posted deadline. | |
1335 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); | |
1336 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1337 EXPECT_TRUE(client_->needs_begin_frames()); | |
1338 client_->Reset(); | |
1339 | |
1340 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) | |
1341 // to avoid excessive toggles. | |
1342 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. | |
1343 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); | |
1344 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1345 client_->Reset(); | |
1346 | |
1347 task_runner().RunPendingTasks(); // Run posted deadline. | |
1348 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); | |
1349 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); | |
1350 client_->Reset(); | |
1351 } | |
1352 | |
1353 TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) { | |
1354 scheduler_settings_.use_external_begin_frame_source = true; | |
1355 SetUpScheduler(true); | |
1356 | |
1357 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1)); | |
1358 | |
1359 // To test swap ack throttling, this test disables automatic swap acks. | |
1360 scheduler_->SetMaxSwapsPending(1); | |
1361 client_->SetAutomaticSwapAck(false); | |
1362 | |
1363 // SetNeedsCommit should begin the frame on the next BeginImplFrame. | |
1364 client_->Reset(); | |
1365 scheduler_->SetNeedsCommit(); | |
1366 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
1367 client_->Reset(); | |
1368 | |
1369 EXPECT_SCOPED(AdvanceFrame()); | |
1370 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1371 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1372 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1373 EXPECT_TRUE(client_->needs_begin_frames()); | |
1374 client_->Reset(); | |
1375 | |
1376 // Queue BeginFrame while we are still handling the previous BeginFrame. | |
1377 SendNextBeginFrame(); | |
1378 EXPECT_NO_ACTION(client_); | |
1379 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1380 EXPECT_TRUE(client_->needs_begin_frames()); | |
1381 client_->Reset(); | |
1382 | |
1383 // NotifyReadyToCommit should trigger the pending commit and draw. | |
1384 scheduler_->NotifyBeginMainFrameStarted(); | |
1385 scheduler_->NotifyReadyToCommit(); | |
1386 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
1387 EXPECT_TRUE(client_->needs_begin_frames()); | |
1388 client_->Reset(); | |
1389 | |
1390 // Swapping will put us into a swap throttled state. | |
1391 // Run posted deadline. | |
1392 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1393 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); | |
1394 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); | |
1395 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1396 EXPECT_TRUE(client_->needs_begin_frames()); | |
1397 client_->Reset(); | |
1398 | |
1399 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames | |
1400 // but not a BeginMainFrame or draw. | |
1401 scheduler_->SetNeedsCommit(); | |
1402 scheduler_->SetNeedsRedraw(); | |
1403 // Run posted BeginRetroFrame. | |
1404 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)); | |
1405 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1406 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1407 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1408 EXPECT_TRUE(client_->needs_begin_frames()); | |
1409 client_->Reset(); | |
1410 | |
1411 // Let time pass sufficiently beyond the regular deadline but not beyond the | |
1412 // late deadline. | |
1413 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() - | |
1414 base::TimeDelta::FromMicroseconds(1)); | |
1415 task_runner().RunUntilTime(now_src()->Now()); | |
1416 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1417 | |
1418 // Take us out of a swap throttled state. | |
1419 scheduler_->DidSwapBuffersComplete(); | |
1420 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_); | |
1421 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1422 EXPECT_TRUE(client_->needs_begin_frames()); | |
1423 client_->Reset(); | |
1424 | |
1425 // Verify that the deadline was rescheduled. | |
1426 task_runner().RunUntilTime(now_src()->Now()); | |
1427 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); | |
1428 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1429 EXPECT_TRUE(client_->needs_begin_frames()); | |
1430 client_->Reset(); | |
1431 } | |
1432 | |
1433 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) { | |
1434 scheduler_settings_.use_external_begin_frame_source = true; | |
1435 SetUpScheduler(true); | |
1436 | |
1437 scheduler_->SetNeedsCommit(); | |
1438 EXPECT_TRUE(client_->needs_begin_frames()); | |
1439 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
1440 | |
1441 client_->Reset(); | |
1442 EXPECT_SCOPED(AdvanceFrame()); | |
1443 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1444 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1445 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1446 | |
1447 client_->Reset(); | |
1448 scheduler_->NotifyBeginMainFrameStarted(); | |
1449 | |
1450 client_->Reset(); | |
1451 SendNextBeginFrame(); | |
1452 // This BeginFrame is queued up as a retro frame. | |
1453 EXPECT_NO_ACTION(client_); | |
1454 // The previous deadline is still pending. | |
1455 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1456 | |
1457 client_->Reset(); | |
1458 // This commit should schedule the (previous) deadline to trigger immediately. | |
1459 scheduler_->NotifyReadyToCommit(); | |
1460 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
1461 | |
1462 client_->Reset(); | |
1463 // The deadline task should trigger causing a draw. | |
1464 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1465 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1466 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); | |
1467 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); | |
1468 | |
1469 // Keep animating. | |
1470 client_->Reset(); | |
1471 scheduler_->SetNeedsAnimate(); | |
1472 scheduler_->SetNeedsRedraw(); | |
1473 EXPECT_NO_ACTION(client_); | |
1474 | |
1475 // Let's advance sufficiently past the next frame's deadline. | |
1476 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() - | |
1477 BeginFrameArgs::DefaultEstimatedParentDrawTime() + | |
1478 base::TimeDelta::FromMicroseconds(1)); | |
1479 | |
1480 // The retro frame hasn't expired yet. | |
1481 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)); | |
1482 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1483 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1484 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1485 | |
1486 // This is an immediate deadline case. | |
1487 client_->Reset(); | |
1488 task_runner().RunPendingTasks(); | |
1489 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1490 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); | |
1491 } | |
1492 | |
1493 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooLate) { | |
1494 scheduler_settings_.use_external_begin_frame_source = true; | |
1495 SetUpScheduler(true); | |
1496 | |
1497 scheduler_->SetNeedsCommit(); | |
1498 EXPECT_TRUE(client_->needs_begin_frames()); | |
1499 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
1500 | |
1501 client_->Reset(); | |
1502 EXPECT_SCOPED(AdvanceFrame()); | |
1503 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1504 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1505 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1506 | |
1507 client_->Reset(); | |
1508 scheduler_->NotifyBeginMainFrameStarted(); | |
1509 | |
1510 client_->Reset(); | |
1511 SendNextBeginFrame(); | |
1512 // This BeginFrame is queued up as a retro frame. | |
1513 EXPECT_NO_ACTION(client_); | |
1514 // The previous deadline is still pending. | |
1515 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1516 | |
1517 client_->Reset(); | |
1518 // This commit should schedule the (previous) deadline to trigger immediately. | |
1519 scheduler_->NotifyReadyToCommit(); | |
1520 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
1521 | |
1522 client_->Reset(); | |
1523 // The deadline task should trigger causing a draw. | |
1524 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1525 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1526 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); | |
1527 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); | |
1528 | |
1529 // Keep animating. | |
1530 client_->Reset(); | |
1531 scheduler_->SetNeedsAnimate(); | |
1532 scheduler_->SetNeedsRedraw(); | |
1533 EXPECT_NO_ACTION(client_); | |
1534 | |
1535 // Let's advance sufficiently past the next frame's deadline. | |
1536 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() + | |
1537 base::TimeDelta::FromMicroseconds(1)); | |
1538 | |
1539 // The retro frame should've expired. | |
1540 EXPECT_NO_ACTION(client_); | |
1541 } | |
1542 | |
1543 void SchedulerTest::BeginFramesNotFromClient( | |
1544 bool use_external_begin_frame_source, | |
1545 bool throttle_frame_production) { | |
1546 scheduler_settings_.use_external_begin_frame_source = | |
1547 use_external_begin_frame_source; | |
1548 scheduler_settings_.throttle_frame_production = throttle_frame_production; | |
1549 SetUpScheduler(true); | |
1550 | |
1551 // SetNeedsCommit should begin the frame on the next BeginImplFrame | |
1552 // without calling SetNeedsBeginFrame. | |
1553 scheduler_->SetNeedsCommit(); | |
1554 EXPECT_NO_ACTION(client_); | |
1555 client_->Reset(); | |
1556 | |
1557 // When the client-driven BeginFrame are disabled, the scheduler posts it's | |
1558 // own BeginFrame tasks. | |
1559 task_runner().RunPendingTasks(); // Run posted BeginFrame. | |
1560 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1561 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1562 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1563 client_->Reset(); | |
1564 | |
1565 // If we don't swap on the deadline, we wait for the next BeginFrame. | |
1566 task_runner().RunPendingTasks(); // Run posted deadline. | |
1567 EXPECT_NO_ACTION(client_); | |
1568 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1569 client_->Reset(); | |
1570 | |
1571 // NotifyReadyToCommit should trigger the commit. | |
1572 scheduler_->NotifyBeginMainFrameStarted(); | |
1573 scheduler_->NotifyReadyToCommit(); | |
1574 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
1575 client_->Reset(); | |
1576 | |
1577 // BeginImplFrame should prepare the draw. | |
1578 task_runner().RunPendingTasks(); // Run posted BeginFrame. | |
1579 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1580 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1581 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1582 client_->Reset(); | |
1583 | |
1584 // BeginImplFrame deadline should draw. | |
1585 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1586 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); | |
1587 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1588 client_->Reset(); | |
1589 | |
1590 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) | |
1591 // to avoid excessive toggles. | |
1592 task_runner().RunPendingTasks(); // Run posted BeginFrame. | |
1593 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); | |
1594 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1595 client_->Reset(); | |
1596 | |
1597 // Make sure SetNeedsBeginFrame isn't called on the client | |
1598 // when the BeginFrame is no longer needed. | |
1599 task_runner().RunPendingTasks(); // Run posted deadline. | |
1600 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_); | |
1601 client_->Reset(); | |
1602 } | |
1603 | |
1604 TEST_F(SchedulerTest, SyntheticBeginFrames) { | |
1605 bool use_external_begin_frame_source = false; | |
1606 bool throttle_frame_production = true; | |
1607 BeginFramesNotFromClient(use_external_begin_frame_source, | |
1608 throttle_frame_production); | |
1609 } | |
1610 | |
1611 TEST_F(SchedulerTest, VSyncThrottlingDisabled) { | |
1612 bool use_external_begin_frame_source = true; | |
1613 bool throttle_frame_production = false; | |
1614 BeginFramesNotFromClient(use_external_begin_frame_source, | |
1615 throttle_frame_production); | |
1616 } | |
1617 | |
1618 TEST_F(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) { | |
1619 bool use_external_begin_frame_source = false; | |
1620 bool throttle_frame_production = false; | |
1621 BeginFramesNotFromClient(use_external_begin_frame_source, | |
1622 throttle_frame_production); | |
1623 } | |
1624 | |
1625 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled( | |
1626 bool use_external_begin_frame_source, | |
1627 bool throttle_frame_production) { | |
1628 scheduler_settings_.use_external_begin_frame_source = | |
1629 use_external_begin_frame_source; | |
1630 scheduler_settings_.throttle_frame_production = throttle_frame_production; | |
1631 SetUpScheduler(true); | |
1632 | |
1633 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1)); | |
1634 | |
1635 // To test swap ack throttling, this test disables automatic swap acks. | |
1636 scheduler_->SetMaxSwapsPending(1); | |
1637 client_->SetAutomaticSwapAck(false); | |
1638 | |
1639 // SetNeedsCommit should begin the frame on the next BeginImplFrame. | |
1640 client_->Reset(); | |
1641 scheduler_->SetNeedsCommit(); | |
1642 EXPECT_NO_ACTION(client_); | |
1643 client_->Reset(); | |
1644 | |
1645 // Trigger the first BeginImplFrame and BeginMainFrame | |
1646 EXPECT_SCOPED(AdvanceFrame()); | |
1647 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1648 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1649 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1650 client_->Reset(); | |
1651 | |
1652 // NotifyReadyToCommit should trigger the pending commit and draw. | |
1653 scheduler_->NotifyBeginMainFrameStarted(); | |
1654 scheduler_->NotifyReadyToCommit(); | |
1655 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
1656 client_->Reset(); | |
1657 | |
1658 // Swapping will put us into a swap throttled state. | |
1659 // Run posted deadline. | |
1660 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1661 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); | |
1662 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); | |
1663 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1664 client_->Reset(); | |
1665 | |
1666 // While swap throttled, BeginFrames should trigger BeginImplFrames, | |
1667 // but not a BeginMainFrame or draw. | |
1668 scheduler_->SetNeedsCommit(); | |
1669 scheduler_->SetNeedsRedraw(); | |
1670 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame. | |
1671 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1672 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1673 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1674 client_->Reset(); | |
1675 | |
1676 // Let time pass sufficiently beyond the regular deadline but not beyond the | |
1677 // late deadline. | |
1678 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() - | |
1679 base::TimeDelta::FromMicroseconds(1)); | |
1680 task_runner().RunUntilTime(now_src()->Now()); | |
1681 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1682 | |
1683 // Take us out of a swap throttled state. | |
1684 scheduler_->DidSwapBuffersComplete(); | |
1685 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_); | |
1686 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1687 client_->Reset(); | |
1688 | |
1689 // Verify that the deadline was rescheduled. | |
1690 // We can't use RunUntilTime(now) here because the next frame is also | |
1691 // scheduled if throttle_frame_production = false. | |
1692 base::TimeTicks before_deadline = now_src()->Now(); | |
1693 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1694 base::TimeTicks after_deadline = now_src()->Now(); | |
1695 EXPECT_EQ(after_deadline, before_deadline); | |
1696 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1697 client_->Reset(); | |
1698 } | |
1699 | |
1700 TEST_F(SchedulerTest, SyntheticBeginFrames_SwapThrottled) { | |
1701 bool use_external_begin_frame_source = false; | |
1702 bool throttle_frame_production = true; | |
1703 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source, | |
1704 throttle_frame_production); | |
1705 } | |
1706 | |
1707 TEST_F(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) { | |
1708 bool use_external_begin_frame_source = true; | |
1709 bool throttle_frame_production = false; | |
1710 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source, | |
1711 throttle_frame_production); | |
1712 } | |
1713 | |
1714 TEST_F(SchedulerTest, | |
1715 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) { | |
1716 bool use_external_begin_frame_source = false; | |
1717 bool throttle_frame_production = false; | |
1718 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source, | |
1719 throttle_frame_production); | |
1720 } | |
1721 | |
1722 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) { | |
1723 scheduler_settings_.use_external_begin_frame_source = true; | |
1724 SetUpScheduler(false); | |
1725 | |
1726 scheduler_->SetCanStart(); | |
1727 scheduler_->SetVisible(true); | |
1728 scheduler_->SetCanDraw(true); | |
1729 | |
1730 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_); | |
1731 client_->Reset(); | |
1732 scheduler_->DidCreateAndInitializeOutputSurface(); | |
1733 EXPECT_NO_ACTION(client_); | |
1734 | |
1735 scheduler_->DidLoseOutputSurface(); | |
1736 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_); | |
1737 } | |
1738 | |
1739 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) { | |
1740 scheduler_settings_.use_external_begin_frame_source = true; | |
1741 SetUpScheduler(true); | |
1742 | |
1743 // SetNeedsCommit should begin the frame. | |
1744 scheduler_->SetNeedsCommit(); | |
1745 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
1746 | |
1747 client_->Reset(); | |
1748 EXPECT_SCOPED(AdvanceFrame()); | |
1749 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1750 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1751 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1752 | |
1753 client_->Reset(); | |
1754 scheduler_->DidLoseOutputSurface(); | |
1755 // SetNeedsBeginFrames(false) is not called until the end of the frame. | |
1756 EXPECT_NO_ACTION(client_); | |
1757 | |
1758 client_->Reset(); | |
1759 scheduler_->NotifyBeginMainFrameStarted(); | |
1760 scheduler_->NotifyReadyToCommit(); | |
1761 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 1); | |
1762 | |
1763 client_->Reset(); | |
1764 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1765 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); | |
1766 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); | |
1767 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); | |
1768 } | |
1769 | |
1770 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency( | |
1771 bool impl_side_painting) { | |
1772 scheduler_settings_.impl_side_painting = impl_side_painting; | |
1773 scheduler_settings_.use_external_begin_frame_source = true; | |
1774 SetUpScheduler(true); | |
1775 | |
1776 // SetNeedsCommit should begin the frame. | |
1777 scheduler_->SetNeedsCommit(); | |
1778 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
1779 | |
1780 client_->Reset(); | |
1781 EXPECT_SCOPED(AdvanceFrame()); | |
1782 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1783 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1784 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1785 | |
1786 client_->Reset(); | |
1787 scheduler_->DidLoseOutputSurface(); | |
1788 // Do nothing when impl frame is in deadine pending state. | |
1789 EXPECT_NO_ACTION(client_); | |
1790 | |
1791 client_->Reset(); | |
1792 // Run posted deadline. | |
1793 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1794 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1795 // OnBeginImplFrameDeadline didn't schedule output surface creation because | |
1796 // main frame is not yet completed. | |
1797 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); | |
1798 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); | |
1799 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1800 | |
1801 // BeginImplFrame is not started. | |
1802 client_->Reset(); | |
1803 task_runner().RunUntilTime(now_src()->Now() + | |
1804 base::TimeDelta::FromMilliseconds(10)); | |
1805 EXPECT_NO_ACTION(client_); | |
1806 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1807 | |
1808 client_->Reset(); | |
1809 scheduler_->NotifyBeginMainFrameStarted(); | |
1810 scheduler_->NotifyReadyToCommit(); | |
1811 if (impl_side_painting) { | |
1812 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3); | |
1813 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3); | |
1814 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3); | |
1815 } else { | |
1816 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2); | |
1817 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 2); | |
1818 } | |
1819 } | |
1820 | |
1821 TEST_F(SchedulerTest, | |
1822 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) { | |
1823 bool impl_side_painting = false; | |
1824 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting); | |
1825 } | |
1826 | |
1827 TEST_F(SchedulerTest, | |
1828 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) { | |
1829 bool impl_side_painting = true; | |
1830 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting); | |
1831 } | |
1832 | |
1833 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit( | |
1834 bool impl_side_painting) { | |
1835 scheduler_settings_.impl_side_painting = impl_side_painting; | |
1836 scheduler_settings_.use_external_begin_frame_source = true; | |
1837 SetUpScheduler(true); | |
1838 | |
1839 // SetNeedsCommit should begin the frame. | |
1840 scheduler_->SetNeedsCommit(); | |
1841 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
1842 | |
1843 client_->Reset(); | |
1844 EXPECT_SCOPED(AdvanceFrame()); | |
1845 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1846 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1847 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1848 | |
1849 client_->Reset(); | |
1850 scheduler_->NotifyBeginMainFrameStarted(); | |
1851 scheduler_->NotifyReadyToCommit(); | |
1852 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
1853 | |
1854 client_->Reset(); | |
1855 scheduler_->DidLoseOutputSurface(); | |
1856 // SetNeedsBeginFrames(false) is not called until the end of the frame. | |
1857 if (impl_side_painting) { | |
1858 // Sync tree should be forced to activate. | |
1859 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); | |
1860 } else { | |
1861 EXPECT_NO_ACTION(client_); | |
1862 } | |
1863 | |
1864 client_->Reset(); | |
1865 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1866 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); | |
1867 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); | |
1868 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); | |
1869 } | |
1870 | |
1871 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) { | |
1872 DidLoseOutputSurfaceAfterReadyToCommit(false); | |
1873 } | |
1874 | |
1875 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) { | |
1876 DidLoseOutputSurfaceAfterReadyToCommit(true); | |
1877 } | |
1878 | |
1879 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) { | |
1880 scheduler_settings_.use_external_begin_frame_source = true; | |
1881 SetUpScheduler(true); | |
1882 | |
1883 scheduler_->SetNeedsPrepareTiles(); | |
1884 scheduler_->SetNeedsRedraw(); | |
1885 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
1886 | |
1887 client_->Reset(); | |
1888 EXPECT_SCOPED(AdvanceFrame()); | |
1889 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1890 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1891 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1892 | |
1893 client_->Reset(); | |
1894 scheduler_->DidLoseOutputSurface(); | |
1895 // SetNeedsBeginFrames(false) is not called until the end of the frame. | |
1896 EXPECT_NO_ACTION(client_); | |
1897 | |
1898 client_->Reset(); | |
1899 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1900 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 4); | |
1901 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 4); | |
1902 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 2, 4); | |
1903 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 3, 4); | |
1904 } | |
1905 | |
1906 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) { | |
1907 scheduler_settings_.use_external_begin_frame_source = true; | |
1908 SetUpScheduler(true); | |
1909 | |
1910 // SetNeedsCommit should begin the frame on the next BeginImplFrame. | |
1911 scheduler_->SetNeedsCommit(); | |
1912 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
1913 | |
1914 // Create a BeginFrame with a long deadline to avoid race conditions. | |
1915 // This is the first BeginFrame, which will be handled immediately. | |
1916 client_->Reset(); | |
1917 BeginFrameArgs args = | |
1918 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); | |
1919 args.deadline += base::TimeDelta::FromHours(1); | |
1920 fake_external_begin_frame_source()->TestOnBeginFrame(args); | |
1921 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1922 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1923 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1924 EXPECT_TRUE(client_->needs_begin_frames()); | |
1925 | |
1926 // Queue BeginFrames while we are still handling the previous BeginFrame. | |
1927 args.frame_time += base::TimeDelta::FromSeconds(1); | |
1928 fake_external_begin_frame_source()->TestOnBeginFrame(args); | |
1929 args.frame_time += base::TimeDelta::FromSeconds(1); | |
1930 fake_external_begin_frame_source()->TestOnBeginFrame(args); | |
1931 | |
1932 // If we don't swap on the deadline, we wait for the next BeginImplFrame. | |
1933 client_->Reset(); | |
1934 task_runner().RunPendingTasks(); // Run posted deadline. | |
1935 EXPECT_NO_ACTION(client_); | |
1936 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1937 EXPECT_TRUE(client_->needs_begin_frames()); | |
1938 | |
1939 // NotifyReadyToCommit should trigger the commit. | |
1940 client_->Reset(); | |
1941 scheduler_->NotifyBeginMainFrameStarted(); | |
1942 scheduler_->NotifyReadyToCommit(); | |
1943 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
1944 EXPECT_TRUE(client_->needs_begin_frames()); | |
1945 | |
1946 client_->Reset(); | |
1947 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty()); | |
1948 scheduler_->DidLoseOutputSurface(); | |
1949 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); | |
1950 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); | |
1951 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); | |
1952 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty()); | |
1953 | |
1954 // Posted BeginRetroFrame is aborted. | |
1955 client_->Reset(); | |
1956 task_runner().RunPendingTasks(); | |
1957 EXPECT_NO_ACTION(client_); | |
1958 } | |
1959 | |
1960 TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) { | |
1961 scheduler_settings_.use_external_begin_frame_source = true; | |
1962 SetUpScheduler(true); | |
1963 | |
1964 // SetNeedsCommit should begin the frame on the next BeginImplFrame. | |
1965 scheduler_->SetNeedsCommit(); | |
1966 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
1967 | |
1968 // Create a BeginFrame with a long deadline to avoid race conditions. | |
1969 // This is the first BeginFrame, which will be handled immediately. | |
1970 client_->Reset(); | |
1971 BeginFrameArgs args = | |
1972 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); | |
1973 args.deadline += base::TimeDelta::FromHours(1); | |
1974 fake_external_begin_frame_source()->TestOnBeginFrame(args); | |
1975 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1976 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1977 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1978 EXPECT_TRUE(client_->needs_begin_frames()); | |
1979 | |
1980 // Queue BeginFrames while we are still handling the previous BeginFrame. | |
1981 args.frame_time += base::TimeDelta::FromSeconds(1); | |
1982 fake_external_begin_frame_source()->TestOnBeginFrame(args); | |
1983 args.frame_time += base::TimeDelta::FromSeconds(1); | |
1984 fake_external_begin_frame_source()->TestOnBeginFrame(args); | |
1985 | |
1986 // If we don't swap on the deadline, we wait for the next BeginImplFrame. | |
1987 client_->Reset(); | |
1988 task_runner().RunPendingTasks(); // Run posted deadline. | |
1989 EXPECT_NO_ACTION(client_); | |
1990 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1991 EXPECT_TRUE(client_->needs_begin_frames()); | |
1992 | |
1993 // NotifyReadyToCommit should trigger the commit. | |
1994 client_->Reset(); | |
1995 scheduler_->NotifyBeginMainFrameStarted(); | |
1996 scheduler_->NotifyReadyToCommit(); | |
1997 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
1998 EXPECT_TRUE(client_->needs_begin_frames()); | |
1999 | |
2000 // BeginImplFrame should prepare the draw. | |
2001 client_->Reset(); | |
2002 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. | |
2003 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
2004 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
2005 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2006 EXPECT_TRUE(client_->needs_begin_frames()); | |
2007 | |
2008 client_->Reset(); | |
2009 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty()); | |
2010 scheduler_->DidLoseOutputSurface(); | |
2011 EXPECT_NO_ACTION(client_); | |
2012 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty()); | |
2013 | |
2014 // BeginImplFrame deadline should abort drawing. | |
2015 client_->Reset(); | |
2016 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
2017 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); | |
2018 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); | |
2019 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); | |
2020 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
2021 EXPECT_FALSE(client_->needs_begin_frames()); | |
2022 | |
2023 // No more BeginRetroFrame because BeginRetroFrame queue is cleared. | |
2024 client_->Reset(); | |
2025 task_runner().RunPendingTasks(); | |
2026 EXPECT_NO_ACTION(client_); | |
2027 } | |
2028 | |
2029 TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) { | |
2030 SetUpScheduler(true); | |
2031 | |
2032 // SetNeedsCommit should begin the frame on the next BeginImplFrame. | |
2033 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames()); | |
2034 scheduler_->SetNeedsCommit(); | |
2035 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); | |
2036 | |
2037 client_->Reset(); | |
2038 AdvanceFrame(); | |
2039 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
2040 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
2041 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2042 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); | |
2043 | |
2044 // NotifyReadyToCommit should trigger the commit. | |
2045 client_->Reset(); | |
2046 scheduler_->NotifyBeginMainFrameStarted(); | |
2047 scheduler_->NotifyReadyToCommit(); | |
2048 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
2049 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); | |
2050 | |
2051 client_->Reset(); | |
2052 scheduler_->DidLoseOutputSurface(); | |
2053 // SetNeedsBeginFrames(false) is not called until the end of the frame. | |
2054 EXPECT_NO_ACTION(client_); | |
2055 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); | |
2056 | |
2057 client_->Reset(); | |
2058 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
2059 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2); | |
2060 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); | |
2061 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames()); | |
2062 } | |
2063 | |
2064 TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) { | |
2065 scheduler_settings_.use_external_begin_frame_source = true; | |
2066 SetUpScheduler(true); | |
2067 | |
2068 // SetNeedsCommit should begin the frame. | |
2069 scheduler_->SetNeedsCommit(); | |
2070 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
2071 | |
2072 client_->Reset(); | |
2073 EXPECT_SCOPED(AdvanceFrame()); | |
2074 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
2075 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
2076 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2077 | |
2078 client_->Reset(); | |
2079 scheduler_->NotifyBeginMainFrameStarted(); | |
2080 scheduler_->NotifyReadyToCommit(); | |
2081 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
2082 | |
2083 client_->Reset(); | |
2084 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
2085 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); | |
2086 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); | |
2087 | |
2088 // Idle time between BeginFrames. | |
2089 client_->Reset(); | |
2090 scheduler_->DidLoseOutputSurface(); | |
2091 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); | |
2092 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); | |
2093 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); | |
2094 } | |
2095 | |
2096 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) { | |
2097 scheduler_settings_.impl_side_painting = true; | |
2098 scheduler_settings_.use_external_begin_frame_source = true; | |
2099 SetUpScheduler(true); | |
2100 | |
2101 // SetNeedsCommit should begin the frame. | |
2102 scheduler_->SetNeedsCommit(); | |
2103 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
2104 | |
2105 client_->Reset(); | |
2106 EXPECT_SCOPED(AdvanceFrame()); | |
2107 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
2108 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
2109 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2110 | |
2111 client_->Reset(); | |
2112 scheduler_->NotifyBeginMainFrameStarted(); | |
2113 scheduler_->NotifyReadyToCommit(); | |
2114 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | |
2115 | |
2116 client_->Reset(); | |
2117 scheduler_->SetVisible(false); | |
2118 // Sync tree should be forced to activate. | |
2119 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); | |
2120 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2); | |
2121 } | |
2122 | |
2123 // Tests to ensure frame sources can be successfully changed while drawing. | |
2124 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) { | |
2125 scheduler_settings_.use_external_begin_frame_source = true; | |
2126 SetUpScheduler(true); | |
2127 | |
2128 // SetNeedsRedraw should begin the frame on the next BeginImplFrame. | |
2129 scheduler_->SetNeedsRedraw(); | |
2130 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
2131 client_->Reset(); | |
2132 | |
2133 EXPECT_SCOPED(AdvanceFrame()); | |
2134 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
2135 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
2136 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2137 EXPECT_TRUE(client_->needs_begin_frames()); | |
2138 client_->Reset(); | |
2139 task_runner().RunPendingTasks(); // Run posted deadline. | |
2140 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); | |
2141 scheduler_->SetNeedsRedraw(); | |
2142 | |
2143 // Switch to an unthrottled frame source. | |
2144 scheduler_->SetThrottleFrameProduction(false); | |
2145 client_->Reset(); | |
2146 | |
2147 // Unthrottled frame source will immediately begin a new frame. | |
2148 task_runner().RunPendingTasks(); // Run posted BeginFrame. | |
2149 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
2150 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
2151 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2152 client_->Reset(); | |
2153 | |
2154 // If we don't swap on the deadline, we wait for the next BeginFrame. | |
2155 task_runner().RunPendingTasks(); // Run posted deadline. | |
2156 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); | |
2157 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
2158 client_->Reset(); | |
2159 } | |
2160 | |
2161 // Tests to ensure frame sources can be successfully changed while a frame | |
2162 // deadline is pending. | |
2163 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) { | |
2164 scheduler_settings_.use_external_begin_frame_source = true; | |
2165 SetUpScheduler(true); | |
2166 | |
2167 // SetNeedsRedraw should begin the frame on the next BeginImplFrame. | |
2168 scheduler_->SetNeedsRedraw(); | |
2169 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
2170 client_->Reset(); | |
2171 | |
2172 EXPECT_SCOPED(AdvanceFrame()); | |
2173 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
2174 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
2175 | |
2176 // Switch to an unthrottled frame source before the frame deadline is hit. | |
2177 scheduler_->SetThrottleFrameProduction(false); | |
2178 client_->Reset(); | |
2179 | |
2180 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2181 EXPECT_TRUE(client_->needs_begin_frames()); | |
2182 client_->Reset(); | |
2183 | |
2184 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame. | |
2185 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2); | |
2186 // Unthrottled frame source will immediately begin a new frame. | |
2187 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2); | |
2188 scheduler_->SetNeedsRedraw(); | |
2189 client_->Reset(); | |
2190 | |
2191 task_runner().RunPendingTasks(); // Run posted deadline. | |
2192 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2); | |
2193 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); | |
2194 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
2195 client_->Reset(); | |
2196 } | |
2197 | |
2198 // Tests to ensure that the active frame source can successfully be changed from | |
2199 // unthrottled to throttled. | |
2200 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) { | |
2201 scheduler_settings_.throttle_frame_production = false; | |
2202 scheduler_settings_.use_external_begin_frame_source = true; | |
2203 SetUpScheduler(true); | |
2204 | |
2205 scheduler_->SetNeedsRedraw(); | |
2206 EXPECT_NO_ACTION(client_); | |
2207 client_->Reset(); | |
2208 | |
2209 task_runner().RunPendingTasks(); // Run posted BeginFrame. | |
2210 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
2211 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
2212 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2213 client_->Reset(); | |
2214 | |
2215 task_runner().RunPendingTasks(); // Run posted deadline. | |
2216 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); | |
2217 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
2218 client_->Reset(); | |
2219 | |
2220 // Switch to a throttled frame source. | |
2221 scheduler_->SetThrottleFrameProduction(true); | |
2222 client_->Reset(); | |
2223 | |
2224 // SetNeedsRedraw should begin the frame on the next BeginImplFrame. | |
2225 scheduler_->SetNeedsRedraw(); | |
2226 task_runner().RunPendingTasks(); | |
2227 EXPECT_NO_ACTION(client_); | |
2228 client_->Reset(); | |
2229 | |
2230 EXPECT_SCOPED(AdvanceFrame()); | |
2231 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
2232 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
2233 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2234 EXPECT_TRUE(client_->needs_begin_frames()); | |
2235 client_->Reset(); | |
2236 task_runner().RunPendingTasks(); // Run posted deadline. | |
2237 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); | |
2238 } | |
2239 | |
2240 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected. | |
2241 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) { | |
2242 scheduler_settings_.use_external_begin_frame_source = true; | |
2243 SetUpScheduler(true); | |
2244 | |
2245 // SetNeedsCommit should begin the frame on the next BeginImplFrame. | |
2246 scheduler_->SetNeedsCommit(); | |
2247 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | |
2248 client_->Reset(); | |
2249 | |
2250 // Trigger a frame draw. | |
2251 EXPECT_SCOPED(AdvanceFrame()); | |
2252 scheduler_->NotifyBeginMainFrameStarted(); | |
2253 scheduler_->NotifyReadyToCommit(); | |
2254 task_runner().RunPendingTasks(); | |
2255 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5); | |
2256 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 5); | |
2257 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 5); | |
2258 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5); | |
2259 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5); | |
2260 client_->Reset(); | |
2261 | |
2262 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) | |
2263 // and send a SendBeginMainFrameNotExpectedSoon. | |
2264 EXPECT_SCOPED(AdvanceFrame()); | |
2265 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); | |
2266 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2267 client_->Reset(); | |
2268 | |
2269 task_runner().RunPendingTasks(); // Run posted deadline. | |
2270 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); | |
2271 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); | |
2272 client_->Reset(); | |
2273 } | |
2274 | |
2275 } // namespace | |
2276 } // namespace cc | |
OLD | NEW |