diff options
-rw-r--r-- | cc/layers/layer.cc | 1 | ||||
-rw-r--r-- | cc/layers/layer_impl.cc | 46 | ||||
-rw-r--r-- | cc/layers/layer_impl.h | 3 | ||||
-rw-r--r-- | cc/layers/layer_impl_unittest.cc | 30 | ||||
-rw-r--r-- | cc/layers/layer_unittest.cc | 49 | ||||
-rw-r--r-- | cc/proto/property_tree.proto | 6 | ||||
-rw-r--r-- | cc/tiles/tile_manager_unittest.cc | 2 | ||||
-rw-r--r-- | cc/trees/damage_tracker_unittest.cc | 92 | ||||
-rw-r--r-- | cc/trees/layer_tree_host.cc | 18 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.cc | 25 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl_unittest.cc | 11 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest.cc | 35 | ||||
-rw-r--r-- | cc/trees/property_tree.cc | 39 | ||||
-rw-r--r-- | cc/trees/property_tree.h | 13 |
14 files changed, 282 insertions, 88 deletions
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index b4fec7a..3842741 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc @@ -533,6 +533,7 @@ void Layer::SetOpacity(float opacity) { if (opacity_ == opacity) return; opacity_ = opacity; + SetSubtreePropertyChanged(); SetNeedsCommit(); } diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 4066816..ae14d9c 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc @@ -689,10 +689,19 @@ base::DictionaryValue* LayerImpl::LayerTreeAsJson() const { bool LayerImpl::LayerPropertyChanged() const { if (layer_property_changed_) return true; - TransformNode* node = + if (transform_tree_index() == -1) + return false; + TransformNode* transform_node = layer_tree_impl()->property_trees()->transform_tree.Node( transform_tree_index()); - if (node && node->data.transform_changed) + if (transform_node && transform_node->data.transform_changed) + return true; + if (effect_tree_index() == -1) + return false; + EffectNode* effect_node = + layer_tree_impl()->property_trees()->effect_tree.Node( + effect_tree_index()); + if (effect_node && effect_node->data.opacity_changed) return true; return false; } @@ -724,6 +733,26 @@ void LayerImpl::NoteLayerPropertyChangedForDescendants() { SetNeedsPushProperties(); } +void LayerImpl::PushLayerPropertyChangedForSubtreeInternal() { + if (LayerPropertyChanged()) + NoteLayerPropertyChanged(); + for (size_t i = 0; i < children_.size(); ++i) + children_[i]->PushLayerPropertyChangedForSubtreeInternal(); +} + +void LayerImpl::PushLayerPropertyChangedForSubtree() { + // We need to update property trees first as layer property can change + // when its corresponsing property tree node changes. + PropertyTrees* property_trees = layer_tree_impl()->property_trees(); + EffectTree effect_tree = property_trees->effect_tree; + for (int i = 1; i < static_cast<int>(effect_tree.size()); ++i) { + EffectNode* node = effect_tree.Node(i); + EffectNode* parent_node = effect_tree.parent(node); + property_trees->effect_tree.UpdateOpacityChanged(node, parent_node); + } + PushLayerPropertyChangedForSubtreeInternal(); +} + void LayerImpl::ValidateQuadResourcesInternal(DrawQuad* quad) const { #if DCHECK_IS_ON() const ResourceProvider* resource_provider = @@ -854,9 +883,12 @@ void LayerImpl::UpdatePropertyTreeOpacity() { // corresponding Layer at the time of the last commit. For example, an // opacity animation might have been in progress at the time the last commit // started, but might have finished since then on the compositor thread. - if (node->owner_id != id()) + float effective_opacity = EffectiveOpacity(); + if (node->owner_id != id() || node->data.opacity == effective_opacity) return; - node->data.opacity = EffectiveOpacity(); + node->data.opacity = effective_opacity; + node->data.opacity_changed = true; + layer_tree_impl()->property_trees()->changed = true; effect_tree.set_needs_update(true); } } @@ -887,8 +919,11 @@ void LayerImpl::OnOpacityAnimated(float opacity) { SetOpacity(opacity); // When hide_layer_and_subtree is true, the effective opacity is zero and we // need not update the opacity on property trees. - if (!hide_layer_and_subtree_) + if (!hide_layer_and_subtree_) { UpdatePropertyTreeOpacity(); + SetNeedsPushProperties(); + layer_tree_impl()->set_needs_update_draw_properties(); + } } void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) { @@ -1135,7 +1170,6 @@ void LayerImpl::SetOpacity(float opacity) { return; opacity_ = opacity; - NoteLayerPropertyChangedForSubtree(); } float LayerImpl::EffectiveOpacity() const { diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index 255f609..40bf810 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h @@ -685,6 +685,8 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, void NoteLayerPropertyChanged(); + void PushLayerPropertyChangedForSubtree(); + protected: LayerImpl(LayerTreeImpl* layer_impl, int id, @@ -718,6 +720,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, void PushScrollOffset(const gfx::ScrollOffset* scroll_offset); void DidUpdateScrollOffset(); void NoteLayerPropertyChangedForDescendantsInternal(); + void PushLayerPropertyChangedForSubtreeInternal(); virtual const char* LayerTypeAsString() const; diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc index 6813aea..1973144 100644 --- a/cc/layers/layer_impl_unittest.cc +++ b/cc/layers/layer_impl_unittest.cc @@ -26,14 +26,20 @@ namespace cc { namespace { -#define EXECUTE_AND_VERIFY_SUBTREE_CHANGED(code_to_test) \ - root->ResetAllChangeTrackingForSubtree(); \ - code_to_test; \ - EXPECT_TRUE(root->needs_push_properties()); \ - EXPECT_FALSE(child->needs_push_properties()); \ - EXPECT_FALSE(grand_child->needs_push_properties()); \ - EXPECT_TRUE(root->LayerPropertyChanged()); \ - EXPECT_TRUE(child->LayerPropertyChanged()); \ +#define EXECUTE_AND_VERIFY_SUBTREE_CHANGED(code_to_test) \ + root->ResetAllChangeTrackingForSubtree(); \ + root->layer_tree_impl() \ + ->property_trees() \ + ->transform_tree.ResetChangeTracking(); \ + root->layer_tree_impl() \ + ->property_trees() \ + ->effect_tree.ResetChangeTracking(); \ + code_to_test; \ + EXPECT_TRUE(root->needs_push_properties()); \ + EXPECT_FALSE(child->needs_push_properties()); \ + EXPECT_FALSE(grand_child->needs_push_properties()); \ + EXPECT_TRUE(root->LayerPropertyChanged()); \ + EXPECT_TRUE(child->LayerPropertyChanged()); \ EXPECT_TRUE(grand_child->LayerPropertyChanged()); #define EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(code_to_test) \ @@ -113,7 +119,7 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { std::set<LayerImpl*>* scroll_children = new std::set<LayerImpl*>(); scroll_children->insert(scroll_child); scroll_children->insert(root); - root->SetHasRenderSurface(true); + root->SetForceRenderSurface(true); scoped_ptr<LayerImpl> clip_parent = LayerImpl::Create(host_impl.active_tree(), 5); @@ -121,6 +127,7 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { std::set<LayerImpl*>* clip_children = new std::set<LayerImpl*>(); clip_children->insert(clip_child); clip_children->insert(root); + root->ResetAllChangeTrackingForSubtree(); root->AddChild(LayerImpl::Create(host_impl.active_tree(), 7)); LayerImpl* child = root->children()[0].get(); @@ -167,7 +174,7 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetScrollDelta(gfx::Vector2d())); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->PushScrollOffsetFromMainThread( gfx::ScrollOffset(arbitrary_vector2d))); - EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetOpacity(arbitrary_number)); + EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->OnOpacityAnimated(arbitrary_number)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetTransform(arbitrary_transform)); // Changing these properties only affects the layer itself. @@ -349,7 +356,8 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { layer->SetBackgroundColor(arbitrary_color)); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( layer->SetBackgroundFilters(arbitrary_filters)); - VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetOpacity(arbitrary_number)); + VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( + layer->OnOpacityAnimated(arbitrary_number)); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetBlendMode(arbitrary_blend_mode); layer->NoteLayerPropertyChanged()); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetTransform(arbitrary_transform)); diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc index b393af3..7631e0f 100644 --- a/cc/layers/layer_unittest.cc +++ b/cc/layers/layer_unittest.cc @@ -1721,55 +1721,6 @@ TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForOpacity) { } TEST_F(LayerTest, - PushPropsDoesntCauseLayerPropertyChangedDuringImplOnlyOpacityAnim) { - scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); - scoped_ptr<LayerImpl> impl_layer = - LayerImpl::Create(host_impl_.active_tree(), 1); - - EXPECT_SET_NEEDS_FULL_TREE_SYNC(1, - layer_tree_host_->SetRootLayer(test_layer)); - - scoped_ptr<AnimationRegistrar> registrar; - if (settings().use_compositor_animation_timelines) { - AddOpacityTransitionToLayerWithPlayer(impl_layer->id(), timeline_impl(), - 1.0, 0.3f, 0.7f, false); - } else { - registrar = AnimationRegistrar::Create(); - impl_layer->layer_animation_controller()->SetAnimationRegistrar( - registrar.get()); - - AddOpacityTransitionToController(impl_layer->layer_animation_controller(), - 1.0, 0.3f, 0.7f, false); - } - - EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetOpacity(0.5f)); - - EXPECT_FALSE(impl_layer->LayerPropertyChanged()); - test_layer->PushPropertiesTo(impl_layer.get()); - EXPECT_TRUE(impl_layer->LayerPropertyChanged()); - - impl_layer->ResetAllChangeTrackingForSubtree(); - if (settings().use_compositor_animation_timelines) { - int animation_id = AddOpacityTransitionToLayerWithPlayer( - impl_layer->id(), timeline_impl(), 1.0, 0.3f, 0.7f, false); - GetAnimationFromLayerWithExistingPlayer(impl_layer->id(), timeline_impl(), - animation_id) - ->set_is_impl_only(true); - } else { - AddOpacityTransitionToController(impl_layer->layer_animation_controller(), - 1.0, 0.3f, 0.7f, false); - impl_layer->layer_animation_controller() - ->GetAnimation(TargetProperty::OPACITY) - ->set_is_impl_only(true); - } - EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetOpacity(0.75f)); - - EXPECT_FALSE(impl_layer->LayerPropertyChanged()); - test_layer->PushPropertiesTo(impl_layer.get()); - EXPECT_FALSE(impl_layer->LayerPropertyChanged()); -} - -TEST_F(LayerTest, PushPropsDoesntCauseLayerPropertyChangedDuringImplOnlyFilterAnim) { scoped_refptr<Layer> test_layer = Layer::Create(layer_settings_); scoped_ptr<LayerImpl> impl_layer = diff --git a/cc/proto/property_tree.proto b/cc/proto/property_tree.proto index bae0efa..77f30f2 100644 --- a/cc/proto/property_tree.proto +++ b/cc/proto/property_tree.proto @@ -82,7 +82,7 @@ message ClipNodeData { } // Proto for struct EffectNodeData. -// NEXT ID: 11 +// NEXT ID: 12 message EffectNodeData { optional float opacity = 1; optional float screen_space_opacity = 2; @@ -91,6 +91,7 @@ message EffectNodeData { optional bool has_background_filters = 5; optional bool is_drawn = 6; optional bool has_animated_opacity = 7; + optional bool opacity_changed = 11; optional int64 num_copy_requests_in_subtree = 8; optional int64 transform_id = 9; optional int64 clip_id = 10; @@ -173,7 +174,7 @@ message TransformTreeData { } // Proto for class PropertyTrees. -// NEXT ID: 11 +// NEXT ID: 12 message PropertyTrees { optional PropertyTree transform_tree = 1; optional PropertyTree effect_tree = 2; @@ -182,6 +183,7 @@ message PropertyTrees { optional bool needs_rebuild = 4; optional bool non_root_surfaces_enabled = 5; + optional bool changed = 11; optional int64 sequence_number = 6; optional Vector2dF inner_viewport_container_bounds_delta = 8; diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc index 355fd04..3dd1453 100644 --- a/cc/tiles/tile_manager_unittest.cc +++ b/cc/tiles/tile_manager_unittest.cc @@ -967,7 +967,7 @@ TEST_F(TileManagerTilePriorityQueueTest, host_impl_.pending_tree()->BuildPropertyTreesForTesting(); host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); - pending_child_layer->SetOpacity(0.0); + pending_child_layer->OnOpacityAnimated(0.0); host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1)); host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text); diff --git a/cc/trees/damage_tracker_unittest.cc b/cc/trees/damage_tracker_unittest.cc index 0be6a68..52b6e0c 100644 --- a/cc/trees/damage_tracker_unittest.cc +++ b/cc/trees/damage_tracker_unittest.cc @@ -52,7 +52,6 @@ void ClearDamageForAllSurfaces(LayerImpl* layer) { } void EmulateDrawingOneFrame(LayerImpl* root) { - root->layer_tree_impl()->property_trees()->needs_rebuild = true; // This emulates only steps that are relevant to testing the damage tracker: // 1. computing the render passes and layerlists // 2. updating all damage trackers in the correct order @@ -78,6 +77,10 @@ void EmulateDrawingOneFrame(LayerImpl* root) { } root->ResetAllChangeTrackingForSubtree(); + root->layer_tree_impl() + ->property_trees() + ->transform_tree.ResetChangeTracking(); + root->layer_tree_impl()->property_trees()->effect_tree.ResetChangeTracking(); } class DamageTrackerTest : public testing::Test { @@ -160,6 +163,7 @@ class DamageTrackerTest : public testing::Test { // Setup includes going past the first frame which always damages // everything, so that we can actually perform specific tests. + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); return root; @@ -170,6 +174,7 @@ class DamageTrackerTest : public testing::Test { // Setup includes going past the first frame which always damages // everything, so that we can actually perform specific tests. + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); return root; @@ -231,6 +236,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForUpdateRects) { // the surface. ClearDamageForAllSurfaces(root.get()); child->SetUpdateRect(gfx::Rect(10, 11, 12, 13)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Damage position on the surface should be: position of update_rect (10, 11) @@ -244,6 +250,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForUpdateRects) { // damage. ClearDamageForAllSurfaces(root.get()); child->SetUpdateRect(gfx::Rect(10, 11, 12, 13)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -254,6 +261,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForUpdateRects) { // update region, but no additional exposed old region. ClearDamageForAllSurfaces(root.get()); child->SetUpdateRect(gfx::Rect(20, 25, 1, 2)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Damage position on the surface should be: position of update_rect (20, 25) @@ -271,6 +279,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) { // to the surface. ClearDamageForAllSurfaces(root.get()); child->AddDamageRect(gfx::Rect(10, 11, 12, 13)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Damage position on the surface should be: position of layer damage_rect @@ -283,6 +292,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) { // damage. ClearDamageForAllSurfaces(root.get()); child->AddDamageRect(gfx::Rect(10, 11, 12, 13)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -292,6 +302,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) { // new damaged region, but no additional exposed old region. ClearDamageForAllSurfaces(root.get()); child->AddDamageRect(gfx::Rect(20, 25, 1, 2)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Damage position on the surface should be: position of layer damage_rect @@ -305,6 +316,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) { ClearDamageForAllSurfaces(root.get()); child->AddDamageRect(gfx::Rect(20, 25, 1, 2)); child->AddDamageRect(gfx::Rect(10, 15, 3, 4)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Damage position on the surface should be: position of layer damage_rect @@ -324,6 +336,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerUpdateAndDamageRects) { ClearDamageForAllSurfaces(root.get()); child->AddDamageRect(gfx::Rect(5, 6, 12, 13)); child->SetUpdateRect(gfx::Rect(15, 16, 14, 10)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Damage position on the surface should be: position of unified layer @@ -338,6 +351,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerUpdateAndDamageRects) { ClearDamageForAllSurfaces(root.get()); child->AddDamageRect(gfx::Rect(10, 11, 12, 13)); child->SetUpdateRect(gfx::Rect(10, 11, 14, 15)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -348,6 +362,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerUpdateAndDamageRects) { ClearDamageForAllSurfaces(root.get()); child->AddDamageRect(gfx::Rect(20, 25, 2, 3)); child->SetUpdateRect(gfx::Rect(5, 10, 7, 8)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Damage position on the surface should be: position of unified layer damage @@ -363,14 +378,14 @@ TEST_F(DamageTrackerTest, VerifyDamageForPropertyChanges) { // CASE 1: The layer's property changed flag takes priority over update rect. // + child->SetForceRenderSurface(true); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; + EmulateDrawingOneFrame(root.get()); ClearDamageForAllSurfaces(root.get()); child->SetUpdateRect(gfx::Rect(10, 11, 12, 13)); - child->SetOpacity(0.5f); + child->OnOpacityAnimated(0.5f); EmulateDrawingOneFrame(root.get()); - // Sanity check - we should not have accidentally created a separate render - // surface for the translucent layer. - ASSERT_FALSE(child->render_surface()); ASSERT_EQ(2u, root->render_surface()->layer_list().size()); // Damage should be the entire child layer in target_surface space. @@ -386,6 +401,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForPropertyChanges) { // Cycle one frame of no change, just to sanity check that the next rect is // not because of the old damage state. ClearDamageForAllSurfaces(root.get()); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -395,6 +411,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForPropertyChanges) { ClearDamageForAllSurfaces(root.get()); child->SetPosition(gfx::PointF(200.f, 230.f)); child->NoteLayerPropertyChanged(); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Expect damage to be the combination of the previous one and the new one. @@ -419,6 +436,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForTransformedLayer) { child->bounds().width() * 0.5f, child->bounds().height() * 0.5f, 0.f)); child->SetPosition(gfx::PointF(85.f, 85.f)); child->NoteLayerPropertyChanged(); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Sanity check that the layer actually moved to (85, 85), damaging its old @@ -431,6 +449,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForTransformedLayer) { // intuitively, since it applies about the layer's anchor. ClearDamageForAllSurfaces(root.get()); child->SetTransform(rotation); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Since the child layer is square, rotation by 45 degrees about the center @@ -472,6 +491,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForPerspectiveClippedLayer) { child->SetPosition(gfx::PointF(0.f, 0.f)); child->SetBounds(gfx::Size(100, 100)); child->SetTransform(transform); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Sanity check that the child layer's bounds would actually get clipped by @@ -482,8 +502,11 @@ TEST_F(DamageTrackerTest, VerifyDamageForPerspectiveClippedLayer) { EXPECT_TRUE(clipped); // Damage the child without moving it. + child->SetForceRenderSurface(true); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; + EmulateDrawingOneFrame(root.get()); ClearDamageForAllSurfaces(root.get()); - child->SetOpacity(0.5f); + child->OnOpacityAnimated(0.5f); EmulateDrawingOneFrame(root.get()); // The expected damage should cover the entire root surface (500x500), but we @@ -508,12 +531,14 @@ TEST_F(DamageTrackerTest, VerifyDamageForBlurredSurface) { // Setting the filter will damage the whole surface. ClearDamageForAllSurfaces(root.get()); surface->SetFilters(filters); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Setting the update rect should cause the corresponding damage to the // surface, blurred based on the size of the blur filter. ClearDamageForAllSurfaces(root.get()); child->SetUpdateRect(gfx::Rect(1, 2, 3, 4)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Damage position on the surface should be: position of update_rect (1, 2) @@ -548,6 +573,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) { ClearDamageForAllSurfaces(root.get()); child->SetForceRenderSurface(true); child->SetFilters(filters); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -564,6 +590,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) { // CASE 1: Setting the update rect should damage the whole surface (for now) ClearDamageForAllSurfaces(root.get()); child->SetUpdateRect(gfx::Rect(1, 1)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = @@ -598,6 +625,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) { // Setting the filter will damage the whole surface. ClearDamageForAllSurfaces(root.get()); child1->SetBackgroundFilters(filters); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // CASE 1: Setting the update rect should cause the corresponding damage to @@ -605,6 +633,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) { // blur filter. ClearDamageForAllSurfaces(root.get()); root->SetUpdateRect(gfx::Rect(297, 297, 2, 2)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); gfx::Rect root_damage_rect = @@ -626,6 +655,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) { // of the blurred layer, only the left/top should end up expanded. ClearDamageForAllSurfaces(root.get()); root->SetUpdateRect(gfx::Rect(297, 297, 30, 30)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = @@ -645,6 +675,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) { // blurred child1 will not cause it to be expanded. ClearDamageForAllSurfaces(root.get()); root->SetUpdateRect(gfx::Rect(30, 30, 2, 2)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = @@ -660,6 +691,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) { // cause it to be expanded. ClearDamageForAllSurfaces(root.get()); root->SetUpdateRect(gfx::Rect(99, 99, 1, 1)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = @@ -679,6 +711,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) { // not get blurred by child1, so it does not need to get expanded. ClearDamageForAllSurfaces(root.get()); child2->SetUpdateRect(gfx::Rect(1, 1)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = @@ -694,6 +727,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) { // frame. ClearDamageForAllSurfaces(root.get()); child1->SetUpdateRect(gfx::Rect(1, 1)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = @@ -724,6 +758,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingLayer) { child2->SetDrawsContent(true); root->AddChild(std::move(child2)); } + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Sanity check - all 3 layers should be on the same render surface; render @@ -740,6 +775,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingLayer) { // Advance one frame without damage so that we know the damage rect is not // leftover from the previous case. ClearDamageForAllSurfaces(root.get()); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = @@ -749,6 +785,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingLayer) { // Then, test removing child1. root->RemoveChild(child1); child1 = NULL; + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = @@ -778,6 +815,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForNewUnchangedLayer) { ASSERT_TRUE(child2->update_rect().IsEmpty()); root->AddChild(std::move(child2)); } + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Sanity check - all 3 layers should be on the same render surface; render @@ -805,6 +843,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForMultipleLayers) { root->AddChild(std::move(child2)); } LayerImpl* child2 = root->children()[1].get(); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Damaging two layers simultaneously should cause combined damage. @@ -813,6 +852,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForMultipleLayers) { ClearDamageForAllSurfaces(root.get()); child1->SetUpdateRect(gfx::Rect(1, 2)); child2->SetUpdateRect(gfx::Rect(3, 4)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); gfx::Rect root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -825,13 +865,17 @@ TEST_F(DamageTrackerTest, VerifyDamageForNestedSurfaces) { LayerImpl* child1 = root->children()[0].get(); LayerImpl* child2 = root->children()[1].get(); LayerImpl* grand_child1 = root->children()[0]->children()[0].get(); + child2->SetForceRenderSurface(true); + grand_child1->SetForceRenderSurface(true); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; + EmulateDrawingOneFrame(root.get()); gfx::Rect child_damage_rect; gfx::Rect root_damage_rect; // CASE 1: Damage to a descendant surface should propagate properly to // ancestor surface. ClearDamageForAllSurfaces(root.get()); - grand_child1->SetOpacity(0.5f); + grand_child1->OnOpacityAnimated(0.5f); EmulateDrawingOneFrame(root.get()); child_damage_rect = child1->render_surface()->damage_tracker()->current_damage_rect(); @@ -847,8 +891,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForNestedSurfaces) { // - child2 damage in root surface space: // gfx::Rect(11, 11, 18, 18); ClearDamageForAllSurfaces(root.get()); - grand_child1->SetOpacity(0.7f); - child2->SetOpacity(0.7f); + grand_child1->OnOpacityAnimated(0.7f); + child2->OnOpacityAnimated(0.7f); EmulateDrawingOneFrame(root.get()); child_damage_rect = child1->render_surface()->damage_tracker()->current_damage_rect(); @@ -875,6 +919,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromDescendantLayer) { ClearDamageForAllSurfaces(root.get()); grand_child1->SetPosition(gfx::PointF(195.f, 205.f)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); child_damage_rect = child1->render_surface()->damage_tracker()->current_damage_rect(); @@ -917,6 +962,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromAncestorLayer) { child1->NoteLayerPropertyChanged(); grand_child1->NoteLayerPropertyChanged(); grand_child2->NoteLayerPropertyChanged(); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); child_damage_rect = child1->render_surface()->damage_tracker()->current_damage_rect(); @@ -945,6 +991,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingRenderSurfaces) { // exposed. ClearDamageForAllSurfaces(root.get()); child1->SetForceRenderSurface(false); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Sanity check that there is only one surface now. @@ -962,6 +1009,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingRenderSurfaces) { // Cycle one frame of no change, just to sanity check that the next rect is // not because of the old damage state. ClearDamageForAllSurfaces(root.get()); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -971,6 +1019,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingRenderSurfaces) { ClearDamageForAllSurfaces(root.get()); child1->SetForceRenderSurface(true); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Sanity check that there is a new surface now. @@ -997,6 +1046,7 @@ TEST_F(DamageTrackerTest, VerifyNoDamageWhenNothingChanged) { // CASE 1: If nothing changes, the damage rect should be empty. // ClearDamageForAllSurfaces(root.get()); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); child_damage_rect = child1->render_surface()->damage_tracker()->current_damage_rect(); @@ -1009,6 +1059,7 @@ TEST_F(DamageTrackerTest, VerifyNoDamageWhenNothingChanged) { // empty. // ClearDamageForAllSurfaces(root.get()); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); child_damage_rect = child1->render_surface()->damage_tracker()->current_damage_rect(); @@ -1028,6 +1079,7 @@ TEST_F(DamageTrackerTest, VerifyNoDamageForUpdateRectThatDoesNotDrawContent) { // damage to any surface because it does not actually draw content. ClearDamageForAllSurfaces(root.get()); child1->SetUpdateRect(gfx::Rect(1, 2)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); child_damage_rect = child1->render_surface()->damage_tracker()->current_damage_rect(); @@ -1059,6 +1111,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplica) { child1->AddChild(std::move(grand_child3)); } child1->SetOpacity(0.5f); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // CASE 1: adding a reflection about the left edge of grand_child1. @@ -1074,6 +1127,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplica) { grand_child1->SetReplicaLayer(std::move(grand_child1_replica)); grand_child1->SetForceRenderSurface(true); } + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); gfx::Rect grand_child_damage_rect = @@ -1096,6 +1150,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplica) { gfx::Rect old_content_rect = child1->render_surface()->content_rect(); grand_child1->SetPosition(gfx::PointF(195.f, 205.f)); grand_child1->NoteLayerPropertyChanged(); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); ASSERT_EQ(old_content_rect.width(), child1->render_surface()->content_rect().width()); @@ -1125,6 +1180,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplica) { ClearDamageForAllSurfaces(root.get()); grand_child1->SetReplicaLayer(nullptr); grand_child1->SetForceRenderSurface(false); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); ASSERT_EQ(old_content_rect.width(), child1->render_surface()->content_rect().width()); @@ -1172,12 +1228,14 @@ TEST_F(DamageTrackerTest, VerifyDamageForMask) { grand_child->SetDrawsContent(true); child->AddChild(std::move(grand_child)); } + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // CASE 1: the update_rect on a mask layer should damage the entire target // surface. ClearDamageForAllSurfaces(root.get()); mask_layer->SetUpdateRect(gfx::Rect(1, 2, 3, 4)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); gfx::Rect child_damage_rect = child->render_surface()->damage_tracker()->current_damage_rect(); @@ -1189,6 +1247,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForMask) { // Advance one frame without damage so that we know the damage rect is not // leftover from the previous case. ClearDamageForAllSurfaces(root.get()); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); child_damage_rect = child->render_surface()->damage_tracker()->current_damage_rect(); @@ -1198,6 +1257,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForMask) { ClearDamageForAllSurfaces(root.get()); mask_layer->NoteLayerPropertyChanged(); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); child_damage_rect = child->render_surface()->damage_tracker()->current_damage_rect(); @@ -1209,6 +1269,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForMask) { // Advance one frame without damage so that we know the damage rect is not // leftover from the previous case. ClearDamageForAllSurfaces(root.get()); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); child_damage_rect = child->render_surface()->damage_tracker()->current_damage_rect(); @@ -1219,6 +1280,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForMask) { child->SetMaskLayer(nullptr); child->NoteLayerPropertyChanged(); ASSERT_TRUE(child->LayerPropertyChanged()); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Sanity check that a render surface still exists. @@ -1262,6 +1324,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplicaMask) { } LayerImpl* replica_mask_layer = grand_child1_replica->mask_layer(); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Sanity check that the appropriate render surfaces were created @@ -1271,6 +1334,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplicaMask) { // region on the target surface. ClearDamageForAllSurfaces(root.get()); replica_mask_layer->NoteLayerPropertyChanged(); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); gfx::Rect grand_child_damage_rect = @@ -1286,6 +1350,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplicaMask) { // ClearDamageForAllSurfaces(root.get()); grand_child1_replica->SetMaskLayer(nullptr); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); grand_child_damage_rect = @@ -1340,6 +1405,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplicaMaskWithTransformOrigin) { } LayerImpl* replica_mask_layer = grand_child1_replica->mask_layer(); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Sanity check that the appropriate render surfaces were created @@ -1350,6 +1416,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplicaMaskWithTransformOrigin) { ClearDamageForAllSurfaces(root.get()); replica_mask_layer->NoteLayerPropertyChanged(); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); gfx::Rect child_damage_rect = @@ -1368,6 +1435,7 @@ TEST_F(DamageTrackerTest, DamageWhenAddedExternally) { child->SetUpdateRect(gfx::Rect(10, 11, 12, 13)); root->render_surface()->damage_tracker()->AddDamageNextUpdate( gfx::Rect(15, 16, 32, 33)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); gfx::Rect root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -1381,6 +1449,7 @@ TEST_F(DamageTrackerTest, DamageWhenAddedExternally) { ClearDamageForAllSurfaces(root.get()); root->render_surface()->damage_tracker()->AddDamageNextUpdate( gfx::Rect(30, 31, 14, 15)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -1393,6 +1462,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForEmptyLayerList) { scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_.active_tree(), 1); root->SetForceRenderSurface(true); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root->draw_properties().render_target = root.get(); @@ -1421,6 +1491,7 @@ TEST_F(DamageTrackerTest, VerifyDamageAccumulatesUntilReset) { ClearDamageForAllSurfaces(root.get()); child->SetUpdateRect(gfx::Rect(10.f, 11.f, 1.f, 2.f)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // Sanity check damage after the first frame; this isnt the actual test yet. @@ -1431,6 +1502,7 @@ TEST_F(DamageTrackerTest, VerifyDamageAccumulatesUntilReset) { // New damage, without having cleared the previous damage, should be unioned // to the previous one. child->SetUpdateRect(gfx::Rect(20, 25, 1, 2)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -1446,6 +1518,7 @@ TEST_F(DamageTrackerTest, VerifyDamageAccumulatesUntilReset) { // Damage should remain empty even after one frame, since there's yet no new // damage. + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -1471,6 +1544,7 @@ TEST_F(DamageTrackerTest, HugeDamageRect) { child->SetPosition(gfx::PointF()); child->SetBounds(gfx::Size(kBigNumber + i, kBigNumber + i)); child->SetTransform(transform); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root.get()); // The expected damage should cover the visible part of the child layer, diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 2dff375..c940d22 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc @@ -426,6 +426,18 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) { sync_tree->RegisterSelection(selection_); + bool property_trees_changed_on_active_tree = + sync_tree->IsActiveTree() && sync_tree->property_trees()->changed; + // We need to preserve the damage status of property trees on active tree. We + // do this by pushing the damage status from active tree property trees to + // main thread property trees. + if (root_layer_ && property_trees_changed_on_active_tree) { + if (property_trees_.sequence_number == + sync_tree->property_trees()->sequence_number) + sync_tree->property_trees()->PushChangeTrackingTo(&property_trees_); + else + sync_tree->root_layer()->PushLayerPropertyChangedForSubtree(); + } // Setting property trees must happen before pushing the page scale. sync_tree->SetPropertyTrees(property_trees_); @@ -485,6 +497,12 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) { micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl); property_trees_.transform_tree.ResetChangeTracking(); + // We don't track changes to effect tree on main thread. But, to preserve any + // change tracking done on active tree's effect tree, we copy it to the main + // thread's effect tree before we push the main thread property trees to + // active tree. + if (property_trees_changed_on_active_tree) + property_trees_.effect_tree.ResetChangeTracking(); } void LayerTreeHost::WillCommit() { diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 165b067..12cc09c 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -1705,10 +1705,9 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame) { DidDrawDamagedArea(); } active_tree_->root_layer()->ResetAllChangeTrackingForSubtree(); - active_tree_->root_layer() - ->layer_tree_impl() - ->property_trees() - ->transform_tree.ResetChangeTracking(); + active_tree_->property_trees()->transform_tree.ResetChangeTracking(); + active_tree_->property_trees()->effect_tree.ResetChangeTracking(); + active_tree_->property_trees()->changed = false; active_tree_->set_has_ever_been_drawn(true); devtools_instrumentation::DidDrawFrame(id_); @@ -1993,14 +1992,24 @@ void LayerTreeHostImpl::ActivateSyncTree() { active_tree_->DetachLayerTree(), active_tree_.get())); } + // We need to preserve the damage status of property trees on active tree. + // We do this by pushing the damage status from active tree property trees + // to pending tree property trees. + if (active_tree_->property_trees()->changed) { + if (pending_tree_->property_trees()->sequence_number == + active_tree_->property_trees()->sequence_number) + active_tree_->property_trees()->PushChangeTrackingTo( + pending_tree_->property_trees()); + else + active_tree_->root_layer()->PushLayerPropertyChangedForSubtree(); + } TreeSynchronizer::PushProperties(pending_tree_->root_layer(), active_tree_->root_layer()); pending_tree_->PushPropertiesTo(active_tree_.get()); if (pending_tree_->root_layer()) { - pending_tree_->root_layer() - ->layer_tree_impl() - ->property_trees() - ->transform_tree.ResetChangeTracking(); + pending_tree_->property_trees()->transform_tree.ResetChangeTracking(); + pending_tree_->property_trees()->effect_tree.ResetChangeTracking(); + pending_tree_->property_trees()->changed = false; } // Now that we've synced everything from the pending tree to the active diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 2735eab..c44a851 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -5983,6 +5983,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // Layer with translucent opacity, drawn with blending. layer1->SetContentsOpaque(true); layer1->SetOpacity(0.5f); + layer1->NoteLayerPropertyChanged(); layer1->SetExpectation(true, false); layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); SetNeedsRebuildPropertyTrees(); @@ -5994,6 +5995,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // Layer with translucent opacity and painting, drawn with blending. layer1->SetContentsOpaque(true); layer1->SetOpacity(0.5f); + layer1->NoteLayerPropertyChanged(); layer1->SetExpectation(true, false); layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); SetNeedsRebuildPropertyTrees(); @@ -6013,10 +6015,12 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // 2 opaque layers, drawn without blending. layer1->SetContentsOpaque(true); layer1->SetOpacity(1.f); + layer1->NoteLayerPropertyChanged(); layer1->SetExpectation(false, false); layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetContentsOpaque(true); layer2->SetOpacity(1.f); + layer2->NoteLayerPropertyChanged(); layer2->SetExpectation(false, false); layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); SetNeedsRebuildPropertyTrees(); @@ -6062,6 +6066,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // carries the inherited opacity). layer1->SetContentsOpaque(true); layer1->SetOpacity(0.5f); + layer1->NoteLayerPropertyChanged(); layer1->SetForceRenderSurface(true); layer1->SetExpectation(false, true); layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); @@ -6081,10 +6086,12 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // layer1 not culled. layer1->SetContentsOpaque(true); layer1->SetOpacity(1.f); + layer1->NoteLayerPropertyChanged(); layer1->SetExpectation(false, false); layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetContentsOpaque(true); layer2->SetOpacity(0.5f); + layer2->NoteLayerPropertyChanged(); layer2->SetExpectation(true, false); layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); SetNeedsRebuildPropertyTrees(); @@ -6097,10 +6104,12 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // A second way of making the child non-opaque. layer1->SetContentsOpaque(true); layer1->SetOpacity(1.f); + layer1->NoteLayerPropertyChanged(); layer1->SetExpectation(false, false); layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetContentsOpaque(false); layer2->SetOpacity(1.f); + layer2->NoteLayerPropertyChanged(); layer2->SetExpectation(true, false); layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); SetNeedsRebuildPropertyTrees(); @@ -6114,10 +6123,12 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { // blended. layer1->SetContentsOpaque(true); layer1->SetOpacity(1.f); + layer1->NoteLayerPropertyChanged(); layer1->SetExpectation(false, false); layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetContentsOpaque(true); layer2->SetOpacity(1.f); + layer2->NoteLayerPropertyChanged(); layer2->SetExpectation(false, false); layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); SetNeedsRebuildPropertyTrees(); diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 09840ce..33fd49f 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -687,6 +687,41 @@ class LayerTreeHostTestPushPropertiesTo : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPushPropertiesTo); +// Verify damage status of property trees is preserved after commit. +class LayerTreeHostTestPropertyTreesChangedSync : public LayerTreeHostTest { + protected: + void SetupTree() override { + scoped_refptr<Layer> root = Layer::Create(layer_settings()); + layer_tree_host()->SetRootLayer(root); + LayerTreeHostTest::SetupTree(); + } + + void BeginTest() override { + index_ = 0; + PostSetNeedsCommitToMainThread(); + } + + void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { + switch (index_) { + case 0: + index_++; + impl->active_tree()->root_layer()->ResetAllChangeTrackingForSubtree(); + impl->active_tree()->root_layer()->OnOpacityAnimated(0.5f); + PostSetNeedsCommitToMainThread(); + break; + case 1: + EXPECT_TRUE(impl->active_tree()->root_layer()->LayerPropertyChanged()); + EndTest(); + break; + } + } + + void AfterTest() override {} + int index_; +}; + +SINGLE_THREAD_TEST_F(LayerTreeHostTestPropertyTreesChangedSync); + // 1 setNeedsRedraw after the first commit has completed should lead to 1 // additional draw. class LayerTreeHostTestSetNeedsRedraw : public LayerTreeHostTest { diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 31ebad1..5183210 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc @@ -435,6 +435,7 @@ EffectNodeData::EffectNodeData() has_background_filters(false), is_drawn(true), has_animated_opacity(false), + opacity_changed(false), num_copy_requests_in_subtree(0), transform_id(0), clip_id(0) {} @@ -449,6 +450,7 @@ bool EffectNodeData::operator==(const EffectNodeData& other) const { has_background_filters == other.has_background_filters && is_drawn == other.is_drawn && has_animated_opacity == other.has_animated_opacity && + opacity_changed == other.opacity_changed && num_copy_requests_in_subtree == other.num_copy_requests_in_subtree && transform_id == other.transform_id && clip_id == other.clip_id; } @@ -463,6 +465,7 @@ void EffectNodeData::ToProtobuf(proto::TreeNode* proto) const { data->set_has_background_filters(has_background_filters); data->set_is_drawn(is_drawn); data->set_has_animated_opacity(has_animated_opacity); + data->set_opacity_changed(opacity_changed); data->set_num_copy_requests_in_subtree(num_copy_requests_in_subtree); data->set_transform_id(transform_id); data->set_clip_id(clip_id); @@ -479,6 +482,7 @@ void EffectNodeData::FromProtobuf(const proto::TreeNode& proto) { has_background_filters = data.has_background_filters(); is_drawn = data.is_drawn(); has_animated_opacity = data.has_animated_opacity(); + opacity_changed = data.opacity_changed(); num_copy_requests_in_subtree = data.num_copy_requests_in_subtree(); transform_id = data.transform_id(); clip_id = data.clip_id(); @@ -1174,12 +1178,20 @@ void EffectTree::UpdateIsDrawn(EffectNode* node, EffectNode* parent_node) { node->data.is_drawn = true; } +void EffectTree::UpdateOpacityChanged(EffectNode* node, + EffectNode* parent_node) { + if (parent_node && parent_node->data.opacity_changed) { + node->data.opacity_changed = true; + } +} + void EffectTree::UpdateEffects(int id) { EffectNode* node = Node(id); EffectNode* parent_node = parent(node); UpdateOpacities(node, parent_node); UpdateIsDrawn(node, parent_node); + UpdateOpacityChanged(node, parent_node); } void EffectTree::ClearCopyRequests() { @@ -1205,6 +1217,13 @@ bool EffectTree::ContributesToDrawnSurface(int id) { return contributes_to_drawn_surface; } +void EffectTree::ResetChangeTracking() { + for (int id = 1; id < static_cast<int>(size()); ++id) { + EffectNode* node = Node(id); + node->data.opacity_changed = false; + } +} + void TransformTree::UpdateNodeAndAncestorsHaveIntegerTranslations( TransformNode* node, TransformNode* parent_node) { @@ -1381,7 +1400,10 @@ gfx::Transform ScrollTree::ScreenSpaceTransform(int scroll_node_id) const { } PropertyTrees::PropertyTrees() - : needs_rebuild(true), non_root_surfaces_enabled(true), sequence_number(0) { + : needs_rebuild(true), + non_root_surfaces_enabled(true), + changed(false), + sequence_number(0) { transform_tree.SetPropertyTrees(this); effect_tree.SetPropertyTrees(this); clip_tree.SetPropertyTrees(this); @@ -1394,7 +1416,7 @@ bool PropertyTrees::operator==(const PropertyTrees& other) const { return transform_tree == other.transform_tree && effect_tree == other.effect_tree && clip_tree == other.clip_tree && scroll_tree == other.scroll_tree && - needs_rebuild == other.needs_rebuild && + needs_rebuild == other.needs_rebuild && changed == other.changed && non_root_surfaces_enabled == other.non_root_surfaces_enabled && sequence_number == other.sequence_number; } @@ -1405,6 +1427,7 @@ PropertyTrees& PropertyTrees::operator=(const PropertyTrees& from) { clip_tree = from.clip_tree; scroll_tree = from.scroll_tree; needs_rebuild = from.needs_rebuild; + changed = from.changed; non_root_surfaces_enabled = from.non_root_surfaces_enabled; sequence_number = from.sequence_number; inner_viewport_container_bounds_delta_ = @@ -1428,6 +1451,7 @@ void PropertyTrees::ToProtobuf(proto::PropertyTrees* proto) const { clip_tree.ToProtobuf(proto->mutable_clip_tree()); scroll_tree.ToProtobuf(proto->mutable_scroll_tree()); proto->set_needs_rebuild(needs_rebuild); + proto->set_changed(changed); proto->set_non_root_surfaces_enabled(non_root_surfaces_enabled); // TODO(khushalsagar): Consider using the sequence number to decide if @@ -1443,6 +1467,7 @@ void PropertyTrees::FromProtobuf(const proto::PropertyTrees& proto) { scroll_tree.FromProtobuf(proto.scroll_tree()); needs_rebuild = proto.needs_rebuild(); + changed = proto.changed(); non_root_surfaces_enabled = proto.non_root_surfaces_enabled(); sequence_number = proto.sequence_number(); @@ -1475,4 +1500,14 @@ void PropertyTrees::SetInnerViewportScrollBoundsDelta( inner_viewport_scroll_bounds_delta_ = bounds_delta; } +void PropertyTrees::PushChangeTrackingTo(PropertyTrees* tree) { + for (int id = 1; id < static_cast<int>(effect_tree.size()); ++id) { + EffectNode* node = effect_tree.Node(id); + if (node->data.opacity_changed) { + EffectNode* target_node = tree->effect_tree.Node(node->id); + target_node->data.opacity_changed = true; + } + } +} + } // namespace cc diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 9be6e0c..be31f18 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h @@ -258,6 +258,9 @@ struct CC_EXPORT EffectNodeData { bool has_background_filters; bool is_drawn; bool has_animated_opacity; + // We need to track changes to opacity on the compositor to compute damage + // rect. + bool opacity_changed; int num_copy_requests_in_subtree; int transform_id; int clip_id; @@ -525,10 +528,14 @@ class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> { void UpdateEffects(int id); + void UpdateOpacityChanged(EffectNode* node, EffectNode* parent_node); + void ClearCopyRequests(); bool ContributesToDrawnSurface(int id); + void ResetChangeTracking(); + void ToProtobuf(proto::PropertyTree* proto) const; void FromProtobuf(const proto::PropertyTree& proto); @@ -575,11 +582,17 @@ class CC_EXPORT PropertyTrees final { ScrollTree scroll_tree; bool needs_rebuild; bool non_root_surfaces_enabled; + // Change tracking done on property trees needs to be preserved across commits + // (when they are not rebuild). We cache a global bool which stores whether + // we did any change tracking so that we can skip copying the change status + // between property trees when this bool is false. + bool changed; int sequence_number; void SetInnerViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta); void SetOuterViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta); void SetInnerViewportScrollBoundsDelta(gfx::Vector2dF bounds_delta); + void PushChangeTrackingTo(PropertyTrees* tree); gfx::Vector2dF inner_viewport_container_bounds_delta() const { return inner_viewport_container_bounds_delta_; |