OLD | NEW |
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 Loading... |
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 slow_duration = base::TimeDelta::FromSeconds(1); |
| 253 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration); |
| 254 |
249 return scheduler_.get(); | 255 return scheduler_.get(); |
250 } | 256 } |
251 | 257 |
252 void CreateSchedulerAndInitSurface() { | 258 void CreateSchedulerAndInitSurface() { |
253 CreateScheduler(); | 259 CreateScheduler(); |
254 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit()); | 260 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit()); |
255 } | 261 } |
256 | 262 |
257 void SetUpScheduler(bool initSurface) { | 263 void SetUpScheduler(bool initSurface) { |
258 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface); | 264 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 BeginFrameArgs args = | 383 BeginFrameArgs args = |
378 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); | 384 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); |
379 fake_external_begin_frame_source_->TestOnBeginFrame(args); | 385 fake_external_begin_frame_source_->TestOnBeginFrame(args); |
380 return args; | 386 return args; |
381 } | 387 } |
382 | 388 |
383 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const { | 389 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const { |
384 return fake_external_begin_frame_source_.get(); | 390 return fake_external_begin_frame_source_.get(); |
385 } | 391 } |
386 | 392 |
387 void MainFrameInHighLatencyMode( | 393 void CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame); |
388 int64 begin_main_frame_to_commit_estimate_in_ms, | 394 void ImplFrameSkippedAfterLateSwapAck_MainThreadMakesDeadline( |
389 int64 commit_to_activate_estimate_in_ms, | 395 bool swap_ack_before_deadline); |
390 bool impl_latency_takes_priority, | 396 void ImplFrameSkippedAfterLateSwapAck_MainThreadMissesDeadline(); |
391 bool should_send_begin_main_frame); | 397 void ImplFrameIsNotSkippedAfterLateSwapAck(); |
392 void BeginFramesNotFromClient(bool use_external_begin_frame_source, | 398 void BeginFramesNotFromClient(bool use_external_begin_frame_source, |
393 bool throttle_frame_production); | 399 bool throttle_frame_production); |
394 void BeginFramesNotFromClient_SwapThrottled( | 400 void BeginFramesNotFromClient_SwapThrottled( |
395 bool use_external_begin_frame_source, | 401 bool use_external_begin_frame_source, |
396 bool throttle_frame_production); | 402 bool throttle_frame_production); |
397 | 403 |
398 scoped_ptr<base::SimpleTestTickClock> now_src_; | 404 scoped_ptr<base::SimpleTestTickClock> now_src_; |
399 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; | 405 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; |
400 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_; | 406 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_; |
401 SchedulerSettings scheduler_settings_; | 407 SchedulerSettings scheduler_settings_; |
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1282 // Scheduler loses output surface, and stops waiting for ready to draw signal. | 1288 // Scheduler loses output surface, and stops waiting for ready to draw signal. |
1283 client_->Reset(); | 1289 client_->Reset(); |
1284 scheduler_->DidLoseOutputSurface(); | 1290 scheduler_->DidLoseOutputSurface(); |
1285 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | 1291 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
1286 task_runner().RunPendingTasks(); // Run posted deadline. | 1292 task_runner().RunPendingTasks(); // Run posted deadline. |
1287 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); | 1293 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); |
1288 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); | 1294 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); |
1289 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); | 1295 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); |
1290 } | 1296 } |
1291 | 1297 |
1292 void SchedulerTest::MainFrameInHighLatencyMode( | 1298 void SchedulerTest::CheckMainFrameSkippedAfterLateCommit( |
1293 int64 begin_main_frame_to_commit_estimate_in_ms, | 1299 bool expect_send_begin_main_frame) { |
1294 int64 commit_to_activate_estimate_in_ms, | 1300 // Impl thread hits deadline before commit finishes. |
1295 bool impl_latency_takes_priority, | 1301 scheduler_->SetNeedsCommit(); |
1296 bool should_send_begin_main_frame) { | 1302 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
1297 scheduler_settings_.use_external_begin_frame_source = true; | 1303 EXPECT_SCOPED(AdvanceFrame()); |
1298 SetUpScheduler(true); | 1304 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
1299 | 1305 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1306 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1307 scheduler_->NotifyBeginMainFrameStarted(); |
| 1308 scheduler_->NotifyReadyToCommit(); |
| 1309 scheduler_->NotifyReadyToActivate(); |
| 1310 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); |
| 1311 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); |
| 1312 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); |
| 1313 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); |
| 1314 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5); |
| 1315 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1316 |
| 1317 client_->Reset(); |
| 1318 scheduler_->SetNeedsCommit(); |
| 1319 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1320 EXPECT_SCOPED(AdvanceFrame()); |
| 1321 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1322 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1323 EXPECT_EQ(expect_send_begin_main_frame, |
| 1324 scheduler_->MainThreadIsInHighLatencyMode()); |
| 1325 EXPECT_EQ(expect_send_begin_main_frame, |
| 1326 client_->HasAction("ScheduledActionSendBeginMainFrame")); |
| 1327 } |
| 1328 |
| 1329 TEST_F(SchedulerTest, MainFrameSkippedAfterLateCommit) { |
| 1330 scheduler_settings_.use_external_begin_frame_source = true; |
| 1331 SetUpScheduler(true); |
| 1332 |
| 1333 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1334 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1335 |
| 1336 bool expect_send_begin_main_frame = false; |
| 1337 EXPECT_SCOPED( |
| 1338 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); |
| 1339 } |
| 1340 |
| 1341 TEST_F(SchedulerTest, |
| 1342 MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode) { |
| 1343 scheduler_settings_.use_external_begin_frame_source = true; |
| 1344 SetUpScheduler(true); |
| 1345 scheduler_->SetImplLatencyTakesPriority(true); |
| 1346 |
| 1347 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1348 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1349 |
| 1350 bool expect_send_begin_main_frame = true; |
| 1351 EXPECT_SCOPED( |
| 1352 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); |
| 1353 } |
| 1354 |
| 1355 TEST_F(SchedulerTest, |
| 1356 MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong) { |
| 1357 scheduler_settings_.use_external_begin_frame_source = true; |
| 1358 SetUpScheduler(true); |
| 1359 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1360 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1361 auto slow_duration = base::TimeDelta::FromSeconds(1); |
1300 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | 1362 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( |
1301 base::TimeDelta::FromMilliseconds( | 1363 slow_duration); |
1302 begin_main_frame_to_commit_estimate_in_ms)); | 1364 |
| 1365 bool expect_send_begin_main_frame = true; |
| 1366 EXPECT_SCOPED( |
| 1367 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); |
| 1368 } |
| 1369 |
| 1370 TEST_F(SchedulerTest, |
| 1371 MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong) { |
| 1372 scheduler_settings_.use_external_begin_frame_source = true; |
| 1373 SetUpScheduler(true); |
| 1374 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1375 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1376 auto slow_duration = base::TimeDelta::FromSeconds(1); |
1303 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | 1377 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( |
1304 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms)); | 1378 slow_duration); |
1305 fake_compositor_timing_history_->SetDrawDurationEstimate( | 1379 |
1306 base::TimeDelta::FromMilliseconds(1)); | 1380 bool expect_send_begin_main_frame = true; |
1307 | 1381 EXPECT_SCOPED( |
1308 scheduler_->SetImplLatencyTakesPriority(impl_latency_takes_priority); | 1382 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); |
1309 | 1383 } |
1310 // Impl thread hits deadline before commit finishes. | 1384 |
| 1385 TEST_F(SchedulerTest, |
| 1386 MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong) { |
| 1387 scheduler_settings_.use_external_begin_frame_source = true; |
| 1388 SetUpScheduler(true); |
| 1389 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1390 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1391 auto slow_duration = base::TimeDelta::FromSeconds(1); |
| 1392 fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration); |
| 1393 |
| 1394 bool expect_send_begin_main_frame = true; |
| 1395 EXPECT_SCOPED( |
| 1396 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); |
| 1397 } |
| 1398 |
| 1399 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong) { |
| 1400 scheduler_settings_.use_external_begin_frame_source = true; |
| 1401 SetUpScheduler(true); |
| 1402 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1403 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1404 auto slow_duration = base::TimeDelta::FromSeconds(1); |
| 1405 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration); |
| 1406 |
| 1407 bool expect_send_begin_main_frame = true; |
| 1408 EXPECT_SCOPED( |
| 1409 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); |
| 1410 } |
| 1411 |
| 1412 void SchedulerTest::ImplFrameSkippedAfterLateSwapAck_MainThreadMakesDeadline( |
| 1413 bool swap_ack_before_deadline) { |
| 1414 // To get into a high latency state, this test disables automatic swap acks. |
| 1415 scheduler_->SetMaxSwapsPending(1); |
| 1416 client_->SetAutomaticSwapAck(false); |
| 1417 |
| 1418 // Draw and swap for first BeginFrame |
| 1419 client_->Reset(); |
| 1420 scheduler_->SetNeedsCommit(); |
| 1421 scheduler_->SetNeedsRedraw(); |
| 1422 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1423 SendNextBeginFrame(); |
| 1424 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 4); |
| 1425 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 4); |
| 1426 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); |
| 1427 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 4); |
| 1428 |
| 1429 client_->Reset(); |
| 1430 scheduler_->NotifyBeginMainFrameStarted(); |
| 1431 scheduler_->NotifyReadyToCommit(); |
| 1432 scheduler_->NotifyReadyToActivate(); |
| 1433 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1434 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1435 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); |
| 1436 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); |
| 1437 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); |
| 1438 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); |
| 1439 |
| 1440 // Verify we skip every other frame if the swap ack consistently |
| 1441 // comes back late. |
| 1442 for (int i = 0; i < 10; i++) { |
| 1443 // Not calling scheduler_->DidSwapBuffersComplete() until after next |
| 1444 // BeginImplFrame puts the impl thread in high latency mode. |
| 1445 client_->Reset(); |
| 1446 scheduler_->SetNeedsCommit(); |
| 1447 scheduler_->SetNeedsRedraw(); |
| 1448 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1449 SendNextBeginFrame(); |
| 1450 // Verify that we skip the BeginImplFrame |
| 1451 EXPECT_NO_ACTION(client_); |
| 1452 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1453 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1454 |
| 1455 // Verify that we do not perform any actions after we are no longer |
| 1456 // swap throttled. |
| 1457 client_->Reset(); |
| 1458 if (swap_ack_before_deadline) { |
| 1459 // It shouldn't matter if the swap ack comes back before the deadline... |
| 1460 scheduler_->DidSwapBuffersComplete(); |
| 1461 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1462 } else { |
| 1463 // ... or after the deadline. |
| 1464 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1465 scheduler_->DidSwapBuffersComplete(); |
| 1466 } |
| 1467 EXPECT_NO_ACTION(client_); |
| 1468 |
| 1469 // Verify that we start the next BeginImplFrame and continue normally |
| 1470 // after having just skipped a BeginImplFrame. |
| 1471 client_->Reset(); |
| 1472 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1473 SendNextBeginFrame(); |
| 1474 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); |
| 1475 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); |
| 1476 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); |
| 1477 |
| 1478 client_->Reset(); |
| 1479 scheduler_->NotifyBeginMainFrameStarted(); |
| 1480 scheduler_->NotifyReadyToCommit(); |
| 1481 scheduler_->NotifyReadyToActivate(); |
| 1482 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1483 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); |
| 1484 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); |
| 1485 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); |
| 1486 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); |
| 1487 } |
| 1488 } |
| 1489 |
| 1490 TEST_F(SchedulerTest, |
| 1491 ImplFrameSkippedAfterLateSwapAck_FastEstimates_SwapAckThenDeadline) { |
| 1492 scheduler_settings_.use_external_begin_frame_source = true; |
| 1493 SetUpScheduler(true); |
| 1494 |
| 1495 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1496 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1497 |
| 1498 bool swap_ack_before_deadline = true; |
| 1499 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck_MainThreadMakesDeadline( |
| 1500 swap_ack_before_deadline)); |
| 1501 } |
| 1502 |
| 1503 TEST_F(SchedulerTest, |
| 1504 ImplFrameSkippedAfterLateSwapAck_FastEstimates_DeadlineThenSwapAck) { |
| 1505 scheduler_settings_.use_external_begin_frame_source = true; |
| 1506 SetUpScheduler(true); |
| 1507 |
| 1508 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1509 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1510 |
| 1511 bool swap_ack_before_deadline = false; |
| 1512 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck_MainThreadMakesDeadline( |
| 1513 swap_ack_before_deadline)); |
| 1514 } |
| 1515 |
| 1516 TEST_F(SchedulerTest, |
| 1517 ImplFrameSkippedAfterLateSwapAck_ImplLatencyTakesPriority) { |
| 1518 scheduler_settings_.use_external_begin_frame_source = true; |
| 1519 SetUpScheduler(true); |
| 1520 |
| 1521 // Even if every estimate related to the main thread is slow, we should |
| 1522 // still expect to recover impl thread latency if the draw is fast and we |
| 1523 // are in impl latency takes priority. |
| 1524 scheduler_->SetImplLatencyTakesPriority(true); |
| 1525 auto slow_duration = base::TimeDelta::FromSeconds(1); |
| 1526 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration); |
| 1527 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1528 fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration); |
| 1529 |
| 1530 bool swap_ack_before_deadline = false; |
| 1531 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck_MainThreadMakesDeadline( |
| 1532 swap_ack_before_deadline)); |
| 1533 } |
| 1534 |
| 1535 TEST_F(SchedulerTest, |
| 1536 ImplFrameSkippedAfterLateSwapAck_ActiveTreeNeedsFirstDraw) { |
| 1537 // This test runs with the main thread such that it always misses the |
| 1538 // deadline, but fast enough such that there's a new commit for the next |
| 1539 // BeginFrame. |
| 1540 scheduler_settings_.use_external_begin_frame_source = true; |
| 1541 SetUpScheduler(true); |
| 1542 |
| 1543 // Even if every estimate related to the main thread is slow, we should |
| 1544 // still expect to recover impl thread latency if we consistently have |
| 1545 // a new active tree ready at the BeginFrame. |
| 1546 auto slow_duration = base::TimeDelta::FromSeconds(1); |
| 1547 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration); |
| 1548 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1549 fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration); |
| 1550 |
| 1551 // To get into a high latency state, this test disables automatic swap acks. |
| 1552 scheduler_->SetMaxSwapsPending(1); |
| 1553 client_->SetAutomaticSwapAck(false); |
| 1554 |
| 1555 // Impl thread hits deadline before commit finishes to make |
| 1556 // MainThreadIsInHighLatencyMode true |
| 1557 client_->Reset(); |
| 1558 scheduler_->SetNeedsCommit(); |
| 1559 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1560 SendNextBeginFrame(); |
| 1561 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1562 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1563 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1564 scheduler_->NotifyBeginMainFrameStarted(); |
| 1565 scheduler_->NotifyReadyToCommit(); |
| 1566 scheduler_->NotifyReadyToActivate(); |
| 1567 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1568 |
| 1569 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); |
| 1570 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); |
| 1571 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); |
| 1572 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); |
| 1573 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5); |
| 1574 |
| 1575 // Draw and swap for first commit, start second commit. |
| 1576 client_->Reset(); |
| 1577 scheduler_->SetNeedsCommit(); |
| 1578 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1579 SendNextBeginFrame(); |
| 1580 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1581 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1582 scheduler_->NotifyBeginMainFrameStarted(); |
| 1583 scheduler_->NotifyReadyToCommit(); |
| 1584 scheduler_->NotifyReadyToActivate(); |
| 1585 |
| 1586 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); |
| 1587 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 6); |
| 1588 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6); |
| 1589 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6); |
| 1590 EXPECT_ACTION("ScheduledActionCommit", client_, 4, 6); |
| 1591 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 5, 6); |
| 1592 |
| 1593 // Verify we skip every other frame if the swap ack consistently |
| 1594 // comes back late. |
| 1595 for (int i = 0; i < 10; i++) { |
| 1596 // Not calling scheduler_->DidSwapBuffersComplete() until after next |
| 1597 // BeginImplFrame puts the impl thread in high latency mode. |
| 1598 client_->Reset(); |
| 1599 scheduler_->SetNeedsCommit(); |
| 1600 scheduler_->SetNeedsRedraw(); |
| 1601 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1602 SendNextBeginFrame(); |
| 1603 // Verify that we skip the BeginImplFrame |
| 1604 EXPECT_NO_ACTION(client_); |
| 1605 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1606 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1607 EXPECT_TRUE(scheduler_->WasSwapThrottledAtLastBeginFrame()); |
| 1608 |
| 1609 // Verify that we do not perform any actions after we are no longer |
| 1610 // swap throttled. |
| 1611 client_->Reset(); |
| 1612 scheduler_->DidSwapBuffersComplete(); |
| 1613 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1614 EXPECT_NO_ACTION(client_); |
| 1615 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1616 |
| 1617 // Verify that we start the next BeginImplFrame and continue normally |
| 1618 // after having just skipped a BeginImplFrame. |
| 1619 client_->Reset(); |
| 1620 SendNextBeginFrame(); |
| 1621 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); |
| 1622 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); |
| 1623 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); |
| 1624 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1625 EXPECT_FALSE(scheduler_->WasSwapThrottledAtLastBeginFrame()); |
| 1626 |
| 1627 client_->Reset(); |
| 1628 scheduler_->NotifyBeginMainFrameStarted(); |
| 1629 scheduler_->NotifyReadyToCommit(); |
| 1630 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1631 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3); |
| 1632 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); |
| 1633 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3); |
| 1634 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1635 |
| 1636 // Activate after the deadline so there's a new active tree |
| 1637 // for the next BeginFrame. |
| 1638 client_->Reset(); |
| 1639 scheduler_->NotifyReadyToActivate(); |
| 1640 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); |
| 1641 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1642 } |
| 1643 } |
| 1644 |
| 1645 TEST_F(SchedulerTest, |
| 1646 ImplFrameSkippedAfterLateSwapAck_OnlyImplSideUpdatesExpected) { |
| 1647 // This tests that we recover impl thread latency when there are no commits. |
| 1648 scheduler_settings_.use_external_begin_frame_source = true; |
| 1649 SetUpScheduler(true); |
| 1650 |
| 1651 // To get into a high latency state, this test disables automatic swap acks. |
| 1652 scheduler_->SetMaxSwapsPending(1); |
| 1653 client_->SetAutomaticSwapAck(false); |
| 1654 |
| 1655 // Even if every estimate related to the main thread is slow, we should |
| 1656 // still expect to recover impl thread latency if there are no commits from |
| 1657 // the main thread. |
| 1658 auto slow_duration = base::TimeDelta::FromSeconds(1); |
| 1659 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration); |
| 1660 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1661 fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration); |
| 1662 |
| 1663 // Draw and swap for first BeginFrame |
| 1664 client_->Reset(); |
| 1665 scheduler_->SetNeedsRedraw(); |
| 1666 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1667 SendNextBeginFrame(); |
| 1668 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3); |
| 1669 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); |
| 1670 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 3); |
| 1671 |
| 1672 client_->Reset(); |
| 1673 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1674 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1675 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); |
| 1676 |
| 1677 // Verify we skip every other frame if the swap ack consistently |
| 1678 // comes back late. |
| 1679 for (int i = 0; i < 10; i++) { |
| 1680 // Not calling scheduler_->DidSwapBuffersComplete() until after next |
| 1681 // BeginImplFrame puts the impl thread in high latency mode. |
| 1682 client_->Reset(); |
| 1683 scheduler_->SetNeedsRedraw(); |
| 1684 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1685 SendNextBeginFrame(); |
| 1686 // Verify that we skip the BeginImplFrame |
| 1687 EXPECT_NO_ACTION(client_); |
| 1688 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1689 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1690 |
| 1691 // Verify that we do not perform any actions after we are no longer |
| 1692 // swap throttled. |
| 1693 client_->Reset(); |
| 1694 scheduler_->DidSwapBuffersComplete(); |
| 1695 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1696 EXPECT_NO_ACTION(client_); |
| 1697 |
| 1698 // Verify that we start the next BeginImplFrame and continue normally |
| 1699 // after having just skipped a BeginImplFrame. |
| 1700 client_->Reset(); |
| 1701 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1702 SendNextBeginFrame(); |
| 1703 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); |
| 1704 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); |
| 1705 |
| 1706 client_->Reset(); |
| 1707 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1708 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); |
| 1709 } |
| 1710 } |
| 1711 |
| 1712 void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() { |
| 1713 // To get into a high latency state, this test disables automatic swap acks. |
| 1714 scheduler_->SetMaxSwapsPending(1); |
| 1715 client_->SetAutomaticSwapAck(false); |
| 1716 |
| 1717 // Draw and swap for first BeginFrame |
| 1718 client_->Reset(); |
| 1719 scheduler_->SetNeedsCommit(); |
| 1720 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1721 SendNextBeginFrame(); |
| 1722 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3); |
| 1723 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); |
| 1724 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); |
| 1725 |
| 1726 client_->Reset(); |
| 1727 scheduler_->NotifyBeginMainFrameStarted(); |
| 1728 scheduler_->NotifyReadyToCommit(); |
| 1729 scheduler_->NotifyReadyToActivate(); |
| 1730 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1731 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1732 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); |
| 1733 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); |
| 1734 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); |
| 1735 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); |
| 1736 |
| 1737 // Verify impl thread consistently operates in high latency mode |
| 1738 // without skipping any frames. |
| 1739 for (int i = 0; i < 10; i++) { |
| 1740 // Not calling scheduler_->DidSwapBuffersComplete() until after next frame |
| 1741 // puts the impl thread in high latency mode. |
| 1742 client_->Reset(); |
| 1743 scheduler_->SetNeedsCommit(); |
| 1744 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1745 SendNextBeginFrame(); |
| 1746 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); |
| 1747 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1748 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1749 |
| 1750 client_->Reset(); |
| 1751 scheduler_->DidSwapBuffersComplete(); |
| 1752 scheduler_->NotifyBeginMainFrameStarted(); |
| 1753 scheduler_->NotifyReadyToCommit(); |
| 1754 scheduler_->NotifyReadyToActivate(); |
| 1755 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1756 |
| 1757 // Verify that we don't skip the actions of the BeginImplFrame |
| 1758 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 0, 5); |
| 1759 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 5); |
| 1760 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 2, 5); |
| 1761 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5); |
| 1762 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5); |
| 1763 } |
| 1764 } |
| 1765 |
| 1766 TEST_F(SchedulerTest, |
| 1767 ImplFrameIsNotSkippedAfterLateSwapAck_CommitEstimateTooLong) { |
| 1768 scheduler_settings_.use_external_begin_frame_source = true; |
| 1769 SetUpScheduler(true); |
| 1770 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1771 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1772 auto slow_duration = base::TimeDelta::FromSeconds(1); |
| 1773 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( |
| 1774 slow_duration); |
| 1775 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); |
| 1776 } |
| 1777 |
| 1778 TEST_F(SchedulerTest, |
| 1779 ImplFrameIsNotSkippedAfterLateSwapAck_ReadyToActivateEstimateTooLong) { |
| 1780 scheduler_settings_.use_external_begin_frame_source = true; |
| 1781 SetUpScheduler(true); |
| 1782 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1783 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1784 auto slow_duration = base::TimeDelta::FromSeconds(1); |
| 1785 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( |
| 1786 slow_duration); |
| 1787 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); |
| 1788 } |
| 1789 |
| 1790 TEST_F(SchedulerTest, |
| 1791 ImplFrameIsNotSkippedAfterLateSwapAck_ActivateEstimateTooLong) { |
| 1792 scheduler_settings_.use_external_begin_frame_source = true; |
| 1793 SetUpScheduler(true); |
| 1794 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1795 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1796 auto slow_duration = base::TimeDelta::FromSeconds(1); |
| 1797 fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration); |
| 1798 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); |
| 1799 } |
| 1800 |
| 1801 TEST_F(SchedulerTest, |
| 1802 ImplFrameIsNotSkippedAfterLateSwapAck_DrawEstimateTooLong) { |
| 1803 scheduler_settings_.use_external_begin_frame_source = true; |
| 1804 SetUpScheduler(true); |
| 1805 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1806 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1807 auto slow_duration = base::TimeDelta::FromSeconds(1); |
| 1808 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration); |
| 1809 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); |
| 1810 } |
| 1811 |
| 1812 TEST_F(SchedulerTest, |
| 1813 MainFrameThenImplFrameSkippedAfterLateCommitAndLateSwapAck) { |
| 1814 // Set up client with custom estimates. |
| 1815 // This test starts off with expensive estimates to prevent latency recovery |
| 1816 // initially, then lowers the estimates to enable it once both the main |
| 1817 // and impl threads are in a high latency mode. |
| 1818 scheduler_settings_.use_external_begin_frame_source = true; |
| 1819 SetUpScheduler(true); |
| 1820 |
| 1821 auto slow_duration = base::TimeDelta::FromSeconds(1); |
| 1822 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration); |
| 1823 |
| 1824 // To get into a high latency state, this test disables automatic swap acks. |
| 1825 scheduler_->SetMaxSwapsPending(1); |
| 1826 client_->SetAutomaticSwapAck(false); |
| 1827 |
| 1828 // Impl thread hits deadline before commit finishes to make |
| 1829 // MainThreadIsInHighLatencyMode true |
| 1830 client_->Reset(); |
1311 scheduler_->SetNeedsCommit(); | 1831 scheduler_->SetNeedsCommit(); |
1312 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | 1832 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
1313 EXPECT_SCOPED(AdvanceFrame()); | 1833 EXPECT_SCOPED(AdvanceFrame()); |
1314 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | 1834 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
1315 task_runner().RunPendingTasks(); // Run posted deadline. | 1835 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
1316 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | 1836 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
1317 scheduler_->NotifyBeginMainFrameStarted(); | 1837 scheduler_->NotifyBeginMainFrameStarted(); |
1318 scheduler_->NotifyReadyToCommit(); | 1838 scheduler_->NotifyReadyToCommit(); |
1319 scheduler_->NotifyReadyToActivate(); | 1839 scheduler_->NotifyReadyToActivate(); |
1320 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | 1840 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
1321 EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame")); | 1841 |
1322 | 1842 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); |
| 1843 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); |
| 1844 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); |
| 1845 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); |
| 1846 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5); |
| 1847 |
| 1848 // Draw and swap for first commit, start second commit. |
1323 client_->Reset(); | 1849 client_->Reset(); |
1324 scheduler_->SetNeedsCommit(); | 1850 scheduler_->SetNeedsCommit(); |
1325 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | 1851 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
1326 EXPECT_SCOPED(AdvanceFrame()); | 1852 EXPECT_SCOPED(AdvanceFrame()); |
1327 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | 1853 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
1328 task_runner().RunPendingTasks(); // Run posted deadline. | 1854 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
1329 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(), | 1855 scheduler_->NotifyBeginMainFrameStarted(); |
1330 should_send_begin_main_frame); | 1856 scheduler_->NotifyReadyToCommit(); |
1331 EXPECT_EQ(client_->HasAction("ScheduledActionSendBeginMainFrame"), | 1857 scheduler_->NotifyReadyToActivate(); |
1332 should_send_begin_main_frame); | 1858 |
1333 } | 1859 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); |
1334 | 1860 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 6); |
1335 TEST_F(SchedulerTest, | 1861 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6); |
1336 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) { | 1862 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6); |
1337 // Set up client so that estimates indicate that we can commit and activate | 1863 EXPECT_ACTION("ScheduledActionCommit", client_, 4, 6); |
1338 // before the deadline (~8ms by default). | 1864 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 5, 6); |
1339 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false)); | 1865 |
1340 } | 1866 // Don't call scheduler_->DidSwapBuffersComplete() until after next frame |
1341 | 1867 // to put the impl thread in a high latency mode. |
1342 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) { | 1868 client_->Reset(); |
1343 // Set up client so that estimates indicate that the commit cannot finish | 1869 scheduler_->SetNeedsCommit(); |
1344 // before the deadline (~8ms by default). | 1870 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
1345 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true)); | 1871 EXPECT_SCOPED(AdvanceFrame()); |
1346 } | 1872 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
1347 | 1873 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
1348 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) { | 1874 |
1349 // Set up client so that estimates indicate that the activate cannot finish | 1875 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); |
1350 // before the deadline (~8ms by default). | 1876 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); |
1351 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true)); | 1877 // Note: BeginMainFrame and swap are skipped here because of |
1352 } | 1878 // swap ack backpressure, not because of latency recovery. |
1353 | 1879 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame")); |
1354 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { | 1880 EXPECT_FALSE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); |
1355 // Set up client so that estimates indicate that we can commit and activate | 1881 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
1356 // before the deadline (~8ms by default), but also enable impl latency takes | 1882 EXPECT_TRUE(scheduler_->WasSwapThrottledAtLastBeginFrame()); |
1357 // priority mode. | 1883 |
1358 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true)); | 1884 // Lower estimates so that the scheduler will attempt latency recovery. |
| 1885 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1886 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1887 |
| 1888 // Now that both threads are in a high latency mode, make sure we |
| 1889 // skip the BeginMainFrame, then the BeginImplFrame, but not both |
| 1890 // at the same time. |
| 1891 |
| 1892 // Verify we skip BeginMainFrame first. |
| 1893 client_->Reset(); |
| 1894 // Previous commit request is still outstanding. |
| 1895 EXPECT_TRUE(scheduler_->NeedsCommit()); |
| 1896 SendNextBeginFrame(); |
| 1897 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1898 EXPECT_TRUE(scheduler_->WasSwapThrottledAtLastBeginFrame()); |
| 1899 scheduler_->DidSwapBuffersComplete(); |
| 1900 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1901 |
| 1902 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1903 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); |
| 1904 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); |
| 1905 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3); |
| 1906 |
| 1907 // Verify we skip the BeginImplFrame second. |
| 1908 client_->Reset(); |
| 1909 // Previous commit request is still outstanding. |
| 1910 EXPECT_TRUE(scheduler_->NeedsCommit()); |
| 1911 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1912 SendNextBeginFrame(); |
| 1913 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1914 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1915 scheduler_->DidSwapBuffersComplete(); |
| 1916 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1917 |
| 1918 EXPECT_NO_ACTION(client_); |
| 1919 |
| 1920 // Then verify we operate in a low latency mode. |
| 1921 client_->Reset(); |
| 1922 // Previous commit request is still outstanding. |
| 1923 EXPECT_TRUE(scheduler_->NeedsCommit()); |
| 1924 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1925 SendNextBeginFrame(); |
| 1926 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1927 scheduler_->NotifyBeginMainFrameStarted(); |
| 1928 scheduler_->NotifyReadyToCommit(); |
| 1929 scheduler_->NotifyReadyToActivate(); |
| 1930 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1931 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1932 scheduler_->DidSwapBuffersComplete(); |
| 1933 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1934 |
| 1935 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); |
| 1936 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6); |
| 1937 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6); |
| 1938 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6); |
| 1939 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6); |
| 1940 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6); |
1359 } | 1941 } |
1360 | 1942 |
1361 TEST_F( | 1943 TEST_F( |
1362 SchedulerTest, | 1944 SchedulerTest, |
1363 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { | 1945 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { |
1364 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main | 1946 // 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. | 1947 // thread. This prevents the scheduler from receiving any pending swap acks. |
1366 | 1948 |
1367 // 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. | |
1369 scheduler_settings_.use_external_begin_frame_source = true; | 1949 scheduler_settings_.use_external_begin_frame_source = true; |
1370 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; | 1950 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; |
1371 SetUpScheduler(true); | 1951 SetUpScheduler(true); |
1372 | 1952 |
1373 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
1374 base::TimeDelta::FromMilliseconds(32)); | |
1375 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
1376 base::TimeDelta::FromMilliseconds(32)); | |
1377 fake_compositor_timing_history_->SetDrawDurationEstimate( | |
1378 base::TimeDelta::FromMilliseconds(1)); | |
1379 | |
1380 // Disables automatic swap acks so this test can force swap ack throttling | 1953 // Disables automatic swap acks so this test can force swap ack throttling |
1381 // to simulate a blocked Browser ui thread. | 1954 // to simulate a blocked Browser ui thread. |
1382 scheduler_->SetMaxSwapsPending(1); | 1955 scheduler_->SetMaxSwapsPending(1); |
1383 client_->SetAutomaticSwapAck(false); | 1956 client_->SetAutomaticSwapAck(false); |
1384 | 1957 |
1385 // Get a new active tree in main-thread high latency mode and put us | 1958 // Get a new active tree in main-thread high latency mode and put us |
1386 // in a swap throttled state. | 1959 // in a swap throttled state. |
1387 client_->Reset(); | 1960 client_->Reset(); |
1388 EXPECT_FALSE(scheduler_->CommitPending()); | 1961 EXPECT_FALSE(scheduler_->CommitPending()); |
1389 scheduler_->SetNeedsCommit(); | 1962 scheduler_->SetNeedsCommit(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1436 | 2009 |
1437 TEST_F(SchedulerTest, | 2010 TEST_F(SchedulerTest, |
1438 Deadlock_NoBeginMainFrameWhileSwapTrottledAndPipelineFull) { | 2011 Deadlock_NoBeginMainFrameWhileSwapTrottledAndPipelineFull) { |
1439 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main | 2012 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main |
1440 // thread. This prevents the scheduler from receiving any pending swap acks. | 2013 // thread. This prevents the scheduler from receiving any pending swap acks. |
1441 | 2014 |
1442 // This particular test makes sure we do not send a BeginMainFrame while | 2015 // This particular test makes sure we do not send a BeginMainFrame while |
1443 // swap trottled and we have a pending tree and active tree that | 2016 // swap trottled and we have a pending tree and active tree that |
1444 // still needs to be drawn for the first time. | 2017 // still needs to be drawn for the first time. |
1445 | 2018 |
1446 // Since we are simulating a long commit, set up a client with draw duration | |
1447 // estimates that prevent skipping main frames to get to low latency mode. | |
1448 scheduler_settings_.use_external_begin_frame_source = true; | 2019 scheduler_settings_.use_external_begin_frame_source = true; |
1449 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; | 2020 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; |
1450 scheduler_settings_.main_frame_before_activation_enabled = true; | 2021 scheduler_settings_.main_frame_before_activation_enabled = true; |
1451 SetUpScheduler(true); | 2022 SetUpScheduler(true); |
1452 | 2023 |
1453 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
1454 base::TimeDelta::FromMilliseconds(32)); | |
1455 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
1456 base::TimeDelta::FromMilliseconds(32)); | |
1457 fake_compositor_timing_history_->SetDrawDurationEstimate( | |
1458 base::TimeDelta::FromMilliseconds(1)); | |
1459 | |
1460 // Disables automatic swap acks so this test can force swap ack throttling | 2024 // Disables automatic swap acks so this test can force swap ack throttling |
1461 // to simulate a blocked Browser ui thread. | 2025 // to simulate a blocked Browser ui thread. |
1462 scheduler_->SetMaxSwapsPending(1); | 2026 scheduler_->SetMaxSwapsPending(1); |
1463 client_->SetAutomaticSwapAck(false); | 2027 client_->SetAutomaticSwapAck(false); |
1464 | 2028 |
1465 // Start a new commit in main-thread high latency mode and hold off on | 2029 // Start a new commit in main-thread high latency mode and hold off on |
1466 // activation. | 2030 // activation. |
1467 client_->Reset(); | 2031 client_->Reset(); |
1468 EXPECT_FALSE(scheduler_->CommitPending()); | 2032 EXPECT_FALSE(scheduler_->CommitPending()); |
1469 scheduler_->SetNeedsCommit(); | 2033 scheduler_->SetNeedsCommit(); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1531 // This verifies we don't block commits longer than we need to | 2095 // This verifies we don't block commits longer than we need to |
1532 // for performance reasons - not deadlock reasons. | 2096 // for performance reasons - not deadlock reasons. |
1533 | 2097 |
1534 // Since we are simulating a long commit, set up a client with draw duration | 2098 // Since we are simulating a long commit, set up a client with draw duration |
1535 // estimates that prevent skipping main frames to get to low latency mode. | 2099 // estimates that prevent skipping main frames to get to low latency mode. |
1536 scheduler_settings_.use_external_begin_frame_source = true; | 2100 scheduler_settings_.use_external_begin_frame_source = true; |
1537 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; | 2101 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; |
1538 scheduler_settings_.main_frame_before_activation_enabled = true; | 2102 scheduler_settings_.main_frame_before_activation_enabled = true; |
1539 SetUpScheduler(true); | 2103 SetUpScheduler(true); |
1540 | 2104 |
1541 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
1542 base::TimeDelta::FromMilliseconds(32)); | |
1543 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
1544 base::TimeDelta::FromMilliseconds(32)); | |
1545 fake_compositor_timing_history_->SetDrawDurationEstimate( | |
1546 base::TimeDelta::FromMilliseconds(1)); | |
1547 | |
1548 // Disables automatic swap acks so this test can force swap ack throttling | 2105 // Disables automatic swap acks so this test can force swap ack throttling |
1549 // to simulate a blocked Browser ui thread. | 2106 // to simulate a blocked Browser ui thread. |
1550 scheduler_->SetMaxSwapsPending(1); | 2107 scheduler_->SetMaxSwapsPending(1); |
1551 client_->SetAutomaticSwapAck(false); | 2108 client_->SetAutomaticSwapAck(false); |
1552 | 2109 |
1553 // Start a new commit in main-thread high latency mode and hold off on | 2110 // Start a new commit in main-thread high latency mode and hold off on |
1554 // activation. | 2111 // activation. |
1555 client_->Reset(); | 2112 client_->Reset(); |
1556 EXPECT_FALSE(scheduler_->CommitPending()); | 2113 EXPECT_FALSE(scheduler_->CommitPending()); |
1557 scheduler_->SetNeedsCommit(); | 2114 scheduler_->SetNeedsCommit(); |
(...skipping 1397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2955 scheduler_->SetImplLatencyTakesPriority(true); | 3512 scheduler_->SetImplLatencyTakesPriority(true); |
2956 scheduler_->SetChildrenNeedBeginFrames(true); | 3513 scheduler_->SetChildrenNeedBeginFrames(true); |
2957 | 3514 |
2958 EXPECT_SCOPED(AdvanceFrame()); | 3515 EXPECT_SCOPED(AdvanceFrame()); |
2959 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); | 3516 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); |
2960 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path); | 3517 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path); |
2961 } | 3518 } |
2962 | 3519 |
2963 } // namespace | 3520 } // namespace |
2964 } // namespace cc | 3521 } // namespace cc |
OLD | NEW |