summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/layers/layer.cc1
-rw-r--r--cc/layers/layer_impl.cc46
-rw-r--r--cc/layers/layer_impl.h3
-rw-r--r--cc/layers/layer_impl_unittest.cc30
-rw-r--r--cc/layers/layer_unittest.cc49
-rw-r--r--cc/proto/property_tree.proto6
-rw-r--r--cc/tiles/tile_manager_unittest.cc2
-rw-r--r--cc/trees/damage_tracker_unittest.cc92
-rw-r--r--cc/trees/layer_tree_host.cc18
-rw-r--r--cc/trees/layer_tree_host_impl.cc25
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc11
-rw-r--r--cc/trees/layer_tree_host_unittest.cc35
-rw-r--r--cc/trees/property_tree.cc39
-rw-r--r--cc/trees/property_tree.h13
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_;