Commit f09db896 authored by ajuma's avatar ajuma Committed by Commit bot

cc: Fix property tree position updates when rebuilding is skipped

The parent_offset currently stored at each transform tree node sometimes
depends on the transform between some other node (which happens to
correspond to node's owning layer's parent's transform node) and the node's
parent. When this transform changes and the transform tree isn't rebuilt,
the parent_offset becomes stale. This CL replaces parent_offset with
source_offset, which is the portion of parent_offset that doesn't depend on
a transform between tree nodes, and adds a source_node_id to each node
so that the transform between nodes (when needed) can be recomputed
when the transform tree is updated.

BUG=480589

Review URL: https://codereview.chromium.org/1106013002

Cr-Commit-Position: refs/heads/master@{#326894}
parent a926d0b8
...@@ -9221,5 +9221,42 @@ TEST_F(LayerTreeHostCommonTest, ChangeTransformOrigin) { ...@@ -9221,5 +9221,42 @@ TEST_F(LayerTreeHostCommonTest, ChangeTransformOrigin) {
EXPECT_EQ(gfx::Rect(5, 5, 5, 5), child->visible_rect_from_property_trees()); EXPECT_EQ(gfx::Rect(5, 5, 5, 5), child->visible_rect_from_property_trees());
} }
TEST_F(LayerTreeHostCommonTest, UpdateScrollChildPosition) {
scoped_refptr<Layer> root = Layer::Create();
scoped_refptr<LayerWithForcedDrawsContent> scroll_parent =
make_scoped_refptr(new LayerWithForcedDrawsContent);
scoped_refptr<LayerWithForcedDrawsContent> scroll_child =
make_scoped_refptr(new LayerWithForcedDrawsContent);
root->AddChild(scroll_child);
root->AddChild(scroll_parent);
scroll_child->SetScrollParent(scroll_parent.get());
scroll_parent->SetScrollClipLayerId(root->id());
scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost());
host->SetRootLayer(root);
gfx::Transform identity_transform;
gfx::Transform scale;
scale.Scale(2.f, 2.f);
SetLayerPropertiesForTesting(root.get(), identity_transform, gfx::Point3F(),
gfx::PointF(), gfx::Size(50, 50), true, false);
SetLayerPropertiesForTesting(scroll_child.get(), scale, gfx::Point3F(),
gfx::PointF(), gfx::Size(40, 40), true, false);
SetLayerPropertiesForTesting(scroll_parent.get(), identity_transform,
gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30),
true, false);
ExecuteCalculateDrawProperties(root.get());
EXPECT_EQ(gfx::Rect(25, 25),
scroll_child->visible_rect_from_property_trees());
scroll_child->SetPosition(gfx::PointF(0, -10.f));
scroll_parent->SetScrollOffset(gfx::ScrollOffset(0.f, 10.f));
ExecuteCalculateDrawProperties(root.get());
EXPECT_EQ(gfx::Rect(0, 5, 25, 25),
scroll_child->visible_rect_from_property_trees());
}
} // namespace } // namespace
} // namespace cc } // namespace cc
...@@ -48,6 +48,7 @@ template class PropertyTree<OpacityNode>; ...@@ -48,6 +48,7 @@ template class PropertyTree<OpacityNode>;
TransformNodeData::TransformNodeData() TransformNodeData::TransformNodeData()
: target_id(-1), : target_id(-1),
content_target_id(-1), content_target_id(-1),
source_node_id(-1),
needs_local_transform_update(true), needs_local_transform_update(true),
is_invertible(true), is_invertible(true),
ancestors_are_invertible(true), ancestors_are_invertible(true),
...@@ -76,8 +77,8 @@ void TransformNodeData::update_post_local_transform( ...@@ -76,8 +77,8 @@ void TransformNodeData::update_post_local_transform(
post_local.MakeIdentity(); post_local.MakeIdentity();
post_local.Scale(post_local_scale_factor, post_local_scale_factor); post_local.Scale(post_local_scale_factor, post_local_scale_factor);
post_local.Translate3d( post_local.Translate3d(
position.x() + parent_offset.x() + transform_origin.x(), position.x() + source_offset.x() + transform_origin.x(),
position.y() + parent_offset.y() + transform_origin.y(), position.y() + source_offset.y() + transform_origin.y(),
transform_origin.z()); transform_origin.z());
} }
...@@ -141,7 +142,8 @@ void TransformTree::UpdateTransforms(int id) { ...@@ -141,7 +142,8 @@ void TransformTree::UpdateTransforms(int id) {
TransformNode* node = Node(id); TransformNode* node = Node(id);
TransformNode* parent_node = parent(node); TransformNode* parent_node = parent(node);
TransformNode* target_node = Node(node->data.target_id); TransformNode* target_node = Node(node->data.target_id);
if (node->data.needs_local_transform_update) if (node->data.needs_local_transform_update ||
node->parent_id != node->data.source_node_id)
UpdateLocalTransform(node); UpdateLocalTransform(node);
UpdateScreenSpaceTransform(node, parent_node, target_node); UpdateScreenSpaceTransform(node, parent_node, target_node);
UpdateSublayerScale(node); UpdateSublayerScale(node);
...@@ -249,8 +251,14 @@ bool TransformTree::CombineInversesBetween(int source_id, ...@@ -249,8 +251,14 @@ bool TransformTree::CombineInversesBetween(int source_id,
void TransformTree::UpdateLocalTransform(TransformNode* node) { void TransformTree::UpdateLocalTransform(TransformNode* node) {
gfx::Transform transform = node->data.post_local; gfx::Transform transform = node->data.post_local;
transform.Translate(-node->data.scroll_offset.x(), gfx::Vector2dF source_to_parent;
-node->data.scroll_offset.y()); if (node->parent_id != node->data.source_node_id) {
gfx::Transform to_parent;
ComputeTransform(node->data.source_node_id, node->parent_id, &to_parent);
source_to_parent = to_parent.To2dTranslation();
}
transform.Translate(source_to_parent.x() - node->data.scroll_offset.x(),
source_to_parent.y() - node->data.scroll_offset.y());
transform.PreconcatTransform(node->data.local); transform.PreconcatTransform(node->data.local);
transform.PreconcatTransform(node->data.pre_local); transform.PreconcatTransform(node->data.pre_local);
node->data.set_to_parent(transform); node->data.set_to_parent(transform);
......
...@@ -60,6 +60,12 @@ struct CC_EXPORT TransformNodeData { ...@@ -60,6 +60,12 @@ struct CC_EXPORT TransformNodeData {
// with this transform node. // with this transform node.
int content_target_id; int content_target_id;
// This is the node with respect to which source_offset is defined. This will
// not be needed once layerization moves to cc, but is needed in order to
// efficiently update the transform tree for changes to position in the layer
// tree.
int source_node_id;
// TODO(vollick): will be moved when accelerated effects are implemented. // TODO(vollick): will be moved when accelerated effects are implemented.
bool needs_local_transform_update; bool needs_local_transform_update;
...@@ -98,7 +104,7 @@ struct CC_EXPORT TransformNodeData { ...@@ -98,7 +104,7 @@ struct CC_EXPORT TransformNodeData {
gfx::Vector2dF scroll_snap; gfx::Vector2dF scroll_snap;
// TODO(vollick): will be moved when accelerated effects are implemented. // TODO(vollick): will be moved when accelerated effects are implemented.
gfx::Vector2dF parent_offset; gfx::Vector2dF source_offset;
void set_to_parent(const gfx::Transform& transform) { void set_to_parent(const gfx::Transform& transform) {
to_parent = transform; to_parent = transform;
......
...@@ -185,33 +185,29 @@ bool AddTransformNodeIfNeeded( ...@@ -185,33 +185,29 @@ bool AddTransformNodeIfNeeded(
LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer); LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer);
gfx::Vector2dF parent_offset; int parent_index = 0;
if (transform_parent)
parent_index = transform_parent->transform_tree_index();
int source_index = parent_index;
gfx::Vector2dF source_offset;
if (transform_parent) { if (transform_parent) {
if (layer->scroll_parent()) { if (layer->scroll_parent()) {
gfx::Transform to_parent;
LayerType* source = layer->parent(); LayerType* source = layer->parent();
parent_offset += source->offset_to_transform_parent(); source_offset += source->offset_to_transform_parent();
data_from_ancestor.transform_tree->ComputeTransform( source_index = source->transform_tree_index();
source->transform_tree_index(),
transform_parent->transform_tree_index(), &to_parent);
parent_offset += to_parent.To2dTranslation();
} else if (!is_fixed) { } else if (!is_fixed) {
parent_offset = transform_parent->offset_to_transform_parent(); source_offset = transform_parent->offset_to_transform_parent();
} else { } else {
if (data_from_ancestor.transform_tree_parent != if (data_from_ancestor.transform_tree_parent !=
data_from_ancestor.transform_fixed_parent) { data_from_ancestor.transform_fixed_parent) {
gfx::Vector2dF fixed_offset = data_from_ancestor.transform_tree_parent source_offset = data_from_ancestor.transform_tree_parent
->offset_to_transform_parent(); ->offset_to_transform_parent();
gfx::Transform parent_to_parent; source_index =
data_from_ancestor.transform_tree->ComputeTransform( data_from_ancestor.transform_tree_parent->transform_tree_index();
data_from_ancestor.transform_tree_parent->transform_tree_index(),
data_from_ancestor.transform_fixed_parent->transform_tree_index(),
&parent_to_parent);
fixed_offset += parent_to_parent.To2dTranslation();
parent_offset += fixed_offset;
} }
parent_offset += data_from_ancestor.scroll_compensation_adjustment; source_offset += data_from_ancestor.scroll_compensation_adjustment;
} }
} }
...@@ -226,17 +222,21 @@ bool AddTransformNodeIfNeeded( ...@@ -226,17 +222,21 @@ bool AddTransformNodeIfNeeded(
data_for_children->should_flatten |= layer->should_flatten_transform(); data_for_children->should_flatten |= layer->should_flatten_transform();
gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() + gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() +
layer->transform().To2dTranslation(); layer->transform().To2dTranslation();
layer->set_offset_to_transform_parent(parent_offset + local_offset); gfx::Vector2dF source_to_parent;
if (source_index != parent_index) {
gfx::Transform to_parent;
data_from_ancestor.transform_tree->ComputeTransform(
source_index, parent_index, &to_parent);
source_to_parent = to_parent.To2dTranslation();
}
layer->set_offset_to_transform_parent(source_offset + source_to_parent +
local_offset);
layer->set_should_flatten_transform_from_property_tree( layer->set_should_flatten_transform_from_property_tree(
data_from_ancestor.should_flatten); data_from_ancestor.should_flatten);
layer->set_transform_tree_index(transform_parent->transform_tree_index()); layer->set_transform_tree_index(parent_index);
return false; return false;
} }
int parent_index = 0;
if (transform_parent)
parent_index = transform_parent->transform_tree_index();
data_for_children->transform_tree->Insert(TransformNode(), parent_index); data_for_children->transform_tree->Insert(TransformNode(), parent_index);
TransformNode* node = data_for_children->transform_tree->back(); TransformNode* node = data_for_children->transform_tree->back();
...@@ -276,7 +276,8 @@ bool AddTransformNodeIfNeeded( ...@@ -276,7 +276,8 @@ bool AddTransformNodeIfNeeded(
post_local_scale_factor); post_local_scale_factor);
} else { } else {
node->data.post_local_scale_factor = post_local_scale_factor; node->data.post_local_scale_factor = post_local_scale_factor;
node->data.parent_offset = parent_offset; node->data.source_offset = source_offset;
node->data.source_node_id = source_index;
node->data.update_post_local_transform(layer->position(), node->data.update_post_local_transform(layer->position(),
layer->transform_origin()); layer->transform_origin());
} }
......
...@@ -47,6 +47,7 @@ TEST(PropertyTreeTest, ComputeTransformChild) { ...@@ -47,6 +47,7 @@ TEST(PropertyTreeTest, ComputeTransformChild) {
TransformNode child; TransformNode child;
child.data.local.Translate(3, 3); child.data.local.Translate(3, 3);
child.data.target_id = 0; child.data.target_id = 0;
child.data.source_node_id = 0;
tree.Insert(child, 0); tree.Insert(child, 0);
tree.UpdateTransforms(1); tree.UpdateTransforms(1);
...@@ -87,6 +88,7 @@ TEST(PropertyTreeTest, TransformsWithFlattening) { ...@@ -87,6 +88,7 @@ TEST(PropertyTreeTest, TransformsWithFlattening) {
int grand_parent = tree.Insert(TransformNode(), 0); int grand_parent = tree.Insert(TransformNode(), 0);
tree.Node(grand_parent)->data.content_target_id = grand_parent; tree.Node(grand_parent)->data.content_target_id = grand_parent;
tree.Node(grand_parent)->data.target_id = grand_parent; tree.Node(grand_parent)->data.target_id = grand_parent;
tree.Node(grand_parent)->data.source_node_id = 0;
gfx::Transform rotation_about_x; gfx::Transform rotation_about_x;
rotation_about_x.RotateAboutXAxis(15); rotation_about_x.RotateAboutXAxis(15);
...@@ -95,17 +97,20 @@ TEST(PropertyTreeTest, TransformsWithFlattening) { ...@@ -95,17 +97,20 @@ TEST(PropertyTreeTest, TransformsWithFlattening) {
tree.Node(parent)->data.needs_sublayer_scale = true; tree.Node(parent)->data.needs_sublayer_scale = true;
tree.Node(parent)->data.target_id = grand_parent; tree.Node(parent)->data.target_id = grand_parent;
tree.Node(parent)->data.content_target_id = parent; tree.Node(parent)->data.content_target_id = parent;
tree.Node(parent)->data.source_node_id = grand_parent;
tree.Node(parent)->data.local = rotation_about_x; tree.Node(parent)->data.local = rotation_about_x;
int child = tree.Insert(TransformNode(), parent); int child = tree.Insert(TransformNode(), parent);
tree.Node(child)->data.target_id = parent; tree.Node(child)->data.target_id = parent;
tree.Node(child)->data.content_target_id = parent; tree.Node(child)->data.content_target_id = parent;
tree.Node(child)->data.source_node_id = parent;
tree.Node(child)->data.flattens_inherited_transform = true; tree.Node(child)->data.flattens_inherited_transform = true;
tree.Node(child)->data.local = rotation_about_x; tree.Node(child)->data.local = rotation_about_x;
int grand_child = tree.Insert(TransformNode(), child); int grand_child = tree.Insert(TransformNode(), child);
tree.Node(grand_child)->data.target_id = parent; tree.Node(grand_child)->data.target_id = parent;
tree.Node(grand_child)->data.content_target_id = parent; tree.Node(grand_child)->data.content_target_id = parent;
tree.Node(grand_child)->data.source_node_id = child;
tree.Node(grand_child)->data.flattens_inherited_transform = true; tree.Node(grand_child)->data.flattens_inherited_transform = true;
tree.Node(grand_child)->data.local = rotation_about_x; tree.Node(grand_child)->data.local = rotation_about_x;
...@@ -162,6 +167,7 @@ TEST(PropertyTreeTest, MultiplicationOrder) { ...@@ -162,6 +167,7 @@ TEST(PropertyTreeTest, MultiplicationOrder) {
TransformNode child; TransformNode child;
child.data.local.Scale(2, 2); child.data.local.Scale(2, 2);
child.data.target_id = 0; child.data.target_id = 0;
child.data.source_node_id = 0;
tree.Insert(child, 0); tree.Insert(child, 0);
tree.UpdateTransforms(1); tree.UpdateTransforms(1);
...@@ -194,6 +200,7 @@ TEST(PropertyTreeTest, ComputeTransformWithUninvertibleTransform) { ...@@ -194,6 +200,7 @@ TEST(PropertyTreeTest, ComputeTransformWithUninvertibleTransform) {
TransformNode child; TransformNode child;
child.data.local.Scale(0, 0); child.data.local.Scale(0, 0);
child.data.target_id = 0; child.data.target_id = 0;
child.data.source_node_id = 0;
tree.Insert(child, 0); tree.Insert(child, 0);
tree.UpdateTransforms(1); tree.UpdateTransforms(1);
...@@ -223,6 +230,7 @@ TEST(PropertyTreeTest, ComputeTransformWithSublayerScale) { ...@@ -223,6 +230,7 @@ TEST(PropertyTreeTest, ComputeTransformWithSublayerScale) {
TransformNode grand_parent; TransformNode grand_parent;
grand_parent.data.local.Scale(2.f, 2.f); grand_parent.data.local.Scale(2.f, 2.f);
grand_parent.data.target_id = 0; grand_parent.data.target_id = 0;
grand_parent.data.source_node_id = 0;
grand_parent.data.needs_sublayer_scale = true; grand_parent.data.needs_sublayer_scale = true;
int grand_parent_id = tree.Insert(grand_parent, 0); int grand_parent_id = tree.Insert(grand_parent, 0);
tree.UpdateTransforms(grand_parent_id); tree.UpdateTransforms(grand_parent_id);
...@@ -230,18 +238,21 @@ TEST(PropertyTreeTest, ComputeTransformWithSublayerScale) { ...@@ -230,18 +238,21 @@ TEST(PropertyTreeTest, ComputeTransformWithSublayerScale) {
TransformNode parent; TransformNode parent;
parent.data.local.Translate(15.f, 15.f); parent.data.local.Translate(15.f, 15.f);
parent.data.target_id = grand_parent_id; parent.data.target_id = grand_parent_id;
parent.data.source_node_id = grand_parent_id;
int parent_id = tree.Insert(parent, grand_parent_id); int parent_id = tree.Insert(parent, grand_parent_id);
tree.UpdateTransforms(parent_id); tree.UpdateTransforms(parent_id);
TransformNode child; TransformNode child;
child.data.local.Scale(3.f, 3.f); child.data.local.Scale(3.f, 3.f);
child.data.target_id = grand_parent_id; child.data.target_id = grand_parent_id;
child.data.source_node_id = parent_id;
int child_id = tree.Insert(child, parent_id); int child_id = tree.Insert(child, parent_id);
tree.UpdateTransforms(child_id); tree.UpdateTransforms(child_id);
TransformNode grand_child; TransformNode grand_child;
grand_child.data.local.Scale(5.f, 5.f); grand_child.data.local.Scale(5.f, 5.f);
grand_child.data.target_id = grand_parent_id; grand_child.data.target_id = grand_parent_id;
grand_child.data.source_node_id = child_id;
grand_child.data.needs_sublayer_scale = true; grand_child.data.needs_sublayer_scale = true;
int grand_child_id = tree.Insert(grand_child, child_id); int grand_child_id = tree.Insert(grand_child, child_id);
tree.UpdateTransforms(grand_child_id); tree.UpdateTransforms(grand_child_id);
...@@ -327,6 +338,7 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) { ...@@ -327,6 +338,7 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) {
int parent = tree.Insert(TransformNode(), 0); int parent = tree.Insert(TransformNode(), 0);
tree.Node(parent)->data.content_target_id = parent; tree.Node(parent)->data.content_target_id = parent;
tree.Node(parent)->data.target_id = parent; tree.Node(parent)->data.target_id = parent;
tree.Node(parent)->data.source_node_id = 0;
tree.Node(parent)->data.local.Translate(2, 2); tree.Node(parent)->data.local.Translate(2, 2);
gfx::Transform rotation_about_x; gfx::Transform rotation_about_x;
...@@ -335,12 +347,14 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) { ...@@ -335,12 +347,14 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) {
int child = tree.Insert(TransformNode(), parent); int child = tree.Insert(TransformNode(), parent);
tree.Node(child)->data.content_target_id = child; tree.Node(child)->data.content_target_id = child;
tree.Node(child)->data.target_id = child; tree.Node(child)->data.target_id = child;
tree.Node(child)->data.source_node_id = parent;
tree.Node(child)->data.local = rotation_about_x; tree.Node(child)->data.local = rotation_about_x;
int grand_child = tree.Insert(TransformNode(), child); int grand_child = tree.Insert(TransformNode(), child);
tree.Node(grand_child)->data.content_target_id = grand_child; tree.Node(grand_child)->data.content_target_id = grand_child;
tree.Node(grand_child)->data.target_id = grand_child; tree.Node(grand_child)->data.target_id = grand_child;
tree.Node(grand_child)->data.source_node_id = child;
tree.Node(grand_child)->data.flattens_inherited_transform = true; tree.Node(grand_child)->data.flattens_inherited_transform = true;
tree.set_needs_update(true); tree.set_needs_update(true);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment