Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(659)

Side by Side Diff: cc/scheduler/scheduler_unittest.cc

Issue 199523002: cc: Throttle swaps in Scheduler instead of OutputSurface (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rebase Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 #include "cc/scheduler/scheduler.h" 4 #include "cc/scheduler/scheduler.h"
5 5
6 #include <string> 6 #include <string>
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_vector.h" 10 #include "base/memory/scoped_vector.h"
(...skipping 22 matching lines...) Expand all
33 namespace { 33 namespace {
34 34
35 class FakeSchedulerClient; 35 class FakeSchedulerClient;
36 36
37 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler, 37 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
38 FakeSchedulerClient* client); 38 FakeSchedulerClient* client);
39 39
40 class FakeSchedulerClient : public SchedulerClient { 40 class FakeSchedulerClient : public SchedulerClient {
41 public: 41 public:
42 FakeSchedulerClient() 42 FakeSchedulerClient()
43 : needs_begin_impl_frame_(false) { 43 : needs_begin_impl_frame_(false), automatic_swap_ack_(true) {
44 Reset(); 44 Reset();
45 } 45 }
46 46
47 void Reset() { 47 void Reset() {
48 actions_.clear(); 48 actions_.clear();
49 states_.clear(); 49 states_.clear();
50 draw_will_happen_ = true; 50 draw_will_happen_ = true;
51 swap_will_happen_if_draw_happens_ = true; 51 swap_will_happen_if_draw_happens_ = true;
52 num_draws_ = 0; 52 num_draws_ = 0;
53 log_anticipated_draw_time_change_ = false; 53 log_anticipated_draw_time_change_ = false;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 bool HasAction(const char* action) const { 85 bool HasAction(const char* action) const {
86 return ActionIndex(action) >= 0; 86 return ActionIndex(action) >= 0;
87 } 87 }
88 88
89 void SetDrawWillHappen(bool draw_will_happen) { 89 void SetDrawWillHappen(bool draw_will_happen) {
90 draw_will_happen_ = draw_will_happen; 90 draw_will_happen_ = draw_will_happen;
91 } 91 }
92 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) { 92 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
93 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens; 93 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
94 } 94 }
95 void SetAutomaticSwapAck(bool automatic_swap_ack) {
96 automatic_swap_ack_ = automatic_swap_ack;
97 }
95 98
96 // SchedulerClient implementation. 99 // SchedulerClient implementation.
97 virtual void SetNeedsBeginFrame(bool enable) OVERRIDE { 100 virtual void SetNeedsBeginFrame(bool enable) OVERRIDE {
98 actions_.push_back("SetNeedsBeginFrame"); 101 actions_.push_back("SetNeedsBeginFrame");
99 states_.push_back(scheduler_->StateAsValue().release()); 102 states_.push_back(scheduler_->StateAsValue().release());
100 needs_begin_impl_frame_ = enable; 103 needs_begin_impl_frame_ = enable;
101 } 104 }
102 virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE { 105 virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
103 actions_.push_back("WillBeginImplFrame"); 106 actions_.push_back("WillBeginImplFrame");
104 states_.push_back(scheduler_->StateAsValue().release()); 107 states_.push_back(scheduler_->StateAsValue().release());
105 } 108 }
106 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE { 109 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
107 actions_.push_back("ScheduledActionSendBeginMainFrame"); 110 actions_.push_back("ScheduledActionSendBeginMainFrame");
108 states_.push_back(scheduler_->StateAsValue().release()); 111 states_.push_back(scheduler_->StateAsValue().release());
109 } 112 }
110 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible() 113 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
111 OVERRIDE { 114 OVERRIDE {
112 actions_.push_back("ScheduledActionDrawAndSwapIfPossible"); 115 actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
113 states_.push_back(scheduler_->StateAsValue().release()); 116 states_.push_back(scheduler_->StateAsValue().release());
114 num_draws_++; 117 num_draws_++;
115 bool did_readback = false; 118 bool did_readback = false;
116 DrawSwapReadbackResult::DrawResult result = 119 DrawSwapReadbackResult::DrawResult result =
117 draw_will_happen_ 120 draw_will_happen_
118 ? DrawSwapReadbackResult::DRAW_SUCCESS 121 ? DrawSwapReadbackResult::DRAW_SUCCESS
119 : DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS; 122 : DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
123 bool swap_will_happen =
124 draw_will_happen_ && swap_will_happen_if_draw_happens_;
125 if (swap_will_happen) {
126 scheduler_->DidSwapBuffers();
127 if (automatic_swap_ack_)
128 scheduler_->OnSwapBuffersComplete();
129 }
120 return DrawSwapReadbackResult( 130 return DrawSwapReadbackResult(
121 result, 131 result,
122 draw_will_happen_ && swap_will_happen_if_draw_happens_, 132 draw_will_happen_ && swap_will_happen_if_draw_happens_,
123 did_readback); 133 did_readback);
124 } 134 }
125 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE { 135 virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
126 actions_.push_back("ScheduledActionDrawAndSwapForced"); 136 actions_.push_back("ScheduledActionDrawAndSwapForced");
127 states_.push_back(scheduler_->StateAsValue().release()); 137 states_.push_back(scheduler_->StateAsValue().release());
128 bool did_swap = swap_will_happen_if_draw_happens_; 138 bool did_swap = swap_will_happen_if_draw_happens_;
129 bool did_readback = false; 139 bool did_readback = false;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE { 185 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
176 return base::TimeDelta(); 186 return base::TimeDelta();
177 } 187 }
178 188
179 virtual void DidBeginImplFrameDeadline() OVERRIDE {} 189 virtual void DidBeginImplFrameDeadline() OVERRIDE {}
180 190
181 protected: 191 protected:
182 bool needs_begin_impl_frame_; 192 bool needs_begin_impl_frame_;
183 bool draw_will_happen_; 193 bool draw_will_happen_;
184 bool swap_will_happen_if_draw_happens_; 194 bool swap_will_happen_if_draw_happens_;
195 bool automatic_swap_ack_;
185 int num_draws_; 196 int num_draws_;
186 bool log_anticipated_draw_time_change_; 197 bool log_anticipated_draw_time_change_;
187 base::TimeTicks posted_begin_impl_frame_deadline_; 198 base::TimeTicks posted_begin_impl_frame_deadline_;
188 std::vector<const char*> actions_; 199 std::vector<const char*> actions_;
189 ScopedVector<base::Value> states_; 200 ScopedVector<base::Value> states_;
190 scoped_ptr<Scheduler> scheduler_; 201 scoped_ptr<Scheduler> scheduler_;
191 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; 202 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
192 }; 203 };
193 204
194 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler, 205 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1301 scheduler->SetNeedsRedraw(); 1312 scheduler->SetNeedsRedraw();
1302 1313
1303 BeginFrameArgs frame_args = BeginFrameArgs::CreateForTesting(); 1314 BeginFrameArgs frame_args = BeginFrameArgs::CreateForTesting();
1304 frame_args.interval = base::TimeDelta::FromMilliseconds(1000); 1315 frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
1305 scheduler->BeginFrame(frame_args); 1316 scheduler->BeginFrame(frame_args);
1306 1317
1307 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1318 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1308 client.task_runner().RunPendingTasks(); // Run posted deadline. 1319 client.task_runner().RunPendingTasks(); // Run posted deadline.
1309 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); 1320 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1310 1321
1322 scheduler->DidSwapBuffers();
1323 scheduler->OnSwapBuffersComplete();
1324
1311 // At this point, we've drawn a frame. Start another commit, but hold off on 1325 // At this point, we've drawn a frame. Start another commit, but hold off on
1312 // the NotifyReadyToCommit for now. 1326 // the NotifyReadyToCommit for now.
1313 EXPECT_FALSE(scheduler->CommitPending()); 1327 EXPECT_FALSE(scheduler->CommitPending());
1314 scheduler->SetNeedsCommit(); 1328 scheduler->SetNeedsCommit();
1315 scheduler->BeginFrame(frame_args); 1329 scheduler->BeginFrame(frame_args);
1316 EXPECT_TRUE(scheduler->CommitPending()); 1330 EXPECT_TRUE(scheduler->CommitPending());
1317 1331
1332 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1333 // blocking on the renderer.
1334 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1335 client.task_runner().RunPendingTasks(); // Run posted deadline.
1336 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1337 scheduler->DidSwapBuffers();
1338
1318 // Spin the event loop a few times and make sure we get more 1339 // Spin the event loop a few times and make sure we get more
1319 // DidAnticipateDrawTimeChange calls every time. 1340 // DidAnticipateDrawTimeChange calls every time.
1320 int actions_so_far = client.num_actions_(); 1341 int actions_so_far = client.num_actions_();
1321 1342
1322 // Does three iterations to make sure that the timer is properly repeating. 1343 // Does three iterations to make sure that the timer is properly repeating.
1323 for (int i = 0; i < 3; ++i) { 1344 for (int i = 0; i < 3; ++i) {
1324 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(), 1345 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1325 client.task_runner().NextPendingTaskDelay().InMicroseconds()) 1346 client.task_runner().NextPendingTaskDelay().InMicroseconds())
1326 << *scheduler->StateAsValue(); 1347 << *scheduler->StateAsValue();
1327 client.task_runner().RunPendingTasks(); 1348 client.task_runner().RunPendingTasks();
(...skipping 10 matching lines...) Expand all
1338 client.task_runner().NextPendingTaskDelay().InMicroseconds()) 1359 client.task_runner().NextPendingTaskDelay().InMicroseconds())
1339 << *scheduler->StateAsValue(); 1360 << *scheduler->StateAsValue();
1340 client.task_runner().RunPendingTasks(); 1361 client.task_runner().RunPendingTasks();
1341 EXPECT_GT(client.num_actions_(), actions_so_far); 1362 EXPECT_GT(client.num_actions_(), actions_so_far);
1342 EXPECT_STREQ(client.Action(client.num_actions_() - 1), 1363 EXPECT_STREQ(client.Action(client.num_actions_() - 1),
1343 "DidAnticipatedDrawTimeChange"); 1364 "DidAnticipatedDrawTimeChange");
1344 actions_so_far = client.num_actions_(); 1365 actions_so_far = client.num_actions_();
1345 } 1366 }
1346 } 1367 }
1347 1368
1348 TEST(SchedulerTest, BeginRetroFrame) { 1369 TEST(SchedulerTest, BeginRetroFrameBasic) {
1349 FakeSchedulerClient client; 1370 FakeSchedulerClient client;
1350 SchedulerSettings scheduler_settings; 1371 SchedulerSettings scheduler_settings;
1351 Scheduler* scheduler = client.CreateScheduler(scheduler_settings); 1372 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
1352 scheduler->SetCanStart(); 1373 scheduler->SetCanStart();
1353 scheduler->SetVisible(true); 1374 scheduler->SetVisible(true);
1354 scheduler->SetCanDraw(true); 1375 scheduler->SetCanDraw(true);
1355 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); 1376 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1356 1377
1357 // SetNeedsCommit should begin the frame on the next BeginImplFrame. 1378 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1358 client.Reset(); 1379 client.Reset();
1359 scheduler->SetNeedsCommit(); 1380 scheduler->SetNeedsCommit();
1360 EXPECT_TRUE(client.needs_begin_impl_frame()); 1381 EXPECT_TRUE(client.needs_begin_impl_frame());
1361 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1382 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1362 client.Reset(); 1383 client.Reset();
1363 1384
1364 // Create a BeginFrame with a long deadline to avoid race conditions. 1385 // Create a BeginFrame with a long deadline to avoid race conditions.
1365 // This is the first BeginFrame, which will be handled immediately. 1386 // This is the first BeginFrame, which will be handled immediately.
1366 BeginFrameArgs args = BeginFrameArgs::CreateForTesting(); 1387 BeginFrameArgs args = BeginFrameArgs::CreateForTesting();
1367 args.deadline += base::TimeDelta::FromHours(1); 1388 args.deadline += base::TimeDelta::FromHours(1);
1368 scheduler->BeginFrame(args); 1389 scheduler->BeginFrame(args);
1369
1370 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); 1390 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1371 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); 1391 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1372 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1392 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1373 EXPECT_TRUE(client.needs_begin_impl_frame()); 1393 EXPECT_TRUE(client.needs_begin_impl_frame());
1374 client.Reset(); 1394 client.Reset();
1375 1395
1376 // Queue BeginFrames while we are still handling the previous BeginFrame. 1396 // Queue BeginFrames while we are still handling the previous BeginFrame.
1377 args.frame_time += base::TimeDelta::FromSeconds(1); 1397 args.frame_time += base::TimeDelta::FromSeconds(1);
1378 scheduler->BeginFrame(args); 1398 scheduler->BeginFrame(args);
1379 args.frame_time += base::TimeDelta::FromSeconds(1); 1399 args.frame_time += base::TimeDelta::FromSeconds(1);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1415 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); 1435 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1416 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); 1436 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1417 client.Reset(); 1437 client.Reset();
1418 1438
1419 client.task_runner().RunPendingTasks(); // Run posted deadline. 1439 client.task_runner().RunPendingTasks(); // Run posted deadline.
1420 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); 1440 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1421 EXPECT_FALSE(client.needs_begin_impl_frame()); 1441 EXPECT_FALSE(client.needs_begin_impl_frame());
1422 client.Reset(); 1442 client.Reset();
1423 } 1443 }
1424 1444
1445 TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) {
1446 FakeSchedulerClient client;
1447 SchedulerSettings scheduler_settings;
1448 Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
1449 scheduler->SetCanStart();
1450 scheduler->SetVisible(true);
1451 scheduler->SetCanDraw(true);
1452 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1453
1454 // To test swap ack throttling, this test disables automatic swap acks.
1455 scheduler->SetMaxSwapsPending(1);
1456 client.SetAutomaticSwapAck(false);
1457
1458 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1459 client.Reset();
1460 scheduler->SetNeedsCommit();
1461 EXPECT_TRUE(client.needs_begin_impl_frame());
1462 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1463 client.Reset();
1464
1465 // Create a BeginFrame with a long deadline to avoid race conditions.
1466 // This is the first BeginFrame, which will be handled immediately.
1467 BeginFrameArgs args = BeginFrameArgs::CreateForTesting();
1468 args.deadline += base::TimeDelta::FromHours(1);
1469 scheduler->BeginFrame(args);
1470 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1471 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1472 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1473 EXPECT_TRUE(client.needs_begin_impl_frame());
1474 client.Reset();
1475
1476 // Queue BeginFrame while we are still handling the previous BeginFrame.
1477 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1478 args.frame_time += base::TimeDelta::FromSeconds(1);
1479 scheduler->BeginFrame(args);
1480 EXPECT_EQ(0, client.num_actions_());
1481 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1482 client.Reset();
1483
1484 // NotifyReadyToCommit should trigger the pending commit and draw.
1485 scheduler->NotifyBeginMainFrameStarted();
1486 scheduler->NotifyReadyToCommit();
1487 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1488 EXPECT_TRUE(client.needs_begin_impl_frame());
1489 client.Reset();
1490
1491 // Swapping will put us into a swap throttled state.
1492 client.task_runner().RunPendingTasks(); // Run posted deadline.
1493 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
1494 EXPECT_ACTION("SetNeedsBeginFrame", client, 1, 2);
1495 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1496 EXPECT_TRUE(client.needs_begin_impl_frame());
1497 client.Reset();
1498
1499 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1500 // but not a BeginMainFrame or draw.
1501 scheduler->SetNeedsCommit();
1502 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1503 EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
1504 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1505 EXPECT_TRUE(client.needs_begin_impl_frame());
1506 client.Reset();
1507
1508 // Queue BeginFrame while we are still handling the previous BeginFrame.
1509 args.frame_time += base::TimeDelta::FromSeconds(1);
1510 scheduler->BeginFrame(args);
1511 EXPECT_EQ(0, client.num_actions_());
1512 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1513 EXPECT_TRUE(client.needs_begin_impl_frame());
1514 client.Reset();
1515
1516 // Take us out of a swap throttled state.
1517 scheduler->OnSwapBuffersComplete();
1518 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
1519 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1520 EXPECT_TRUE(client.needs_begin_impl_frame());
1521 client.Reset();
1522
1523 // BeginImplFrame deadline should draw.
1524 scheduler->SetNeedsRedraw();
1525 client.task_runner().RunPendingTasks(); // Run posted deadline.
1526 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
1527 EXPECT_ACTION("SetNeedsBeginFrame", client, 1, 2);
1528 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1529 EXPECT_TRUE(client.needs_begin_impl_frame());
1530 client.Reset();
1531 }
1532
1425 } // namespace 1533 } // namespace
1426 } // namespace cc 1534 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698