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"
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"
21 template <typename LayerType
>
22 void CalculateVisibleRects(
23 const std::vector
<LayerType
*>& layers_that_need_visible_rects
,
24 const ClipTree
& clip_tree
,
25 const TransformTree
& transform_tree
) {
26 for (size_t i
= 0; i
< layers_that_need_visible_rects
.size(); ++i
) {
27 LayerType
* layer
= layers_that_need_visible_rects
[i
];
29 // TODO(ajuma): Compute content_scale rather than using it. Note that for
30 // PictureLayer and PictureImageLayers, content_bounds == bounds and
31 // content_scale_x == content_scale_y == 1.0, so once impl painting is on
32 // everywhere, this code will be unnecessary.
33 gfx::Size layer_content_bounds
= layer
->content_bounds();
34 float contents_scale_x
= layer
->contents_scale_x();
35 float contents_scale_y
= layer
->contents_scale_y();
36 const bool has_clip
= layer
->clip_tree_index() > 0;
37 const TransformNode
* transform_node
=
38 transform_tree
.Node(layer
->transform_tree_index());
40 const ClipNode
* clip_node
= clip_tree
.Node(layer
->clip_tree_index());
41 const TransformNode
* clip_transform_node
=
42 transform_tree
.Node(clip_node
->data
.transform_id
);
43 const bool target_is_root_surface
=
44 transform_node
->data
.content_target_id
== 1;
45 // When the target is the root surface, we need to include the root
46 // transform by walking up to the root of the transform tree.
48 target_is_root_surface
? 0 : transform_node
->data
.content_target_id
;
49 const TransformNode
* target_node
= transform_tree
.Node(target_id
);
51 gfx::Transform content_to_target
= transform_node
->data
.to_target
;
53 content_to_target
.Translate(layer
->offset_to_transform_parent().x(),
54 layer
->offset_to_transform_parent().y());
55 content_to_target
.Scale(1.0 / contents_scale_x
, 1.0 / contents_scale_y
);
57 gfx::Rect clip_rect_in_target_space
;
58 gfx::Transform clip_to_target
;
60 if (clip_transform_node
->data
.target_id
== target_node
->id
) {
61 clip_to_target
= clip_transform_node
->data
.to_target
;
63 success
= transform_tree
.ComputeTransformWithDestinationSublayerScale(
64 clip_transform_node
->id
, target_node
->id
, &clip_to_target
);
67 if (target_node
->id
> clip_node
->data
.transform_id
) {
69 DCHECK(target_node
->data
.to_screen_is_animated
);
71 // An animated singular transform may become non-singular during the
72 // animation, so we still need to compute a visible rect. In this
73 // situation, we treat the entire layer as visible.
74 layer
->set_visible_rect_from_property_trees(
75 gfx::Rect(layer_content_bounds
));
79 clip_rect_in_target_space
=
80 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
81 clip_to_target
, clip_node
->data
.combined_clip
));
83 // Computing a transform to an ancestor should always succeed.
85 clip_rect_in_target_space
=
86 gfx::ToEnclosingRect(MathUtil::MapClippedRect(
87 clip_to_target
, clip_node
->data
.combined_clip
));
90 gfx::Rect layer_content_rect
= gfx::Rect(layer_content_bounds
);
91 gfx::Rect layer_content_bounds_in_target_space
=
92 MathUtil::MapEnclosingClippedRect(content_to_target
,
94 clip_rect_in_target_space
.Intersect(layer_content_bounds_in_target_space
);
95 if (clip_rect_in_target_space
.IsEmpty()) {
96 layer
->set_visible_rect_from_property_trees(gfx::Rect());
100 gfx::Transform target_to_content
;
101 gfx::Transform target_to_layer
;
103 if (transform_node
->data
.ancestors_are_invertible
) {
104 target_to_layer
= transform_node
->data
.from_target
;
107 success
= transform_tree
.ComputeTransformWithSourceSublayerScale(
108 target_node
->id
, transform_node
->id
, &target_to_layer
);
112 DCHECK(transform_node
->data
.to_screen_is_animated
);
114 // An animated singular transform may become non-singular during the
115 // animation, so we still need to compute a visible rect. In this
116 // situation, we treat the entire layer as visible.
117 layer
->set_visible_rect_from_property_trees(
118 gfx::Rect(layer_content_bounds
));
122 target_to_content
.Scale(contents_scale_x
, contents_scale_y
);
123 target_to_content
.Translate(-layer
->offset_to_transform_parent().x(),
124 -layer
->offset_to_transform_parent().y());
125 target_to_content
.PreconcatTransform(target_to_layer
);
127 gfx::Rect visible_rect
= MathUtil::ProjectEnclosingClippedRect(
128 target_to_content
, clip_rect_in_target_space
);
130 visible_rect
.Intersect(gfx::Rect(layer_content_bounds
));
132 layer
->set_visible_rect_from_property_trees(visible_rect
);
134 layer
->set_visible_rect_from_property_trees(
135 gfx::Rect(layer_content_bounds
));
140 template <typename LayerType
>
141 static bool IsRootLayerOfNewRenderingContext(LayerType
* layer
) {
143 return !layer
->parent()->Is3dSorted() && layer
->Is3dSorted();
144 return layer
->Is3dSorted();
147 template <typename LayerType
>
148 static inline bool LayerIsInExisting3DRenderingContext(LayerType
* layer
) {
149 return layer
->Is3dSorted() && layer
->parent() &&
150 layer
->parent()->Is3dSorted();
153 template <typename LayerType
>
154 static bool TransformToScreenIsKnown(LayerType
* layer
,
155 const TransformTree
& tree
) {
156 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
157 return !node
->data
.to_screen_is_animated
;
160 template <typename LayerType
>
161 static bool HasSingularTransform(LayerType
* layer
, const TransformTree
& tree
) {
162 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
163 return !node
->data
.is_invertible
|| !node
->data
.ancestors_are_invertible
;
166 template <typename LayerType
>
167 static bool IsLayerBackFaceVisible(LayerType
* layer
,
168 const TransformTree
& tree
) {
169 // The current W3C spec on CSS transforms says that backface visibility should
170 // be determined differently depending on whether the layer is in a "3d
171 // rendering context" or not. For Chromium code, we can determine whether we
172 // are in a 3d rendering context by checking if the parent preserves 3d.
174 if (LayerIsInExisting3DRenderingContext(layer
))
175 return DrawTransformFromPropertyTrees(layer
, tree
).IsBackFaceVisible();
177 // In this case, either the layer establishes a new 3d rendering context, or
178 // is not in a 3d rendering context at all.
179 return layer
->transform().IsBackFaceVisible();
182 template <typename LayerType
>
183 static bool IsAnimatingTransformToScreen(LayerType
* layer
,
184 const TransformTree
& tree
) {
185 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
186 return node
->data
.to_screen_is_animated
;
189 static inline bool TransformToScreenIsKnown(Layer
* layer
,
190 const TransformTree
& tree
) {
191 return !IsAnimatingTransformToScreen(layer
, tree
);
194 static inline bool TransformToScreenIsKnown(LayerImpl
* layer
,
195 const TransformTree
& tree
) {
199 template <typename LayerType
>
200 static bool HasInvertibleOrAnimatedTransform(LayerType
* layer
) {
201 return layer
->transform_is_invertible() || layer
->TransformIsAnimating();
204 static inline bool SubtreeShouldBeSkipped(LayerImpl
* layer
,
205 bool layer_is_drawn
) {
206 // If the layer transform is not invertible, it should not be drawn.
207 // TODO(ajuma): Correctly process subtrees with singular transform for the
208 // case where we may animate to a non-singular transform and wish to
210 if (!HasInvertibleOrAnimatedTransform(layer
))
213 // When we need to do a readback/copy of a layer's output, we can not skip
214 // it or any of its ancestors.
215 if (layer
->draw_properties().layer_or_descendant_has_copy_request
)
218 // We cannot skip the the subtree if a descendant has a wheel or touch handler
219 // or the hit testing code will break (it requires fresh transforms, etc).
220 if (layer
->draw_properties().layer_or_descendant_has_input_handler
)
223 // If the layer is not drawn, then skip it and its subtree.
227 // If layer is on the pending tree and opacity is being animated then
228 // this subtree can't be skipped as we need to create, prioritize and
229 // include tiles for this layer when deciding if tree can be activated.
230 if (layer
->layer_tree_impl()->IsPendingTree() && layer
->OpacityIsAnimating())
233 // The opacity of a layer always applies to its children (either implicitly
234 // via a render surface or explicitly if the parent preserves 3D), so the
235 // entire subtree can be skipped if this layer is fully transparent.
236 return !layer
->opacity();
239 static inline bool SubtreeShouldBeSkipped(Layer
* layer
, bool layer_is_drawn
) {
240 // If the layer transform is not invertible, it should not be drawn.
241 if (!layer
->transform_is_invertible() && !layer
->TransformIsAnimating())
244 // When we need to do a readback/copy of a layer's output, we can not skip
245 // it or any of its ancestors.
246 if (layer
->draw_properties().layer_or_descendant_has_copy_request
)
249 // We cannot skip the the subtree if a descendant has a wheel or touch handler
250 // or the hit testing code will break (it requires fresh transforms, etc).
251 if (layer
->draw_properties().layer_or_descendant_has_input_handler
)
254 // If the layer is not drawn, then skip it and its subtree.
258 // If the opacity is being animated then the opacity on the main thread is
259 // unreliable (since the impl thread may be using a different opacity), so it
260 // should not be trusted.
261 // In particular, it should not cause the subtree to be skipped.
262 // Similarly, for layers that might animate opacity using an impl-only
263 // animation, their subtree should also not be skipped.
264 return !layer
->opacity() && !layer
->OpacityIsAnimating() &&
265 !layer
->OpacityCanAnimateOnImplThread();
268 template <typename LayerType
>
269 static bool LayerShouldBeSkipped(LayerType
* layer
,
271 const TransformTree
& tree
) {
272 // Layers can be skipped if any of these conditions are met.
273 // - is not drawn due to it or one of its ancestors being hidden (or having
274 // no copy requests).
275 // - does not draw content.
277 // - has empty bounds
278 // - the layer is not double-sided, but its back face is visible.
280 // Some additional conditions need to be computed at a later point after the
281 // recursion is finished.
282 // - the intersection of render_surface content and layer clip_rect is empty
283 // - the visible_content_rect is empty
285 // Note, if the layer should not have been drawn due to being fully
286 // transparent, we would have skipped the entire subtree and never made it
287 // into this function, so it is safe to omit this check here.
291 if (!layer
->DrawsContent() || layer
->bounds().IsEmpty())
294 LayerType
* backface_test_layer
= layer
;
295 if (layer
->use_parent_backface_visibility()) {
296 DCHECK(layer
->parent());
297 DCHECK(!layer
->parent()->use_parent_backface_visibility());
298 backface_test_layer
= layer
->parent();
301 // The layer should not be drawn if (1) it is not double-sided and (2) the
302 // back of the layer is known to be facing the screen.
303 if (!backface_test_layer
->double_sided() &&
304 TransformToScreenIsKnown(backface_test_layer
, tree
) &&
305 IsLayerBackFaceVisible(backface_test_layer
, tree
))
311 template <typename LayerType
>
312 void FindLayersThatNeedVisibleRects(LayerType
* layer
,
313 const TransformTree
& tree
,
314 bool subtree_is_visible_from_ancestor
,
315 std::vector
<LayerType
*>* layers_to_update
) {
316 bool layer_is_drawn
=
317 layer
->HasCopyRequest() ||
318 (subtree_is_visible_from_ancestor
&& !layer
->hide_layer_and_subtree());
320 if (layer
->parent() && SubtreeShouldBeSkipped(layer
, layer_is_drawn
))
323 if (!LayerShouldBeSkipped(layer
, layer_is_drawn
, tree
))
324 layers_to_update
->push_back(layer
);
326 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
327 FindLayersThatNeedVisibleRects(layer
->child_at(i
), tree
, layer_is_drawn
,
334 void ComputeClips(ClipTree
* clip_tree
, const TransformTree
& transform_tree
) {
335 if (!clip_tree
->needs_update())
337 for (int i
= 0; i
< static_cast<int>(clip_tree
->size()); ++i
) {
338 ClipNode
* clip_node
= clip_tree
->Node(i
);
340 // Only descendants of a real clipping layer (i.e., not 0) may have their
341 // clip adjusted due to intersecting with an ancestor clip.
342 const bool is_clipped
= clip_node
->parent_id
> 0;
344 clip_node
->data
.combined_clip
= clip_node
->data
.clip
;
348 ClipNode
* parent_clip_node
= clip_tree
->parent(clip_node
);
349 const TransformNode
* parent_transform_node
=
350 transform_tree
.Node(parent_clip_node
->data
.transform_id
);
351 const TransformNode
* transform_node
=
352 transform_tree
.Node(clip_node
->data
.transform_id
);
354 // Clips must be combined in target space. We cannot, for example, combine
355 // clips in the space of the child clip. The reason is non-affine
356 // transforms. Say we have the following tree T->A->B->C, and B clips C, but
357 // draw into target T. It may be the case that A applies a perspective
358 // transform, and B and C are at different z positions. When projected into
359 // target space, the relative sizes and positions of B and C can shift.
360 // Since it's the relationship in target space that matters, that's where we
361 // must combine clips.
362 gfx::Transform parent_to_target
;
363 gfx::Transform clip_to_target
;
364 gfx::Transform target_to_clip
;
366 const bool target_is_root_surface
= clip_node
->data
.target_id
== 1;
367 // When the target is the root surface, we need to include the root
368 // transform by walking up to the root of the transform tree.
369 const int target_id
=
370 target_is_root_surface
? 0 : clip_node
->data
.target_id
;
373 if (parent_transform_node
->data
.content_target_id
==
374 clip_node
->data
.target_id
) {
375 parent_to_target
= parent_transform_node
->data
.to_target
;
377 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
378 parent_transform_node
->id
, target_id
, &parent_to_target
);
381 if (transform_node
->data
.content_target_id
== clip_node
->data
.target_id
) {
382 clip_to_target
= transform_node
->data
.to_target
;
384 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
385 transform_node
->id
, target_id
, &clip_to_target
);
388 if (transform_node
->data
.content_target_id
== clip_node
->data
.target_id
&&
389 transform_node
->data
.ancestors_are_invertible
) {
390 target_to_clip
= transform_node
->data
.from_target
;
392 success
&= clip_to_target
.GetInverse(&target_to_clip
);
395 // If we can't compute a transform, it's because we had to use the inverse
396 // of a singular transform. We won't draw in this case, so there's no need
401 // In order to intersect with as small a rect as possible, we do a
402 // preliminary clip in target space so that when we project back, there's
403 // less likelihood of intersecting the view plane.
404 gfx::RectF inherited_clip_in_target_space
= MathUtil::MapClippedRect(
405 parent_to_target
, parent_clip_node
->data
.combined_clip
);
407 gfx::RectF clip_in_target_space
=
408 MathUtil::MapClippedRect(clip_to_target
, clip_node
->data
.clip
);
410 gfx::RectF intersected_in_target_space
= gfx::IntersectRects(
411 inherited_clip_in_target_space
, clip_in_target_space
);
413 clip_node
->data
.combined_clip
= MathUtil::ProjectClippedRect(
414 target_to_clip
, intersected_in_target_space
);
416 clip_node
->data
.combined_clip
.Intersect(clip_node
->data
.clip
);
418 clip_tree
->set_needs_update(false);
421 void ComputeTransforms(TransformTree
* transform_tree
) {
422 if (!transform_tree
->needs_update())
424 for (int i
= 1; i
< static_cast<int>(transform_tree
->size()); ++i
)
425 transform_tree
->UpdateTransforms(i
);
426 transform_tree
->set_needs_update(false);
429 template <typename LayerType
>
430 void ComputeVisibleRectsUsingPropertyTreesInternal(
431 LayerType
* root_layer
,
432 PropertyTrees
* property_trees
) {
433 if (property_trees
->transform_tree
.needs_update())
434 property_trees
->clip_tree
.set_needs_update(true);
435 ComputeTransforms(&property_trees
->transform_tree
);
436 ComputeClips(&property_trees
->clip_tree
, property_trees
->transform_tree
);
438 std::vector
<LayerType
*> layers_to_update
;
439 const bool subtree_is_visible_from_ancestor
= true;
440 FindLayersThatNeedVisibleRects(root_layer
, property_trees
->transform_tree
,
441 subtree_is_visible_from_ancestor
,
443 CalculateVisibleRects(layers_to_update
, property_trees
->clip_tree
,
444 property_trees
->transform_tree
);
447 void BuildPropertyTreesAndComputeVisibleRects(
449 const Layer
* page_scale_layer
,
450 float page_scale_factor
,
451 float device_scale_factor
,
452 const gfx::Rect
& viewport
,
453 const gfx::Transform
& device_transform
,
454 PropertyTrees
* property_trees
) {
455 PropertyTreeBuilder::BuildPropertyTrees(
456 root_layer
, page_scale_layer
, page_scale_factor
, device_scale_factor
,
457 viewport
, device_transform
, property_trees
);
458 ComputeVisibleRectsUsingPropertyTrees(root_layer
, property_trees
);
461 void BuildPropertyTreesAndComputeVisibleRects(
462 LayerImpl
* root_layer
,
463 const LayerImpl
* page_scale_layer
,
464 float page_scale_factor
,
465 float device_scale_factor
,
466 const gfx::Rect
& viewport
,
467 const gfx::Transform
& device_transform
,
468 PropertyTrees
* property_trees
) {
469 PropertyTreeBuilder::BuildPropertyTrees(
470 root_layer
, page_scale_layer
, page_scale_factor
, device_scale_factor
,
471 viewport
, device_transform
, property_trees
);
472 ComputeVisibleRectsUsingPropertyTrees(root_layer
, property_trees
);
475 void ComputeVisibleRectsUsingPropertyTrees(Layer
* root_layer
,
476 PropertyTrees
* property_trees
) {
477 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
);
480 void ComputeVisibleRectsUsingPropertyTrees(LayerImpl
* root_layer
,
481 PropertyTrees
* property_trees
) {
482 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
);
485 template <typename LayerType
>
486 gfx::Transform
DrawTransformFromPropertyTreesInternal(
487 const LayerType
* layer
,
488 const TransformTree
& tree
) {
489 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
490 // TODO(vollick): ultimately we'll need to find this information (whether or
491 // not we establish a render surface) somewhere other than the layer.
492 const TransformNode
* target_node
=
493 layer
->render_surface() ? node
: tree
.Node(node
->data
.content_target_id
);
495 gfx::Transform xform
;
496 const bool owns_non_root_surface
= layer
->parent() && layer
->render_surface();
497 if (!owns_non_root_surface
) {
498 // If you're not the root, or you don't own a surface, you need to apply
499 // your local offset.
500 xform
= node
->data
.to_target
;
501 if (layer
->should_flatten_transform_from_property_tree())
503 xform
.Translate(layer
->offset_to_transform_parent().x(),
504 layer
->offset_to_transform_parent().y());
505 // A fixed-position layer does not necessarily have the same render target
506 // as its transform node. In particular, its transform node may be an
507 // ancestor of its render target's transform node. For example, given layer
508 // tree R->S->F, suppose F is fixed and S owns a render surface (e.g., say S
509 // has opacity 0.9 and both S and F draw content). Then F's transform node
510 // is the root node, so the target space transform from that node is defined
511 // with respect to the root render surface. But F will render to S's
512 // surface, so must apply a change of basis transform to the target space
513 // transform from its transform node.
514 if (layer
->position_constraint().is_fixed_position()) {
515 gfx::Transform tree_target_to_render_target
;
516 tree
.ComputeTransform(node
->data
.content_target_id
,
517 layer
->render_target()->transform_tree_index(),
518 &tree_target_to_render_target
);
519 xform
.ConcatTransform(tree_target_to_render_target
);
522 // Surfaces need to apply their sublayer scale.
523 xform
.Scale(target_node
->data
.sublayer_scale
.x(),
524 target_node
->data
.sublayer_scale
.y());
526 xform
.Scale(1.0 / layer
->contents_scale_x(), 1.0 / layer
->contents_scale_y());
530 gfx::Transform
DrawTransformFromPropertyTrees(const Layer
* layer
,
531 const TransformTree
& tree
) {
532 return DrawTransformFromPropertyTreesInternal(layer
, tree
);
535 gfx::Transform
DrawTransformFromPropertyTrees(const LayerImpl
* layer
,
536 const TransformTree
& tree
) {
537 return DrawTransformFromPropertyTreesInternal(layer
, tree
);
540 template <typename LayerType
>
541 gfx::Transform
ScreenSpaceTransformFromPropertyTreesInternal(
543 const TransformTree
& tree
) {
544 gfx::Transform
xform(1, 0, 0, 1, layer
->offset_to_transform_parent().x(),
545 layer
->offset_to_transform_parent().y());
546 if (layer
->transform_tree_index() >= 0) {
547 gfx::Transform ssxform
=
548 tree
.Node(layer
->transform_tree_index())->data
.to_screen
;
549 xform
.ConcatTransform(ssxform
);
550 if (layer
->should_flatten_transform_from_property_tree())
553 xform
.Scale(1.0 / layer
->contents_scale_x(), 1.0 / layer
->contents_scale_y());
557 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
559 const TransformTree
& tree
) {
560 return ScreenSpaceTransformFromPropertyTreesInternal(layer
, tree
);
563 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
564 const LayerImpl
* layer
,
565 const TransformTree
& tree
) {
566 return ScreenSpaceTransformFromPropertyTreesInternal(layer
, tree
);
569 template <typename LayerType
>
570 float DrawOpacityFromPropertyTreesInternal(LayerType layer
,
571 const OpacityTree
& tree
) {
572 if (!layer
->render_target())
575 const OpacityNode
* target_node
=
576 tree
.Node(layer
->render_target()->opacity_tree_index());
577 const OpacityNode
* node
= tree
.Node(layer
->opacity_tree_index());
578 if (node
== target_node
)
581 float draw_opacity
= 1.f
;
582 while (node
!= target_node
) {
583 draw_opacity
*= node
->data
;
584 node
= tree
.parent(node
);
589 float DrawOpacityFromPropertyTrees(const Layer
* layer
,
590 const OpacityTree
& tree
) {
591 return DrawOpacityFromPropertyTreesInternal(layer
, tree
);
594 float DrawOpacityFromPropertyTrees(const LayerImpl
* layer
,
595 const OpacityTree
& tree
) {
596 return DrawOpacityFromPropertyTreesInternal(layer
, tree
);