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) {
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 cc
......@@ -48,6 +48,7 @@ template class PropertyTree<OpacityNode>;
TransformNodeData::TransformNodeData()
: target_id(-1),
content_target_id(-1),
source_node_id(-1),
needs_local_transform_update(true),
is_invertible(true),
ancestors_are_invertible(true),
......@@ -76,8 +77,8 @@ void TransformNodeData::update_post_local_transform(
post_local.MakeIdentity();
post_local.Scale(post_local_scale_factor, post_local_scale_factor);
post_local.Translate3d(
position.x() + parent_offset.x() + transform_origin.x(),
position.y() + parent_offset.y() + transform_origin.y(),
position.x() + source_offset.x() + transform_origin.x(),
position.y() + source_offset.y() + transform_origin.y(),
transform_origin.z());
}
......@@ -141,7 +142,8 @@ void TransformTree::UpdateTransforms(int id) {
TransformNode* node = Node(id);
TransformNode* parent_node = parent(node);
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);
UpdateScreenSpaceTransform(node, parent_node, target_node);
UpdateSublayerScale(node);
......@@ -249,8 +251,14 @@ bool TransformTree::CombineInversesBetween(int source_id,
void TransformTree::UpdateLocalTransform(TransformNode* node) {
gfx::Transform transform = node->data.post_local;
transform.Translate(-node->data.scroll_offset.x(),
-node->data.scroll_offset.y());
gfx::Vector2dF source_to_parent;
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.pre_local);
node->data.set_to_parent(transform);
......
......@@ -60,6 +60,12 @@ struct CC_EXPORT TransformNodeData {
// with this transform node.
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.
bool needs_local_transform_update;
......@@ -98,7 +104,7 @@ struct CC_EXPORT TransformNodeData {
gfx::Vector2dF scroll_snap;
// 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) {
to_parent = transform;
......
......@@ -185,33 +185,29 @@ bool AddTransformNodeIfNeeded(
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 (layer->scroll_parent()) {
gfx::Transform to_parent;
LayerType* source = layer->parent();
parent_offset += source->offset_to_transform_parent();
data_from_ancestor.transform_tree->ComputeTransform(
source->transform_tree_index(),
transform_parent->transform_tree_index(), &to_parent);
parent_offset += to_parent.To2dTranslation();
source_offset += source->offset_to_transform_parent();
source_index = source->transform_tree_index();
} else if (!is_fixed) {
parent_offset = transform_parent->offset_to_transform_parent();
source_offset = transform_parent->offset_to_transform_parent();
} else {
if (data_from_ancestor.transform_tree_parent !=
data_from_ancestor.transform_fixed_parent) {
gfx::Vector2dF fixed_offset = data_from_ancestor.transform_tree_parent
->offset_to_transform_parent();
gfx::Transform parent_to_parent;
data_from_ancestor.transform_tree->ComputeTransform(
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;
source_offset = data_from_ancestor.transform_tree_parent
->offset_to_transform_parent();
source_index =
data_from_ancestor.transform_tree_parent->transform_tree_index();
}
parent_offset += data_from_ancestor.scroll_compensation_adjustment;
source_offset += data_from_ancestor.scroll_compensation_adjustment;
}
}
......@@ -226,17 +222,21 @@ bool AddTransformNodeIfNeeded(
data_for_children->should_flatten |= layer->should_flatten_transform();
gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() +
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(
data_from_ancestor.should_flatten);
layer->set_transform_tree_index(transform_parent->transform_tree_index());
layer->set_transform_tree_index(parent_index);
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);
TransformNode* node = data_for_children->transform_tree->back();
......@@ -276,7 +276,8 @@ bool AddTransformNodeIfNeeded(
post_local_scale_factor);
} else {
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(),
layer->transform_origin());
}
......
......@@ -47,6 +47,7 @@ TEST(PropertyTreeTest, ComputeTransformChild) {
TransformNode child;
child.data.local.Translate(3, 3);
child.data.target_id = 0;
child.data.source_node_id = 0;
tree.Insert(child, 0);
tree.UpdateTransforms(1);
......@@ -87,6 +88,7 @@ TEST(PropertyTreeTest, TransformsWithFlattening) {
int grand_parent = tree.Insert(TransformNode(), 0);
tree.Node(grand_parent)->data.content_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;
rotation_about_x.RotateAboutXAxis(15);
......@@ -95,17 +97,20 @@ TEST(PropertyTreeTest, TransformsWithFlattening) {
tree.Node(parent)->data.needs_sublayer_scale = true;
tree.Node(parent)->data.target_id = grand_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;
int child = tree.Insert(TransformNode(), parent);
tree.Node(child)->data.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.local = rotation_about_x;
int grand_child = tree.Insert(TransformNode(), child);
tree.Node(grand_child)->data.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.local = rotation_about_x;
......@@ -162,6 +167,7 @@ TEST(PropertyTreeTest, MultiplicationOrder) {
TransformNode child;
child.data.local.Scale(2, 2);
child.data.target_id = 0;
child.data.source_node_id = 0;
tree.Insert(child, 0);
tree.UpdateTransforms(1);
......@@ -194,6 +200,7 @@ TEST(PropertyTreeTest, ComputeTransformWithUninvertibleTransform) {
TransformNode child;
child.data.local.Scale(0, 0);
child.data.target_id = 0;
child.data.source_node_id = 0;
tree.Insert(child, 0);
tree.UpdateTransforms(1);
......@@ -223,6 +230,7 @@ TEST(PropertyTreeTest, ComputeTransformWithSublayerScale) {
TransformNode grand_parent;
grand_parent.data.local.Scale(2.f, 2.f);
grand_parent.data.target_id = 0;
grand_parent.data.source_node_id = 0;
grand_parent.data.needs_sublayer_scale = true;
int grand_parent_id = tree.Insert(grand_parent, 0);
tree.UpdateTransforms(grand_parent_id);
......@@ -230,18 +238,21 @@ TEST(PropertyTreeTest, ComputeTransformWithSublayerScale) {
TransformNode parent;
parent.data.local.Translate(15.f, 15.f);
parent.data.target_id = grand_parent_id;
parent.data.source_node_id = grand_parent_id;
int parent_id = tree.Insert(parent, grand_parent_id);
tree.UpdateTransforms(parent_id);
TransformNode child;
child.data.local.Scale(3.f, 3.f);
child.data.target_id = grand_parent_id;
child.data.source_node_id = parent_id;
int child_id = tree.Insert(child, parent_id);
tree.UpdateTransforms(child_id);
TransformNode grand_child;
grand_child.data.local.Scale(5.f, 5.f);
grand_child.data.target_id = grand_parent_id;
grand_child.data.source_node_id = child_id;
grand_child.data.needs_sublayer_scale = true;
int grand_child_id = tree.Insert(grand_child, child_id);
tree.UpdateTransforms(grand_child_id);
......@@ -327,6 +338,7 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) {
int parent = tree.Insert(TransformNode(), 0);
tree.Node(parent)->data.content_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);
gfx::Transform rotation_about_x;
......@@ -335,12 +347,14 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) {
int child = tree.Insert(TransformNode(), parent);
tree.Node(child)->data.content_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;
int grand_child = tree.Insert(TransformNode(), 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.source_node_id = child;
tree.Node(grand_child)->data.flattens_inherited_transform = 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