diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-30 21:23:59 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-30 21:23:59 +0000 |
commit | f02a27ff8e75fd674cb8702b4785eed9cf02586d (patch) | |
tree | 3fafac78ed29eefa34e4e1016b7f1177b0cc5dc5 | |
parent | 204e289678f041bdadd1836f4a3e1dc40cd752c6 (diff) | |
download | chromium_src-f02a27ff8e75fd674cb8702b4785eed9cf02586d.zip chromium_src-f02a27ff8e75fd674cb8702b4785eed9cf02586d.tar.gz chromium_src-f02a27ff8e75fd674cb8702b4785eed9cf02586d.tar.bz2 |
cc: Make tile-creation lazy
This is a reland of https://chromiumcodereview.appspot.com/12865017/ after
rebasing, fixing tests, and fixing the crash in crbug.com/231360.
The TilesExist unit tests needed to check for the Tile* being NULL in
addition to checking if the tile's priority in the active tree being live.
When we create tiles in the live rect, if a tile is outside the recorded
region, it will not be created. So it is not safe to assume that always
all tiles inside the live rect do exist. This was the crash.
The original CL deferred tile creation from cloning time (during commit) to instead be during UpdateTilePriorities. Tiles that were previously marked with is_live=false will now just not be created at all. The fallout of this is that the tiling needs to know about invalidation via the client so that it can sync on a per-tile basis, rather than cloning an entire tiling at a time. Additionally, some cleanup was done to make it so that a tiling has a fixed layer bounds at creation time, since this can only happen during commit.
R=enne
BUG=190816,231360
Review URL: https://chromiumcodereview.appspot.com/14600003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@197476 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/layers/picture_image_layer_impl_unittest.cc | 4 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl.cc | 62 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl.h | 8 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl_unittest.cc | 28 | ||||
-rw-r--r-- | cc/resources/picture_layer_tiling.cc | 275 | ||||
-rw-r--r-- | cc/resources/picture_layer_tiling.h | 57 | ||||
-rw-r--r-- | cc/resources/picture_layer_tiling_set.cc | 54 | ||||
-rw-r--r-- | cc/resources/picture_layer_tiling_set.h | 13 | ||||
-rw-r--r-- | cc/resources/picture_layer_tiling_set_unittest.cc | 11 | ||||
-rw-r--r-- | cc/resources/picture_layer_tiling_unittest.cc | 84 | ||||
-rw-r--r-- | cc/resources/picture_pile_base.h | 1 | ||||
-rw-r--r-- | cc/test/fake_picture_layer_tiling_client.cc | 10 | ||||
-rw-r--r-- | cc/test/fake_picture_layer_tiling_client.h | 5 |
13 files changed, 309 insertions, 303 deletions
diff --git a/cc/layers/picture_image_layer_impl_unittest.cc b/cc/layers/picture_image_layer_impl_unittest.cc index 5e8b1d8..abedc8d 100644 --- a/cc/layers/picture_image_layer_impl_unittest.cc +++ b/cc/layers/picture_image_layer_impl_unittest.cc @@ -35,8 +35,8 @@ class PictureImageLayerImplTest : public testing::Test { TestablePictureImageLayerImpl* layer = new TestablePictureImageLayerImpl(host_impl_.pending_tree(), id); layer->SetBounds(gfx::Size(100, 200)); - layer->tilings_.reset(new PictureLayerTilingSet(&tiling_client_)); - layer->tilings_->SetLayerBounds(layer->bounds()); + layer->tilings_.reset(new PictureLayerTilingSet(&tiling_client_, + layer->bounds())); layer->pile_ = tiling_client_.pile(); return make_scoped_ptr(layer); } diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index 29d84f2..d830590 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc @@ -61,8 +61,7 @@ scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl( void PictureLayerImpl::CreateTilingSet() { DCHECK(layer_tree_impl()->IsPendingTree()); DCHECK(!tilings_); - tilings_.reset(new PictureLayerTilingSet(this)); - tilings_->SetLayerBounds(bounds()); + tilings_.reset(new PictureLayerTilingSet(this, bounds())); } void PictureLayerImpl::TransferTilingSet( @@ -90,7 +89,6 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { layer_impl->is_using_lcd_text_ = is_using_lcd_text_; } - void PictureLayerImpl::AppendQuads(QuadSink* quad_sink, AppendQuadsData* append_quads_data) { gfx::Rect rect(visible_content_rect()); @@ -390,8 +388,25 @@ void PictureLayerImpl::UpdatePile(Tile* tile) { tile->set_picture_pile(pile_); } +const Region* PictureLayerImpl::GetInvalidation() { + return &invalidation_; +} + +const PictureLayerTiling* PictureLayerImpl::GetTwinTiling( + const PictureLayerTiling* tiling) { + + const PictureLayerImpl* other_layer = layer_tree_impl()->IsActiveTree() ? + PendingTwin() : ActiveTwin(); + if (!other_layer) + return NULL; + for (size_t i = 0; i < other_layer->tilings_->num_tilings(); ++i) + if (other_layer->tilings_->tiling_at(i)->contents_scale() == + tiling->contents_scale()) + return other_layer->tilings_->tiling_at(i); + return NULL; +} + gfx::Size PictureLayerImpl::CalculateTileSize( - gfx::Size current_tile_size, gfx::Size content_bounds) { if (is_mask_) { int max_size = layer_tree_impl()->MaxTextureSize(); @@ -487,31 +502,20 @@ void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) { } } - tilings_->CloneAll(*other->tilings_, invalidation_, MinimumContentsScale()); - DCHECK(bounds() == tilings_->LayerBounds()); + // Union in the other newly exposed regions as invalid. + Region difference_region = Region(gfx::Rect(bounds())); + difference_region.Subtract(gfx::Rect(other->bounds())); + invalidation_.Union(difference_region); - // It's a sad but unfortunate fact that PicturePile tiling edges do not line - // up with PictureLayerTiling edges. Tiles can only be added if they are - // entirely covered by recordings (that may come from multiple PicturePile - // tiles). This check happens in this class's CreateTile() call. - for (int x = 0; x < pile_->num_tiles_x(); ++x) { - for (int y = 0; y < pile_->num_tiles_y(); ++y) { - bool previously_had = other->pile_->HasRecordingAt(x, y); - bool now_has = pile_->HasRecordingAt(x, y); - if (!now_has || previously_had) - continue; - gfx::Rect layer_rect = pile_->tile_bounds(x, y); - tilings_->CreateTilesFromLayerRect(layer_rect); - } - } + tilings_->CloneAll(*other->tilings_, MinimumContentsScale()); + DCHECK(bounds() == tilings_->layer_bounds()); } void PictureLayerImpl::SyncTiling( - const PictureLayerTiling* tiling, - const Region& pending_layer_invalidation) { + const PictureLayerTiling* tiling) { if (!DrawsContent() || tiling->contents_scale() < MinimumContentsScale()) return; - tilings_->Clone(tiling, pending_layer_invalidation); + tilings_->Clone(tiling); } void PictureLayerImpl::SetIsMask(bool is_mask) { @@ -614,18 +618,10 @@ PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) { const Region& recorded = pile_->recorded_region(); DCHECK(!recorded.IsEmpty()); - for (Region::Iterator iter(recorded); iter.has_rect(); iter.next()) - tiling->CreateTilesFromLayerRect(iter.rect()); - PictureLayerImpl* twin = layer_tree_impl()->IsPendingTree() ? ActiveTwin() : PendingTwin(); - if (!twin) - return tiling; - - if (layer_tree_impl()->IsPendingTree()) - twin->SyncTiling(tiling, invalidation_); - else - twin->SyncTiling(tiling, twin->invalidation_); + if (twin) + twin->SyncTiling(tiling); return tiling; } diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h index a2e5a8d..068e4d2 100644 --- a/cc/layers/picture_layer_impl.h +++ b/cc/layers/picture_layer_impl.h @@ -54,14 +54,14 @@ class CC_EXPORT PictureLayerImpl gfx::Rect content_rect) OVERRIDE; virtual void UpdatePile(Tile* tile) OVERRIDE; virtual gfx::Size CalculateTileSize( - gfx::Size current_tile_size, gfx::Size content_bounds) OVERRIDE; + virtual const Region* GetInvalidation() OVERRIDE; + virtual const PictureLayerTiling* GetTwinTiling( + const PictureLayerTiling* tiling) OVERRIDE; // PushPropertiesTo active tree => pending tree void SyncFromActiveLayer(); - void SyncTiling( - const PictureLayerTiling* tiling, - const Region& pending_layer_invalidation); + void SyncTiling(const PictureLayerTiling* tiling); void CreateTilingSet(); void TransferTilingSet(scoped_ptr<PictureLayerTilingSet> tilings); diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index ee21993..a3f0ae3 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc @@ -41,16 +41,12 @@ class TestablePictureLayerImpl : public PictureLayerImpl { Region& invalidation() { return invalidation_; } virtual gfx::Size CalculateTileSize( - gfx::Size current_tile_size, gfx::Size content_bounds) OVERRIDE { if (fixed_tile_size_.IsEmpty()) { - return PictureLayerImpl::CalculateTileSize(current_tile_size, - content_bounds); + return PictureLayerImpl::CalculateTileSize(content_bounds); } - if (current_tile_size.IsEmpty()) - return fixed_tile_size_; - return current_tile_size; + return fixed_tile_size_; } using PictureLayerImpl::AddTiling; @@ -116,8 +112,12 @@ class PictureLayerImplTest : public testing::Test { active_layer_->AddTiling(2.3f); active_layer_->AddTiling(1.0f); active_layer_->AddTiling(0.5f); + for (size_t i = 0; i < active_layer_->tilings().num_tilings(); ++i) + active_layer_->tilings().tiling_at(i)->CreateAllTilesForTesting(); pending_layer_->invalidation() = invalidation; pending_layer_->SyncFromActiveLayer(); + for (size_t i = 0; i < pending_layer_->tilings().num_tilings(); ++i) + pending_layer_->tilings().tiling_at(i)->CreateAllTilesForTesting(); } void SetupPendingTree( @@ -178,6 +178,7 @@ class PictureLayerImplTest : public testing::Test { 1.f, false, &result_scale_x, &result_scale_y, &result_bounds); // Add 1x1 rects at the centers of each tile, then re-record pile contents + active_layer_->tilings().tiling_at(0)->CreateAllTilesForTesting(); std::vector<Tile*> tiles = active_layer_->tilings().tiling_at(0)->AllTilesForTesting(); EXPECT_EQ(16u, tiles.size()); @@ -352,8 +353,13 @@ TEST_F(PictureLayerImplTest, NoInvalidationBoundsChange) { ++iter) { EXPECT_TRUE(*iter); EXPECT_FALSE(iter.geometry_rect().IsEmpty()); + std::vector<Tile*> active_tiles = + active_layer_->tilings().tiling_at(i)->AllTilesForTesting(); + std::vector<Tile*> pending_tiles = tiling->AllTilesForTesting(); if (iter.geometry_rect().right() >= active_content_bounds.width() || - iter.geometry_rect().bottom() >= active_content_bounds.height()) { + iter.geometry_rect().bottom() >= active_content_bounds.height() || + active_tiles[0]->content_rect().size() != + pending_tiles[0]->content_rect().size()) { EXPECT_EQ(pending_pile, iter->picture_pile()); } else { EXPECT_EQ(active_pile, iter->picture_pile()); @@ -698,6 +704,8 @@ TEST_F(PictureLayerImplTest, ClampTilesToToMaxTileSize) { 1.f, false, &result_scale_x, &result_scale_y, &result_bounds); ASSERT_EQ(2u, pending_layer_->tilings().num_tilings()); + pending_layer_->tilings().tiling_at(0)->CreateAllTilesForTesting(); + // The default value. EXPECT_EQ(gfx::Size(256, 256).ToString(), host_impl_.settings().default_tile_size.ToString()); @@ -719,6 +727,8 @@ TEST_F(PictureLayerImplTest, ClampTilesToToMaxTileSize) { 1.f, false, &result_scale_x, &result_scale_y, &result_bounds); ASSERT_EQ(2u, pending_layer_->tilings().num_tilings()); + pending_layer_->tilings().tiling_at(0)->CreateAllTilesForTesting(); + // Verify the tiles are not larger than the context's max texture size. tile = pending_layer_->tilings().tiling_at(0)->AllTilesForTesting()[0]; EXPECT_GE(140, tile->content_rect().width()); @@ -745,6 +755,8 @@ TEST_F(PictureLayerImplTest, ClampSingleTileToToMaxTileSize) { 1.f, false, &result_scale_x, &result_scale_y, &result_bounds); ASSERT_EQ(2u, pending_layer_->tilings().num_tilings()); + pending_layer_->tilings().tiling_at(0)->CreateAllTilesForTesting(); + // The default value. The layer is smaller than this. EXPECT_EQ(gfx::Size(512, 512).ToString(), host_impl_.settings().max_untiled_layer_size.ToString()); @@ -766,6 +778,8 @@ TEST_F(PictureLayerImplTest, ClampSingleTileToToMaxTileSize) { 1.f, false, &result_scale_x, &result_scale_y, &result_bounds); ASSERT_EQ(2u, pending_layer_->tilings().num_tilings()); + pending_layer_->tilings().tiling_at(0)->CreateAllTilesForTesting(); + // There should be more than one tile since the max texture size won't cover // the layer. high_res_tiling = pending_layer_->tilings().tiling_at(0); diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc index 48e5dae..7216152 100644 --- a/cc/resources/picture_layer_tiling.cc +++ b/cc/resources/picture_layer_tiling.cc @@ -17,21 +17,43 @@ namespace cc { scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( - float contents_scale) { - return make_scoped_ptr(new PictureLayerTiling(contents_scale)); + float contents_scale, + gfx::Size layer_bounds, + PictureLayerTilingClient* client) { + return make_scoped_ptr(new PictureLayerTiling(contents_scale, + layer_bounds, + client)); } -scoped_ptr<PictureLayerTiling> PictureLayerTiling::Clone() const { - return make_scoped_ptr(new PictureLayerTiling(*this)); +scoped_ptr<PictureLayerTiling> PictureLayerTiling::Clone( + gfx::Size layer_bounds, + PictureLayerTilingClient* client) const { + scoped_ptr<PictureLayerTiling> out = + make_scoped_ptr(new PictureLayerTiling(contents_scale_, + layer_bounds, + client)); + out->resolution_ = resolution_; + out->last_source_frame_number_ = last_source_frame_number_; + out->last_impl_frame_time_ = last_impl_frame_time_; + return out.Pass(); } -PictureLayerTiling::PictureLayerTiling(float contents_scale) - : client_(NULL), - contents_scale_(contents_scale), - tiling_data_(gfx::Size(), gfx::Size(), true), +PictureLayerTiling::PictureLayerTiling(float contents_scale, + gfx::Size layer_bounds, + PictureLayerTilingClient* client) + : contents_scale_(contents_scale), + layer_bounds_(layer_bounds), resolution_(NON_IDEAL_RESOLUTION), + client_(client), + tiling_data_(gfx::Size(), gfx::Size(), true), last_source_frame_number_(0), - last_impl_frame_time_(0) { + last_impl_frame_time_(0.0) { + gfx::Size content_bounds = + gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)); + gfx::Size tile_size = client_->CalculateTileSize(content_bounds); + + tiling_data_.SetTotalSize(content_bounds); + tiling_data_.SetMaxTextureSize(tile_size); } PictureLayerTiling::~PictureLayerTiling() { @@ -57,10 +79,29 @@ Tile* PictureLayerTiling::TileAt(int i, int j) const { } void PictureLayerTiling::CreateTile(int i, int j) { - gfx::Rect tile_rect = tiling_data_.TileBoundsWithBorder(i, j); - tile_rect.set_size(tiling_data_.max_texture_size()); TileMapKey key(i, j); DCHECK(tiles_.find(key) == tiles_.end()); + + gfx::Rect paint_rect = tiling_data_.TileBoundsWithBorder(i, j); + gfx::Rect tile_rect = paint_rect; + tile_rect.set_size(tiling_data_.max_texture_size()); + + // Check our twin for a valid tile. + const PictureLayerTiling* twin = client_->GetTwinTiling(this); + if (twin && tiling_data_.max_texture_size() == + twin->tiling_data_.max_texture_size()) { + Tile* candidate_tile = twin->TileAt(i, j); + if (candidate_tile) { + gfx::Rect rect = + gfx::ToEnclosingRect(ScaleRect(paint_rect, 1.0f / contents_scale_)); + if (!client_->GetInvalidation()->Intersects(rect)) { + tiles_[key] = candidate_tile; + return; + } + } + } + + // Create a new tile because our twin didn't have a valid one. scoped_refptr<Tile> tile = client_->CreateTile(this, tile_rect); if (tile) tiles_[key] = tile; @@ -73,89 +114,6 @@ Region PictureLayerTiling::OpaqueRegionInContentRect( return opaque_region; } -void PictureLayerTiling::SetLayerBounds(gfx::Size layer_bounds) { - if (layer_bounds_ == layer_bounds) - return; - - gfx::Size old_layer_bounds = layer_bounds_; - layer_bounds_ = layer_bounds; - gfx::Size old_content_bounds = tiling_data_.total_size(); - gfx::Size content_bounds = - gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds_, contents_scale_)); - - tiling_data_.SetTotalSize(content_bounds); - if (layer_bounds_.IsEmpty()) { - tiles_.clear(); - return; - } - - gfx::Size tile_size = client_->CalculateTileSize( - tiling_data_.max_texture_size(), - content_bounds); - if (tile_size != tiling_data_.max_texture_size()) { - tiling_data_.SetMaxTextureSize(tile_size); - tiles_.clear(); - CreateTilesFromLayerRect(gfx::Rect(layer_bounds_)); - return; - } - - // Any tiles outside our new bounds are invalid and should be dropped. - if (old_content_bounds.width() > content_bounds.width() || - old_content_bounds.height() > content_bounds.height()) { - int right = - tiling_data_.TileXIndexFromSrcCoord(content_bounds.width() - 1); - int bottom = - tiling_data_.TileYIndexFromSrcCoord(content_bounds.height() - 1); - - std::vector<TileMapKey> invalid_tile_keys; - for (TileMap::const_iterator it = tiles_.begin(); - it != tiles_.end(); ++it) { - if (it->first.first > right || it->first.second > bottom) - invalid_tile_keys.push_back(it->first); - } - for (size_t i = 0; i < invalid_tile_keys.size(); ++i) - tiles_.erase(invalid_tile_keys[i]); - } - - // Create tiles for newly exposed areas. - Region layer_region((gfx::Rect(layer_bounds_))); - layer_region.Subtract(gfx::Rect(old_layer_bounds)); - for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) { - Invalidate(iter.rect()); - CreateTilesFromLayerRect(iter.rect()); - } -} - -void PictureLayerTiling::Invalidate(const Region& layer_invalidation) { - std::vector<TileMapKey> new_tiles; - - for (Region::Iterator region_iter(layer_invalidation); - region_iter.has_rect(); - region_iter.next()) { - gfx::Rect layer_invalidation = region_iter.rect(); - layer_invalidation.Intersect(gfx::Rect(layer_bounds_)); - gfx::Rect rect = - gfx::ToEnclosingRect(ScaleRect(layer_invalidation, contents_scale_)); - - for (PictureLayerTiling::CoverageIterator tile_iter(this, - contents_scale_, - rect); - tile_iter; - ++tile_iter) { - TileMapKey key(tile_iter.tile_i_, tile_iter.tile_j_); - TileMap::iterator found = tiles_.find(key); - if (found == tiles_.end()) - continue; - - tiles_.erase(found); - new_tiles.push_back(key); - } - } - - for (size_t i = 0; i < new_tiles.size(); ++i) - CreateTile(new_tiles[i].first, new_tiles[i].second); -} - void PictureLayerTiling::InvalidateTilesWithText() { std::vector<TileMapKey> new_tiles; for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { @@ -169,23 +127,6 @@ void PictureLayerTiling::InvalidateTilesWithText() { } } -void PictureLayerTiling::CreateTilesFromLayerRect(gfx::Rect layer_rect) { - gfx::Rect content_rect = - gfx::ToEnclosingRect(ScaleRect(layer_rect, contents_scale_)); - CreateTilesFromContentRect(content_rect); -} - -void PictureLayerTiling::CreateTilesFromContentRect(gfx::Rect content_rect) { - for (TilingData::Iterator iter(&tiling_data_, content_rect); iter; ++iter) { - TileMap::iterator found = - tiles_.find(TileMapKey(iter.index_x(), iter.index_y())); - // Ignore any tiles that already exist. - if (found != tiles_.end()) - continue; - CreateTile(iter.index_x(), iter.index_y()); - } -} - PictureLayerTiling::CoverageIterator::CoverageIterator() : tiling_(NULL), current_tile_(NULL), @@ -338,6 +279,11 @@ gfx::Size PictureLayerTiling::CoverageIterator::texture_size() const { return tiling_->tiling_data_.max_texture_size(); } +void PictureLayerTiling::Reset() { + live_tiles_rect_ = gfx::Rect(); + tiles_.clear(); +} + void PictureLayerTiling::UpdateTilePriorities( WhichTree tree, gfx::Size device_viewport, @@ -356,6 +302,29 @@ void PictureLayerTiling::UpdateTilePriorities( if (ContentRect().IsEmpty()) return; + gfx::Rect viewport_in_content_space = + gfx::ToEnclosingRect(gfx::ScaleRect(viewport_in_layer_space, + contents_scale_)); + gfx::Rect visible_content_rect = + gfx::ToEnclosingRect(gfx::ScaleRect(visible_layer_rect, + contents_scale_)); + + gfx::Size tile_size = tiling_data_.max_texture_size(); + int64 interest_rect_area = + max_tiles_for_interest_area * tile_size.width() * tile_size.height(); + + gfx::Rect starting_rect = visible_content_rect.IsEmpty() + ? viewport_in_content_space + : visible_content_rect; + gfx::Rect interest_rect = ExpandRectEquallyToAreaBoundedBy( + starting_rect, + interest_rect_area, + ContentRect()); + DCHECK(interest_rect.IsEmpty() || + ContentRect().Contains(interest_rect)); + + SetLiveTilesRect(interest_rect); + bool first_update_in_new_source_frame = current_source_frame_number != last_source_frame_number_; @@ -372,50 +341,11 @@ void PictureLayerTiling::UpdateTilePriorities( if (!first_update_in_new_impl_frame && !first_update_in_new_source_frame) return; - double time_delta = 0; - if (last_impl_frame_time_ != 0 && last_layer_bounds == current_layer_bounds) + double time_delta = 0.0; + if (last_impl_frame_time_ != 0.0 && + last_layer_bounds == current_layer_bounds) time_delta = current_frame_time - last_impl_frame_time_; - gfx::Rect viewport_in_content_space = - gfx::ToEnclosingRect(gfx::ScaleRect(viewport_in_layer_space, - contents_scale_)); - gfx::Rect visible_content_rect = - gfx::ToEnclosingRect(gfx::ScaleRect(visible_layer_rect, - contents_scale_)); - - gfx::Size tile_size = tiling_data_.max_texture_size(); - int64 prioritized_rect_area = - max_tiles_for_interest_area * - tile_size.width() * tile_size.height(); - - gfx::Rect starting_rect = visible_content_rect.IsEmpty() - ? viewport_in_content_space - : visible_content_rect; - gfx::Rect prioritized_rect = ExpandRectEquallyToAreaBoundedBy( - starting_rect, - prioritized_rect_area, - ContentRect()); - DCHECK(prioritized_rect.IsEmpty() || - ContentRect().Contains(prioritized_rect)); - - // Iterate through all of the tiles that were live last frame but will - // not be live this frame, and mark them as being dead. - for (TilingData::DifferenceIterator iter(&tiling_data_, - last_prioritized_rect_, - prioritized_rect); - iter; - ++iter) { - TileMap::iterator find = tiles_.find(iter.index()); - if (find == tiles_.end()) - continue; - - TilePriority priority; - DCHECK(!priority.is_live); - Tile* tile = find->second.get(); - tile->SetPriority(tree, priority); - } - last_prioritized_rect_ = prioritized_rect; - gfx::Rect view_rect(device_viewport); float current_scale = current_layer_contents_scale / contents_scale_; float last_scale = last_layer_contents_scale / contents_scale_; @@ -430,7 +360,7 @@ void PictureLayerTiling::UpdateTilePriorities( last_screen_transform.matrix().get(0, 3), last_screen_transform.matrix().get(1, 3)); - for (TilingData::Iterator iter(&tiling_data_, prioritized_rect); + for (TilingData::Iterator iter(&tiling_data_, interest_rect); iter; ++iter) { TileMap::iterator find = tiles_.find(iter.index()); if (find == tiles_.end()) @@ -463,7 +393,7 @@ void PictureLayerTiling::UpdateTilePriorities( tile->SetPriority(tree, priority); } } else { - for (TilingData::Iterator iter(&tiling_data_, prioritized_rect); + for (TilingData::Iterator iter(&tiling_data_, interest_rect); iter; ++iter) { TileMap::iterator find = tiles_.find(iter.index()); if (find == tiles_.end()) @@ -511,6 +441,41 @@ void PictureLayerTiling::UpdateTilePriorities( last_impl_frame_time_ = current_frame_time; } +void PictureLayerTiling::SetLiveTilesRect( + gfx::Rect new_live_tiles_rect) { + DCHECK(new_live_tiles_rect.IsEmpty() || + ContentRect().Contains(new_live_tiles_rect)); + if (live_tiles_rect_ == new_live_tiles_rect) + return; + + // Iterate to delete all tiles outside of our new live_tiles rect. + for (TilingData::DifferenceIterator iter(&tiling_data_, + live_tiles_rect_, + new_live_tiles_rect); + iter; + ++iter) { + TileMapKey key(iter.index()); + TileMap::iterator found = tiles_.find(key); + // If the tile was outside of the recorded region, it won't exist even + // though it was in the live rect. + if (found == tiles_.end()) + continue; + tiles_.erase(found); + } + + // Iterate to allocate new tiles for all regions with newly exposed area. + for (TilingData::DifferenceIterator iter(&tiling_data_, + new_live_tiles_rect, + live_tiles_rect_); + iter; + ++iter) { + TileMapKey key(iter.index()); + CreateTile(key.first, key.second); + } + + live_tiles_rect_ = new_live_tiles_rect; +} + void PictureLayerTiling::DidBecomeActive() { for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { it->second->SetPriority(ACTIVE_TREE, it->second->priority(PENDING_TREE)); diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h index 29686d2..6227147 100644 --- a/cc/resources/picture_layer_tiling.h +++ b/cc/resources/picture_layer_tiling.h @@ -32,8 +32,10 @@ class PictureLayerTilingClient { gfx::Rect content_rect) = 0; virtual void UpdatePile(Tile* tile) = 0; virtual gfx::Size CalculateTileSize( - gfx::Size current_tile_size, gfx::Size content_bounds) = 0; + virtual const Region* GetInvalidation() = 0; + virtual const PictureLayerTiling* GetTwinTiling( + const PictureLayerTiling* tiling) = 0; protected: virtual ~PictureLayerTilingClient() {} @@ -44,18 +46,15 @@ class CC_EXPORT PictureLayerTiling { ~PictureLayerTiling(); // Create a tiling with no tiles. CreateTiles must be called to add some. - static scoped_ptr<PictureLayerTiling> Create(float contents_scale); - scoped_ptr<PictureLayerTiling> Clone() const; - + static scoped_ptr<PictureLayerTiling> Create( + float contents_scale, + gfx::Size layer_bounds, + PictureLayerTilingClient* client); + scoped_ptr<PictureLayerTiling> Clone(gfx::Size layer_bounds, + PictureLayerTilingClient* client) const; gfx::Size layer_bounds() const { return layer_bounds_; } - void SetLayerBounds(gfx::Size layer_bounds); - void Invalidate(const Region& layer_invalidation); void InvalidateTilesWithText(); - // Add any tiles that intersect with |layer_rect|. If any tiles already - // exist, then this leaves them as-is. - void CreateTilesFromLayerRect(gfx::Rect layer_rect); - void SetClient(PictureLayerTilingClient* client); void set_resolution(TileResolution resolution) { resolution_ = resolution; } TileResolution resolution() const { return resolution_; } @@ -64,6 +63,10 @@ class CC_EXPORT PictureLayerTiling { gfx::SizeF ContentSizeF() const; float contents_scale() const { return contents_scale_; } + void CreateAllTilesForTesting() { + SetLiveTilesRect(gfx::Rect(tiling_data_.total_size())); + } + std::vector<Tile*> AllTilesForTesting() const { std::vector<Tile*> all_tiles; for (TileMap::const_iterator it = tiles_.begin(); @@ -72,11 +75,6 @@ class CC_EXPORT PictureLayerTiling { return all_tiles; } - static gfx::Rect ExpandRectEquallyToAreaBoundedBy( - gfx::Rect starting_rect, - int64 target_area, - gfx::Rect bounding_rect); - // Iterate over all tiles to fill content_rect. Even if tiles are invalid // (i.e. no valid resource) this tiling should still iterate over them. // The union of all geometry_rect calls for each element iterated over should @@ -125,7 +123,7 @@ class CC_EXPORT PictureLayerTiling { Region OpaqueRegionInContentRect(gfx::Rect content_rect) const; - void Reset() { return tiles_.clear(); } + void Reset(); void UpdateTilePriorities( WhichTree tree, @@ -150,23 +148,34 @@ class CC_EXPORT PictureLayerTiling { scoped_ptr<base::Value> AsValue() const; + static gfx::Rect ExpandRectEquallyToAreaBoundedBy( + gfx::Rect starting_rect, + int64 target_area, + gfx::Rect bounding_rect); + protected: typedef std::pair<int, int> TileMapKey; typedef base::hash_map<TileMapKey, scoped_refptr<Tile> > TileMap; - explicit PictureLayerTiling(float contents_scale); - Tile* TileAt(int, int) const; - void CreateTilesFromContentRect(gfx::Rect layer_rect); + PictureLayerTiling(float contents_scale, + gfx::Size layer_bounds, + PictureLayerTilingClient* client); + void SetLiveTilesRect(gfx::Rect live_tiles_rect); void CreateTile(int i, int j); + Tile* TileAt(int, int) const; - PictureLayerTilingClient* client_; + // Given properties. float contents_scale_; gfx::Size layer_bounds_; - gfx::Rect last_prioritized_rect_; - // It is not legal to have a NULL tile in the tiles_ map. - TileMap tiles_; - TilingData tiling_data_; TileResolution resolution_; + PictureLayerTilingClient* client_; + + // Internal data. + TilingData tiling_data_; + TileMap tiles_; // It is not legal to have a NULL tile in the tiles_ map. + gfx::Rect live_tiles_rect_; + + // State saved for computing velocities based upon finite differences. int last_source_frame_number_; double last_impl_frame_time_; diff --git a/cc/resources/picture_layer_tiling_set.cc b/cc/resources/picture_layer_tiling_set.cc index cc15047..65ab01c 100644 --- a/cc/resources/picture_layer_tiling_set.cc +++ b/cc/resources/picture_layer_tiling_set.cc @@ -21,8 +21,10 @@ class LargestToSmallestScaleFunctor { PictureLayerTilingSet::PictureLayerTilingSet( - PictureLayerTilingClient * client) - : client_(client) { + PictureLayerTilingClient* client, + gfx::Size layer_bounds) + : client_(client), + layer_bounds_(layer_bounds) { } PictureLayerTilingSet::~PictureLayerTilingSet() { @@ -36,61 +38,36 @@ void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) { void PictureLayerTilingSet::CloneAll( const PictureLayerTilingSet& other, - const Region& invalidation, float minimum_contents_scale) { tilings_.clear(); tilings_.reserve(other.tilings_.size()); for (size_t i = 0; i < other.tilings_.size(); ++i) { - if (other.tilings_[i]->contents_scale() < minimum_contents_scale) + const PictureLayerTiling* tiling = other.tilings_[i]; + if (tiling->contents_scale() < minimum_contents_scale) continue; - Clone(other.tilings_[i], invalidation); + tilings_.push_back(tiling->Clone(layer_bounds_, client_)); } + tilings_.sort(LargestToSmallestScaleFunctor()); } -void PictureLayerTilingSet::Clone( - const PictureLayerTiling* tiling, - const Region& invalidation) { - +void PictureLayerTilingSet::Clone(const PictureLayerTiling* tiling) { for (size_t i = 0; i < tilings_.size(); ++i) DCHECK_NE(tilings_[i]->contents_scale(), tiling->contents_scale()); - tilings_.push_back(tiling->Clone()); - gfx::Size size = tilings_.back()->layer_bounds(); - tilings_.back()->SetClient(client_); - tilings_.back()->Invalidate(invalidation); - // Intentionally use this set's layer bounds, as it may have changed. - tilings_.back()->SetLayerBounds(layer_bounds_); - + tilings_.push_back(tiling->Clone(layer_bounds_, client_)); tilings_.sort(LargestToSmallestScaleFunctor()); } -void PictureLayerTilingSet::SetLayerBounds(gfx::Size layer_bounds) { - if (layer_bounds_ == layer_bounds) - return; - layer_bounds_ = layer_bounds; - for (size_t i = 0; i < tilings_.size(); ++i) - tilings_[i]->SetLayerBounds(layer_bounds); -} - -gfx::Size PictureLayerTilingSet::LayerBounds() const { - return layer_bounds_; -} - -void PictureLayerTilingSet::Invalidate(const Region& layer_invalidation) { - for (size_t i = 0; i < tilings_.size(); ++i) - tilings_[i]->Invalidate(layer_invalidation); -} - void PictureLayerTilingSet::InvalidateTilesWithText() { for (size_t i = 0; i < tilings_.size(); ++i) tilings_[i]->InvalidateTilesWithText(); } PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) { - tilings_.push_back(PictureLayerTiling::Create(contents_scale)); + tilings_.push_back(PictureLayerTiling::Create(contents_scale, + layer_bounds_, + client_)); PictureLayerTiling* appended = tilings_.back(); - appended->SetClient(client_); - appended->SetLayerBounds(layer_bounds_); tilings_.sort(LargestToSmallestScaleFunctor()); return appended; @@ -113,11 +90,6 @@ void PictureLayerTilingSet::RemoveAllTiles() { tilings_[i]->Reset(); } -void PictureLayerTilingSet::CreateTilesFromLayerRect(gfx::Rect layer_rect) { - for (size_t i = 0; i < tilings_.size(); ++i) - tilings_[i]->CreateTilesFromLayerRect(layer_rect); -} - PictureLayerTilingSet::CoverageIterator::CoverageIterator( const PictureLayerTilingSet* set, float contents_scale, diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h index 31f7e93..d263e71 100644 --- a/cc/resources/picture_layer_tiling_set.h +++ b/cc/resources/picture_layer_tiling_set.h @@ -14,7 +14,8 @@ namespace cc { class CC_EXPORT PictureLayerTilingSet { public: - explicit PictureLayerTilingSet(PictureLayerTilingClient* client); + PictureLayerTilingSet(PictureLayerTilingClient* client, + gfx::Size layer_bounds); ~PictureLayerTilingSet(); void SetClient(PictureLayerTilingClient* client); @@ -22,14 +23,11 @@ class CC_EXPORT PictureLayerTilingSet { // Shallow copies all data (except client and bounds from other). void CloneAll( const PictureLayerTilingSet& other, - const Region& invalidation, float minimum_contents_scale); - void Clone(const PictureLayerTiling* tiling, const Region& invalidation); + void Clone(const PictureLayerTiling* tiling); - void SetLayerBounds(gfx::Size layer_bounds); - gfx::Size LayerBounds() const; + gfx::Size layer_bounds() const { return layer_bounds_; } - void Invalidate(const Region& layer_invalidation); void InvalidateTilesWithText(); PictureLayerTiling* AddTiling(float contents_scale); @@ -48,9 +46,6 @@ class CC_EXPORT PictureLayerTilingSet { // Remove all tiles; keep all tilings. void RemoveAllTiles(); - // For all tilings, create any tile that intersects |layer_rect|. - void CreateTilesFromLayerRect(gfx::Rect layer_rect); - void UpdateTilePriorities( WhichTree tree, gfx::Size device_viewport, diff --git a/cc/resources/picture_layer_tiling_set_unittest.cc b/cc/resources/picture_layer_tiling_set_unittest.cc index 90aa5ed..b79433d 100644 --- a/cc/resources/picture_layer_tiling_set_unittest.cc +++ b/cc/resources/picture_layer_tiling_set_unittest.cc @@ -19,11 +19,9 @@ namespace { TEST(PictureLayerTilingSetTest, NoResources) { FakePictureLayerTilingClient client; - PictureLayerTilingSet set(&client); - client.SetTileSize(gfx::Size(256, 256)); - gfx::Size layer_bounds(1000, 800); - set.SetLayerBounds(layer_bounds); + PictureLayerTilingSet set(&client, layer_bounds); + client.SetTileSize(gfx::Size(256, 256)); set.AddTiling(1.0); set.AddTiling(1.5); @@ -67,14 +65,13 @@ class PictureLayerTilingSetTestWithResources : public testing::Test { FakePictureLayerTilingClient client; client.SetTileSize(gfx::Size(256, 256)); - PictureLayerTilingSet set(&client); - gfx::Size layer_bounds(1000, 800); - set.SetLayerBounds(layer_bounds); + PictureLayerTilingSet set(&client, layer_bounds); float scale = min_scale; for (int i = 0; i < num_tilings; ++i, scale += scale_increment) { PictureLayerTiling* tiling = set.AddTiling(scale); + tiling->CreateAllTilesForTesting(); std::vector<Tile*> tiles = tiling->AllTilesForTesting(); for (size_t i = 0; i < tiles.size(); ++i) { EXPECT_FALSE(tiles[i]->drawing_info().GetResourceForTesting()); diff --git a/cc/resources/picture_layer_tiling_unittest.cc b/cc/resources/picture_layer_tiling_unittest.cc index a17c025..83e0db4 100644 --- a/cc/resources/picture_layer_tiling_unittest.cc +++ b/cc/resources/picture_layer_tiling_unittest.cc @@ -12,6 +12,27 @@ namespace cc { namespace { +class TestablePictureLayerTiling : public PictureLayerTiling { + public: + using PictureLayerTiling::SetLiveTilesRect; + + static scoped_ptr<TestablePictureLayerTiling> Create( + float contents_scale, + gfx::Size layer_bounds, + PictureLayerTilingClient* client) { + return make_scoped_ptr(new TestablePictureLayerTiling( + contents_scale, + layer_bounds, + client)); + } + + protected: + TestablePictureLayerTiling(float contents_scale, + gfx::Size layer_bounds, + PictureLayerTilingClient* client) + : PictureLayerTiling(contents_scale, layer_bounds, client) { } +}; + class PictureLayerTilingIteratorTest : public testing::Test { public: PictureLayerTilingIteratorTest() {} @@ -21,9 +42,20 @@ class PictureLayerTilingIteratorTest : public testing::Test { float contents_scale, gfx::Size layer_bounds) { client_.SetTileSize(tile_size); - tiling_ = PictureLayerTiling::Create(contents_scale); - tiling_->SetClient(&client_); - tiling_->SetLayerBounds(layer_bounds); + tiling_ = TestablePictureLayerTiling::Create(contents_scale, + layer_bounds, + &client_); + } + + void SetLiveRectAndVerifyTiles(gfx::Rect live_tiles_rect) { + tiling_->SetLiveTilesRect(live_tiles_rect); + + std::vector<Tile*> tiles = tiling_->AllTilesForTesting(); + for (std::vector<Tile*>::iterator iter = tiles.begin(); + iter != tiles.end(); + ++iter) { + EXPECT_TRUE(live_tiles_rect.Intersects((*iter)->content_rect())); + } } void VerifyTilesExactlyCoverRect( @@ -68,16 +100,17 @@ class PictureLayerTilingIteratorTest : public testing::Test { VerifyTilesExactlyCoverRect(rect_scale, rect, rect); } - void VerifyTiles(float rect_scale, - gfx::Rect rect, - base::Callback<void(Tile* tile)> callback) { + void VerifyTiles( + float rect_scale, + gfx::Rect rect, + base::Callback<void(Tile* tile, gfx::Rect geometry_rect)> callback) { Region remaining = rect; for (PictureLayerTiling::CoverageIterator iter( tiling_.get(), rect_scale, rect); iter; ++iter) { remaining.Subtract(iter.geometry_rect()); - callback.Run(*iter); + callback.Run(*iter, iter.geometry_rect()); } EXPECT_TRUE(remaining.IsEmpty()); } @@ -92,11 +125,21 @@ class PictureLayerTilingIteratorTest : public testing::Test { protected: FakePictureLayerTilingClient client_; - scoped_ptr<PictureLayerTiling> tiling_; + scoped_ptr<TestablePictureLayerTiling> tiling_; DISALLOW_COPY_AND_ASSIGN(PictureLayerTilingIteratorTest); }; +TEST_F(PictureLayerTilingIteratorTest, LiveTilesExactlyCoverLiveTileRect) { + Initialize(gfx::Size(100, 100), 1, gfx::Size(1099, 801)); + SetLiveRectAndVerifyTiles(gfx::Rect(100, 100)); + SetLiveRectAndVerifyTiles(gfx::Rect(101, 99)); + SetLiveRectAndVerifyTiles(gfx::Rect(1099, 1)); + SetLiveRectAndVerifyTiles(gfx::Rect(1, 801)); + SetLiveRectAndVerifyTiles(gfx::Rect(1099, 1)); + SetLiveRectAndVerifyTiles(gfx::Rect(201, 800)); +} + TEST_F(PictureLayerTilingIteratorTest, IteratorCoversLayerBoundsNoScale) { Initialize(gfx::Size(100, 100), 1, gfx::Size(1099, 801)); VerifyTilesExactlyCoverRect(1, gfx::Rect()); @@ -406,9 +449,9 @@ TEST(PictureLayerTilingTest, EmptyStartingRect) { EXPECT_TRUE(out.IsEmpty()); } -static void TileExists(bool live, Tile* tile) { - ASSERT_TRUE(tile != NULL); - EXPECT_EQ(live, tile->priority(ACTIVE_TREE).is_live); +static void TileExists(bool exists, Tile* tile, gfx::Rect geometry_rect) { + EXPECT_EQ(exists, tile != NULL && tile->priority(ACTIVE_TREE).is_live) << + geometry_rect.ToString(); } TEST_F(PictureLayerTilingIteratorTest, TilesExist) { @@ -526,12 +569,14 @@ TEST_F(PictureLayerTilingIteratorTest, TilesExistOutsideViewport) { VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true)); } -static void TilesIntersectingRectExist(gfx::Rect rect, Tile* tile) { - ASSERT_TRUE(tile != NULL); - bool expected_live = rect.Intersects(tile->content_rect()); - EXPECT_EQ(expected_live, tile->priority(ACTIVE_TREE).is_live) << +static void TilesIntersectingRectExist(gfx::Rect rect, + Tile* tile, + gfx::Rect geometry_rect) { + bool expected_exists = rect.Intersects(geometry_rect); + EXPECT_EQ(expected_exists, + tile != NULL && tile->priority(ACTIVE_TREE).is_live) << "Rects intersecting " << rect.ToString() << " should exist. " << - "Current tile rect is " << tile->content_rect().ToString(); + "Current tile rect is " << geometry_rect.ToString(); } TEST_F(PictureLayerTilingIteratorTest, @@ -563,9 +608,10 @@ TEST_F(PictureLayerTilingIteratorTest, base::Bind(&TilesIntersectingRectExist, visible_rect)); } -static void CountExistingTiles(int *count, Tile* tile) { - ASSERT_TRUE(tile != NULL); - if (tile->priority(ACTIVE_TREE).is_live) +static void CountExistingTiles(int *count, + Tile* tile, + gfx::Rect geometry_rect) { + if (tile != NULL && tile->priority(ACTIVE_TREE).is_live) ++(*count); } diff --git a/cc/resources/picture_pile_base.h b/cc/resources/picture_pile_base.h index 5233929..fdfff2b 100644 --- a/cc/resources/picture_pile_base.h +++ b/cc/resources/picture_pile_base.h @@ -39,6 +39,7 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> { bool CanRaster(float contents_scale, gfx::Rect content_rect); void SetTileGridSize(gfx::Size tile_grid_size); + TilingData& tiling() { return tiling_; } protected: virtual ~PicturePileBase(); diff --git a/cc/test/fake_picture_layer_tiling_client.cc b/cc/test/fake_picture_layer_tiling_client.cc index 7e35c38..c8c4d29 100644 --- a/cc/test/fake_picture_layer_tiling_client.cc +++ b/cc/test/fake_picture_layer_tiling_client.cc @@ -52,9 +52,17 @@ void FakePictureLayerTilingClient::SetTileSize(gfx::Size tile_size) { } gfx::Size FakePictureLayerTilingClient::CalculateTileSize( - gfx::Size /* current_tile_size */, gfx::Size /* content_bounds */) { return tile_size_; } +const Region* FakePictureLayerTilingClient::GetInvalidation() { + return NULL; +} + +const PictureLayerTiling* FakePictureLayerTilingClient::GetTwinTiling( + const PictureLayerTiling* tiling) { + return NULL; +} + } // namespace cc diff --git a/cc/test/fake_picture_layer_tiling_client.h b/cc/test/fake_picture_layer_tiling_client.h index 4cde8cd..9f41348 100644 --- a/cc/test/fake_picture_layer_tiling_client.h +++ b/cc/test/fake_picture_layer_tiling_client.h @@ -25,13 +25,16 @@ class FakePictureLayerTilingClient : public PictureLayerTilingClient { PictureLayerTiling* tiling, gfx::Rect rect) OVERRIDE; virtual void UpdatePile(Tile* tile) OVERRIDE {} virtual gfx::Size CalculateTileSize( - gfx::Size current_tile_size, gfx::Size content_bounds) OVERRIDE; void SetTileSize(gfx::Size tile_size); gfx::Size TileSize() const { return tile_size_; } scoped_refptr<PicturePileImpl> pile() { return pile_; } + virtual const Region* GetInvalidation() OVERRIDE; + virtual const PictureLayerTiling* GetTwinTiling( + const PictureLayerTiling* tiling) OVERRIDE; + protected: FakeTileManagerClient tile_manager_client_; FakeRenderingStatsInstrumentation stats_instrumentation_; |