Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(335)

Side by Side Diff: cc/trees/property_tree.cc

Issue 1013463003: Update from https://crrev.com/320931 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/trees/property_tree.h ('k') | cc/trees/property_tree_builder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <set> 5 #include <set>
6 #include <vector>
6 7
7 #include "base/logging.h" 8 #include "base/logging.h"
8 #include "cc/base/math_util.h" 9 #include "cc/base/math_util.h"
9 #include "cc/trees/property_tree.h" 10 #include "cc/trees/property_tree.h"
10 11
11 namespace cc { 12 namespace cc {
12 13
13 template <typename T> 14 template <typename T>
14 PropertyTree<T>::PropertyTree() { 15 PropertyTree<T>::PropertyTree() {
15 nodes_.push_back(T()); 16 nodes_.push_back(T());
(...skipping 21 matching lines...) Expand all
37 38
38 TransformNodeData::TransformNodeData() 39 TransformNodeData::TransformNodeData()
39 : target_id(-1), 40 : target_id(-1),
40 content_target_id(-1), 41 content_target_id(-1),
41 needs_local_transform_update(true), 42 needs_local_transform_update(true),
42 is_invertible(true), 43 is_invertible(true),
43 ancestors_are_invertible(true), 44 ancestors_are_invertible(true),
44 is_animated(false), 45 is_animated(false),
45 to_screen_is_animated(false), 46 to_screen_is_animated(false),
46 flattens_inherited_transform(false), 47 flattens_inherited_transform(false),
47 flattens_local_transform(false), 48 node_and_ancestors_are_flat(true),
48 scrolls(false), 49 scrolls(false),
49 needs_sublayer_scale(false), 50 needs_sublayer_scale(false),
50 layer_scale_factor(1.0f) { 51 layer_scale_factor(1.0f) {
51 } 52 }
52 53
53 TransformNodeData::~TransformNodeData() { 54 TransformNodeData::~TransformNodeData() {
54 } 55 }
55 56
56 ClipNodeData::ClipNodeData() : transform_id(-1), target_id(-1) { 57 ClipNodeData::ClipNodeData() : transform_id(-1), target_id(-1) {
57 } 58 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 } 129 }
129 NOTREACHED(); 130 NOTREACHED();
130 return 0; 131 return 0;
131 } 132 }
132 133
133 bool TransformTree::CombineTransformsBetween(int source_id, 134 bool TransformTree::CombineTransformsBetween(int source_id,
134 int dest_id, 135 int dest_id,
135 gfx::Transform* transform) const { 136 gfx::Transform* transform) const {
136 const TransformNode* current = Node(source_id); 137 const TransformNode* current = Node(source_id);
137 const TransformNode* dest = Node(dest_id); 138 const TransformNode* dest = Node(dest_id);
138 if (!dest || dest->data.ancestors_are_invertible) { 139 // Combine transforms to and from the screen when possible. Since flattening
140 // is a non-linear operation, we cannot use this approach when there is
141 // non-trivial flattening between the source and destination nodes. For
142 // example, consider the tree R->A->B->C, where B flattens its inherited
143 // transform, and A has a non-flat transform. Suppose C is the source and A is
144 // the destination. The expected result is C * B. But C's to_screen
145 // transform is C * B * flattened(A * R), and A's from_screen transform is
146 // R^{-1} * A^{-1}. If at least one of A and R isn't flat, the inverse of
147 // flattened(A * R) won't be R^{-1} * A{-1}, so multiplying C's to_screen and
148 // A's from_screen will not produce the correct result.
149 if (!dest || (dest->data.ancestors_are_invertible &&
150 current->data.node_and_ancestors_are_flat)) {
139 transform->ConcatTransform(current->data.to_screen); 151 transform->ConcatTransform(current->data.to_screen);
140 if (dest) 152 if (dest)
141 transform->ConcatTransform(dest->data.from_screen); 153 transform->ConcatTransform(dest->data.from_screen);
142 return true; 154 return true;
143 } 155 }
144 156
145 bool all_are_invertible = true; 157 bool all_are_invertible = true;
158
159 // Flattening is defined in a way that requires it to be applied while
160 // traversing downward in the tree. We first identify nodes that are on the
161 // path from the source to the destination (this is traversing upward), and
162 // then we visit these nodes in reverse order, flattening as needed. We
163 // early-out if we get to a node whose target node is the destination, since
164 // we can then re-use the target space transform stored at that node.
165 std::vector<int> source_to_destination;
166 source_to_destination.push_back(current->id);
167 current = parent(current);
146 for (; current && current->id > dest_id; current = parent(current)) { 168 for (; current && current->id > dest_id; current = parent(current)) {
147 transform->ConcatTransform(current->data.to_parent); 169 if (current->data.target_id == dest_id &&
148 if (!current->data.is_invertible) 170 current->data.content_target_id == dest_id)
171 break;
172 source_to_destination.push_back(current->id);
173 }
174
175 gfx::Transform combined_transform;
176 if (current->id > dest_id) {
177 combined_transform = current->data.to_target;
178 // The stored target space transform has sublayer scale baked in, but we
179 // need the unscaled transform.
180 combined_transform.Scale(1.0f / dest->data.sublayer_scale.x(),
181 1.0f / dest->data.sublayer_scale.y());
182 }
183
184 for (int i = source_to_destination.size() - 1; i >= 0; i--) {
185 const TransformNode* node = Node(source_to_destination[i]);
186 if (node->data.flattens_inherited_transform)
187 combined_transform.FlattenTo2d();
188 combined_transform.PreconcatTransform(node->data.to_parent);
189
190 if (!node->data.is_invertible)
149 all_are_invertible = false; 191 all_are_invertible = false;
150 } 192 }
151 193
194 transform->ConcatTransform(combined_transform);
152 return all_are_invertible; 195 return all_are_invertible;
153 } 196 }
154 197
155 bool TransformTree::CombineInversesBetween(int source_id, 198 bool TransformTree::CombineInversesBetween(int source_id,
156 int dest_id, 199 int dest_id,
157 gfx::Transform* transform) const { 200 gfx::Transform* transform) const {
158 const TransformNode* current = Node(dest_id); 201 const TransformNode* current = Node(dest_id);
159 const TransformNode* dest = Node(source_id); 202 const TransformNode* dest = Node(source_id);
160 if (current->data.ancestors_are_invertible) { 203 // Just as in CombineTransformsBetween, we can use screen space transforms in
204 // this computation only when there isn't any non-trivial flattening
205 // involved.
206 if (current->data.ancestors_are_invertible &&
207 current->data.node_and_ancestors_are_flat) {
161 transform->PreconcatTransform(current->data.from_screen); 208 transform->PreconcatTransform(current->data.from_screen);
162 if (dest) 209 if (dest)
163 transform->PreconcatTransform(dest->data.to_screen); 210 transform->PreconcatTransform(dest->data.to_screen);
164 return true; 211 return true;
165 } 212 }
166 213
167 bool all_are_invertible = true; 214 // Inverting a flattening is not equivalent to flattening an inverse. This
168 for (; current && current->id > source_id; current = parent(current)) { 215 // means we cannot, for example, use the inverse of each node's to_parent
169 transform->PreconcatTransform(current->data.from_parent); 216 // transform, flattening where needed. Instead, we must compute the transform
170 if (!current->data.is_invertible) 217 // from the destination to the source, with flattening, and then invert the
171 all_are_invertible = false; 218 // result.
172 } 219 gfx::Transform dest_to_source;
173 220 CombineTransformsBetween(dest_id, source_id, &dest_to_source);
221 gfx::Transform source_to_dest;
222 bool all_are_invertible = dest_to_source.GetInverse(&source_to_dest);
223 transform->PreconcatTransform(source_to_dest);
174 return all_are_invertible; 224 return all_are_invertible;
175 } 225 }
176 226
177 void TransformTree::UpdateLocalTransform(TransformNode* node) { 227 void TransformTree::UpdateLocalTransform(TransformNode* node) {
178 gfx::Transform transform = node->data.post_local; 228 gfx::Transform transform = node->data.post_local;
179 transform.Translate(-node->data.scroll_offset.x(), 229 transform.Translate(-node->data.scroll_offset.x(),
180 -node->data.scroll_offset.y()); 230 -node->data.scroll_offset.y());
181 transform.PreconcatTransform(node->data.local); 231 transform.PreconcatTransform(node->data.local);
182 transform.PreconcatTransform(node->data.pre_local); 232 transform.PreconcatTransform(node->data.pre_local);
183 node->data.set_to_parent(transform); 233 node->data.set_to_parent(transform);
184 node->data.needs_local_transform_update = false; 234 node->data.needs_local_transform_update = false;
185 } 235 }
186 236
187 void TransformTree::UpdateScreenSpaceTransform(TransformNode* node, 237 void TransformTree::UpdateScreenSpaceTransform(TransformNode* node,
188 TransformNode* parent_node, 238 TransformNode* parent_node,
189 TransformNode* target_node) { 239 TransformNode* target_node) {
190 if (!parent_node) { 240 if (!parent_node) {
191 node->data.to_screen = node->data.to_parent; 241 node->data.to_screen = node->data.to_parent;
192 node->data.ancestors_are_invertible = true; 242 node->data.ancestors_are_invertible = true;
193 node->data.to_screen_is_animated = false; 243 node->data.to_screen_is_animated = false;
194 } else if (parent_node->data.flattens_local_transform || 244 node->data.node_and_ancestors_are_flat = node->data.to_parent.IsFlat();
195 node->data.flattens_inherited_transform) { 245 } else {
196 // Flattening is tricky. Once a layer is drawn into its render target, it 246 node->data.to_screen = parent_node->data.to_screen;
197 // cannot escape, so we only need to consider transforms between the layer 247 if (node->data.flattens_inherited_transform)
198 // and its target when flattening (i.e., its draw transform). To compute the 248 node->data.to_screen.FlattenTo2d();
199 // screen space transform when flattening is involved we combine three
200 // transforms, A * B * C, where A is the screen space transform of the
201 // target, B is the flattened draw transform of the layer's parent, and C is
202 // the local transform.
203 node->data.to_screen = target_node->data.to_screen;
204 gfx::Transform flattened;
205 ComputeTransform(parent_node->id, target_node->id, &flattened);
206 flattened.FlattenTo2d();
207 node->data.to_screen.PreconcatTransform(flattened);
208 node->data.to_screen.PreconcatTransform(node->data.to_parent); 249 node->data.to_screen.PreconcatTransform(node->data.to_parent);
209 node->data.ancestors_are_invertible = 250 node->data.ancestors_are_invertible =
210 parent_node->data.ancestors_are_invertible; 251 parent_node->data.ancestors_are_invertible;
211 } else { 252 node->data.node_and_ancestors_are_flat =
212 node->data.to_screen = parent_node->data.to_screen; 253 parent_node->data.node_and_ancestors_are_flat &&
213 node->data.to_screen.PreconcatTransform(node->data.to_parent); 254 node->data.to_parent.IsFlat();
214 node->data.ancestors_are_invertible =
215 parent_node->data.ancestors_are_invertible;
216 } 255 }
217 256
218 if (!node->data.to_screen.GetInverse(&node->data.from_screen)) 257 if (!node->data.to_screen.GetInverse(&node->data.from_screen))
219 node->data.ancestors_are_invertible = false; 258 node->data.ancestors_are_invertible = false;
220 } 259 }
221 260
222 void TransformTree::UpdateSublayerScale(TransformNode* node) { 261 void TransformTree::UpdateSublayerScale(TransformNode* node) {
223 // The sublayer scale depends on the screen space transform, so update it too. 262 // The sublayer scale depends on the screen space transform, so update it too.
224 node->data.sublayer_scale = 263 node->data.sublayer_scale =
225 node->data.needs_sublayer_scale 264 node->data.needs_sublayer_scale
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 gfx::Transform inverse_delta(gfx::Transform::kSkipInitialization); 319 gfx::Transform inverse_delta(gfx::Transform::kSkipInitialization);
281 bool invertible_delta = delta.GetInverse(&inverse_delta); 320 bool invertible_delta = delta.GetInverse(&inverse_delta);
282 321
283 // The delta should be a translation, modulo floating point error, and should 322 // The delta should be a translation, modulo floating point error, and should
284 // therefore be invertible. 323 // therefore be invertible.
285 DCHECK(invertible_delta); 324 DCHECK(invertible_delta);
286 325
287 // Now that we have our scroll delta, we must apply it to each of our 326 // Now that we have our scroll delta, we must apply it to each of our
288 // combined, to/from matrices. 327 // combined, to/from matrices.
289 node->data.to_parent.PreconcatTransform(delta); 328 node->data.to_parent.PreconcatTransform(delta);
290 node->data.from_parent.ConcatTransform(inverse_delta);
291 node->data.to_target.PreconcatTransform(delta); 329 node->data.to_target.PreconcatTransform(delta);
292 node->data.from_target.ConcatTransform(inverse_delta); 330 node->data.from_target.ConcatTransform(inverse_delta);
293 node->data.to_screen.PreconcatTransform(delta); 331 node->data.to_screen.PreconcatTransform(delta);
294 node->data.from_screen.ConcatTransform(inverse_delta); 332 node->data.from_screen.ConcatTransform(inverse_delta);
295 } 333 }
296 334
297 } // namespace cc 335 } // namespace cc
OLDNEW
« no previous file with comments | « cc/trees/property_tree.h ('k') | cc/trees/property_tree_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698