Index: cc/layers/picture_layer_impl.cc |
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc |
index 54cfac88b32ec722abac90809ad0c5c9486e7731..392450a32942284cf6315b74e1e4b43faf2836ac 100644 |
--- a/cc/layers/picture_layer_impl.cc |
+++ b/cc/layers/picture_layer_impl.cc |
@@ -63,9 +63,13 @@ PictureLayerImpl::Pair::Pair(PictureLayerImpl* active_layer, |
PictureLayerImpl::Pair::~Pair() { |
} |
-PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id) |
+PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, |
+ int id, |
+ bool is_mask) |
: LayerImpl(tree_impl, id), |
twin_layer_(nullptr), |
+ tilings_(CreatePictureLayerTilingSet()), |
+ // TODO(danakj): Can this be null to start? |
raster_source_(PicturePileImpl::Create()), |
ideal_page_scale_(0.f), |
ideal_device_scale_(0.f), |
@@ -81,7 +85,8 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id) |
needs_post_commit_initialization_(true), |
should_update_tile_priorities_(false), |
only_used_low_res_last_append_quads_(false), |
- is_mask_(false) { |
+ is_mask_(is_mask), |
+ nearest_neighbor_(false) { |
layer_tree_impl()->RegisterPictureLayerImpl(this); |
} |
@@ -95,8 +100,10 @@ scoped_ptr<TilingSetEvictionQueue> PictureLayerImpl::CreateEvictionQueue( |
TreePriority tree_priority) { |
if (!tilings_) |
return make_scoped_ptr(new TilingSetEvictionQueue()); |
- return make_scoped_ptr( |
- new TilingSetEvictionQueue(tilings_.get(), tree_priority)); |
+ bool skip_shared_out_of_order_tiles = |
+ GetPendingOrActiveTwinLayer() != nullptr; |
+ return make_scoped_ptr(new TilingSetEvictionQueue( |
+ tilings_.get(), tree_priority, skip_shared_out_of_order_tiles)); |
} |
scoped_ptr<TilingSetRasterQueue> PictureLayerImpl::CreateRasterQueue( |
@@ -113,7 +120,7 @@ const char* PictureLayerImpl::LayerTypeAsString() const { |
scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl( |
LayerTreeImpl* tree_impl) { |
- return PictureLayerImpl::Create(tree_impl, id()); |
+ return PictureLayerImpl::Create(tree_impl, id(), is_mask_); |
} |
void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { |
@@ -121,6 +128,7 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { |
// a descendant of an opacity 0 layer). |
DoPostCommitInitializationIfNeeded(); |
PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); |
+ DCHECK_EQ(layer_impl->is_mask_, is_mask_); |
LayerImpl::PushPropertiesTo(base_layer); |
@@ -134,54 +142,39 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { |
twin_layer_ = layer_impl; |
layer_impl->twin_layer_ = this; |
- layer_impl->set_is_mask(is_mask_); |
- layer_impl->UpdateRasterSource(raster_source_); |
+ layer_impl->SetNearestNeighbor(nearest_neighbor_); |
+ // Solid color layers have no tilings. |
DCHECK_IMPLIES(raster_source_->IsSolidColor(), tilings_->num_tilings() == 0); |
- // Tilings would be expensive to push, so we swap. |
- layer_impl->tilings_.swap(tilings_); |
- layer_impl->tilings_->SetClient(layer_impl); |
- if (tilings_) |
- tilings_->SetClient(this); |
+ // The pending tree should only have a high res (and possibly low res) tiling. |
+ DCHECK_LE(tilings_->num_tilings(), |
+ layer_tree_impl()->create_low_res_tiling() ? 2u : 1u); |
- // Ensure that the recycle tree doesn't have any unshared tiles. |
- if (tilings_ && raster_source_->IsSolidColor()) |
- tilings_->RemoveAllTilings(); |
+ layer_impl->UpdateRasterSource(raster_source_, &invalidation_, |
+ tilings_.get()); |
+ DCHECK(invalidation_.IsEmpty()); |
- // Remove invalidated tiles from what will become a recycle tree. |
- if (tilings_) |
- tilings_->RemoveTilesInRegion(invalidation_); |
+ // After syncing a solid color layer, the active layer has no tilings. |
+ DCHECK_IMPLIES(raster_source_->IsSolidColor(), |
+ layer_impl->tilings_->num_tilings() == 0); |
layer_impl->raster_page_scale_ = raster_page_scale_; |
layer_impl->raster_device_scale_ = raster_device_scale_; |
layer_impl->raster_source_scale_ = raster_source_scale_; |
layer_impl->raster_contents_scale_ = raster_contents_scale_; |
layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_; |
- layer_impl->needs_post_commit_initialization_ = false; |
- // The invalidation on this soon-to-be-recycled layer must be cleared to |
- // mirror clearing the invalidation in PictureLayer's version of this function |
- // in case push properties is skipped. |
- layer_impl->invalidation_.Swap(&invalidation_); |
- invalidation_.Clear(); |
+ layer_impl->SanityCheckTilingState(); |
+ |
+ layer_impl->needs_post_commit_initialization_ = false; |
needs_post_commit_initialization_ = true; |
// We always need to push properties. |
// See http://crbug.com/303943 |
+ // TODO(danakj): Stop always pushing properties since we don't swap tilings. |
needs_push_properties_ = true; |
} |
-void PictureLayerImpl::UpdateRasterSource( |
- scoped_refptr<RasterSource> raster_source) { |
- bool could_have_tilings = CanHaveTilings(); |
- raster_source_.swap(raster_source); |
- |
- // Need to call UpdateTiles again if CanHaveTilings changed. |
- if (could_have_tilings != CanHaveTilings()) { |
- layer_tree_impl()->set_needs_update_draw_properties(); |
- } |
-} |
- |
void PictureLayerImpl::AppendQuads(RenderPass* render_pass, |
const Occlusion& occlusion_in_content_space, |
AppendQuadsData* append_quads_data) { |
@@ -251,8 +244,9 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, |
PictureDrawQuad* quad = |
render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); |
quad->SetNew(shared_quad_state, geometry_rect, opaque_rect, |
- visible_geometry_rect, texture_rect, texture_size, RGBA_8888, |
- quad_content_rect, max_contents_scale, raster_source_); |
+ visible_geometry_rect, texture_rect, texture_size, |
+ nearest_neighbor_, RGBA_8888, quad_content_rect, |
+ max_contents_scale, raster_source_); |
return; |
} |
@@ -364,7 +358,8 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, |
draw_info.get_resource_id(), |
texture_rect, |
iter.texture_size(), |
- draw_info.contents_swizzled()); |
+ draw_info.contents_swizzled(), |
+ nearest_neighbor_); |
has_draw_quad = true; |
break; |
} |
@@ -386,8 +381,8 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, |
render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); |
quad->SetNew(shared_quad_state, geometry_rect, opaque_rect, |
visible_geometry_rect, texture_rect, iter.texture_size(), |
- format, iter->content_rect(), iter->contents_scale(), |
- raster_source_); |
+ nearest_neighbor_, format, iter->content_rect(), |
+ iter->contents_scale(), raster_source_); |
has_draw_quad = true; |
break; |
} |
@@ -485,8 +480,6 @@ void PictureLayerImpl::UpdateTiles(const Occlusion& occlusion_in_content_space, |
UpdateIdealScales(); |
- DCHECK_IMPLIES(tilings_->num_tilings() == 0, raster_contents_scale_ == 0.f) |
- << "A layer with no tilings shouldn't have valid raster scales"; |
if (!raster_contents_scale_ || ShouldAdjustRasterScale()) { |
RecalculateRasterScales(); |
AddTilingsForRasterScale(); |
@@ -581,6 +574,44 @@ PictureLayerImpl* PictureLayerImpl::GetRecycledTwinLayer() const { |
return twin_layer_; |
} |
+void PictureLayerImpl::UpdateRasterSource( |
+ scoped_refptr<RasterSource> raster_source, |
+ Region* new_invalidation, |
+ const PictureLayerTilingSet* pending_set) { |
+ // The bounds and the pile size may differ if the pile wasn't updated (ie. |
+ // PictureLayer::Update didn't happen). In that case the pile will be empty. |
+ DCHECK_IMPLIES(!raster_source->GetSize().IsEmpty(), |
+ bounds() == raster_source->GetSize()) |
+ << " bounds " << bounds().ToString() << " pile " |
+ << raster_source->GetSize().ToString(); |
+ |
+ bool could_have_tilings = CanHaveTilings(); |
+ raster_source_.swap(raster_source); |
+ |
+ // The |new_invalidation| must be cleared before updating tilings since they |
+ // access the invalidation through the PictureLayerTilingClient interface. |
+ invalidation_.Clear(); |
+ invalidation_.Swap(new_invalidation); |
+ |
+ bool can_have_tilings = CanHaveTilings(); |
+ |
+ // Need to call UpdateTiles again if CanHaveTilings changed. |
+ if (could_have_tilings != can_have_tilings) |
+ layer_tree_impl()->set_needs_update_draw_properties(); |
+ |
+ if (!can_have_tilings) { |
+ RemoveAllTilings(); |
+ return; |
+ } |
+ |
+ // We could do this after doing UpdateTiles, which would avoid doing this for |
+ // tilings that are going to disappear on the pending tree (if scale changed). |
+ // But that would also be more complicated, so we just do it here for now. |
+ tilings_->UpdateTilingsToCurrentRasterSource( |
+ raster_source_.get(), pending_set, raster_source_->GetSize(), |
+ invalidation_, MinimumContentsScale()); |
+} |
+ |
void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) { |
if (layer_tree_impl()->IsActiveTree()) { |
gfx::RectF layer_damage_rect = |
@@ -600,9 +631,10 @@ void PictureLayerImpl::DidBeginTracing() { |
} |
void PictureLayerImpl::ReleaseResources() { |
+ // Recreate tilings with new settings, since some of those might change when |
+ // we release resources. If tilings_ is null, then leave it as null. |
if (tilings_) |
- RemoveAllTilings(); |
- |
+ tilings_ = CreatePictureLayerTilingSet(); |
ResetRasterScale(); |
// To avoid an edge case after lost context where the tree is up to date but |
@@ -637,6 +669,8 @@ scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling, |
const Region* PictureLayerImpl::GetPendingInvalidation() { |
if (layer_tree_impl()->IsPendingTree()) |
return &invalidation_; |
+ if (layer_tree_impl()->IsRecycleTree()) |
+ return nullptr; |
DCHECK(layer_tree_impl()->IsActiveTree()); |
if (PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer()) |
return &twin_layer->invalidation_; |
@@ -648,9 +682,6 @@ const PictureLayerTiling* PictureLayerImpl::GetPendingOrActiveTwinTiling( |
PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer(); |
if (!twin_layer) |
return nullptr; |
- // TODO(danakj): Remove this when no longer swapping tilings. |
- if (!twin_layer->tilings_) |
- return nullptr; |
return twin_layer->tilings_->FindTilingWithScale(tiling->contents_scale()); |
} |
@@ -668,22 +699,6 @@ TilePriority::PriorityBin PictureLayerImpl::GetMaxTilePriorityBin() const { |
return TilePriority::NOW; |
} |
-size_t PictureLayerImpl::GetMaxTilesForInterestArea() const { |
- return layer_tree_impl()->settings().max_tiles_for_interest_area; |
-} |
- |
-float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const { |
- return layer_tree_impl()->use_gpu_rasterization() |
- ? 0.f |
- : layer_tree_impl()->settings().skewport_target_time_in_seconds; |
-} |
- |
-int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const { |
- return layer_tree_impl() |
- ->settings() |
- .skewport_extrapolation_limit_in_content_pixels; |
-} |
- |
bool PictureLayerImpl::RequiresHighResToDraw() const { |
return layer_tree_impl()->RequiresHighResToDraw(); |
} |
@@ -765,69 +780,15 @@ gfx::Size PictureLayerImpl::CalculateTileSize( |
return gfx::Size(tile_width, tile_height); |
} |
-void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) { |
- DCHECK(!other->needs_post_commit_initialization_); |
- DCHECK(other->tilings_); |
- |
- if (!DrawsContent()) { |
- RemoveAllTilings(); |
- return; |
- } |
- |
- raster_page_scale_ = other->raster_page_scale_; |
- raster_device_scale_ = other->raster_device_scale_; |
- raster_source_scale_ = other->raster_source_scale_; |
- raster_contents_scale_ = other->raster_contents_scale_; |
- low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_; |
- |
- bool synced_high_res_tiling = false; |
- if (CanHaveTilings()) { |
- synced_high_res_tiling = tilings_->SyncTilings( |
- *other->tilings_, raster_source_->GetSize(), invalidation_, |
- MinimumContentsScale(), raster_source_.get()); |
- } else { |
- RemoveAllTilings(); |
- } |
- |
- // If our MinimumContentsScale has changed to prevent the twin's high res |
- // tiling from being synced, we should reset the raster scale and let it be |
- // recalculated (1) again. This can happen if our bounds shrink to the point |
- // where min contents scale grows. |
- // (1) - TODO(vmpstr) Instead of hoping that this will be recalculated, we |
- // should refactor this code a little bit and actually recalculate this. |
- // However, this is a larger undertaking, so this will work for now. |
- if (!synced_high_res_tiling) |
- ResetRasterScale(); |
- else |
- SanityCheckTilingState(); |
-} |
- |
-void PictureLayerImpl::SyncTiling( |
- const PictureLayerTiling* tiling) { |
- if (!tilings_) |
- return; |
- if (!CanHaveTilingWithScale(tiling->contents_scale())) |
- return; |
- tilings_->AddTiling(tiling->contents_scale(), raster_source_->GetSize()); |
- |
- // If this tree needs update draw properties, then the tiling will |
- // get updated prior to drawing or activation. If this tree does not |
- // need update draw properties, then its transforms are up to date and |
- // we can create tiles for this tiling immediately. |
- if (!layer_tree_impl()->needs_update_draw_properties() && |
- should_update_tile_priorities_) { |
- // TODO(danakj): Add a DCHECK() that we are not using occlusion tracking |
- // when we stop using the pending tree in the browser compositor. If we want |
- // to support occlusion tracking here, we need to dirty the draw properties |
- // or save occlusion as a draw property. |
- UpdateTilePriorities(Occlusion()); |
- } |
-} |
- |
void PictureLayerImpl::GetContentsResourceId( |
ResourceProvider::ResourceId* resource_id, |
gfx::Size* resource_size) const { |
- DCHECK_EQ(bounds().ToString(), raster_source_->GetSize().ToString()); |
+ // The bounds and the pile size may differ if the pile wasn't updated (ie. |
+ // PictureLayer::Update didn't happen). In that case the pile will be empty. |
+ DCHECK_IMPLIES(!raster_source_->GetSize().IsEmpty(), |
+ bounds() == raster_source_->GetSize()) |
+ << " bounds " << bounds().ToString() << " pile " |
+ << raster_source_->GetSize().ToString(); |
gfx::Rect content_rect(bounds()); |
PictureLayerTilingSet::CoverageIterator iter( |
tilings_.get(), 1.f, content_rect, ideal_contents_scale_); |
@@ -854,21 +815,18 @@ void PictureLayerImpl::GetContentsResourceId( |
*resource_size = iter.texture_size(); |
} |
+void PictureLayerImpl::SetNearestNeighbor(bool nearest_neighbor) { |
+ if (nearest_neighbor_ == nearest_neighbor) |
+ return; |
+ |
+ nearest_neighbor_ = nearest_neighbor; |
+ NoteLayerPropertyChanged(); |
+} |
+ |
void PictureLayerImpl::DoPostCommitInitialization() { |
+ // TODO(danakj): Remove this. |
DCHECK(needs_post_commit_initialization_); |
DCHECK(layer_tree_impl()->IsPendingTree()); |
- |
- if (!tilings_) |
- tilings_ = PictureLayerTilingSet::Create(this); |
- |
- PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer(); |
- if (twin_layer) { |
- // If the twin has never been pushed to, do not sync from it. |
- // This can happen if this function is called during activation. |
- if (!twin_layer->needs_post_commit_initialization_) |
- SyncFromActiveLayer(twin_layer); |
- } |
- |
needs_post_commit_initialization_ = false; |
} |
@@ -881,9 +839,6 @@ PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) { |
DCHECK(raster_source_->HasRecordings()); |
- if (PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer()) |
- twin_layer->SyncTiling(tiling); |
- |
return tiling; |
} |
@@ -929,6 +884,12 @@ void PictureLayerImpl::AddTilingsForRasterScale() { |
// Make sure we always have one high-res (even if high == low). |
high_res->set_resolution(HIGH_RESOLUTION); |
+ if (layer_tree_impl()->IsPendingTree()) { |
+ // On the pending tree, drop any tilings that are non-ideal since we don't |
+ // need them to activate anyway. |
+ tilings_->RemoveNonIdealTilings(); |
+ } |
+ |
SanityCheckTilingState(); |
} |
@@ -1113,9 +1074,6 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer( |
layer_tree_impl()->create_low_res_tiling(), twin_set, |
recycled_twin_set); |
- if (twin_set && twin_set->num_tilings() == 0) |
- twin->ResetRasterScale(); |
- |
if (recycled_twin_set && recycled_twin_set->num_tilings() == 0) |
recycled_twin->ResetRasterScale(); |
@@ -1158,6 +1116,8 @@ bool PictureLayerImpl::CanHaveTilings() const { |
return false; |
if (!raster_source_->HasRecordings()) |
return false; |
+ // If the |raster_source_| has a recording it should have non-empty bounds. |
+ DCHECK(!raster_source_->GetSize().IsEmpty()); |
return true; |
} |
@@ -1196,6 +1156,17 @@ float PictureLayerImpl::MaximumTilingContentsScale() const { |
return std::max(max_contents_scale, MinimumContentsScale()); |
} |
+scoped_ptr<PictureLayerTilingSet> |
+PictureLayerImpl::CreatePictureLayerTilingSet() { |
+ const LayerTreeSettings& settings = layer_tree_impl()->settings(); |
+ return PictureLayerTilingSet::Create( |
+ this, settings.max_tiles_for_interest_area, |
+ layer_tree_impl()->use_gpu_rasterization() |
+ ? 0.f |
+ : settings.skewport_target_time_in_seconds, |
+ settings.skewport_extrapolation_limit_in_content_pixels); |
+} |
+ |
void PictureLayerImpl::UpdateIdealScales() { |
DCHECK(CanHaveTilings()); |