| Index: cc/tiles/picture_layer_tiling_set.cc
|
| diff --git a/cc/tiles/picture_layer_tiling_set.cc b/cc/tiles/picture_layer_tiling_set.cc
|
| index 865ff0976d459f21a5bf049531f430829eb064e9..f4c26a0668c524ad906ac92378a3d4a7bf2b8e15 100644
|
| --- a/cc/tiles/picture_layer_tiling_set.cc
|
| +++ b/cc/tiles/picture_layer_tiling_set.cc
|
| @@ -12,6 +12,7 @@
|
|
|
| #include "base/memory/ptr_util.h"
|
| #include "cc/playback/raster_source.h"
|
| +#include "ui/gfx/geometry/rect_conversions.h"
|
|
|
| namespace cc {
|
|
|
| @@ -31,31 +32,34 @@ inline float LargerRatio(float float1, float float2) {
|
| return float1 > float2 ? float1 / float2 : float2 / float1;
|
| }
|
|
|
| +const float kSoonBorderDistanceViewportPercentage = 0.15f;
|
| +const float kMaxSoonBorderDistanceInScreenPixels = 312.f;
|
| +
|
| } // namespace
|
|
|
| // static
|
| std::unique_ptr<PictureLayerTilingSet> PictureLayerTilingSet::Create(
|
| WhichTree tree,
|
| PictureLayerTilingClient* client,
|
| - size_t tiling_interest_area_padding,
|
| + int tiling_interest_area_padding,
|
| float skewport_target_time_in_seconds,
|
| - int skewport_extrapolation_limit_in_content_pixels) {
|
| - return base::WrapUnique(new PictureLayerTilingSet(
|
| - tree, client, tiling_interest_area_padding,
|
| - skewport_target_time_in_seconds,
|
| - skewport_extrapolation_limit_in_content_pixels));
|
| + int skewport_extrapolation_limit_in_screen_pixels) {
|
| + return base::WrapUnique(
|
| + new PictureLayerTilingSet(tree, client, tiling_interest_area_padding,
|
| + skewport_target_time_in_seconds,
|
| + skewport_extrapolation_limit_in_screen_pixels));
|
| }
|
|
|
| PictureLayerTilingSet::PictureLayerTilingSet(
|
| WhichTree tree,
|
| PictureLayerTilingClient* client,
|
| - size_t tiling_interest_area_padding,
|
| + int tiling_interest_area_padding,
|
| float skewport_target_time_in_seconds,
|
| - int skewport_extrapolation_limit_in_content_pixels)
|
| + int skewport_extrapolation_limit_in_screen_pixels)
|
| : tiling_interest_area_padding_(tiling_interest_area_padding),
|
| skewport_target_time_in_seconds_(skewport_target_time_in_seconds),
|
| - skewport_extrapolation_limit_in_content_pixels_(
|
| - skewport_extrapolation_limit_in_content_pixels),
|
| + skewport_extrapolation_limit_in_screen_pixels_(
|
| + skewport_extrapolation_limit_in_screen_pixels),
|
| tree_(tree),
|
| client_(client) {}
|
|
|
| @@ -79,14 +83,12 @@ void PictureLayerTilingSet::CopyTilingsAndPropertiesFromPendingTwin(
|
| float contents_scale = pending_twin_tiling->contents_scale();
|
| PictureLayerTiling* this_tiling = FindTilingWithScale(contents_scale);
|
| if (!this_tiling) {
|
| - std::unique_ptr<PictureLayerTiling> new_tiling =
|
| - PictureLayerTiling::Create(
|
| - tree_, contents_scale, raster_source, client_,
|
| - tiling_interest_area_padding_, skewport_target_time_in_seconds_,
|
| - skewport_extrapolation_limit_in_content_pixels_);
|
| + std::unique_ptr<PictureLayerTiling> new_tiling(new PictureLayerTiling(
|
| + tree_, contents_scale, raster_source_, client_));
|
| tilings_.push_back(std::move(new_tiling));
|
| this_tiling = tilings_.back().get();
|
| tiling_sort_required = true;
|
| + state_since_last_tile_priority_update_.added_tilings = true;
|
| }
|
| this_tiling->TakeTilesAndPropertiesFrom(pending_twin_tiling.get(),
|
| layer_invalidation);
|
| @@ -107,6 +109,8 @@ void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForActivation(
|
| RemoveTilingsBelowScale(minimum_contents_scale);
|
| RemoveTilingsAboveScale(maximum_contents_scale);
|
|
|
| + raster_source_ = raster_source;
|
| +
|
| // Copy over tilings that are shared with the |pending_twin_set| tiling set.
|
| // Also, copy all of the properties from twin tilings.
|
| CopyTilingsAndPropertiesFromPendingTwin(pending_twin_set, raster_source,
|
| @@ -120,6 +124,7 @@ void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForActivation(
|
|
|
| tiling->SetRasterSourceAndResize(raster_source);
|
| tiling->Invalidate(layer_invalidation);
|
| + state_since_last_tile_priority_update_.invalidated = true;
|
| // This is needed for cases where the live tiles rect didn't change but
|
| // recordings exist in the raster source that did not exist on the last
|
| // raster source.
|
| @@ -145,6 +150,8 @@ void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForCommit(
|
| RemoveTilingsBelowScale(minimum_contents_scale);
|
| RemoveTilingsAboveScale(maximum_contents_scale);
|
|
|
| + raster_source_ = raster_source;
|
| +
|
| // Invalidate tiles and update them to the new raster source.
|
| for (const std::unique_ptr<PictureLayerTiling>& tiling : tilings_) {
|
| DCHECK(tree_ != PENDING_TREE || !tiling->has_tiles());
|
| @@ -152,8 +159,10 @@ void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForCommit(
|
|
|
| // We can commit on either active or pending trees, but only active one can
|
| // have tiles at this point.
|
| - if (tree_ == ACTIVE_TREE)
|
| + if (tree_ == ACTIVE_TREE) {
|
| tiling->Invalidate(layer_invalidation);
|
| + state_since_last_tile_priority_update_.invalidated = true;
|
| + }
|
|
|
| // This is needed for cases where the live tiles rect didn't change but
|
| // recordings exist in the raster source that did not exist on the last
|
| @@ -166,9 +175,11 @@ void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForCommit(
|
| void PictureLayerTilingSet::UpdateRasterSourceDueToLCDChange(
|
| scoped_refptr<RasterSource> raster_source,
|
| const Region& layer_invalidation) {
|
| + raster_source_ = raster_source;
|
| for (const auto& tiling : tilings_) {
|
| tiling->SetRasterSourceAndResize(raster_source);
|
| tiling->Invalidate(layer_invalidation);
|
| + state_since_last_tile_priority_update_.invalidated = true;
|
| // Since the invalidation changed, we need to create any missing tiles in
|
| // the live tiles rect again.
|
| tiling->CreateMissingTilesInLiveTilesRect();
|
| @@ -252,16 +263,18 @@ void PictureLayerTilingSet::MarkAllTilingsNonIdeal() {
|
| PictureLayerTiling* PictureLayerTilingSet::AddTiling(
|
| float contents_scale,
|
| scoped_refptr<RasterSource> raster_source) {
|
| + if (!raster_source_)
|
| + raster_source_ = raster_source;
|
| +
|
| for (size_t i = 0; i < tilings_.size(); ++i) {
|
| DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
|
| DCHECK_EQ(tilings_[i]->raster_source(), raster_source.get());
|
| }
|
|
|
| - tilings_.push_back(PictureLayerTiling::Create(
|
| - tree_, contents_scale, raster_source, client_,
|
| - tiling_interest_area_padding_, skewport_target_time_in_seconds_,
|
| - skewport_extrapolation_limit_in_content_pixels_));
|
| + tilings_.push_back(base::WrapUnique(
|
| + new PictureLayerTiling(tree_, contents_scale, raster_source, client_)));
|
| PictureLayerTiling* appended = tilings_.back().get();
|
| + state_since_last_tile_priority_update_.added_tilings = true;
|
|
|
| std::sort(tilings_.begin(), tilings_.end(), LargestToSmallestScaleFunctor());
|
| return appended;
|
| @@ -357,21 +370,165 @@ float PictureLayerTilingSet::GetMaximumContentsScale() const {
|
| return tilings_[0]->contents_scale();
|
| }
|
|
|
| +bool PictureLayerTilingSet::TilingsNeedUpdate(
|
| + const gfx::Rect& visible_rect_in_layer_space,
|
| + double current_frame_time_in_seconds) {
|
| + // If we don't have any tilings, we don't need an update.
|
| + if (num_tilings() == 0)
|
| + return false;
|
| +
|
| + // If we never updated the tiling set, then our history is empty. We should
|
| + // update tilings.
|
| + if (visible_rect_history_.empty())
|
| + return true;
|
| +
|
| + // If we've added new tilings since the last update, then we have to update at
|
| + // least that one tiling.
|
| + if (state_since_last_tile_priority_update_.added_tilings)
|
| + return true;
|
| +
|
| + // Finally, if some state changed (either frame time or visible rect), then we
|
| + // need to inform the tilings of the change.
|
| + const auto& last_frame = visible_rect_history_.front();
|
| + if (current_frame_time_in_seconds != last_frame.frame_time_in_seconds)
|
| + return true;
|
| +
|
| + if (visible_rect_in_layer_space != last_frame.visible_rect_in_layer_space)
|
| + return true;
|
| + return false;
|
| +}
|
| +
|
| +gfx::Rect PictureLayerTilingSet::ComputeSkewport(
|
| + const gfx::Rect& visible_rect_in_layer_space,
|
| + double current_frame_time_in_seconds,
|
| + float ideal_contents_scale) {
|
| + gfx::Rect skewport = visible_rect_in_layer_space;
|
| + if (skewport.IsEmpty() || visible_rect_history_.empty())
|
| + return skewport;
|
| +
|
| + // Use the oldest recorded history to get a stable skewport.
|
| + const auto& historical_frame = visible_rect_history_.back();
|
| + double time_delta =
|
| + current_frame_time_in_seconds - historical_frame.frame_time_in_seconds;
|
| + if (time_delta == 0.)
|
| + return skewport;
|
| +
|
| + double extrapolation_multiplier =
|
| + skewport_target_time_in_seconds_ / time_delta;
|
| + int old_x = historical_frame.visible_rect_in_layer_space.x();
|
| + int old_y = historical_frame.visible_rect_in_layer_space.y();
|
| + int old_right = historical_frame.visible_rect_in_layer_space.right();
|
| + int old_bottom = historical_frame.visible_rect_in_layer_space.bottom();
|
| +
|
| + int new_x = visible_rect_in_layer_space.x();
|
| + int new_y = visible_rect_in_layer_space.y();
|
| + int new_right = visible_rect_in_layer_space.right();
|
| + int new_bottom = visible_rect_in_layer_space.bottom();
|
| +
|
| + int inset_x = (new_x - old_x) * extrapolation_multiplier;
|
| + int inset_y = (new_y - old_y) * extrapolation_multiplier;
|
| + int inset_right = (old_right - new_right) * extrapolation_multiplier;
|
| + int inset_bottom = (old_bottom - new_bottom) * extrapolation_multiplier;
|
| +
|
| + int skewport_extrapolation_limit_in_layer_pixels =
|
| + skewport_extrapolation_limit_in_screen_pixels_ / ideal_contents_scale;
|
| + gfx::Rect max_skewport = skewport;
|
| + max_skewport.Inset(-skewport_extrapolation_limit_in_layer_pixels,
|
| + -skewport_extrapolation_limit_in_layer_pixels);
|
| +
|
| + skewport.Inset(inset_x, inset_y, inset_right, inset_bottom);
|
| + skewport.Union(visible_rect_in_layer_space);
|
| + skewport.Intersect(max_skewport);
|
| +
|
| + // Due to limits in int's representation, it is possible that the two
|
| + // operations above (union and intersect) result in an empty skewport. To
|
| + // avoid any unpleasant situations like that, union the visible rect again to
|
| + // ensure that skewport.Contains(visible_rect_in_layer_space) is always
|
| + // true.
|
| + skewport.Union(visible_rect_in_layer_space);
|
| + return skewport;
|
| +}
|
| +
|
| +gfx::Rect PictureLayerTilingSet::ComputeSoonBorderRect(
|
| + const gfx::Rect& visible_rect,
|
| + float ideal_contents_scale) {
|
| + int max_dimension = std::max(visible_rect.width(), visible_rect.height());
|
| + int distance =
|
| + std::min<int>(kMaxSoonBorderDistanceInScreenPixels * ideal_contents_scale,
|
| + max_dimension * kSoonBorderDistanceViewportPercentage);
|
| +
|
| + gfx::Rect soon_border_rect = visible_rect;
|
| + soon_border_rect.Inset(-distance, -distance);
|
| + return soon_border_rect;
|
| +}
|
| +
|
| +void PictureLayerTilingSet::UpdatePriorityRects(
|
| + const gfx::Rect& visible_rect_in_layer_space,
|
| + double current_frame_time_in_seconds,
|
| + float ideal_contents_scale) {
|
| + visible_rect_in_layer_space_ = gfx::Rect();
|
| + eventually_rect_in_layer_space_ = gfx::Rect();
|
| +
|
| + // We keep things as floats in here.
|
| + if (!visible_rect_in_layer_space.IsEmpty()) {
|
| + gfx::RectF eventually_rectf(visible_rect_in_layer_space);
|
| + eventually_rectf.Inset(-tiling_interest_area_padding_,
|
| + -tiling_interest_area_padding_);
|
| + if (eventually_rectf.Intersects(
|
| + gfx::RectF(gfx::SizeF(raster_source_->GetSize())))) {
|
| + visible_rect_in_layer_space_ = visible_rect_in_layer_space;
|
| + eventually_rect_in_layer_space_ = gfx::ToEnclosingRect(eventually_rectf);
|
| + }
|
| + }
|
| +
|
| + skewport_in_layer_space_ =
|
| + ComputeSkewport(visible_rect_in_layer_space_,
|
| + current_frame_time_in_seconds, ideal_contents_scale);
|
| + DCHECK(skewport_in_layer_space_.Contains(visible_rect_in_layer_space_));
|
| + DCHECK(eventually_rect_in_layer_space_.Contains(skewport_in_layer_space_));
|
| +
|
| + soon_border_rect_in_layer_space_ =
|
| + ComputeSoonBorderRect(visible_rect_in_layer_space_, ideal_contents_scale);
|
| + DCHECK(
|
| + soon_border_rect_in_layer_space_.Contains(visible_rect_in_layer_space_));
|
| + DCHECK(eventually_rect_in_layer_space_.Contains(
|
| + soon_border_rect_in_layer_space_));
|
| +
|
| + // Finally, update our visible rect history. Note that we use the original
|
| + // visible rect here, since we want as accurate of a history as possible for
|
| + // stable skewports.
|
| + visible_rect_history_.push_front(FrameVisibleRect(
|
| + visible_rect_in_layer_space_, current_frame_time_in_seconds));
|
| + if (visible_rect_history_.size() > 2)
|
| + visible_rect_history_.pop_back();
|
| +}
|
| +
|
| bool PictureLayerTilingSet::UpdateTilePriorities(
|
| - const gfx::Rect& required_rect_in_layer_space,
|
| + const gfx::Rect& visible_rect_in_layer_space,
|
| float ideal_contents_scale,
|
| double current_frame_time_in_seconds,
|
| const Occlusion& occlusion_in_layer_space,
|
| bool can_require_tiles_for_activation) {
|
| - bool updated = false;
|
| + StateSinceLastTilePriorityUpdate::AutoClear auto_clear_state(
|
| + &state_since_last_tile_priority_update_);
|
| +
|
| + if (!TilingsNeedUpdate(visible_rect_in_layer_space,
|
| + current_frame_time_in_seconds)) {
|
| + return state_since_last_tile_priority_update_.invalidated;
|
| + }
|
| +
|
| + UpdatePriorityRects(visible_rect_in_layer_space,
|
| + current_frame_time_in_seconds, ideal_contents_scale);
|
| +
|
| for (const auto& tiling : tilings_) {
|
| tiling->set_can_require_tiles_for_activation(
|
| can_require_tiles_for_activation);
|
| - updated |= tiling->ComputeTilePriorityRects(
|
| - required_rect_in_layer_space, ideal_contents_scale,
|
| - current_frame_time_in_seconds, occlusion_in_layer_space);
|
| + tiling->ComputeTilePriorityRects(
|
| + visible_rect_in_layer_space_, skewport_in_layer_space_,
|
| + soon_border_rect_in_layer_space_, eventually_rect_in_layer_space_,
|
| + ideal_contents_scale, occlusion_in_layer_space);
|
| }
|
| - return updated;
|
| + return true;
|
| }
|
|
|
| void PictureLayerTilingSet::GetAllPrioritizedTilesForTracing(
|
|
|