diff options
-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_; |