Chromium Code Reviews| Index: cc/resources/picture_layer_tiling.cc |
| diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc |
| index 497b75c23016de5462450a43ae3dc3e467c5a450..42d0f1c7cbac5494e4d2b2e2814a0344ca425308 100644 |
| --- a/cc/resources/picture_layer_tiling.cc |
| +++ b/cc/resources/picture_layer_tiling.cc |
| @@ -17,6 +17,17 @@ |
| namespace cc { |
| +namespace { |
| + |
| +const int kTileBundleWidth = 2; |
| +const int kTileBundleHeight = 2; |
| + |
| +std::pair<int, int> ComputeTileBundleIndex(int i, int j) { |
| + return std::make_pair(i / kTileBundleWidth, j / kTileBundleHeight); |
| +} |
| + |
| +} |
| + |
| scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( |
| float contents_scale, |
| gfx::Size layer_bounds, |
| @@ -34,6 +45,8 @@ PictureLayerTiling::PictureLayerTiling(float contents_scale, |
| resolution_(NON_IDEAL_RESOLUTION), |
| client_(client), |
| tiling_data_(gfx::Size(), gfx::Size(), true), |
| + bundle_tiling_data_(gfx::Size(), gfx::Size(), true), |
| + current_tree_(PENDING_TREE), |
| last_impl_frame_time_in_seconds_(0.0) { |
| gfx::Size content_bounds = |
| gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)); |
| @@ -47,6 +60,10 @@ PictureLayerTiling::PictureLayerTiling(float contents_scale, |
| tiling_data_.SetTotalSize(content_bounds); |
| tiling_data_.SetMaxTextureSize(tile_size); |
| + bundle_tiling_data_.SetTotalSize(content_bounds); |
| + bundle_tiling_data_.SetMaxTextureSize( |
| + gfx::Size(tile_size.width() * kTileBundleWidth, |
| + tile_size.height() * kTileBundleHeight)); |
| } |
| PictureLayerTiling::~PictureLayerTiling() { |
| @@ -64,41 +81,103 @@ gfx::SizeF PictureLayerTiling::ContentSizeF() const { |
| return gfx::ScaleSize(layer_bounds_, contents_scale_); |
| } |
| -Tile* PictureLayerTiling::TileAt(int i, int j) const { |
| - TileMap::const_iterator iter = tiles_.find(TileMapKey(i, j)); |
| - if (iter == tiles_.end()) |
| +TileBundle* PictureLayerTiling::CreateBundleForTileAt( |
| + int i, |
| + int j, |
| + const PictureLayerTiling* twin_tiling) { |
| + TileBundleMapKey key = ComputeTileBundleIndex(i, j); |
| + DCHECK(tile_bundles_.find(key) == tile_bundles_.end()); |
| + |
| + scoped_refptr<TileBundle> candidate_bundle = NULL; |
| + |
| + // Always try to get the twin bundle first. TileBundles are always shared |
| + // between trees. |
| + if (twin_tiling && |
| + tiling_data_.max_texture_size() == |
| + twin_tiling->tiling_data_.max_texture_size()) { |
| + candidate_bundle = twin_tiling->TileBundleAt(key.first, key.second); |
| + } |
| + |
| + // If we couldn't get a tile bundle, create a new one. |
| + if (!candidate_bundle) { |
| + candidate_bundle = client_->CreateTileBundle(key.first * kTileBundleWidth, |
| + key.second * kTileBundleHeight, |
| + kTileBundleWidth, |
| + kTileBundleHeight); |
| + } |
| + candidate_bundle->SwapTilesIfRequired(); |
| + tile_bundles_[key] = candidate_bundle; |
| + return candidate_bundle.get(); |
| +} |
| + |
| +TileBundle* PictureLayerTiling::TileBundleContainingTileAt(int i, int j) const { |
| + TileBundleMapKey key = ComputeTileBundleIndex(i, j); |
| + return TileBundleAt(key.first, key.second); |
| +} |
| + |
| +TileBundle* PictureLayerTiling::TileBundleAt(int i, int j) const { |
| + TileBundleMapKey key(i, j); |
| + TileBundleMap::const_iterator it = tile_bundles_.find(key); |
| + if (it == tile_bundles_.end()) |
| return NULL; |
| - return iter->second.get(); |
| + it->second->SwapTilesIfRequired(); |
| + return it->second.get(); |
| } |
| -void PictureLayerTiling::CreateTile(int i, |
| +Tile* PictureLayerTiling::TileAt(WhichTree tree, int i, int j) const { |
| + TileBundle* bundle = TileBundleContainingTileAt(i, j); |
| + if (!bundle) |
| + return NULL; |
| + return bundle->TileAt(tree, i, j); |
| +} |
| + |
| +void PictureLayerTiling::CreateTile(WhichTree tree, |
| + int i, |
| int j, |
| const PictureLayerTiling* twin_tiling) { |
| - TileMapKey key(i, j); |
| - DCHECK(tiles_.find(key) == tiles_.end()); |
| + TileBundle* bundle = TileBundleContainingTileAt(i, j); |
| + if (!bundle) |
| + bundle = CreateBundleForTileAt(i, j, twin_tiling); |
| 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. |
| - if (twin_tiling && |
| - tiling_data_.max_texture_size() == |
| - twin_tiling->tiling_data_.max_texture_size()) { |
| - if (Tile* candidate_tile = twin_tiling->TileAt(i, j)) { |
| - gfx::Rect rect = |
| - gfx::ScaleToEnclosingRect(paint_rect, 1.0f / contents_scale_); |
| - if (!client_->GetInvalidation()->Intersects(rect)) { |
| - tiles_[key] = candidate_tile; |
| - return; |
| - } |
| + WhichTree twin_tree = (tree == ACTIVE_TREE) ? PENDING_TREE : ACTIVE_TREE; |
| + if (Tile* candidate_tile = bundle->TileAt(twin_tree, i, j)) { |
| + gfx::Rect rect = |
| + gfx::ScaleToEnclosingRect(paint_rect, 1.0f / contents_scale_); |
| + if (!client_->GetInvalidation()->Intersects(rect)) { |
| + bundle->AddTileAt(tree, i, j, 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.get()) |
| - tiles_[key] = tile; |
| + bundle->AddTileAt(tree, i, j, tile); |
| +} |
| + |
| +bool PictureLayerTiling::RemoveTile(WhichTree tree, int i, int j) { |
| + TileBundleMapKey key = ComputeTileBundleIndex(i, j); |
| + TileBundleMap::iterator it = tile_bundles_.find(key); |
| + if (it == tile_bundles_.end()) |
| + return false; |
| + |
| + it->second->SwapTilesIfRequired(); |
| + return it->second->RemoveTileAt(tree, i, j); |
| +} |
| + |
| +void PictureLayerTiling::RemoveBundleIfEmptyContainingTileAt(int i, int j) { |
| + TileBundleMapKey key = ComputeTileBundleIndex(i, j); |
| + TileBundleMap::iterator it = tile_bundles_.find(key); |
| + if (it == tile_bundles_.end()) |
| + return; |
| + |
| + if (it->second->IsEmpty()) |
| + tile_bundles_.erase(it); |
| } |
| Region PictureLayerTiling::OpaqueRegionInContentRect( |
| @@ -109,19 +188,30 @@ Region PictureLayerTiling::OpaqueRegionInContentRect( |
| } |
| void PictureLayerTiling::SetCanUseLCDText(bool can_use_lcd_text) { |
| - for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) |
| - it->second->set_can_use_lcd_text(can_use_lcd_text); |
| + // TODO(vmpstr): This can be done per bundle with results used |
| + // in tile manager. |
| + for (TileBundleMap::iterator it = tile_bundles_.begin(); |
| + it != tile_bundles_.end(); |
| + ++it) { |
| + for (TileBundle::Iterator tile_it(it->second, current_tree_); |
| + tile_it; |
| + ++tile_it) |
| + tile_it->set_can_use_lcd_text(can_use_lcd_text); |
| + } |
| } |
| void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { |
| + DCHECK(current_tree_ == PENDING_TREE); |
| + |
| const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); |
| for (TilingData::Iterator iter(&tiling_data_, live_tiles_rect_); iter; |
| ++iter) { |
| - TileMapKey key = iter.index(); |
| - TileMap::iterator find = tiles_.find(key); |
| - if (find != tiles_.end()) |
| + int tile_x = iter.index_x(); |
| + int tile_y = iter.index_y(); |
| + Tile* tile = TileAt(PENDING_TREE, tile_x, tile_y); |
| + if (tile) |
| continue; |
| - CreateTile(key.first, key.second, twin_tiling); |
| + CreateTile(PENDING_TREE, tile_x, tile_y, twin_tiling); |
| } |
| } |
| @@ -129,6 +219,7 @@ void PictureLayerTiling::SetLayerBounds(gfx::Size layer_bounds) { |
| if (layer_bounds_ == layer_bounds) |
| return; |
| + DCHECK(current_tree_ == PENDING_TREE); |
| DCHECK(!layer_bounds.IsEmpty()); |
| gfx::Size old_layer_bounds = layer_bounds_; |
| @@ -141,6 +232,10 @@ void PictureLayerTiling::SetLayerBounds(gfx::Size layer_bounds) { |
| if (tile_size != tiling_data_.max_texture_size()) { |
| tiling_data_.SetTotalSize(content_bounds); |
| tiling_data_.SetMaxTextureSize(tile_size); |
| + bundle_tiling_data_.SetTotalSize(content_bounds); |
| + bundle_tiling_data_.SetMaxTextureSize( |
|
enne (OOO)
2013/11/27 23:43:19
Re: unit tests. Can you also make sure to add som
vmpstr
2013/12/02 23:08:00
This is done. I ended up changing the bundle_tilin
|
| + gfx::Size(tile_size.width() * kTileBundleWidth, |
| + tile_size.height() * kTileBundleHeight)); |
| Reset(); |
| return; |
| } |
| @@ -150,6 +245,7 @@ void PictureLayerTiling::SetLayerBounds(gfx::Size layer_bounds) { |
| bounded_live_tiles_rect.Intersect(gfx::Rect(content_bounds)); |
| SetLiveTilesRect(bounded_live_tiles_rect); |
| tiling_data_.SetTotalSize(content_bounds); |
| + bundle_tiling_data_.SetTotalSize(content_bounds); |
| // Create tiles for newly exposed areas. |
| Region layer_region((gfx::Rect(layer_bounds_))); |
| @@ -158,7 +254,9 @@ void PictureLayerTiling::SetLayerBounds(gfx::Size layer_bounds) { |
| } |
| void PictureLayerTiling::Invalidate(const Region& layer_region) { |
| - std::vector<TileMapKey> new_tile_keys; |
| + DCHECK(current_tree_ == PENDING_TREE); |
| + |
| + std::vector<std::pair<int, int> > new_tile_keys; |
| for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) { |
| gfx::Rect layer_rect = iter.rect(); |
| gfx::Rect content_rect = |
| @@ -167,18 +265,23 @@ void PictureLayerTiling::Invalidate(const Region& layer_region) { |
| if (content_rect.IsEmpty()) |
| continue; |
| for (TilingData::Iterator iter(&tiling_data_, content_rect); iter; ++iter) { |
| - TileMapKey key(iter.index()); |
| - TileMap::iterator find = tiles_.find(key); |
| - if (find == tiles_.end()) |
| - continue; |
| - tiles_.erase(find); |
| - new_tile_keys.push_back(key); |
| + int tile_x = iter.index_x(); |
| + int tile_y = iter.index_y(); |
| + |
| + // If there is no bundle for the given tile, we can skip. |
| + bool deleted = RemoveTile(PENDING_TREE, tile_x, tile_y); |
| + if (deleted) |
| + new_tile_keys.push_back(std::make_pair(tile_x, tile_y)); |
| } |
| } |
| const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); |
| - for (size_t i = 0; i < new_tile_keys.size(); ++i) |
| - CreateTile(new_tile_keys[i].first, new_tile_keys[i].second, twin_tiling); |
| + for (size_t i = 0; i < new_tile_keys.size(); ++i) { |
| + CreateTile(PENDING_TREE, |
| + new_tile_keys[i].first, |
| + new_tile_keys[i].second, |
| + twin_tiling); |
| + } |
| } |
| PictureLayerTiling::CoverageIterator::CoverageIterator() |
| @@ -205,7 +308,8 @@ PictureLayerTiling::CoverageIterator::CoverageIterator( |
| left_(0), |
| top_(0), |
| right_(-1), |
| - bottom_(-1) { |
| + bottom_(-1), |
| + tree_(tiling->current_tree_) { |
| DCHECK(tiling_); |
| if (dest_rect_.IsEmpty()) |
| return; |
| @@ -260,7 +364,7 @@ PictureLayerTiling::CoverageIterator::operator++() { |
| } |
| } |
| - current_tile_ = tiling_->TileAt(tile_i_, tile_j_); |
| + current_tile_ = tiling_->TileAt(tree_, tile_i_, tile_j_); |
| // Calculate the current geometry rect. Due to floating point rounding |
| // and ToEnclosingRect, tiles might overlap in destination space on the |
| @@ -316,6 +420,19 @@ PictureLayerTiling::CoverageIterator::full_tile_geometry_rect() const { |
| return rect; |
| } |
| +TilePriority PictureLayerTiling::CoverageIterator::priority() { |
| + TileBundle* bundle = tiling_->TileBundleContainingTileAt(tile_i_, tile_j_); |
| + if (bundle) |
| + return bundle->GetPriority(tree_); |
| + return TilePriority(); |
| +} |
| + |
| +void PictureLayerTiling::CoverageIterator::SetPriorityForTesting( |
| + const TilePriority& priority) { |
| + TileBundle* bundle = tiling_->TileBundleContainingTileAt(tile_i_, tile_j_); |
| + bundle->SetPriority(tree_, priority); |
| +} |
| + |
| gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const { |
| gfx::PointF tex_origin = |
| tiling_->tiling_data_.TileBoundsWithBorder(tile_i_, tile_j_).origin(); |
| @@ -336,7 +453,7 @@ gfx::Size PictureLayerTiling::CoverageIterator::texture_size() const { |
| void PictureLayerTiling::Reset() { |
| live_tiles_rect_ = gfx::Rect(); |
| - tiles_.clear(); |
| + tile_bundles_.clear(); |
| } |
| void PictureLayerTiling::UpdateTilePriorities( |
| @@ -352,6 +469,10 @@ void PictureLayerTiling::UpdateTilePriorities( |
| const gfx::Transform& current_screen_transform, |
| double current_frame_time_in_seconds, |
| size_t max_tiles_for_interest_area) { |
| + if (!has_ever_been_updated()) |
| + current_tree_ = tree; |
| + |
| + DCHECK_EQ(tree, current_tree_); |
| if (!NeedsUpdateForFrameAtTime(current_frame_time_in_seconds)) { |
| // This should never be zero for the purposes of has_ever_been_updated(). |
| DCHECK_NE(current_frame_time_in_seconds, 0.0); |
| @@ -407,23 +528,22 @@ void PictureLayerTiling::UpdateTilePriorities( |
| last_screen_transform.matrix().get(0, 3), |
| last_screen_transform.matrix().get(1, 3)); |
| - for (TilingData::Iterator iter(&tiling_data_, interest_rect); |
| + for (TilingData::Iterator iter(&bundle_tiling_data_, interest_rect); |
| iter; ++iter) { |
| - TileMap::iterator find = tiles_.find(iter.index()); |
| - if (find == tiles_.end()) |
| + int bundle_x = iter.index_x(); |
| + int bundle_y = iter.index_y(); |
| + TileBundle* bundle = TileBundleAt(bundle_x, bundle_y); |
| + if (!bundle) |
| continue; |
| - Tile* tile = find->second.get(); |
| - gfx::Rect tile_bounds = |
| - tiling_data_.TileBounds(iter.index_x(), iter.index_y()); |
| - gfx::RectF current_screen_rect = gfx::ScaleRect( |
| - tile_bounds, |
| - current_scale, |
| - current_scale) + current_offset; |
| - gfx::RectF last_screen_rect = gfx::ScaleRect( |
| - tile_bounds, |
| - last_scale, |
| - last_scale) + last_offset; |
| + gfx::Rect bundle_bounds = |
| + bundle_tiling_data_.TileBounds(bundle_x, bundle_y); |
| + gfx::RectF current_screen_rect = |
| + gfx::ScaleRect(bundle_bounds, current_scale, current_scale) + |
| + current_offset; |
| + gfx::RectF last_screen_rect = |
| + gfx::ScaleRect(bundle_bounds, last_scale, last_scale) + |
| + last_offset; |
| float distance_to_visible_in_pixels = |
| TilePriority::manhattanDistance(current_screen_rect, view_rect); |
| @@ -435,7 +555,8 @@ void PictureLayerTiling::UpdateTilePriorities( |
| resolution_, |
| time_to_visible_in_seconds, |
| distance_to_visible_in_pixels); |
| - tile->SetPriority(tree, priority); |
| + |
| + bundle->SetPriority(tree, priority); |
| } |
| } else if (!last_screen_transform.HasPerspective() && |
| !current_screen_transform.HasPerspective()) { |
| @@ -455,55 +576,57 @@ void PictureLayerTiling::UpdateTilePriorities( |
| last_screen_transform.matrix().get(0, 3), |
| last_screen_transform.matrix().get(1, 3)); |
| - float current_tile_width = tiling_data_.TileSizeX(0) * current_scale; |
| - float last_tile_width = tiling_data_.TileSizeX(0) * last_scale; |
| - float current_tile_height = tiling_data_.TileSizeY(0) * current_scale; |
| - float last_tile_height = tiling_data_.TileSizeY(0) * last_scale; |
| + float current_bundle_width = |
| + bundle_tiling_data_.TileSizeX(0) * current_scale; |
| + float last_bundle_width = |
| + bundle_tiling_data_.TileSizeX(0) * last_scale; |
| + float current_bundle_height = |
| + bundle_tiling_data_.TileSizeY(0) * current_scale; |
| + float last_bundle_height = |
| + bundle_tiling_data_.TileSizeY(0) * last_scale; |
| // Apply screen space transform to local basis vectors (tile_width, 0) and |
| // (0, tile_height); the math simplifies and can be initialized directly. |
| gfx::Vector2dF current_horizontal( |
| - current_screen_transform.matrix().get(0, 0) * current_tile_width, |
| - current_screen_transform.matrix().get(1, 0) * current_tile_width); |
| + current_screen_transform.matrix().get(0, 0) * current_bundle_width, |
| + current_screen_transform.matrix().get(1, 0) * current_bundle_width); |
| gfx::Vector2dF current_vertical( |
| - current_screen_transform.matrix().get(0, 1) * current_tile_height, |
| - current_screen_transform.matrix().get(1, 1) * current_tile_height); |
| + current_screen_transform.matrix().get(0, 1) * current_bundle_height, |
| + current_screen_transform.matrix().get(1, 1) * current_bundle_height); |
| gfx::Vector2dF last_horizontal( |
| - last_screen_transform.matrix().get(0, 0) * last_tile_width, |
| - last_screen_transform.matrix().get(1, 0) * last_tile_width); |
| + last_screen_transform.matrix().get(0, 0) * last_bundle_width, |
| + last_screen_transform.matrix().get(1, 0) * last_bundle_width); |
| gfx::Vector2dF last_vertical( |
| - last_screen_transform.matrix().get(0, 1) * last_tile_height, |
| - last_screen_transform.matrix().get(1, 1) * last_tile_height); |
| + last_screen_transform.matrix().get(0, 1) * last_bundle_height, |
| + last_screen_transform.matrix().get(1, 1) * last_bundle_height); |
| - for (TilingData::Iterator iter(&tiling_data_, interest_rect); |
| + for (TilingData::Iterator iter(&bundle_tiling_data_, interest_rect); |
| iter; ++iter) { |
| - TileMap::iterator find = tiles_.find(iter.index()); |
| - if (find == tiles_.end()) |
| + int bundle_x = iter.index_x(); |
| + int bundle_y = iter.index_y(); |
| + TileBundle* bundle = TileBundleAt(bundle_x, bundle_y); |
| + if (!bundle) |
| continue; |
| - Tile* tile = find->second.get(); |
| - |
| - int i = iter.index_x(); |
| - int j = iter.index_y(); |
| - gfx::PointF current_tile_origin = current_screen_space_origin + |
| - ScaleVector2d(current_horizontal, i) + |
| - ScaleVector2d(current_vertical, j); |
| - gfx::PointF last_tile_origin = last_screen_space_origin + |
| - ScaleVector2d(last_horizontal, i) + |
| - ScaleVector2d(last_vertical, j); |
| + gfx::PointF current_bundle_origin = current_screen_space_origin + |
| + ScaleVector2d(current_horizontal, bundle_x) + |
| + ScaleVector2d(current_vertical, bundle_y); |
| + gfx::PointF last_bundle_origin = last_screen_space_origin + |
| + ScaleVector2d(last_horizontal, bundle_x) + |
| + ScaleVector2d(last_vertical, bundle_y); |
| gfx::RectF current_screen_rect = gfx::QuadF( |
| - current_tile_origin, |
| - current_tile_origin + current_horizontal, |
| - current_tile_origin + current_horizontal + current_vertical, |
| - current_tile_origin + current_vertical).BoundingBox(); |
| + current_bundle_origin, |
| + current_bundle_origin + current_horizontal, |
| + current_bundle_origin + current_horizontal + current_vertical, |
| + current_bundle_origin + current_vertical).BoundingBox(); |
| gfx::RectF last_screen_rect = gfx::QuadF( |
| - last_tile_origin, |
| - last_tile_origin + last_horizontal, |
| - last_tile_origin + last_horizontal + last_vertical, |
| - last_tile_origin + last_vertical).BoundingBox(); |
| + last_bundle_origin, |
| + last_bundle_origin + last_horizontal, |
| + last_bundle_origin + last_horizontal + last_vertical, |
| + last_bundle_origin + last_vertical).BoundingBox(); |
| float distance_to_visible_in_pixels = |
| TilePriority::manhattanDistance(current_screen_rect, view_rect); |
| @@ -515,26 +638,28 @@ void PictureLayerTiling::UpdateTilePriorities( |
| resolution_, |
| time_to_visible_in_seconds, |
| distance_to_visible_in_pixels); |
| - tile->SetPriority(tree, priority); |
| + |
| + bundle->SetPriority(tree, priority); |
| } |
| } else { |
| - for (TilingData::Iterator iter(&tiling_data_, interest_rect); |
| + for (TilingData::Iterator iter(&bundle_tiling_data_, interest_rect); |
| iter; ++iter) { |
| - TileMap::iterator find = tiles_.find(iter.index()); |
| - if (find == tiles_.end()) |
| + int bundle_x = iter.index_x(); |
| + int bundle_y = iter.index_y(); |
| + TileBundle* bundle = TileBundleAt(bundle_x, bundle_y); |
| + if (!bundle) |
| continue; |
| - Tile* tile = find->second.get(); |
| - gfx::Rect tile_bounds = |
| - tiling_data_.TileBounds(iter.index_x(), iter.index_y()); |
| + gfx::Rect bundle_bounds = |
| + bundle_tiling_data_.TileBounds(bundle_x, bundle_y); |
| gfx::RectF current_layer_content_rect = gfx::ScaleRect( |
| - tile_bounds, |
| + bundle_bounds, |
| current_scale, |
| current_scale); |
| gfx::RectF current_screen_rect = MathUtil::MapClippedRect( |
| current_screen_transform, current_layer_content_rect); |
| gfx::RectF last_layer_content_rect = gfx::ScaleRect( |
| - tile_bounds, |
| + bundle_bounds, |
| last_scale, |
| last_scale); |
| gfx::RectF last_screen_rect = MathUtil::MapClippedRect( |
| @@ -551,15 +676,15 @@ void PictureLayerTiling::UpdateTilePriorities( |
| resolution_, |
| time_to_visible_in_seconds, |
| distance_to_visible_in_pixels); |
| - tile->SetPriority(tree, priority); |
| + |
| + bundle->SetPriority(tree, priority); |
| } |
| } |
| last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; |
| } |
| -void PictureLayerTiling::SetLiveTilesRect( |
| - gfx::Rect new_live_tiles_rect) { |
| +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) |
| @@ -571,12 +696,13 @@ void PictureLayerTiling::SetLiveTilesRect( |
| new_live_tiles_rect); |
| iter; |
| ++iter) { |
| - TileMapKey key(iter.index()); |
| - TileMap::iterator found = tiles_.find(key); |
| + int tile_x = iter.index_x(); |
| + int tile_y = iter.index_y(); |
| + |
| // 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()) |
| - tiles_.erase(found); |
| + RemoveTile(current_tree_, tile_x, tile_y); |
| + RemoveBundleIfEmptyContainingTileAt(tile_x, tile_y); |
| } |
| const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); |
| @@ -587,8 +713,7 @@ void PictureLayerTiling::SetLiveTilesRect( |
| live_tiles_rect_); |
| iter; |
| ++iter) { |
| - TileMapKey key(iter.index()); |
| - CreateTile(key.first, key.second, twin_tiling); |
| + CreateTile(current_tree_, iter.index_x(), iter.index_y(), twin_tiling); |
| } |
| live_tiles_rect_ = new_live_tiles_rect; |
| @@ -599,35 +724,52 @@ void PictureLayerTiling::DidBecomeRecycled() { |
| // still in the tree. Calling this first on an active tiling that is becoming |
| // recycled takes care of tiles that are no longer in the active tree (eg. |
| // due to a pending invalidation). |
| - for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| - it->second->SetPriority(ACTIVE_TREE, TilePriority()); |
| + for (TileBundleMap::const_iterator it = tile_bundles_.begin(); |
| + it != tile_bundles_.end(); |
| + ++it) { |
| + it->second->DidBecomeRecycled(); |
| } |
| + // Note that recycled tree would not be accessed, and the next tree |
| + // stage after recycled in pending, so we can just set the state to |
| + // pending here. |
| + current_tree_ = PENDING_TREE; |
| } |
| void PictureLayerTiling::DidBecomeActive() { |
| - for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| - it->second->SetPriority(ACTIVE_TREE, it->second->priority(PENDING_TREE)); |
| - it->second->SetPriority(PENDING_TREE, TilePriority()); |
| - |
| - // Tile holds a ref onto a picture pile. If the tile never gets invalidated |
| - // and recreated, then that picture pile ref could exist indefinitely. To |
| - // prevent this, ask the client to update the pile to its own ref. This |
| - // will cause PicturePileImpls and their clones to get deleted once the |
| - // corresponding PictureLayerImpl and any in flight raster jobs go out of |
| - // scope. |
| - client_->UpdatePile(it->second.get()); |
| + for (TileBundleMap::const_iterator it = tile_bundles_.begin(); |
| + it != tile_bundles_.end(); |
| + ++it) { |
| + it->second->DidBecomeActive(); |
| + for (TileBundle::Iterator tile_it(it->second.get(), ACTIVE_TREE); |
| + tile_it; |
| + ++tile_it) { |
| + // Tile holds a ref onto a picture pile. If the tile never gets |
| + // invalidated and recreated, then that picture pile ref could exist |
| + // indefinitely. To prevent this, ask the client to update the pile to |
| + // its own ref. This will cause PicturePileImpls and their clones to get |
| + // deleted once the corresponding PictureLayerImpl and any in flight |
| + // raster jobs go out of scope. |
| + client_->UpdatePile(*tile_it); |
| + } |
| } |
| + current_tree_ = ACTIVE_TREE; |
| } |
| void PictureLayerTiling::UpdateTilesToCurrentPile() { |
| - for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| - client_->UpdatePile(it->second.get()); |
| + for (TileBundleMap::const_iterator it = tile_bundles_.begin(); |
| + it != tile_bundles_.end(); |
| + ++it) { |
| + for (TileBundle::Iterator tile_it(it->second.get(), PENDING_TREE); |
| + tile_it; |
| + ++tile_it) { |
| + client_->UpdatePile(*tile_it); |
| + } |
| } |
| } |
| scoped_ptr<base::Value> PictureLayerTiling::AsValue() const { |
| scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
| - state->SetInteger("num_tiles", tiles_.size()); |
| + state->SetInteger("num_tile_bundles", tile_bundles_.size()); |
| state->SetDouble("content_scale", contents_scale_); |
| state->Set("content_bounds", |
| MathUtil::AsValue(ContentRect().size()).release()); |
| @@ -636,9 +778,11 @@ scoped_ptr<base::Value> PictureLayerTiling::AsValue() const { |
| size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { |
| size_t amount = 0; |
| - for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| - const Tile* tile = it->second.get(); |
| - amount += tile->GPUMemoryUsageInBytes(); |
| + for (TileBundleMap::const_iterator it = tile_bundles_.begin(); |
| + it != tile_bundles_.end(); |
| + ++it) { |
| + for (TileBundle::Iterator tile_it(it->second.get()); tile_it; ++tile_it) |
| + amount += tile_it->GPUMemoryUsageInBytes(); |
| } |
| return amount; |
| } |