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 1360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true)); | 1371 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true)); |
1372 } | 1372 } |
1373 | 1373 |
1374 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { | 1374 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { |
1375 // Set up client so that estimates indicate that we can commit and activate | 1375 // Set up client so that estimates indicate that we can commit and activate |
1376 // before the deadline (~8ms by default), but also enable impl latency takes | 1376 // before the deadline (~8ms by default), but also enable impl latency takes |
1377 // priority mode. | 1377 // priority mode. |
1378 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true)); | 1378 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true)); |
1379 } | 1379 } |
1380 | 1380 |
1381 TEST_F(SchedulerTest, PollForCommitCompletion) { | 1381 TEST_F(SchedulerTest, |
| 1382 Deadlock_NotifyReadyToCommitMakesProgressWhileSwapTrottled) { |
| 1383 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main |
| 1384 // thread. This prevents the scheduler from receiving any pending swap acks. |
| 1385 // This test makes sure that we keep updating the TextureUploader with |
| 1386 // DidAnticipatedDrawTimeChange's so that it can make forward progress and |
| 1387 // upload all the textures needed for the commit to complete. |
| 1388 |
1382 // Since we are simulating a long commit, set up a client with draw duration | 1389 // Since we are simulating a long commit, set up a client with draw duration |
1383 // estimates that prevent skipping main frames to get to low latency mode. | 1390 // estimates that prevent skipping main frames to get to low latency mode. |
1384 SchedulerClientWithFixedEstimates* client = | 1391 SchedulerClientWithFixedEstimates* client = |
1385 new SchedulerClientWithFixedEstimates( | 1392 new SchedulerClientWithFixedEstimates( |
1386 base::TimeDelta::FromMilliseconds(1), | 1393 base::TimeDelta::FromMilliseconds(1), |
1387 base::TimeDelta::FromMilliseconds(32), | 1394 base::TimeDelta::FromMilliseconds(32), |
1388 base::TimeDelta::FromMilliseconds(32)); | 1395 base::TimeDelta::FromMilliseconds(32)); |
1389 scheduler_settings_.use_external_begin_frame_source = true; | 1396 scheduler_settings_.use_external_begin_frame_source = true; |
1390 SetUpScheduler(make_scoped_ptr(client).Pass(), true); | 1397 SetUpScheduler(make_scoped_ptr(client).Pass(), true); |
1391 | 1398 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1432 task_runner().DelayToNextTaskTime().InMicroseconds()) | 1439 task_runner().DelayToNextTaskTime().InMicroseconds()) |
1433 << scheduler_->AsValue()->ToString(); | 1440 << scheduler_->AsValue()->ToString(); |
1434 task_runner().RunPendingTasks(); | 1441 task_runner().RunPendingTasks(); |
1435 EXPECT_GT(client->num_actions_(), actions_so_far); | 1442 EXPECT_GT(client->num_actions_(), actions_so_far); |
1436 EXPECT_STREQ(client->Action(client->num_actions_() - 1), | 1443 EXPECT_STREQ(client->Action(client->num_actions_() - 1), |
1437 "DidAnticipatedDrawTimeChange"); | 1444 "DidAnticipatedDrawTimeChange"); |
1438 actions_so_far = client->num_actions_(); | 1445 actions_so_far = client->num_actions_(); |
1439 } | 1446 } |
1440 } | 1447 } |
1441 | 1448 |
| 1449 TEST_F( |
| 1450 SchedulerTest, |
| 1451 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { |
| 1452 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main |
| 1453 // thread. This prevents the scheduler from receiving any pending swap acks. |
| 1454 |
| 1455 // Since we are simulating a long commit, set up a client with draw duration |
| 1456 // estimates that prevent skipping main frames to get to low latency mode. |
| 1457 SchedulerClientWithFixedEstimates* client = |
| 1458 new SchedulerClientWithFixedEstimates( |
| 1459 base::TimeDelta::FromMilliseconds(1), |
| 1460 base::TimeDelta::FromMilliseconds(32), |
| 1461 base::TimeDelta::FromMilliseconds(32)); |
| 1462 scheduler_settings_.use_external_begin_frame_source = true; |
| 1463 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; |
| 1464 scheduler_settings_.impl_side_painting = true; |
| 1465 SetUpScheduler(make_scoped_ptr(client).Pass(), true); |
| 1466 |
| 1467 // Disables automatic swap acks so this test can force swap ack throttling |
| 1468 // to simulate a blocked Browser ui thread. |
| 1469 scheduler_->SetMaxSwapsPending(1); |
| 1470 client_->SetAutomaticSwapAck(false); |
| 1471 |
| 1472 // Get a new active tree in main-thread high latency mode and put us |
| 1473 // in a swap throttled state. |
| 1474 client_->Reset(); |
| 1475 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1476 scheduler_->SetNeedsCommit(); |
| 1477 scheduler_->SetNeedsRedraw(); |
| 1478 EXPECT_SCOPED(AdvanceFrame()); |
| 1479 EXPECT_TRUE(scheduler_->CommitPending()); |
| 1480 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1481 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1482 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1483 scheduler_->NotifyBeginMainFrameStarted(); |
| 1484 scheduler_->NotifyReadyToCommit(); |
| 1485 scheduler_->NotifyReadyToActivate(); |
| 1486 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1487 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 7); |
| 1488 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 7); |
| 1489 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 7); |
| 1490 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 7); |
| 1491 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 7); |
| 1492 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 7); |
| 1493 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 6, 7); |
| 1494 |
| 1495 // Make sure that we can finish the next commit even while swap throttled. |
| 1496 client_->Reset(); |
| 1497 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1498 scheduler_->SetNeedsCommit(); |
| 1499 EXPECT_SCOPED(AdvanceFrame()); |
| 1500 scheduler_->NotifyBeginMainFrameStarted(); |
| 1501 scheduler_->NotifyReadyToCommit(); |
| 1502 scheduler_->NotifyReadyToActivate(); |
| 1503 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1504 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1505 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1506 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5); |
| 1507 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 5); |
| 1508 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); |
| 1509 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); |
| 1510 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 5); |
| 1511 |
| 1512 // Make sure we do not send a BeginMainFrame while swap throttled and |
| 1513 // we have both a pending tree and an active tree. |
| 1514 client_->Reset(); |
| 1515 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1516 scheduler_->SetNeedsCommit(); |
| 1517 EXPECT_SCOPED(AdvanceFrame()); |
| 1518 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1519 task_runner().RunPendingTasks(); // Run posted deadline. |
| 1520 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); |
| 1521 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); |
| 1522 } |
| 1523 |
| 1524 TEST_F(SchedulerTest, |
| 1525 Deadlock_NoBeginMainFrameWhileSwapTrottledAndPipelineFull) { |
| 1526 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main |
| 1527 // thread. This prevents the scheduler from receiving any pending swap acks. |
| 1528 |
| 1529 // This particular test makes sure we do not send a BeginMainFrame while |
| 1530 // swap trottled and we have a pending tree and active tree that |
| 1531 // still needs to be drawn for the first time. |
| 1532 |
| 1533 // Since we are simulating a long commit, set up a client with draw duration |
| 1534 // estimates that prevent skipping main frames to get to low latency mode. |
| 1535 SchedulerClientWithFixedEstimates* client = |
| 1536 new SchedulerClientWithFixedEstimates( |
| 1537 base::TimeDelta::FromMilliseconds(1), |
| 1538 base::TimeDelta::FromMilliseconds(32), |
| 1539 base::TimeDelta::FromMilliseconds(32)); |
| 1540 scheduler_settings_.use_external_begin_frame_source = true; |
| 1541 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; |
| 1542 scheduler_settings_.main_frame_before_activation_enabled = true; |
| 1543 scheduler_settings_.impl_side_painting = true; |
| 1544 SetUpScheduler(make_scoped_ptr(client).Pass(), true); |
| 1545 |
| 1546 // Disables automatic swap acks so this test can force swap ack throttling |
| 1547 // to simulate a blocked Browser ui thread. |
| 1548 scheduler_->SetMaxSwapsPending(1); |
| 1549 client_->SetAutomaticSwapAck(false); |
| 1550 |
| 1551 // Start a new commit in main-thread high latency mode and hold off on |
| 1552 // activation. |
| 1553 client_->Reset(); |
| 1554 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1555 scheduler_->SetNeedsCommit(); |
| 1556 scheduler_->SetNeedsRedraw(); |
| 1557 EXPECT_SCOPED(AdvanceFrame()); |
| 1558 EXPECT_TRUE(scheduler_->CommitPending()); |
| 1559 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1560 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1561 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1562 scheduler_->DidSwapBuffersComplete(); |
| 1563 scheduler_->NotifyBeginMainFrameStarted(); |
| 1564 scheduler_->NotifyReadyToCommit(); |
| 1565 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1566 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6); |
| 1567 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6); |
| 1568 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6); |
| 1569 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6); |
| 1570 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6); |
| 1571 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6); |
| 1572 |
| 1573 // Start another commit while we still have an active tree. |
| 1574 // Enter a swap throttled state. |
| 1575 client_->Reset(); |
| 1576 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1577 scheduler_->SetNeedsCommit(); |
| 1578 scheduler_->SetNeedsRedraw(); |
| 1579 EXPECT_SCOPED(AdvanceFrame()); |
| 1580 EXPECT_TRUE(scheduler_->CommitPending()); |
| 1581 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1582 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1583 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1584 scheduler_->NotifyBeginMainFrameStarted(); |
| 1585 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4); |
| 1586 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4); |
| 1587 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4); |
| 1588 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); |
| 1589 |
| 1590 // Can't commit yet because there's still a pending tree. |
| 1591 client_->Reset(); |
| 1592 scheduler_->NotifyReadyToCommit(); |
| 1593 EXPECT_NO_ACTION(client_); |
| 1594 |
| 1595 // Activate the pending tree, which also unblocks the commit immediately. |
| 1596 client_->Reset(); |
| 1597 scheduler_->NotifyReadyToActivate(); |
| 1598 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2); |
| 1599 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2); |
| 1600 |
| 1601 // Make sure we do not send a BeginMainFrame while swap throttled and |
| 1602 // we have both a pending tree and an active tree that still needs |
| 1603 // it's first draw. |
| 1604 client_->Reset(); |
| 1605 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1606 scheduler_->SetNeedsCommit(); |
| 1607 EXPECT_SCOPED(AdvanceFrame()); |
| 1608 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1609 task_runner().RunPendingTasks(); // Run posted deadline. |
| 1610 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); |
| 1611 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); |
| 1612 } |
| 1613 |
| 1614 TEST_F( |
| 1615 SchedulerTest, |
| 1616 CommitMakesProgressWhenIdleAndHasPendingTreeAndActiveTreeNeedsFirstDraw) { |
| 1617 // This verifies we don't block commits longer than we need to |
| 1618 // for performance reasons - not deadlock reasons. |
| 1619 |
| 1620 // Since we are simulating a long commit, set up a client with draw duration |
| 1621 // estimates that prevent skipping main frames to get to low latency mode. |
| 1622 SchedulerClientWithFixedEstimates* client = |
| 1623 new SchedulerClientWithFixedEstimates( |
| 1624 base::TimeDelta::FromMilliseconds(1), |
| 1625 base::TimeDelta::FromMilliseconds(32), |
| 1626 base::TimeDelta::FromMilliseconds(32)); |
| 1627 scheduler_settings_.use_external_begin_frame_source = true; |
| 1628 scheduler_settings_.main_frame_while_swap_throttled_enabled = true; |
| 1629 scheduler_settings_.main_frame_before_activation_enabled = true; |
| 1630 scheduler_settings_.impl_side_painting = true; |
| 1631 SetUpScheduler(make_scoped_ptr(client).Pass(), true); |
| 1632 |
| 1633 // Disables automatic swap acks so this test can force swap ack throttling |
| 1634 // to simulate a blocked Browser ui thread. |
| 1635 scheduler_->SetMaxSwapsPending(1); |
| 1636 client_->SetAutomaticSwapAck(false); |
| 1637 |
| 1638 // Start a new commit in main-thread high latency mode and hold off on |
| 1639 // activation. |
| 1640 client_->Reset(); |
| 1641 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1642 scheduler_->SetNeedsCommit(); |
| 1643 scheduler_->SetNeedsRedraw(); |
| 1644 EXPECT_SCOPED(AdvanceFrame()); |
| 1645 EXPECT_TRUE(scheduler_->CommitPending()); |
| 1646 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1647 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1648 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1649 scheduler_->DidSwapBuffersComplete(); |
| 1650 scheduler_->NotifyBeginMainFrameStarted(); |
| 1651 scheduler_->NotifyReadyToCommit(); |
| 1652 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1653 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6); |
| 1654 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6); |
| 1655 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6); |
| 1656 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6); |
| 1657 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6); |
| 1658 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6); |
| 1659 |
| 1660 // Start another commit while we still have an active tree. |
| 1661 client_->Reset(); |
| 1662 EXPECT_FALSE(scheduler_->CommitPending()); |
| 1663 scheduler_->SetNeedsCommit(); |
| 1664 scheduler_->SetNeedsRedraw(); |
| 1665 EXPECT_SCOPED(AdvanceFrame()); |
| 1666 EXPECT_TRUE(scheduler_->CommitPending()); |
| 1667 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1668 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); |
| 1669 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1670 scheduler_->NotifyBeginMainFrameStarted(); |
| 1671 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4); |
| 1672 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4); |
| 1673 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4); |
| 1674 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); |
| 1675 scheduler_->DidSwapBuffersComplete(); |
| 1676 |
| 1677 // Can't commit yet because there's still a pending tree. |
| 1678 client_->Reset(); |
| 1679 scheduler_->NotifyReadyToCommit(); |
| 1680 EXPECT_NO_ACTION(client_); |
| 1681 |
| 1682 // Activate the pending tree, which also unblocks the commit immediately |
| 1683 // while we are in an idle state. |
| 1684 client_->Reset(); |
| 1685 scheduler_->NotifyReadyToActivate(); |
| 1686 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2); |
| 1687 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2); |
| 1688 } |
| 1689 |
1442 TEST_F(SchedulerTest, BeginRetroFrame) { | 1690 TEST_F(SchedulerTest, BeginRetroFrame) { |
1443 scheduler_settings_.use_external_begin_frame_source = true; | 1691 scheduler_settings_.use_external_begin_frame_source = true; |
1444 SetUpScheduler(true); | 1692 SetUpScheduler(true); |
1445 | 1693 |
1446 // SetNeedsCommit should begin the frame on the next BeginImplFrame. | 1694 // SetNeedsCommit should begin the frame on the next BeginImplFrame. |
1447 scheduler_->SetNeedsCommit(); | 1695 scheduler_->SetNeedsCommit(); |
1448 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | 1696 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); |
1449 client_->Reset(); | 1697 client_->Reset(); |
1450 | 1698 |
1451 // Create a BeginFrame with a long deadline to avoid race conditions. | 1699 // Create a BeginFrame with a long deadline to avoid race conditions. |
(...skipping 1187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2639 | 2887 |
2640 // At the next BeginFrame, authoritative interval is used instead of previous | 2888 // At the next BeginFrame, authoritative interval is used instead of previous |
2641 // interval. | 2889 // interval. |
2642 EXPECT_NE(initial_interval, scheduler_->begin_impl_frame_args().interval); | 2890 EXPECT_NE(initial_interval, scheduler_->begin_impl_frame_args().interval); |
2643 EXPECT_EQ(authoritative_interval, | 2891 EXPECT_EQ(authoritative_interval, |
2644 scheduler_->begin_impl_frame_args().interval); | 2892 scheduler_->begin_impl_frame_args().interval); |
2645 } | 2893 } |
2646 | 2894 |
2647 } // namespace | 2895 } // namespace |
2648 } // namespace cc | 2896 } // namespace cc |
OLD | NEW |