diff options
author | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-29 22:13:47 +0000 |
---|---|---|
committer | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-29 22:13:47 +0000 |
commit | 63db922a88e051d26447ad46899a02c7b583e503 (patch) | |
tree | d0348a000f1ef7296682bffc847f3028835c275b /cc | |
parent | b559b1363c3095ff42577739e00a37b1975d1959 (diff) | |
download | chromium_src-63db922a88e051d26447ad46899a02c7b583e503.zip chromium_src-63db922a88e051d26447ad46899a02c7b583e503.tar.gz chromium_src-63db922a88e051d26447ad46899a02c7b583e503.tar.bz2 |
cc: Limit the set of tiles updated each frame
The viewport rect is projected into content space, to avoid clipping issues and
so that offscreen layers can still get tiles. Then an area around that rect is
used to determine the set of tiles to consider prioritizing.
R=nduca@chromium.org
BUG=171826
Review URL: https://chromiumcodereview.appspot.com/12092009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@179432 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/picture_layer_impl.cc | 10 | ||||
-rw-r--r-- | cc/picture_layer_tiling.cc | 93 | ||||
-rw-r--r-- | cc/picture_layer_tiling.h | 2 | ||||
-rw-r--r-- | cc/picture_layer_tiling_set.cc | 7 | ||||
-rw-r--r-- | cc/picture_layer_tiling_set.h | 1 | ||||
-rw-r--r-- | cc/tile_manager.cc | 17 | ||||
-rw-r--r-- | cc/tile_priority.cc | 3 | ||||
-rw-r--r-- | cc/tile_priority.h | 36 |
8 files changed, 130 insertions, 39 deletions
diff --git a/cc/picture_layer_impl.cc b/cc/picture_layer_impl.cc index f7687f7..a7cd43c8 100644 --- a/cc/picture_layer_impl.cc +++ b/cc/picture_layer_impl.cc @@ -232,10 +232,20 @@ void PictureLayerImpl::updateTilePriorities() { last_content_scale_ == contentsScaleX()) { time_delta = current_frame_time - last_impl_frame_time_; } + + gfx::Rect viewport_in_content_space; + gfx::Transform screenToLayer(gfx::Transform::kSkipInitialization); + if (screenSpaceTransform().GetInverse(&screenToLayer)) { + gfx::Rect device_viewport(layerTreeImpl()->device_viewport_size()); + viewport_in_content_space = gfx::ToEnclosingRect( + MathUtil::projectClippedRect(screenToLayer, device_viewport)); + } + WhichTree tree = layerTreeImpl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE; tilings_->UpdateTilePriorities( tree, layerTreeImpl()->device_viewport_size(), + viewport_in_content_space, last_content_scale_, contentsScaleX(), last_screen_space_transform_, diff --git a/cc/picture_layer_tiling.cc b/cc/picture_layer_tiling.cc index ad460f1..0127754 100644 --- a/cc/picture_layer_tiling.cc +++ b/cc/picture_layer_tiling.cc @@ -292,6 +292,7 @@ gfx::Size PictureLayerTiling::Iterator::texture_size() const { void PictureLayerTiling::UpdateTilePriorities( WhichTree tree, const gfx::Size& device_viewport, + const gfx::RectF viewport_in_layer_space, float last_layer_contents_scale, float current_layer_contents_scale, const gfx::Transform& last_screen_transform, @@ -301,10 +302,40 @@ void PictureLayerTiling::UpdateTilePriorities( if (content_rect.IsEmpty()) return; - gfx::Rect view_rect(gfx::Point(), device_viewport); + gfx::Rect viewport_in_content_space = + gfx::ToEnclosingRect(gfx::ScaleRect(viewport_in_layer_space, + contents_scale_)); + gfx::Rect inflated_rect = viewport_in_content_space; + inflated_rect.Inset( + -TilePriority::kMaxDistanceInContentSpace, + -TilePriority::kMaxDistanceInContentSpace, + -TilePriority::kMaxDistanceInContentSpace, + -TilePriority::kMaxDistanceInContentSpace); + inflated_rect.Intersect(ContentRect()); + + // 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_, + inflated_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->set_priority(tree, priority); + } + last_prioritized_rect_ = inflated_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_; + // Fast path tile priority calculation when both transforms are translations. if (last_screen_transform.IsIdentityOrTranslation() && current_screen_transform.IsIdentityOrTranslation()) { @@ -315,60 +346,72 @@ void PictureLayerTiling::UpdateTilePriorities( last_screen_transform.matrix().get(0, 3), last_screen_transform.matrix().get(1, 3)); - for (TileMap::const_iterator it = tiles_.begin(); - it != tiles_.end(); ++it) { - TileMapKey key = it->first; - TilePriority priority; - priority.resolution = resolution_; + for (TilingData::Iterator iter(&tiling_data_, inflated_rect); + iter; ++iter) { + TileMap::iterator find = tiles_.find(iter.index()); + if (find == tiles_.end()) + continue; + Tile* tile = find->second.get(); - gfx::Rect tile_bound = tiling_data_.TileBounds(key.first, key.second); + gfx::Rect tile_bounds = + tiling_data_.TileBounds(iter.index_x(), iter.index_y()); gfx::RectF current_screen_rect = gfx::ScaleRect( - tile_bound, + tile_bounds, current_scale, current_scale) + current_offset; gfx::RectF last_screen_rect = gfx::ScaleRect( - tile_bound, + tile_bounds, last_scale, last_scale) + last_offset; - priority.time_to_visible_in_seconds = + float time_to_visible_in_seconds = TilePriority::TimeForBoundsToIntersect( last_screen_rect, current_screen_rect, time_delta, view_rect); - - priority.distance_to_visible_in_pixels = + float distance_to_visible_in_pixels = TilePriority::manhattanDistance(current_screen_rect, view_rect); - it->second->set_priority(tree, priority); + + TilePriority priority( + resolution_, + time_to_visible_in_seconds, + distance_to_visible_in_pixels); + tile->set_priority(tree, priority); } } else { - for (TileMap::const_iterator it = tiles_.begin(); - it != tiles_.end(); ++it) { - TileMapKey key = it->first; - TilePriority priority; - priority.resolution = resolution_; + for (TilingData::Iterator iter(&tiling_data_, inflated_rect); + iter; ++iter) { + TileMap::iterator find = tiles_.find(iter.index()); + if (find == tiles_.end()) + continue; + Tile* tile = find->second.get(); - gfx::Rect tile_bound = tiling_data_.TileBounds(key.first, key.second); + gfx::Rect tile_bounds = + tiling_data_.TileBounds(iter.index_x(), iter.index_y()); gfx::RectF current_layer_content_rect = gfx::ScaleRect( - tile_bound, + tile_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_bound, + tile_bounds, last_scale, last_scale); gfx::RectF last_screen_rect = MathUtil::mapClippedRect( last_screen_transform, last_layer_content_rect); - priority.time_to_visible_in_seconds = + float time_to_visible_in_seconds = TilePriority::TimeForBoundsToIntersect( last_screen_rect, current_screen_rect, time_delta, view_rect); - - priority.distance_to_visible_in_pixels = + float distance_to_visible_in_pixels = TilePriority::manhattanDistance(current_screen_rect, view_rect); - it->second->set_priority(tree, priority); + + TilePriority priority( + resolution_, + time_to_visible_in_seconds, + distance_to_visible_in_pixels); + tile->set_priority(tree, priority); } } } diff --git a/cc/picture_layer_tiling.h b/cc/picture_layer_tiling.h index 0c48eb6..c0409c3 100644 --- a/cc/picture_layer_tiling.h +++ b/cc/picture_layer_tiling.h @@ -112,6 +112,7 @@ class CC_EXPORT PictureLayerTiling { void UpdateTilePriorities( WhichTree tree, const gfx::Size& device_viewport, + const gfx::RectF viewport_in_layer_space, float last_contents_scale, float current_contents_scale, const gfx::Transform& last_screen_transform, @@ -135,6 +136,7 @@ class CC_EXPORT PictureLayerTiling { PictureLayerTilingClient* client_; 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_; diff --git a/cc/picture_layer_tiling_set.cc b/cc/picture_layer_tiling_set.cc index 9dffe08..fe5b95e 100644 --- a/cc/picture_layer_tiling_set.cc +++ b/cc/picture_layer_tiling_set.cc @@ -258,15 +258,22 @@ PictureLayerTilingSet::Iterator::operator bool() const { void PictureLayerTilingSet::UpdateTilePriorities( WhichTree tree, const gfx::Size& device_viewport, + const gfx::Rect viewport_in_content_space, float layer_content_scale_x, float layer_content_scale_y, const gfx::Transform& last_screen_transform, const gfx::Transform& current_screen_transform, double time_delta) { + gfx::RectF viewport_in_layer_space = gfx::ScaleRect( + viewport_in_content_space, + 1.f / layer_content_scale_x, + 1.f / layer_content_scale_y); + for (size_t i = 0; i < tilings_.size(); ++i) { tilings_[i]->UpdateTilePriorities( tree, device_viewport, + viewport_in_layer_space, layer_content_scale_x, layer_content_scale_y, last_screen_transform, diff --git a/cc/picture_layer_tiling_set.h b/cc/picture_layer_tiling_set.h index fc272c1..d6a8950 100644 --- a/cc/picture_layer_tiling_set.h +++ b/cc/picture_layer_tiling_set.h @@ -52,6 +52,7 @@ class CC_EXPORT PictureLayerTilingSet { void UpdateTilePriorities( WhichTree tree, const gfx::Size& device_viewport, + gfx::Rect viewport_in_content_space, float layer_content_scale_x, float layer_content_scale_y, const gfx::Transform& last_screen_transform, diff --git a/cc/tile_manager.cc b/cc/tile_manager.cc index de7bf0d..6535125 100644 --- a/cc/tile_manager.cc +++ b/cc/tile_manager.cc @@ -35,22 +35,17 @@ const int kMaxPendingUploadBytes = 100 * 1024 * 1024; // Determine bin based on three categories of tiles: things we need now, // things we need soon, and eventually. TileManagerBin BinFromTilePriority(const TilePriority& prio) { + if (!prio.is_live) + return NEVER_BIN; // The amount of time for which we want to have prepainting coverage. const double prepainting_window_time_seconds = 1.0; const double backfling_guard_distance_pixels = 314.0; - // Explicitly limit how far ahead we will prepaint for low and non-low res. - const double max_lores_paint_distance_pixels = 8192.0; - const double max_hires_paint_distance_pixels = 4096.0; - if (prio.resolution == cc::LOW_RESOLUTION) { - if (prio.distance_to_visible_in_pixels > max_lores_paint_distance_pixels) - return cc::NEVER_BIN; - } - else { - if (prio.distance_to_visible_in_pixels > max_hires_paint_distance_pixels) - return cc::NEVER_BIN; - } + // Explicitly limit how far ahead we will prepaint to limit memory usage. + if (prio.distance_to_visible_in_pixels > + TilePriority::kMaxDistanceInContentSpace) + return NEVER_BIN; if (prio.time_to_visible_in_seconds == std::numeric_limits<float>::max()) return NEVER_BIN; diff --git a/cc/tile_priority.cc b/cc/tile_priority.cc index 5fcf4f2..ec77029 100644 --- a/cc/tile_priority.cc +++ b/cc/tile_priority.cc @@ -53,7 +53,8 @@ Range TimeRangeValueLargerThanThreshold( namespace cc { -const double TilePriority::kMaxTimeToVisibleInSeconds = 1000; +const double TilePriority::kMaxTimeToVisibleInSeconds = 1000.0; +const double TilePriority::kMaxDistanceInContentSpace = 4096.0; scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree) { switch (tree) { diff --git a/cc/tile_priority.h b/cc/tile_priority.h index 1895e8d..7672a38 100644 --- a/cc/tile_priority.h +++ b/cc/tile_priority.h @@ -33,16 +33,45 @@ scoped_ptr<base::Value> WhichTreeAsValue( enum TileResolution { LOW_RESOLUTION = 0 , HIGH_RESOLUTION = 1, - NON_IDEAL_RESOLUTION = 2 + NON_IDEAL_RESOLUTION = 2, }; struct CC_EXPORT TilePriority { TilePriority() - : resolution(NON_IDEAL_RESOLUTION), + : is_live(false), + resolution(NON_IDEAL_RESOLUTION), time_to_visible_in_seconds(std::numeric_limits<float>::max()), distance_to_visible_in_pixels(std::numeric_limits<float>::max()) {} + TilePriority( + TileResolution resolution, + float time_to_visible_in_seconds, + float distance_to_visible_in_pixels) + : is_live(true), + resolution(resolution), + time_to_visible_in_seconds(time_to_visible_in_seconds), + distance_to_visible_in_pixels(distance_to_visible_in_pixels) {} + TilePriority(const TilePriority& active, const TilePriority& pending) { + if (!pending.is_live) { + if (!active.is_live) { + is_live = false; + return; + } + is_live = true; + resolution = active.resolution; + time_to_visible_in_seconds = active.time_to_visible_in_seconds; + distance_to_visible_in_pixels = active.distance_to_visible_in_pixels; + return; + } else if (!active.is_live) { + is_live = true; + resolution = pending.resolution; + time_to_visible_in_seconds = pending.time_to_visible_in_seconds; + distance_to_visible_in_pixels = pending.distance_to_visible_in_pixels; + return; + } + + is_live = true; if (active.resolution == HIGH_RESOLUTION || pending.resolution == HIGH_RESOLUTION) resolution = HIGH_RESOLUTION; @@ -61,6 +90,7 @@ struct CC_EXPORT TilePriority { } static const double kMaxTimeToVisibleInSeconds; + static const double kMaxDistanceInContentSpace; static int manhattanDistance(const gfx::RectF& a, const gfx::RectF& b); @@ -72,6 +102,8 @@ struct CC_EXPORT TilePriority { double time_delta, gfx::RectF target_bounds); + // If a tile is not live, then all other fields are invalid. + bool is_live; TileResolution resolution; float time_to_visible_in_seconds; float distance_to_visible_in_pixels; |