[Eraser strings] Remove unused Supervised User infobar and corresponding strings
[chromium-blink-merge.git] / cc / trees / property_tree_builder.cc
blob1396ebb857aaa578611c3ce52ae691140b09e42a
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.
5 #include "cc/trees/property_tree_builder.h"
7 #include <map>
8 #include <set>
10 #include "cc/base/math_util.h"
11 #include "cc/layers/layer.h"
12 #include "cc/layers/layer_impl.h"
13 #include "cc/trees/layer_tree_host.h"
14 #include "ui/gfx/geometry/point_f.h"
15 #include "ui/gfx/geometry/vector2d_conversions.h"
17 namespace cc {
19 class LayerTreeHost;
21 namespace {
23 template <typename LayerType>
24 struct DataForRecursion {
25 TransformTree* transform_tree;
26 ClipTree* clip_tree;
27 OpacityTree* opacity_tree;
28 LayerType* transform_tree_parent;
29 LayerType* transform_fixed_parent;
30 LayerType* render_target;
31 int clip_tree_parent;
32 int opacity_tree_parent;
33 const LayerType* page_scale_layer;
34 const LayerType* inner_viewport_scroll_layer;
35 const LayerType* outer_viewport_scroll_layer;
36 float page_scale_factor;
37 float device_scale_factor;
38 bool in_subtree_of_page_scale_layer;
39 bool affected_by_inner_viewport_bounds_delta;
40 bool affected_by_outer_viewport_bounds_delta;
41 bool should_flatten;
42 bool ancestor_clips_subtree;
43 const gfx::Transform* device_transform;
44 gfx::Vector2dF scroll_compensation_adjustment;
45 int sequence_number;
48 template <typename LayerType>
49 static LayerType* GetTransformParent(const DataForRecursion<LayerType>& data,
50 LayerType* layer) {
51 return layer->position_constraint().is_fixed_position()
52 ? data.transform_fixed_parent
53 : data.transform_tree_parent;
56 template <typename LayerType>
57 static ClipNode* GetClipParent(const DataForRecursion<LayerType>& data,
58 LayerType* layer) {
59 const bool inherits_clip = !layer->parent() || !layer->clip_parent();
60 const int id = inherits_clip ? data.clip_tree_parent
61 : layer->clip_parent()->clip_tree_index();
62 return data.clip_tree->Node(id);
65 template <typename LayerType>
66 static bool RequiresClipNode(LayerType* layer,
67 const DataForRecursion<LayerType>& data,
68 int parent_transform_id,
69 bool is_clipped) {
70 const bool render_surface_applies_clip =
71 layer->render_surface() && is_clipped;
72 const bool render_surface_may_grow_due_to_clip_children =
73 layer->render_surface() && layer->num_unclipped_descendants() > 0;
75 if (layer->masks_to_bounds() || layer->mask_layer() ||
76 render_surface_may_grow_due_to_clip_children)
77 return true;
79 if (!render_surface_applies_clip)
80 return false;
82 return !!layer->parent();
85 template <typename LayerType>
86 static bool LayerClipsSubtree(LayerType* layer) {
87 return layer->masks_to_bounds() || layer->mask_layer();
90 template <typename LayerType>
91 void AddClipNodeIfNeeded(const DataForRecursion<LayerType>& data_from_ancestor,
92 LayerType* layer,
93 bool created_transform_node,
94 DataForRecursion<LayerType>* data_for_children) {
95 ClipNode* parent = GetClipParent(data_from_ancestor, layer);
96 int parent_id = parent->id;
98 bool ancestor_clips_subtree =
99 data_from_ancestor.ancestor_clips_subtree ||
100 (layer->clip_parent() && layer->clip_parent()->is_clipped());
102 data_for_children->ancestor_clips_subtree = false;
103 bool has_unclipped_surface = false;
105 if (layer->has_render_surface()) {
106 if (ancestor_clips_subtree && layer->num_unclipped_descendants() > 0)
107 data_for_children->ancestor_clips_subtree = true;
108 else if (!ancestor_clips_subtree && !layer->num_unclipped_descendants())
109 has_unclipped_surface = true;
110 } else {
111 data_for_children->ancestor_clips_subtree = ancestor_clips_subtree;
114 bool layer_clips_subtree = LayerClipsSubtree(layer);
115 if (layer_clips_subtree)
116 data_for_children->ancestor_clips_subtree = true;
118 if (has_unclipped_surface)
119 parent_id = 0;
121 if (!RequiresClipNode(layer, data_from_ancestor, parent->data.transform_id,
122 ancestor_clips_subtree)) {
123 // Unclipped surfaces reset the clip rect.
124 data_for_children->clip_tree_parent = parent_id;
125 } else {
126 LayerType* transform_parent = data_for_children->transform_tree_parent;
127 if (layer->position_constraint().is_fixed_position() &&
128 !created_transform_node) {
129 transform_parent = data_for_children->transform_fixed_parent;
131 ClipNode node;
132 node.data.clip = gfx::RectF(
133 gfx::PointF() + layer->offset_to_transform_parent(), layer->bounds());
134 node.data.transform_id = transform_parent->transform_tree_index();
135 node.data.target_id =
136 data_for_children->render_target->transform_tree_index();
137 node.owner_id = layer->id();
138 node.data.inherit_parent_target_space_clip =
139 !data_for_children->ancestor_clips_subtree &&
140 layer->has_render_surface() && ancestor_clips_subtree;
141 node.data.requires_tight_clip_rect =
142 ancestor_clips_subtree &&
143 (!layer->render_surface() ||
144 (layer->render_surface() && !layer_clips_subtree &&
145 layer->num_unclipped_descendants()));
146 data_for_children->clip_tree_parent =
147 data_for_children->clip_tree->Insert(node, parent_id);
150 layer->SetClipTreeIndex(
151 has_unclipped_surface ? 0 : data_for_children->clip_tree_parent);
153 layer->set_is_clipped(data_for_children->ancestor_clips_subtree);
155 // TODO(awoloszyn): Right now when we hit a node with a replica, we reset the
156 // clip for all children since we may need to draw. We need to figure out a
157 // better way, since we will need both the clipped and unclipped versions.
160 template <typename LayerType>
161 bool AddTransformNodeIfNeeded(
162 const DataForRecursion<LayerType>& data_from_ancestor,
163 LayerType* layer,
164 DataForRecursion<LayerType>* data_for_children) {
165 const bool is_root = !layer->parent();
166 const bool is_page_scale_layer = layer == data_from_ancestor.page_scale_layer;
167 const bool is_scrollable = layer->scrollable();
168 const bool is_fixed = layer->position_constraint().is_fixed_position();
170 const bool has_significant_transform =
171 !layer->transform().IsIdentityOr2DTranslation();
173 const bool has_potentially_animated_transform =
174 layer->HasPotentiallyRunningTransformAnimation();
176 // A transform node is needed even for a finished animation, since differences
177 // in the timing of animation state updates can mean that an animation that's
178 // in the Finished state at tree-building time on the main thread is still in
179 // the Running state right after commit on the compositor thread.
180 const bool has_any_transform_animation =
181 layer->HasAnyAnimationTargetingProperty(Animation::TRANSFORM);
183 const bool has_surface = !!layer->render_surface();
185 bool requires_node = is_root || is_scrollable || has_significant_transform ||
186 has_any_transform_animation || has_surface || is_fixed ||
187 is_page_scale_layer;
189 LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer);
190 DCHECK_IMPLIES(!is_root, transform_parent);
192 int parent_index = 0;
193 if (transform_parent)
194 parent_index = transform_parent->transform_tree_index();
196 int source_index = parent_index;
198 gfx::Vector2dF source_offset;
199 if (transform_parent) {
200 if (layer->scroll_parent()) {
201 LayerType* source = layer->parent();
202 source_offset += source->offset_to_transform_parent();
203 source_index = source->transform_tree_index();
204 } else if (!is_fixed) {
205 source_offset = transform_parent->offset_to_transform_parent();
206 } else {
207 source_offset = data_from_ancestor.transform_tree_parent
208 ->offset_to_transform_parent();
209 source_index =
210 data_from_ancestor.transform_tree_parent->transform_tree_index();
211 source_offset += data_from_ancestor.scroll_compensation_adjustment;
215 if (layer->IsContainerForFixedPositionLayers() || is_root) {
216 data_for_children->affected_by_inner_viewport_bounds_delta =
217 layer == data_from_ancestor.inner_viewport_scroll_layer;
218 data_for_children->affected_by_outer_viewport_bounds_delta =
219 layer == data_from_ancestor.outer_viewport_scroll_layer;
220 if (is_scrollable) {
221 DCHECK(!is_root);
222 DCHECK(layer->transform().IsIdentity());
223 data_for_children->transform_fixed_parent = layer->parent();
224 } else {
225 data_for_children->transform_fixed_parent = layer;
228 data_for_children->transform_tree_parent = layer;
230 if (layer->IsContainerForFixedPositionLayers() || is_fixed)
231 data_for_children->scroll_compensation_adjustment = gfx::Vector2dF();
233 if (!requires_node) {
234 data_for_children->should_flatten |= layer->should_flatten_transform();
235 gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() +
236 layer->transform().To2dTranslation();
237 gfx::Vector2dF source_to_parent;
238 if (source_index != parent_index) {
239 gfx::Transform to_parent;
240 data_from_ancestor.transform_tree->ComputeTransform(
241 source_index, parent_index, &to_parent);
242 source_to_parent = to_parent.To2dTranslation();
244 layer->set_offset_to_transform_parent(source_offset + source_to_parent +
245 local_offset);
246 layer->set_should_flatten_transform_from_property_tree(
247 data_from_ancestor.should_flatten);
248 layer->SetTransformTreeIndex(parent_index);
249 return false;
252 data_for_children->transform_tree->Insert(TransformNode(), parent_index);
254 TransformNode* node = data_for_children->transform_tree->back();
255 layer->SetTransformTreeIndex(node->id);
257 node->data.scrolls = is_scrollable;
258 node->data.flattens_inherited_transform = data_for_children->should_flatten;
260 // Surfaces inherently flatten transforms.
261 data_for_children->should_flatten =
262 layer->should_flatten_transform() || has_surface;
263 node->data.target_id =
264 data_from_ancestor.render_target->transform_tree_index();
265 node->data.content_target_id =
266 data_for_children->render_target->transform_tree_index();
267 DCHECK_NE(node->data.target_id, -1);
268 node->data.is_animated = has_potentially_animated_transform;
270 float post_local_scale_factor = 1.0f;
271 if (is_root) {
272 node->data.post_local = *data_from_ancestor.device_transform;
273 post_local_scale_factor = data_from_ancestor.device_scale_factor;
276 if (is_page_scale_layer)
277 post_local_scale_factor *= data_from_ancestor.page_scale_factor;
279 if (has_surface && !is_root) {
280 node->data.needs_sublayer_scale = true;
281 node->data.layer_scale_factor = data_from_ancestor.device_scale_factor;
282 if (data_from_ancestor.in_subtree_of_page_scale_layer)
283 node->data.layer_scale_factor *= data_from_ancestor.page_scale_factor;
286 node->data.source_node_id = source_index;
287 if (is_root) {
288 node->data.post_local.Scale(post_local_scale_factor,
289 post_local_scale_factor);
290 node->data.post_local.Translate(layer->position().x(),
291 layer->position().y());
292 } else {
293 node->data.post_local_scale_factor = post_local_scale_factor;
294 node->data.source_offset = source_offset;
295 node->data.update_post_local_transform(layer->position(),
296 layer->transform_origin());
299 if (!layer->scroll_parent())
300 node->data.scroll_offset = layer->CurrentScrollOffset();
302 if (is_fixed) {
303 if (data_from_ancestor.affected_by_inner_viewport_bounds_delta) {
304 node->data.affected_by_inner_viewport_bounds_delta_x =
305 layer->position_constraint().is_fixed_to_right_edge();
306 node->data.affected_by_inner_viewport_bounds_delta_y =
307 layer->position_constraint().is_fixed_to_bottom_edge();
308 if (node->data.affected_by_inner_viewport_bounds_delta_x ||
309 node->data.affected_by_inner_viewport_bounds_delta_y) {
310 data_for_children->transform_tree
311 ->AddNodeAffectedByInnerViewportBoundsDelta(node->id);
313 } else if (data_from_ancestor.affected_by_outer_viewport_bounds_delta) {
314 node->data.affected_by_outer_viewport_bounds_delta_x =
315 layer->position_constraint().is_fixed_to_right_edge();
316 node->data.affected_by_outer_viewport_bounds_delta_y =
317 layer->position_constraint().is_fixed_to_bottom_edge();
318 if (node->data.affected_by_outer_viewport_bounds_delta_x ||
319 node->data.affected_by_outer_viewport_bounds_delta_y) {
320 data_for_children->transform_tree
321 ->AddNodeAffectedByOuterViewportBoundsDelta(node->id);
326 node->data.local = layer->transform();
327 node->data.update_pre_local_transform(layer->transform_origin());
329 node->data.needs_local_transform_update = true;
330 data_from_ancestor.transform_tree->UpdateTransforms(node->id);
332 layer->set_offset_to_transform_parent(gfx::Vector2dF());
334 // Flattening (if needed) will be handled by |node|.
335 layer->set_should_flatten_transform_from_property_tree(false);
337 data_for_children->scroll_compensation_adjustment +=
338 layer->ScrollCompensationAdjustment() - node->data.scroll_snap;
340 node->owner_id = layer->id();
342 return true;
345 bool IsAnimatingOpacity(Layer* layer) {
346 return layer->HasPotentiallyRunningOpacityAnimation() ||
347 layer->OpacityCanAnimateOnImplThread();
350 bool IsAnimatingOpacity(LayerImpl* layer) {
351 return layer->HasPotentiallyRunningOpacityAnimation();
354 template <typename LayerType>
355 void AddOpacityNodeIfNeeded(
356 const DataForRecursion<LayerType>& data_from_ancestor,
357 LayerType* layer,
358 DataForRecursion<LayerType>* data_for_children) {
359 const bool is_root = !layer->parent();
360 const bool has_transparency = layer->opacity() != 1.f;
361 const bool has_animated_opacity = IsAnimatingOpacity(layer);
362 bool requires_node = is_root || has_transparency || has_animated_opacity;
364 int parent_id = data_from_ancestor.opacity_tree_parent;
366 if (!requires_node) {
367 layer->SetOpacityTreeIndex(parent_id);
368 data_for_children->opacity_tree_parent = parent_id;
369 return;
372 OpacityNode node;
373 node.owner_id = layer->id();
374 node.data.opacity = layer->opacity();
375 node.data.screen_space_opacity = layer->opacity();
376 if (!is_root)
377 node.data.screen_space_opacity *=
378 data_from_ancestor.opacity_tree->Node(parent_id)
379 ->data.screen_space_opacity;
380 data_for_children->opacity_tree_parent =
381 data_for_children->opacity_tree->Insert(node, parent_id);
382 layer->SetOpacityTreeIndex(data_for_children->opacity_tree_parent);
385 template <typename LayerType>
386 void BuildPropertyTreesInternal(
387 LayerType* layer,
388 const DataForRecursion<LayerType>& data_from_parent) {
389 layer->set_property_tree_sequence_number(data_from_parent.sequence_number);
390 DataForRecursion<LayerType> data_for_children(data_from_parent);
391 if (layer->render_surface())
392 data_for_children.render_target = layer;
394 bool created_transform_node =
395 AddTransformNodeIfNeeded(data_from_parent, layer, &data_for_children);
396 AddClipNodeIfNeeded(data_from_parent, layer, created_transform_node,
397 &data_for_children);
399 if (data_from_parent.opacity_tree)
400 AddOpacityNodeIfNeeded(data_from_parent, layer, &data_for_children);
402 if (layer == data_from_parent.page_scale_layer)
403 data_for_children.in_subtree_of_page_scale_layer = true;
405 for (size_t i = 0; i < layer->children().size(); ++i) {
406 if (!layer->child_at(i)->scroll_parent()) {
407 BuildPropertyTreesInternal(layer->child_at(i), data_for_children);
408 } else {
409 // The child should be included in its scroll parent's list of scroll
410 // children.
411 DCHECK(layer->child_at(i)->scroll_parent()->scroll_children()->count(
412 layer->child_at(i)));
416 if (layer->scroll_children()) {
417 for (LayerType* scroll_child : *layer->scroll_children()) {
418 DCHECK_EQ(scroll_child->scroll_parent(), layer);
419 BuildPropertyTreesInternal(scroll_child, data_for_children);
423 if (layer->has_replica())
424 BuildPropertyTreesInternal(layer->replica_layer(), data_for_children);
427 } // namespace
429 template <typename LayerType>
430 void BuildPropertyTreesTopLevelInternal(
431 LayerType* root_layer,
432 const LayerType* page_scale_layer,
433 const LayerType* inner_viewport_scroll_layer,
434 const LayerType* outer_viewport_scroll_layer,
435 float page_scale_factor,
436 float device_scale_factor,
437 const gfx::Rect& viewport,
438 const gfx::Transform& device_transform,
439 PropertyTrees* property_trees) {
440 if (!property_trees->needs_rebuild)
441 return;
443 property_trees->sequence_number++;
445 DataForRecursion<LayerType> data_for_recursion;
446 data_for_recursion.transform_tree = &property_trees->transform_tree;
447 data_for_recursion.clip_tree = &property_trees->clip_tree;
448 data_for_recursion.opacity_tree = &property_trees->opacity_tree;
449 data_for_recursion.transform_tree_parent = nullptr;
450 data_for_recursion.transform_fixed_parent = nullptr;
451 data_for_recursion.render_target = root_layer;
452 data_for_recursion.clip_tree_parent = 0;
453 data_for_recursion.opacity_tree_parent = -1;
454 data_for_recursion.page_scale_layer = page_scale_layer;
455 data_for_recursion.inner_viewport_scroll_layer = inner_viewport_scroll_layer;
456 data_for_recursion.outer_viewport_scroll_layer = outer_viewport_scroll_layer;
457 data_for_recursion.page_scale_factor = page_scale_factor;
458 data_for_recursion.device_scale_factor = device_scale_factor;
459 data_for_recursion.in_subtree_of_page_scale_layer = false;
460 data_for_recursion.affected_by_inner_viewport_bounds_delta = false;
461 data_for_recursion.affected_by_outer_viewport_bounds_delta = false;
462 data_for_recursion.should_flatten = false;
463 data_for_recursion.ancestor_clips_subtree = true;
464 data_for_recursion.device_transform = &device_transform;
466 data_for_recursion.transform_tree->clear();
467 data_for_recursion.clip_tree->clear();
468 data_for_recursion.opacity_tree->clear();
469 data_for_recursion.sequence_number = property_trees->sequence_number;
471 ClipNode root_clip;
472 root_clip.data.clip = viewport;
473 root_clip.data.transform_id = 0;
474 data_for_recursion.clip_tree_parent =
475 data_for_recursion.clip_tree->Insert(root_clip, 0);
476 BuildPropertyTreesInternal(root_layer, data_for_recursion);
477 property_trees->needs_rebuild = false;
479 // The transform tree is kept up-to-date as it is built, but the
480 // combined_clips stored in the clip tree aren't computed during tree
481 // building.
482 property_trees->transform_tree.set_needs_update(false);
483 property_trees->clip_tree.set_needs_update(true);
484 property_trees->opacity_tree.set_needs_update(false);
487 void PropertyTreeBuilder::BuildPropertyTrees(
488 Layer* root_layer,
489 const Layer* page_scale_layer,
490 const Layer* inner_viewport_scroll_layer,
491 const Layer* outer_viewport_scroll_layer,
492 float page_scale_factor,
493 float device_scale_factor,
494 const gfx::Rect& viewport,
495 const gfx::Transform& device_transform,
496 PropertyTrees* property_trees) {
497 BuildPropertyTreesTopLevelInternal(
498 root_layer, page_scale_layer, inner_viewport_scroll_layer,
499 outer_viewport_scroll_layer, page_scale_factor, device_scale_factor,
500 viewport, device_transform, property_trees);
503 void PropertyTreeBuilder::BuildPropertyTrees(
504 LayerImpl* root_layer,
505 const LayerImpl* page_scale_layer,
506 const LayerImpl* inner_viewport_scroll_layer,
507 const LayerImpl* outer_viewport_scroll_layer,
508 float page_scale_factor,
509 float device_scale_factor,
510 const gfx::Rect& viewport,
511 const gfx::Transform& device_transform,
512 PropertyTrees* property_trees) {
513 BuildPropertyTreesTopLevelInternal(
514 root_layer, page_scale_layer, inner_viewport_scroll_layer,
515 outer_viewport_scroll_layer, page_scale_factor, device_scale_factor,
516 viewport, device_transform, property_trees);
519 } // namespace cc