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

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

Issue 1139613003: cc: Avoid deadlock with the UI thread and NPAPI in more cases (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: get rid of complicated imminent logic Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2011 The Chromium Authors. All rights reserved. 1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 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
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
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.
sunnyps 2015/05/20 19:26:51 nit: while we have a pending tree.
brianderson 2015/05/20 19:49:47 Done.
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();
sunnyps 2015/05/20 19:26:51 nit: Move the DidSwapBuffersComplete call above th
brianderson 2015/05/20 19:49:47 Done.
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
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
OLDNEW
« cc/scheduler/scheduler_state_machine.cc ('K') | « cc/scheduler/scheduler_state_machine_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698