OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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/layers/picture_layer_impl.h" | 5 #include "cc/layers/picture_layer_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
(...skipping 1538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1549 DCHECK(*this); | 1549 DCHECK(*this); |
1550 | 1550 |
1551 IteratorType index = stages_[current_stage_].iterator_type; | 1551 IteratorType index = stages_[current_stage_].iterator_type; |
1552 DCHECK(iterators_[index]); | 1552 DCHECK(iterators_[index]); |
1553 DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type); | 1553 DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type); |
1554 | 1554 |
1555 return *iterators_[index]; | 1555 return *iterators_[index]; |
1556 } | 1556 } |
1557 | 1557 |
1558 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator() | 1558 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator() |
1559 : iterator_index_(0), | 1559 : tiling_index_(0), |
1560 iteration_stage_(TilePriority::EVENTUALLY), | 1560 iteration_stage_(TilePriority::EVENTUALLY), |
1561 range_index_(0), | |
1561 required_for_activation_(false), | 1562 required_for_activation_(false), |
1562 layer_(NULL) {} | 1563 tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES), |
1564 layer_(NULL) { | |
1565 } | |
1563 | 1566 |
1564 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator( | 1567 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator( |
1565 PictureLayerImpl* layer, | 1568 PictureLayerImpl* layer, |
1566 TreePriority tree_priority) | 1569 TreePriority tree_priority) |
1567 : iterator_index_(0), | 1570 : tiling_index_(0), |
1568 iteration_stage_(TilePriority::EVENTUALLY), | 1571 iteration_stage_(TilePriority::EVENTUALLY), |
1572 range_index_(0), | |
1569 required_for_activation_(false), | 1573 required_for_activation_(false), |
1574 tree_priority_(tree_priority), | |
1570 layer_(layer) { | 1575 layer_(layer) { |
1571 // Early out if the layer has no tilings. | 1576 // Early out if the layer has no tilings. |
1572 // TODO(vmpstr): Once tile priorities are determined by the iterators, ensure | 1577 // TODO(vmpstr): Once tile priorities are determined by the iterators, ensure |
1573 // that layers that don't have valid tile priorities have lowest priorities so | 1578 // that layers that don't have valid tile priorities have lowest priorities so |
1574 // they evict their tiles first (crbug.com/381704) | 1579 // they evict their tiles first (crbug.com/381704) |
1575 if (!layer_->tilings_ || !layer_->tilings_->num_tilings()) | 1580 if (!layer_->tilings_ || !layer_->tilings_->num_tilings()) |
1576 return; | 1581 return; |
1577 | 1582 |
1583 ConstructRanges(); | |
1584 if (!CurrentTilingIndexInRange()) | |
1585 AdvanceRange(); | |
1586 | |
1587 // There must be at least one valid range. | |
1588 DCHECK(CurrentTilingIndexInRange()); | |
1589 | |
1590 iterator_ = PictureLayerTiling::TilingEvictionTileIterator( | |
1591 layer_->tilings_->tiling_at(tiling_index_), | |
1592 tree_priority, | |
1593 iteration_stage_, | |
1594 required_for_activation_); | |
1595 | |
1596 if (!iterator_) | |
1597 AdvanceToNextIterator(); | |
1598 } | |
1599 | |
1600 PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() { | |
1601 } | |
1602 | |
1603 Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() { | |
1604 DCHECK(*this); | |
1605 return *iterator_; | |
1606 } | |
1607 | |
1608 const Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() const { | |
1609 DCHECK(*this); | |
1610 return *iterator_; | |
1611 } | |
1612 | |
1613 PictureLayerImpl::LayerEvictionTileIterator& | |
1614 PictureLayerImpl::LayerEvictionTileIterator:: | |
1615 operator++() { | |
1616 DCHECK(*this); | |
1617 ++iterator_; | |
1618 | |
1619 if (!iterator_) | |
1620 AdvanceToNextIterator(); | |
1621 return *this; | |
1622 } | |
1623 | |
1624 void PictureLayerImpl::LayerEvictionTileIterator::ConstructRanges() { | |
1625 // TODO(vmpstr): See if these can be looked up from the tiling set. | |
1578 size_t high_res_tiling_index = layer_->tilings_->num_tilings(); | 1626 size_t high_res_tiling_index = layer_->tilings_->num_tilings(); |
1579 size_t low_res_tiling_index = layer_->tilings_->num_tilings(); | 1627 size_t low_res_tiling_index = layer_->tilings_->num_tilings(); |
1580 for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) { | 1628 for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) { |
1581 PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i); | 1629 PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i); |
1582 if (tiling->resolution() == HIGH_RESOLUTION) | 1630 if (tiling->resolution() == HIGH_RESOLUTION) |
1583 high_res_tiling_index = i; | 1631 high_res_tiling_index = i; |
1584 else if (tiling->resolution() == LOW_RESOLUTION) | 1632 else if (tiling->resolution() == LOW_RESOLUTION) |
1585 low_res_tiling_index = i; | 1633 low_res_tiling_index = i; |
1586 } | 1634 } |
1587 | 1635 |
1588 iterators_.reserve(layer_->tilings_->num_tilings()); | 1636 DCHECK_LT(high_res_tiling_index, layer_->tilings_->num_tilings()); |
1589 | 1637 |
1590 // Higher resolution non-ideal goes first. | 1638 // First iterate from highest resolution to the HIGH_RES tiling. |
1591 for (size_t i = 0; i < high_res_tiling_index; ++i) { | 1639 ranges_[HIGHER_THAN_HIGH_RES].start_index = 0; |
1592 iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator( | 1640 ranges_[HIGHER_THAN_HIGH_RES].one_past_end_index = high_res_tiling_index; |
1593 layer_->tilings_->tiling_at(i), tree_priority)); | 1641 |
1642 // Next, iterate from the lowest resolution to the LOW_RES tiling. Note that | |
1643 // if we don't have a low res tiling, then the start index will be the same as | |
1644 // one past the end, which means it is an empty range. | |
1645 ranges_[LOWER_THAN_LOW_RES].start_index = layer_->tilings_->num_tilings() - 1; | |
1646 ranges_[LOWER_THAN_LOW_RES].one_past_end_index = low_res_tiling_index; | |
1647 | |
1648 // Next, iterate from just after the LOW_RES tiling to the HIGH_RES tiling. | |
1649 // Note that if there is no low res tiling, then start index will be the last | |
1650 // tiling. | |
1651 ranges_[BETWEEN_HIGH_AND_LOW_RES].start_index = low_res_tiling_index - 1; | |
1652 ranges_[BETWEEN_HIGH_AND_LOW_RES].one_past_end_index = high_res_tiling_index; | |
1653 | |
1654 if (low_res_tiling_index < layer_->tilings_->num_tilings()) { | |
1655 // Next, iterate a range of one element: LOW_RES tiling. | |
1656 ranges_[LOW_RES].start_index = low_res_tiling_index; | |
1657 ranges_[LOW_RES].one_past_end_index = low_res_tiling_index + 1; | |
1658 } else { | |
1659 // If there is no LOW_RES tiling, then set an empty range. | |
1660 ranges_[LOW_RES].start_index = 0; | |
1661 ranges_[LOW_RES].one_past_end_index = 0; | |
1594 } | 1662 } |
1595 | 1663 |
1596 // Lower resolution non-ideal goes next. | 1664 // Finally, iterate a range of one element: HIGH_RES tiling. |
1597 for (size_t i = layer_->tilings_->num_tilings() - 1; | 1665 ranges_[HIGH_RES].start_index = high_res_tiling_index; |
1598 i > high_res_tiling_index; | 1666 ranges_[HIGH_RES].one_past_end_index = high_res_tiling_index + 1; |
1599 --i) { | |
1600 PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i); | |
1601 if (tiling->resolution() == LOW_RESOLUTION) | |
1602 continue; | |
1603 | 1667 |
1604 iterators_.push_back( | 1668 range_index_ = HIGHER_THAN_HIGH_RES; |
1605 PictureLayerTiling::TilingEvictionTileIterator(tiling, tree_priority)); | 1669 tiling_index_ = ranges_[range_index_].start_index; |
1670 } | |
1671 | |
1672 bool PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingIndexInRange() { | |
1673 TilingIterationRange& range = ranges_[range_index_]; | |
1674 if (range.start_index < range.one_past_end_index) { | |
1675 return tiling_index_ >= range.start_index && | |
1676 tiling_index_ < range.one_past_end_index; | |
1677 } else if (range.start_index > range.one_past_end_index) { | |
1678 return tiling_index_ <= range.start_index && | |
1679 tiling_index_ > range.one_past_end_index; | |
1606 } | 1680 } |
1681 // Empty range means we're not in range. | |
1682 return false; | |
1683 } | |
reveman
2014/07/29 21:41:32
I think I'd like to see this function removed and
vmpstr
2014/07/30 00:18:51
I'm still a little bit confused about how we would
reveman
2014/07/30 16:06:47
See my comment about RangeOffsetToTilingSetIndex b
vmpstr
2014/07/30 20:06:39
Acknowledged.
| |
1607 | 1684 |
1608 // Now, put the low res tiling if we have one. | 1685 void PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextIterator() { |
1609 if (low_res_tiling_index < layer_->tilings_->num_tilings()) { | 1686 DCHECK(!iterator_); |
1610 iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator( | 1687 while (!iterator_) { |
1611 layer_->tilings_->tiling_at(low_res_tiling_index), tree_priority)); | 1688 bool success = AdvanceTiling(); |
1612 } | 1689 if (!success) |
1690 success = AdvanceRange(); | |
1691 if (!success) | |
1692 success = AdvanceStage(); | |
1693 if (!success) | |
1694 break; | |
reveman
2014/07/29 21:41:32
hm, doesn't this need to be a nested loop? ie. we
vmpstr
2014/07/30 00:18:51
AdvanceTiling will advance to the next tiling if o
reveman
2014/07/31 15:32:47
AdvanceTiling doesn't advance until it finds non-e
vmpstr
2014/08/01 06:04:48
Well, this is kind of a weird one. Here's my reaso
reveman
2014/08/01 17:54:46
I feel like there's a lack of uniformity in curren
vmpstr
2014/08/01 19:39:50
Done.
| |
1613 | 1695 |
1614 // Finally, put the high res tiling if we have one. | 1696 iterator_ = PictureLayerTiling::TilingEvictionTileIterator( |
1615 if (high_res_tiling_index < layer_->tilings_->num_tilings()) { | 1697 layer_->tilings_->tiling_at(tiling_index_), |
1616 iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator( | 1698 tree_priority_, |
1617 layer_->tilings_->tiling_at(high_res_tiling_index), tree_priority)); | 1699 iteration_stage_, |
1618 } | 1700 required_for_activation_); |
1619 | |
1620 DCHECK_GT(iterators_.size(), 0u); | |
1621 | |
1622 if (!iterators_[iterator_index_] || | |
1623 !IsCorrectType(&iterators_[iterator_index_])) { | |
1624 AdvanceToNextIterator(); | |
1625 } | 1701 } |
1626 } | 1702 } |
1627 | 1703 |
1628 PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() {} | 1704 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceTiling() { |
1705 // We can't advance the tiling if we're already not in range. | |
1706 if (!CurrentTilingIndexInRange()) | |
reveman
2014/07/29 21:41:33
Seems odd that we check this both before and after
vmpstr
2014/07/30 00:18:52
I don't think this was required. I replaced it wit
reveman
2014/07/31 15:32:47
Acknowledged.
| |
1707 return false; | |
1629 | 1708 |
1630 Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() { | 1709 int direction = ranges_[range_index_].start_index < |
1631 DCHECK(*this); | 1710 ranges_[range_index_].one_past_end_index |
1632 return *iterators_[iterator_index_]; | 1711 ? 1 |
1712 : -1; | |
reveman
2014/07/29 21:41:32
I think it would be cleaner to adjust the index ba
vmpstr
2014/07/30 00:18:52
I'm not sure I understand what you mean. Would Ran
reveman
2014/07/30 16:06:48
RangeOffsetToTilingSetIndex would simply take an o
vmpstr
2014/07/30 20:06:38
I've done this. To be honest, I find this more con
reveman
2014/07/31 15:32:47
Let's see what it looks like after rebase onto my
vmpstr
2014/08/01 06:04:48
Done.
| |
1713 tiling_index_ += direction; | |
1714 | |
1715 return CurrentTilingIndexInRange(); | |
1633 } | 1716 } |
1634 | 1717 |
1635 const Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() const { | 1718 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceRange() { |
1636 DCHECK(*this); | 1719 DCHECK(!CurrentTilingIndexInRange()); |
1637 return *iterators_[iterator_index_]; | 1720 bool wrapped_around = false; |
reveman
2014/07/29 21:41:32
I think this function would be a bit cleaner with
vmpstr
2014/07/30 00:18:52
switch (range_index_) {
case HIGHER_THAN_HIGH_RES
reveman
2014/07/31 15:32:47
Yup, thanks!
| |
1721 while (!CurrentTilingIndexInRange()) { | |
1722 range_index_ = static_cast<RangeType>((range_index_ + 1) % NUM_RANGE_TYPES); | |
1723 tiling_index_ = ranges_[range_index_].start_index; | |
1724 if (range_index_ == 0) | |
1725 wrapped_around = true; | |
1726 } | |
1727 // If we wrapped around the ranges, we need to indicate that we should advance | |
1728 // the stage. | |
1729 return !wrapped_around; | |
1638 } | 1730 } |
1639 | 1731 |
1640 PictureLayerImpl::LayerEvictionTileIterator& | 1732 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceStage() { |
reveman
2014/07/29 21:41:33
Think this function would also be cleaner with a s
vmpstr
2014/07/30 00:18:52
switch over bins? That would end up looking like t
reveman
2014/07/30 16:06:47
Why don't we add an enum for all stages? ie. EVENT
vmpstr
2014/07/30 20:06:38
I don't like that. Either this enum would have to
reveman
2014/07/31 15:32:47
Enum living here and two utility functions that re
vmpstr
2014/08/01 06:04:48
Done.
| |
1641 PictureLayerImpl::LayerEvictionTileIterator:: | 1733 // If we're NOW and required_for_activation, then this was the last pass |
1642 operator++() { | 1734 // through the iterators. |
1643 DCHECK(*this); | 1735 if (iteration_stage_ == TilePriority::NOW && required_for_activation_) |
1644 ++iterators_[iterator_index_]; | 1736 return false; |
1645 if (!iterators_[iterator_index_] || | 1737 |
1646 !IsCorrectType(&iterators_[iterator_index_])) { | 1738 if (!required_for_activation_) { |
1647 AdvanceToNextIterator(); | 1739 required_for_activation_ = true; |
1740 } else { | |
1741 required_for_activation_ = false; | |
1742 iteration_stage_ = | |
1743 static_cast<TilePriority::PriorityBin>(iteration_stage_ - 1); | |
1648 } | 1744 } |
1649 return *this; | 1745 return true; |
1650 } | |
1651 | |
1652 void PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextIterator() { | |
1653 ++iterator_index_; | |
1654 | |
1655 while (true) { | |
1656 while (iterator_index_ < iterators_.size()) { | |
1657 if (iterators_[iterator_index_] && | |
1658 IsCorrectType(&iterators_[iterator_index_])) { | |
1659 return; | |
1660 } | |
1661 ++iterator_index_; | |
1662 } | |
1663 | |
1664 // If we're NOW and required_for_activation, then this was the last pass | |
1665 // through the iterators. | |
1666 if (iteration_stage_ == TilePriority::NOW && required_for_activation_) | |
1667 break; | |
1668 | |
1669 if (!required_for_activation_) { | |
1670 required_for_activation_ = true; | |
1671 } else { | |
1672 required_for_activation_ = false; | |
1673 iteration_stage_ = | |
1674 static_cast<TilePriority::PriorityBin>(iteration_stage_ - 1); | |
1675 } | |
1676 iterator_index_ = 0; | |
1677 } | |
1678 } | 1746 } |
1679 | 1747 |
1680 PictureLayerImpl::LayerEvictionTileIterator::operator bool() const { | 1748 PictureLayerImpl::LayerEvictionTileIterator::operator bool() const { |
1681 return iterator_index_ < iterators_.size(); | 1749 return iterator_; |
reveman
2014/07/29 21:41:32
!!iterator_?
vmpstr
2014/07/30 00:18:51
Done.
| |
1682 } | |
1683 | |
1684 bool PictureLayerImpl::LayerEvictionTileIterator::IsCorrectType( | |
1685 PictureLayerTiling::TilingEvictionTileIterator* it) const { | |
1686 return it->get_type() == iteration_stage_ && | |
1687 (**it)->required_for_activation() == required_for_activation_; | |
1688 } | 1750 } |
1689 | 1751 |
1690 } // namespace cc | 1752 } // namespace cc |
OLD | NEW |