Index: cc/resources/active_picture_layer_tiling.cc |
diff --git a/cc/resources/active_picture_layer_tiling.cc b/cc/resources/active_picture_layer_tiling.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3b8682a27289f04154af4c3dae06e9340978f5aa |
--- /dev/null |
+++ b/cc/resources/active_picture_layer_tiling.cc |
@@ -0,0 +1,280 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "cc/resources/active_picture_layer_tiling.h" |
+ |
+#include "ui/gfx/geometry/point_conversions.h" |
+#include "ui/gfx/geometry/rect_conversions.h" |
+#include "ui/gfx/geometry/safe_integer_conversions.h" |
+#include "ui/gfx/geometry/size_conversions.h" |
+ |
+namespace cc { |
+ |
+scoped_ptr<PictureLayerTiling> ActivePictureLayerTiling::Create( |
+ float contents_scale, |
+ scoped_refptr<RasterSource> raster_source, |
+ PictureLayerTilingClient* client, |
+ size_t max_tiles_for_interest_area, |
+ float skewport_target_time_in_seconds, |
+ int skewport_extrapolation_limit_in_content_pixels) { |
+ return make_scoped_ptr(new ActivePictureLayerTiling( |
+ contents_scale, raster_source, client, max_tiles_for_interest_area, |
+ skewport_target_time_in_seconds, |
+ skewport_extrapolation_limit_in_content_pixels)); |
+} |
+ |
+ActivePictureLayerTiling::ActivePictureLayerTiling( |
+ float contents_scale, |
+ scoped_refptr<RasterSource> raster_source, |
+ PictureLayerTilingClient* client, |
+ size_t max_tiles_for_interest_area, |
+ float skewport_target_time_in_seconds, |
+ int skewport_extrapolation_limit_in_content_pixels) |
+ : PictureLayerTiling(contents_scale, |
+ raster_source, |
+ client, |
+ max_tiles_for_interest_area, |
+ skewport_target_time_in_seconds, |
+ skewport_extrapolation_limit_in_content_pixels) { |
+} |
+ |
+ActivePictureLayerTiling::~ActivePictureLayerTiling() { |
+} |
+ |
+void ActivePictureLayerTiling::SetRasterSourceAndResize( |
+ const scoped_refptr<RasterSource> raster_source) { |
+ DCHECK(!raster_source->IsSolidColor()); |
+ gfx::Size old_layer_bounds = raster_source_->GetSize(); |
+ raster_source_ = raster_source; |
+ gfx::Size new_layer_bounds = raster_source_->GetSize(); |
+ gfx::Size content_bounds = |
+ gfx::ToCeiledSize(gfx::ScaleSize(new_layer_bounds, contents_scale_)); |
+ gfx::Size tile_size = client_->CalculateTileSize(content_bounds); |
+ |
+ if (tile_size != tiling_data_.max_texture_size()) { |
+ tiling_data_.SetTilingSize(content_bounds); |
+ tiling_data_.SetMaxTextureSize(tile_size); |
+ // When the tile size changes, the TilingData positions no longer work |
+ // as valid keys to the TileMap, so just drop all tiles and clear the live |
+ // tiles rect. |
+ Reset(); |
+ return; |
+ } |
+ |
+ if (old_layer_bounds == new_layer_bounds) |
+ return; |
+ |
+ // The SetLiveTilesRect() method would drop tiles outside the new bounds, |
+ // but may do so incorrectly if resizing the tiling causes the number of |
+ // tiles in the tiling_data_ to change. |
+ gfx::Rect content_rect(content_bounds); |
+ int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x()); |
+ int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y()); |
+ int before_right = |
+ tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); |
+ int before_bottom = |
+ tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); |
+ |
+ // The live_tiles_rect_ is clamped to stay within the tiling size as we |
+ // change it. |
+ live_tiles_rect_.Intersect(content_rect); |
+ tiling_data_.SetTilingSize(content_bounds); |
+ |
+ int after_right = -1; |
+ int after_bottom = -1; |
+ if (!live_tiles_rect_.IsEmpty()) { |
+ after_right = |
+ tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); |
+ after_bottom = |
+ tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); |
+ } |
+ |
+ // Drop tiles outside the new layer bounds if the layer shrank. |
+ for (int i = after_right + 1; i <= before_right; ++i) { |
+ for (int j = before_top; j <= before_bottom; ++j) |
+ RemoveTileAt(i, j); |
+ } |
+ for (int i = before_left; i <= after_right; ++i) { |
+ for (int j = after_bottom + 1; j <= before_bottom; ++j) |
+ RemoveTileAt(i, j); |
+ } |
+ |
+ CreateMissingTilesInLiveTilesRect(); |
+} |
+ |
+void ActivePictureLayerTiling::Invalidate(const Region& layer_invalidation) { |
+ // We only invalidate the active tiling when it's orphaned: it has no pending |
+ // twin, so it's slated for removal in the future. |
+ DCHECK(!client_->GetPendingOrActiveTwinTiling(this)); |
+ if (live_tiles_rect_.IsEmpty()) |
+ return; |
+ std::vector<TileMapKey> new_tile_keys; |
+ gfx::Rect expanded_live_tiles_rect = |
+ tiling_data_.ExpandRectIgnoringBordersToTileBounds(live_tiles_rect_); |
+ for (Region::Iterator iter(layer_invalidation); iter.has_rect(); |
+ iter.next()) { |
+ gfx::Rect layer_rect = iter.rect(); |
+ gfx::Rect content_rect = |
+ gfx::ScaleToEnclosingRect(layer_rect, contents_scale_); |
+ // Consider tiles inside the live tiles rect even if only their border |
+ // pixels intersect the invalidation. But don't consider tiles outside |
+ // the live tiles rect with the same conditions, as they won't exist. |
+ int border_pixels = tiling_data_.border_texels(); |
+ content_rect.Inset(-border_pixels, -border_pixels); |
+ // Avoid needless work by not bothering to invalidate where there aren't |
+ // tiles. |
+ content_rect.Intersect(expanded_live_tiles_rect); |
+ if (content_rect.IsEmpty()) |
+ continue; |
+ // Since the content_rect includes border pixels already, don't include |
+ // borders when iterating to avoid double counting them. |
+ bool include_borders = false; |
+ for ( |
+ TilingData::Iterator iter(&tiling_data_, content_rect, include_borders); |
+ iter; ++iter) { |
+ if (RemoveTileAt(iter.index_x(), iter.index_y())) |
+ new_tile_keys.push_back(iter.index()); |
+ } |
+ } |
+ |
+ for (const auto& key : new_tile_keys) |
+ CreateTile(key.first, key.second); |
+} |
+ |
+void ActivePictureLayerTiling::SetRasterSourceOnTiles() { |
+ for (auto& tile_pair : tiles_) |
+ tile_pair.second->set_raster_source(raster_source_.get()); |
+} |
+ |
+void ActivePictureLayerTiling::CreateMissingTilesInLiveTilesRect() { |
+ bool include_borders = false; |
+ for (TilingData::Iterator iter(&tiling_data_, live_tiles_rect_, |
+ include_borders); |
+ iter; ++iter) { |
+ TileMapKey key = iter.index(); |
+ TileMap::iterator find = tiles_.find(key); |
+ if (find != tiles_.end()) |
+ continue; |
+ CreateTile(key.first, key.second); |
+ } |
+ |
+ VerifyLiveTilesRect(false); |
+} |
+ |
+void ActivePictureLayerTiling::TakeTilesAndPropertiesFrom( |
+ PictureLayerTiling* pending_twin) { |
+ SetRasterSourceAndResize(pending_twin->raster_source_); |
+ resolution_ = pending_twin->resolution_; |
+ SetLiveTilesRect(pending_twin->live_tiles_rect()); |
+ |
+ for (const auto& tile_pair : pending_twin->tiles_) |
+ tiles_[tile_pair.first] = tile_pair.second; |
+ pending_twin->tiles_.clear(); |
+ |
+ VerifyLiveTilesRect(false); |
+ |
+ SetTilePriorityRects(pending_twin->current_content_to_screen_scale_, |
+ pending_twin->current_visible_rect_, |
+ pending_twin->current_skewport_rect_, |
+ pending_twin->current_soon_border_rect_, |
+ pending_twin->current_eventually_rect_, |
+ pending_twin->current_occlusion_in_layer_space_); |
+} |
+ |
+bool ActivePictureLayerTiling::IsTileOccluded(const Tile* tile) const { |
+ if (!IsTileOccludedOnActiveTree(tile)) |
+ return false; |
+ |
+ // If we decide that the tile is occluded, but the same tile would not be |
enne (OOO)
2015/04/02 21:45:34
Can you help me understand this logic in the land
vmpstr
2015/04/02 22:33:26
This tile exists on the active tree and the questi
|
+ // occluded with a pending viewport, then we have to treat this tile as |
+ // unoccluded. |
+ const PictureLayerTiling* pending_twin = |
+ client_->GetPendingOrActiveTwinTiling(this); |
+ if (pending_twin) { |
+ // If there's a pending tile in the same position. Or if the pending twin |
+ // would have to be creating all tiles, then we don't need to worry about |
+ // occlusion on the twin. |
+ if (!TilingMatchesTileIndecies(pending_twin) || |
+ pending_twin->TileAt(tile->tiling_i_index(), tile->tiling_j_index())) { |
+ return true; |
+ } |
+ return pending_twin->IsTileOccluded(tile); |
+ } |
+ return true; |
+} |
+ |
+bool ActivePictureLayerTiling::IsTileRequiredForActivation( |
+ const Tile* tile) const { |
+ const PictureLayerTiling* pending_twin = |
+ client_->GetPendingOrActiveTwinTiling(this); |
+ // If we don't have a pending tree, or the pending tree will overwrite the |
+ // given tile, then it is not required for activation. |
+ if (!pending_twin || !TilingMatchesTileIndecies(pending_twin) || |
+ pending_twin->TileAt(tile->tiling_i_index(), tile->tiling_j_index())) { |
+ return false; |
+ } |
+ // Otherwise, ask the pending twin if this tile is required for activation. |
+ return pending_twin->IsTileRequiredForActivation(tile); |
+} |
+ |
+bool ActivePictureLayerTiling::IsTileRequiredForDraw(const Tile* tile) const { |
+ if (resolution_ != HIGH_RESOLUTION) |
+ return false; |
+ |
+ bool tile_is_visible = current_visible_rect_.Intersects(tile->content_rect()); |
+ if (!tile_is_visible) |
+ return false; |
+ |
+ if (IsTileOccludedOnActiveTree(tile)) |
+ return false; |
+ return true; |
+} |
+ |
+bool ActivePictureLayerTiling::IsTileOccludedOnActiveTree( |
enne (OOO)
2015/04/02 21:45:34
This looks a lot like PendingPictureLayerTiling::I
vmpstr
2015/04/02 22:33:26
Yep, I think this can be moved to PictureLayerTili
|
+ const Tile* tile) const { |
+ if (!current_occlusion_in_layer_space_.HasOcclusion()) |
+ return false; |
+ gfx::Rect tile_query_rect = |
+ gfx::IntersectRects(tile->content_rect(), current_visible_rect_); |
+ // Explicitly check if the tile is outside the viewport. If so, we need to |
+ // return false, since occlusion for this tile is unknown. |
+ if (tile_query_rect.IsEmpty()) |
+ return false; |
+ |
+ if (contents_scale_ != 1.f) { |
+ tile_query_rect = |
+ gfx::ScaleToEnclosingRect(tile_query_rect, 1.f / contents_scale_); |
+ } |
+ return current_occlusion_in_layer_space_.IsOccluded(tile_query_rect); |
+} |
+ |
+void ActivePictureLayerTiling::SetLiveTilesRect( |
+ const gfx::Rect& new_live_tiles_rect) { |
+ DCHECK(new_live_tiles_rect.IsEmpty() || |
+ gfx::Rect(tiling_size()).Contains(new_live_tiles_rect)) |
+ << "tiling_size: " << tiling_size().ToString() |
+ << " new_live_tiles_rect: " << new_live_tiles_rect.ToString(); |
+ 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) { |
+ RemoveTileAt(iter.index_x(), iter.index_y()); |
+ } |
+ |
+ // 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; |
+ VerifyLiveTilesRect(false); |
+} |
+ |
+} // namespace cc |