Roll src/third_party/skia d32087a:1052f51
[chromium-blink-merge.git] / cc / trees / property_tree_builder.cc
blob36d74684d7ac68430b0e2df5b542dabcb55d74de
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 static const int kInvalidPropertyTreeNodeId = -1;
24 static const int kRootPropertyTreeNodeId = 0;
25 static const int kUnclippedRootClipTreeNodeId = 0;
27 template <typename LayerType>
28 struct DataForRecursion {
29 TransformTree* transform_tree;
30 ClipTree* clip_tree;
31 EffectTree* effect_tree;
32 LayerType* transform_tree_parent;
33 LayerType* transform_fixed_parent;
34 int render_target;
35 int clip_tree_parent;
36 int effect_tree_parent;
37 const LayerType* page_scale_layer;
38 const LayerType* inner_viewport_scroll_layer;
39 const LayerType* outer_viewport_scroll_layer;
40 float page_scale_factor;
41 float device_scale_factor;
42 bool in_subtree_of_page_scale_layer;
43 bool affected_by_inner_viewport_bounds_delta;
44 bool affected_by_outer_viewport_bounds_delta;
45 bool should_flatten;
46 bool ancestor_clips_subtree;
47 const gfx::Transform* device_transform;
48 gfx::Vector2dF scroll_compensation_adjustment;
49 int sequence_number;
52 template <typename LayerType>
53 static LayerType* GetTransformParent(const DataForRecursion<LayerType>& data,
54 LayerType* layer) {
55 return layer->position_constraint().is_fixed_position()
56 ? data.transform_fixed_parent
57 : data.transform_tree_parent;
60 template <typename LayerType>
61 static ClipNode* GetClipParent(const DataForRecursion<LayerType>& data,
62 LayerType* layer) {
63 const bool inherits_clip = !layer->parent() || !layer->clip_parent();
64 const int id = inherits_clip ? data.clip_tree_parent
65 : layer->clip_parent()->clip_tree_index();
66 return data.clip_tree->Node(id);
69 template <typename LayerType>
70 static bool RequiresClipNode(LayerType* layer,
71 const DataForRecursion<LayerType>& data,
72 int parent_transform_id,
73 bool is_clipped) {
74 const bool render_surface_applies_clip =
75 layer->has_render_surface() && is_clipped;
76 const bool render_surface_may_grow_due_to_clip_children =
77 layer->has_render_surface() && layer->num_unclipped_descendants() > 0;
79 if (layer->masks_to_bounds() || layer->mask_layer() ||
80 render_surface_may_grow_due_to_clip_children)
81 return true;
83 if (!render_surface_applies_clip)
84 return false;
86 return true;
89 template <typename LayerType>
90 static bool LayerClipsSubtree(LayerType* layer) {
91 return layer->masks_to_bounds() || layer->mask_layer();
94 template <typename LayerType>
95 void AddClipNodeIfNeeded(const DataForRecursion<LayerType>& data_from_ancestor,
96 LayerType* layer,
97 bool created_render_surface,
98 bool created_transform_node,
99 DataForRecursion<LayerType>* data_for_children) {
100 ClipNode* parent = GetClipParent(data_from_ancestor, layer);
101 int parent_id = parent->id;
103 bool ancestor_clips_subtree =
104 data_from_ancestor.ancestor_clips_subtree ||
105 (layer->clip_parent() && layer->clip_parent()->is_clipped());
107 data_for_children->ancestor_clips_subtree = false;
108 bool has_unclipped_surface = false;
110 if (layer->has_render_surface()) {
111 if (ancestor_clips_subtree && layer->num_unclipped_descendants() > 0)
112 data_for_children->ancestor_clips_subtree = true;
113 else if (!ancestor_clips_subtree)
114 has_unclipped_surface = true;
115 } else {
116 data_for_children->ancestor_clips_subtree = ancestor_clips_subtree;
119 bool layer_clips_subtree = LayerClipsSubtree(layer);
120 if (layer_clips_subtree)
121 data_for_children->ancestor_clips_subtree = true;
123 if (has_unclipped_surface) {
124 parent_id = kUnclippedRootClipTreeNodeId;
125 data_for_children->effect_tree->Node(data_for_children->render_target)
126 ->data.clip_id = kUnclippedRootClipTreeNodeId;
128 if (!RequiresClipNode(layer, data_from_ancestor, parent->data.transform_id,
129 ancestor_clips_subtree)) {
130 // Unclipped surfaces reset the clip rect.
131 data_for_children->clip_tree_parent = parent_id;
132 } else {
133 LayerType* transform_parent = data_for_children->transform_tree_parent;
134 if (layer->position_constraint().is_fixed_position() &&
135 !created_transform_node) {
136 transform_parent = data_for_children->transform_fixed_parent;
138 ClipNode node;
139 node.data.clip = gfx::RectF(
140 gfx::PointF() + layer->offset_to_transform_parent(), layer->bounds());
141 node.data.transform_id = transform_parent->transform_tree_index();
142 node.data.target_id =
143 data_for_children->effect_tree->Node(data_for_children->render_target)
144 ->data.transform_id;
145 node.owner_id = layer->id();
146 node.data.inherit_parent_target_space_clip = !layer_clips_subtree &&
147 layer->has_render_surface() &&
148 ancestor_clips_subtree;
149 node.data.requires_tight_clip_rect =
150 ancestor_clips_subtree &&
151 (!layer->has_render_surface() ||
152 (!layer_clips_subtree && layer->num_unclipped_descendants()));
154 node.data.render_surface_is_clipped = layer->has_render_surface() &&
155 ancestor_clips_subtree &&
156 !layer->num_unclipped_descendants();
158 data_for_children->clip_tree_parent =
159 data_for_children->clip_tree->Insert(node, parent_id);
162 layer->SetClipTreeIndex(data_for_children->clip_tree_parent);
164 layer->set_is_clipped(data_for_children->ancestor_clips_subtree);
166 // TODO(awoloszyn): Right now when we hit a node with a replica, we reset the
167 // clip for all children since we may need to draw. We need to figure out a
168 // better way, since we will need both the clipped and unclipped versions.
171 template <typename LayerType>
172 bool AddTransformNodeIfNeeded(
173 const DataForRecursion<LayerType>& data_from_ancestor,
174 LayerType* layer,
175 bool created_render_surface,
176 DataForRecursion<LayerType>* data_for_children) {
177 const bool is_root = !layer->parent();
178 const bool is_page_scale_layer = layer == data_from_ancestor.page_scale_layer;
179 const bool is_scrollable = layer->scrollable();
180 const bool is_fixed = layer->position_constraint().is_fixed_position();
182 const bool has_significant_transform =
183 !layer->transform().IsIdentityOr2DTranslation();
185 const bool has_potentially_animated_transform =
186 layer->HasPotentiallyRunningTransformAnimation();
188 // A transform node is needed even for a finished animation, since differences
189 // in the timing of animation state updates can mean that an animation that's
190 // in the Finished state at tree-building time on the main thread is still in
191 // the Running state right after commit on the compositor thread.
192 const bool has_any_transform_animation =
193 layer->HasAnyAnimationTargetingProperty(Animation::TRANSFORM);
195 const bool has_surface = layer->has_render_surface();
197 bool requires_node = is_root || is_scrollable || has_significant_transform ||
198 has_any_transform_animation || has_surface || is_fixed ||
199 is_page_scale_layer;
201 LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer);
202 DCHECK_IMPLIES(!is_root, transform_parent);
204 int parent_index = kRootPropertyTreeNodeId;
205 if (transform_parent)
206 parent_index = transform_parent->transform_tree_index();
208 int source_index = parent_index;
210 gfx::Vector2dF source_offset;
211 if (transform_parent) {
212 if (layer->scroll_parent()) {
213 LayerType* source = layer->parent();
214 source_offset += source->offset_to_transform_parent();
215 source_index = source->transform_tree_index();
216 } else if (!is_fixed) {
217 source_offset = transform_parent->offset_to_transform_parent();
218 } else {
219 source_offset = data_from_ancestor.transform_tree_parent
220 ->offset_to_transform_parent();
221 source_index =
222 data_from_ancestor.transform_tree_parent->transform_tree_index();
223 source_offset += data_from_ancestor.scroll_compensation_adjustment;
227 if (layer->IsContainerForFixedPositionLayers() || is_root) {
228 data_for_children->affected_by_inner_viewport_bounds_delta =
229 layer == data_from_ancestor.inner_viewport_scroll_layer;
230 data_for_children->affected_by_outer_viewport_bounds_delta =
231 layer == data_from_ancestor.outer_viewport_scroll_layer;
232 if (is_scrollable) {
233 DCHECK(!is_root);
234 DCHECK(layer->transform().IsIdentity());
235 data_for_children->transform_fixed_parent = layer->parent();
236 } else {
237 data_for_children->transform_fixed_parent = layer;
240 data_for_children->transform_tree_parent = layer;
242 if (layer->IsContainerForFixedPositionLayers() || is_fixed)
243 data_for_children->scroll_compensation_adjustment = gfx::Vector2dF();
245 if (!requires_node) {
246 data_for_children->should_flatten |= layer->should_flatten_transform();
247 gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() +
248 layer->transform().To2dTranslation();
249 gfx::Vector2dF source_to_parent;
250 if (source_index != parent_index) {
251 gfx::Transform to_parent;
252 data_from_ancestor.transform_tree->ComputeTransform(
253 source_index, parent_index, &to_parent);
254 source_to_parent = to_parent.To2dTranslation();
256 layer->set_offset_to_transform_parent(source_offset + source_to_parent +
257 local_offset);
258 layer->set_should_flatten_transform_from_property_tree(
259 data_from_ancestor.should_flatten);
260 layer->SetTransformTreeIndex(parent_index);
261 return false;
264 data_for_children->transform_tree->Insert(TransformNode(), parent_index);
266 TransformNode* node = data_for_children->transform_tree->back();
267 layer->SetTransformTreeIndex(node->id);
269 node->data.scrolls = is_scrollable;
270 node->data.flattens_inherited_transform = data_for_children->should_flatten;
272 // Surfaces inherently flatten transforms.
273 data_for_children->should_flatten =
274 layer->should_flatten_transform() || has_surface;
275 DCHECK_GT(data_from_ancestor.effect_tree->size(), 0u);
277 node->data.target_id =
278 data_for_children->effect_tree->Node(data_from_ancestor.render_target)
279 ->data.transform_id;
280 node->data.content_target_id =
281 data_for_children->effect_tree->Node(data_for_children->render_target)
282 ->data.transform_id;
283 DCHECK_NE(node->data.target_id, kInvalidPropertyTreeNodeId);
285 node->data.is_animated = has_potentially_animated_transform;
286 if (has_potentially_animated_transform) {
287 float maximum_animation_target_scale = 0.f;
288 if (layer->MaximumTargetScale(&maximum_animation_target_scale)) {
289 node->data.local_maximum_animation_target_scale =
290 maximum_animation_target_scale;
293 float starting_animation_scale = 0.f;
294 if (layer->AnimationStartScale(&starting_animation_scale)) {
295 node->data.local_starting_animation_scale = starting_animation_scale;
298 node->data.has_only_translation_animations =
299 layer->HasOnlyTranslationTransforms();
302 float post_local_scale_factor = 1.0f;
303 if (is_root) {
304 node->data.post_local = *data_from_ancestor.device_transform;
305 post_local_scale_factor = data_from_ancestor.device_scale_factor;
308 if (is_page_scale_layer)
309 post_local_scale_factor *= data_from_ancestor.page_scale_factor;
311 if (has_surface && !is_root) {
312 node->data.needs_sublayer_scale = true;
313 node->data.layer_scale_factor = data_from_ancestor.device_scale_factor;
314 if (data_from_ancestor.in_subtree_of_page_scale_layer)
315 node->data.layer_scale_factor *= data_from_ancestor.page_scale_factor;
318 node->data.source_node_id = source_index;
319 if (is_root) {
320 node->data.post_local.Scale(post_local_scale_factor,
321 post_local_scale_factor);
322 node->data.post_local.Translate(layer->position().x(),
323 layer->position().y());
324 } else {
325 node->data.post_local_scale_factor = post_local_scale_factor;
326 node->data.source_offset = source_offset;
327 node->data.update_post_local_transform(layer->position(),
328 layer->transform_origin());
331 if (!layer->scroll_parent())
332 node->data.scroll_offset = layer->CurrentScrollOffset();
334 if (is_fixed) {
335 if (data_from_ancestor.affected_by_inner_viewport_bounds_delta) {
336 node->data.affected_by_inner_viewport_bounds_delta_x =
337 layer->position_constraint().is_fixed_to_right_edge();
338 node->data.affected_by_inner_viewport_bounds_delta_y =
339 layer->position_constraint().is_fixed_to_bottom_edge();
340 if (node->data.affected_by_inner_viewport_bounds_delta_x ||
341 node->data.affected_by_inner_viewport_bounds_delta_y) {
342 data_for_children->transform_tree
343 ->AddNodeAffectedByInnerViewportBoundsDelta(node->id);
345 } else if (data_from_ancestor.affected_by_outer_viewport_bounds_delta) {
346 node->data.affected_by_outer_viewport_bounds_delta_x =
347 layer->position_constraint().is_fixed_to_right_edge();
348 node->data.affected_by_outer_viewport_bounds_delta_y =
349 layer->position_constraint().is_fixed_to_bottom_edge();
350 if (node->data.affected_by_outer_viewport_bounds_delta_x ||
351 node->data.affected_by_outer_viewport_bounds_delta_y) {
352 data_for_children->transform_tree
353 ->AddNodeAffectedByOuterViewportBoundsDelta(node->id);
358 node->data.local = layer->transform();
359 node->data.update_pre_local_transform(layer->transform_origin());
361 node->data.needs_local_transform_update = true;
362 data_from_ancestor.transform_tree->UpdateTransforms(node->id);
364 layer->set_offset_to_transform_parent(gfx::Vector2dF());
366 // Flattening (if needed) will be handled by |node|.
367 layer->set_should_flatten_transform_from_property_tree(false);
369 data_for_children->scroll_compensation_adjustment +=
370 layer->ScrollCompensationAdjustment() - node->data.scroll_snap;
372 node->owner_id = layer->id();
374 return true;
377 bool IsAnimatingOpacity(Layer* layer) {
378 return layer->HasPotentiallyRunningOpacityAnimation() ||
379 layer->OpacityCanAnimateOnImplThread();
382 bool IsAnimatingOpacity(LayerImpl* layer) {
383 return layer->HasPotentiallyRunningOpacityAnimation();
386 template <typename LayerType>
387 bool AddEffectNodeIfNeeded(
388 const DataForRecursion<LayerType>& data_from_ancestor,
389 LayerType* layer,
390 DataForRecursion<LayerType>* data_for_children) {
391 const bool is_root = !layer->parent();
392 const bool has_transparency = layer->opacity() != 1.f;
393 const bool has_animated_opacity = IsAnimatingOpacity(layer);
394 const bool has_render_surface = layer->has_render_surface();
395 bool requires_node =
396 is_root || has_transparency || has_animated_opacity || has_render_surface;
398 int parent_id = data_from_ancestor.effect_tree_parent;
400 if (!requires_node) {
401 layer->SetEffectTreeIndex(parent_id);
402 data_for_children->effect_tree_parent = parent_id;
403 return false;
406 EffectNode node;
407 node.owner_id = layer->id();
408 node.data.opacity = layer->opacity();
409 node.data.screen_space_opacity = layer->opacity();
410 node.data.has_render_surface = has_render_surface;
411 if (!is_root) {
412 // For every effect node, we create a transform node, so it's safe to use
413 // the next available id from the transform tree as this effect node's
414 // transform id.
415 node.data.transform_id =
416 data_from_ancestor.transform_tree->next_available_id();
417 node.data.clip_id = data_from_ancestor.clip_tree_parent;
419 node.data.screen_space_opacity *=
420 data_from_ancestor.effect_tree->Node(parent_id)
421 ->data.screen_space_opacity;
422 } else {
423 // Root render surface acts the unbounded and untransformed to draw content
424 // into. Transform node created from root layer (includes device scale
425 // factor) and clip node created from root layer (include viewports) applies
426 // to root render surface's content, but not root render surface itself.
427 node.data.transform_id = kRootPropertyTreeNodeId;
428 node.data.clip_id = kUnclippedRootClipTreeNodeId;
430 data_for_children->effect_tree_parent =
431 data_for_children->effect_tree->Insert(node, parent_id);
432 layer->SetEffectTreeIndex(data_for_children->effect_tree_parent);
433 return has_render_surface;
436 template <typename LayerType>
437 void BuildPropertyTreesInternal(
438 LayerType* layer,
439 const DataForRecursion<LayerType>& data_from_parent) {
440 layer->set_property_tree_sequence_number(data_from_parent.sequence_number);
441 DataForRecursion<LayerType> data_for_children(data_from_parent);
443 bool created_render_surface =
444 AddEffectNodeIfNeeded(data_from_parent, layer, &data_for_children);
446 if (created_render_surface) {
447 data_for_children.render_target = data_for_children.effect_tree_parent;
448 layer->set_draw_blend_mode(SkXfermode::kSrcOver_Mode);
449 } else {
450 layer->set_draw_blend_mode(layer->blend_mode());
453 bool created_transform_node = AddTransformNodeIfNeeded(
454 data_from_parent, layer, created_render_surface, &data_for_children);
455 AddClipNodeIfNeeded(data_from_parent, layer, created_render_surface,
456 created_transform_node, &data_for_children);
458 if (layer == data_from_parent.page_scale_layer)
459 data_for_children.in_subtree_of_page_scale_layer = true;
461 for (size_t i = 0; i < layer->children().size(); ++i) {
462 if (!layer->child_at(i)->scroll_parent()) {
463 BuildPropertyTreesInternal(layer->child_at(i), data_for_children);
464 } else {
465 // The child should be included in its scroll parent's list of scroll
466 // children.
467 DCHECK(layer->child_at(i)->scroll_parent()->scroll_children()->count(
468 layer->child_at(i)));
472 if (layer->scroll_children()) {
473 for (LayerType* scroll_child : *layer->scroll_children()) {
474 DCHECK_EQ(scroll_child->scroll_parent(), layer);
475 BuildPropertyTreesInternal(scroll_child, data_for_children);
479 if (layer->has_replica())
480 BuildPropertyTreesInternal(layer->replica_layer(), data_for_children);
483 } // namespace
485 template <typename LayerType>
486 void BuildPropertyTreesTopLevelInternal(
487 LayerType* root_layer,
488 const LayerType* page_scale_layer,
489 const LayerType* inner_viewport_scroll_layer,
490 const LayerType* outer_viewport_scroll_layer,
491 float page_scale_factor,
492 float device_scale_factor,
493 const gfx::Rect& viewport,
494 const gfx::Transform& device_transform,
495 PropertyTrees* property_trees) {
496 if (!property_trees->needs_rebuild)
497 return;
499 property_trees->sequence_number++;
501 DataForRecursion<LayerType> data_for_recursion;
502 data_for_recursion.transform_tree = &property_trees->transform_tree;
503 data_for_recursion.clip_tree = &property_trees->clip_tree;
504 data_for_recursion.effect_tree = &property_trees->effect_tree;
505 data_for_recursion.transform_tree_parent = nullptr;
506 data_for_recursion.transform_fixed_parent = nullptr;
507 data_for_recursion.render_target = kRootPropertyTreeNodeId;
508 data_for_recursion.clip_tree_parent = kUnclippedRootClipTreeNodeId;
509 data_for_recursion.effect_tree_parent = kInvalidPropertyTreeNodeId;
510 data_for_recursion.page_scale_layer = page_scale_layer;
511 data_for_recursion.inner_viewport_scroll_layer = inner_viewport_scroll_layer;
512 data_for_recursion.outer_viewport_scroll_layer = outer_viewport_scroll_layer;
513 data_for_recursion.page_scale_factor = page_scale_factor;
514 data_for_recursion.device_scale_factor = device_scale_factor;
515 data_for_recursion.in_subtree_of_page_scale_layer = false;
516 data_for_recursion.affected_by_inner_viewport_bounds_delta = false;
517 data_for_recursion.affected_by_outer_viewport_bounds_delta = false;
518 data_for_recursion.should_flatten = false;
519 data_for_recursion.ancestor_clips_subtree = true;
520 data_for_recursion.device_transform = &device_transform;
522 data_for_recursion.transform_tree->clear();
523 data_for_recursion.clip_tree->clear();
524 data_for_recursion.effect_tree->clear();
525 data_for_recursion.sequence_number = property_trees->sequence_number;
527 ClipNode root_clip;
528 root_clip.data.clip = gfx::RectF(viewport);
529 root_clip.data.transform_id = kRootPropertyTreeNodeId;
530 data_for_recursion.clip_tree_parent = data_for_recursion.clip_tree->Insert(
531 root_clip, kUnclippedRootClipTreeNodeId);
532 BuildPropertyTreesInternal(root_layer, data_for_recursion);
533 property_trees->needs_rebuild = false;
535 // The transform tree is kept up-to-date as it is built, but the
536 // combined_clips stored in the clip tree aren't computed during tree
537 // building.
538 property_trees->transform_tree.set_needs_update(false);
539 property_trees->clip_tree.set_needs_update(true);
540 property_trees->effect_tree.set_needs_update(false);
543 void PropertyTreeBuilder::BuildPropertyTrees(
544 Layer* root_layer,
545 const Layer* page_scale_layer,
546 const Layer* inner_viewport_scroll_layer,
547 const Layer* outer_viewport_scroll_layer,
548 float page_scale_factor,
549 float device_scale_factor,
550 const gfx::Rect& viewport,
551 const gfx::Transform& device_transform,
552 PropertyTrees* property_trees) {
553 BuildPropertyTreesTopLevelInternal(
554 root_layer, page_scale_layer, inner_viewport_scroll_layer,
555 outer_viewport_scroll_layer, page_scale_factor, device_scale_factor,
556 viewport, device_transform, property_trees);
559 void PropertyTreeBuilder::BuildPropertyTrees(
560 LayerImpl* root_layer,
561 const LayerImpl* page_scale_layer,
562 const LayerImpl* inner_viewport_scroll_layer,
563 const LayerImpl* outer_viewport_scroll_layer,
564 float page_scale_factor,
565 float device_scale_factor,
566 const gfx::Rect& viewport,
567 const gfx::Transform& device_transform,
568 PropertyTrees* property_trees) {
569 BuildPropertyTreesTopLevelInternal(
570 root_layer, page_scale_layer, inner_viewport_scroll_layer,
571 outer_viewport_scroll_layer, page_scale_factor, device_scale_factor,
572 viewport, device_transform, property_trees);
575 } // namespace cc