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 if (!combined_clip_rect_in_target_space
.IsEmpty()) {
93 layer
->set_clip_rect_in_target_space_from_property_trees(
94 combined_clip_rect_in_target_space
);
96 layer
->set_clip_rect_in_target_space_from_property_trees(gfx::Rect());
99 if (!clip_rect_in_target_space
.IsEmpty()) {
100 layer
->set_clip_rect_in_target_space_from_property_trees(
101 clip_rect_in_target_space
);
103 layer
->set_clip_rect_in_target_space_from_property_trees(gfx::Rect());
107 gfx::Rect layer_content_rect
= gfx::Rect(layer_bounds
);
108 gfx::Rect layer_content_bounds_in_target_space
=
109 MathUtil::MapEnclosingClippedRect(content_to_target
,
111 combined_clip_rect_in_target_space
.Intersect(
112 layer_content_bounds_in_target_space
);
113 if (combined_clip_rect_in_target_space
.IsEmpty()) {
114 layer
->set_visible_rect_from_property_trees(gfx::Rect());
118 // If the layer is fully contained within the clip, treat it as fully
119 // visible. Since clip_rect_in_target_space has already been intersected
120 // with layer_content_bounds_in_target_space, the layer is fully contained
121 // within the clip iff these rects are equal.
122 if (combined_clip_rect_in_target_space
==
123 layer_content_bounds_in_target_space
) {
124 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
128 gfx::Transform target_to_content
;
129 gfx::Transform target_to_layer
;
131 if (transform_node
->data
.ancestors_are_invertible
) {
132 target_to_layer
= transform_node
->data
.from_target
;
135 success
= transform_tree
.ComputeTransformWithSourceSublayerScale(
136 target_node
->id
, transform_node
->id
, &target_to_layer
);
140 // An animated singular transform may become non-singular during the
141 // animation, so we still need to compute a visible rect. In this
142 // situation, we treat the entire layer as visible.
143 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
147 target_to_content
.Translate(-layer
->offset_to_transform_parent().x(),
148 -layer
->offset_to_transform_parent().y());
149 target_to_content
.PreconcatTransform(target_to_layer
);
151 gfx::Rect visible_rect
= MathUtil::ProjectEnclosingClippedRect(
152 target_to_content
, combined_clip_rect_in_target_space
);
154 visible_rect
.Intersect(gfx::Rect(layer_bounds
));
156 layer
->set_visible_rect_from_property_trees(visible_rect
);
158 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
159 layer
->set_clip_rect_in_target_space_from_property_trees(
160 gfx::Rect(layer_bounds
));
165 template <typename LayerType
>
166 static bool IsRootLayerOfNewRenderingContext(LayerType
* layer
) {
168 return !layer
->parent()->Is3dSorted() && layer
->Is3dSorted();
169 return layer
->Is3dSorted();
172 template <typename LayerType
>
173 static inline bool LayerIsInExisting3DRenderingContext(LayerType
* layer
) {
174 return layer
->Is3dSorted() && layer
->parent() &&
175 layer
->parent()->Is3dSorted() &&
176 layer
->parent()->sorting_context_id() == layer
->sorting_context_id();
179 template <typename LayerType
>
180 static bool TransformToScreenIsKnown(LayerType
* layer
,
181 const TransformTree
& tree
) {
182 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
183 return !node
->data
.to_screen_is_animated
;
186 template <typename LayerType
>
187 static bool HasSingularTransform(LayerType
* layer
, const TransformTree
& tree
) {
188 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
189 return !node
->data
.is_invertible
|| !node
->data
.ancestors_are_invertible
;
192 template <typename LayerType
>
193 static bool IsLayerBackFaceVisible(LayerType
* layer
,
194 const TransformTree
& tree
) {
195 // The current W3C spec on CSS transforms says that backface visibility should
196 // be determined differently depending on whether the layer is in a "3d
197 // rendering context" or not. For Chromium code, we can determine whether we
198 // are in a 3d rendering context by checking if the parent preserves 3d.
200 if (LayerIsInExisting3DRenderingContext(layer
))
201 return DrawTransformFromPropertyTrees(layer
, tree
).IsBackFaceVisible();
203 // In this case, either the layer establishes a new 3d rendering context, or
204 // is not in a 3d rendering context at all.
205 return layer
->transform().IsBackFaceVisible();
208 template <typename LayerType
>
209 static bool IsSurfaceBackFaceVisible(LayerType
* layer
,
210 const TransformTree
& tree
) {
211 if (LayerIsInExisting3DRenderingContext(layer
)) {
212 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
213 // Draw transform as a contributing render surface.
214 // TODO(enne): we shouldn't walk the tree during a tree walk.
215 gfx::Transform surface_draw_transform
;
216 tree
.ComputeTransform(node
->id
, node
->data
.target_id
,
217 &surface_draw_transform
);
218 return surface_draw_transform
.IsBackFaceVisible();
221 if (IsRootLayerOfNewRenderingContext(layer
))
222 return layer
->transform().IsBackFaceVisible();
224 // If the render_surface is not part of a new or existing rendering context,
225 // then the layers that contribute to this surface will decide back-face
226 // visibility for themselves.
230 template <typename LayerType
>
231 static bool IsAnimatingTransformToScreen(LayerType
* layer
,
232 const TransformTree
& tree
) {
233 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
234 return node
->data
.to_screen_is_animated
;
237 static inline bool TransformToScreenIsKnown(Layer
* layer
,
238 const TransformTree
& tree
) {
239 return !IsAnimatingTransformToScreen(layer
, tree
);
242 static inline bool TransformToScreenIsKnown(LayerImpl
* layer
,
243 const TransformTree
& tree
) {
247 template <typename LayerType
>
248 static bool HasInvertibleOrAnimatedTransform(LayerType
* layer
) {
249 return layer
->transform_is_invertible() ||
250 layer
->HasPotentiallyRunningTransformAnimation();
253 static inline bool SubtreeShouldBeSkipped(LayerImpl
* layer
,
255 const TransformTree
& tree
) {
256 // If the layer transform is not invertible, it should not be drawn.
257 // TODO(ajuma): Correctly process subtrees with singular transform for the
258 // case where we may animate to a non-singular transform and wish to
260 if (!HasInvertibleOrAnimatedTransform(layer
))
263 // When we need to do a readback/copy of a layer's output, we can not skip
264 // it or any of its ancestors.
265 if (layer
->draw_properties().layer_or_descendant_has_copy_request
)
268 // If the layer is not drawn, then skip it and its subtree.
272 if (layer
->render_surface() && !layer
->double_sided() &&
273 IsSurfaceBackFaceVisible(layer
, tree
))
276 // If layer is on the pending tree and opacity is being animated then
277 // this subtree can't be skipped as we need to create, prioritize and
278 // include tiles for this layer when deciding if tree can be activated.
279 if (layer
->layer_tree_impl()->IsPendingTree() &&
280 layer
->HasPotentiallyRunningOpacityAnimation())
283 // If layer has a background filter, don't skip the layer, even it the
285 if (!layer
->background_filters().IsEmpty())
288 // The opacity of a layer always applies to its children (either implicitly
289 // via a render surface or explicitly if the parent preserves 3D), so the
290 // entire subtree can be skipped if this layer is fully transparent.
291 return !layer
->opacity();
294 static inline bool SubtreeShouldBeSkipped(Layer
* layer
,
296 const TransformTree
& tree
) {
297 // If the layer transform is not invertible, it should not be drawn.
298 if (!layer
->transform_is_invertible() &&
299 !layer
->HasPotentiallyRunningTransformAnimation())
302 // When we need to do a readback/copy of a layer's output, we can not skip
303 // it or any of its ancestors.
304 if (layer
->num_layer_or_descendants_with_copy_request() > 0)
307 // If the layer is not drawn, then skip it and its subtree.
311 if (layer
->has_render_surface() && !layer
->double_sided() &&
312 !layer
->HasPotentiallyRunningTransformAnimation() &&
313 IsSurfaceBackFaceVisible(layer
, tree
))
316 // If layer has a background filter, don't skip the layer, even it the
318 if (!layer
->background_filters().IsEmpty())
321 // If the opacity is being animated then the opacity on the main thread is
322 // unreliable (since the impl thread may be using a different opacity), so it
323 // should not be trusted.
324 // In particular, it should not cause the subtree to be skipped.
325 // Similarly, for layers that might animate opacity using an impl-only
326 // animation, their subtree should also not be skipped.
327 return !layer
->opacity() && !layer
->HasPotentiallyRunningOpacityAnimation() &&
328 !layer
->OpacityCanAnimateOnImplThread();
331 template <typename LayerType
>
332 static bool LayerShouldBeSkipped(LayerType
* layer
,
334 const TransformTree
& tree
) {
335 // Layers can be skipped if any of these conditions are met.
336 // - is not drawn due to it or one of its ancestors being hidden (or having
337 // no copy requests).
338 // - does not draw content.
340 // - has empty bounds
341 // - the layer is not double-sided, but its back face is visible.
343 // Some additional conditions need to be computed at a later point after the
344 // recursion is finished.
345 // - the intersection of render_surface content and layer clip_rect is empty
346 // - the visible_layer_rect is empty
348 // Note, if the layer should not have been drawn due to being fully
349 // transparent, we would have skipped the entire subtree and never made it
350 // into this function, so it is safe to omit this check here.
354 if (!layer
->DrawsContent() || layer
->bounds().IsEmpty())
357 LayerType
* backface_test_layer
= layer
;
358 if (layer
->use_parent_backface_visibility()) {
359 DCHECK(layer
->parent());
360 DCHECK(!layer
->parent()->use_parent_backface_visibility());
361 backface_test_layer
= layer
->parent();
364 // The layer should not be drawn if (1) it is not double-sided and (2) the
365 // back of the layer is known to be facing the screen.
366 if (!backface_test_layer
->double_sided() &&
367 TransformToScreenIsKnown(backface_test_layer
, tree
) &&
368 IsLayerBackFaceVisible(backface_test_layer
, tree
))
374 template <typename LayerType
>
375 void FindLayersThatNeedUpdates(
377 const TransformTree
& tree
,
378 bool subtree_is_visible_from_ancestor
,
379 typename
LayerType::LayerListType
* update_layer_list
,
380 std::vector
<LayerType
*>* visible_layer_list
) {
381 bool layer_is_drawn
=
382 layer
->HasCopyRequest() ||
383 (subtree_is_visible_from_ancestor
&& !layer
->hide_layer_and_subtree());
385 if (layer
->parent() && SubtreeShouldBeSkipped(layer
, layer_is_drawn
, tree
))
388 if (!LayerShouldBeSkipped(layer
, layer_is_drawn
, tree
)) {
389 visible_layer_list
->push_back(layer
);
390 update_layer_list
->push_back(layer
);
393 // Append mask layers to the update layer list. They don't have valid visible
394 // rects, so need to get added after the above calculation. Replica layers
395 // don't need to be updated.
396 if (LayerType
* mask_layer
= layer
->mask_layer())
397 update_layer_list
->push_back(mask_layer
);
398 if (LayerType
* replica_layer
= layer
->replica_layer()) {
399 if (LayerType
* mask_layer
= replica_layer
->mask_layer())
400 update_layer_list
->push_back(mask_layer
);
403 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
404 FindLayersThatNeedUpdates(layer
->child_at(i
), tree
, layer_is_drawn
,
405 update_layer_list
, visible_layer_list
);
411 void ComputeClips(ClipTree
* clip_tree
, const TransformTree
& transform_tree
) {
412 if (!clip_tree
->needs_update())
414 for (int i
= 0; i
< static_cast<int>(clip_tree
->size()); ++i
) {
415 ClipNode
* clip_node
= clip_tree
->Node(i
);
416 const TransformNode
* transform_node
=
417 transform_tree
.Node(clip_node
->data
.transform_id
);
419 // Only descendants of a real clipping layer (i.e., not 0) may have their
420 // clip adjusted due to intersecting with an ancestor clip.
421 const bool is_clipped
= clip_node
->parent_id
> 0;
423 DCHECK(!clip_node
->data
.inherit_parent_target_space_clip
);
424 clip_node
->data
.combined_clip
= clip_node
->data
.clip
;
425 if (clip_node
->id
> 0) {
426 gfx::Transform to_target
= transform_node
->data
.to_target
;
427 clip_node
->data
.clip_in_target_space
=
428 MathUtil::MapClippedRect(to_target
, clip_node
->data
.combined_clip
);
433 ClipNode
* parent_clip_node
= clip_tree
->parent(clip_node
);
434 const TransformNode
* parent_transform_node
=
435 transform_tree
.Node(parent_clip_node
->data
.transform_id
);
437 // Clips must be combined in target space. We cannot, for example, combine
438 // clips in the space of the child clip. The reason is non-affine
439 // transforms. Say we have the following tree T->A->B->C, and B clips C, but
440 // draw into target T. It may be the case that A applies a perspective
441 // transform, and B and C are at different z positions. When projected into
442 // target space, the relative sizes and positions of B and C can shift.
443 // Since it's the relationship in target space that matters, that's where we
444 // must combine clips.
445 gfx::Transform parent_to_target
;
446 gfx::Transform clip_to_target
;
448 gfx::Transform target_to_clip
;
449 gfx::Transform parent_to_transform_target
;
450 gfx::Transform transform_target_to_target
;
452 const bool target_is_root_surface
= clip_node
->data
.target_id
== 1;
453 // When the target is the root surface, we need to include the root
454 // transform by walking up to the root of the transform tree.
455 const int target_id
=
456 target_is_root_surface
? 0 : clip_node
->data
.target_id
;
459 // When render surface applies clip, we need the clip from the target's
460 // target space. But, as the combined clip is in parent clip's target
461 // space, we need to first transform it from parent's target space to
462 // target's target space.
463 if (clip_node
->data
.inherit_parent_target_space_clip
) {
464 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
465 parent_transform_node
->id
, transform_node
->data
.target_id
,
466 &parent_to_transform_target
);
467 success
&= transform_tree
.ComputeTransformWithSourceSublayerScale(
468 transform_node
->data
.target_id
, target_id
,
469 &transform_target_to_target
);
470 transform_target_to_target
.matrix().postScale(
471 transform_node
->data
.sublayer_scale
.x(),
472 transform_node
->data
.sublayer_scale
.y(), 1.0);
473 } else if (parent_transform_node
->data
.content_target_id
==
474 clip_node
->data
.target_id
) {
475 parent_to_target
= parent_transform_node
->data
.to_target
;
477 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
478 parent_transform_node
->id
, target_id
, &parent_to_target
);
481 if (transform_node
->data
.content_target_id
== clip_node
->data
.target_id
) {
482 clip_to_target
= transform_node
->data
.to_target
;
484 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
485 transform_node
->id
, target_id
, &clip_to_target
);
488 if (transform_node
->data
.content_target_id
== clip_node
->data
.target_id
&&
489 transform_node
->data
.ancestors_are_invertible
) {
490 target_to_clip
= transform_node
->data
.from_target
;
492 success
&= clip_to_target
.GetInverse(&target_to_clip
);
495 // If we can't compute a transform, it's because we had to use the inverse
496 // of a singular transform. We won't draw in this case, so there's no need
502 // In order to intersect with as small a rect as possible, we do a
503 // preliminary clip in target space so that when we project back, there's
504 // less likelihood of intersecting the view plane.
505 gfx::RectF inherited_clip_in_target_space
;
506 if (clip_node
->data
.inherit_parent_target_space_clip
) {
507 gfx::RectF combined_clip_in_transform_target_space
;
508 if (parent_transform_node
->id
> transform_node
->data
.target_id
)
509 combined_clip_in_transform_target_space
= MathUtil::MapClippedRect(
510 parent_to_transform_target
, parent_clip_node
->data
.combined_clip
);
512 combined_clip_in_transform_target_space
= MathUtil::ProjectClippedRect(
513 parent_to_transform_target
, parent_clip_node
->data
.combined_clip
);
514 inherited_clip_in_target_space
= MathUtil::ProjectClippedRect(
515 transform_target_to_target
, combined_clip_in_transform_target_space
);
516 } else if (parent_transform_node
->id
> target_id
) {
517 inherited_clip_in_target_space
= MathUtil::MapClippedRect(
518 parent_to_target
, parent_clip_node
->data
.combined_clip
);
520 inherited_clip_in_target_space
= MathUtil::ProjectClippedRect(
521 parent_to_target
, parent_clip_node
->data
.combined_clip
);
524 // When render surface inherits its parent target space clip, the layer
525 // that created the clip node doesn't apply any clip. So, we shouldn't clip
526 // using the clip value stored in the clip node.
527 gfx::RectF intersected_in_target_space
;
528 if (!clip_node
->data
.inherit_parent_target_space_clip
) {
529 gfx::RectF clip_in_target_space
=
530 MathUtil::MapClippedRect(clip_to_target
, clip_node
->data
.clip
);
531 intersected_in_target_space
= gfx::IntersectRects(
532 inherited_clip_in_target_space
, clip_in_target_space
);
533 if (!clip_node
->data
.requires_tight_clip_rect
)
534 clip_node
->data
.clip_in_target_space
= clip_in_target_space
;
536 clip_node
->data
.clip_in_target_space
= intersected_in_target_space
;
538 intersected_in_target_space
= inherited_clip_in_target_space
;
539 clip_node
->data
.clip_in_target_space
= intersected_in_target_space
;
542 clip_node
->data
.combined_clip
= MathUtil::ProjectClippedRect(
543 target_to_clip
, intersected_in_target_space
);
545 if (!clip_node
->data
.inherit_parent_target_space_clip
)
546 clip_node
->data
.combined_clip
.Intersect(clip_node
->data
.clip
);
548 clip_tree
->set_needs_update(false);
551 void ComputeTransforms(TransformTree
* transform_tree
) {
552 if (!transform_tree
->needs_update())
554 for (int i
= 1; i
< static_cast<int>(transform_tree
->size()); ++i
)
555 transform_tree
->UpdateTransforms(i
);
556 transform_tree
->set_needs_update(false);
559 void ComputeOpacities(EffectTree
* effect_tree
) {
560 if (!effect_tree
->needs_update())
562 for (int i
= 1; i
< static_cast<int>(effect_tree
->size()); ++i
)
563 effect_tree
->UpdateOpacities(i
);
564 effect_tree
->set_needs_update(false);
567 template <typename LayerType
>
568 void ComputeVisibleRectsUsingPropertyTreesInternal(
569 LayerType
* root_layer
,
570 PropertyTrees
* property_trees
,
571 typename
LayerType::LayerListType
* update_layer_list
) {
572 if (property_trees
->transform_tree
.needs_update())
573 property_trees
->clip_tree
.set_needs_update(true);
574 ComputeTransforms(&property_trees
->transform_tree
);
575 ComputeClips(&property_trees
->clip_tree
, property_trees
->transform_tree
);
576 ComputeOpacities(&property_trees
->effect_tree
);
578 const bool subtree_is_visible_from_ancestor
= true;
579 std::vector
<LayerType
*> visible_layer_list
;
580 FindLayersThatNeedUpdates(root_layer
, property_trees
->transform_tree
,
581 subtree_is_visible_from_ancestor
, update_layer_list
,
582 &visible_layer_list
);
583 CalculateVisibleRects
<LayerType
>(visible_layer_list
,
584 property_trees
->clip_tree
,
585 property_trees
->transform_tree
);
588 void BuildPropertyTreesAndComputeVisibleRects(
590 const Layer
* page_scale_layer
,
591 const Layer
* inner_viewport_scroll_layer
,
592 const Layer
* outer_viewport_scroll_layer
,
593 float page_scale_factor
,
594 float device_scale_factor
,
595 const gfx::Rect
& viewport
,
596 const gfx::Transform
& device_transform
,
597 PropertyTrees
* property_trees
,
598 LayerList
* update_layer_list
) {
599 PropertyTreeBuilder::BuildPropertyTrees(
600 root_layer
, page_scale_layer
, inner_viewport_scroll_layer
,
601 outer_viewport_scroll_layer
, page_scale_factor
, device_scale_factor
,
602 viewport
, device_transform
, property_trees
);
603 ComputeVisibleRectsUsingPropertyTrees(root_layer
, property_trees
,
607 void BuildPropertyTreesAndComputeVisibleRects(
608 LayerImpl
* root_layer
,
609 const LayerImpl
* page_scale_layer
,
610 const LayerImpl
* inner_viewport_scroll_layer
,
611 const LayerImpl
* outer_viewport_scroll_layer
,
612 float page_scale_factor
,
613 float device_scale_factor
,
614 const gfx::Rect
& viewport
,
615 const gfx::Transform
& device_transform
,
616 PropertyTrees
* property_trees
,
617 LayerImplList
* update_layer_list
) {
618 PropertyTreeBuilder::BuildPropertyTrees(
619 root_layer
, page_scale_layer
, inner_viewport_scroll_layer
,
620 outer_viewport_scroll_layer
, page_scale_factor
, device_scale_factor
,
621 viewport
, device_transform
, property_trees
);
622 ComputeVisibleRectsUsingPropertyTrees(root_layer
, property_trees
,
626 void ComputeVisibleRectsUsingPropertyTrees(Layer
* root_layer
,
627 PropertyTrees
* property_trees
,
628 LayerList
* update_layer_list
) {
629 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
,
633 void ComputeVisibleRectsUsingPropertyTrees(LayerImpl
* root_layer
,
634 PropertyTrees
* property_trees
,
635 LayerImplList
* update_layer_list
) {
636 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
,
640 template <typename LayerType
>
641 gfx::Transform
DrawTransformFromPropertyTreesInternal(
642 const LayerType
* layer
,
643 const TransformNode
* node
) {
644 gfx::Transform xform
;
645 const bool owns_non_root_surface
=
646 layer
->parent() && layer
->has_render_surface();
647 if (!owns_non_root_surface
) {
648 // If you're not the root, or you don't own a surface, you need to apply
649 // your local offset.
650 xform
= node
->data
.to_target
;
651 if (layer
->should_flatten_transform_from_property_tree())
653 xform
.Translate(layer
->offset_to_transform_parent().x(),
654 layer
->offset_to_transform_parent().y());
656 // Surfaces need to apply their sublayer scale.
657 xform
.Scale(node
->data
.sublayer_scale
.x(), node
->data
.sublayer_scale
.y());
662 gfx::Transform
DrawTransformFromPropertyTrees(const Layer
* layer
,
663 const TransformTree
& tree
) {
664 return DrawTransformFromPropertyTreesInternal(
665 layer
, tree
.Node(layer
->transform_tree_index()));
668 gfx::Transform
DrawTransformFromPropertyTrees(const LayerImpl
* layer
,
669 const TransformTree
& tree
) {
670 return DrawTransformFromPropertyTreesInternal(
671 layer
, tree
.Node(layer
->transform_tree_index()));
674 gfx::Transform
SurfaceDrawTransform(const RenderSurfaceImpl
* render_surface
,
675 const TransformTree
& tree
) {
676 const TransformNode
* node
= tree
.Node(render_surface
->TransformTreeIndex());
677 gfx::Transform render_surface_transform
;
678 // The draw transform of root render surface is identity tranform.
680 return render_surface_transform
;
681 const TransformNode
* target_node
= tree
.Node(node
->data
.target_id
);
682 if (target_node
->id
== 1)
683 target_node
= tree
.Node(0);
684 tree
.ComputeTransformWithDestinationSublayerScale(node
->id
, target_node
->id
,
685 &render_surface_transform
);
686 if (node
->data
.sublayer_scale
.x() != 0.0 &&
687 node
->data
.sublayer_scale
.y() != 0.0)
688 render_surface_transform
.Scale(1.0 / node
->data
.sublayer_scale
.x(),
689 1.0 / node
->data
.sublayer_scale
.y());
690 return render_surface_transform
;
693 bool SurfaceIsClipped(const RenderSurfaceImpl
* render_surface
,
694 const ClipNode
* clip_node
) {
695 // If the render surface's owning layer doesn't form a clip node, it is not
697 if (render_surface
->OwningLayerId() != clip_node
->owner_id
)
699 return clip_node
->data
.render_surface_is_clipped
;
702 gfx::Rect
SurfaceClipRect(const RenderSurfaceImpl
* render_surface
,
703 const ClipNode
* parent_clip_node
,
707 return gfx::ToEnclosingRect(parent_clip_node
->data
.clip_in_target_space
);
710 gfx::Transform
SurfaceScreenSpaceTransform(
711 const RenderSurfaceImpl
* render_surface
,
712 const TransformTree
& tree
) {
713 const TransformNode
* node
= tree
.Node(render_surface
->TransformTreeIndex());
714 gfx::Transform screen_space_transform
;
715 // The screen space transform of root render surface is identity tranform.
717 return screen_space_transform
;
718 screen_space_transform
= node
->data
.to_screen
;
719 if (node
->data
.sublayer_scale
.x() != 0.0 &&
720 node
->data
.sublayer_scale
.y() != 0.0)
721 screen_space_transform
.Scale(1.0 / node
->data
.sublayer_scale
.x(),
722 1.0 / node
->data
.sublayer_scale
.y());
723 return screen_space_transform
;
726 template <typename LayerType
>
727 gfx::Transform
ScreenSpaceTransformFromPropertyTreesInternal(
729 const TransformNode
* node
) {
730 gfx::Transform
xform(1, 0, 0, 1, layer
->offset_to_transform_parent().x(),
731 layer
->offset_to_transform_parent().y());
732 gfx::Transform ssxform
= node
->data
.to_screen
;
733 xform
.ConcatTransform(ssxform
);
734 if (layer
->should_flatten_transform_from_property_tree())
739 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
741 const TransformTree
& tree
) {
742 return ScreenSpaceTransformFromPropertyTreesInternal(
743 layer
, tree
.Node(layer
->transform_tree_index()));
746 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
747 const LayerImpl
* layer
,
748 const TransformTree
& tree
) {
749 return ScreenSpaceTransformFromPropertyTreesInternal(
750 layer
, tree
.Node(layer
->transform_tree_index()));
753 float LayerDrawOpacity(const LayerImpl
* layer
, const EffectTree
& tree
) {
754 if (!layer
->render_target())
757 const EffectNode
* target_node
=
758 tree
.Node(layer
->render_target()->effect_tree_index());
759 const EffectNode
* node
= tree
.Node(layer
->effect_tree_index());
760 if (node
== target_node
)
763 float draw_opacity
= 1.f
;
764 while (node
!= target_node
) {
765 draw_opacity
*= node
->data
.opacity
;
766 node
= tree
.parent(node
);
771 float SurfaceDrawOpacity(RenderSurfaceImpl
* render_surface
,
772 const EffectTree
& tree
) {
773 const EffectNode
* node
= tree
.Node(render_surface
->EffectTreeIndex());
774 float target_opacity_tree_index
= render_surface
->TargetEffectTreeIndex();
775 if (target_opacity_tree_index
< 0)
776 return node
->data
.screen_space_opacity
;
777 const EffectNode
* target_node
= tree
.Node(target_opacity_tree_index
);
778 float draw_opacity
= 1.f
;
779 while (node
!= target_node
) {
780 draw_opacity
*= node
->data
.opacity
;
781 node
= tree
.parent(node
);
786 bool LayerCanUseLcdText(const LayerImpl
* layer
,
787 bool layers_always_allowed_lcd_text
,
788 bool can_use_lcd_text
,
789 const TransformNode
* transform_node
,
790 const EffectNode
* effect_node
) {
791 if (layers_always_allowed_lcd_text
)
793 if (!can_use_lcd_text
)
795 if (!layer
->contents_opaque())
798 if (effect_node
->data
.screen_space_opacity
!= 1.f
)
800 if (!transform_node
->data
.node_and_ancestors_have_only_integer_translation
)
802 if (static_cast<int>(layer
->offset_to_transform_parent().x()) !=
803 layer
->offset_to_transform_parent().x())
805 if (static_cast<int>(layer
->offset_to_transform_parent().y()) !=
806 layer
->offset_to_transform_parent().y())
811 gfx::Rect
LayerDrawableContentRect(
812 const LayerImpl
* layer
,
813 const gfx::Rect
& layer_bounds_in_target_space
,
814 const gfx::Rect
& clip_rect
) {
815 if (layer
->is_clipped())
816 return IntersectRects(layer_bounds_in_target_space
, clip_rect
);
818 return layer_bounds_in_target_space
;
821 gfx::Transform
ReplicaToSurfaceTransform(
822 const RenderSurfaceImpl
* render_surface
,
823 const TransformTree
& tree
) {
824 gfx::Transform replica_to_surface
;
825 if (!render_surface
->HasReplica())
826 return replica_to_surface
;
827 const LayerImpl
* replica_layer
= render_surface
->ReplicaLayer();
828 const TransformNode
* surface_transform_node
=
829 tree
.Node(render_surface
->TransformTreeIndex());
830 replica_to_surface
.Scale(surface_transform_node
->data
.sublayer_scale
.x(),
831 surface_transform_node
->data
.sublayer_scale
.y());
832 replica_to_surface
.Translate(replica_layer
->offset_to_transform_parent().x(),
833 replica_layer
->offset_to_transform_parent().y());
834 gfx::Transform replica_transform_node_to_surface
;
835 tree
.ComputeTransform(replica_layer
->transform_tree_index(),
836 render_surface
->TransformTreeIndex(),
837 &replica_transform_node_to_surface
);
838 replica_to_surface
.PreconcatTransform(replica_transform_node_to_surface
);
839 if (surface_transform_node
->data
.sublayer_scale
.x() != 0 &&
840 surface_transform_node
->data
.sublayer_scale
.y() != 0) {
841 replica_to_surface
.Scale(
842 1.0 / surface_transform_node
->data
.sublayer_scale
.x(),
843 1.0 / surface_transform_node
->data
.sublayer_scale
.y());
845 return replica_to_surface
;
848 gfx::Rect
LayerClipRect(const LayerImpl
* layer
,
849 const gfx::Rect
& layer_bounds_in_target_space
) {
850 if (layer
->is_clipped())
851 return layer
->clip_rect_in_target_space_from_property_trees();
853 return layer_bounds_in_target_space
;
856 void ComputeLayerDrawPropertiesUsingPropertyTrees(
857 const LayerImpl
* layer
,
858 const PropertyTrees
* property_trees
,
859 bool layers_always_allowed_lcd_text
,
860 bool can_use_lcd_text
,
861 DrawProperties
* draw_properties
) {
862 draw_properties
->visible_layer_rect
=
863 layer
->visible_rect_from_property_trees();
865 const TransformNode
* transform_node
=
866 property_trees
->transform_tree
.Node(layer
->transform_tree_index());
867 const EffectNode
* effect_node
=
868 property_trees
->effect_tree
.Node(layer
->effect_tree_index());
870 draw_properties
->target_space_transform
=
871 DrawTransformFromPropertyTreesInternal(layer
, transform_node
);
872 draw_properties
->screen_space_transform
=
873 ScreenSpaceTransformFromPropertyTreesInternal(layer
, transform_node
);
874 draw_properties
->screen_space_transform_is_animating
=
875 transform_node
->data
.to_screen_is_animated
;
876 if (layer
->layer_tree_impl()
878 .layer_transforms_should_scale_layer_contents
) {
879 draw_properties
->maximum_animation_contents_scale
=
880 transform_node
->data
.combined_maximum_animation_target_scale
;
881 draw_properties
->starting_animation_contents_scale
=
882 transform_node
->data
.combined_starting_animation_scale
;
884 draw_properties
->maximum_animation_contents_scale
= 0.f
;
885 draw_properties
->starting_animation_contents_scale
= 0.f
;
888 draw_properties
->opacity
=
889 LayerDrawOpacity(layer
, property_trees
->effect_tree
);
890 draw_properties
->can_use_lcd_text
=
891 LayerCanUseLcdText(layer
, layers_always_allowed_lcd_text
,
892 can_use_lcd_text
, transform_node
, effect_node
);
894 gfx::Rect bounds_in_target_space
= MathUtil::MapEnclosingClippedRect(
895 draw_properties
->target_space_transform
, gfx::Rect(layer
->bounds()));
896 draw_properties
->clip_rect
= LayerClipRect(layer
, bounds_in_target_space
);
897 draw_properties
->drawable_content_rect
= LayerDrawableContentRect(
898 layer
, bounds_in_target_space
, draw_properties
->clip_rect
);
901 void ComputeSurfaceDrawPropertiesUsingPropertyTrees(
902 RenderSurfaceImpl
* render_surface
,
903 const PropertyTrees
* property_trees
,
904 RenderSurfaceDrawProperties
* draw_properties
) {
905 const ClipNode
* clip_node
=
906 property_trees
->clip_tree
.Node(render_surface
->ClipTreeIndex());
908 draw_properties
->is_clipped
= SurfaceIsClipped(render_surface
, clip_node
);
909 draw_properties
->draw_opacity
=
910 SurfaceDrawOpacity(render_surface
, property_trees
->effect_tree
);
911 draw_properties
->draw_transform
=
912 SurfaceDrawTransform(render_surface
, property_trees
->transform_tree
);
913 draw_properties
->screen_space_transform
= SurfaceScreenSpaceTransform(
914 render_surface
, property_trees
->transform_tree
);
916 if (render_surface
->HasReplica()) {
917 gfx::Transform replica_to_surface
= ReplicaToSurfaceTransform(
918 render_surface
, property_trees
->transform_tree
);
919 draw_properties
->replica_draw_transform
=
920 draw_properties
->draw_transform
* replica_to_surface
;
921 draw_properties
->replica_screen_space_transform
=
922 draw_properties
->screen_space_transform
* replica_to_surface
;
924 draw_properties
->replica_draw_transform
.MakeIdentity();
925 draw_properties
->replica_screen_space_transform
.MakeIdentity();
928 draw_properties
->clip_rect
= SurfaceClipRect(
929 render_surface
, property_trees
->clip_tree
.parent(clip_node
),
930 draw_properties
->is_clipped
);