Commit 7fceb779 authored by vmpstr's avatar vmpstr Committed by Commit bot

cc: Remove tiles from recycle tree that were deleted on active.

This patch removes tiles from the recycle tree that were deleted from
the active tree as a result of a shifting live tiles rect. It is
important to do this, since if the active tree then would recreate
the deleted tile (ie, live tiles rect shift back), we have to ensure
that this tile will be shared when the next pending tree is created.
If we don't do it, we can run into a situation in which we will
continuously raster the same tile.

The patch does the following:
- Adds a way to get a recycled tree twin tiling.
- During LiveTilesRect tile deletion, deletes tiles from the same
  location from the recycle twin (if one exists).

R=danakj, enne

Review URL: https://codereview.chromium.org/502453003

Cr-Commit-Position: refs/heads/master@{#291949}
parent aa7e9b61
......@@ -118,6 +118,11 @@ class FixedInvalidationPictureLayerTilingClient
return base_client_->GetTwinTiling(tiling);
}
virtual PictureLayerTiling* GetRecycledTwinTiling(
const PictureLayerTiling* tiling) OVERRIDE {
return base_client_->GetRecycledTwinTiling(tiling);
}
virtual size_t GetMaxTilesForInterestArea() const OVERRIDE {
return base_client_->GetMaxTilesForInterestArea();
}
......
......@@ -109,7 +109,7 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
LayerImpl::PushPropertiesTo(base_layer);
// When the pending tree pushes to the active tree, the pending twin
// disappears.
// becomes recycled.
layer_impl->twin_layer_ = NULL;
twin_layer_ = NULL;
......@@ -541,6 +541,12 @@ gfx::Rect PictureLayerImpl::GetViewportForTilePriorityInContentSpace() const {
return visible_rect_in_content_space;
}
PictureLayerImpl* PictureLayerImpl::GetRecycledTwinLayer() {
// TODO(vmpstr): Maintain recycled twin as a member. crbug.com/407418
return static_cast<PictureLayerImpl*>(
layer_tree_impl()->FindRecycleTreeLayerById(id()));
}
void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
if (layer_tree_impl()->IsActiveTree()) {
gfx::RectF layer_damage_rect =
......@@ -613,6 +619,14 @@ const PictureLayerTiling* PictureLayerImpl::GetTwinTiling(
return twin_layer_->tilings_->TilingAtScale(tiling->contents_scale());
}
PictureLayerTiling* PictureLayerImpl::GetRecycledTwinTiling(
const PictureLayerTiling* tiling) {
PictureLayerImpl* recycled_twin = GetRecycledTwinLayer();
if (!recycled_twin || !recycled_twin->tilings_)
return NULL;
return recycled_twin->tilings_->TilingAtScale(tiling->contents_scale());
}
size_t PictureLayerImpl::GetMaxTilesForInterestArea() const {
return layer_tree_impl()->settings().max_tiles_for_interest_area;
}
......@@ -1253,8 +1267,7 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
if (to_remove.empty())
return;
PictureLayerImpl* recycled_twin = static_cast<PictureLayerImpl*>(
layer_tree_impl()->FindRecycleTreeLayerById(id()));
PictureLayerImpl* recycled_twin = GetRecycledTwinLayer();
// Remove tilings on this tree and the twin tree.
for (size_t i = 0; i < to_remove.size(); ++i) {
const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]);
......
......@@ -124,6 +124,8 @@ class CC_EXPORT PictureLayerImpl
virtual const Region* GetInvalidation() OVERRIDE;
virtual const PictureLayerTiling* GetTwinTiling(
const PictureLayerTiling* tiling) const OVERRIDE;
virtual PictureLayerTiling* GetRecycledTwinTiling(
const PictureLayerTiling* tiling) OVERRIDE;
virtual size_t GetMaxTilesForInterestArea() const OVERRIDE;
virtual float GetSkewportTargetTimeInSeconds() const OVERRIDE;
virtual int GetSkewportExtrapolationLimitInContentPixels() const OVERRIDE;
......@@ -173,6 +175,7 @@ class CC_EXPORT PictureLayerImpl
const gfx::Rect& rect,
const Region& missing_region) const;
gfx::Rect GetViewportForTilePriorityInContentSpace() const;
PictureLayerImpl* GetRecycledTwinLayer();
void DoPostCommitInitializationIfNeeded() {
if (needs_post_commit_initialization_)
......
......@@ -53,7 +53,10 @@ class PictureLayerImplTest : public testing::Test {
host_impl_(ImplSidePaintingSettings(),
&proxy_,
&shared_bitmap_manager_),
id_(7) {}
id_(7),
pending_layer_(NULL),
old_pending_layer_(NULL),
active_layer_(NULL) {}
explicit PictureLayerImplTest(const LayerTreeSettings& settings)
: proxy_(base::MessageLoopProxy::current()),
......@@ -86,6 +89,8 @@ class PictureLayerImplTest : public testing::Test {
void ActivateTree() {
host_impl_.ActivateSyncTree();
CHECK(!host_impl_.pending_tree());
CHECK(host_impl_.recycle_tree());
old_pending_layer_ = pending_layer_;
pending_layer_ = NULL;
active_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.active_tree()->LayerById(id_));
......@@ -266,6 +271,7 @@ class PictureLayerImplTest : public testing::Test {
FakeLayerTreeHostImpl host_impl_;
int id_;
FakePictureLayerImpl* pending_layer_;
FakePictureLayerImpl* old_pending_layer_;
FakePictureLayerImpl* active_layer_;
private:
......@@ -4145,5 +4151,31 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
VerifyEvictionConsidersOcclusion(active_layer_,
total_expected_occluded_tile_count);
}
TEST_F(PictureLayerImplTest, RecycledTwinLayer) {
gfx::Size tile_size(102, 102);
gfx::Size layer_bounds(1000, 1000);
scoped_refptr<FakePicturePileImpl> pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
SetupPendingTree(pile);
EXPECT_FALSE(pending_layer_->GetRecycledTwinLayer());
ActivateTree();
EXPECT_TRUE(active_layer_->GetRecycledTwinLayer());
EXPECT_EQ(old_pending_layer_, active_layer_->GetRecycledTwinLayer());
SetupPendingTree(pile);
EXPECT_FALSE(pending_layer_->GetRecycledTwinLayer());
EXPECT_FALSE(active_layer_->GetRecycledTwinLayer());
ActivateTree();
EXPECT_TRUE(active_layer_->GetRecycledTwinLayer());
EXPECT_EQ(old_pending_layer_, active_layer_->GetRecycledTwinLayer());
host_impl_.ResetRecycleTreeForTesting();
EXPECT_FALSE(active_layer_->GetRecycledTwinLayer());
}
} // namespace
} // namespace cc
......@@ -607,6 +607,15 @@ void PictureLayerTiling::UpdateTilePriorities(
current_eventually_rect_ = eventually_rect;
}
void PictureLayerTiling::RemoveTileAt(int i, int j) {
TileMapKey key(i, j);
TileMap::iterator found = tiles_.find(key);
if (found == tiles_.end())
return;
ReleaseTile(found->second.get(), client_->GetTree());
tiles_.erase(found);
}
void PictureLayerTiling::SetLiveTilesRect(
const gfx::Rect& new_live_tiles_rect) {
DCHECK(new_live_tiles_rect.IsEmpty() ||
......@@ -617,6 +626,7 @@ void PictureLayerTiling::SetLiveTilesRect(
return;
// Iterate to delete all tiles outside of our new live_tiles rect.
PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this);
for (TilingData::DifferenceIterator iter(&tiling_data_,
live_tiles_rect_,
new_live_tiles_rect);
......@@ -629,6 +639,8 @@ void PictureLayerTiling::SetLiveTilesRect(
if (found != tiles_.end()) {
ReleaseTile(found->second.get(), client_->GetTree());
tiles_.erase(found);
if (recycled_twin)
recycled_twin->RemoveTileAt(iter.index_x(), iter.index_y());
}
}
......
......@@ -44,6 +44,8 @@ class CC_EXPORT PictureLayerTilingClient {
virtual const Region* GetInvalidation() = 0;
virtual const PictureLayerTiling* GetTwinTiling(
const PictureLayerTiling* tiling) const = 0;
virtual PictureLayerTiling* GetRecycledTwinTiling(
const PictureLayerTiling* tiling) = 0;
virtual size_t GetMaxTilesForInterestArea() const = 0;
virtual float GetSkewportTargetTimeInSeconds() const = 0;
virtual int GetSkewportExtrapolationLimitInContentPixels() const = 0;
......@@ -295,6 +297,7 @@ class CC_EXPORT PictureLayerTiling {
PictureLayerTilingClient* client);
void SetLiveTilesRect(const gfx::Rect& live_tiles_rect);
Tile* CreateTile(int i, int j, const PictureLayerTiling* twin_tiling);
void RemoveTileAt(int i, int j);
// Computes a skewport. The calculation extrapolates the last visible
// rect and the current visible rect to expand the skewport to where it
......
......@@ -1948,5 +1948,88 @@ TEST(PictureLayerTilingTest, ResetClearsPriorities) {
tiles.clear();
}
TEST(PictureLayerTilingTest, RecycledTilesCleared) {
// This test performs the following:
// Setup:
// - Two tilings, one active one recycled with all tiles shared.
// Procedure:
// - Viewport moves somewhere far away and active tiling clears tiles.
// - Viewport moves back and a new active tiling tile is created.
// Result:
// - Recycle tiling does _not_ have the tile in the same location (thus it
// will be shared next time a pending tiling is created).
FakePictureLayerTilingClient client;
scoped_ptr<TestablePictureLayerTiling> tiling;
client.SetTileSize(gfx::Size(100, 100));
client.set_tree(ACTIVE_TREE);
client.set_max_tiles_for_interest_area(10);
tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
gfx::Size(10000, 10000),
&client);
// Create all tiles on this tiling.
tiling->UpdateTilePriorities(ACTIVE_TREE,
gfx::Rect(0, 0, 100, 100),
1.0f,
1.0f,
NULL, // occlusion tracker
NULL, // render target
gfx::Transform()); // draw transform
FakePictureLayerTilingClient second_client;
second_client.SetTileSize(gfx::Size(100, 100));
second_client.set_tree(PENDING_TREE);
second_client.set_twin_tiling(tiling.get());
second_client.set_max_tiles_for_interest_area(10);
scoped_ptr<TestablePictureLayerTiling> second_tiling;
second_tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
gfx::Size(10000, 10000),
&second_client);
// Create all tiles on the second tiling. All tiles should be shared.
second_tiling->UpdateTilePriorities(ACTIVE_TREE,
gfx::Rect(0, 0, 100, 100),
1.0f,
1.0f,
NULL, // occlusion tracker
NULL, // render target
gfx::Transform()); // draw transform
// Verify that tiles exist and are shared.
ASSERT_TRUE(tiling->TileAt(0, 0));
ASSERT_EQ(tiling->TileAt(0, 0), second_tiling->TileAt(0, 0));
// Set the second tiling as recycled.
client.set_twin_tiling(NULL);
client.set_recycled_twin_tiling(second_tiling.get());
second_client.set_twin_tiling(NULL);
// Move the viewport far away from the (0, 0) tile.
tiling->UpdateTilePriorities(ACTIVE_TREE,
gfx::Rect(9000, 9000, 100, 100),
1.0f,
2.0,
NULL, // occlusion tracker
NULL, // render target
gfx::Transform()); // draw transform
// Ensure the tile was deleted.
EXPECT_FALSE(tiling->TileAt(0, 0));
// Move the viewport back to (0, 0) tile.
tiling->UpdateTilePriorities(ACTIVE_TREE,
gfx::Rect(0, 0, 100, 100),
1.0f,
3.0,
NULL, // occlusion tracker
NULL, // render target
gfx::Transform()); // draw transform
// Ensure that we now have a tile here, but the recycle tiling does not.
EXPECT_TRUE(tiling->TileAt(0, 0));
EXPECT_FALSE(second_tiling->TileAt(0, 0));
}
} // namespace
} // namespace cc
......@@ -60,6 +60,7 @@ class FakePictureLayerImpl : public PictureLayerImpl {
using PictureLayerImpl::MinimumContentsScale;
using PictureLayerImpl::GetViewportForTilePriorityInContentSpace;
using PictureLayerImpl::SanityCheckTilingState;
using PictureLayerImpl::GetRecycledTwinLayer;
using PictureLayerImpl::UpdateIdealScales;
using PictureLayerImpl::MaximumTilingContentsScale;
......
......@@ -15,10 +15,12 @@ FakePictureLayerTilingClient::FakePictureLayerTilingClient()
: tile_manager_(new FakeTileManager(&tile_manager_client_)),
pile_(FakePicturePileImpl::CreateInfiniteFilledPile()),
twin_tiling_(NULL),
recycled_twin_tiling_(NULL),
allow_create_tile_(true),
max_tiles_for_interest_area_(10000),
skewport_target_time_in_seconds_(1.0f),
skewport_extrapolation_limit_in_content_pixels_(2000) {}
skewport_extrapolation_limit_in_content_pixels_(2000) {
}
FakePictureLayerTilingClient::FakePictureLayerTilingClient(
ResourceProvider* resource_provider)
......@@ -28,9 +30,11 @@ FakePictureLayerTilingClient::FakePictureLayerTilingClient(
new FakeTileManager(&tile_manager_client_, resource_pool_.get())),
pile_(FakePicturePileImpl::CreateInfiniteFilledPile()),
twin_tiling_(NULL),
recycled_twin_tiling_(NULL),
allow_create_tile_(true),
max_tiles_for_interest_area_(10000),
skewport_target_time_in_seconds_(1.0f) {}
skewport_target_time_in_seconds_(1.0f) {
}
FakePictureLayerTilingClient::~FakePictureLayerTilingClient() {
}
......@@ -79,6 +83,11 @@ const PictureLayerTiling* FakePictureLayerTilingClient::GetTwinTiling(
return twin_tiling_;
}
PictureLayerTiling* FakePictureLayerTilingClient::GetRecycledTwinTiling(
const PictureLayerTiling* tiling) {
return recycled_twin_tiling_;
}
WhichTree FakePictureLayerTilingClient::GetTree() const {
return tree_;
}
......
......@@ -36,9 +36,14 @@ class FakePictureLayerTilingClient : public PictureLayerTilingClient {
virtual const Region* GetInvalidation() OVERRIDE;
virtual const PictureLayerTiling* GetTwinTiling(
const PictureLayerTiling* tiling) const OVERRIDE;
virtual PictureLayerTiling* GetRecycledTwinTiling(
const PictureLayerTiling* tiling) OVERRIDE;
virtual WhichTree GetTree() const OVERRIDE;
void set_twin_tiling(PictureLayerTiling* tiling) { twin_tiling_ = tiling; }
void set_recycled_twin_tiling(PictureLayerTiling* tiling) {
recycled_twin_tiling_ = tiling;
}
void set_text_rect(const gfx::Rect& rect) { text_rect_ = rect; }
void set_allow_create_tile(bool allow) { allow_create_tile_ = allow; }
void set_invalidation(const Region& region) { invalidation_ = region; }
......@@ -64,6 +69,7 @@ class FakePictureLayerTilingClient : public PictureLayerTilingClient {
scoped_refptr<PicturePileImpl> pile_;
gfx::Size tile_size_;
PictureLayerTiling* twin_tiling_;
PictureLayerTiling* recycled_twin_tiling_;
gfx::Rect text_rect_;
bool allow_create_tile_;
Region invalidation_;
......
......@@ -1167,6 +1167,12 @@ void LayerTreeHostImpl::ResetTreesForTesting() {
recycle_tree_.reset();
}
void LayerTreeHostImpl::ResetRecycleTreeForTesting() {
if (recycle_tree_)
recycle_tree_->DetachLayerTree();
recycle_tree_.reset();
}
void LayerTreeHostImpl::EnforceManagedMemoryPolicy(
const ManagedMemoryPolicy& policy) {
......
......@@ -217,6 +217,7 @@ class CC_EXPORT LayerTreeHostImpl
// Resets all of the trees to an empty state.
void ResetTreesForTesting();
void ResetRecycleTreeForTesting();
DrawMode GetDrawMode() const;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment