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

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

Issue 687873004: Introduce Property Trees (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@wip-awoloszyn2
Patch Set: . Created 6 years 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "cc/trees/property_tree_builder.h"
6
7 #include <map>
8 #include <set>
9
10 #include "cc/base/math_util.h"
11 #include "cc/layers/layer.h"
12 #include "cc/trees/layer_tree_host.h"
13 #include "ui/gfx/point_f.h"
14
15 namespace cc {
16
17 class LayerTreeHost;
18
19 namespace {
20
21 struct DataForRecursion {
22 TransformTree* transform_tree;
23 ClipTree* clip_tree;
24 Layer* transform_tree_parent;
25 Layer* transform_fixed_parent;
26 Layer* render_target;
27 int clip_tree_parent;
28 gfx::Vector2dF offset_to_transform_tree_parent;
29 gfx::Vector2dF offset_to_transform_fixed_parent;
30 const Layer* page_scale_layer;
31 float page_scale_factor;
32 float device_scale_factor;
33 };
34
35 static Layer* GetTransformParent(const DataForRecursion& data, Layer* layer) {
36 return layer->position_constraint().is_fixed_position()
37 ? data.transform_fixed_parent
38 : data.transform_tree_parent;
39 }
40
41 static ClipNode* GetClipParent(const DataForRecursion& data, Layer* layer) {
42 const bool inherits_clip = !layer->parent() || !layer->clip_parent();
43 const int id = inherits_clip ? data.clip_tree_parent
44 : layer->clip_parent()->clip_tree_index();
45 return data.clip_tree->Node(id);
46 }
47
48 static bool RequiresClipNode(Layer* layer,
49 bool axis_aligned_with_respect_to_parent) {
50 const bool render_surface_applies_non_axis_aligned_clip =
51 layer->render_surface() && !axis_aligned_with_respect_to_parent &&
52 layer->is_clipped();
53 const bool render_surface_may_grow_due_to_clip_children =
54 layer->render_surface() && layer->num_unclipped_descendants() > 0;
55
56 return !layer->parent() || layer->masks_to_bounds() || layer->mask_layer() ||
57 render_surface_applies_non_axis_aligned_clip ||
58 render_surface_may_grow_due_to_clip_children;
59 }
60
61 void AddClipNodeIfNeeded(const DataForRecursion& data_from_ancestor,
62 Layer* layer,
63 DataForRecursion* data_for_children) {
64 ClipNode* parent = GetClipParent(data_from_ancestor, layer);
65 int parent_id = parent->id;
66
67 const bool axis_aligned_with_respect_to_parent = Are2DAxisAligned(
68 *data_from_ancestor.transform_tree, layer->transform_tree_index(),
69 parent->data.transform_id);
70
71 // TODO(vollick): once Andrew refactors the surface determinations out of
enne (OOO) 2014/12/10 23:45:59 What's the status on this work?
Ian Vollick 2014/12/12 03:01:47 Andrew's got a patch up for review. Ball's in Dana
72 // CDP, the the layer->render_surface() check will be invalid.
73 const bool has_unclipped_surface =
74 layer->render_surface() &&
75 layer->render_surface()->clip_rect().IsEmpty() &&
76 layer->num_unclipped_descendants() == 0;
77
78 if (has_unclipped_surface)
79 parent_id = 0;
80
81 if (!RequiresClipNode(layer, axis_aligned_with_respect_to_parent)) {
82 // Unclipped surfaces reset the clip rect.
83 data_for_children->clip_tree_parent = parent_id;
84 } else if (layer->parent()) {
85 // Note the root clip gets handled elsewhere.
86 Layer* transform_parent = GetTransformParent(*data_for_children, layer);
87 ClipNode node;
88 node.data.clip = gfx::RectF(
89 gfx::PointF() + layer->offset_to_transform_parent(), layer->bounds());
90 node.data.transform_id = transform_parent->transform_tree_index();
91 node.data.target_id =
92 data_from_ancestor.render_target->transform_tree_index();
93
94 data_for_children->clip_tree_parent =
95 data_for_children->clip_tree->Insert(node, parent_id);
96 }
97
98 layer->set_clip_tree_index(
99 has_unclipped_surface ? 0 : data_for_children->clip_tree_parent);
100
101 // TODO(awoloszyn): Right now when we hit a node with a replica, we reset the
102 // clip for all children since we may need to draw. We need to figure out a
103 // better way, since we will need both the clipped and unclipped versions.
104 }
105
106 void AddTransformNodeIfNeeded(const DataForRecursion& data_from_ancestor,
107 Layer* layer,
108 DataForRecursion* data_for_children) {
109 const bool is_root = !layer->parent();
110 const bool is_page_scale_application_layer =
111 layer->parent() && layer->parent() == data_from_ancestor.page_scale_layer;
112 const bool is_scrollable = layer->scrollable();
113 const bool is_fixed = layer->position_constraint().is_fixed_position();
114
115 const bool has_significant_transform =
116 !layer->transform().IsIdentityOr2DTranslation();
117
118 const bool has_animated_transform =
119 layer->layer_animation_controller()->IsAnimatingProperty(
120 Animation::Transform);
121
122 const bool has_transform_origin = layer->transform_origin() != gfx::Point3F();
123
124 const bool has_surface = layer->render_surface();
125
126 const bool flattening_change = layer->parent() &&
127 layer->should_flatten_transform() &&
128 !layer->parent()->should_flatten_transform();
129
130 bool requires_node = is_root || is_scrollable || is_fixed ||
131 has_significant_transform || has_animated_transform ||
132 is_page_scale_application_layer || flattening_change ||
133 has_transform_origin || has_surface;
134
135 Layer* transform_parent = GetTransformParent(data_from_ancestor, layer);
136
137 // May be non-zero if layer is fixed or has a scroll parent.
138 gfx::Vector2dF parent_offset;
139 if (transform_parent) {
140 // TODO(vollick): This is to mimic bugs in current CDP. Need to log a bug
enne (OOO) 2014/12/10 23:45:59 !!!
Ian Vollick 2014/12/12 03:01:47 Yeah :( I've logged the bug and referenced it in t
141 // about this and reference it here.
142 if (!is_fixed)
143 parent_offset = transform_parent->offset_to_transform_parent();
144
145 gfx::Transform to_parent;
146 Layer* source = data_from_ancestor.transform_tree_parent;
147 if (layer->scroll_parent()) {
148 source = layer->parent();
149 parent_offset += layer->parent()->offset_to_transform_parent();
150 }
151
152 ComputeTransform(*data_from_ancestor.transform_tree,
153 source->transform_tree_index(),
154 transform_parent->transform_tree_index(), &to_parent);
155
156 parent_offset += to_parent.To2dTranslation();
157 }
158
159 if (layer->IsContainerForFixedPositionLayers() || is_root)
160 data_for_children->transform_fixed_parent = layer;
161 data_for_children->transform_tree_parent = layer;
162
163 if (!requires_node) {
164 gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() +
165 layer->transform().To2dTranslation();
166 layer->set_offset_to_transform_parent(parent_offset + local_offset);
167 layer->set_transform_tree_index(transform_parent->transform_tree_index());
168 return;
169 }
170
171 if (!is_root) {
172 data_for_children->transform_tree->Insert(
173 TransformNode(), transform_parent->transform_tree_index());
174 }
175
176 TransformNode* node = data_for_children->transform_tree->back();
177
178 node->data.flattens = layer->should_flatten_transform();
179 node->data.target_id =
180 data_from_ancestor.render_target->transform_tree_index();
181
182 gfx::Transform transform;
183 float device_and_page_scale_factors = 1.0f;
184 if (is_root)
185 device_and_page_scale_factors = data_from_ancestor.device_scale_factor;
186 if (is_page_scale_application_layer)
187 device_and_page_scale_factors *= data_from_ancestor.page_scale_factor;
188
189 transform.Scale(device_and_page_scale_factors, device_and_page_scale_factors);
190
191 // NB: We've accounted for the scroll offset here but we haven't taken into
192 // account snapping to screen space pixels (since we haven't computed any
193 // screen space transforms). For the purposes of computing rects we need to
194 // record, this should be fine (the visible rects we compute may be slightly
195 // different than what we'd compute with snapping, but since we significantly
196 // expand the visible rect when determining what to record, the slight
197 // difference should be inconsequential).
198 gfx::Vector2dF position = layer->position().OffsetFromOrigin();
199 if (!layer->scroll_parent()) {
200 position -= gfx::Vector2dF(layer->TotalScrollOffset().x(),
201 layer->TotalScrollOffset().y());
202 }
203
204 position += parent_offset;
205
206 transform.Translate3d(position.x() + layer->transform_origin().x(),
207 position.y() + layer->transform_origin().y(),
208 layer->transform_origin().z());
209 transform.PreconcatTransform(layer->transform());
210 transform.Translate3d(-layer->transform_origin().x(),
211 -layer->transform_origin().y(),
212 -layer->transform_origin().z());
213
214 node->data.to_parent = transform;
215 node->data.is_invertible = transform.GetInverse(&node->data.from_parent);
216
217 UpdateScreenSpaceTransform(data_from_ancestor.transform_tree, node->id);
218
219 layer->set_offset_to_transform_parent(gfx::Vector2dF());
220 layer->set_transform_tree_index(node->id);
221 }
222
223 void BuildPropertyTreesInternal(Layer* layer,
224 const DataForRecursion& data_from_parent) {
225 DataForRecursion data_for_children(data_from_parent);
226 if (layer->render_surface())
227 data_for_children.render_target = layer;
228
229 AddTransformNodeIfNeeded(data_from_parent, layer, &data_for_children);
230 AddClipNodeIfNeeded(data_from_parent, layer, &data_for_children);
231
232 for (size_t i = 0; i < layer->children().size(); ++i) {
233 if (!layer->children()[i]->scroll_parent())
234 BuildPropertyTreesInternal(layer->children()[i].get(), data_for_children);
235 }
236
237 if (layer->scroll_children()) {
238 for (Layer* scroll_child : *layer->scroll_children()) {
239 BuildPropertyTreesInternal(scroll_child, data_for_children);
240 }
241 }
242
243 if (layer->has_replica())
244 BuildPropertyTreesInternal(layer->replica_layer(), data_for_children);
245 }
246
247 } // namespace
248
249 void PropertyTreeBuilder::BuildPropertyTrees(
250 Layer* root_layer,
251 const Layer* page_scale_layer,
252 float page_scale_factor,
253 float device_scale_factor,
254 const gfx::Rect& viewport,
255 const gfx::Transform& device_transform,
256 TransformTree* transform_tree,
257 ClipTree* clip_tree) {
258 DataForRecursion data_for_recursion;
259 data_for_recursion.transform_tree = transform_tree;
260 data_for_recursion.clip_tree = clip_tree;
261 data_for_recursion.transform_tree_parent = nullptr;
262 data_for_recursion.transform_fixed_parent = nullptr;
263 data_for_recursion.render_target = root_layer;
264 data_for_recursion.clip_tree_parent = 0;
265 data_for_recursion.page_scale_layer = page_scale_layer;
266 data_for_recursion.page_scale_factor = page_scale_factor;
267 data_for_recursion.device_scale_factor = device_scale_factor;
268
269 int transform_root_id = 0;
270 int clip_root_id = 0;
271
272 // We only need to clip the root if we have a non-empty viewport. The root of
enne (OOO) 2014/12/10 23:46:00 When is the viewport empty?
Ian Vollick 2014/12/12 03:01:47 This happens in unit tests and the assumption ther
enne (OOO) 2014/12/12 19:05:49 Can you leave a comment saying that empty viewport
Ian Vollick 2014/12/15 21:45:17 This is now unnecessary due to hush's patch. Remov
273 // the clip tree does not clip, so we need to add another node in this case.
274 if (!viewport.IsEmpty()) {
275 data_for_recursion.clip_tree_parent = clip_tree->Insert(ClipNode(), 0);
276 clip_root_id = data_for_recursion.clip_tree_parent;
277 }
278
279 BuildPropertyTreesInternal(root_layer, data_for_recursion);
280
281 TransformNode* transform_root = transform_tree->Node(transform_root_id);
282 ClipNode* clip_root = clip_tree->Node(clip_root_id);
283
284 gfx::Transform combined_transform =
285 device_transform * transform_root->data.to_parent;
enne (OOO) 2014/12/10 23:45:59 Is this ever not identity? Doesn't the transform r
Ian Vollick 2014/12/12 03:01:47 The dsf (and device transform) are applied to the
Ian Vollick 2014/12/15 21:45:17 I've added an extra "super root" to the transform
286
287 transform_root->data.set_to_parent(combined_transform);
288 gfx::RectF transformed_viewport = viewport;
289
290 if (!combined_transform.IsIdentity()) {
291 gfx::Transform inverse_transform;
292 if (!combined_transform.GetInverse(&inverse_transform)) {
293 // If we have an univertible transform, then we clip off the entire
294 // subtree.
295 transformed_viewport = gfx::RectF();
296 } else {
297 transformed_viewport =
298 MathUtil::ProjectClippedRect(inverse_transform, viewport);
299 }
300 }
301
302 clip_root->data.clip = transformed_viewport;
enne (OOO) 2014/12/10 23:46:00 Why do you need to inverse transform the viewport
Ian Vollick 2014/12/12 03:01:47 To get to screen space (where this clip is applied
enne (OOO) 2014/12/12 19:05:49 Hmm. Maybe I just figured that this function woul
Ian Vollick 2014/12/15 21:45:17 Now that we have the super root, we don't need to
303 clip_root->data.transform_id = transform_root->id;
304 }
305
306 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698