| Index: cc/layers/picture_layer_impl.cc
|
| diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
|
| index c294a330635797c82f7186c4768a87962738ba23..89c068b9fab4c4059a870df4ba7c3a8994a2d7bd 100644
|
| --- a/cc/layers/picture_layer_impl.cc
|
| +++ b/cc/layers/picture_layer_impl.cc
|
| @@ -75,7 +75,8 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
|
| raster_source_scale_is_fixed_(false),
|
| was_screen_space_transform_animating_(false),
|
| needs_post_commit_initialization_(true),
|
| - should_update_tile_priorities_(false) {
|
| + should_update_tile_priorities_(false),
|
| + only_used_low_res_last_append_quads_(false) {
|
| layer_tree_impl()->RegisterPictureLayerImpl(this);
|
| }
|
|
|
| @@ -98,15 +99,6 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
|
| DoPostCommitInitializationIfNeeded();
|
| PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
|
|
|
| - // We have already synced the important bits from the the active layer, and
|
| - // we will soon swap out its tilings and use them for recycling. However,
|
| - // there are now tiles in this layer's tilings that were unref'd and replaced
|
| - // with new tiles (due to invalidation). This resets all active priorities on
|
| - // the to-be-recycled tiling to ensure replaced tiles don't linger and take
|
| - // memory (due to a stale 'active' priority).
|
| - if (layer_impl->tilings_)
|
| - layer_impl->tilings_->DidBecomeRecycled();
|
| -
|
| LayerImpl::PushPropertiesTo(base_layer);
|
|
|
| // When the pending tree pushes to the active tree, the pending twin
|
| @@ -251,10 +243,10 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass,
|
| } else if (mode == ManagedTileState::DrawInfo::PICTURE_PILE_MODE) {
|
| color = DebugColors::PictureTileBorderColor();
|
| width = DebugColors::PictureTileBorderWidth(layer_tree_impl());
|
| - } else if (iter->priority(ACTIVE_TREE).resolution == HIGH_RESOLUTION) {
|
| + } else if (iter.resolution() == HIGH_RESOLUTION) {
|
| color = DebugColors::HighResTileBorderColor();
|
| width = DebugColors::HighResTileBorderWidth(layer_tree_impl());
|
| - } else if (iter->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION) {
|
| + } else if (iter.resolution() == LOW_RESOLUTION) {
|
| color = DebugColors::LowResTileBorderColor();
|
| width = DebugColors::LowResTileBorderWidth(layer_tree_impl());
|
| } else if (iter->contents_scale() > max_contents_scale) {
|
| @@ -293,6 +285,7 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass,
|
|
|
| size_t missing_tile_count = 0u;
|
| size_t on_demand_missing_tile_count = 0u;
|
| + only_used_low_res_last_append_quads_ = true;
|
| for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
|
| max_contents_scale,
|
| scaled_visible_content_rect,
|
| @@ -411,11 +404,16 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass,
|
| continue;
|
| }
|
|
|
| - if (iter->priority(ACTIVE_TREE).resolution != HIGH_RESOLUTION) {
|
| + if (iter.resolution() != HIGH_RESOLUTION) {
|
| append_quads_data->approximated_visible_content_area +=
|
| visible_geometry_rect.width() * visible_geometry_rect.height();
|
| }
|
|
|
| + // If we have a draw quad, but it's not low resolution, then
|
| + // mark that we've used something other than low res to draw.
|
| + if (iter.resolution() != LOW_RESOLUTION)
|
| + only_used_low_res_last_append_quads_ = false;
|
| +
|
| if (seen_tilings.empty() || seen_tilings.back() != iter.CurrentTiling())
|
| seen_tilings.push_back(iter.CurrentTiling());
|
| }
|
| @@ -479,9 +477,6 @@ void PictureLayerImpl::UpdateTiles(const Occlusion& occlusion_in_content_space,
|
| should_update_tile_priorities_ = true;
|
|
|
| UpdateTilePriorities(occlusion_in_content_space);
|
| -
|
| - if (layer_tree_impl()->IsPendingTree())
|
| - MarkVisibleResourcesAsRequired();
|
| }
|
|
|
| void PictureLayerImpl::UpdateTilePriorities(
|
| @@ -509,17 +504,26 @@ void PictureLayerImpl::UpdateTilePriorities(
|
| GetViewportForTilePriorityInContentSpace();
|
| WhichTree tree =
|
| layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
|
| + bool can_require_tiles_for_activation =
|
| + !only_used_low_res_last_append_quads_ || RequiresHighResToDraw() ||
|
| + !layer_tree_impl()->SmoothnessTakesPriority();
|
| for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
|
| + PictureLayerTiling* tiling = tilings_->tiling_at(i);
|
| +
|
| + tiling->set_can_require_tiles_for_activation(
|
| + can_require_tiles_for_activation);
|
| +
|
| // Pass |occlusion_in_content_space| for |occlusion_in_layer_space| since
|
| - // they are the same space in picture lbayer, as contents scale is always 1.
|
| - tilings_->tiling_at(i)->UpdateTilePriorities(tree,
|
| - viewport_rect_in_layer_space,
|
| - ideal_contents_scale_,
|
| - current_frame_time_in_seconds,
|
| - occlusion_in_content_space);
|
| + // they are the same space in picture layer, as contents scale is always 1.
|
| + tiling->ComputeTilePriorityRects(tree,
|
| + viewport_rect_in_layer_space,
|
| + ideal_contents_scale_,
|
| + current_frame_time_in_seconds,
|
| + occlusion_in_content_space);
|
| }
|
|
|
| // Tile priorities were modified.
|
| + // TODO(vmpstr): See if this can be removed in favour of calling it from LTHI
|
| layer_tree_impl()->DidModifyTilePriorities();
|
| }
|
|
|
| @@ -561,7 +565,7 @@ void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
|
|
|
| void PictureLayerImpl::DidBecomeActive() {
|
| LayerImpl::DidBecomeActive();
|
| - tilings_->DidBecomeActive();
|
| + // TODO(vmpstr): See if this can be removed in favour of calling it from LTHI
|
| layer_tree_impl()->DidModifyTilePriorities();
|
| }
|
|
|
| @@ -655,6 +659,10 @@ int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const {
|
| .skewport_extrapolation_limit_in_content_pixels;
|
| }
|
|
|
| +bool PictureLayerImpl::RequiresHighResToDraw() const {
|
| + return layer_tree_impl()->RequiresHighResToDraw();
|
| +}
|
| +
|
| gfx::Size PictureLayerImpl::CalculateTileSize(
|
| const gfx::Size& content_bounds) const {
|
| int max_texture_size =
|
| @@ -792,159 +800,6 @@ ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const {
|
| return draw_info.get_resource_id();
|
| }
|
|
|
| -void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
|
| - DCHECK(layer_tree_impl()->IsPendingTree());
|
| - DCHECK(ideal_contents_scale_);
|
| - DCHECK_GT(tilings_->num_tilings(), 0u);
|
| -
|
| - // The goal of this function is to find the minimum set of tiles that need to
|
| - // be ready to draw in order to activate without flashing content from a
|
| - // higher res on the active tree to a lower res on the pending tree.
|
| -
|
| - // First, early out for layers with no visible content.
|
| - if (visible_rect_for_tile_priority_.IsEmpty())
|
| - return;
|
| -
|
| - // Only mark tiles inside the viewport for tile priority as required for
|
| - // activation. This viewport is normally the same as the draw viewport but
|
| - // can be independently overridden by embedders like Android WebView with
|
| - // SetExternalDrawConstraints.
|
| - gfx::Rect rect = GetViewportForTilePriorityInContentSpace();
|
| - rect.Intersect(visible_rect_for_tile_priority_);
|
| -
|
| - float min_acceptable_scale =
|
| - std::min(raster_contents_scale_, ideal_contents_scale_);
|
| -
|
| - if (PictureLayerImpl* twin = twin_layer_) {
|
| - float twin_min_acceptable_scale =
|
| - std::min(twin->ideal_contents_scale_, twin->raster_contents_scale_);
|
| - // Ignore 0 scale in case CalculateContentsScale() has never been
|
| - // called for active twin.
|
| - if (twin_min_acceptable_scale != 0.0f) {
|
| - min_acceptable_scale =
|
| - std::min(min_acceptable_scale, twin_min_acceptable_scale);
|
| - }
|
| - }
|
| -
|
| - PictureLayerTiling* high_res = NULL;
|
| - PictureLayerTiling* low_res = NULL;
|
| -
|
| - // First pass: ready to draw tiles in acceptable but non-ideal tilings are
|
| - // marked as required for activation so that their textures are not thrown
|
| - // away; any non-ready tiles are not marked as required.
|
| - Region missing_region = rect;
|
| - for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
|
| - PictureLayerTiling* tiling = tilings_->tiling_at(i);
|
| - DCHECK(tiling->has_ever_been_updated());
|
| -
|
| - if (tiling->resolution() == LOW_RESOLUTION) {
|
| - DCHECK(!low_res) << "There can only be one low res tiling";
|
| - low_res = tiling;
|
| - }
|
| - if (tiling->contents_scale() < min_acceptable_scale)
|
| - continue;
|
| - if (tiling->resolution() == HIGH_RESOLUTION) {
|
| - DCHECK(!high_res) << "There can only be one high res tiling";
|
| - high_res = tiling;
|
| - continue;
|
| - }
|
| - for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, rect); iter;
|
| - ++iter) {
|
| - if (!*iter || !iter->IsReadyToDraw())
|
| - continue;
|
| -
|
| - missing_region.Subtract(iter.geometry_rect());
|
| - iter->MarkRequiredForActivation();
|
| - }
|
| - }
|
| - DCHECK(high_res) << "There must be one high res tiling";
|
| -
|
| - // If these pointers are null (because no twin, no matching tiling, or the
|
| - // simpification just below), then high res tiles will be required to fill any
|
| - // holes left by the first pass above. If the pointers are valid, then this
|
| - // layer is allowed to skip any tiles that are not ready on its twin.
|
| - const PictureLayerTiling* twin_high_res = NULL;
|
| - const PictureLayerTiling* twin_low_res = NULL;
|
| -
|
| - if (twin_layer_) {
|
| - // As a simplification, only allow activating to skip twin tiles that the
|
| - // active layer is also missing when both this layer and its twin have
|
| - // "simple" sets of tilings: only 2 tilings (high and low) or only 1 high
|
| - // res tiling. This avoids having to iterate/track coverage of non-ideal
|
| - // tilings during the last draw call on the active layer.
|
| - if (tilings_->num_tilings() <= 2 &&
|
| - twin_layer_->tilings_->num_tilings() <= tilings_->num_tilings()) {
|
| - twin_low_res = low_res ? GetTwinTiling(low_res) : NULL;
|
| - twin_high_res = high_res ? GetTwinTiling(high_res) : NULL;
|
| - }
|
| -
|
| - // If this layer and its twin have different transforms, then don't compare
|
| - // them and only allow activating to high res tiles, since tiles on each
|
| - // layer will be in different places on screen.
|
| - if (layer_tree_impl()->RequiresHighResToDraw() ||
|
| - bounds() != twin_layer_->bounds() ||
|
| - draw_properties().screen_space_transform !=
|
| - twin_layer_->draw_properties().screen_space_transform) {
|
| - twin_high_res = NULL;
|
| - twin_low_res = NULL;
|
| - }
|
| - }
|
| -
|
| - // As a second pass, mark as required any visible high res tiles not filled in
|
| - // by acceptable non-ideal tiles from the first pass.
|
| - if (MarkVisibleTilesAsRequired(
|
| - high_res, twin_high_res, rect, missing_region)) {
|
| - // As an optional third pass, if a high res tile was skipped because its
|
| - // twin was also missing, then fall back to mark low res tiles as required
|
| - // in case the active twin is substituting those for missing high res
|
| - // content. Only suitable, when low res is enabled.
|
| - if (low_res) {
|
| - MarkVisibleTilesAsRequired(low_res, twin_low_res, rect, missing_region);
|
| - }
|
| - }
|
| -}
|
| -
|
| -bool PictureLayerImpl::MarkVisibleTilesAsRequired(
|
| - PictureLayerTiling* tiling,
|
| - const PictureLayerTiling* optional_twin_tiling,
|
| - const gfx::Rect& rect,
|
| - const Region& missing_region) const {
|
| - bool twin_had_missing_tile = false;
|
| - for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, rect); iter;
|
| - ++iter) {
|
| - Tile* tile = *iter;
|
| - // A null tile (i.e. missing recording) can just be skipped.
|
| - if (!tile)
|
| - continue;
|
| -
|
| - // If the tile is occluded, don't mark it as required for activation.
|
| - if (tile->is_occluded(PENDING_TREE))
|
| - continue;
|
| -
|
| - // If the missing region doesn't cover it, this tile is fully
|
| - // covered by acceptable tiles at other scales.
|
| - if (!missing_region.Intersects(iter.geometry_rect()))
|
| - continue;
|
| -
|
| - // If the twin tile doesn't exist (i.e. missing recording or so far away
|
| - // that it is outside the visible tile rect) or this tile is shared between
|
| - // with the twin, then this tile isn't required to prevent flashing.
|
| - if (optional_twin_tiling) {
|
| - Tile* twin_tile = optional_twin_tiling->TileAt(iter.i(), iter.j());
|
| - if (!twin_tile || twin_tile == tile) {
|
| - // However if the shared tile is being used on the active tree, then
|
| - // there's no missing content in this place, and low res is not needed.
|
| - if (!twin_tile || !twin_tile->IsReadyToDraw())
|
| - twin_had_missing_tile = true;
|
| - continue;
|
| - }
|
| - }
|
| -
|
| - tile->MarkRequiredForActivation();
|
| - }
|
| - return twin_had_missing_tile;
|
| -}
|
| -
|
| void PictureLayerImpl::DoPostCommitInitialization() {
|
| DCHECK(needs_post_commit_initialization_);
|
| DCHECK(layer_tree_impl()->IsPendingTree());
|
| @@ -1342,8 +1197,7 @@ void PictureLayerImpl::SanityCheckTilingState() const {
|
| if (tilings_->num_tilings() == 0)
|
| return;
|
|
|
| - // MarkVisibleResourcesAsRequired depends on having exactly 1 high res
|
| - // tiling to mark its tiles as being required for activation.
|
| + // We should only have one high res tiling.
|
| DCHECK_EQ(1, tilings_->NumHighResTilings());
|
| #endif
|
| }
|
| @@ -1504,10 +1358,16 @@ bool PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw() const {
|
| ++iter) {
|
| const Tile* tile = *iter;
|
| // A null tile (i.e. missing recording) can just be skipped.
|
| + // TODO(vmpstr): Verify this is true if we create tiles in raster
|
| + // iterators.
|
| if (!tile)
|
| continue;
|
|
|
| - if (tile->required_for_activation() && !tile->IsReadyToDraw())
|
| + // We can't check tile->required_for_activation, because that value might
|
| + // be out of date. It is updated in the raster/eviction iterators.
|
| + // TODO(vmpstr): Remove the comment once you can't access this information
|
| + // from the tile.
|
| + if (tiling->IsTileRequiredForActivation(tile) && !tile->IsReadyToDraw())
|
| return false;
|
| }
|
| }
|
| @@ -1538,19 +1398,17 @@ PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator(
|
| return;
|
| }
|
|
|
| - WhichTree tree = layer_->GetTree();
|
| -
|
| // Find high and low res tilings and initialize the iterators.
|
| for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) {
|
| PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i);
|
| if (tiling->resolution() == HIGH_RESOLUTION) {
|
| iterators_[HIGH_RES] =
|
| - PictureLayerTiling::TilingRasterTileIterator(tiling, tree);
|
| + PictureLayerTiling::TilingRasterTileIterator(tiling);
|
| }
|
|
|
| if (tiling->resolution() == LOW_RESOLUTION) {
|
| iterators_[LOW_RES] =
|
| - PictureLayerTiling::TilingRasterTileIterator(tiling, tree);
|
| + PictureLayerTiling::TilingRasterTileIterator(tiling);
|
| }
|
| }
|
|
|
|
|