cc: use property trees instead of CDP on the main thread
[chromium-blink-merge.git] / cc / trees / draw_property_utils.cc
blobb1b4de1dd74f9119823c0a79eac420571d530d70
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/draw_property_utils.h"
7 #include <vector>
9 #include "cc/base/math_util.h"
10 #include "cc/layers/layer.h"
11 #include "cc/layers/layer_impl.h"
12 #include "cc/trees/layer_tree_impl.h"
13 #include "cc/trees/property_tree.h"
14 #include "cc/trees/property_tree_builder.h"
15 #include "ui/gfx/geometry/rect_conversions.h"
17 namespace cc {
19 namespace {
21 template <typename LayerType>
22 void CalculateVisibleRects(const std::vector<LayerType*>& visible_layer_list,
23 const ClipTree& clip_tree,
24 const TransformTree& transform_tree) {
25 for (auto& layer : visible_layer_list) {
26 // TODO(ajuma): Compute content_scale rather than using it. Note that for
27 // PictureLayer and PictureImageLayers, content_bounds == bounds and
28 // content_scale_x == content_scale_y == 1.0, so once impl painting is on
29 // everywhere, this code will be unnecessary.
30 gfx::Size layer_bounds = layer->bounds();
31 const bool has_clip = layer->clip_tree_index() > 0;
32 const TransformNode* transform_node =
33 transform_tree.Node(layer->transform_tree_index());
34 if (has_clip) {
35 const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
36 const TransformNode* clip_transform_node =
37 transform_tree.Node(clip_node->data.transform_id);
38 const bool target_is_root_surface =
39 transform_node->data.content_target_id == 1;
40 // When the target is the root surface, we need to include the root
41 // transform by walking up to the root of the transform tree.
42 const int target_id =
43 target_is_root_surface ? 0 : transform_node->data.content_target_id;
44 const TransformNode* target_node = transform_tree.Node(target_id);
46 gfx::Transform content_to_target = transform_node->data.to_target;
48 content_to_target.Translate(layer->offset_to_transform_parent().x(),
49 layer->offset_to_transform_parent().y());
51 gfx::Rect clip_rect_in_target_space;
52 gfx::Transform clip_to_target;
53 bool success = true;
54 if (clip_transform_node->data.target_id == target_node->id) {
55 clip_to_target = clip_transform_node->data.to_target;
56 } else {
57 success = transform_tree.ComputeTransformWithDestinationSublayerScale(
58 clip_transform_node->id, target_node->id, &clip_to_target);
61 if (target_node->id > clip_node->data.transform_id) {
62 if (!success) {
63 DCHECK(target_node->data.to_screen_is_animated);
65 // An animated singular transform may become non-singular during the
66 // animation, so we still need to compute a visible rect. In this
67 // situation, we treat the entire layer as visible.
68 layer->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds));
69 continue;
72 clip_rect_in_target_space =
73 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
74 clip_to_target, clip_node->data.combined_clip));
75 } else {
76 // Computing a transform to an ancestor should always succeed.
77 DCHECK(success);
78 clip_rect_in_target_space =
79 gfx::ToEnclosingRect(MathUtil::MapClippedRect(
80 clip_to_target, clip_node->data.combined_clip));
83 gfx::Rect layer_content_rect = gfx::Rect(layer_bounds);
84 gfx::Rect layer_content_bounds_in_target_space =
85 MathUtil::MapEnclosingClippedRect(content_to_target,
86 layer_content_rect);
87 clip_rect_in_target_space.Intersect(layer_content_bounds_in_target_space);
88 if (clip_rect_in_target_space.IsEmpty()) {
89 layer->set_visible_rect_from_property_trees(gfx::Rect());
90 continue;
93 gfx::Transform target_to_content;
94 gfx::Transform target_to_layer;
96 if (transform_node->data.ancestors_are_invertible) {
97 target_to_layer = transform_node->data.from_target;
98 success = true;
99 } else {
100 success = transform_tree.ComputeTransformWithSourceSublayerScale(
101 target_node->id, transform_node->id, &target_to_layer);
104 if (!success) {
105 DCHECK(transform_node->data.to_screen_is_animated);
107 // An animated singular transform may become non-singular during the
108 // animation, so we still need to compute a visible rect. In this
109 // situation, we treat the entire layer as visible.
110 layer->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds));
111 continue;
114 target_to_content.Translate(-layer->offset_to_transform_parent().x(),
115 -layer->offset_to_transform_parent().y());
116 target_to_content.PreconcatTransform(target_to_layer);
118 gfx::Rect visible_rect = MathUtil::ProjectEnclosingClippedRect(
119 target_to_content, clip_rect_in_target_space);
121 visible_rect.Intersect(gfx::Rect(layer_bounds));
123 layer->set_visible_rect_from_property_trees(visible_rect);
124 } else {
125 layer->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds));
130 template <typename LayerType>
131 static bool IsRootLayerOfNewRenderingContext(LayerType* layer) {
132 if (layer->parent())
133 return !layer->parent()->Is3dSorted() && layer->Is3dSorted();
134 return layer->Is3dSorted();
137 template <typename LayerType>
138 static inline bool LayerIsInExisting3DRenderingContext(LayerType* layer) {
139 return layer->Is3dSorted() && layer->parent() &&
140 layer->parent()->Is3dSorted();
143 template <typename LayerType>
144 static bool TransformToScreenIsKnown(LayerType* layer,
145 const TransformTree& tree) {
146 const TransformNode* node = tree.Node(layer->transform_tree_index());
147 return !node->data.to_screen_is_animated;
150 template <typename LayerType>
151 static bool HasSingularTransform(LayerType* layer, const TransformTree& tree) {
152 const TransformNode* node = tree.Node(layer->transform_tree_index());
153 return !node->data.is_invertible || !node->data.ancestors_are_invertible;
156 template <typename LayerType>
157 static bool IsLayerBackFaceVisible(LayerType* layer,
158 const TransformTree& tree) {
159 // The current W3C spec on CSS transforms says that backface visibility should
160 // be determined differently depending on whether the layer is in a "3d
161 // rendering context" or not. For Chromium code, we can determine whether we
162 // are in a 3d rendering context by checking if the parent preserves 3d.
164 if (LayerIsInExisting3DRenderingContext(layer))
165 return DrawTransformFromPropertyTrees(layer, tree).IsBackFaceVisible();
167 // In this case, either the layer establishes a new 3d rendering context, or
168 // is not in a 3d rendering context at all.
169 return layer->transform().IsBackFaceVisible();
172 template <typename LayerType>
173 static bool IsAnimatingTransformToScreen(LayerType* layer,
174 const TransformTree& tree) {
175 const TransformNode* node = tree.Node(layer->transform_tree_index());
176 return node->data.to_screen_is_animated;
179 static inline bool TransformToScreenIsKnown(Layer* layer,
180 const TransformTree& tree) {
181 return !IsAnimatingTransformToScreen(layer, tree);
184 static inline bool TransformToScreenIsKnown(LayerImpl* layer,
185 const TransformTree& tree) {
186 return true;
189 template <typename LayerType>
190 static bool HasInvertibleOrAnimatedTransform(LayerType* layer) {
191 return layer->transform_is_invertible() || layer->TransformIsAnimating();
194 static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
195 bool layer_is_drawn) {
196 // If the layer transform is not invertible, it should not be drawn.
197 // TODO(ajuma): Correctly process subtrees with singular transform for the
198 // case where we may animate to a non-singular transform and wish to
199 // pre-raster.
200 if (!HasInvertibleOrAnimatedTransform(layer))
201 return true;
203 // When we need to do a readback/copy of a layer's output, we can not skip
204 // it or any of its ancestors.
205 if (layer->draw_properties().layer_or_descendant_has_copy_request)
206 return false;
208 // We cannot skip the the subtree if a descendant has a wheel or touch handler
209 // or the hit testing code will break (it requires fresh transforms, etc).
210 if (layer->draw_properties().layer_or_descendant_has_input_handler)
211 return false;
213 // If the layer is not drawn, then skip it and its subtree.
214 if (!layer_is_drawn)
215 return true;
217 // If layer is on the pending tree and opacity is being animated then
218 // this subtree can't be skipped as we need to create, prioritize and
219 // include tiles for this layer when deciding if tree can be activated.
220 if (layer->layer_tree_impl()->IsPendingTree() && layer->OpacityIsAnimating())
221 return false;
223 // The opacity of a layer always applies to its children (either implicitly
224 // via a render surface or explicitly if the parent preserves 3D), so the
225 // entire subtree can be skipped if this layer is fully transparent.
226 return !layer->opacity();
229 static inline bool SubtreeShouldBeSkipped(Layer* layer, bool layer_is_drawn) {
230 // If the layer transform is not invertible, it should not be drawn.
231 if (!layer->transform_is_invertible() && !layer->TransformIsAnimating())
232 return true;
234 // When we need to do a readback/copy of a layer's output, we can not skip
235 // it or any of its ancestors.
236 if (layer->draw_properties().layer_or_descendant_has_copy_request)
237 return false;
239 // We cannot skip the the subtree if a descendant has a wheel or touch handler
240 // or the hit testing code will break (it requires fresh transforms, etc).
241 if (layer->draw_properties().layer_or_descendant_has_input_handler)
242 return false;
244 // If the layer is not drawn, then skip it and its subtree.
245 if (!layer_is_drawn)
246 return true;
248 // If the opacity is being animated then the opacity on the main thread is
249 // unreliable (since the impl thread may be using a different opacity), so it
250 // should not be trusted.
251 // In particular, it should not cause the subtree to be skipped.
252 // Similarly, for layers that might animate opacity using an impl-only
253 // animation, their subtree should also not be skipped.
254 return !layer->opacity() && !layer->OpacityIsAnimating() &&
255 !layer->OpacityCanAnimateOnImplThread();
258 template <typename LayerType>
259 static bool LayerShouldBeSkipped(LayerType* layer,
260 bool layer_is_drawn,
261 const TransformTree& tree) {
262 // Layers can be skipped if any of these conditions are met.
263 // - is not drawn due to it or one of its ancestors being hidden (or having
264 // no copy requests).
265 // - does not draw content.
266 // - is transparent.
267 // - has empty bounds
268 // - the layer is not double-sided, but its back face is visible.
270 // Some additional conditions need to be computed at a later point after the
271 // recursion is finished.
272 // - the intersection of render_surface content and layer clip_rect is empty
273 // - the visible_content_rect is empty
275 // Note, if the layer should not have been drawn due to being fully
276 // transparent, we would have skipped the entire subtree and never made it
277 // into this function, so it is safe to omit this check here.
278 if (!layer_is_drawn)
279 return true;
281 if (!layer->DrawsContent() || layer->bounds().IsEmpty())
282 return true;
284 LayerType* backface_test_layer = layer;
285 if (layer->use_parent_backface_visibility()) {
286 DCHECK(layer->parent());
287 DCHECK(!layer->parent()->use_parent_backface_visibility());
288 backface_test_layer = layer->parent();
291 // The layer should not be drawn if (1) it is not double-sided and (2) the
292 // back of the layer is known to be facing the screen.
293 if (!backface_test_layer->double_sided() &&
294 TransformToScreenIsKnown(backface_test_layer, tree) &&
295 IsLayerBackFaceVisible(backface_test_layer, tree))
296 return true;
298 return false;
301 template <typename LayerType>
302 void FindLayersThatNeedUpdates(
303 LayerType* layer,
304 const TransformTree& tree,
305 bool subtree_is_visible_from_ancestor,
306 typename LayerType::LayerListType* update_layer_list,
307 std::vector<LayerType*>* visible_layer_list) {
308 bool layer_is_drawn =
309 layer->HasCopyRequest() ||
310 (subtree_is_visible_from_ancestor && !layer->hide_layer_and_subtree());
312 if (layer->parent() && SubtreeShouldBeSkipped(layer, layer_is_drawn))
313 return;
315 if (!LayerShouldBeSkipped(layer, layer_is_drawn, tree)) {
316 visible_layer_list->push_back(layer);
317 update_layer_list->push_back(layer);
320 // Append mask layers to the update layer list. They don't have valid visible
321 // rects, so need to get added after the above calculation. Replica layers
322 // don't need to be updated.
323 if (LayerType* mask_layer = layer->mask_layer())
324 update_layer_list->push_back(mask_layer);
325 if (LayerType* replica_layer = layer->replica_layer()) {
326 if (LayerType* mask_layer = replica_layer->mask_layer())
327 update_layer_list->push_back(mask_layer);
330 for (size_t i = 0; i < layer->children().size(); ++i) {
331 FindLayersThatNeedUpdates(layer->child_at(i), tree, layer_is_drawn,
332 update_layer_list, visible_layer_list);
336 } // namespace
338 void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) {
339 if (!clip_tree->needs_update())
340 return;
341 for (int i = 0; i < static_cast<int>(clip_tree->size()); ++i) {
342 ClipNode* clip_node = clip_tree->Node(i);
344 // Only descendants of a real clipping layer (i.e., not 0) may have their
345 // clip adjusted due to intersecting with an ancestor clip.
346 const bool is_clipped = clip_node->parent_id > 0;
347 if (!is_clipped) {
348 clip_node->data.combined_clip = clip_node->data.clip;
349 continue;
352 ClipNode* parent_clip_node = clip_tree->parent(clip_node);
353 const TransformNode* parent_transform_node =
354 transform_tree.Node(parent_clip_node->data.transform_id);
355 const TransformNode* transform_node =
356 transform_tree.Node(clip_node->data.transform_id);
358 // Clips must be combined in target space. We cannot, for example, combine
359 // clips in the space of the child clip. The reason is non-affine
360 // transforms. Say we have the following tree T->A->B->C, and B clips C, but
361 // draw into target T. It may be the case that A applies a perspective
362 // transform, and B and C are at different z positions. When projected into
363 // target space, the relative sizes and positions of B and C can shift.
364 // Since it's the relationship in target space that matters, that's where we
365 // must combine clips.
366 gfx::Transform parent_to_target;
367 gfx::Transform clip_to_target;
368 gfx::Transform target_to_clip;
370 const bool target_is_root_surface = clip_node->data.target_id == 1;
371 // When the target is the root surface, we need to include the root
372 // transform by walking up to the root of the transform tree.
373 const int target_id =
374 target_is_root_surface ? 0 : clip_node->data.target_id;
376 bool success = true;
377 if (parent_transform_node->data.content_target_id ==
378 clip_node->data.target_id) {
379 parent_to_target = parent_transform_node->data.to_target;
380 } else {
381 success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
382 parent_transform_node->id, target_id, &parent_to_target);
385 if (transform_node->data.content_target_id == clip_node->data.target_id) {
386 clip_to_target = transform_node->data.to_target;
387 } else {
388 success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
389 transform_node->id, target_id, &clip_to_target);
392 if (transform_node->data.content_target_id == clip_node->data.target_id &&
393 transform_node->data.ancestors_are_invertible) {
394 target_to_clip = transform_node->data.from_target;
395 } else {
396 success &= clip_to_target.GetInverse(&target_to_clip);
399 // If we can't compute a transform, it's because we had to use the inverse
400 // of a singular transform. We won't draw in this case, so there's no need
401 // to compute clips.
402 if (!success)
403 continue;
405 // In order to intersect with as small a rect as possible, we do a
406 // preliminary clip in target space so that when we project back, there's
407 // less likelihood of intersecting the view plane.
408 gfx::RectF inherited_clip_in_target_space = MathUtil::MapClippedRect(
409 parent_to_target, parent_clip_node->data.combined_clip);
411 gfx::RectF clip_in_target_space =
412 MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip);
414 gfx::RectF intersected_in_target_space = gfx::IntersectRects(
415 inherited_clip_in_target_space, clip_in_target_space);
417 clip_node->data.combined_clip = MathUtil::ProjectClippedRect(
418 target_to_clip, intersected_in_target_space);
420 clip_node->data.combined_clip.Intersect(clip_node->data.clip);
422 clip_tree->set_needs_update(false);
425 void ComputeTransforms(TransformTree* transform_tree) {
426 if (!transform_tree->needs_update())
427 return;
428 for (int i = 1; i < static_cast<int>(transform_tree->size()); ++i)
429 transform_tree->UpdateTransforms(i);
430 transform_tree->set_needs_update(false);
433 template <typename LayerType>
434 void ComputeVisibleRectsUsingPropertyTreesInternal(
435 LayerType* root_layer,
436 PropertyTrees* property_trees,
437 typename LayerType::LayerListType* update_layer_list) {
438 if (property_trees->transform_tree.needs_update())
439 property_trees->clip_tree.set_needs_update(true);
440 ComputeTransforms(&property_trees->transform_tree);
441 ComputeClips(&property_trees->clip_tree, property_trees->transform_tree);
443 const bool subtree_is_visible_from_ancestor = true;
444 std::vector<LayerType*> visible_layer_list;
445 FindLayersThatNeedUpdates(root_layer, property_trees->transform_tree,
446 subtree_is_visible_from_ancestor, update_layer_list,
447 &visible_layer_list);
448 CalculateVisibleRects<LayerType>(visible_layer_list,
449 property_trees->clip_tree,
450 property_trees->transform_tree);
453 void BuildPropertyTreesAndComputeVisibleRects(
454 Layer* root_layer,
455 const Layer* page_scale_layer,
456 float page_scale_factor,
457 float device_scale_factor,
458 const gfx::Rect& viewport,
459 const gfx::Transform& device_transform,
460 PropertyTrees* property_trees,
461 LayerList* update_layer_list) {
462 PropertyTreeBuilder::BuildPropertyTrees(
463 root_layer, page_scale_layer, page_scale_factor, device_scale_factor,
464 viewport, device_transform, property_trees);
465 ComputeVisibleRectsUsingPropertyTrees(root_layer, property_trees,
466 update_layer_list);
469 void BuildPropertyTreesAndComputeVisibleRects(
470 LayerImpl* root_layer,
471 const LayerImpl* page_scale_layer,
472 float page_scale_factor,
473 float device_scale_factor,
474 const gfx::Rect& viewport,
475 const gfx::Transform& device_transform,
476 PropertyTrees* property_trees,
477 LayerImplList* update_layer_list) {
478 PropertyTreeBuilder::BuildPropertyTrees(
479 root_layer, page_scale_layer, page_scale_factor, device_scale_factor,
480 viewport, device_transform, property_trees);
481 ComputeVisibleRectsUsingPropertyTrees(root_layer, property_trees,
482 update_layer_list);
485 void ComputeVisibleRectsUsingPropertyTrees(Layer* root_layer,
486 PropertyTrees* property_trees,
487 LayerList* update_layer_list) {
488 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer, property_trees,
489 update_layer_list);
492 void ComputeVisibleRectsUsingPropertyTrees(LayerImpl* root_layer,
493 PropertyTrees* property_trees,
494 LayerImplList* update_layer_list) {
495 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer, property_trees,
496 update_layer_list);
499 template <typename LayerType>
500 gfx::Transform DrawTransformFromPropertyTreesInternal(
501 const LayerType* layer,
502 const TransformTree& tree) {
503 const TransformNode* node = tree.Node(layer->transform_tree_index());
504 // TODO(vollick): ultimately we'll need to find this information (whether or
505 // not we establish a render surface) somewhere other than the layer.
506 const TransformNode* target_node =
507 layer->render_surface() ? node : tree.Node(node->data.content_target_id);
509 gfx::Transform xform;
510 const bool owns_non_root_surface = layer->parent() && layer->render_surface();
511 if (!owns_non_root_surface) {
512 // If you're not the root, or you don't own a surface, you need to apply
513 // your local offset.
514 xform = node->data.to_target;
515 if (layer->should_flatten_transform_from_property_tree())
516 xform.FlattenTo2d();
517 xform.Translate(layer->offset_to_transform_parent().x(),
518 layer->offset_to_transform_parent().y());
519 } else {
520 // Surfaces need to apply their sublayer scale.
521 xform.Scale(target_node->data.sublayer_scale.x(),
522 target_node->data.sublayer_scale.y());
524 return xform;
527 gfx::Transform DrawTransformFromPropertyTrees(const Layer* layer,
528 const TransformTree& tree) {
529 return DrawTransformFromPropertyTreesInternal(layer, tree);
532 gfx::Transform DrawTransformFromPropertyTrees(const LayerImpl* layer,
533 const TransformTree& tree) {
534 return DrawTransformFromPropertyTreesInternal(layer, tree);
537 template <typename LayerType>
538 gfx::Transform ScreenSpaceTransformFromPropertyTreesInternal(
539 LayerType* layer,
540 const TransformTree& tree) {
541 gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(),
542 layer->offset_to_transform_parent().y());
543 if (layer->transform_tree_index() >= 0) {
544 gfx::Transform ssxform =
545 tree.Node(layer->transform_tree_index())->data.to_screen;
546 xform.ConcatTransform(ssxform);
547 if (layer->should_flatten_transform_from_property_tree())
548 xform.FlattenTo2d();
550 return xform;
553 gfx::Transform ScreenSpaceTransformFromPropertyTrees(
554 const Layer* layer,
555 const TransformTree& tree) {
556 return ScreenSpaceTransformFromPropertyTreesInternal(layer, tree);
559 gfx::Transform ScreenSpaceTransformFromPropertyTrees(
560 const LayerImpl* layer,
561 const TransformTree& tree) {
562 return ScreenSpaceTransformFromPropertyTreesInternal(layer, tree);
565 template <typename LayerType>
566 float DrawOpacityFromPropertyTreesInternal(LayerType layer,
567 const OpacityTree& tree) {
568 if (!layer->render_target())
569 return 0.f;
571 const OpacityNode* target_node =
572 tree.Node(layer->render_target()->opacity_tree_index());
573 const OpacityNode* node = tree.Node(layer->opacity_tree_index());
574 if (node == target_node)
575 return 1.f;
577 float draw_opacity = 1.f;
578 while (node != target_node) {
579 draw_opacity *= node->data;
580 node = tree.parent(node);
582 return draw_opacity;
585 float DrawOpacityFromPropertyTrees(const Layer* layer,
586 const OpacityTree& tree) {
587 return DrawOpacityFromPropertyTreesInternal(layer, tree);
590 float DrawOpacityFromPropertyTrees(const LayerImpl* layer,
591 const OpacityTree& tree) {
592 return DrawOpacityFromPropertyTreesInternal(layer, tree);
595 } // namespace cc