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 combined_clip_rect_in_target_space
;
52 gfx::Rect clip_rect_in_target_space
;
53 gfx::Transform clip_to_target
;
55 if (clip_transform_node
->data
.target_id
== target_node
->id
) {
56 clip_to_target
= clip_transform_node
->data
.to_target
;
58 success
= transform_tree
.ComputeTransformWithDestinationSublayerScale(
59 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
));
69 layer
->set_clip_rect_in_target_space_from_property_trees(
70 gfx::ToEnclosingRect(clip_node
->data
.combined_clip
));
74 combined_clip_rect_in_target_space
=
75 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
76 clip_to_target
, clip_node
->data
.combined_clip
));
77 clip_rect_in_target_space
= gfx::ToEnclosingRect(
78 MathUtil::ProjectClippedRect(clip_to_target
, clip_node
->data
.clip
));
80 // Computing a transform to an ancestor should always succeed.
82 combined_clip_rect_in_target_space
=
83 gfx::ToEnclosingRect(MathUtil::MapClippedRect(
84 clip_to_target
, clip_node
->data
.combined_clip
));
85 clip_rect_in_target_space
= gfx::ToEnclosingRect(
86 MathUtil::MapClippedRect(clip_to_target
, clip_node
->data
.clip
));
89 if (clip_node
->data
.requires_tight_clip_rect
)
90 layer
->set_clip_rect_in_target_space_from_property_trees(
91 combined_clip_rect_in_target_space
);
93 layer
->set_clip_rect_in_target_space_from_property_trees(
94 clip_rect_in_target_space
);
96 gfx::Rect layer_content_rect
= gfx::Rect(layer_bounds
);
97 gfx::Rect layer_content_bounds_in_target_space
=
98 MathUtil::MapEnclosingClippedRect(content_to_target
,
100 combined_clip_rect_in_target_space
.Intersect(
101 layer_content_bounds_in_target_space
);
102 clip_rect_in_target_space
.Intersect(layer_content_bounds_in_target_space
);
103 if (combined_clip_rect_in_target_space
.IsEmpty()) {
104 layer
->set_visible_rect_from_property_trees(gfx::Rect());
108 // If the layer is fully contained within the clip, treat it as fully
109 // visible. Since clip_rect_in_target_space has already been intersected
110 // with layer_content_bounds_in_target_space, the layer is fully contained
111 // within the clip iff these rects are equal.
112 if (combined_clip_rect_in_target_space
==
113 layer_content_bounds_in_target_space
) {
114 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
118 gfx::Transform target_to_content
;
119 gfx::Transform target_to_layer
;
121 if (transform_node
->data
.ancestors_are_invertible
) {
122 target_to_layer
= transform_node
->data
.from_target
;
125 success
= transform_tree
.ComputeTransformWithSourceSublayerScale(
126 target_node
->id
, transform_node
->id
, &target_to_layer
);
130 // An animated singular transform may become non-singular during the
131 // animation, so we still need to compute a visible rect. In this
132 // situation, we treat the entire layer as visible.
133 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
137 target_to_content
.Translate(-layer
->offset_to_transform_parent().x(),
138 -layer
->offset_to_transform_parent().y());
139 target_to_content
.PreconcatTransform(target_to_layer
);
141 gfx::Rect visible_rect
= MathUtil::ProjectEnclosingClippedRect(
142 target_to_content
, combined_clip_rect_in_target_space
);
144 visible_rect
.Intersect(gfx::Rect(layer_bounds
));
146 layer
->set_visible_rect_from_property_trees(visible_rect
);
148 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
149 layer
->set_clip_rect_in_target_space_from_property_trees(
150 gfx::Rect(layer_bounds
));
155 template <typename LayerType
>
156 static bool IsRootLayerOfNewRenderingContext(LayerType
* layer
) {
158 return !layer
->parent()->Is3dSorted() && layer
->Is3dSorted();
159 return layer
->Is3dSorted();
162 template <typename LayerType
>
163 static inline bool LayerIsInExisting3DRenderingContext(LayerType
* layer
) {
164 return layer
->Is3dSorted() && layer
->parent() &&
165 layer
->parent()->Is3dSorted() &&
166 layer
->parent()->sorting_context_id() == layer
->sorting_context_id();
169 template <typename LayerType
>
170 static bool TransformToScreenIsKnown(LayerType
* layer
,
171 const TransformTree
& tree
) {
172 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
173 return !node
->data
.to_screen_is_animated
;
176 template <typename LayerType
>
177 static bool HasSingularTransform(LayerType
* layer
, const TransformTree
& tree
) {
178 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
179 return !node
->data
.is_invertible
|| !node
->data
.ancestors_are_invertible
;
182 template <typename LayerType
>
183 static bool IsLayerBackFaceVisible(LayerType
* layer
,
184 const TransformTree
& tree
) {
185 // The current W3C spec on CSS transforms says that backface visibility should
186 // be determined differently depending on whether the layer is in a "3d
187 // rendering context" or not. For Chromium code, we can determine whether we
188 // are in a 3d rendering context by checking if the parent preserves 3d.
190 if (LayerIsInExisting3DRenderingContext(layer
))
191 return DrawTransformFromPropertyTrees(layer
, tree
).IsBackFaceVisible();
193 // In this case, either the layer establishes a new 3d rendering context, or
194 // is not in a 3d rendering context at all.
195 return layer
->transform().IsBackFaceVisible();
198 template <typename LayerType
>
199 static bool IsSurfaceBackFaceVisible(LayerType
* layer
,
200 const TransformTree
& tree
) {
201 if (LayerIsInExisting3DRenderingContext(layer
)) {
202 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
203 // Draw transform as a contributing render surface.
204 // TODO(enne): we shouldn't walk the tree during a tree walk.
205 gfx::Transform surface_draw_transform
;
206 tree
.ComputeTransform(node
->id
, node
->data
.target_id
,
207 &surface_draw_transform
);
208 return surface_draw_transform
.IsBackFaceVisible();
211 if (IsRootLayerOfNewRenderingContext(layer
))
212 return layer
->transform().IsBackFaceVisible();
214 // If the render_surface is not part of a new or existing rendering context,
215 // then the layers that contribute to this surface will decide back-face
216 // visibility for themselves.
220 template <typename LayerType
>
221 static bool IsAnimatingTransformToScreen(LayerType
* layer
,
222 const TransformTree
& tree
) {
223 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
224 return node
->data
.to_screen_is_animated
;
227 static inline bool TransformToScreenIsKnown(Layer
* layer
,
228 const TransformTree
& tree
) {
229 return !IsAnimatingTransformToScreen(layer
, tree
);
232 static inline bool TransformToScreenIsKnown(LayerImpl
* layer
,
233 const TransformTree
& tree
) {
237 template <typename LayerType
>
238 static bool HasInvertibleOrAnimatedTransform(LayerType
* layer
) {
239 return layer
->transform_is_invertible() ||
240 layer
->HasPotentiallyRunningTransformAnimation();
243 static inline bool SubtreeShouldBeSkipped(LayerImpl
* layer
,
245 const TransformTree
& tree
) {
246 // If the layer transform is not invertible, it should not be drawn.
247 // TODO(ajuma): Correctly process subtrees with singular transform for the
248 // case where we may animate to a non-singular transform and wish to
250 if (!HasInvertibleOrAnimatedTransform(layer
))
253 // When we need to do a readback/copy of a layer's output, we can not skip
254 // it or any of its ancestors.
255 if (layer
->draw_properties().layer_or_descendant_has_copy_request
)
258 // If the layer is not drawn, then skip it and its subtree.
262 if (layer
->render_surface() && !layer
->double_sided() &&
263 IsSurfaceBackFaceVisible(layer
, tree
))
266 // If layer is on the pending tree and opacity is being animated then
267 // this subtree can't be skipped as we need to create, prioritize and
268 // include tiles for this layer when deciding if tree can be activated.
269 if (layer
->layer_tree_impl()->IsPendingTree() &&
270 layer
->HasPotentiallyRunningOpacityAnimation())
273 // If layer has a background filter, don't skip the layer, even it the
275 if (!layer
->background_filters().IsEmpty())
278 // The opacity of a layer always applies to its children (either implicitly
279 // via a render surface or explicitly if the parent preserves 3D), so the
280 // entire subtree can be skipped if this layer is fully transparent.
281 return !layer
->opacity();
284 static inline bool SubtreeShouldBeSkipped(Layer
* layer
,
286 const TransformTree
& tree
) {
287 // If the layer transform is not invertible, it should not be drawn.
288 if (!layer
->transform_is_invertible() &&
289 !layer
->HasPotentiallyRunningTransformAnimation())
292 // When we need to do a readback/copy of a layer's output, we can not skip
293 // it or any of its ancestors.
294 if (layer
->num_layer_or_descendants_with_copy_request() > 0)
297 // If the layer is not drawn, then skip it and its subtree.
301 if (layer
->has_render_surface() && !layer
->double_sided() &&
302 !layer
->HasPotentiallyRunningTransformAnimation() &&
303 IsSurfaceBackFaceVisible(layer
, tree
))
306 // If layer has a background filter, don't skip the layer, even it the
308 if (!layer
->background_filters().IsEmpty())
311 // If the opacity is being animated then the opacity on the main thread is
312 // unreliable (since the impl thread may be using a different opacity), so it
313 // should not be trusted.
314 // In particular, it should not cause the subtree to be skipped.
315 // Similarly, for layers that might animate opacity using an impl-only
316 // animation, their subtree should also not be skipped.
317 return !layer
->opacity() && !layer
->HasPotentiallyRunningOpacityAnimation() &&
318 !layer
->OpacityCanAnimateOnImplThread();
321 template <typename LayerType
>
322 static bool LayerShouldBeSkipped(LayerType
* layer
,
324 const TransformTree
& tree
) {
325 // Layers can be skipped if any of these conditions are met.
326 // - is not drawn due to it or one of its ancestors being hidden (or having
327 // no copy requests).
328 // - does not draw content.
330 // - has empty bounds
331 // - the layer is not double-sided, but its back face is visible.
333 // Some additional conditions need to be computed at a later point after the
334 // recursion is finished.
335 // - the intersection of render_surface content and layer clip_rect is empty
336 // - the visible_layer_rect is empty
338 // Note, if the layer should not have been drawn due to being fully
339 // transparent, we would have skipped the entire subtree and never made it
340 // into this function, so it is safe to omit this check here.
344 if (!layer
->DrawsContent() || layer
->bounds().IsEmpty())
347 LayerType
* backface_test_layer
= layer
;
348 if (layer
->use_parent_backface_visibility()) {
349 DCHECK(layer
->parent());
350 DCHECK(!layer
->parent()->use_parent_backface_visibility());
351 backface_test_layer
= layer
->parent();
354 // The layer should not be drawn if (1) it is not double-sided and (2) the
355 // back of the layer is known to be facing the screen.
356 if (!backface_test_layer
->double_sided() &&
357 TransformToScreenIsKnown(backface_test_layer
, tree
) &&
358 IsLayerBackFaceVisible(backface_test_layer
, tree
))
364 template <typename LayerType
>
365 void FindLayersThatNeedUpdates(
367 const TransformTree
& tree
,
368 bool subtree_is_visible_from_ancestor
,
369 typename
LayerType::LayerListType
* update_layer_list
,
370 std::vector
<LayerType
*>* visible_layer_list
) {
371 bool layer_is_drawn
=
372 layer
->HasCopyRequest() ||
373 (subtree_is_visible_from_ancestor
&& !layer
->hide_layer_and_subtree());
375 if (layer
->parent() && SubtreeShouldBeSkipped(layer
, layer_is_drawn
, tree
))
378 if (!LayerShouldBeSkipped(layer
, layer_is_drawn
, tree
)) {
379 visible_layer_list
->push_back(layer
);
380 update_layer_list
->push_back(layer
);
383 // Append mask layers to the update layer list. They don't have valid visible
384 // rects, so need to get added after the above calculation. Replica layers
385 // don't need to be updated.
386 if (LayerType
* mask_layer
= layer
->mask_layer())
387 update_layer_list
->push_back(mask_layer
);
388 if (LayerType
* replica_layer
= layer
->replica_layer()) {
389 if (LayerType
* mask_layer
= replica_layer
->mask_layer())
390 update_layer_list
->push_back(mask_layer
);
393 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
394 FindLayersThatNeedUpdates(layer
->child_at(i
), tree
, layer_is_drawn
,
395 update_layer_list
, visible_layer_list
);
401 void ComputeClips(ClipTree
* clip_tree
, const TransformTree
& transform_tree
) {
402 if (!clip_tree
->needs_update())
404 for (int i
= 0; i
< static_cast<int>(clip_tree
->size()); ++i
) {
405 ClipNode
* clip_node
= clip_tree
->Node(i
);
406 const TransformNode
* transform_node
=
407 transform_tree
.Node(clip_node
->data
.transform_id
);
409 // Only descendants of a real clipping layer (i.e., not 0) may have their
410 // clip adjusted due to intersecting with an ancestor clip.
411 const bool is_clipped
= clip_node
->parent_id
> 0;
413 DCHECK(!clip_node
->data
.inherit_parent_target_space_clip
);
414 clip_node
->data
.combined_clip
= clip_node
->data
.clip
;
415 if (clip_node
->id
> 0) {
416 gfx::Transform to_target
= transform_node
->data
.to_target
;
417 clip_node
->data
.clip_in_target_space
=
418 MathUtil::MapClippedRect(to_target
, clip_node
->data
.combined_clip
);
423 ClipNode
* parent_clip_node
= clip_tree
->parent(clip_node
);
424 const TransformNode
* parent_transform_node
=
425 transform_tree
.Node(parent_clip_node
->data
.transform_id
);
427 // Clips must be combined in target space. We cannot, for example, combine
428 // clips in the space of the child clip. The reason is non-affine
429 // transforms. Say we have the following tree T->A->B->C, and B clips C, but
430 // draw into target T. It may be the case that A applies a perspective
431 // transform, and B and C are at different z positions. When projected into
432 // target space, the relative sizes and positions of B and C can shift.
433 // Since it's the relationship in target space that matters, that's where we
434 // must combine clips.
435 gfx::Transform parent_to_target
;
436 gfx::Transform clip_to_target
;
438 gfx::Transform target_to_clip
;
439 gfx::Transform parent_to_transform_target
;
440 gfx::Transform transform_target_to_target
;
442 const bool target_is_root_surface
= clip_node
->data
.target_id
== 1;
443 // When the target is the root surface, we need to include the root
444 // transform by walking up to the root of the transform tree.
445 const int target_id
=
446 target_is_root_surface
? 0 : clip_node
->data
.target_id
;
449 // When render surface applies clip, we need the clip from the target's
450 // target space. But, as the combined clip is in parent clip's target
451 // space, we need to first transform it from parent's target space to
452 // target's target space.
453 if (clip_node
->data
.inherit_parent_target_space_clip
) {
454 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
455 parent_transform_node
->id
, transform_node
->data
.target_id
,
456 &parent_to_transform_target
);
457 success
&= transform_tree
.ComputeTransformWithSourceSublayerScale(
458 transform_node
->data
.target_id
, target_id
,
459 &transform_target_to_target
);
460 transform_target_to_target
.matrix().postScale(
461 transform_node
->data
.sublayer_scale
.x(),
462 transform_node
->data
.sublayer_scale
.y(), 1.0);
463 } else if (parent_transform_node
->data
.content_target_id
==
464 clip_node
->data
.target_id
) {
465 parent_to_target
= parent_transform_node
->data
.to_target
;
467 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
468 parent_transform_node
->id
, target_id
, &parent_to_target
);
471 if (transform_node
->data
.content_target_id
== clip_node
->data
.target_id
) {
472 clip_to_target
= transform_node
->data
.to_target
;
474 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
475 transform_node
->id
, target_id
, &clip_to_target
);
478 if (transform_node
->data
.content_target_id
== clip_node
->data
.target_id
&&
479 transform_node
->data
.ancestors_are_invertible
) {
480 target_to_clip
= transform_node
->data
.from_target
;
482 success
&= clip_to_target
.GetInverse(&target_to_clip
);
485 // If we can't compute a transform, it's because we had to use the inverse
486 // of a singular transform. We won't draw in this case, so there's no need
492 // In order to intersect with as small a rect as possible, we do a
493 // preliminary clip in target space so that when we project back, there's
494 // less likelihood of intersecting the view plane.
495 gfx::RectF inherited_clip_in_target_space
;
496 if (clip_node
->data
.inherit_parent_target_space_clip
) {
497 gfx::RectF combined_clip_in_transform_target_space
;
498 if (parent_transform_node
->id
> transform_node
->data
.target_id
)
499 combined_clip_in_transform_target_space
= MathUtil::MapClippedRect(
500 parent_to_transform_target
, parent_clip_node
->data
.combined_clip
);
502 combined_clip_in_transform_target_space
= MathUtil::ProjectClippedRect(
503 parent_to_transform_target
, parent_clip_node
->data
.combined_clip
);
504 inherited_clip_in_target_space
= MathUtil::ProjectClippedRect(
505 transform_target_to_target
, combined_clip_in_transform_target_space
);
506 } else if (parent_transform_node
->id
> target_id
) {
507 inherited_clip_in_target_space
= MathUtil::MapClippedRect(
508 parent_to_target
, parent_clip_node
->data
.combined_clip
);
510 inherited_clip_in_target_space
= MathUtil::ProjectClippedRect(
511 parent_to_target
, parent_clip_node
->data
.combined_clip
);
514 // When render surface inherits its parent target space clip, the layer
515 // that created the clip node doesn't apply any clip. So, we shouldn't clip
516 // using the clip value stored in the clip node.
517 gfx::RectF intersected_in_target_space
;
518 if (!clip_node
->data
.inherit_parent_target_space_clip
) {
519 gfx::RectF clip_in_target_space
=
520 MathUtil::MapClippedRect(clip_to_target
, clip_node
->data
.clip
);
521 intersected_in_target_space
= gfx::IntersectRects(
522 inherited_clip_in_target_space
, clip_in_target_space
);
523 if (!clip_node
->data
.requires_tight_clip_rect
)
524 clip_node
->data
.clip_in_target_space
= clip_in_target_space
;
526 clip_node
->data
.clip_in_target_space
= intersected_in_target_space
;
528 intersected_in_target_space
= inherited_clip_in_target_space
;
529 clip_node
->data
.clip_in_target_space
= intersected_in_target_space
;
532 clip_node
->data
.combined_clip
= MathUtil::ProjectClippedRect(
533 target_to_clip
, intersected_in_target_space
);
535 if (!clip_node
->data
.inherit_parent_target_space_clip
)
536 clip_node
->data
.combined_clip
.Intersect(clip_node
->data
.clip
);
538 clip_tree
->set_needs_update(false);
541 void ComputeTransforms(TransformTree
* transform_tree
) {
542 if (!transform_tree
->needs_update())
544 for (int i
= 1; i
< static_cast<int>(transform_tree
->size()); ++i
)
545 transform_tree
->UpdateTransforms(i
);
546 transform_tree
->set_needs_update(false);
549 void ComputeOpacities(EffectTree
* effect_tree
) {
550 if (!effect_tree
->needs_update())
552 for (int i
= 1; i
< static_cast<int>(effect_tree
->size()); ++i
)
553 effect_tree
->UpdateOpacities(i
);
554 effect_tree
->set_needs_update(false);
557 template <typename LayerType
>
558 void ComputeVisibleRectsUsingPropertyTreesInternal(
559 LayerType
* root_layer
,
560 PropertyTrees
* property_trees
,
561 typename
LayerType::LayerListType
* update_layer_list
) {
562 if (property_trees
->transform_tree
.needs_update())
563 property_trees
->clip_tree
.set_needs_update(true);
564 ComputeTransforms(&property_trees
->transform_tree
);
565 ComputeClips(&property_trees
->clip_tree
, property_trees
->transform_tree
);
566 ComputeOpacities(&property_trees
->effect_tree
);
568 const bool subtree_is_visible_from_ancestor
= true;
569 std::vector
<LayerType
*> visible_layer_list
;
570 FindLayersThatNeedUpdates(root_layer
, property_trees
->transform_tree
,
571 subtree_is_visible_from_ancestor
, update_layer_list
,
572 &visible_layer_list
);
573 CalculateVisibleRects
<LayerType
>(visible_layer_list
,
574 property_trees
->clip_tree
,
575 property_trees
->transform_tree
);
578 void BuildPropertyTreesAndComputeVisibleRects(
580 const Layer
* page_scale_layer
,
581 const Layer
* inner_viewport_scroll_layer
,
582 const Layer
* outer_viewport_scroll_layer
,
583 float page_scale_factor
,
584 float device_scale_factor
,
585 const gfx::Rect
& viewport
,
586 const gfx::Transform
& device_transform
,
587 PropertyTrees
* property_trees
,
588 LayerList
* update_layer_list
) {
589 PropertyTreeBuilder::BuildPropertyTrees(
590 root_layer
, page_scale_layer
, inner_viewport_scroll_layer
,
591 outer_viewport_scroll_layer
, page_scale_factor
, device_scale_factor
,
592 viewport
, device_transform
, property_trees
);
593 ComputeVisibleRectsUsingPropertyTrees(root_layer
, property_trees
,
597 void BuildPropertyTreesAndComputeVisibleRects(
598 LayerImpl
* root_layer
,
599 const LayerImpl
* page_scale_layer
,
600 const LayerImpl
* inner_viewport_scroll_layer
,
601 const LayerImpl
* outer_viewport_scroll_layer
,
602 float page_scale_factor
,
603 float device_scale_factor
,
604 const gfx::Rect
& viewport
,
605 const gfx::Transform
& device_transform
,
606 PropertyTrees
* property_trees
,
607 LayerImplList
* update_layer_list
) {
608 PropertyTreeBuilder::BuildPropertyTrees(
609 root_layer
, page_scale_layer
, inner_viewport_scroll_layer
,
610 outer_viewport_scroll_layer
, page_scale_factor
, device_scale_factor
,
611 viewport
, device_transform
, property_trees
);
612 ComputeVisibleRectsUsingPropertyTrees(root_layer
, property_trees
,
616 void ComputeVisibleRectsUsingPropertyTrees(Layer
* root_layer
,
617 PropertyTrees
* property_trees
,
618 LayerList
* update_layer_list
) {
619 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
,
623 void ComputeVisibleRectsUsingPropertyTrees(LayerImpl
* root_layer
,
624 PropertyTrees
* property_trees
,
625 LayerImplList
* update_layer_list
) {
626 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
,
630 template <typename LayerType
>
631 gfx::Transform
DrawTransformFromPropertyTreesInternal(
632 const LayerType
* layer
,
633 const TransformTree
& tree
) {
634 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
636 gfx::Transform xform
;
637 const bool owns_non_root_surface
=
638 layer
->parent() && layer
->has_render_surface();
639 if (!owns_non_root_surface
) {
640 // If you're not the root, or you don't own a surface, you need to apply
641 // your local offset.
642 xform
= node
->data
.to_target
;
643 if (layer
->should_flatten_transform_from_property_tree())
645 xform
.Translate(layer
->offset_to_transform_parent().x(),
646 layer
->offset_to_transform_parent().y());
648 // Surfaces need to apply their sublayer scale.
649 xform
.Scale(node
->data
.sublayer_scale
.x(), node
->data
.sublayer_scale
.y());
654 gfx::Transform
DrawTransformFromPropertyTrees(const Layer
* layer
,
655 const TransformTree
& tree
) {
656 return DrawTransformFromPropertyTreesInternal(layer
, tree
);
659 gfx::Transform
DrawTransformFromPropertyTrees(const LayerImpl
* layer
,
660 const TransformTree
& tree
) {
661 return DrawTransformFromPropertyTreesInternal(layer
, tree
);
664 gfx::Transform
DrawTransformOfRenderSurfaceFromPropertyTrees(
665 const RenderSurfaceImpl
* render_surface
,
666 const TransformTree
& tree
) {
667 const TransformNode
* node
= tree
.Node(render_surface
->TransformTreeIndex());
668 gfx::Transform render_surface_transform
;
669 // The draw transform of root render surface is identity tranform.
671 return render_surface_transform
;
672 const TransformNode
* target_node
= tree
.Node(node
->data
.target_id
);
673 if (target_node
->id
== 1)
674 target_node
= tree
.Node(0);
675 tree
.ComputeTransformWithDestinationSublayerScale(node
->id
, target_node
->id
,
676 &render_surface_transform
);
677 if (node
->data
.sublayer_scale
.x() != 0.0 &&
678 node
->data
.sublayer_scale
.y() != 0.0)
679 render_surface_transform
.Scale(1.0 / node
->data
.sublayer_scale
.x(),
680 1.0 / node
->data
.sublayer_scale
.y());
681 return render_surface_transform
;
684 bool RenderSurfaceIsClippedFromPropertyTrees(
685 const RenderSurfaceImpl
* render_surface
,
686 const ClipTree
& tree
) {
687 const ClipNode
* node
= tree
.Node(render_surface
->ClipTreeIndex());
688 // If the render surface's owning layer doesn't form a clip node, it is not
690 if (render_surface
->OwningLayerId() != node
->owner_id
)
692 return node
->data
.render_surface_is_clipped
;
695 gfx::Rect
ClipRectOfRenderSurfaceFromPropertyTrees(
696 const RenderSurfaceImpl
* render_surface
,
697 const ClipTree
& clip_tree
) {
698 if (!RenderSurfaceIsClippedFromPropertyTrees(render_surface
, clip_tree
))
700 const ClipNode
* clip_node
= clip_tree
.Node(render_surface
->ClipTreeIndex());
701 const ClipNode
* parent_clip_node
= clip_tree
.parent(clip_node
);
702 return gfx::ToEnclosingRect(parent_clip_node
->data
.clip_in_target_space
);
705 gfx::Transform
ScreenSpaceTransformOfRenderSurfaceFromPropertyTrees(
706 const RenderSurfaceImpl
* render_surface
,
707 const TransformTree
& tree
) {
708 const TransformNode
* node
= tree
.Node(render_surface
->TransformTreeIndex());
709 gfx::Transform screen_space_transform
;
710 // The screen space transform of root render surface is identity tranform.
712 return screen_space_transform
;
713 screen_space_transform
= node
->data
.to_screen
;
714 if (node
->data
.sublayer_scale
.x() != 0.0 &&
715 node
->data
.sublayer_scale
.y() != 0.0)
716 screen_space_transform
.Scale(1.0 / node
->data
.sublayer_scale
.x(),
717 1.0 / node
->data
.sublayer_scale
.y());
718 return screen_space_transform
;
721 template <typename LayerType
>
722 gfx::Transform
ScreenSpaceTransformFromPropertyTreesInternal(
724 const TransformTree
& tree
) {
725 gfx::Transform
xform(1, 0, 0, 1, layer
->offset_to_transform_parent().x(),
726 layer
->offset_to_transform_parent().y());
727 if (layer
->transform_tree_index() >= 0) {
728 gfx::Transform ssxform
=
729 tree
.Node(layer
->transform_tree_index())->data
.to_screen
;
730 xform
.ConcatTransform(ssxform
);
731 if (layer
->should_flatten_transform_from_property_tree())
737 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
739 const TransformTree
& tree
) {
740 return ScreenSpaceTransformFromPropertyTreesInternal(layer
, tree
);
743 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
744 const LayerImpl
* layer
,
745 const TransformTree
& tree
) {
746 return ScreenSpaceTransformFromPropertyTreesInternal(layer
, tree
);
749 template <typename LayerType
>
750 bool ScreenSpaceTransformIsAnimatingFromPropertyTreesInternal(
752 const TransformTree
& tree
) {
753 return tree
.Node(layer
->transform_tree_index())->data
.to_screen_is_animated
;
756 bool ScreenSpaceTransformIsAnimatingFromPropertyTrees(
758 const TransformTree
& tree
) {
759 return ScreenSpaceTransformIsAnimatingFromPropertyTreesInternal(layer
, tree
);
762 bool ScreenSpaceTransformIsAnimatingFromPropertyTrees(
763 const LayerImpl
* layer
,
764 const TransformTree
& tree
) {
765 return ScreenSpaceTransformIsAnimatingFromPropertyTreesInternal(layer
, tree
);
768 float MaximumAnimationTargetScaleFromPropertyTrees(const LayerImpl
* layer
,
769 const TransformTree
& tree
) {
770 if (!layer
->layer_tree_impl()
772 .layer_transforms_should_scale_layer_contents
)
775 return tree
.Node(layer
->transform_tree_index())
776 ->data
.combined_maximum_animation_target_scale
;
779 float StartingAnimationScaleFromPropertyTrees(const LayerImpl
* layer
,
780 const TransformTree
& tree
) {
781 if (!layer
->layer_tree_impl()
783 .layer_transforms_should_scale_layer_contents
)
786 return tree
.Node(layer
->transform_tree_index())
787 ->data
.combined_starting_animation_scale
;
790 float DrawOpacityFromPropertyTrees(const LayerImpl
* layer
,
791 const EffectTree
& tree
) {
792 if (!layer
->render_target())
795 const EffectNode
* target_node
=
796 tree
.Node(layer
->render_target()->effect_tree_index());
797 const EffectNode
* node
= tree
.Node(layer
->effect_tree_index());
798 if (node
== target_node
)
801 float draw_opacity
= 1.f
;
802 while (node
!= target_node
) {
803 draw_opacity
*= node
->data
.opacity
;
804 node
= tree
.parent(node
);
809 float DrawOpacityOfRenderSurfaceFromPropertyTrees(
810 RenderSurfaceImpl
* render_surface
,
811 const EffectTree
& tree
) {
812 const EffectNode
* node
= tree
.Node(render_surface
->EffectTreeIndex());
813 float target_opacity_tree_index
= render_surface
->TargetEffectTreeIndex();
814 if (target_opacity_tree_index
< 0)
815 return node
->data
.screen_space_opacity
;
816 const EffectNode
* target_node
= tree
.Node(target_opacity_tree_index
);
817 float draw_opacity
= 1.f
;
818 while (node
!= target_node
) {
819 draw_opacity
*= node
->data
.opacity
;
820 node
= tree
.parent(node
);
825 bool CanUseLcdTextFromPropertyTrees(const LayerImpl
* layer
,
826 bool layers_always_allowed_lcd_text
,
827 bool can_use_lcd_text
,
828 PropertyTrees
* property_trees
) {
829 if (layers_always_allowed_lcd_text
)
831 if (!can_use_lcd_text
)
833 if (!layer
->contents_opaque())
835 DCHECK(!property_trees
->transform_tree
.needs_update());
836 DCHECK(!property_trees
->effect_tree
.needs_update());
838 const EffectNode
* opacity_node
=
839 property_trees
->effect_tree
.Node(layer
->effect_tree_index());
840 if (opacity_node
->data
.screen_space_opacity
!= 1.f
)
842 const TransformNode
* transform_node
=
843 property_trees
->transform_tree
.Node(layer
->transform_tree_index());
844 if (!transform_node
->data
.node_and_ancestors_have_only_integer_translation
)
846 if (static_cast<int>(layer
->offset_to_transform_parent().x()) !=
847 layer
->offset_to_transform_parent().x())
849 if (static_cast<int>(layer
->offset_to_transform_parent().y()) !=
850 layer
->offset_to_transform_parent().y())
855 gfx::Rect
DrawableContentRectOfSurfaceFromPropertyTrees(
856 const RenderSurfaceImpl
* render_surface
,
857 const TransformTree
& transform_tree
) {
858 gfx::Rect drawable_content_rect
=
859 gfx::ToEnclosingRect(MathUtil::MapClippedRect(
860 DrawTransformOfRenderSurfaceFromPropertyTrees(render_surface
,
862 render_surface
->content_rect_from_property_trees()));
863 if (render_surface
->HasReplica()) {
864 drawable_content_rect
.Union(gfx::ToEnclosingRect(MathUtil::MapClippedRect(
865 DrawTransformOfRenderSurfaceReplicaFromPropertyTrees(render_surface
,
867 render_surface
->content_rect_from_property_trees())));
869 return drawable_content_rect
;
872 gfx::Rect
DrawableContentRectFromPropertyTrees(
873 const LayerImpl
* layer
,
874 const TransformTree
& transform_tree
) {
875 gfx::Rect drawable_content_rect
= MathUtil::MapEnclosingClippedRect(
876 DrawTransformFromPropertyTrees(layer
, transform_tree
),
877 gfx::Rect(layer
->bounds()));
878 if (layer
->is_clipped()) {
879 drawable_content_rect
.Intersect(
880 layer
->clip_rect_in_target_space_from_property_trees());
882 return drawable_content_rect
;
885 gfx::Rect
ClipRectFromPropertyTrees(const LayerImpl
* layer
,
886 const TransformTree
& transform_tree
) {
887 if (layer
->is_clipped())
888 return layer
->clip_rect_in_target_space_from_property_trees();
889 return MathUtil::MapEnclosingClippedRect(
890 DrawTransformFromPropertyTrees(layer
, transform_tree
),
891 gfx::Rect(layer
->bounds()));
894 gfx::Transform
ReplicaToSurfaceTransform(
895 const RenderSurfaceImpl
* render_surface
,
896 const TransformTree
& tree
) {
897 gfx::Transform replica_to_surface
;
898 if (!render_surface
->HasReplica())
899 return replica_to_surface
;
900 const LayerImpl
* replica_layer
= render_surface
->ReplicaLayer();
901 const TransformNode
* surface_transform_node
=
902 tree
.Node(render_surface
->TransformTreeIndex());
903 replica_to_surface
.Scale(surface_transform_node
->data
.sublayer_scale
.x(),
904 surface_transform_node
->data
.sublayer_scale
.y());
905 replica_to_surface
.Translate(replica_layer
->offset_to_transform_parent().x(),
906 replica_layer
->offset_to_transform_parent().y());
907 gfx::Transform replica_transform_node_to_surface
;
908 tree
.ComputeTransform(replica_layer
->transform_tree_index(),
909 render_surface
->TransformTreeIndex(),
910 &replica_transform_node_to_surface
);
911 replica_to_surface
.PreconcatTransform(replica_transform_node_to_surface
);
912 if (surface_transform_node
->data
.sublayer_scale
.x() != 0 &&
913 surface_transform_node
->data
.sublayer_scale
.y() != 0) {
914 replica_to_surface
.Scale(
915 1.0 / surface_transform_node
->data
.sublayer_scale
.x(),
916 1.0 / surface_transform_node
->data
.sublayer_scale
.y());
918 return replica_to_surface
;
921 gfx::Transform
DrawTransformOfRenderSurfaceReplicaFromPropertyTrees(
922 const RenderSurfaceImpl
* render_surface
,
923 const TransformTree
& tree
) {
924 if (!render_surface
->HasReplica())
925 return gfx::Transform();
926 return DrawTransformOfRenderSurfaceFromPropertyTrees(render_surface
, tree
) *
927 ReplicaToSurfaceTransform(render_surface
, tree
);
930 gfx::Transform
ScreenSpaceTransformOfRenderSurfaceReplicaFromPropertyTrees(
931 const RenderSurfaceImpl
* render_surface
,
932 const TransformTree
& tree
) {
933 if (!render_surface
->HasReplica())
934 return gfx::Transform();
935 return ScreenSpaceTransformOfRenderSurfaceFromPropertyTrees(render_surface
,
937 ReplicaToSurfaceTransform(render_surface
, tree
);