Index: cc/resources/picture_layer_tiling.cc |
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc |
index cfab6f25c852b97040c36488cceffa89abc790c1..939e0b163d4a459aa50d0437a9aec5b94c2f8230 100644 |
--- a/cc/resources/picture_layer_tiling.cc |
+++ b/cc/resources/picture_layer_tiling.cc |
@@ -339,223 +339,154 @@ void PictureLayerTiling::Reset() { |
tiles_.clear(); |
} |
+gfx::Rect PictureLayerTiling::ComputeSkewport( |
+ double current_frame_time_in_seconds, |
+ const gfx::Rect& visible_rect_in_content_space) const { |
+ gfx::Rect skewport = visible_rect_in_content_space; |
+ if (last_impl_frame_time_in_seconds_ == 0.0) |
+ return skewport; |
+ |
+ double time_delta = |
+ current_frame_time_in_seconds - last_impl_frame_time_in_seconds_; |
+ if (time_delta == 0.0) |
+ return skewport; |
+ |
+ float skewport_target_time_in_seconds = |
+ client_->GetSkewportTargetTimeInSeconds(); |
+ double extrapolation_multiplier = |
+ skewport_target_time_in_seconds / time_delta; |
+ |
+ int old_x = last_visible_rect_in_content_space_.x(); |
+ int old_y = last_visible_rect_in_content_space_.y(); |
+ int old_right = last_visible_rect_in_content_space_.right(); |
+ int old_bottom = last_visible_rect_in_content_space_.bottom(); |
+ |
+ int new_x = visible_rect_in_content_space.x(); |
+ int new_y = visible_rect_in_content_space.y(); |
+ int new_right = visible_rect_in_content_space.right(); |
+ int new_bottom = visible_rect_in_content_space.bottom(); |
+ |
+ int skewport_limit = client_->GetSkewportExtrapolationLimitInContentPixels(); |
+ |
+ // Compute the maximum skewport based on |skewport_limit|. |
+ gfx::Rect max_skewport = skewport; |
+ max_skewport.Inset( |
+ -skewport_limit, -skewport_limit, -skewport_limit, -skewport_limit); |
+ |
+ // Inset the skewport by the needed adjustment. |
+ skewport.Inset(extrapolation_multiplier * (new_x - old_x), |
+ extrapolation_multiplier * (new_y - old_y), |
+ extrapolation_multiplier * (old_right - new_right), |
+ extrapolation_multiplier * (old_bottom - new_bottom)); |
+ |
+ // Clip the skewport to |max_skewport|. |
+ skewport.Intersect(max_skewport); |
+ |
+ // Finally, ensure that visible rect is contained in the skewport. |
+ skewport.Union(visible_rect_in_content_space); |
+ return skewport; |
+} |
+ |
void PictureLayerTiling::UpdateTilePriorities( |
WhichTree tree, |
- const gfx::Size& device_viewport, |
- const gfx::Rect& viewport_in_layer_space, |
const gfx::Rect& visible_layer_rect, |
- const gfx::Size& last_layer_bounds, |
- const gfx::Size& current_layer_bounds, |
- float last_layer_contents_scale, |
- float current_layer_contents_scale, |
- const gfx::Transform& last_screen_transform, |
- const gfx::Transform& current_screen_transform, |
- double current_frame_time_in_seconds, |
- size_t max_tiles_for_interest_area) { |
+ float layer_contents_scale, |
+ double current_frame_time_in_seconds) { |
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); |
return; |
} |
+ |
+ gfx::Rect visible_rect_in_content_space = |
+ gfx::ScaleToEnclosingRect(visible_layer_rect, contents_scale_); |
+ |
if (ContentRect().IsEmpty()) { |
last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; |
+ last_visible_rect_in_content_space_ = visible_rect_in_content_space; |
return; |
} |
- gfx::Rect viewport_in_content_space = |
- gfx::ScaleToEnclosingRect(viewport_in_layer_space, contents_scale_); |
- gfx::Rect visible_content_rect = |
- gfx::ScaleToEnclosingRect(visible_layer_rect, contents_scale_); |
+ size_t max_tiles_for_interest_area = client_->GetMaxTilesForInterestArea(); |
gfx::Size tile_size = tiling_data_.max_texture_size(); |
- int64 interest_rect_area = |
+ int64 eventually_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(), |
- &expansion_cache_); |
- DCHECK(interest_rect.IsEmpty() || |
- ContentRect().Contains(interest_rect)); |
- |
- SetLiveTilesRect(interest_rect); |
- |
- double time_delta = 0; |
- if (last_impl_frame_time_in_seconds_ != 0.0 && |
- last_layer_bounds == current_layer_bounds) { |
- time_delta = |
- current_frame_time_in_seconds - last_impl_frame_time_in_seconds_; |
+ gfx::Rect skewport = ComputeSkewport(current_frame_time_in_seconds, |
+ visible_rect_in_content_space); |
+ DCHECK(skewport.Contains(visible_rect_in_content_space)); |
+ |
+ gfx::Rect eventually_rect = |
+ ExpandRectEquallyToAreaBoundedBy(visible_rect_in_content_space, |
+ eventually_rect_area, |
+ ContentRect(), |
+ &expansion_cache_); |
+ |
+ DCHECK(eventually_rect.IsEmpty() || ContentRect().Contains(eventually_rect)); |
+ |
+ SetLiveTilesRect(eventually_rect); |
+ |
+ last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; |
+ last_visible_rect_in_content_space_ = visible_rect_in_content_space; |
+ |
+ // Assign now priority to all visible tiles. |
+ TilePriority now_priority(resolution_, TilePriority::NOW, 0); |
+ for (TilingData::Iterator iter(&tiling_data_, visible_rect_in_content_space); |
+ iter; |
+ ++iter) { |
+ TileMap::iterator find = tiles_.find(iter.index()); |
+ if (find == tiles_.end()) |
+ continue; |
+ Tile* tile = find->second.get(); |
+ |
+ tile->SetPriority(tree, now_priority); |
} |
- gfx::RectF 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.IsApproximatelyIdentityOrTranslation( |
- std::numeric_limits<float>::epsilon()) && |
- current_screen_transform.IsApproximatelyIdentityOrTranslation( |
- std::numeric_limits<float>::epsilon())) { |
- gfx::Vector2dF current_offset( |
- current_screen_transform.matrix().get(0, 3), |
- current_screen_transform.matrix().get(1, 3)); |
- gfx::Vector2dF last_offset( |
- last_screen_transform.matrix().get(0, 3), |
- last_screen_transform.matrix().get(1, 3)); |
- |
- for (TilingData::Iterator iter(&tiling_data_, interest_rect); |
- iter; ++iter) { |
- TileMap::iterator find = tiles_.find(iter.index()); |
- if (find == tiles_.end()) |
- 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; |
- |
- float distance_to_visible_in_pixels = |
- current_screen_rect.ManhattanInternalDistance(view_rect); |
- |
- float time_to_visible_in_seconds = |
- TilePriority::TimeForBoundsToIntersect( |
- last_screen_rect, current_screen_rect, time_delta, view_rect); |
- TilePriority priority( |
- resolution_, |
- time_to_visible_in_seconds, |
- distance_to_visible_in_pixels); |
- tile->SetPriority(tree, priority); |
- } |
- } else if (!last_screen_transform.HasPerspective() && |
- !current_screen_transform.HasPerspective()) { |
- // Secondary fast path that can be applied for any affine transforms. |
- |
- // Initialize the necessary geometry in screen space, so that we can |
- // iterate over tiles in screen space without needing a costly transform |
- // mapping for each tile. |
- |
- // Apply screen space transform to the local origin point (0, 0); only the |
- // translation component is needed and can be initialized directly. |
- gfx::Point current_screen_space_origin( |
- current_screen_transform.matrix().get(0, 3), |
- current_screen_transform.matrix().get(1, 3)); |
- |
- gfx::Point last_screen_space_origin( |
- 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; |
- |
- // 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); |
- gfx::Vector2dF current_vertical( |
- current_screen_transform.matrix().get(0, 1) * current_tile_height, |
- current_screen_transform.matrix().get(1, 1) * current_tile_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); |
- gfx::Vector2dF last_vertical( |
- last_screen_transform.matrix().get(0, 1) * last_tile_height, |
- last_screen_transform.matrix().get(1, 1) * last_tile_height); |
- |
- for (TilingData::Iterator iter(&tiling_data_, interest_rect); |
- iter; ++iter) { |
- TileMap::iterator find = tiles_.find(iter.index()); |
- if (find == tiles_.end()) |
- continue; |
+ // Assign soon priority to all tiles in the skewport that are not visible. |
+ float content_to_screen_scale = |
+ 1.0f / (contents_scale_ * layer_contents_scale); |
+ for (TilingData::DifferenceIterator iter( |
+ &tiling_data_, skewport, visible_rect_in_content_space); |
+ iter; |
+ ++iter) { |
+ TileMap::iterator find = tiles_.find(iter.index()); |
+ if (find == tiles_.end()) |
+ continue; |
+ Tile* tile = find->second.get(); |
- 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::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(); |
- |
- 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(); |
- |
- float distance_to_visible_in_pixels = |
- current_screen_rect.ManhattanInternalDistance(view_rect); |
- |
- float time_to_visible_in_seconds = |
- TilePriority::TimeForBoundsToIntersect( |
- last_screen_rect, current_screen_rect, time_delta, view_rect); |
- TilePriority priority( |
- resolution_, |
- time_to_visible_in_seconds, |
- distance_to_visible_in_pixels); |
- tile->SetPriority(tree, priority); |
- } |
- } else { |
- for (TilingData::Iterator iter(&tiling_data_, interest_rect); |
- iter; ++iter) { |
- TileMap::iterator find = tiles_.find(iter.index()); |
- if (find == tiles_.end()) |
- continue; |
- Tile* tile = find->second.get(); |
- |
- gfx::Rect tile_bounds = |
- tiling_data_.TileBounds(iter.index_x(), iter.index_y()); |
- gfx::RectF current_layer_content_rect = gfx::ScaleRect( |
- 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_bounds, |
- last_scale, |
- last_scale); |
- gfx::RectF last_screen_rect = MathUtil::MapClippedRect( |
- last_screen_transform, last_layer_content_rect); |
- |
- float distance_to_visible_in_pixels = |
- current_screen_rect.ManhattanInternalDistance(view_rect); |
- |
- float time_to_visible_in_seconds = |
- TilePriority::TimeForBoundsToIntersect( |
- last_screen_rect, current_screen_rect, time_delta, view_rect); |
- |
- TilePriority priority( |
- resolution_, |
- time_to_visible_in_seconds, |
- distance_to_visible_in_pixels); |
- tile->SetPriority(tree, priority); |
- } |
+ gfx::Rect tile_bounds = |
+ tiling_data_.TileBounds(iter.index_x(), iter.index_y()); |
+ |
+ float distance_to_visible = |
+ visible_rect_in_content_space.ManhattanInternalDistance(tile_bounds) * |
+ content_to_screen_scale; |
+ |
+ TilePriority priority(resolution_, TilePriority::SOON, distance_to_visible); |
+ tile->SetPriority(tree, priority); |
} |
- last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; |
+ // Assign eventually priority to all tiles in the eventually rect that are not |
+ // in the skewport. |
+ for (TilingData::DifferenceIterator iter( |
+ &tiling_data_, eventually_rect, skewport); |
+ iter; |
+ ++iter) { |
+ TileMap::iterator find = tiles_.find(iter.index()); |
+ if (find == tiles_.end()) |
+ continue; |
+ Tile* tile = find->second.get(); |
+ |
+ gfx::Rect tile_bounds = |
+ tiling_data_.TileBounds(iter.index_x(), iter.index_y()); |
+ |
+ float distance_to_visible = |
+ visible_rect_in_content_space.ManhattanInternalDistance(tile_bounds) * |
+ content_to_screen_scale; |
+ TilePriority priority( |
+ resolution_, TilePriority::EVENTUALLY, distance_to_visible); |
+ tile->SetPriority(tree, priority); |
+ } |
} |
void PictureLayerTiling::SetLiveTilesRect( |