diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-24 18:32:19 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-24 18:32:19 +0000 |
commit | c0ae06c1ab9c462312fa9afb14eb1f1bf003b301 (patch) | |
tree | b9d5397fe7a1fc5127f7e436b87427a94a9a8c4f /cc | |
parent | 53ac9412855439338937ed1c4d0103b717ff64e4 (diff) | |
download | chromium_src-c0ae06c1ab9c462312fa9afb14eb1f1bf003b301.zip chromium_src-c0ae06c1ab9c462312fa9afb14eb1f1bf003b301.tar.gz chromium_src-c0ae06c1ab9c462312fa9afb14eb1f1bf003b301.tar.bz2 |
Add a hide_layer_and_subtree() flag to cc::Layer
This flag does what it says. We can use this flag to simplify ui::Layer
as it was recursively calling SetIsDrawable() instead, and now can just
SetHideLayerAndSubtree() on a single layer.
This flag is needed to allow readbacks of layers that are have hidden
visibility (possibly due to an ancestor).
Tests:
LayerTest.CheckPropertyChangeCausesCorrectBehavior
LayerImplTest.VerifyLayerChangesAreTrackedProperly
LayerTreeHostCommonTest.SubtreeHidden_SingleLayer
LayerTreeHostCommonTest.SubtreeHidden_SingleLayerImpl
LayerTreeHostCommonTest.SubtreeHidden_TwoLayers
LayerTreeHostCommonTest.SubtreeHidden_TwoLayersImpl
R=enne, piman
BUG=242572
Review URL: https://chromiumcodereview.appspot.com/16896017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208241 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/layers/layer.cc | 11 | ||||
-rw-r--r-- | cc/layers/layer.h | 4 | ||||
-rw-r--r-- | cc/layers/layer_impl.cc | 10 | ||||
-rw-r--r-- | cc/layers/layer_impl.h | 4 | ||||
-rw-r--r-- | cc/layers/layer_impl_unittest.cc | 1 | ||||
-rw-r--r-- | cc/layers/layer_unittest.cc | 1 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_common.cc | 11 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_common_unittest.cc | 246 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest.cc | 93 |
9 files changed, 378 insertions, 3 deletions
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index bdcbc75..fcdbded 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc @@ -47,6 +47,7 @@ Layer::Layer() anchor_point_z_(0.f), is_container_for_fixed_position_layers_(false), is_drawable_(false), + hide_layer_and_subtree_(false), masks_to_bounds_(false), contents_opaque_(false), double_sided_(true), @@ -612,6 +613,15 @@ void Layer::SetIsDrawable(bool is_drawable) { SetNeedsCommit(); } +void Layer::SetHideLayerAndSubtree(bool hide) { + DCHECK(IsPropertyChangeAllowed()); + if (hide_layer_and_subtree_ == hide) + return; + + hide_layer_and_subtree_ = hide; + SetNeedsCommit(); +} + void Layer::SetNeedsDisplayRect(const gfx::RectF& dirty_rect) { update_rect_.Union(dirty_rect); needs_display_ = true; @@ -682,6 +692,7 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { draw_checkerboard_for_missing_tiles_); layer->SetForceRenderSurface(force_render_surface_); layer->SetDrawsContent(DrawsContent()); + layer->SetHideLayerAndSubtree(hide_layer_and_subtree_); layer->SetFilters(filters()); layer->SetFilter(filter()); layer->SetBackgroundFilters(background_filters()); diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 91972b3..7fc53b3 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h @@ -268,6 +268,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, void SetIsDrawable(bool is_drawable); + void SetHideLayerAndSubtree(bool hide); + bool hide_layer_and_subtree() const { return hide_layer_and_subtree_; } + void SetReplicaLayer(Layer* layer); Layer* replica_layer() { return replica_layer_.get(); } const Layer* replica_layer() const { return replica_layer_.get(); } @@ -465,6 +468,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, bool is_container_for_fixed_position_layers_; LayerPositionConstraint position_constraint_; bool is_drawable_; + bool hide_layer_and_subtree_; bool masks_to_bounds_; bool contents_opaque_; bool double_sided_; diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 0c11c6b..254a17f 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc @@ -51,6 +51,7 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id) use_parent_backface_visibility_(false), draw_checkerboard_for_missing_tiles_(false), draws_content_(false), + hide_layer_and_subtree_(false), force_render_surface_(false), is_container_for_fixed_position_layers_(false), draw_depth_(0.f), @@ -368,6 +369,7 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { draw_checkerboard_for_missing_tiles_); layer->SetForceRenderSurface(force_render_surface_); layer->SetDrawsContent(DrawsContent()); + layer->SetHideLayerAndSubtree(hide_layer_and_subtree_); layer->SetFilters(filters()); layer->SetFilter(filter()); layer->SetBackgroundFilters(background_filters()); @@ -604,6 +606,14 @@ void LayerImpl::SetDrawsContent(bool draws_content) { NoteLayerPropertyChanged(); } +void LayerImpl::SetHideLayerAndSubtree(bool hide) { + if (hide_layer_and_subtree_ == hide) + return; + + hide_layer_and_subtree_ = hide; + NoteLayerPropertyChangedForSubtree(); +} + void LayerImpl::SetAnchorPoint(gfx::PointF anchor_point) { if (anchor_point_ == anchor_point) return; diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index c1f6eff..3f2cae2 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h @@ -134,6 +134,9 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver { void SetDrawsContent(bool draws_content); bool DrawsContent() const { return draws_content_; } + void SetHideLayerAndSubtree(bool hide); + bool hide_layer_and_subtree() const { return hide_layer_and_subtree_; } + bool force_render_surface() const { return force_render_surface_; } void SetForceRenderSurface(bool force) { force_render_surface_ = force; } @@ -513,6 +516,7 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver { gfx::Transform transform_; bool draws_content_; + bool hide_layer_and_subtree_; bool force_render_surface_; // Set for the layer that other layers are fixed to. diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc index dc1b29b..cc5e35d 100644 --- a/cc/layers/layer_impl_unittest.cc +++ b/cc/layers/layer_impl_unittest.cc @@ -131,6 +131,7 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->ScrollBy(arbitrary_vector2d)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetScrollDelta(gfx::Vector2d())); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetScrollOffset(arbitrary_vector2d)); + EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetHideLayerAndSubtree(true)); // Changing these properties only affects the layer itself. EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->SetContentBounds(arbitrary_size)); diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc index daf4589..bfbf15e 100644 --- a/cc/layers/layer_unittest.cc +++ b/cc/layers/layer_unittest.cc @@ -528,6 +528,7 @@ TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) { EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetDrawCheckerboardForMissingTiles( !test_layer->DrawCheckerboardForMissingTiles())); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetForceRenderSurface(true)); + EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetHideLayerAndSubtree(true)); EXPECT_SET_NEEDS_FULL_TREE_SYNC(1, test_layer->SetMaskLayer( dummy_layer1.get())); diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index 2e3d840..f4c64f9 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc @@ -232,6 +232,10 @@ static bool LayerShouldBeSkipped(LayerType* layer) { } static inline bool SubtreeShouldBeSkipped(LayerImpl* layer) { + // The embedder can request to hide the entire layer's subtree. + if (layer->hide_layer_and_subtree()) + return true; + // If layer is on the pending tree and opacity is being animated then // this subtree can't be skipped as we need to create, prioritize and // include tiles for this layer when deciding if tree can be activated. @@ -245,6 +249,10 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer) { } static inline bool SubtreeShouldBeSkipped(Layer* layer) { + // The embedder can request to hide the entire layer's subtree. + if (layer->hide_layer_and_subtree()) + return true; + // If the opacity is being animated then the opacity on the main thread is // unreliable (since the impl thread may be using a different opacity), so it // should not be trusted. @@ -1491,6 +1499,7 @@ static void CalculateDrawPropertiesInternal( } UpdateTilePrioritiesForLayer(layer); + SavePaintPropertiesLayer(layer); // If neither this layer nor any of its children were added, early out. if (sorting_start_index == descendants.size()) @@ -1518,8 +1527,6 @@ static void CalculateDrawPropertiesInternal( layer->render_target()->render_surface()-> AddContributingDelegatedRenderPassLayer(layer); } - - SavePaintPropertiesLayer(layer); } void LayerTreeHostCommon::CalculateDrawProperties( diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 850768e..793d5da 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc @@ -7733,7 +7733,7 @@ TEST(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) { root->AddChild(child.Pass()); - std::vector<LayerImpl*> render_surface_layer_list; + LayerImplList render_surface_layer_list; int dummy_max_texture_size = 512; LayerTreeHostCommon::CalculateDrawProperties(root.get(), root->bounds(), @@ -7900,5 +7900,249 @@ INSTANTIATE_TEST_CASE_P(LayerTreeHostCommonTest, LCDTextTest, testing::Combine(testing::Bool(), testing::Bool())); +TEST(LayerTreeHostCommonTest, SubtreeHidden_SingleLayer) { + FakeImplProxy proxy; + FakeLayerTreeHostImpl host_impl(&proxy); + host_impl.CreatePendingTree(); + const gfx::Transform identity_matrix; + + scoped_refptr<Layer> root = Layer::Create(); + SetLayerPropertiesForTesting(root.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(50, 50), + false); + root->SetIsDrawable(true); + + scoped_refptr<Layer> child = Layer::Create(); + SetLayerPropertiesForTesting(child.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(40, 40), + false); + child->SetIsDrawable(true); + + scoped_refptr<Layer> grand_child = Layer::Create(); + SetLayerPropertiesForTesting(grand_child.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(30, 30), + false); + grand_child->SetIsDrawable(true); + grand_child->SetHideLayerAndSubtree(true); + + child->AddChild(grand_child); + root->AddChild(child); + + LayerList render_surface_layer_list; + int dummy_max_texture_size = 512; + LayerTreeHostCommon::CalculateDrawProperties(root.get(), + root->bounds(), + gfx::Transform(), + 1.f, + 1.f, + NULL, + dummy_max_texture_size, + false, + true, // can_adjust_raster_scale + &render_surface_layer_list); + + // We should have one render surface and two layers. The grand child has + // hidden itself. + ASSERT_EQ(1u, render_surface_layer_list.size()); + ASSERT_EQ(2u, root->render_surface()->layer_list().size()); + EXPECT_EQ(root->id(), root->render_surface()->layer_list()[0]->id()); + EXPECT_EQ(child->id(), root->render_surface()->layer_list()[1]->id()); +} + +TEST(LayerTreeHostCommonTest, SubtreeHidden_SingleLayerImpl) { + FakeImplProxy proxy; + FakeLayerTreeHostImpl host_impl(&proxy); + host_impl.CreatePendingTree(); + const gfx::Transform identity_matrix; + + scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.pending_tree(), 1); + SetLayerPropertiesForTesting(root.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(50, 50), + false); + root->SetDrawsContent(true); + + scoped_ptr<LayerImpl> child = LayerImpl::Create(host_impl.pending_tree(), 2); + SetLayerPropertiesForTesting(child.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(40, 40), + false); + child->SetDrawsContent(true); + + scoped_ptr<LayerImpl> grand_child = + LayerImpl::Create(host_impl.pending_tree(), 3); + SetLayerPropertiesForTesting(grand_child.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(30, 30), + false); + grand_child->SetDrawsContent(true); + grand_child->SetHideLayerAndSubtree(true); + + child->AddChild(grand_child.Pass()); + root->AddChild(child.Pass()); + + LayerImplList render_surface_layer_list; + int dummy_max_texture_size = 512; + LayerTreeHostCommon::CalculateDrawProperties(root.get(), + root->bounds(), + gfx::Transform(), + 1.f, + 1.f, + NULL, + dummy_max_texture_size, + false, + true, // can_adjust_raster_scale + &render_surface_layer_list); + + // We should have one render surface and two layers. The grand child has + // hidden itself. + ASSERT_EQ(1u, render_surface_layer_list.size()); + ASSERT_EQ(2u, root->render_surface()->layer_list().size()); + EXPECT_EQ(1, root->render_surface()->layer_list()[0]->id()); + EXPECT_EQ(2, root->render_surface()->layer_list()[1]->id()); +} + +TEST(LayerTreeHostCommonTest, SubtreeHidden_TwoLayers) { + FakeImplProxy proxy; + FakeLayerTreeHostImpl host_impl(&proxy); + host_impl.CreatePendingTree(); + const gfx::Transform identity_matrix; + + scoped_refptr<Layer> root = Layer::Create(); + SetLayerPropertiesForTesting(root.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(50, 50), + false); + root->SetIsDrawable(true); + + scoped_refptr<Layer> child = Layer::Create(); + SetLayerPropertiesForTesting(child.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(40, 40), + false); + child->SetIsDrawable(true); + child->SetHideLayerAndSubtree(true); + + scoped_refptr<Layer> grand_child = Layer::Create(); + SetLayerPropertiesForTesting(grand_child.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(30, 30), + false); + grand_child->SetIsDrawable(true); + + child->AddChild(grand_child); + root->AddChild(child); + + LayerList render_surface_layer_list; + int dummy_max_texture_size = 512; + LayerTreeHostCommon::CalculateDrawProperties(root.get(), + root->bounds(), + gfx::Transform(), + 1.f, + 1.f, + NULL, + dummy_max_texture_size, + false, + true, // can_adjust_raster_scale + &render_surface_layer_list); + + // We should have one render surface and one layers. The child has + // hidden itself and the grand child. + ASSERT_EQ(1u, render_surface_layer_list.size()); + ASSERT_EQ(1u, root->render_surface()->layer_list().size()); + EXPECT_EQ(root->id(), root->render_surface()->layer_list()[0]->id()); +} + +TEST(LayerTreeHostCommonTest, SubtreeHidden_TwoLayersImpl) { + FakeImplProxy proxy; + FakeLayerTreeHostImpl host_impl(&proxy); + host_impl.CreatePendingTree(); + const gfx::Transform identity_matrix; + + scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.pending_tree(), 1); + SetLayerPropertiesForTesting(root.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(50, 50), + false); + root->SetDrawsContent(true); + + scoped_ptr<LayerImpl> child = LayerImpl::Create(host_impl.pending_tree(), 2); + SetLayerPropertiesForTesting(child.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(40, 40), + false); + child->SetDrawsContent(true); + child->SetHideLayerAndSubtree(true); + + scoped_ptr<LayerImpl> grand_child = + LayerImpl::Create(host_impl.pending_tree(), 3); + SetLayerPropertiesForTesting(grand_child.get(), + identity_matrix, + identity_matrix, + gfx::PointF(), + gfx::PointF(), + gfx::Size(30, 30), + false); + grand_child->SetDrawsContent(true); + + child->AddChild(grand_child.Pass()); + root->AddChild(child.Pass()); + + LayerImplList render_surface_layer_list; + int dummy_max_texture_size = 512; + LayerTreeHostCommon::CalculateDrawProperties(root.get(), + root->bounds(), + gfx::Transform(), + 1.f, + 1.f, + NULL, + dummy_max_texture_size, + false, + true, // can_adjust_raster_scale + &render_surface_layer_list); + + // We should have one render surface and one layers. The child has + // hidden itself and the grand child. + ASSERT_EQ(1u, render_surface_layer_list.size()); + ASSERT_EQ(1u, root->render_surface()->layer_list().size()); + EXPECT_EQ(1, root->render_surface()->layer_list()[0]->id()); +} + } // namespace } // namespace cc diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index ed6dd2c..66deed9 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -161,6 +161,99 @@ class LayerTreeHostTestSetNeedsCommit2 : public LayerTreeHostTest { MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsCommit2); +// Verify that we pass property values in PushPropertiesTo. +class LayerTreeHostTestPushPropertiesTo : public LayerTreeHostTest { + protected: + virtual void SetupTree() OVERRIDE { + scoped_refptr<Layer> root = Layer::Create(); + root->SetBounds(gfx::Size(10, 10)); + layer_tree_host()->SetRootLayer(root); + LayerTreeHostTest::SetupTree(); + } + + enum Properties { + STARTUP, + BOUNDS, + HIDE_LAYER_AND_SUBTREE, + DRAWS_CONTENT, + DONE, + }; + + virtual void BeginTest() OVERRIDE { + index_ = STARTUP; + PostSetNeedsCommitToMainThread(); + } + + virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE { + VerifyAfterValues(impl->active_tree()->root_layer()); + } + + virtual void DidCommitAndDrawFrame() OVERRIDE { + SetBeforeValues(layer_tree_host()->root_layer()); + VerifyBeforeValues(layer_tree_host()->root_layer()); + + ++index_; + if (index_ == DONE) { + EndTest(); + return; + } + + SetAfterValues(layer_tree_host()->root_layer()); + } + + virtual void AfterTest() OVERRIDE {} + + void VerifyBeforeValues(Layer* layer) { + EXPECT_EQ(gfx::Size(10, 10).ToString(), layer->bounds().ToString()); + EXPECT_FALSE(layer->hide_layer_and_subtree()); + EXPECT_FALSE(layer->DrawsContent()); + } + + void SetBeforeValues(Layer* layer) { + layer->SetBounds(gfx::Size(10, 10)); + layer->SetHideLayerAndSubtree(false); + layer->SetIsDrawable(false); + } + + void VerifyAfterValues(LayerImpl* layer) { + switch (static_cast<Properties>(index_)) { + case STARTUP: + case DONE: + break; + case BOUNDS: + EXPECT_EQ(gfx::Size(20, 20).ToString(), layer->bounds().ToString()); + break; + case HIDE_LAYER_AND_SUBTREE: + EXPECT_TRUE(layer->hide_layer_and_subtree()); + break; + case DRAWS_CONTENT: + EXPECT_TRUE(layer->DrawsContent()); + break; + } + } + + void SetAfterValues(Layer* layer) { + switch (static_cast<Properties>(index_)) { + case STARTUP: + case DONE: + break; + case BOUNDS: + layer->SetBounds(gfx::Size(20, 20)); + break; + case HIDE_LAYER_AND_SUBTREE: + layer->SetHideLayerAndSubtree(true); + break; + case DRAWS_CONTENT: + layer->SetIsDrawable(true); + break; + } + } + + int index_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPushPropertiesTo); + // 1 setNeedsRedraw after the first commit has completed should lead to 1 // additional draw. class LayerTreeHostTestSetNeedsRedraw : public LayerTreeHostTest { |