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

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

Issue 1133673004: cc: Heuristic for Renderer latency recovery (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: improve test readability and coverage Created 5 years, 5 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
« no previous file with comments | « cc/scheduler/scheduler_state_machine.cc ('k') | cc/test/scheduler_test_common.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 4
5 #include "cc/scheduler/scheduler.h" 5 #include "cc/scheduler/scheduler.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 scoped_ptr<FakeCompositorTimingHistory> fake_compositor_timing_history = 239 scoped_ptr<FakeCompositorTimingHistory> fake_compositor_timing_history =
240 FakeCompositorTimingHistory::Create(); 240 FakeCompositorTimingHistory::Create();
241 fake_compositor_timing_history_ = fake_compositor_timing_history.get(); 241 fake_compositor_timing_history_ = fake_compositor_timing_history.get();
242 242
243 scheduler_ = TestScheduler::Create( 243 scheduler_ = TestScheduler::Create(
244 now_src_.get(), client_.get(), scheduler_settings_, 0, 244 now_src_.get(), client_.get(), scheduler_settings_, 0,
245 task_runner_.get(), fake_external_begin_frame_source_.get(), 245 task_runner_.get(), fake_external_begin_frame_source_.get(),
246 fake_compositor_timing_history.Pass()); 246 fake_compositor_timing_history.Pass());
247 DCHECK(scheduler_); 247 DCHECK(scheduler_);
248 client_->set_scheduler(scheduler_.get()); 248 client_->set_scheduler(scheduler_.get());
249
250 // Use large estimates by default to avoid latency recovery
251 // in most tests.
252 base::TimeDelta one_second = base::TimeDelta::FromSeconds(1);
253 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
254 one_second);
255 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
256 one_second);
257 fake_compositor_timing_history_->SetDrawDurationEstimate(one_second);
258
249 return scheduler_.get(); 259 return scheduler_.get();
250 } 260 }
251 261
252 void CreateSchedulerAndInitSurface() { 262 void CreateSchedulerAndInitSurface() {
253 CreateScheduler(); 263 CreateScheduler();
254 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit()); 264 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
255 } 265 }
256 266
257 void SetUpScheduler(bool initSurface) { 267 void SetUpScheduler(bool initSurface) {
258 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface); 268 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 BeginFrameArgs args = 387 BeginFrameArgs args =
378 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); 388 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
379 fake_external_begin_frame_source_->TestOnBeginFrame(args); 389 fake_external_begin_frame_source_->TestOnBeginFrame(args);
380 return args; 390 return args;
381 } 391 }
382 392
383 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const { 393 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
384 return fake_external_begin_frame_source_.get(); 394 return fake_external_begin_frame_source_.get();
385 } 395 }
386 396
387 void MainFrameInHighLatencyMode( 397 void MainFrameInHighLatencyMode(bool should_send_begin_main_frame);
388 int64 begin_main_frame_to_commit_estimate_in_ms, 398 void ImplFrameInHighLatencySkipImplFrame(bool swap_ack_before_deadline);
389 int64 commit_to_activate_estimate_in_ms, 399 void ImplFrameInHighLatencyDontSkipImplFrame();
390 bool impl_latency_takes_priority,
391 bool should_send_begin_main_frame);
392 void BeginFramesNotFromClient(bool use_external_begin_frame_source, 400 void BeginFramesNotFromClient(bool use_external_begin_frame_source,
393 bool throttle_frame_production); 401 bool throttle_frame_production);
394 void BeginFramesNotFromClient_SwapThrottled( 402 void BeginFramesNotFromClient_SwapThrottled(
395 bool use_external_begin_frame_source, 403 bool use_external_begin_frame_source,
396 bool throttle_frame_production); 404 bool throttle_frame_production);
397 405
398 scoped_ptr<base::SimpleTestTickClock> now_src_; 406 scoped_ptr<base::SimpleTestTickClock> now_src_;
399 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; 407 scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
400 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_; 408 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_;
401 SchedulerSettings scheduler_settings_; 409 SchedulerSettings scheduler_settings_;
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after
1282 // Scheduler loses output surface, and stops waiting for ready to draw signal. 1290 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1283 client_->Reset(); 1291 client_->Reset();
1284 scheduler_->DidLoseOutputSurface(); 1292 scheduler_->DidLoseOutputSurface();
1285 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); 1293 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1286 task_runner().RunPendingTasks(); // Run posted deadline. 1294 task_runner().RunPendingTasks(); // Run posted deadline.
1287 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); 1295 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1288 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); 1296 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1289 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); 1297 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1290 } 1298 }
1291 1299
1292 void SchedulerTest::MainFrameInHighLatencyMode( 1300 void SchedulerTest::MainFrameInHighLatencyMode(
mithro-old 2015/07/08 00:54:51 nit: I think this could be named better. My thoug
1293 int64 begin_main_frame_to_commit_estimate_in_ms, 1301 bool expect_send_begin_main_frame) {
1294 int64 commit_to_activate_estimate_in_ms,
1295 bool impl_latency_takes_priority,
1296 bool should_send_begin_main_frame) {
1297 scheduler_settings_.use_external_begin_frame_source = true;
1298 SetUpScheduler(true);
1299
1300 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
1301 base::TimeDelta::FromMilliseconds(
1302 begin_main_frame_to_commit_estimate_in_ms));
1303 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1304 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
1305 fake_compositor_timing_history_->SetDrawDurationEstimate(
1306 base::TimeDelta::FromMilliseconds(1));
1307
1308 scheduler_->SetImplLatencyTakesPriority(impl_latency_takes_priority);
1309
1310 // Impl thread hits deadline before commit finishes. 1302 // Impl thread hits deadline before commit finishes.
1311 scheduler_->SetNeedsCommit(); 1303 scheduler_->SetNeedsCommit();
1312 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); 1304 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1313 EXPECT_SCOPED(AdvanceFrame()); 1305 EXPECT_SCOPED(AdvanceFrame());
1314 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); 1306 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1315 task_runner().RunPendingTasks(); // Run posted deadline. 1307 task_runner().RunPendingTasks(); // Run posted deadline.
1316 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); 1308 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1317 scheduler_->NotifyBeginMainFrameStarted(); 1309 scheduler_->NotifyBeginMainFrameStarted();
1318 scheduler_->NotifyReadyToCommit(); 1310 scheduler_->NotifyReadyToCommit();
1319 scheduler_->NotifyReadyToActivate(); 1311 scheduler_->NotifyReadyToActivate();
1320 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); 1312 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1321 EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame")); 1313 EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
1322 1314
1323 client_->Reset(); 1315 client_->Reset();
1324 scheduler_->SetNeedsCommit(); 1316 scheduler_->SetNeedsCommit();
1325 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); 1317 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1326 EXPECT_SCOPED(AdvanceFrame()); 1318 EXPECT_SCOPED(AdvanceFrame());
1327 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); 1319 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1328 task_runner().RunPendingTasks(); // Run posted deadline. 1320 task_runner().RunPendingTasks(); // Run posted deadline.
1329 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(), 1321 EXPECT_EQ(expect_send_begin_main_frame,
1330 should_send_begin_main_frame); 1322 scheduler_->MainThreadIsInHighLatencyMode());
1331 EXPECT_EQ(client_->HasAction("ScheduledActionSendBeginMainFrame"), 1323 EXPECT_EQ(expect_send_begin_main_frame,
1332 should_send_begin_main_frame); 1324 client_->HasAction("ScheduledActionSendBeginMainFrame"));
1325 }
1326
1327 TEST_F(SchedulerTest, SkipMainFrameIfHighLatencyAndCanDrawBeforeDeadline) {
mithro-old 2015/07/08 00:54:51 nit: s/IfHighLatency/IfLateCommit/ or maybe IfMiss
1328 scheduler_settings_.use_external_begin_frame_source = true;
1329 SetUpScheduler(true);
1330
1331 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1332 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1333
1334 bool expect_send_begin_main_frame = false;
1335 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame));
1336 }
1337
1338 TEST_F(SchedulerTest, DontSkipMainFrameInPreferImplLatencyMode) {
1339 scheduler_settings_.use_external_begin_frame_source = true;
1340 SetUpScheduler(true);
1341 scheduler_->SetImplLatencyTakesPriority(true);
1342
1343 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1344 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1345
1346 bool expect_send_begin_main_frame = true;
1347 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame));
1348 }
1349
1350 TEST_F(SchedulerTest, DontSkipMainFrameIfCommitEstimateTooLong) {
1351 scheduler_settings_.use_external_begin_frame_source = true;
1352 SetUpScheduler(true);
1353 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta());
mithro-old 2015/07/08 00:54:51 nit: It seems like it could be dangerous to be usi
1354 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
1355 base::TimeDelta::FromMilliseconds(16));
mithro-old 2015/07/08 00:54:51 nit: Should we use a larger value here?
1356 bool expect_send_begin_main_frame = true;
1357 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame));
1358 }
1359
1360 TEST_F(SchedulerTest, DontSkipMainFrameIfReadyToActivateEstimateTooLong) {
1361 scheduler_settings_.use_external_begin_frame_source = true;
1362 SetUpScheduler(true);
1363 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta());
1364 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1365 base::TimeDelta::FromMilliseconds(16));
1366 bool expect_send_begin_main_frame = true;
1367 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame));
1368 }
1369
1370 TEST_F(SchedulerTest, DontSkipMainFrameIfActivateEstimateTooLong) {
1371 scheduler_settings_.use_external_begin_frame_source = true;
1372 SetUpScheduler(true);
1373 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta());
1374 fake_compositor_timing_history_->SetActivateDurationEstimate(
1375 base::TimeDelta::FromMilliseconds(16));
1376 bool expect_send_begin_main_frame = true;
1377 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame));
1378 }
1379
1380 TEST_F(SchedulerTest, DontSkipMainFrameIfDrawEstimateTooLong) {
1381 scheduler_settings_.use_external_begin_frame_source = true;
1382 SetUpScheduler(true);
1383 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta());
1384 fake_compositor_timing_history_->SetDrawDurationEstimate(
1385 base::TimeDelta::FromMilliseconds(16));
1386 bool expect_send_begin_main_frame = true;
1387 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame));
1388 }
1389
1390 void SchedulerTest::ImplFrameInHighLatencySkipImplFrame(
mithro-old 2015/07/08 00:54:51 nit: Name - see comments above too.
1391 bool swap_ack_before_deadline) {
1392 // Set up client with specified estimates.
1393 scheduler_settings_.use_external_begin_frame_source = true;
1394 SetUpScheduler(true);
1395
1396 // Use estimates that indicate commit and activate can finish before the
1397 // deadline.
1398 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1399 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1400
1401 // To get into a high latency state, this test disables automatic swap acks.
1402 scheduler_->SetMaxSwapsPending(1);
1403 client_->SetAutomaticSwapAck(false);
1404
1405 // Draw and swap for first BeginFrame
1406 client_->Reset();
1407 scheduler_->SetNeedsCommit();
1408 scheduler_->SetNeedsRedraw();
1409 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1410 SendNextBeginFrame();
1411 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 4);
1412 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 4);
1413 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1414 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 4);
1415
1416 client_->Reset();
1417 scheduler_->NotifyBeginMainFrameStarted();
1418 scheduler_->NotifyReadyToCommit();
1419 scheduler_->NotifyReadyToActivate();
1420 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1421 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1422 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1423 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1424 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1425 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1426
1427 // Verify we skip every other frame if the swap ack consistently
1428 // comes back late.
1429 for (int i = 0; i < 10; i++) {
1430 // Not calling scheduler_->DidSwapBuffersComplete() until after next
1431 // BeginImplFrame puts the impl thread in high latency mode.
1432 client_->Reset();
1433 scheduler_->SetNeedsCommit();
1434 scheduler_->SetNeedsRedraw();
1435 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1436 SendNextBeginFrame();
1437 // Verify that we skip the BeginImplFrame
1438 EXPECT_NO_ACTION(client_);
1439 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1440 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1441
1442 // Verify that we do not perform any actions after we are no longer
1443 // swap throttled.
1444 // Also verify the scheduler logic that determines if we are in a high
mithro-old 2015/07/08 00:54:51 Where is the verification that this comment is ref
1445 // latency mode is immune to whether or not the swap ack comes back before
1446 // or after the deadline.
1447 client_->Reset();
1448 if (swap_ack_before_deadline) {
1449 scheduler_->DidSwapBuffersComplete();
1450 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1451 } else {
1452 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1453 scheduler_->DidSwapBuffersComplete();
1454 }
1455 EXPECT_NO_ACTION(client_);
1456
1457 // Verify that we start the next BeginImplFrame and continue normally
1458 // after having just skipped a BeginImplFrame.
1459 client_->Reset();
1460 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1461 scheduler_->SetNeedsCommit();
1462 scheduler_->SetNeedsRedraw();
1463 SendNextBeginFrame();
1464 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
1465 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
1466 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3);
1467
1468 client_->Reset();
1469 scheduler_->NotifyBeginMainFrameStarted();
1470 scheduler_->NotifyReadyToCommit();
1471 scheduler_->NotifyReadyToActivate();
1472 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1473 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1474 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1475 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1476 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1477 }
1333 } 1478 }
1334 1479
1335 TEST_F(SchedulerTest, 1480 TEST_F(SchedulerTest,
1336 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) { 1481 SkipSwapIfHighLatencyAndCanDrawBeforeDeadline_SwapAckThenDeadline) {
1337 // Set up client so that estimates indicate that we can commit and activate 1482 bool swap_ack_before_deadline = true;
1338 // before the deadline (~8ms by default). 1483 EXPECT_SCOPED(ImplFrameInHighLatencySkipImplFrame(swap_ack_before_deadline));
1339 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false)); 1484 }
1340 } 1485
1341 1486 TEST_F(SchedulerTest,
1342 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) { 1487 SkipSwapIfHighLatencyAndCanDrawBeforeDeadline_DeadlineThenSwapAck) {
1343 // Set up client so that estimates indicate that the commit cannot finish 1488 bool swap_ack_before_deadline = false;
1344 // before the deadline (~8ms by default). 1489 EXPECT_SCOPED(ImplFrameInHighLatencySkipImplFrame(swap_ack_before_deadline));
1345 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true)); 1490 }
1346 } 1491
1347 1492 void SchedulerTest::ImplFrameInHighLatencyDontSkipImplFrame() {
1348 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) { 1493 // To get into a high latency state, this test disables automatic swap acks.
1349 // Set up client so that estimates indicate that the activate cannot finish 1494 scheduler_->SetMaxSwapsPending(1);
1350 // before the deadline (~8ms by default). 1495 client_->SetAutomaticSwapAck(false);
1351 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true)); 1496
1352 } 1497 // Draw and swap for first BeginFrame
1353 1498 client_->Reset();
1354 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { 1499 scheduler_->SetNeedsCommit();
1355 // Set up client so that estimates indicate that we can commit and activate 1500 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1356 // before the deadline (~8ms by default), but also enable impl latency takes 1501 SendNextBeginFrame();
1357 // priority mode. 1502 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
1358 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true)); 1503 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3);
1504 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3);
1505
1506 client_->Reset();
1507 scheduler_->NotifyBeginMainFrameStarted();
1508 scheduler_->NotifyReadyToCommit();
1509 scheduler_->NotifyReadyToActivate();
1510 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1511 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1512 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1513 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1514 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1515 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1516
1517 // Verify impl thread consistently operates in high latency mode
1518 // without skipping any frames.
1519 for (int i = 0; i < 10; i++) {
1520 // Not calling scheduler_->DidSwapBuffersComplete() until after next frame
1521 // puts the impl thread in high latency mode.
1522 client_->Reset();
1523 scheduler_->SetNeedsCommit();
1524 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1525 SendNextBeginFrame();
1526 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1527 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1528 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1529
1530 client_->Reset();
1531 scheduler_->DidSwapBuffersComplete();
1532 scheduler_->NotifyBeginMainFrameStarted();
1533 scheduler_->NotifyReadyToCommit();
1534 scheduler_->NotifyReadyToActivate();
1535 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1536
1537 // Verify that we don't skip the actions of the BeginImplFrame
1538 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 0, 5);
1539 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 5);
1540 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 2, 5);
1541 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5);
1542 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5);
1543 }
1544 }
1545
1546 TEST_F(SchedulerTest, DontSkipImplFrameIfCommitEstimateTooLong) {
1547 scheduler_settings_.use_external_begin_frame_source = true;
1548 SetUpScheduler(true);
1549 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta());
1550 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
1551 base::TimeDelta::FromMilliseconds(16));
1552 EXPECT_SCOPED(ImplFrameInHighLatencyDontSkipImplFrame());
1553 }
1554
1555 TEST_F(SchedulerTest, DontSkipImplFrameIfReadyToActivateEstimateTooLong) {
1556 scheduler_settings_.use_external_begin_frame_source = true;
1557 SetUpScheduler(true);
1558 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta());
1559 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1560 base::TimeDelta::FromMilliseconds(16));
1561 EXPECT_SCOPED(ImplFrameInHighLatencyDontSkipImplFrame());
1562 }
1563
1564 TEST_F(SchedulerTest, DontSkipImplFrameIfActivateEstimateTooLong) {
1565 scheduler_settings_.use_external_begin_frame_source = true;
1566 SetUpScheduler(true);
1567 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta());
1568 fake_compositor_timing_history_->SetActivateDurationEstimate(
1569 base::TimeDelta::FromMilliseconds(16));
1570 EXPECT_SCOPED(ImplFrameInHighLatencyDontSkipImplFrame());
1571 }
1572
1573 TEST_F(SchedulerTest, DontSkipImplFrameIfDrawEstimateTooLong) {
1574 scheduler_settings_.use_external_begin_frame_source = true;
1575 SetUpScheduler(true);
1576 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta());
1577 fake_compositor_timing_history_->SetDrawDurationEstimate(
1578 base::TimeDelta::FromMilliseconds(16));
1579 EXPECT_SCOPED(ImplFrameInHighLatencyDontSkipImplFrame());
1580 }
1581
1582 TEST_F(SchedulerTest, MainAndSwapInHighLatencyMode) {
1583 // Set up client with custom estimates.
1584 // This test starts off with expensive estimates to prevent latency recovery
1585 // initially, then lowers the estimates to enable it once both the main
1586 // and impl threads are in a high latency mode.
1587 scheduler_settings_.use_external_begin_frame_source = true;
1588 SetUpScheduler(true);
1589
1590 auto slow_duration = base::TimeDelta::FromMilliseconds(16);
1591 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta());
1592 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration);
1593
1594 // To get into a high latency state, this test disables automatic swap acks.
1595 scheduler_->SetMaxSwapsPending(1);
1596 client_->SetAutomaticSwapAck(false);
1597
1598 // Impl thread hits deadline before commit finishes to make
1599 // MainThreadIsInHighLatencyMode true
1600 client_->Reset();
1601 scheduler_->SetNeedsCommit();
1602 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1603 EXPECT_SCOPED(AdvanceFrame());
1604 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1605 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1606 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1607 scheduler_->NotifyBeginMainFrameStarted();
1608 scheduler_->NotifyReadyToCommit();
1609 scheduler_->NotifyReadyToActivate();
1610 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1611
1612 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5);
1613 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5);
1614 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1615 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1616 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5);
1617
1618 // Draw and swap for first commit, start second commit.
1619 client_->Reset();
1620 scheduler_->SetNeedsCommit();
1621 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1622 EXPECT_SCOPED(AdvanceFrame());
1623 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1624 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1625 scheduler_->NotifyBeginMainFrameStarted();
1626 scheduler_->NotifyReadyToCommit();
1627 scheduler_->NotifyReadyToActivate();
1628
1629 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
1630 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 6);
1631 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6);
1632 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6);
1633 EXPECT_ACTION("ScheduledActionCommit", client_, 4, 6);
1634 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 5, 6);
1635
1636 // Don't call scheduler_->DidSwapBuffersComplete() until after next frame
1637 // to put the impl thread in a high latency mode.
1638 client_->Reset();
1639 scheduler_->SetNeedsCommit();
1640 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1641 EXPECT_SCOPED(AdvanceFrame());
1642 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1643 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1644 scheduler_->DidSwapBuffersComplete();
1645
1646 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1647 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1648 // Note: BeginMainFrame and swap are skipped here because of
1649 // swap ack backpressure, not because of latency recovery.
1650 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
1651 EXPECT_FALSE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1652
1653 // Lower estimates so that the scheduler will attempt latency recovery.
1654 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1655 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1656
1657 // Now that both threads are in a high latency mode, make sure we
1658 // skip the BeginMainFrame, then the BeginImplFrame, but not both
1659 // at the same time.
1660
1661 // Verify we skip BeginMainFrame first.
1662 client_->Reset();
1663 // Previous commit request is still outstanding.
1664 EXPECT_TRUE(scheduler_->NeedsCommit());
1665 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1666 SendNextBeginFrame();
1667 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1668 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1669
1670 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
1671 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
1672 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
1673 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
1674
1675 // Verify we skip the BeginImplFrame second.
1676 client_->Reset();
1677 // Previous commit request is still outstanding.
1678 EXPECT_TRUE(scheduler_->NeedsCommit());
1679 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1680 SendNextBeginFrame();
1681 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1682 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1683 scheduler_->DidSwapBuffersComplete();
1684 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1685
1686 EXPECT_NO_ACTION(client_);
1687
1688 // Then verify we operate in a low latency mode.
1689 client_->Reset();
1690 // Previous commit request is still outstanding.
1691 EXPECT_TRUE(scheduler_->NeedsCommit());
1692 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1693 SendNextBeginFrame();
1694 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1695 scheduler_->NotifyBeginMainFrameStarted();
1696 scheduler_->NotifyReadyToCommit();
1697 scheduler_->NotifyReadyToActivate();
1698 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1699 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1700 scheduler_->DidSwapBuffersComplete();
1701 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1702
1703 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
1704 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6);
1705 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6);
1706 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6);
1707 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6);
1708 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6);
1359 } 1709 }
1360 1710
1361 TEST_F( 1711 TEST_F(
1362 SchedulerTest, 1712 SchedulerTest,
1363 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { 1713 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) {
1364 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main 1714 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1365 // thread. This prevents the scheduler from receiving any pending swap acks. 1715 // thread. This prevents the scheduler from receiving any pending swap acks.
1366 1716
1367 // Since we are simulating a long commit, set up a client with draw duration 1717 // Since we are simulating a long commit, set up a client with draw duration
1368 // estimates that prevent skipping main frames to get to low latency mode. 1718 // estimates that prevent skipping main frames to get to low latency mode.
(...skipping 1586 matching lines...) Expand 10 before | Expand all | Expand 10 after
2955 scheduler_->SetImplLatencyTakesPriority(true); 3305 scheduler_->SetImplLatencyTakesPriority(true);
2956 scheduler_->SetChildrenNeedBeginFrames(true); 3306 scheduler_->SetChildrenNeedBeginFrames(true);
2957 3307
2958 EXPECT_SCOPED(AdvanceFrame()); 3308 EXPECT_SCOPED(AdvanceFrame());
2959 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); 3309 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
2960 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path); 3310 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path);
2961 } 3311 }
2962 3312
2963 } // namespace 3313 } // namespace
2964 } // namespace cc 3314 } // namespace cc
OLDNEW
« no previous file with comments | « cc/scheduler/scheduler_state_machine.cc ('k') | cc/test/scheduler_test_common.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698