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(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());
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.
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
;
54 if (clip_transform_node
->data
.target_id
== target_node
->id
) {
55 clip_to_target
= clip_transform_node
->data
.to_target
;
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
) {
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
));
72 clip_rect_in_target_space
=
73 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
74 clip_to_target
, clip_node
->data
.combined_clip
));
76 // Computing a transform to an ancestor should always succeed.
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
,
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());
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
;
100 success
= transform_tree
.ComputeTransformWithSourceSublayerScale(
101 target_node
->id
, transform_node
->id
, &target_to_layer
);
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
));
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
);
125 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
130 template <typename LayerType
>
131 static bool IsRootLayerOfNewRenderingContext(LayerType
* layer
) {
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
) {
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
200 if (!HasInvertibleOrAnimatedTransform(layer
))
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
)
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
)
213 // If the layer is not drawn, then skip it and its subtree.
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())
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())
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
)
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
)
244 // If the layer is not drawn, then skip it and its subtree.
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
,
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.
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.
281 if (!layer
->DrawsContent() || layer
->bounds().IsEmpty())
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
))
301 template <typename LayerType
>
302 void FindLayersThatNeedUpdates(
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
))
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
);
338 void ComputeClips(ClipTree
* clip_tree
, const TransformTree
& transform_tree
) {
339 if (!clip_tree
->needs_update())
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;
348 clip_node
->data
.combined_clip
= clip_node
->data
.clip
;
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
;
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
;
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
;
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
;
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
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())
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(
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
,
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
,
485 void ComputeVisibleRectsUsingPropertyTrees(Layer
* root_layer
,
486 PropertyTrees
* property_trees
,
487 LayerList
* update_layer_list
) {
488 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
,
492 void ComputeVisibleRectsUsingPropertyTrees(LayerImpl
* root_layer
,
493 PropertyTrees
* property_trees
,
494 LayerImplList
* update_layer_list
) {
495 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
,
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())
517 xform
.Translate(layer
->offset_to_transform_parent().x(),
518 layer
->offset_to_transform_parent().y());
520 // Surfaces need to apply their sublayer scale.
521 xform
.Scale(target_node
->data
.sublayer_scale
.x(),
522 target_node
->data
.sublayer_scale
.y());
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(
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())
553 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
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())
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
)
577 float draw_opacity
= 1.f
;
578 while (node
!= target_node
) {
579 draw_opacity
*= node
->data
;
580 node
= tree
.parent(node
);
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
);