diff options
author | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-27 21:28:12 +0000 |
---|---|---|
committer | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-27 21:28:12 +0000 |
commit | 8f802b2596f69ecd68ac6496da0e4b661183a777 (patch) | |
tree | 8dff0d63a3a8dabf11bb9ceb93daab88159aa50b /cc/layers | |
parent | b9adabf3fd45ddbba723a7e78241df62c0cb730b (diff) | |
download | chromium_src-8f802b2596f69ecd68ac6496da0e4b661183a777.zip chromium_src-8f802b2596f69ecd68ac6496da0e4b661183a777.tar.gz chromium_src-8f802b2596f69ecd68ac6496da0e4b661183a777.tar.bz2 |
Re-land: cc: Examine layers to determine if we're ready to activate.
This introduces a new mechanism for determining when
we're ready to activate the pending tree. The tile
priority is still used to determine when it's worth
waking up the compositor thread and evaluating if
we can activate. However, the actual check that
determines if we're ready to activate doesn't rely
on the state of scheduled raster tasks but is a
synchronous call on each layer.
The result is a pending tree activation mechanism that
is much easier to debug and validate for correctness,
while still providing the performance benefits of the
old mechanism by taking the "required to activate" field
of the tile priority into account when scheduling tasks.
BUG=375206
TEST=cc_unittests --gtest_filter=PictureLayerImplTest.AllTilesRequiredForActivationAreReadyToDraw
Review URL: https://codereview.chromium.org/287643004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@273040 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/layers')
-rw-r--r-- | cc/layers/layer_impl.h | 2 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl.cc | 178 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl.h | 3 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl_unittest.cc | 56 |
4 files changed, 170 insertions, 69 deletions
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index 99642cb..c97ae12 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h @@ -188,7 +188,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, virtual RenderPass::Id NextContributingRenderPassId(RenderPass::Id id) const; virtual void UpdateTilePriorities() {} - virtual void NotifyTileInitialized(const Tile* tile) {} + virtual void NotifyTileStateChanged(const Tile* tile) {} virtual ScrollbarLayerImplBase* ToScrollbarLayer(); diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index 250dafa..76ab5bb6 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc @@ -233,7 +233,8 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink, // unused can be considered for removal. std::vector<PictureLayerTiling*> seen_tilings; - bool had_checkerboard_quads = false; + size_t missing_tile_count = 0u; + size_t on_demand_missing_tile_count = 0u; for (PictureLayerTilingSet::CoverageIterator iter( tilings_.get(), contents_scale_x(), rect, ideal_contents_scale_); iter; @@ -247,8 +248,75 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink, append_quads_data->visible_content_area += visible_geometry_rect.width() * visible_geometry_rect.height(); - if (!*iter || !iter->IsReadyToDraw()) { - had_checkerboard_quads = true; + scoped_ptr<DrawQuad> draw_quad; + if (*iter && iter->IsReadyToDraw()) { + const ManagedTileState::TileVersion& tile_version = + iter->GetTileVersionForDrawing(); + switch (tile_version.mode()) { + case ManagedTileState::TileVersion::RESOURCE_MODE: { + gfx::RectF texture_rect = iter.texture_rect(); + gfx::Rect opaque_rect = iter->opaque_rect(); + opaque_rect.Intersect(geometry_rect); + + if (iter->contents_scale() != ideal_contents_scale_) + append_quads_data->had_incomplete_tile = true; + + scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create(); + quad->SetNew(shared_quad_state, + geometry_rect, + opaque_rect, + visible_geometry_rect, + tile_version.get_resource_id(), + texture_rect, + iter.texture_size(), + tile_version.contents_swizzled()); + draw_quad = quad.PassAs<DrawQuad>(); + break; + } + case ManagedTileState::TileVersion::PICTURE_PILE_MODE: { + if (!layer_tree_impl() + ->GetRendererCapabilities() + .allow_rasterize_on_demand) { + ++on_demand_missing_tile_count; + break; + } + + gfx::RectF texture_rect = iter.texture_rect(); + gfx::Rect opaque_rect = iter->opaque_rect(); + opaque_rect.Intersect(geometry_rect); + + ResourceProvider* resource_provider = + layer_tree_impl()->resource_provider(); + ResourceFormat format = + resource_provider->memory_efficient_texture_format(); + scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create(); + quad->SetNew(shared_quad_state, + geometry_rect, + opaque_rect, + visible_geometry_rect, + texture_rect, + iter.texture_size(), + format, + iter->content_rect(), + iter->contents_scale(), + pile_); + draw_quad = quad.PassAs<DrawQuad>(); + break; + } + case ManagedTileState::TileVersion::SOLID_COLOR_MODE: { + scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); + quad->SetNew(shared_quad_state, + geometry_rect, + visible_geometry_rect, + tile_version.get_solid_color(), + false); + draw_quad = quad.PassAs<DrawQuad>(); + break; + } + } + } + + if (!draw_quad) { if (draw_checkerboard_for_missing_tiles()) { scoped_ptr<CheckerboardDrawQuad> quad = CheckerboardDrawQuad::Create(); SkColor color = DebugColors::DefaultCheckerboardColor(); @@ -270,69 +338,10 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink, append_quads_data->had_incomplete_tile = true; append_quads_data->approximated_visible_content_area += visible_geometry_rect.width() * visible_geometry_rect.height(); + ++missing_tile_count; continue; } - const ManagedTileState::TileVersion& tile_version = - iter->GetTileVersionForDrawing(); - scoped_ptr<DrawQuad> draw_quad; - switch (tile_version.mode()) { - case ManagedTileState::TileVersion::RESOURCE_MODE: { - gfx::RectF texture_rect = iter.texture_rect(); - gfx::Rect opaque_rect = iter->opaque_rect(); - opaque_rect.Intersect(geometry_rect); - - if (iter->contents_scale() != ideal_contents_scale_) - append_quads_data->had_incomplete_tile = true; - - scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create(); - quad->SetNew(shared_quad_state, - geometry_rect, - opaque_rect, - visible_geometry_rect, - tile_version.get_resource_id(), - texture_rect, - iter.texture_size(), - tile_version.contents_swizzled()); - draw_quad = quad.PassAs<DrawQuad>(); - break; - } - case ManagedTileState::TileVersion::PICTURE_PILE_MODE: { - gfx::RectF texture_rect = iter.texture_rect(); - gfx::Rect opaque_rect = iter->opaque_rect(); - opaque_rect.Intersect(geometry_rect); - - ResourceProvider* resource_provider = - layer_tree_impl()->resource_provider(); - ResourceFormat format = - resource_provider->memory_efficient_texture_format(); - scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create(); - quad->SetNew(shared_quad_state, - geometry_rect, - opaque_rect, - visible_geometry_rect, - texture_rect, - iter.texture_size(), - format, - iter->content_rect(), - iter->contents_scale(), - pile_); - draw_quad = quad.PassAs<DrawQuad>(); - break; - } - case ManagedTileState::TileVersion::SOLID_COLOR_MODE: { - scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); - quad->SetNew(shared_quad_state, - geometry_rect, - visible_geometry_rect, - tile_version.get_solid_color(), - false); - draw_quad = quad.PassAs<DrawQuad>(); - break; - } - } - - DCHECK(draw_quad); quad_sink->Append(draw_quad.Pass()); if (iter->priority(ACTIVE_TREE).resolution != HIGH_RESOLUTION) { @@ -344,10 +353,14 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink, seen_tilings.push_back(iter.CurrentTiling()); } - if (had_checkerboard_quads) { - TRACE_EVENT_INSTANT0("cc", + if (missing_tile_count) { + TRACE_EVENT_INSTANT2("cc", "PictureLayerImpl::AppendQuads checkerboard", - TRACE_EVENT_SCOPE_THREAD); + TRACE_EVENT_SCOPE_THREAD, + "missing_tile_count", + missing_tile_count, + "on_demand_missing_tile_count", + on_demand_missing_tile_count); } // Aggressively remove any tilings that are not seen to save memory. Note @@ -429,7 +442,7 @@ void PictureLayerImpl::UpdateTilePriorities() { layer_tree_impl()->DidModifyTilePriorities(); } -void PictureLayerImpl::NotifyTileInitialized(const Tile* tile) { +void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) { if (layer_tree_impl()->IsActiveTree()) { gfx::RectF layer_damage_rect = gfx::ScaleRect(tile->content_rect(), 1.f / tile->contents_scale()); @@ -1354,6 +1367,37 @@ bool PictureLayerImpl::IsOnActiveOrPendingTree() const { return !layer_tree_impl()->IsRecycleTree(); } +bool PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw() const { + if (!layer_tree_impl()->IsPendingTree()) + return true; + + if (!tilings_) + return true; + + for (size_t i = 0; i < tilings_->num_tilings(); ++i) { + PictureLayerTiling* tiling = tilings_->tiling_at(i); + if (tiling->resolution() != HIGH_RESOLUTION && + tiling->resolution() != LOW_RESOLUTION) + continue; + + gfx::Rect rect(visible_content_rect()); + for (PictureLayerTiling::CoverageIterator iter( + tiling, contents_scale_x(), rect); + iter; + ++iter) { + const Tile* tile = *iter; + // A null tile (i.e. missing recording) can just be skipped. + if (!tile) + continue; + + if (tile->required_for_activation() && !tile->IsReadyToDraw()) + return false; + } + } + + return true; +} + PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator() : layer_(NULL) {} diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h index afd96aa..9609ccf 100644 --- a/cc/layers/picture_layer_impl.h +++ b/cc/layers/picture_layer_impl.h @@ -92,7 +92,7 @@ class CC_EXPORT PictureLayerImpl virtual void AppendQuads(QuadSink* quad_sink, AppendQuadsData* append_quads_data) OVERRIDE; virtual void UpdateTilePriorities() OVERRIDE; - virtual void NotifyTileInitialized(const Tile* tile) OVERRIDE; + virtual void NotifyTileStateChanged(const Tile* tile) OVERRIDE; virtual void DidBecomeActive() OVERRIDE; virtual void DidBeginTracing() OVERRIDE; virtual void ReleaseResources() OVERRIDE; @@ -136,6 +136,7 @@ class CC_EXPORT PictureLayerImpl PictureLayerImpl* GetTwinLayer() { return twin_layer_; } WhichTree GetTree() const; bool IsOnActiveOrPendingTree() const; + bool AllTilesRequiredForActivationAreReadyToDraw() const; protected: friend class LayerRasterTileIterator; diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index d919298..64454ae 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc @@ -2391,5 +2391,61 @@ TEST_F(PictureLayerImplTest, RasterScaleChangeWithoutAnimation) { EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f); } +TEST_F(PictureLayerImplTest, LowResReadyToDrawNotEnoughToActivate) { + gfx::Size tile_size(100, 100); + gfx::Size layer_bounds(1000, 1000); + + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); + + // Make sure some tiles are not shared. + pending_layer_->set_invalidation(gfx::Rect(gfx::Point(50, 50), tile_size)); + + CreateHighLowResAndSetAllTilesVisible(); + active_layer_->SetAllTilesReady(); + pending_layer_->MarkVisibleResourcesAsRequired(); + + // All pending layer tiles required are not ready. + EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw()); + + // Initialize all low-res tiles. + pending_layer_->SetAllTilesReadyInTiling(pending_layer_->LowResTiling()); + + // Low-res tiles should not be enough. + EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw()); + + // Initialize remaining tiles. + pending_layer_->SetAllTilesReady(); + + EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw()); +} + +TEST_F(PictureLayerImplTest, HighResReadyToDrawNotEnoughToActivate) { + gfx::Size tile_size(100, 100); + gfx::Size layer_bounds(1000, 1000); + + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); + + // Make sure some tiles are not shared. + pending_layer_->set_invalidation(gfx::Rect(gfx::Point(50, 50), tile_size)); + + CreateHighLowResAndSetAllTilesVisible(); + active_layer_->SetAllTilesReady(); + pending_layer_->MarkVisibleResourcesAsRequired(); + + // All pending layer tiles required are not ready. + EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw()); + + // Initialize all high-res tiles. + pending_layer_->SetAllTilesReadyInTiling(pending_layer_->HighResTiling()); + + // High-res tiles should not be enough. + EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw()); + + // Initialize remaining tiles. + pending_layer_->SetAllTilesReady(); + + EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw()); +} + } // namespace } // namespace cc |