Commit 83613c7e authored by danakj@chromium.org's avatar danakj@chromium.org

cc: Explicitly invalidate all dropped recordings on the main thread.

Currently PictureLayerTiling drops tiles when bounds change under the
assumption that these recordings have been dropped by the main thread,
however it misses some cases. For instance if the layer grows, and the
main thread has to drop recording tiles along the growing edge, but it
is outside the interest rect, then the PictureLayerTiling has no idea
that these recordings are gone, which leads to us having Tiles on the
compositor thread which can not be rastered.

Instead of having the impl side try to guess at these things, we now
have the PicturePile explicitly expand invalidation to cover every
recoding tile that has its picture dropped or that is removed from the
recording. Then the impl-side PictureLayerTiling only drops what the
main thread tells it to, and does not make any guesses of its own.

Perf sheriffs: This is expected to change results for "invalidation"
tests as it changes what code paths those tests execute.

R=enne
BUG=386998

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282744 0039d316-1c4b-4281-b951-d872f2087c98
parent cf9dc488
...@@ -44,7 +44,7 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { ...@@ -44,7 +44,7 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
// Update may not get called for an empty layer, so resize here instead. // Update may not get called for an empty layer, so resize here instead.
// Using layer_impl because either bounds() or paint_properties().bounds // Using layer_impl because either bounds() or paint_properties().bounds
// may disagree and either one could have been pushed to layer_impl. // may disagree and either one could have been pushed to layer_impl.
pile_->SetTilingRect(gfx::Rect()); pile_->SetEmptyBounds();
} else if (update_source_frame_number_ == } else if (update_source_frame_number_ ==
layer_tree_host()->source_frame_number()) { layer_tree_host()->source_frame_number()) {
// TODO(ernstm): This DCHECK is only valid as long as the pile's tiling_rect // TODO(ernstm): This DCHECK is only valid as long as the pile's tiling_rect
...@@ -109,8 +109,6 @@ bool PictureLayer::Update(ResourceUpdateQueue* queue, ...@@ -109,8 +109,6 @@ bool PictureLayer::Update(ResourceUpdateQueue* queue,
devtools_instrumentation::ScopedLayerTreeTask update_layer( devtools_instrumentation::ScopedLayerTreeTask update_layer(
devtools_instrumentation::kUpdateLayer, id(), layer_tree_host()->id()); devtools_instrumentation::kUpdateLayer, id(), layer_tree_host()->id());
pile_->SetTilingRect(layer_rect);
// Calling paint in WebKit can sometimes cause invalidations, so save // Calling paint in WebKit can sometimes cause invalidations, so save
// off the invalidation prior to calling update. // off the invalidation prior to calling update.
pending_invalidation_.Swap(&pile_invalidation_); pending_invalidation_.Swap(&pile_invalidation_);
...@@ -133,6 +131,7 @@ bool PictureLayer::Update(ResourceUpdateQueue* queue, ...@@ -133,6 +131,7 @@ bool PictureLayer::Update(ResourceUpdateQueue* queue,
SafeOpaqueBackgroundColor(), SafeOpaqueBackgroundColor(),
contents_opaque(), contents_opaque(),
client_->FillsBoundsCompletely(), client_->FillsBoundsCompletely(),
layer_rect,
visible_layer_rect, visible_layer_rect,
update_source_frame_number_, update_source_frame_number_,
RecordingMode(), RecordingMode(),
......
...@@ -108,10 +108,6 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { ...@@ -108,10 +108,6 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
// Tilings would be expensive to push, so we swap. // Tilings would be expensive to push, so we swap.
layer_impl->tilings_.swap(tilings_); layer_impl->tilings_.swap(tilings_);
// Ensure that we don't have any tiles that are out of date.
if (tilings_)
tilings_->RemoveTilesInRegion(invalidation_);
layer_impl->tilings_->SetClient(layer_impl); layer_impl->tilings_->SetClient(layer_impl);
if (tilings_) if (tilings_)
tilings_->SetClient(this); tilings_->SetClient(this);
...@@ -676,15 +672,20 @@ void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) { ...@@ -676,15 +672,20 @@ void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
raster_contents_scale_ = other->raster_contents_scale_; raster_contents_scale_ = other->raster_contents_scale_;
low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_; low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_;
// Union in the other newly exposed regions as invalid. // The tilings on this layer were swapped here from the active layer on
Region difference_region = Region(gfx::Rect(bounds())); // activation, so they have not seen the invalidation that was given to
difference_region.Subtract(gfx::Rect(other->bounds())); // the active layer. So union that invalidation in here, but don't save
invalidation_.Union(difference_region); // it and pass it back to the active layer again.
Region invalidation_from_pending_and_active =
UnionRegions(invalidation_, other->invalidation_);
bool synced_high_res_tiling = false; bool synced_high_res_tiling = false;
if (CanHaveTilings()) { if (CanHaveTilings()) {
synced_high_res_tiling = tilings_->SyncTilings( synced_high_res_tiling =
*other->tilings_, bounds(), invalidation_, MinimumContentsScale()); tilings_->SyncTilings(*other->tilings_,
bounds(),
invalidation_from_pending_and_active,
MinimumContentsScale());
} else { } else {
RemoveAllTilings(); RemoveAllTilings();
} }
......
...@@ -1492,40 +1492,128 @@ TEST_F(PictureLayerImplTest, ActivateUninitializedLayer) { ...@@ -1492,40 +1492,128 @@ TEST_F(PictureLayerImplTest, ActivateUninitializedLayer) {
EXPECT_FALSE(active_layer_->needs_post_commit_initialization()); EXPECT_FALSE(active_layer_->needs_post_commit_initialization());
} }
TEST_F(PictureLayerImplTest, RemoveInvalidTilesOnActivation) { TEST_F(PictureLayerImplTest, ShareTilesOnSync) {
SetupDefaultTrees(gfx::Size(1500, 1500));
AddDefaultTilingsWithInvalidation(gfx::Rect());
host_impl_.ActivateSyncTree();
host_impl_.CreatePendingTree();
active_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.active_tree()->LayerById(id_));
// Force the active tree to sync to the pending tree "post-commit".
pending_layer_->DoPostCommitInitializationIfNeeded();
// Both invalidations should drop tiles from the pending tree.
EXPECT_EQ(3u, active_layer_->num_tilings());
EXPECT_EQ(3u, pending_layer_->num_tilings());
for (size_t i = 0; i < active_layer_->num_tilings(); ++i) {
PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(i);
PictureLayerTiling* pending_tiling =
pending_layer_->tilings()->tiling_at(i);
ASSERT_TRUE(active_tiling);
ASSERT_TRUE(pending_tiling);
EXPECT_TRUE(active_tiling->TileAt(0, 0));
EXPECT_TRUE(active_tiling->TileAt(1, 0));
EXPECT_TRUE(active_tiling->TileAt(0, 1));
EXPECT_TRUE(active_tiling->TileAt(1, 1));
EXPECT_TRUE(pending_tiling->TileAt(0, 0));
EXPECT_TRUE(pending_tiling->TileAt(1, 0));
EXPECT_TRUE(pending_tiling->TileAt(0, 1));
EXPECT_TRUE(pending_tiling->TileAt(1, 1));
EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
}
}
TEST_F(PictureLayerImplTest, RemoveInvalidActiveTreeTilesOnSync) {
SetupDefaultTrees(gfx::Size(1500, 1500)); SetupDefaultTrees(gfx::Size(1500, 1500));
AddDefaultTilingsWithInvalidation(gfx::Rect(0, 0, 1, 1)); AddDefaultTilingsWithInvalidation(gfx::Rect(0, 0, 1, 1));
FakePictureLayerImpl* recycled_layer = pending_layer_; // This activates the 0,0,1,1 invalidation.
host_impl_.ActivateSyncTree(); host_impl_.ActivateSyncTree();
host_impl_.CreatePendingTree();
active_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.active_tree()->LayerById(id_));
// Force the active tree to sync to the pending tree "post-commit".
pending_layer_->DoPostCommitInitializationIfNeeded();
// Both invalidations should drop tiles from the pending tree.
EXPECT_EQ(3u, active_layer_->num_tilings());
EXPECT_EQ(3u, pending_layer_->num_tilings());
for (size_t i = 0; i < active_layer_->num_tilings(); ++i) {
PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(i);
PictureLayerTiling* pending_tiling =
pending_layer_->tilings()->tiling_at(i);
ASSERT_TRUE(active_tiling);
ASSERT_TRUE(pending_tiling);
EXPECT_TRUE(active_tiling->TileAt(0, 0));
EXPECT_TRUE(active_tiling->TileAt(1, 0));
EXPECT_TRUE(active_tiling->TileAt(0, 1));
EXPECT_TRUE(active_tiling->TileAt(1, 1));
EXPECT_TRUE(pending_tiling->TileAt(0, 0));
EXPECT_TRUE(pending_tiling->TileAt(1, 0));
EXPECT_TRUE(pending_tiling->TileAt(0, 1));
EXPECT_TRUE(pending_tiling->TileAt(1, 1));
EXPECT_NE(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
}
}
TEST_F(PictureLayerImplTest, RemoveInvalidPendingTreeTilesOnSync) {
SetupDefaultTrees(gfx::Size(1500, 1500));
AddDefaultTilingsWithInvalidation(gfx::Rect());
host_impl_.ActivateSyncTree();
host_impl_.CreatePendingTree();
active_layer_ = static_cast<FakePictureLayerImpl*>( active_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.active_tree()->LayerById(id_)); host_impl_.active_tree()->LayerById(id_));
// Set some invalidation on the pending tree "during commit". We should
// replace raster tiles that touch this.
pending_layer_->set_invalidation(gfx::Rect(1, 1));
// Force the active tree to sync to the pending tree "post-commit".
pending_layer_->DoPostCommitInitializationIfNeeded();
// Both invalidations should drop tiles from the pending tree.
EXPECT_EQ(3u, active_layer_->num_tilings()); EXPECT_EQ(3u, active_layer_->num_tilings());
EXPECT_EQ(3u, recycled_layer->num_tilings()); EXPECT_EQ(3u, pending_layer_->num_tilings());
EXPECT_FALSE(host_impl_.pending_tree());
for (size_t i = 0; i < active_layer_->num_tilings(); ++i) { for (size_t i = 0; i < active_layer_->num_tilings(); ++i) {
PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(i); PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(i);
PictureLayerTiling* recycled_tiling = PictureLayerTiling* pending_tiling =
recycled_layer->tilings()->tiling_at(i); pending_layer_->tilings()->tiling_at(i);
ASSERT_TRUE(active_tiling); ASSERT_TRUE(active_tiling);
ASSERT_TRUE(recycled_tiling); ASSERT_TRUE(pending_tiling);
EXPECT_TRUE(active_tiling->TileAt(0, 0)); EXPECT_TRUE(active_tiling->TileAt(0, 0));
EXPECT_TRUE(active_tiling->TileAt(1, 0)); EXPECT_TRUE(active_tiling->TileAt(1, 0));
EXPECT_TRUE(active_tiling->TileAt(0, 1)); EXPECT_TRUE(active_tiling->TileAt(0, 1));
EXPECT_TRUE(active_tiling->TileAt(1, 1)); EXPECT_TRUE(active_tiling->TileAt(1, 1));
EXPECT_FALSE(recycled_tiling->TileAt(0, 0)); EXPECT_TRUE(pending_tiling->TileAt(0, 0));
EXPECT_TRUE(recycled_tiling->TileAt(1, 0)); EXPECT_TRUE(pending_tiling->TileAt(1, 0));
EXPECT_TRUE(recycled_tiling->TileAt(0, 1)); EXPECT_TRUE(pending_tiling->TileAt(0, 1));
EXPECT_TRUE(recycled_tiling->TileAt(1, 1)); EXPECT_TRUE(pending_tiling->TileAt(1, 1));
EXPECT_EQ(active_tiling->TileAt(1, 0), recycled_tiling->TileAt(1, 0)); EXPECT_NE(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
EXPECT_EQ(active_tiling->TileAt(0, 1), recycled_tiling->TileAt(0, 1)); EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
EXPECT_EQ(active_tiling->TileAt(1, 1), recycled_tiling->TileAt(1, 1)); EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
} }
} }
......
...@@ -138,50 +138,47 @@ void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { ...@@ -138,50 +138,47 @@ void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() {
} }
} }
void PictureLayerTiling::SetLayerBounds(const gfx::Size& layer_bounds) { void PictureLayerTiling::UpdateTilesToCurrentPile(
if (layer_bounds_ == layer_bounds) const Region& layer_invalidation,
return; const gfx::Size& new_layer_bounds) {
DCHECK(!new_layer_bounds.IsEmpty());
DCHECK(!layer_bounds.IsEmpty());
gfx::Size old_layer_bounds = layer_bounds_; gfx::Size old_layer_bounds = layer_bounds_;
layer_bounds_ = layer_bounds; layer_bounds_ = new_layer_bounds;
gfx::Size content_bounds = gfx::Size content_bounds =
gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds_, contents_scale_)); gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds_, contents_scale_));
gfx::Size tile_size = tiling_data_.max_texture_size();
gfx::Size tile_size = client_->CalculateTileSize(content_bounds); if (layer_bounds_ != old_layer_bounds) {
if (tile_size != tiling_data_.max_texture_size()) { // Drop tiles outside the new layer bounds if the layer shrank.
SetLiveTilesRect(
gfx::IntersectRects(live_tiles_rect_, gfx::Rect(content_bounds)));
tiling_data_.SetTilingRect(gfx::Rect(content_bounds)); tiling_data_.SetTilingRect(gfx::Rect(content_bounds));
tile_size = client_->CalculateTileSize(content_bounds);
}
if (tile_size != tiling_data_.max_texture_size()) {
tiling_data_.SetMaxTextureSize(tile_size); tiling_data_.SetMaxTextureSize(tile_size);
// When the tile size changes, the TilingData positions no longer work
// as valid keys to the TileMap, so just drop all tiles.
Reset(); Reset();
return; } else {
Invalidate(layer_invalidation);
} }
// Any tiles outside our new bounds are invalid and should be dropped. PicturePileImpl* pile = client_->GetPile();
gfx::Rect bounded_live_tiles_rect(live_tiles_rect_); for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
bounded_live_tiles_rect.Intersect(gfx::Rect(content_bounds)); it->second->set_picture_pile(pile);
SetLiveTilesRect(bounded_live_tiles_rect);
tiling_data_.SetTilingRect(gfx::Rect(content_bounds));
// Create tiles for newly exposed areas.
Region layer_region((gfx::Rect(layer_bounds_)));
layer_region.Subtract(gfx::Rect(old_layer_bounds));
Invalidate(layer_region);
}
void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_region) {
DoInvalidate(layer_region, false /* recreate_tiles */);
} }
void PictureLayerTiling::Invalidate(const Region& layer_region) { void PictureLayerTiling::Invalidate(const Region& layer_region) {
DoInvalidate(layer_region, true /* recreate_tiles */);
}
void PictureLayerTiling::DoInvalidate(const Region& layer_region,
bool recreate_tiles) {
std::vector<TileMapKey> new_tile_keys; std::vector<TileMapKey> new_tile_keys;
gfx::Rect expanded_live_tiles_rect( // TODO(danakj): What we really want is to ignore border pixels that intersect
tiling_data_.ExpandRectToTileBoundsWithBorders(live_tiles_rect_)); // the rect when choosing which tiles it covers, then expand to those tiles
// plus their border pixels.
gfx::Rect expanded_live_tiles_rect =
tiling_data_.ExpandRectToTileBounds(live_tiles_rect_);
for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) { for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) {
gfx::Rect layer_rect = iter.rect(); gfx::Rect layer_rect = iter.rect();
gfx::Rect content_rect = gfx::Rect content_rect =
...@@ -201,15 +198,17 @@ void PictureLayerTiling::DoInvalidate(const Region& layer_region, ...@@ -201,15 +198,17 @@ void PictureLayerTiling::DoInvalidate(const Region& layer_region,
if (find == tiles_.end()) if (find == tiles_.end())
continue; continue;
tiles_.erase(find); tiles_.erase(find);
if (recreate_tiles) new_tile_keys.push_back(key);
new_tile_keys.push_back(key);
} }
} }
if (recreate_tiles) { if (!new_tile_keys.empty()) {
const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); for (size_t i = 0; i < new_tile_keys.size(); ++i) {
for (size_t i = 0; i < new_tile_keys.size(); ++i) // Don't try to share a tile with the twin layer, it's been invalidated so
// we have to make our own tile here.
PictureLayerTiling* twin_tiling = NULL;
CreateTile(new_tile_keys[i].first, new_tile_keys[i].second, twin_tiling); CreateTile(new_tile_keys[i].first, new_tile_keys[i].second, twin_tiling);
}
} }
} }
...@@ -622,13 +621,6 @@ void PictureLayerTiling::DidBecomeActive() { ...@@ -622,13 +621,6 @@ void PictureLayerTiling::DidBecomeActive() {
} }
} }
void PictureLayerTiling::UpdateTilesToCurrentPile() {
PicturePileImpl* pile = client_->GetPile();
for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
it->second->set_picture_pile(pile);
}
}
scoped_ptr<base::Value> PictureLayerTiling::AsValue() const { scoped_ptr<base::Value> PictureLayerTiling::AsValue() const {
scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
state->SetInteger("num_tiles", tiles_.size()); state->SetInteger("num_tiles", tiles_.size());
......
...@@ -127,9 +127,8 @@ class CC_EXPORT PictureLayerTiling { ...@@ -127,9 +127,8 @@ class CC_EXPORT PictureLayerTiling {
const gfx::Size& layer_bounds, const gfx::Size& layer_bounds,
PictureLayerTilingClient* client); PictureLayerTilingClient* client);
gfx::Size layer_bounds() const { return layer_bounds_; } gfx::Size layer_bounds() const { return layer_bounds_; }
void SetLayerBounds(const gfx::Size& layer_bounds); void UpdateTilesToCurrentPile(const Region& layer_invalidation,
void Invalidate(const Region& layer_region); const gfx::Size& new_layer_bounds);
void RemoveTilesInRegion(const Region& layer_region);
void CreateMissingTilesInLiveTilesRect(); void CreateMissingTilesInLiveTilesRect();
void SetClient(PictureLayerTilingClient* client); void SetClient(PictureLayerTilingClient* client);
...@@ -150,6 +149,8 @@ class CC_EXPORT PictureLayerTiling { ...@@ -150,6 +149,8 @@ class CC_EXPORT PictureLayerTiling {
SetLiveTilesRect(tiling_data_.tiling_rect()); SetLiveTilesRect(tiling_data_.tiling_rect());
} }
const TilingData& TilingDataForTesting() const { return tiling_data_; }
std::vector<Tile*> AllTilesForTesting() const { std::vector<Tile*> AllTilesForTesting() const {
std::vector<Tile*> all_tiles; std::vector<Tile*> all_tiles;
for (TileMap::const_iterator it = tiles_.begin(); for (TileMap::const_iterator it = tiles_.begin();
...@@ -230,8 +231,6 @@ class CC_EXPORT PictureLayerTiling { ...@@ -230,8 +231,6 @@ class CC_EXPORT PictureLayerTiling {
// while DidBecomeActive promotes pending priority on a similar set of tiles. // while DidBecomeActive promotes pending priority on a similar set of tiles.
void DidBecomeRecycled(); void DidBecomeRecycled();
void UpdateTilesToCurrentPile();
bool NeedsUpdateForFrameAtTime(double frame_time_in_seconds) { bool NeedsUpdateForFrameAtTime(double frame_time_in_seconds) {
return frame_time_in_seconds != last_impl_frame_time_in_seconds_; return frame_time_in_seconds != last_impl_frame_time_in_seconds_;
} }
...@@ -282,7 +281,7 @@ class CC_EXPORT PictureLayerTiling { ...@@ -282,7 +281,7 @@ class CC_EXPORT PictureLayerTiling {
const; const;
void UpdateEvictionCacheIfNeeded(TreePriority tree_priority); void UpdateEvictionCacheIfNeeded(TreePriority tree_priority);
void DoInvalidate(const Region& layer_region, bool recreate_tiles); void Invalidate(const Region& layer_region);
// Given properties. // Given properties.
float contents_scale_; float contents_scale_;
......
...@@ -39,7 +39,8 @@ class PictureLayerTilingPerfTest : public testing::Test { ...@@ -39,7 +39,8 @@ class PictureLayerTilingPerfTest : public testing::Test {
void RunInvalidateTest(const std::string& test_name, const Region& region) { void RunInvalidateTest(const std::string& test_name, const Region& region) {
timer_.Reset(); timer_.Reset();
do { do {
picture_layer_tiling_->Invalidate(region); picture_layer_tiling_->UpdateTilesToCurrentPile(
region, picture_layer_tiling_->TilingRect().size());
timer_.NextLap(); timer_.NextLap();
} while (!timer_.HasTimeLimitExpired()); } while (!timer_.HasTimeLimitExpired());
......
...@@ -69,12 +69,8 @@ bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other, ...@@ -69,12 +69,8 @@ bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other,
if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) { if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) {
this_tiling->set_resolution(other.tilings_[i]->resolution()); this_tiling->set_resolution(other.tilings_[i]->resolution());
// These two calls must come before updating the pile, because they may this_tiling->UpdateTilesToCurrentPile(layer_invalidation,
// destroy tiles that the new pile cannot raster. new_layer_bounds);
this_tiling->SetLayerBounds(new_layer_bounds);
this_tiling->Invalidate(layer_invalidation);
this_tiling->UpdateTilesToCurrentPile();
this_tiling->CreateMissingTilesInLiveTilesRect(); this_tiling->CreateMissingTilesInLiveTilesRect();
if (this_tiling->resolution() == HIGH_RESOLUTION) if (this_tiling->resolution() == HIGH_RESOLUTION)
have_high_res_tiling = true; have_high_res_tiling = true;
...@@ -98,11 +94,6 @@ bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other, ...@@ -98,11 +94,6 @@ bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other,
return have_high_res_tiling; return have_high_res_tiling;
} }
void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
for (size_t i = 0; i < tilings_.size(); ++i)
tilings_[i]->RemoveTilesInRegion(region);
}
PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) { PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
for (size_t i = 0; i < tilings_.size(); ++i) for (size_t i = 0; i < tilings_.size(); ++i)
DCHECK_NE(tilings_[i]->contents_scale(), contents_scale); DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
......
...@@ -31,8 +31,6 @@ class CC_EXPORT PictureLayerTilingSet { ...@@ -31,8 +31,6 @@ class CC_EXPORT PictureLayerTilingSet {
const Region& layer_invalidation, const Region& layer_invalidation,
float minimum_contents_scale); float minimum_contents_scale);
void RemoveTilesInRegion(const Region& region);
gfx::Size layer_bounds() const { return layer_bounds_; } gfx::Size layer_bounds() const { return layer_bounds_; }
PictureLayerTiling* AddTiling(float contents_scale); PictureLayerTiling* AddTiling(float contents_scale);
......
...@@ -230,7 +230,10 @@ class PictureLayerTilingSetSyncTest : public testing::Test { ...@@ -230,7 +230,10 @@ class PictureLayerTilingSetSyncTest : public testing::Test {
ASSERT_TRUE(!!tile); ASSERT_TRUE(!!tile);
EXPECT_EQ(tile->picture_pile(), pile); EXPECT_EQ(tile->picture_pile(), pile);
EXPECT_TRUE(tile->content_rect().Intersects(tiling->live_tiles_rect())) EXPECT_TRUE(tile->content_rect().Intersects(tiling->live_tiles_rect()))
<< "All tiles must be inside the live tiles rect."; << "All tiles must be inside the live tiles rect."
<< " Tile rect: " << tile->content_rect().ToString()
<< " Live rect: " << tiling->live_tiles_rect().ToString()
<< " Scale: " << tiling->contents_scale();
} }
for (PictureLayerTiling::CoverageIterator iter( for (PictureLayerTiling::CoverageIterator iter(
......
...@@ -190,7 +190,8 @@ class PictureLayerTilingIteratorTest : public testing::Test { ...@@ -190,7 +190,8 @@ class PictureLayerTilingIteratorTest : public testing::Test {
}; };
TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) { TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) {
// Verifies that a resize deletes tiles that used to be on the edge. // Verifies that a resize with invalidation for newly exposed pixels will
// deletes tiles that intersect that invalidation.
gfx::Size tile_size(100, 100); gfx::Size tile_size(100, 100);
gfx::Size original_layer_size(10, 10); gfx::Size original_layer_size(10, 10);
Initialize(tile_size, 1.f, original_layer_size); Initialize(tile_size, 1.f, original_layer_size);
...@@ -202,10 +203,37 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) { ...@@ -202,10 +203,37 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) {
// Stop creating tiles so that any invalidations are left as holes. // Stop creating tiles so that any invalidations are left as holes.
client_.set_allow_create_tile(false); client_.set_allow_create_tile(false);
tiling_->SetLayerBounds(gfx::Size(200, 200)); Region invalidation =
SubtractRegions(gfx::Rect(tile_size), gfx::Rect(original_layer_size));
tiling_->UpdateTilesToCurrentPile(invalidation, gfx::Size(200, 200));
EXPECT_FALSE(tiling_->TileAt(0, 0)); EXPECT_FALSE(tiling_->TileAt(0, 0));
} }
TEST_F(PictureLayerTilingIteratorTest, ResizeOverBorderPixelsDeletesTiles) {
// Verifies that a resize with invalidation for newly exposed pixels will
// deletes tiles that intersect that invalidation.
gfx::Size tile_size(100, 100);
gfx::Size original_layer_size(99, 99);
Initialize(tile_size, 1.f, original_layer_size);
SetLiveRectAndVerifyTiles(gfx::Rect(original_layer_size));
// Tiling only has one tile, since its total size is less than one.
EXPECT_TRUE(tiling_->TileAt(0, 0));
// Stop creating tiles so that any invalidations are left as holes.
client_.set_allow_create_tile(false);
Region invalidation =
SubtractRegions(gfx::Rect(tile_size), gfx::Rect(original_layer_size));
tiling_->UpdateTilesToCurrentPile(invalidation, gfx::Size(200, 200));
EXPECT_FALSE(tiling_->TileAt(0, 0));
// The original tile was the same size after resize, but it would include new
// border pixels.
EXPECT_EQ(gfx::Rect(original_layer_size),
tiling_->TilingDataForTesting().TileBounds(0, 0));
}
TEST_F(PictureLayerTilingIteratorTest, LiveTilesExactlyCoverLiveTileRect) { TEST_F(PictureLayerTilingIteratorTest, LiveTilesExactlyCoverLiveTileRect) {
Initialize(gfx::Size(100, 100), 1, gfx::Size(1099, 801)); Initialize(gfx::Size(100, 100), 1, gfx::Size(1099, 801));
SetLiveRectAndVerifyTiles(gfx::Rect(100, 100)); SetLiveRectAndVerifyTiles(gfx::Rect(100, 100));
......
...@@ -157,6 +157,7 @@ bool PicturePile::UpdateAndExpandInvalidation( ...@@ -157,6 +157,7 @@ bool PicturePile::UpdateAndExpandInvalidation(
SkColor background_color, SkColor background_color,
bool contents_opaque, bool contents_opaque,
bool contents_fill_bounds_completely, bool contents_fill_bounds_completely,
const gfx::Rect& layer_bounds_rect,
const gfx::Rect& visible_layer_rect, const gfx::Rect& visible_layer_rect,
int frame_number, int frame_number,
Picture::RecordingMode recording_mode, Picture::RecordingMode recording_mode,
...@@ -165,6 +166,15 @@ bool PicturePile::UpdateAndExpandInvalidation( ...@@ -165,6 +166,15 @@ bool PicturePile::UpdateAndExpandInvalidation(
contents_opaque_ = contents_opaque; contents_opaque_ = contents_opaque;
contents_fill_bounds_completely_ = contents_fill_bounds_completely; contents_fill_bounds_completely_ = contents_fill_bounds_completely;
bool updated = false;
Region resize_invalidation;
gfx::Rect old_tiling_rect = tiling_rect();
if (old_tiling_rect != layer_bounds_rect) {
tiling_.SetTilingRect(layer_bounds_rect);
updated = true;
}
gfx::Rect interest_rect = visible_layer_rect; gfx::Rect interest_rect = visible_layer_rect;
interest_rect.Inset( interest_rect.Inset(
-kPixelDistanceToRecord, -kPixelDistanceToRecord,
...@@ -177,11 +187,99 @@ bool PicturePile::UpdateAndExpandInvalidation( ...@@ -177,11 +187,99 @@ bool PicturePile::UpdateAndExpandInvalidation(
gfx::Rect interest_rect_over_tiles = gfx::Rect interest_rect_over_tiles =
tiling_.ExpandRectToTileBounds(interest_rect); tiling_.ExpandRectToTileBounds(interest_rect);
Region invalidation_expanded_to_full_tiles; if (old_tiling_rect != layer_bounds_rect) {
has_any_recordings_ = false;
bool invalidated = false; if (tiling_rect().origin() != old_tiling_rect.origin()) {
// If the origin changes we just do something simple.
picture_map_.clear();
invalidation->Union(old_tiling_rect);
invalidation->Union(tiling_rect());
} else {
// Drop recordings that are outside the new layer bounds or that changed
// size.
std::vector<PictureMapKey> to_erase;
int min_toss_x = tiling_.num_tiles_x();
if (tiling_rect().right() > old_tiling_rect.right()) {
min_toss_x =
tiling_.FirstBorderTileXIndexFromSrcCoord(old_tiling_rect.right());
}
int min_toss_y = tiling_.num_tiles_y();
if (tiling_rect().bottom() > old_tiling_rect.bottom()) {
min_toss_y =
tiling_.FirstBorderTileYIndexFromSrcCoord(old_tiling_rect.bottom());
}
for (PictureMap::const_iterator it = picture_map_.begin();
it != picture_map_.end();
++it) {
const PictureMapKey& key = it->first;
if (key.first < min_toss_x && key.second < min_toss_y) {
has_any_recordings_ |= !!it->second.GetPicture();
continue;
}
to_erase.push_back(key);
}
for (size_t i = 0; i < to_erase.size(); ++i)
picture_map_.erase(to_erase[i]);
// If a recording is dropped and not re-recorded below, invalidate that
// full recording to cause any raster tiles that would use it to be
// dropped.
// If the recording will be replaced below, just invalidate newly exposed
// areas to force raster tiles that include the old recording to know
// there is new recording to display.
gfx::Rect old_tiling_rect_over_tiles =
tiling_.ExpandRectToTileBounds(old_tiling_rect);
if (min_toss_x < tiling_.num_tiles_x()) {
int unrecorded_left = std::max(tiling_.TilePositionX(min_toss_x),
interest_rect_over_tiles.right());
int exposed_left = old_tiling_rect.right();
int left = std::min(unrecorded_left, exposed_left);
int tile_right =
tiling_.TilePositionX(min_toss_x) + tiling_.TileSizeX(min_toss_x);
int exposed_right = tiling_rect().right();
int right = std::min(tile_right, exposed_right);
gfx::Rect right_side(left,
old_tiling_rect_over_tiles.y(),
right - left,
old_tiling_rect_over_tiles.height());
resize_invalidation.Union(right_side);
}
if (min_toss_y < tiling_.num_tiles_y()) {
int unrecorded_top = std::max(tiling_.TilePositionY(min_toss_y),
interest_rect_over_tiles.bottom());
int exposed_top = old_tiling_rect.bottom();
int top = std::min(unrecorded_top, exposed_top);
int tile_bottom =
tiling_.TilePositionY(min_toss_y) + tiling_.TileSizeY(min_toss_y);
int exposed_bottom = tiling_rect().bottom();
int bottom = std::min(tile_bottom, exposed_bottom);
gfx::Rect bottom_side(old_tiling_rect_over_tiles.x(),
top,
old_tiling_rect_over_tiles.width(),
bottom - top);
resize_invalidation.Union(bottom_side);
}
}
}
Region invalidation_expanded_to_full_tiles;
for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) { for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) {
gfx::Rect invalid_rect = i.rect(); gfx::Rect invalid_rect = i.rect();
// Expand invalidation that is outside tiles that intersect the interest
// rect. These tiles are no longer valid and should be considerered fully
// invalid, so we can know to not keep around raster tiles that intersect
// with these recording tiles.
gfx::Rect invalid_rect_outside_interest_rect_tiles = invalid_rect;
// TODO(danakj): We should have a Rect-subtract-Rect-to-2-rects operator
// instead of using Rect::Subtract which gives you the bounding box of the
// subtraction.
invalid_rect_outside_interest_rect_tiles.Subtract(interest_rect_over_tiles);
invalidation_expanded_to_full_tiles.Union(tiling_.ExpandRectToTileBounds(
invalid_rect_outside_interest_rect_tiles));
// Split this inflated invalidation across tile boundaries and apply it // Split this inflated invalidation across tile boundaries and apply it
// to all tiles that it touches. // to all tiles that it touches.
bool include_borders = true; bool include_borders = true;
...@@ -195,23 +293,18 @@ bool PicturePile::UpdateAndExpandInvalidation( ...@@ -195,23 +293,18 @@ bool PicturePile::UpdateAndExpandInvalidation(
continue; continue;
// Inform the grid cell that it has been invalidated in this frame. // Inform the grid cell that it has been invalidated in this frame.
invalidated = picture_it->second.Invalidate(frame_number) || invalidated; updated = picture_it->second.Invalidate(frame_number) || updated;
// Invalidate drops the picture so the whole tile better be invalidated if
// it won't be re-recorded below.
DCHECK(
tiling_.TileBounds(key.first, key.second).Intersects(interest_rect) ||
invalidation_expanded_to_full_tiles.Contains(
tiling_.TileBounds(key.first, key.second)));
} }
// Expand invalidation that is outside tiles that intersect the interest
// rect. These tiles are no longer valid and should be considerered fully
// invalid, so we can know to not keep around raster tiles that intersect
// with these recording tiles.
gfx::Rect invalid_rect_outside_interest_rect_tiles = invalid_rect;
// TODO(danakj): We should have a Rect-subtract-Rect-to-2-rects operator
// instead of using Rect::Subtract which gives you the bounding box of the
// subtraction.
invalid_rect_outside_interest_rect_tiles.Subtract(interest_rect_over_tiles);
invalidation_expanded_to_full_tiles.Union(tiling_.ExpandRectToTileBounds(
invalid_rect_outside_interest_rect_tiles));
} }
invalidation->Union(invalidation_expanded_to_full_tiles); invalidation->Union(invalidation_expanded_to_full_tiles);
invalidation->Union(resize_invalidation);
// Make a list of all invalid tiles; we will attempt to // Make a list of all invalid tiles; we will attempt to
// cluster these into multiple invalidation regions. // cluster these into multiple invalidation regions.
...@@ -249,7 +342,7 @@ bool PicturePile::UpdateAndExpandInvalidation( ...@@ -249,7 +342,7 @@ bool PicturePile::UpdateAndExpandInvalidation(
ClusterTiles(invalid_tiles, &record_rects); ClusterTiles(invalid_tiles, &record_rects);
if (record_rects.empty()) if (record_rects.empty())
return invalidated; return updated;
for (std::vector<gfx::Rect>::iterator it = record_rects.begin(); for (std::vector<gfx::Rect>::iterator it = record_rects.begin();
it != record_rects.end(); it != record_rects.end();
...@@ -315,4 +408,11 @@ bool PicturePile::UpdateAndExpandInvalidation( ...@@ -315,4 +408,11 @@ bool PicturePile::UpdateAndExpandInvalidation(
return true; return true;
} }
void PicturePile::SetEmptyBounds() {
tiling_.SetTilingRect(gfx::Rect());
picture_map_.clear();
has_any_recordings_ = false;
recorded_viewport_ = gfx::Rect();
}
} // namespace cc } // namespace cc
...@@ -28,11 +28,14 @@ class CC_EXPORT PicturePile : public PicturePileBase { ...@@ -28,11 +28,14 @@ class CC_EXPORT PicturePile : public PicturePileBase {
SkColor background_color, SkColor background_color,
bool contents_opaque, bool contents_opaque,
bool contents_fill_bounds_completely, bool contents_fill_bounds_completely,
const gfx::Rect& layer_bounds_rect,
const gfx::Rect& visible_layer_rect, const gfx::Rect& visible_layer_rect,
int frame_number, int frame_number,
Picture::RecordingMode recording_mode, Picture::RecordingMode recording_mode,
RenderingStatsInstrumentation* stats_instrumentation); RenderingStatsInstrumentation* stats_instrumentation);
void SetEmptyBounds();
void set_slow_down_raster_scale_factor(int factor) { void set_slow_down_raster_scale_factor(int factor) {
slow_down_raster_scale_factor_for_debug_ = factor; slow_down_raster_scale_factor_for_debug_ = factor;
} }
......
...@@ -92,50 +92,6 @@ PicturePileBase::PicturePileBase(const PicturePileBase* other, ...@@ -92,50 +92,6 @@ PicturePileBase::PicturePileBase(const PicturePileBase* other,
PicturePileBase::~PicturePileBase() { PicturePileBase::~PicturePileBase() {
} }
void PicturePileBase::SetTilingRect(const gfx::Rect& new_tiling_rect) {
if (tiling_rect() == new_tiling_rect)
return;
gfx::Rect old_tiling_rect = tiling_rect();
tiling_.SetTilingRect(new_tiling_rect);
has_any_recordings_ = false;
// Don't waste time in Resize figuring out what these hints should be.
recorded_viewport_ = gfx::Rect();
if (new_tiling_rect.origin() != old_tiling_rect.origin()) {
picture_map_.clear();
return;
}
// Find all tiles that contain any pixels outside the new rect.
std::vector<PictureMapKey> to_erase;
int min_toss_x = tiling_.num_tiles_x();
if (new_tiling_rect.right() > old_tiling_rect.right()) {
min_toss_x =
tiling_.FirstBorderTileXIndexFromSrcCoord(old_tiling_rect.right());
}
int min_toss_y = tiling_.num_tiles_y();
if (new_tiling_rect.bottom() > old_tiling_rect.bottom()) {
min_toss_y =
tiling_.FirstBorderTileYIndexFromSrcCoord(old_tiling_rect.bottom());
}
for (PictureMap::const_iterator it = picture_map_.begin();
it != picture_map_.end();
++it) {
const PictureMapKey& key = it->first;
if (key.first < min_toss_x && key.second < min_toss_y) {
has_any_recordings_ |= !!it->second.GetPicture();
continue;
}
to_erase.push_back(key);
}
for (size_t i = 0; i < to_erase.size(); ++i)
picture_map_.erase(to_erase[i]);
}
void PicturePileBase::SetMinContentsScale(float min_contents_scale) { void PicturePileBase::SetMinContentsScale(float min_contents_scale) {
DCHECK(min_contents_scale); DCHECK(min_contents_scale);
if (min_contents_scale_ == min_contents_scale) if (min_contents_scale_ == min_contents_scale)
......
...@@ -29,7 +29,6 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> { ...@@ -29,7 +29,6 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
explicit PicturePileBase(const PicturePileBase* other); explicit PicturePileBase(const PicturePileBase* other);
PicturePileBase(const PicturePileBase* other, unsigned thread_index); PicturePileBase(const PicturePileBase* other, unsigned thread_index);
void SetTilingRect(const gfx::Rect& tiling_rect);
gfx::Rect tiling_rect() const { return tiling_.tiling_rect(); } gfx::Rect tiling_rect() const { return tiling_.tiling_rect(); }
void SetMinContentsScale(float min_contents_scale); void SetMinContentsScale(float min_contents_scale);
......
This diff is collapsed.
...@@ -109,7 +109,9 @@ class CC_EXPORT Tile : public RefCountedManaged<Tile> { ...@@ -109,7 +109,9 @@ class CC_EXPORT Tile : public RefCountedManaged<Tile> {
int source_frame_number() const { return source_frame_number_; } int source_frame_number() const { return source_frame_number_; }
void set_picture_pile(scoped_refptr<PicturePileImpl> pile) { void set_picture_pile(scoped_refptr<PicturePileImpl> pile) {
DCHECK(pile->CanRaster(contents_scale_, content_rect_)); DCHECK(pile->CanRaster(contents_scale_, content_rect_))
<< gfx::ScaleToEnclosingRect(content_rect_, 1.f / contents_scale_)
.ToString();
picture_pile_ = pile; picture_pile_ = pile;
} }
......
...@@ -629,8 +629,10 @@ TEST_F(TileManagerTileIteratorTest, RasterTileIterator) { ...@@ -629,8 +629,10 @@ TEST_F(TileManagerTileIteratorTest, RasterTileIterator) {
// Invalidate the pending tree. // Invalidate the pending tree.
pending_layer_->set_invalidation(invalidation); pending_layer_->set_invalidation(invalidation);
pending_layer_->HighResTiling()->Invalidate(invalidation); pending_layer_->HighResTiling()->UpdateTilesToCurrentPile(
pending_layer_->LowResTiling()->Invalidate(invalidation); invalidation, gfx::Size(1000, 1000));
pending_layer_->LowResTiling()->UpdateTilesToCurrentPile(
invalidation, gfx::Size(1000, 1000));
active_layer_->ResetAllTilesPriorities(); active_layer_->ResetAllTilesPriorities();
pending_layer_->ResetAllTilesPriorities(); pending_layer_->ResetAllTilesPriorities();
...@@ -830,8 +832,10 @@ TEST_F(TileManagerTileIteratorTest, EvictionTileIterator) { ...@@ -830,8 +832,10 @@ TEST_F(TileManagerTileIteratorTest, EvictionTileIterator) {
// Invalidate the pending tree. // Invalidate the pending tree.
pending_layer_->set_invalidation(invalidation); pending_layer_->set_invalidation(invalidation);
pending_layer_->HighResTiling()->Invalidate(invalidation); pending_layer_->HighResTiling()->UpdateTilesToCurrentPile(
pending_layer_->LowResTiling()->Invalidate(invalidation); invalidation, gfx::Size(1000, 1000));
pending_layer_->LowResTiling()->UpdateTilesToCurrentPile(
invalidation, gfx::Size(1000, 1000));
active_layer_->ResetAllTilesPriorities(); active_layer_->ResetAllTilesPriorities();
pending_layer_->ResetAllTilesPriorities(); pending_layer_->ResetAllTilesPriorities();
......
...@@ -63,7 +63,6 @@ FakePicturePileImpl::CreateInfiniteFilledPile() { ...@@ -63,7 +63,6 @@ FakePicturePileImpl::CreateInfiniteFilledPile() {
scoped_refptr<FakePicturePileImpl> pile(new FakePicturePileImpl()); scoped_refptr<FakePicturePileImpl> pile(new FakePicturePileImpl());
gfx::Size size(std::numeric_limits<int>::max(), gfx::Size size(std::numeric_limits<int>::max(),
std::numeric_limits<int>::max()); std::numeric_limits<int>::max());
pile->SetTilingRect(gfx::Rect(size));
pile->tiling().SetTilingRect(gfx::Rect(size)); pile->tiling().SetTilingRect(gfx::Rect(size));
pile->tiling().SetMaxTextureSize(size); pile->tiling().SetMaxTextureSize(size);
pile->SetTileGridSize(size); pile->SetTileGridSize(size);
......
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