Index: cc/resources/pending_picture_layer_tiling.cc |
diff --git a/cc/resources/pending_picture_layer_tiling.cc b/cc/resources/pending_picture_layer_tiling.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f536dc5738d6d471be22613295f72393ead5a328 |
--- /dev/null |
+++ b/cc/resources/pending_picture_layer_tiling.cc |
@@ -0,0 +1,241 @@ |
+// 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/pending_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> PendingPictureLayerTiling::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 PendingPictureLayerTiling( |
+ contents_scale, raster_source, client, max_tiles_for_interest_area, |
+ skewport_target_time_in_seconds, |
+ skewport_extrapolation_limit_in_content_pixels)); |
+} |
+ |
+PendingPictureLayerTiling::PendingPictureLayerTiling( |
+ 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) { |
+} |
+ |
+PendingPictureLayerTiling::~PendingPictureLayerTiling() { |
+} |
+ |
+void PendingPictureLayerTiling::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); |
+ } |
+ |
+ // There is no recycled twin since this is run on the pending tiling |
+ // during commit, and on the active tree during activate. |
+ // 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); |
+ } |
+ |
+ if (after_right > before_right) { |
+ DCHECK_EQ(after_right, before_right + 1); |
+ for (int j = before_top; j <= after_bottom; ++j) |
+ CreateTile(after_right, j); |
+ } |
+ if (after_bottom > before_bottom) { |
+ DCHECK_EQ(after_bottom, before_bottom + 1); |
+ for (int i = before_left; i <= before_right; ++i) |
+ CreateTile(i, after_bottom); |
+ } |
+} |
+ |
+void PendingPictureLayerTiling::Invalidate(const Region& layer_invalidation) { |
+ // Nothing to do here. |
+} |
+ |
+void PendingPictureLayerTiling::SetRasterSourceOnTiles() { |
+// Nothing to do, but we can verify that the tiles already have the latest |
+// raster source. |
+#if DCHECK_IS_ON() |
+ for (const auto& tile_pair : tiles_) |
+ DCHECK_EQ(raster_source_.get(), tile_pair.second->raster_source()); |
+#endif |
+} |
+ |
+bool PendingPictureLayerTiling::ShouldCreateTileAt(int i, int j) const { |
+ const PictureLayerTiling* active_twin = |
+ client_->GetPendingOrActiveTwinTiling(this); |
+ if (!active_twin) |
+ return true; |
+ |
+ if (!TilingMatchesTileIndecies(active_twin)) |
enne (OOO)
2015/04/02 21:45:34
indices?
vmpstr
2015/04/02 22:33:27
Yup, poor spelling on my part.
|
+ return true; |
+ |
+ gfx::Rect paint_rect = tiling_data_.TileBoundsWithBorder(i, j); |
+ gfx::Rect tile_rect = paint_rect; |
+ tile_rect.set_size(tiling_data_.max_texture_size()); |
+ |
+ if (!active_twin->raster_source()->CoversRect(tile_rect, contents_scale())) |
+ return true; |
+ |
+ const Region* layer_invalidation = client_->GetPendingInvalidation(); |
+ gfx::Rect layer_rect = |
+ gfx::ScaleToEnclosingRect(tile_rect, 1.f / contents_scale()); |
+ |
+ if (layer_invalidation && layer_invalidation->Intersects(layer_rect)) |
+ return true; |
+ return false; |
+} |
+ |
+void PendingPictureLayerTiling::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; |
+ |
+ if (ShouldCreateTileAt(key.first, key.second)) |
+ CreateTile(key.first, key.second); |
+ } |
+ VerifyLiveTilesRect(false); |
+} |
+ |
+void PendingPictureLayerTiling::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()); |
+ if (ShouldCreateTileAt(key.first, key.second)) |
+ CreateTile(key.first, key.second); |
+ } |
+ |
+ live_tiles_rect_ = new_live_tiles_rect; |
+ VerifyLiveTilesRect(false); |
+} |
+ |
+void PendingPictureLayerTiling::TakeTilesAndPropertiesFrom( |
+ PictureLayerTiling* pending_twin) { |
+ // This function should only be called on the active tree. |
+ NOTREACHED(); |
+} |
+ |
+bool PendingPictureLayerTiling::IsTileOccluded(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); |
+} |
+ |
+bool PendingPictureLayerTiling::IsTileRequiredForActivation( |
+ const Tile* tile) const { |
+ if (!can_require_tiles_for_activation_) |
+ return false; |
+ |
+ if (resolution_ != HIGH_RESOLUTION) |
+ return false; |
+ |
+ if (IsTileOccluded(tile)) |
+ return false; |
+ |
+ return tile->content_rect().Intersects(current_visible_rect_); |
+} |
+ |
+bool PendingPictureLayerTiling::IsTileRequiredForDraw(const Tile* tile) const { |
+ return false; |
+} |
+ |
+} // namespace cc |