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/draw_properties.h"
11 #include "cc/layers/layer.h"
12 #include "cc/layers/layer_impl.h"
13 #include "cc/layers/render_surface_draw_properties.h"
14 #include "cc/trees/layer_tree_impl.h"
15 #include "cc/trees/property_tree.h"
16 #include "cc/trees/property_tree_builder.h"
17 #include "ui/gfx/geometry/rect_conversions.h"
23 template <typename LayerType
>
24 void CalculateVisibleRects(const std::vector
<LayerType
*>& visible_layer_list
,
25 const ClipTree
& clip_tree
,
26 const TransformTree
& transform_tree
) {
27 for (auto& layer
: visible_layer_list
) {
28 // TODO(ajuma): Compute content_scale rather than using it. Note that for
29 // PictureLayer and PictureImageLayers, content_bounds == bounds and
30 // content_scale_x == content_scale_y == 1.0, so once impl painting is on
31 // everywhere, this code will be unnecessary.
32 gfx::Size layer_bounds
= layer
->bounds();
33 const bool has_clip
= layer
->clip_tree_index() > 0;
34 const TransformNode
* transform_node
=
35 transform_tree
.Node(layer
->transform_tree_index());
37 const ClipNode
* clip_node
= clip_tree
.Node(layer
->clip_tree_index());
38 const TransformNode
* clip_transform_node
=
39 transform_tree
.Node(clip_node
->data
.transform_id
);
40 const bool target_is_root_surface
=
41 transform_node
->data
.content_target_id
== 1;
42 // When the target is the root surface, we need to include the root
43 // transform by walking up to the root of the transform tree.
45 target_is_root_surface
? 0 : transform_node
->data
.content_target_id
;
46 const TransformNode
* target_node
= transform_tree
.Node(target_id
);
48 gfx::Transform content_to_target
= transform_node
->data
.to_target
;
50 content_to_target
.Translate(layer
->offset_to_transform_parent().x(),
51 layer
->offset_to_transform_parent().y());
53 gfx::Rect combined_clip_rect_in_target_space
;
54 gfx::Rect clip_rect_in_target_space
;
55 gfx::Transform clip_to_target
;
57 if (clip_transform_node
->data
.target_id
== target_node
->id
) {
58 clip_to_target
= clip_transform_node
->data
.to_target
;
60 success
= transform_tree
.ComputeTransformWithDestinationSublayerScale(
61 clip_transform_node
->id
, target_node
->id
, &clip_to_target
);
63 if (target_node
->id
> clip_node
->data
.transform_id
) {
65 DCHECK(target_node
->data
.to_screen_is_animated
);
67 // An animated singular transform may become non-singular during the
68 // animation, so we still need to compute a visible rect. In this
69 // situation, we treat the entire layer as visible.
70 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
71 layer
->set_clip_rect_in_target_space_from_property_trees(
72 gfx::ToEnclosingRect(clip_node
->data
.combined_clip
));
76 combined_clip_rect_in_target_space
=
77 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
78 clip_to_target
, clip_node
->data
.combined_clip
));
79 clip_rect_in_target_space
= gfx::ToEnclosingRect(
80 MathUtil::ProjectClippedRect(clip_to_target
, clip_node
->data
.clip
));
82 // Computing a transform to an ancestor should always succeed.
84 combined_clip_rect_in_target_space
=
85 gfx::ToEnclosingRect(MathUtil::MapClippedRect(
86 clip_to_target
, clip_node
->data
.combined_clip
));
87 clip_rect_in_target_space
= gfx::ToEnclosingRect(
88 MathUtil::MapClippedRect(clip_to_target
, clip_node
->data
.clip
));
91 if (clip_node
->data
.requires_tight_clip_rect
)
92 layer
->set_clip_rect_in_target_space_from_property_trees(
93 combined_clip_rect_in_target_space
);
95 layer
->set_clip_rect_in_target_space_from_property_trees(
96 clip_rect_in_target_space
);
98 gfx::Rect layer_content_rect
= gfx::Rect(layer_bounds
);
99 gfx::Rect layer_content_bounds_in_target_space
=
100 MathUtil::MapEnclosingClippedRect(content_to_target
,
102 combined_clip_rect_in_target_space
.Intersect(
103 layer_content_bounds_in_target_space
);
104 clip_rect_in_target_space
.Intersect(layer_content_bounds_in_target_space
);
105 if (combined_clip_rect_in_target_space
.IsEmpty()) {
106 layer
->set_visible_rect_from_property_trees(gfx::Rect());
110 // If the layer is fully contained within the clip, treat it as fully
111 // visible. Since clip_rect_in_target_space has already been intersected
112 // with layer_content_bounds_in_target_space, the layer is fully contained
113 // within the clip iff these rects are equal.
114 if (combined_clip_rect_in_target_space
==
115 layer_content_bounds_in_target_space
) {
116 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
120 gfx::Transform target_to_content
;
121 gfx::Transform target_to_layer
;
123 if (transform_node
->data
.ancestors_are_invertible
) {
124 target_to_layer
= transform_node
->data
.from_target
;
127 success
= transform_tree
.ComputeTransformWithSourceSublayerScale(
128 target_node
->id
, transform_node
->id
, &target_to_layer
);
132 // An animated singular transform may become non-singular during the
133 // animation, so we still need to compute a visible rect. In this
134 // situation, we treat the entire layer as visible.
135 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
139 target_to_content
.Translate(-layer
->offset_to_transform_parent().x(),
140 -layer
->offset_to_transform_parent().y());
141 target_to_content
.PreconcatTransform(target_to_layer
);
143 gfx::Rect visible_rect
= MathUtil::ProjectEnclosingClippedRect(
144 target_to_content
, combined_clip_rect_in_target_space
);
146 visible_rect
.Intersect(gfx::Rect(layer_bounds
));
148 layer
->set_visible_rect_from_property_trees(visible_rect
);
150 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
151 layer
->set_clip_rect_in_target_space_from_property_trees(
152 gfx::Rect(layer_bounds
));
157 template <typename LayerType
>
158 static bool IsRootLayerOfNewRenderingContext(LayerType
* layer
) {
160 return !layer
->parent()->Is3dSorted() && layer
->Is3dSorted();
161 return layer
->Is3dSorted();
164 template <typename LayerType
>
165 static inline bool LayerIsInExisting3DRenderingContext(LayerType
* layer
) {
166 return layer
->Is3dSorted() && layer
->parent() &&
167 layer
->parent()->Is3dSorted() &&
168 layer
->parent()->sorting_context_id() == layer
->sorting_context_id();
171 template <typename LayerType
>
172 static bool TransformToScreenIsKnown(LayerType
* layer
,
173 const TransformTree
& tree
) {
174 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
175 return !node
->data
.to_screen_is_animated
;
178 template <typename LayerType
>
179 static bool HasSingularTransform(LayerType
* layer
, const TransformTree
& tree
) {
180 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
181 return !node
->data
.is_invertible
|| !node
->data
.ancestors_are_invertible
;
184 template <typename LayerType
>
185 static bool IsLayerBackFaceVisible(LayerType
* layer
,
186 const TransformTree
& tree
) {
187 // The current W3C spec on CSS transforms says that backface visibility should
188 // be determined differently depending on whether the layer is in a "3d
189 // rendering context" or not. For Chromium code, we can determine whether we
190 // are in a 3d rendering context by checking if the parent preserves 3d.
192 if (LayerIsInExisting3DRenderingContext(layer
))
193 return DrawTransformFromPropertyTrees(layer
, tree
).IsBackFaceVisible();
195 // In this case, either the layer establishes a new 3d rendering context, or
196 // is not in a 3d rendering context at all.
197 return layer
->transform().IsBackFaceVisible();
200 template <typename LayerType
>
201 static bool IsSurfaceBackFaceVisible(LayerType
* layer
,
202 const TransformTree
& tree
) {
203 if (LayerIsInExisting3DRenderingContext(layer
)) {
204 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
205 // Draw transform as a contributing render surface.
206 // TODO(enne): we shouldn't walk the tree during a tree walk.
207 gfx::Transform surface_draw_transform
;
208 tree
.ComputeTransform(node
->id
, node
->data
.target_id
,
209 &surface_draw_transform
);
210 return surface_draw_transform
.IsBackFaceVisible();
213 if (IsRootLayerOfNewRenderingContext(layer
))
214 return layer
->transform().IsBackFaceVisible();
216 // If the render_surface is not part of a new or existing rendering context,
217 // then the layers that contribute to this surface will decide back-face
218 // visibility for themselves.
222 template <typename LayerType
>
223 static bool IsAnimatingTransformToScreen(LayerType
* layer
,
224 const TransformTree
& tree
) {
225 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
226 return node
->data
.to_screen_is_animated
;
229 static inline bool TransformToScreenIsKnown(Layer
* layer
,
230 const TransformTree
& tree
) {
231 return !IsAnimatingTransformToScreen(layer
, tree
);
234 static inline bool TransformToScreenIsKnown(LayerImpl
* layer
,
235 const TransformTree
& tree
) {
239 template <typename LayerType
>
240 static bool HasInvertibleOrAnimatedTransform(LayerType
* layer
) {
241 return layer
->transform_is_invertible() ||
242 layer
->HasPotentiallyRunningTransformAnimation();
245 static inline bool SubtreeShouldBeSkipped(LayerImpl
* layer
,
247 const TransformTree
& tree
) {
248 // If the layer transform is not invertible, it should not be drawn.
249 // TODO(ajuma): Correctly process subtrees with singular transform for the
250 // case where we may animate to a non-singular transform and wish to
252 if (!HasInvertibleOrAnimatedTransform(layer
))
255 // When we need to do a readback/copy of a layer's output, we can not skip
256 // it or any of its ancestors.
257 if (layer
->draw_properties().layer_or_descendant_has_copy_request
)
260 // If the layer is not drawn, then skip it and its subtree.
264 if (layer
->render_surface() && !layer
->double_sided() &&
265 IsSurfaceBackFaceVisible(layer
, tree
))
268 // If layer is on the pending tree and opacity is being animated then
269 // this subtree can't be skipped as we need to create, prioritize and
270 // include tiles for this layer when deciding if tree can be activated.
271 if (layer
->layer_tree_impl()->IsPendingTree() &&
272 layer
->HasPotentiallyRunningOpacityAnimation())
275 // If layer has a background filter, don't skip the layer, even it the
277 if (!layer
->background_filters().IsEmpty())
280 // The opacity of a layer always applies to its children (either implicitly
281 // via a render surface or explicitly if the parent preserves 3D), so the
282 // entire subtree can be skipped if this layer is fully transparent.
283 return !layer
->opacity();
286 static inline bool SubtreeShouldBeSkipped(Layer
* layer
,
288 const TransformTree
& tree
) {
289 // If the layer transform is not invertible, it should not be drawn.
290 if (!layer
->transform_is_invertible() &&
291 !layer
->HasPotentiallyRunningTransformAnimation())
294 // When we need to do a readback/copy of a layer's output, we can not skip
295 // it or any of its ancestors.
296 if (layer
->num_layer_or_descendants_with_copy_request() > 0)
299 // If the layer is not drawn, then skip it and its subtree.
303 if (layer
->has_render_surface() && !layer
->double_sided() &&
304 !layer
->HasPotentiallyRunningTransformAnimation() &&
305 IsSurfaceBackFaceVisible(layer
, tree
))
308 // If layer has a background filter, don't skip the layer, even it the
310 if (!layer
->background_filters().IsEmpty())
313 // If the opacity is being animated then the opacity on the main thread is
314 // unreliable (since the impl thread may be using a different opacity), so it
315 // should not be trusted.
316 // In particular, it should not cause the subtree to be skipped.
317 // Similarly, for layers that might animate opacity using an impl-only
318 // animation, their subtree should also not be skipped.
319 return !layer
->opacity() && !layer
->HasPotentiallyRunningOpacityAnimation() &&
320 !layer
->OpacityCanAnimateOnImplThread();
323 template <typename LayerType
>
324 static bool LayerShouldBeSkipped(LayerType
* layer
,
326 const TransformTree
& tree
) {
327 // Layers can be skipped if any of these conditions are met.
328 // - is not drawn due to it or one of its ancestors being hidden (or having
329 // no copy requests).
330 // - does not draw content.
332 // - has empty bounds
333 // - the layer is not double-sided, but its back face is visible.
335 // Some additional conditions need to be computed at a later point after the
336 // recursion is finished.
337 // - the intersection of render_surface content and layer clip_rect is empty
338 // - the visible_layer_rect is empty
340 // Note, if the layer should not have been drawn due to being fully
341 // transparent, we would have skipped the entire subtree and never made it
342 // into this function, so it is safe to omit this check here.
346 if (!layer
->DrawsContent() || layer
->bounds().IsEmpty())
349 LayerType
* backface_test_layer
= layer
;
350 if (layer
->use_parent_backface_visibility()) {
351 DCHECK(layer
->parent());
352 DCHECK(!layer
->parent()->use_parent_backface_visibility());
353 backface_test_layer
= layer
->parent();
356 // The layer should not be drawn if (1) it is not double-sided and (2) the
357 // back of the layer is known to be facing the screen.
358 if (!backface_test_layer
->double_sided() &&
359 TransformToScreenIsKnown(backface_test_layer
, tree
) &&
360 IsLayerBackFaceVisible(backface_test_layer
, tree
))
366 template <typename LayerType
>
367 void FindLayersThatNeedUpdates(
369 const TransformTree
& tree
,
370 bool subtree_is_visible_from_ancestor
,
371 typename
LayerType::LayerListType
* update_layer_list
,
372 std::vector
<LayerType
*>* visible_layer_list
) {
373 bool layer_is_drawn
=
374 layer
->HasCopyRequest() ||
375 (subtree_is_visible_from_ancestor
&& !layer
->hide_layer_and_subtree());
377 if (layer
->parent() && SubtreeShouldBeSkipped(layer
, layer_is_drawn
, tree
))
380 if (!LayerShouldBeSkipped(layer
, layer_is_drawn
, tree
)) {
381 visible_layer_list
->push_back(layer
);
382 update_layer_list
->push_back(layer
);
385 // Append mask layers to the update layer list. They don't have valid visible
386 // rects, so need to get added after the above calculation. Replica layers
387 // don't need to be updated.
388 if (LayerType
* mask_layer
= layer
->mask_layer())
389 update_layer_list
->push_back(mask_layer
);
390 if (LayerType
* replica_layer
= layer
->replica_layer()) {
391 if (LayerType
* mask_layer
= replica_layer
->mask_layer())
392 update_layer_list
->push_back(mask_layer
);
395 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
396 FindLayersThatNeedUpdates(layer
->child_at(i
), tree
, layer_is_drawn
,
397 update_layer_list
, visible_layer_list
);
403 void ComputeClips(ClipTree
* clip_tree
, const TransformTree
& transform_tree
) {
404 if (!clip_tree
->needs_update())
406 for (int i
= 0; i
< static_cast<int>(clip_tree
->size()); ++i
) {
407 ClipNode
* clip_node
= clip_tree
->Node(i
);
408 const TransformNode
* transform_node
=
409 transform_tree
.Node(clip_node
->data
.transform_id
);
411 // Only descendants of a real clipping layer (i.e., not 0) may have their
412 // clip adjusted due to intersecting with an ancestor clip.
413 const bool is_clipped
= clip_node
->parent_id
> 0;
415 DCHECK(!clip_node
->data
.inherit_parent_target_space_clip
);
416 clip_node
->data
.combined_clip
= clip_node
->data
.clip
;
417 if (clip_node
->id
> 0) {
418 gfx::Transform to_target
= transform_node
->data
.to_target
;
419 clip_node
->data
.clip_in_target_space
=
420 MathUtil::MapClippedRect(to_target
, clip_node
->data
.combined_clip
);
425 ClipNode
* parent_clip_node
= clip_tree
->parent(clip_node
);
426 const TransformNode
* parent_transform_node
=
427 transform_tree
.Node(parent_clip_node
->data
.transform_id
);
429 // Clips must be combined in target space. We cannot, for example, combine
430 // clips in the space of the child clip. The reason is non-affine
431 // transforms. Say we have the following tree T->A->B->C, and B clips C, but
432 // draw into target T. It may be the case that A applies a perspective
433 // transform, and B and C are at different z positions. When projected into
434 // target space, the relative sizes and positions of B and C can shift.
435 // Since it's the relationship in target space that matters, that's where we
436 // must combine clips.
437 gfx::Transform parent_to_target
;
438 gfx::Transform clip_to_target
;
440 gfx::Transform target_to_clip
;
441 gfx::Transform parent_to_transform_target
;
442 gfx::Transform transform_target_to_target
;
444 const bool target_is_root_surface
= clip_node
->data
.target_id
== 1;
445 // When the target is the root surface, we need to include the root
446 // transform by walking up to the root of the transform tree.
447 const int target_id
=
448 target_is_root_surface
? 0 : clip_node
->data
.target_id
;
451 // When render surface applies clip, we need the clip from the target's
452 // target space. But, as the combined clip is in parent clip's target
453 // space, we need to first transform it from parent's target space to
454 // target's target space.
455 if (clip_node
->data
.inherit_parent_target_space_clip
) {
456 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
457 parent_transform_node
->id
, transform_node
->data
.target_id
,
458 &parent_to_transform_target
);
459 success
&= transform_tree
.ComputeTransformWithSourceSublayerScale(
460 transform_node
->data
.target_id
, target_id
,
461 &transform_target_to_target
);
462 transform_target_to_target
.matrix().postScale(
463 transform_node
->data
.sublayer_scale
.x(),
464 transform_node
->data
.sublayer_scale
.y(), 1.0);
465 } else if (parent_transform_node
->data
.content_target_id
==
466 clip_node
->data
.target_id
) {
467 parent_to_target
= parent_transform_node
->data
.to_target
;
469 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
470 parent_transform_node
->id
, target_id
, &parent_to_target
);
473 if (transform_node
->data
.content_target_id
== clip_node
->data
.target_id
) {
474 clip_to_target
= transform_node
->data
.to_target
;
476 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
477 transform_node
->id
, target_id
, &clip_to_target
);
480 if (transform_node
->data
.content_target_id
== clip_node
->data
.target_id
&&
481 transform_node
->data
.ancestors_are_invertible
) {
482 target_to_clip
= transform_node
->data
.from_target
;
484 success
&= clip_to_target
.GetInverse(&target_to_clip
);
487 // If we can't compute a transform, it's because we had to use the inverse
488 // of a singular transform. We won't draw in this case, so there's no need
494 // In order to intersect with as small a rect as possible, we do a
495 // preliminary clip in target space so that when we project back, there's
496 // less likelihood of intersecting the view plane.
497 gfx::RectF inherited_clip_in_target_space
;
498 if (clip_node
->data
.inherit_parent_target_space_clip
) {
499 gfx::RectF combined_clip_in_transform_target_space
;
500 if (parent_transform_node
->id
> transform_node
->data
.target_id
)
501 combined_clip_in_transform_target_space
= MathUtil::MapClippedRect(
502 parent_to_transform_target
, parent_clip_node
->data
.combined_clip
);
504 combined_clip_in_transform_target_space
= MathUtil::ProjectClippedRect(
505 parent_to_transform_target
, parent_clip_node
->data
.combined_clip
);
506 inherited_clip_in_target_space
= MathUtil::ProjectClippedRect(
507 transform_target_to_target
, combined_clip_in_transform_target_space
);
508 } else if (parent_transform_node
->id
> target_id
) {
509 inherited_clip_in_target_space
= MathUtil::MapClippedRect(
510 parent_to_target
, parent_clip_node
->data
.combined_clip
);
512 inherited_clip_in_target_space
= MathUtil::ProjectClippedRect(
513 parent_to_target
, parent_clip_node
->data
.combined_clip
);
516 // When render surface inherits its parent target space clip, the layer
517 // that created the clip node doesn't apply any clip. So, we shouldn't clip
518 // using the clip value stored in the clip node.
519 gfx::RectF intersected_in_target_space
;
520 if (!clip_node
->data
.inherit_parent_target_space_clip
) {
521 gfx::RectF clip_in_target_space
=
522 MathUtil::MapClippedRect(clip_to_target
, clip_node
->data
.clip
);
523 intersected_in_target_space
= gfx::IntersectRects(
524 inherited_clip_in_target_space
, clip_in_target_space
);
525 if (!clip_node
->data
.requires_tight_clip_rect
)
526 clip_node
->data
.clip_in_target_space
= clip_in_target_space
;
528 clip_node
->data
.clip_in_target_space
= intersected_in_target_space
;
530 intersected_in_target_space
= inherited_clip_in_target_space
;
531 clip_node
->data
.clip_in_target_space
= intersected_in_target_space
;
534 clip_node
->data
.combined_clip
= MathUtil::ProjectClippedRect(
535 target_to_clip
, intersected_in_target_space
);
537 if (!clip_node
->data
.inherit_parent_target_space_clip
)
538 clip_node
->data
.combined_clip
.Intersect(clip_node
->data
.clip
);
540 clip_tree
->set_needs_update(false);
543 void ComputeTransforms(TransformTree
* transform_tree
) {
544 if (!transform_tree
->needs_update())
546 for (int i
= 1; i
< static_cast<int>(transform_tree
->size()); ++i
)
547 transform_tree
->UpdateTransforms(i
);
548 transform_tree
->set_needs_update(false);
551 void ComputeOpacities(EffectTree
* effect_tree
) {
552 if (!effect_tree
->needs_update())
554 for (int i
= 1; i
< static_cast<int>(effect_tree
->size()); ++i
)
555 effect_tree
->UpdateOpacities(i
);
556 effect_tree
->set_needs_update(false);
559 template <typename LayerType
>
560 void ComputeVisibleRectsUsingPropertyTreesInternal(
561 LayerType
* root_layer
,
562 PropertyTrees
* property_trees
,
563 typename
LayerType::LayerListType
* update_layer_list
) {
564 if (property_trees
->transform_tree
.needs_update())
565 property_trees
->clip_tree
.set_needs_update(true);
566 ComputeTransforms(&property_trees
->transform_tree
);
567 ComputeClips(&property_trees
->clip_tree
, property_trees
->transform_tree
);
568 ComputeOpacities(&property_trees
->effect_tree
);
570 const bool subtree_is_visible_from_ancestor
= true;
571 std::vector
<LayerType
*> visible_layer_list
;
572 FindLayersThatNeedUpdates(root_layer
, property_trees
->transform_tree
,
573 subtree_is_visible_from_ancestor
, update_layer_list
,
574 &visible_layer_list
);
575 CalculateVisibleRects
<LayerType
>(visible_layer_list
,
576 property_trees
->clip_tree
,
577 property_trees
->transform_tree
);
580 void BuildPropertyTreesAndComputeVisibleRects(
582 const Layer
* page_scale_layer
,
583 const Layer
* inner_viewport_scroll_layer
,
584 const Layer
* outer_viewport_scroll_layer
,
585 float page_scale_factor
,
586 float device_scale_factor
,
587 const gfx::Rect
& viewport
,
588 const gfx::Transform
& device_transform
,
589 PropertyTrees
* property_trees
,
590 LayerList
* update_layer_list
) {
591 PropertyTreeBuilder::BuildPropertyTrees(
592 root_layer
, page_scale_layer
, inner_viewport_scroll_layer
,
593 outer_viewport_scroll_layer
, page_scale_factor
, device_scale_factor
,
594 viewport
, device_transform
, property_trees
);
595 ComputeVisibleRectsUsingPropertyTrees(root_layer
, property_trees
,
599 void BuildPropertyTreesAndComputeVisibleRects(
600 LayerImpl
* root_layer
,
601 const LayerImpl
* page_scale_layer
,
602 const LayerImpl
* inner_viewport_scroll_layer
,
603 const LayerImpl
* outer_viewport_scroll_layer
,
604 float page_scale_factor
,
605 float device_scale_factor
,
606 const gfx::Rect
& viewport
,
607 const gfx::Transform
& device_transform
,
608 PropertyTrees
* property_trees
,
609 LayerImplList
* update_layer_list
) {
610 PropertyTreeBuilder::BuildPropertyTrees(
611 root_layer
, page_scale_layer
, inner_viewport_scroll_layer
,
612 outer_viewport_scroll_layer
, page_scale_factor
, device_scale_factor
,
613 viewport
, device_transform
, property_trees
);
614 ComputeVisibleRectsUsingPropertyTrees(root_layer
, property_trees
,
618 void ComputeVisibleRectsUsingPropertyTrees(Layer
* root_layer
,
619 PropertyTrees
* property_trees
,
620 LayerList
* update_layer_list
) {
621 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
,
625 void ComputeVisibleRectsUsingPropertyTrees(LayerImpl
* root_layer
,
626 PropertyTrees
* property_trees
,
627 LayerImplList
* update_layer_list
) {
628 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
,
632 template <typename LayerType
>
633 gfx::Transform
DrawTransformFromPropertyTreesInternal(
634 const LayerType
* layer
,
635 const TransformNode
* node
) {
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(
657 layer
, tree
.Node(layer
->transform_tree_index()));
660 gfx::Transform
DrawTransformFromPropertyTrees(const LayerImpl
* layer
,
661 const TransformTree
& tree
) {
662 return DrawTransformFromPropertyTreesInternal(
663 layer
, tree
.Node(layer
->transform_tree_index()));
666 gfx::Transform
SurfaceDrawTransform(const RenderSurfaceImpl
* render_surface
,
667 const TransformTree
& tree
) {
668 const TransformNode
* node
= tree
.Node(render_surface
->TransformTreeIndex());
669 gfx::Transform render_surface_transform
;
670 // The draw transform of root render surface is identity tranform.
672 return render_surface_transform
;
673 const TransformNode
* target_node
= tree
.Node(node
->data
.target_id
);
674 if (target_node
->id
== 1)
675 target_node
= tree
.Node(0);
676 tree
.ComputeTransformWithDestinationSublayerScale(node
->id
, target_node
->id
,
677 &render_surface_transform
);
678 if (node
->data
.sublayer_scale
.x() != 0.0 &&
679 node
->data
.sublayer_scale
.y() != 0.0)
680 render_surface_transform
.Scale(1.0 / node
->data
.sublayer_scale
.x(),
681 1.0 / node
->data
.sublayer_scale
.y());
682 return render_surface_transform
;
685 bool SurfaceIsClipped(const RenderSurfaceImpl
* render_surface
,
686 const ClipNode
* clip_node
) {
687 // If the render surface's owning layer doesn't form a clip node, it is not
689 if (render_surface
->OwningLayerId() != clip_node
->owner_id
)
691 return clip_node
->data
.render_surface_is_clipped
;
694 gfx::Rect
SurfaceClipRect(const RenderSurfaceImpl
* render_surface
,
695 const ClipNode
* parent_clip_node
,
699 return gfx::ToEnclosingRect(parent_clip_node
->data
.clip_in_target_space
);
702 gfx::Transform
SurfaceScreenSpaceTransform(
703 const RenderSurfaceImpl
* render_surface
,
704 const TransformTree
& tree
) {
705 const TransformNode
* node
= tree
.Node(render_surface
->TransformTreeIndex());
706 gfx::Transform screen_space_transform
;
707 // The screen space transform of root render surface is identity tranform.
709 return screen_space_transform
;
710 screen_space_transform
= node
->data
.to_screen
;
711 if (node
->data
.sublayer_scale
.x() != 0.0 &&
712 node
->data
.sublayer_scale
.y() != 0.0)
713 screen_space_transform
.Scale(1.0 / node
->data
.sublayer_scale
.x(),
714 1.0 / node
->data
.sublayer_scale
.y());
715 return screen_space_transform
;
718 template <typename LayerType
>
719 gfx::Transform
ScreenSpaceTransformFromPropertyTreesInternal(
721 const TransformNode
* node
) {
722 gfx::Transform
xform(1, 0, 0, 1, layer
->offset_to_transform_parent().x(),
723 layer
->offset_to_transform_parent().y());
724 gfx::Transform ssxform
= node
->data
.to_screen
;
725 xform
.ConcatTransform(ssxform
);
726 if (layer
->should_flatten_transform_from_property_tree())
731 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
733 const TransformTree
& tree
) {
734 return ScreenSpaceTransformFromPropertyTreesInternal(
735 layer
, tree
.Node(layer
->transform_tree_index()));
738 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
739 const LayerImpl
* layer
,
740 const TransformTree
& tree
) {
741 return ScreenSpaceTransformFromPropertyTreesInternal(
742 layer
, tree
.Node(layer
->transform_tree_index()));
745 float LayerDrawOpacity(const LayerImpl
* layer
, const EffectTree
& tree
) {
746 if (!layer
->render_target())
749 const EffectNode
* target_node
=
750 tree
.Node(layer
->render_target()->effect_tree_index());
751 const EffectNode
* node
= tree
.Node(layer
->effect_tree_index());
752 if (node
== target_node
)
755 float draw_opacity
= 1.f
;
756 while (node
!= target_node
) {
757 draw_opacity
*= node
->data
.opacity
;
758 node
= tree
.parent(node
);
763 float SurfaceDrawOpacity(RenderSurfaceImpl
* render_surface
,
764 const EffectTree
& tree
) {
765 const EffectNode
* node
= tree
.Node(render_surface
->EffectTreeIndex());
766 float target_opacity_tree_index
= render_surface
->TargetEffectTreeIndex();
767 if (target_opacity_tree_index
< 0)
768 return node
->data
.screen_space_opacity
;
769 const EffectNode
* target_node
= tree
.Node(target_opacity_tree_index
);
770 float draw_opacity
= 1.f
;
771 while (node
!= target_node
) {
772 draw_opacity
*= node
->data
.opacity
;
773 node
= tree
.parent(node
);
778 bool LayerCanUseLcdText(const LayerImpl
* layer
,
779 bool layers_always_allowed_lcd_text
,
780 bool can_use_lcd_text
,
781 const TransformNode
* transform_node
,
782 const EffectNode
* effect_node
) {
783 if (layers_always_allowed_lcd_text
)
785 if (!can_use_lcd_text
)
787 if (!layer
->contents_opaque())
790 if (effect_node
->data
.screen_space_opacity
!= 1.f
)
792 if (!transform_node
->data
.node_and_ancestors_have_only_integer_translation
)
794 if (static_cast<int>(layer
->offset_to_transform_parent().x()) !=
795 layer
->offset_to_transform_parent().x())
797 if (static_cast<int>(layer
->offset_to_transform_parent().y()) !=
798 layer
->offset_to_transform_parent().y())
803 gfx::Rect
LayerDrawableContentRect(
804 const LayerImpl
* layer
,
805 const gfx::Rect
& layer_bounds_in_target_space
,
806 const gfx::Rect
& clip_rect
) {
807 if (layer
->is_clipped())
808 return IntersectRects(layer_bounds_in_target_space
, clip_rect
);
810 return layer_bounds_in_target_space
;
813 gfx::Transform
ReplicaToSurfaceTransform(
814 const RenderSurfaceImpl
* render_surface
,
815 const TransformTree
& tree
) {
816 gfx::Transform replica_to_surface
;
817 if (!render_surface
->HasReplica())
818 return replica_to_surface
;
819 const LayerImpl
* replica_layer
= render_surface
->ReplicaLayer();
820 const TransformNode
* surface_transform_node
=
821 tree
.Node(render_surface
->TransformTreeIndex());
822 replica_to_surface
.Scale(surface_transform_node
->data
.sublayer_scale
.x(),
823 surface_transform_node
->data
.sublayer_scale
.y());
824 replica_to_surface
.Translate(replica_layer
->offset_to_transform_parent().x(),
825 replica_layer
->offset_to_transform_parent().y());
826 gfx::Transform replica_transform_node_to_surface
;
827 tree
.ComputeTransform(replica_layer
->transform_tree_index(),
828 render_surface
->TransformTreeIndex(),
829 &replica_transform_node_to_surface
);
830 replica_to_surface
.PreconcatTransform(replica_transform_node_to_surface
);
831 if (surface_transform_node
->data
.sublayer_scale
.x() != 0 &&
832 surface_transform_node
->data
.sublayer_scale
.y() != 0) {
833 replica_to_surface
.Scale(
834 1.0 / surface_transform_node
->data
.sublayer_scale
.x(),
835 1.0 / surface_transform_node
->data
.sublayer_scale
.y());
837 return replica_to_surface
;
840 gfx::Rect
LayerClipRect(const LayerImpl
* layer
,
841 const gfx::Rect
& layer_bounds_in_target_space
) {
842 if (layer
->is_clipped())
843 return layer
->clip_rect_in_target_space_from_property_trees();
845 return layer_bounds_in_target_space
;
848 void ComputeLayerDrawPropertiesUsingPropertyTrees(
849 const LayerImpl
* layer
,
850 const PropertyTrees
* property_trees
,
851 bool layers_always_allowed_lcd_text
,
852 bool can_use_lcd_text
,
853 DrawProperties
* draw_properties
) {
854 draw_properties
->visible_layer_rect
=
855 layer
->visible_rect_from_property_trees();
857 const TransformNode
* transform_node
=
858 property_trees
->transform_tree
.Node(layer
->transform_tree_index());
859 const EffectNode
* effect_node
=
860 property_trees
->effect_tree
.Node(layer
->effect_tree_index());
862 draw_properties
->target_space_transform
=
863 DrawTransformFromPropertyTreesInternal(layer
, transform_node
);
864 draw_properties
->screen_space_transform
=
865 ScreenSpaceTransformFromPropertyTreesInternal(layer
, transform_node
);
866 draw_properties
->screen_space_transform_is_animating
=
867 transform_node
->data
.to_screen_is_animated
;
868 if (layer
->layer_tree_impl()
870 .layer_transforms_should_scale_layer_contents
) {
871 draw_properties
->maximum_animation_contents_scale
=
872 transform_node
->data
.combined_maximum_animation_target_scale
;
873 draw_properties
->starting_animation_contents_scale
=
874 transform_node
->data
.combined_starting_animation_scale
;
876 draw_properties
->maximum_animation_contents_scale
= 0.f
;
877 draw_properties
->starting_animation_contents_scale
= 0.f
;
880 draw_properties
->opacity
=
881 LayerDrawOpacity(layer
, property_trees
->effect_tree
);
882 draw_properties
->can_use_lcd_text
=
883 LayerCanUseLcdText(layer
, layers_always_allowed_lcd_text
,
884 can_use_lcd_text
, transform_node
, effect_node
);
886 gfx::Rect bounds_in_target_space
= MathUtil::MapEnclosingClippedRect(
887 draw_properties
->target_space_transform
, gfx::Rect(layer
->bounds()));
888 draw_properties
->clip_rect
= LayerClipRect(layer
, bounds_in_target_space
);
889 draw_properties
->drawable_content_rect
= LayerDrawableContentRect(
890 layer
, bounds_in_target_space
, draw_properties
->clip_rect
);
893 void ComputeSurfaceDrawPropertiesUsingPropertyTrees(
894 RenderSurfaceImpl
* render_surface
,
895 const PropertyTrees
* property_trees
,
896 RenderSurfaceDrawProperties
* draw_properties
) {
897 const ClipNode
* clip_node
=
898 property_trees
->clip_tree
.Node(render_surface
->ClipTreeIndex());
900 draw_properties
->is_clipped
= SurfaceIsClipped(render_surface
, clip_node
);
901 draw_properties
->draw_opacity
=
902 SurfaceDrawOpacity(render_surface
, property_trees
->effect_tree
);
903 draw_properties
->draw_transform
=
904 SurfaceDrawTransform(render_surface
, property_trees
->transform_tree
);
905 draw_properties
->screen_space_transform
= SurfaceScreenSpaceTransform(
906 render_surface
, property_trees
->transform_tree
);
908 if (render_surface
->HasReplica()) {
909 gfx::Transform replica_to_surface
= ReplicaToSurfaceTransform(
910 render_surface
, property_trees
->transform_tree
);
911 draw_properties
->replica_draw_transform
=
912 draw_properties
->draw_transform
* replica_to_surface
;
913 draw_properties
->replica_screen_space_transform
=
914 draw_properties
->screen_space_transform
* replica_to_surface
;
916 draw_properties
->replica_draw_transform
.MakeIdentity();
917 draw_properties
->replica_screen_space_transform
.MakeIdentity();
920 draw_properties
->clip_rect
= SurfaceClipRect(
921 render_surface
, property_trees
->clip_tree
.parent(clip_node
),
922 draw_properties
->is_clipped
);