Pepper: Allow DidCreate to safely delete the plugin instance
[chromium-blink-merge.git] / cc / trees / property_tree_builder.cc
blob0c080dd2ace2e883c98e64cbcac10a239db34d0b
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/trees/layer_tree_host.h"
13 #include "ui/gfx/geometry/point_f.h"
15 namespace cc {
17 class LayerTreeHost;
19 namespace {
21 struct DataForRecursion {
22 TransformTree* transform_tree;
23 ClipTree* clip_tree;
24 OpacityTree* opacity_tree;
25 Layer* transform_tree_parent;
26 Layer* transform_fixed_parent;
27 Layer* render_target;
28 int clip_tree_parent;
29 int opacity_tree_parent;
30 gfx::Vector2dF offset_to_transform_tree_parent;
31 gfx::Vector2dF offset_to_transform_fixed_parent;
32 const Layer* page_scale_layer;
33 float page_scale_factor;
34 float device_scale_factor;
35 bool in_subtree_of_page_scale_application_layer;
36 const gfx::Transform* device_transform;
39 static Layer* GetTransformParent(const DataForRecursion& data, Layer* layer) {
40 return layer->position_constraint().is_fixed_position()
41 ? data.transform_fixed_parent
42 : data.transform_tree_parent;
45 static ClipNode* GetClipParent(const DataForRecursion& data, Layer* layer) {
46 const bool inherits_clip = !layer->parent() || !layer->clip_parent();
47 const int id = inherits_clip ? data.clip_tree_parent
48 : layer->clip_parent()->clip_tree_index();
49 return data.clip_tree->Node(id);
52 static bool RequiresClipNode(Layer* layer,
53 bool axis_aligned_with_respect_to_parent) {
54 const bool render_surface_applies_non_axis_aligned_clip =
55 layer->render_surface() && !axis_aligned_with_respect_to_parent &&
56 layer->is_clipped();
57 const bool render_surface_may_grow_due_to_clip_children =
58 layer->render_surface() && layer->num_unclipped_descendants() > 0;
60 return !layer->parent() || layer->masks_to_bounds() || layer->mask_layer() ||
61 render_surface_applies_non_axis_aligned_clip ||
62 render_surface_may_grow_due_to_clip_children;
65 void AddClipNodeIfNeeded(const DataForRecursion& data_from_ancestor,
66 Layer* layer,
67 DataForRecursion* data_for_children) {
68 ClipNode* parent = GetClipParent(data_from_ancestor, layer);
69 int parent_id = parent->id;
70 const bool axis_aligned_with_respect_to_parent =
71 data_from_ancestor.transform_tree->Are2DAxisAligned(
72 layer->transform_tree_index(), parent->data.transform_id);
74 // TODO(vollick): once Andrew refactors the surface determinations out of
75 // CDP, the the layer->render_surface() check will be invalid.
76 const bool has_unclipped_surface =
77 layer->render_surface() &&
78 !layer->render_surface()->is_clipped() &&
79 layer->num_unclipped_descendants() == 0;
81 if (has_unclipped_surface)
82 parent_id = 0;
84 if (!RequiresClipNode(layer, axis_aligned_with_respect_to_parent)) {
85 // Unclipped surfaces reset the clip rect.
86 data_for_children->clip_tree_parent = parent_id;
87 } else if (layer->parent()) {
88 // Note the root clip gets handled elsewhere.
89 Layer* transform_parent = GetTransformParent(*data_for_children, layer);
90 ClipNode node;
91 node.data.clip = gfx::RectF(
92 gfx::PointF() + layer->offset_to_transform_parent(), layer->bounds());
93 node.data.transform_id = transform_parent->transform_tree_index();
94 node.data.target_id =
95 data_from_ancestor.render_target->transform_tree_index();
97 data_for_children->clip_tree_parent =
98 data_for_children->clip_tree->Insert(node, parent_id);
101 layer->set_clip_tree_index(
102 has_unclipped_surface ? 0 : data_for_children->clip_tree_parent);
104 // TODO(awoloszyn): Right now when we hit a node with a replica, we reset the
105 // clip for all children since we may need to draw. We need to figure out a
106 // better way, since we will need both the clipped and unclipped versions.
109 void AddTransformNodeIfNeeded(const DataForRecursion& data_from_ancestor,
110 Layer* layer,
111 DataForRecursion* data_for_children) {
112 const bool is_root = !layer->parent();
113 const bool is_page_scale_application_layer =
114 layer->parent() && layer->parent() == data_from_ancestor.page_scale_layer;
115 const bool is_scrollable = layer->scrollable();
116 const bool is_fixed = layer->position_constraint().is_fixed_position();
118 const bool has_significant_transform =
119 !layer->transform().IsIdentityOr2DTranslation();
121 const bool has_animated_transform =
122 layer->layer_animation_controller()->IsAnimatingProperty(
123 Animation::TRANSFORM);
125 const bool has_surface = !!layer->render_surface();
127 const bool flattening_change = layer->parent() &&
128 layer->should_flatten_transform() &&
129 !layer->parent()->should_flatten_transform();
131 bool requires_node = is_root || is_scrollable || is_fixed ||
132 has_significant_transform || has_animated_transform ||
133 is_page_scale_application_layer || flattening_change ||
134 has_surface;
136 Layer* transform_parent = GetTransformParent(data_from_ancestor, layer);
138 // May be non-zero if layer is fixed or has a scroll parent.
139 gfx::Vector2dF parent_offset;
140 if (transform_parent) {
141 // TODO(vollick): This is to mimic existing bugs (crbug.com/441447).
142 if (!is_fixed)
143 parent_offset = transform_parent->offset_to_transform_parent();
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();
151 data_from_ancestor.transform_tree->ComputeTransform(
152 source->transform_tree_index(),
153 transform_parent->transform_tree_index(), &to_parent);
155 parent_offset += to_parent.To2dTranslation();
158 if (layer->IsContainerForFixedPositionLayers() || is_root)
159 data_for_children->transform_fixed_parent = layer;
160 data_for_children->transform_tree_parent = layer;
162 if (!requires_node) {
163 gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() +
164 layer->transform().To2dTranslation();
165 layer->set_offset_to_transform_parent(parent_offset + local_offset);
166 layer->set_transform_tree_index(transform_parent->transform_tree_index());
167 return;
170 int parent_index = 0;
171 if (transform_parent)
172 parent_index = transform_parent->transform_tree_index();
174 data_for_children->transform_tree->Insert(TransformNode(), parent_index);
176 TransformNode* node = data_for_children->transform_tree->back();
177 layer->set_transform_tree_index(node->id);
179 node->data.scrolls = is_scrollable;
180 node->data.flattens = layer->should_flatten_transform();
181 node->data.target_id =
182 data_from_ancestor.render_target->transform_tree_index();
183 node->data.content_target_id =
184 data_for_children->render_target->transform_tree_index();
185 DCHECK_NE(node->data.target_id, -1);
186 node->data.is_animated = layer->TransformIsAnimating();
188 float scale_factors = 1.0f;
189 if (is_root) {
190 node->data.post_local = *data_from_ancestor.device_transform;
191 scale_factors = data_from_ancestor.device_scale_factor;
194 if (is_page_scale_application_layer)
195 scale_factors *= data_from_ancestor.page_scale_factor;
197 if (has_surface && !is_root) {
198 node->data.needs_sublayer_scale = true;
199 node->data.layer_scale_factor = data_from_ancestor.device_scale_factor;
200 if (data_from_ancestor.in_subtree_of_page_scale_application_layer)
201 node->data.layer_scale_factor *= data_from_ancestor.page_scale_factor;
204 node->data.post_local.Scale(scale_factors, scale_factors);
205 node->data.post_local.Translate3d(
206 layer->position().x() + parent_offset.x() + layer->transform_origin().x(),
207 layer->position().y() + parent_offset.y() + layer->transform_origin().y(),
208 layer->transform_origin().z());
210 if (!layer->scroll_parent()) {
211 node->data.scroll_offset =
212 gfx::ScrollOffsetToVector2dF(layer->CurrentScrollOffset());
215 node->data.local = layer->transform();
216 node->data.pre_local.Translate3d(-layer->transform_origin().x(),
217 -layer->transform_origin().y(),
218 -layer->transform_origin().z());
220 node->data.needs_local_transform_update = true;
221 data_from_ancestor.transform_tree->UpdateTransforms(node->id);
223 layer->set_offset_to_transform_parent(gfx::Vector2dF());
226 void AddOpacityNodeIfNeeded(const DataForRecursion& data_from_ancestor,
227 Layer* layer,
228 DataForRecursion* data_for_children) {
229 const bool is_root = !layer->parent();
230 const bool has_transparency = layer->opacity() != 1.f;
231 const bool has_animated_opacity =
232 layer->layer_animation_controller()->IsAnimatingProperty(
233 Animation::OPACITY) ||
234 layer->OpacityCanAnimateOnImplThread();
235 bool requires_node = is_root || has_transparency || has_animated_opacity;
237 int parent_id = data_from_ancestor.opacity_tree_parent;
239 if (!requires_node) {
240 layer->set_opacity_tree_index(parent_id);
241 data_for_children->opacity_tree_parent = parent_id;
242 return;
245 OpacityNode node;
246 node.data = layer->opacity();
247 data_for_children->opacity_tree_parent =
248 data_for_children->opacity_tree->Insert(node, parent_id);
249 layer->set_opacity_tree_index(data_for_children->opacity_tree_parent);
252 void BuildPropertyTreesInternal(Layer* layer,
253 const DataForRecursion& data_from_parent) {
254 DataForRecursion data_for_children(data_from_parent);
255 if (layer->render_surface())
256 data_for_children.render_target = layer;
258 AddTransformNodeIfNeeded(data_from_parent, layer, &data_for_children);
259 AddClipNodeIfNeeded(data_from_parent, layer, &data_for_children);
261 if (data_from_parent.opacity_tree)
262 AddOpacityNodeIfNeeded(data_from_parent, layer, &data_for_children);
264 if (layer == data_from_parent.page_scale_layer)
265 data_for_children.in_subtree_of_page_scale_application_layer = true;
267 for (size_t i = 0; i < layer->children().size(); ++i) {
268 if (!layer->children()[i]->scroll_parent())
269 BuildPropertyTreesInternal(layer->children()[i].get(), data_for_children);
272 if (layer->scroll_children()) {
273 for (Layer* scroll_child : *layer->scroll_children()) {
274 BuildPropertyTreesInternal(scroll_child, data_for_children);
278 if (layer->has_replica())
279 BuildPropertyTreesInternal(layer->replica_layer(), data_for_children);
282 } // namespace
284 void PropertyTreeBuilder::BuildPropertyTrees(
285 Layer* root_layer,
286 const Layer* page_scale_layer,
287 float page_scale_factor,
288 float device_scale_factor,
289 const gfx::Rect& viewport,
290 const gfx::Transform& device_transform,
291 TransformTree* transform_tree,
292 ClipTree* clip_tree,
293 OpacityTree* opacity_tree) {
294 DataForRecursion data_for_recursion;
295 data_for_recursion.transform_tree = transform_tree;
296 data_for_recursion.clip_tree = clip_tree;
297 data_for_recursion.opacity_tree = opacity_tree;
298 data_for_recursion.transform_tree_parent = nullptr;
299 data_for_recursion.transform_fixed_parent = nullptr;
300 data_for_recursion.render_target = root_layer;
301 data_for_recursion.clip_tree_parent = 0;
302 data_for_recursion.opacity_tree_parent = -1;
303 data_for_recursion.page_scale_layer = page_scale_layer;
304 data_for_recursion.page_scale_factor = page_scale_factor;
305 data_for_recursion.device_scale_factor = device_scale_factor;
306 data_for_recursion.in_subtree_of_page_scale_application_layer = false;
307 data_for_recursion.device_transform = &device_transform;
309 ClipNode root_clip;
310 root_clip.data.clip = viewport;
311 root_clip.data.transform_id = 0;
312 data_for_recursion.clip_tree_parent = clip_tree->Insert(root_clip, 0);
313 BuildPropertyTreesInternal(root_layer, data_for_recursion);
316 } // namespace cc