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 one_second = base::TimeDelta::FromSeconds(1); | |
253 fake_compositor_timing_history_->SetDrawDurationEstimate(one_second); | |
254 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
255 one_second); | |
256 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
257 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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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( |
388 int64 begin_main_frame_to_commit_estimate_in_ms, | 398 int64 begin_main_frame_to_commit_estimate_in_ms, |
389 int64 commit_to_activate_estimate_in_ms, | 399 int64 commit_to_activate_estimate_in_ms, |
390 bool impl_latency_takes_priority, | 400 bool impl_latency_takes_priority, |
391 bool should_send_begin_main_frame); | 401 bool should_send_begin_main_frame); |
402 void ImplFrameInHighLatency(int64 draw_estimate_in_ms, | |
403 int64 begin_main_frame_to_commit_estimate_in_ms, | |
404 int64 commit_to_activate_estimate_in_ms, | |
405 bool has_impl_side_updates, | |
406 bool swap_ack_before_deadline, | |
407 bool should_draw_and_swap_in_high_latency); | |
392 void BeginFramesNotFromClient(bool use_external_begin_frame_source, | 408 void BeginFramesNotFromClient(bool use_external_begin_frame_source, |
393 bool throttle_frame_production); | 409 bool throttle_frame_production); |
394 void BeginFramesNotFromClient_SwapThrottled( | 410 void BeginFramesNotFromClient_SwapThrottled( |
395 bool use_external_begin_frame_source, | 411 bool use_external_begin_frame_source, |
396 bool throttle_frame_production); | 412 bool throttle_frame_production); |
397 | 413 |
398 scoped_ptr<base::SimpleTestTickClock> now_src_; | 414 scoped_ptr<base::SimpleTestTickClock> now_src_; |
399 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; | 415 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; |
400 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_; | 416 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_; |
401 SchedulerSettings scheduler_settings_; | 417 SchedulerSettings scheduler_settings_; |
(...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1328 task_runner().RunPendingTasks(); // Run posted deadline. | 1344 task_runner().RunPendingTasks(); // Run posted deadline. |
1329 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(), | 1345 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(), |
1330 should_send_begin_main_frame); | 1346 should_send_begin_main_frame); |
1331 EXPECT_EQ(client_->HasAction("ScheduledActionSendBeginMainFrame"), | 1347 EXPECT_EQ(client_->HasAction("ScheduledActionSendBeginMainFrame"), |
1332 should_send_begin_main_frame); | 1348 should_send_begin_main_frame); |
1333 } | 1349 } |
1334 | 1350 |
1335 TEST_F(SchedulerTest, | 1351 TEST_F(SchedulerTest, |
1336 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) { | 1352 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) { |
1337 // Set up client so that estimates indicate that we can commit and activate | 1353 // Set up client so that estimates indicate that we can commit and activate |
1338 // before the deadline (~8ms by default). | 1354 // before the deadline (~11ms by default). |
1339 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false)); | 1355 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false)); |
1340 } | 1356 } |
1341 | 1357 |
1342 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) { | 1358 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) { |
1343 // Set up client so that estimates indicate that the commit cannot finish | 1359 // Set up client so that estimates indicate that the commit cannot finish |
1344 // before the deadline (~8ms by default). | 1360 // before the deadline (~11ms by default). |
1345 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true)); | 1361 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true)); |
1346 } | 1362 } |
1347 | 1363 |
1348 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) { | 1364 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) { |
1349 // Set up client so that estimates indicate that the activate cannot finish | 1365 // Set up client so that estimates indicate that the activate cannot finish |
1350 // before the deadline (~8ms by default). | 1366 // before the deadline (~11ms by default). |
1351 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true)); | 1367 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true)); |
1352 } | 1368 } |
1353 | 1369 |
1354 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { | 1370 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { |
1355 // Set up client so that estimates indicate that we can commit and activate | 1371 // Set up client so that estimates indicate that we can commit and activate |
1356 // before the deadline (~8ms by default), but also enable impl latency takes | 1372 // before the deadline (~11ms by default), but also enable impl latency takes |
1357 // priority mode. | 1373 // priority mode. |
1358 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true)); | 1374 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true)); |
1359 } | 1375 } |
1360 | 1376 |
1377 void SchedulerTest::ImplFrameInHighLatency( | |
1378 int64 draw_estimate_in_ms, | |
1379 int64 begin_main_frame_to_commit_estimate_in_ms, | |
1380 int64 commit_to_activate_estimate_in_ms, | |
1381 bool has_impl_side_updates, | |
1382 bool swap_ack_before_deadline, | |
1383 bool should_draw_and_swap_in_high_latency) { | |
1384 // Set up client with specified estimates. | |
1385 scheduler_settings_.use_external_begin_frame_source = true; | |
1386 SetUpScheduler(true); | |
1387 | |
1388 fake_compositor_timing_history_->SetDrawDurationEstimate( | |
1389 base::TimeDelta::FromMilliseconds(draw_estimate_in_ms)); | |
1390 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
1391 base::TimeDelta::FromMilliseconds( | |
1392 begin_main_frame_to_commit_estimate_in_ms)); | |
1393 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
1394 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms)); | |
1395 | |
1396 // To get into a high latency state, this test disables automatic swap acks. | |
1397 scheduler_->SetMaxSwapsPending(1); | |
1398 client_->SetAutomaticSwapAck(false); | |
1399 | |
1400 // Draw and swap for first BeginFrame | |
1401 client_->Reset(); | |
1402 scheduler_->SetNeedsCommit(); | |
1403 if (has_impl_side_updates) { | |
1404 scheduler_->SetNeedsRedraw(); | |
1405 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1406 SendNextBeginFrame(); | |
1407 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 4); | |
1408 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 4); | |
1409 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
1410 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 4); | |
1411 } else { | |
1412 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1413 SendNextBeginFrame(); | |
1414 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3); | |
1415 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); | |
1416 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); | |
1417 } | |
1418 | |
1419 client_->Reset(); | |
1420 scheduler_->NotifyBeginMainFrameStarted(); | |
1421 scheduler_->NotifyReadyToCommit(); | |
1422 scheduler_->NotifyReadyToActivate(); | |
1423 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1424 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1425 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); | |
1426 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); | |
1427 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
1428 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); | |
1429 | |
1430 // Not calling scheduler_->DidSwapBuffersComplete() until after next frame | |
1431 // puts the impl thread in high latency mode. | |
1432 client_->Reset(); | |
1433 scheduler_->SetNeedsCommit(); | |
1434 if (has_impl_side_updates) | |
1435 scheduler_->SetNeedsRedraw(); | |
1436 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1437 SendNextBeginFrame(); | |
1438 if (should_draw_and_swap_in_high_latency) { | |
mithro-old
2015/07/06 11:58:43
I don't quite understand what is going on here in
brianderson
2015/07/07 02:04:49
I renamed should_draw_and_swap_in_high_latency to
mithro-old
2015/07/07 07:35:38
I think you should split the giant SchedulerTest::
| |
1439 if (has_impl_side_updates) { | |
1440 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1441 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1442 } else { | |
1443 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); | |
1444 } | |
1445 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1446 } else { | |
1447 EXPECT_NO_ACTION(client_); | |
1448 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1449 } | |
1450 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1451 | |
1452 client_->Reset(); | |
1453 if (should_draw_and_swap_in_high_latency) { | |
1454 DCHECK(swap_ack_before_deadline); | |
1455 scheduler_->DidSwapBuffersComplete(); | |
1456 scheduler_->NotifyBeginMainFrameStarted(); | |
1457 scheduler_->NotifyReadyToCommit(); | |
1458 scheduler_->NotifyReadyToActivate(); | |
1459 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1460 } else if (swap_ack_before_deadline) { | |
1461 scheduler_->DidSwapBuffersComplete(); | |
1462 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1463 } else { | |
1464 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1465 scheduler_->DidSwapBuffersComplete(); | |
1466 } | |
1467 | |
1468 // Verify that we recovered immediately if we were supposed to and | |
1469 // that we didn't if weren't. | |
1470 if (should_draw_and_swap_in_high_latency) { | |
1471 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 0, 5); | |
1472 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 5); | |
1473 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 2, 5); | |
1474 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5); | |
1475 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5); | |
1476 scheduler_->DidSwapBuffersComplete(); | |
1477 } else { | |
1478 EXPECT_NO_ACTION(client_); | |
1479 } | |
1480 | |
1481 // Verify that we: | |
1482 // 1) Don't skip two frames in a row. | |
1483 // 2) Continue normal operation if we didn't skip a frame. | |
1484 // 3) Make forward progress even when we aren't expecting another swap ack. | |
1485 client_->Reset(); | |
1486 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1487 scheduler_->SetNeedsCommit(); | |
1488 if (has_impl_side_updates) { | |
1489 scheduler_->SetNeedsRedraw(); | |
1490 SendNextBeginFrame(); | |
1491 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); | |
1492 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); | |
1493 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); | |
1494 } else { | |
1495 SendNextBeginFrame(); | |
1496 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1497 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); | |
1498 } | |
1499 | |
1500 client_->Reset(); | |
1501 scheduler_->NotifyBeginMainFrameStarted(); | |
1502 scheduler_->NotifyReadyToCommit(); | |
1503 scheduler_->NotifyReadyToActivate(); | |
1504 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1505 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); | |
1506 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); | |
1507 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
1508 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); | |
1509 } | |
1510 | |
1511 TEST_F(SchedulerTest, | |
1512 SkipSwapIfHighLatencyAndCanDrawBeforeDeadline_SwapAckThenDeadline) { | |
1513 // Use estimates that indicate commit and activate can finish before the | |
1514 // deadline. | |
1515 int64 draw_estimate_in_ms = 1; | |
1516 int64 begin_main_frame_to_commit_estimate_in_ms = 1; | |
1517 int64 commit_to_activate_estimate_in_ms = 1; | |
1518 bool has_impl_side_updates = true; | |
1519 bool swap_ack_before_deadline = true; | |
1520 bool should_draw_and_swap_in_high_latency = false; | |
1521 EXPECT_SCOPED(ImplFrameInHighLatency( | |
1522 draw_estimate_in_ms, begin_main_frame_to_commit_estimate_in_ms, | |
1523 commit_to_activate_estimate_in_ms, has_impl_side_updates, | |
1524 swap_ack_before_deadline, should_draw_and_swap_in_high_latency)); | |
1525 } | |
1526 | |
1527 TEST_F(SchedulerTest, | |
1528 SkipSwapIfHighLatencyAndCanDrawBeforeDeadline_DeadlineThenSwapAck) { | |
1529 // Use estimates that indicate commit and activate can finish before the | |
1530 // deadline. | |
1531 int64 draw_estimate_in_ms = 1; | |
1532 int64 begin_main_frame_to_commit_estimate_in_ms = 1; | |
1533 int64 commit_to_activate_estimate_in_ms = 1; | |
1534 bool has_impl_side_updates = true; | |
1535 bool swap_ack_before_deadline = false; | |
1536 bool should_draw_and_swap_in_high_latency = false; | |
1537 EXPECT_SCOPED(ImplFrameInHighLatency( | |
1538 draw_estimate_in_ms, begin_main_frame_to_commit_estimate_in_ms, | |
1539 commit_to_activate_estimate_in_ms, has_impl_side_updates, | |
1540 swap_ack_before_deadline, should_draw_and_swap_in_high_latency)); | |
1541 } | |
1542 | |
1543 TEST_F(SchedulerTest, NotSkipSwapIfHighLatencyAndCanDrawTooLong) { | |
1544 // Use estimates that indicate draw cannot finish before the deadline. | |
1545 int64 draw_estimate_in_ms = 20; | |
1546 int64 begin_main_frame_to_commit_estimate_in_ms = 1; | |
1547 int64 commit_to_activate_estimate_in_ms = 1; | |
1548 bool has_impl_side_updates = true; | |
1549 bool swap_ack_before_deadline = true; | |
1550 bool should_draw_and_swap_in_high_latency = true; | |
1551 EXPECT_SCOPED(ImplFrameInHighLatency( | |
1552 draw_estimate_in_ms, begin_main_frame_to_commit_estimate_in_ms, | |
1553 commit_to_activate_estimate_in_ms, has_impl_side_updates, | |
1554 swap_ack_before_deadline, should_draw_and_swap_in_high_latency)); | |
1555 } | |
1556 | |
1557 TEST_F(SchedulerTest, NotSkipSwapIfHighLatencyAndCanActivateTooLong) { | |
1558 // Use estimates that indicate commit and activate cannot finish before the | |
1559 // deadline. | |
1560 int64 draw_estimate_in_ms = 1; | |
1561 int64 begin_main_frame_to_commit_estimate_in_ms = 8; | |
1562 int64 commit_to_activate_estimate_in_ms = 8; | |
1563 bool has_impl_side_updates = false; | |
1564 bool swap_ack_before_deadline = true; | |
1565 bool should_draw_and_swap_in_high_latency = true; | |
1566 EXPECT_SCOPED(ImplFrameInHighLatency( | |
1567 draw_estimate_in_ms, begin_main_frame_to_commit_estimate_in_ms, | |
1568 commit_to_activate_estimate_in_ms, has_impl_side_updates, | |
1569 swap_ack_before_deadline, should_draw_and_swap_in_high_latency)); | |
1570 } | |
1571 | |
1572 TEST_F(SchedulerTest, MainAndSwapInHighLatencyMode) { | |
1573 // Set up client with custom estimates. | |
1574 // This test starts off with expensive estimates to prevent latency recovery | |
1575 // initially, the lowers the estimates to enable it once both the main | |
1576 // and impl threads are in a high latency mode. | |
1577 scheduler_settings_.use_external_begin_frame_source = true; | |
1578 SetUpScheduler(true); | |
1579 | |
1580 auto slow_duration = base::TimeDelta::FromMilliseconds(10); | |
1581 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration); | |
1582 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
1583 slow_duration); | |
1584 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
1585 slow_duration); | |
1586 | |
1587 // To get into a high latency state, this test disables automatic swap acks. | |
1588 scheduler_->SetMaxSwapsPending(1); | |
1589 client_->SetAutomaticSwapAck(false); | |
1590 | |
1591 // Impl thread hits deadline before commit finishes to make | |
1592 // MainThreadIsInHighLatencyMode true | |
1593 client_->Reset(); | |
1594 scheduler_->SetNeedsCommit(); | |
1595 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1596 EXPECT_SCOPED(AdvanceFrame()); | |
1597 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1598 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1599 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1600 scheduler_->NotifyBeginMainFrameStarted(); | |
1601 scheduler_->NotifyReadyToCommit(); | |
1602 scheduler_->NotifyReadyToActivate(); | |
1603 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1604 | |
1605 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); | |
1606 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); | |
1607 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); | |
1608 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); | |
1609 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5); | |
1610 | |
1611 // Draw and swap for first commit, start second commit. | |
1612 client_->Reset(); | |
1613 scheduler_->SetNeedsCommit(); | |
1614 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1615 EXPECT_SCOPED(AdvanceFrame()); | |
1616 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1617 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1618 scheduler_->NotifyBeginMainFrameStarted(); | |
1619 scheduler_->NotifyReadyToCommit(); | |
1620 scheduler_->NotifyReadyToActivate(); | |
1621 | |
1622 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); | |
1623 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 6); | |
1624 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6); | |
1625 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6); | |
1626 EXPECT_ACTION("ScheduledActionCommit", client_, 4, 6); | |
1627 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 5, 6); | |
1628 | |
1629 // Don't call scheduler_->DidSwapBuffersComplete() until after next frame | |
1630 // to put the impl thread in a high latency mode. | |
1631 client_->Reset(); | |
1632 scheduler_->SetNeedsCommit(); | |
1633 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1634 EXPECT_SCOPED(AdvanceFrame()); | |
1635 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1636 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1637 scheduler_->DidSwapBuffersComplete(); | |
1638 | |
1639 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1640 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1641 // Note: BeginMainFrame and swap are skipped here because of | |
1642 // swap ack backpressure, not because of latency recovery. | |
1643 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame")); | |
1644 EXPECT_FALSE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
1645 | |
1646 // Lower estimates so that the scheduler will attempt latency recovery. | |
1647 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
1648 fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration); | |
1649 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
1650 fast_duration); | |
1651 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
1652 fast_duration); | |
1653 | |
1654 // Now that both threads are in a high latency mode, make sure we | |
1655 // skip the BeginMainFrame, then the BeginImplFrame, but not both | |
1656 // at the same time. | |
1657 | |
1658 // Verify we skip BeginMainFrame first. | |
1659 client_->Reset(); | |
1660 // Previous commit request is still outstanding. | |
1661 EXPECT_TRUE(scheduler_->NeedsCommit()); | |
1662 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1663 SendNextBeginFrame(); | |
1664 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1665 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1666 | |
1667 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); | |
1668 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); | |
1669 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3); | |
1670 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame")); | |
1671 | |
1672 // Verify we skip the BeginImplFrame second. | |
1673 client_->Reset(); | |
1674 // Previous commit request is still outstanding. | |
1675 EXPECT_TRUE(scheduler_->NeedsCommit()); | |
1676 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1677 SendNextBeginFrame(); | |
1678 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1679 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1680 scheduler_->DidSwapBuffersComplete(); | |
1681 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1682 | |
1683 EXPECT_NO_ACTION(client_); | |
1684 | |
1685 // Then verify we operate in a low latency mode. | |
1686 client_->Reset(); | |
1687 // Previous commit request is still outstanding. | |
1688 EXPECT_TRUE(scheduler_->NeedsCommit()); | |
1689 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1690 SendNextBeginFrame(); | |
1691 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1692 scheduler_->NotifyBeginMainFrameStarted(); | |
1693 scheduler_->NotifyReadyToCommit(); | |
1694 scheduler_->NotifyReadyToActivate(); | |
1695 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1696 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1697 scheduler_->DidSwapBuffersComplete(); | |
1698 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1699 | |
1700 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); | |
1701 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6); | |
1702 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6); | |
1703 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6); | |
1704 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6); | |
1705 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6); | |
1706 } | |
1707 | |
1361 TEST_F( | 1708 TEST_F( |
1362 SchedulerTest, | 1709 SchedulerTest, |
1363 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { | 1710 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { |
1364 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main | 1711 // 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. | 1712 // thread. This prevents the scheduler from receiving any pending swap acks. |
1366 | 1713 |
1367 // Since we are simulating a long commit, set up a client with draw duration | 1714 // 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. | 1715 // estimates that prevent skipping main frames to get to low latency mode. |
1369 scheduler_settings_.use_external_begin_frame_source = true; | 1716 scheduler_settings_.use_external_begin_frame_source = true; |
1370 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; | 1717 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; |
(...skipping 1584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2955 scheduler_->SetImplLatencyTakesPriority(true); | 3302 scheduler_->SetImplLatencyTakesPriority(true); |
2956 scheduler_->SetChildrenNeedBeginFrames(true); | 3303 scheduler_->SetChildrenNeedBeginFrames(true); |
2957 | 3304 |
2958 EXPECT_SCOPED(AdvanceFrame()); | 3305 EXPECT_SCOPED(AdvanceFrame()); |
2959 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); | 3306 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); |
2960 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path); | 3307 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path); |
2961 } | 3308 } |
2962 | 3309 |
2963 } // namespace | 3310 } // namespace |
2964 } // namespace cc | 3311 } // namespace cc |
OLD | NEW |