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 // 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.
42 const int target_id
= transform_node
->data
.content_target_id
;
43 const TransformNode
* target_node
= transform_tree
.Node(target_id
);
45 gfx::Transform content_to_target
= transform_node
->data
.to_target
;
47 content_to_target
.Translate(layer
->offset_to_transform_parent().x(),
48 layer
->offset_to_transform_parent().y());
50 gfx::Rect combined_clip_rect_in_target_space
;
51 gfx::Rect clip_rect_in_target_space
;
52 gfx::Transform clip_to_target
;
54 if (clip_transform_node
->data
.target_id
== target_node
->id
) {
55 clip_to_target
= clip_transform_node
->data
.to_target
;
57 success
= transform_tree
.ComputeTransformWithDestinationSublayerScale(
58 clip_transform_node
->id
, target_node
->id
, &clip_to_target
);
60 if (target_node
->id
> clip_node
->data
.transform_id
) {
62 DCHECK(target_node
->data
.to_screen_is_animated
);
64 // An animated singular transform may become non-singular during the
65 // animation, so we still need to compute a visible rect. In this
66 // situation, we treat the entire layer as visible.
67 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
68 layer
->set_clip_rect_in_target_space_from_property_trees(
69 gfx::ToEnclosingRect(clip_node
->data
.combined_clip
));
73 combined_clip_rect_in_target_space
=
74 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
75 clip_to_target
, clip_node
->data
.combined_clip
));
76 clip_rect_in_target_space
= gfx::ToEnclosingRect(
77 MathUtil::ProjectClippedRect(clip_to_target
, clip_node
->data
.clip
));
79 // Computing a transform to an ancestor should always succeed.
81 combined_clip_rect_in_target_space
=
82 gfx::ToEnclosingRect(MathUtil::MapClippedRect(
83 clip_to_target
, clip_node
->data
.combined_clip
));
84 clip_rect_in_target_space
= gfx::ToEnclosingRect(
85 MathUtil::MapClippedRect(clip_to_target
, clip_node
->data
.clip
));
88 if (clip_node
->data
.requires_tight_clip_rect
) {
89 if (!combined_clip_rect_in_target_space
.IsEmpty()) {
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(gfx::Rect());
96 if (!clip_rect_in_target_space
.IsEmpty()) {
97 layer
->set_clip_rect_in_target_space_from_property_trees(
98 clip_rect_in_target_space
);
100 layer
->set_clip_rect_in_target_space_from_property_trees(gfx::Rect());
104 gfx::Rect layer_content_rect
= gfx::Rect(layer_bounds
);
105 gfx::Rect layer_content_bounds_in_target_space
=
106 MathUtil::MapEnclosingClippedRect(content_to_target
,
108 combined_clip_rect_in_target_space
.Intersect(
109 layer_content_bounds_in_target_space
);
110 if (combined_clip_rect_in_target_space
.IsEmpty()) {
111 layer
->set_visible_rect_from_property_trees(gfx::Rect());
115 // If the layer is fully contained within the clip, treat it as fully
116 // visible. Since clip_rect_in_target_space has already been intersected
117 // with layer_content_bounds_in_target_space, the layer is fully contained
118 // within the clip iff these rects are equal.
119 if (combined_clip_rect_in_target_space
==
120 layer_content_bounds_in_target_space
) {
121 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
125 gfx::Transform target_to_content
;
126 gfx::Transform target_to_layer
;
128 if (transform_node
->data
.ancestors_are_invertible
) {
129 target_to_layer
= transform_node
->data
.from_target
;
132 success
= transform_tree
.ComputeTransformWithSourceSublayerScale(
133 target_node
->id
, transform_node
->id
, &target_to_layer
);
137 // An animated singular transform may become non-singular during the
138 // animation, so we still need to compute a visible rect. In this
139 // situation, we treat the entire layer as visible.
140 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
144 target_to_content
.Translate(-layer
->offset_to_transform_parent().x(),
145 -layer
->offset_to_transform_parent().y());
146 target_to_content
.PreconcatTransform(target_to_layer
);
148 gfx::Rect visible_rect
= MathUtil::ProjectEnclosingClippedRect(
149 target_to_content
, combined_clip_rect_in_target_space
);
151 visible_rect
.Intersect(gfx::Rect(layer_bounds
));
153 layer
->set_visible_rect_from_property_trees(visible_rect
);
155 layer
->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds
));
156 layer
->set_clip_rect_in_target_space_from_property_trees(
157 gfx::Rect(layer_bounds
));
162 template <typename LayerType
>
163 static bool IsRootLayerOfNewRenderingContext(LayerType
* layer
) {
165 return !layer
->parent()->Is3dSorted() && layer
->Is3dSorted();
166 return layer
->Is3dSorted();
169 template <typename LayerType
>
170 static inline bool LayerIsInExisting3DRenderingContext(LayerType
* layer
) {
171 return layer
->Is3dSorted() && layer
->parent() &&
172 layer
->parent()->Is3dSorted() &&
173 layer
->parent()->sorting_context_id() == layer
->sorting_context_id();
176 template <typename LayerType
>
177 static bool TransformToScreenIsKnown(LayerType
* layer
,
178 const TransformTree
& tree
) {
179 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
180 return !node
->data
.to_screen_is_animated
;
183 template <typename LayerType
>
184 static bool HasSingularTransform(LayerType
* layer
, const TransformTree
& tree
) {
185 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
186 return !node
->data
.is_invertible
|| !node
->data
.ancestors_are_invertible
;
189 template <typename LayerType
>
190 static bool IsLayerBackFaceVisible(LayerType
* layer
,
191 const TransformTree
& tree
) {
192 // The current W3C spec on CSS transforms says that backface visibility should
193 // be determined differently depending on whether the layer is in a "3d
194 // rendering context" or not. For Chromium code, we can determine whether we
195 // are in a 3d rendering context by checking if the parent preserves 3d.
197 if (LayerIsInExisting3DRenderingContext(layer
))
198 return DrawTransformFromPropertyTrees(layer
, tree
).IsBackFaceVisible();
200 // In this case, either the layer establishes a new 3d rendering context, or
201 // is not in a 3d rendering context at all.
202 return layer
->transform().IsBackFaceVisible();
205 template <typename LayerType
>
206 static bool IsSurfaceBackFaceVisible(LayerType
* layer
,
207 const TransformTree
& tree
) {
208 if (LayerIsInExisting3DRenderingContext(layer
)) {
209 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
210 // Draw transform as a contributing render surface.
211 // TODO(enne): we shouldn't walk the tree during a tree walk.
212 gfx::Transform surface_draw_transform
;
213 tree
.ComputeTransform(node
->id
, node
->data
.target_id
,
214 &surface_draw_transform
);
215 return surface_draw_transform
.IsBackFaceVisible();
218 if (IsRootLayerOfNewRenderingContext(layer
))
219 return layer
->transform().IsBackFaceVisible();
221 // If the render_surface is not part of a new or existing rendering context,
222 // then the layers that contribute to this surface will decide back-face
223 // visibility for themselves.
227 template <typename LayerType
>
228 static bool IsAnimatingTransformToScreen(LayerType
* layer
,
229 const TransformTree
& tree
) {
230 const TransformNode
* node
= tree
.Node(layer
->transform_tree_index());
231 return node
->data
.to_screen_is_animated
;
234 static inline bool TransformToScreenIsKnown(Layer
* layer
,
235 const TransformTree
& tree
) {
236 return !IsAnimatingTransformToScreen(layer
, tree
);
239 static inline bool TransformToScreenIsKnown(LayerImpl
* layer
,
240 const TransformTree
& tree
) {
244 template <typename LayerType
>
245 static bool HasInvertibleOrAnimatedTransform(LayerType
* layer
) {
246 return layer
->transform_is_invertible() ||
247 layer
->HasPotentiallyRunningTransformAnimation();
250 static inline bool SubtreeShouldBeSkipped(LayerImpl
* layer
,
252 const TransformTree
& tree
) {
253 // If the layer transform is not invertible, it should not be drawn.
254 // TODO(ajuma): Correctly process subtrees with singular transform for the
255 // case where we may animate to a non-singular transform and wish to
257 if (!HasInvertibleOrAnimatedTransform(layer
))
260 // When we need to do a readback/copy of a layer's output, we can not skip
261 // it or any of its ancestors.
262 if (layer
->draw_properties().layer_or_descendant_has_copy_request
)
265 // If the layer is not drawn, then skip it and its subtree.
269 if (layer
->render_surface() && !layer
->double_sided() &&
270 IsSurfaceBackFaceVisible(layer
, tree
))
273 // If layer is on the pending tree and opacity is being animated then
274 // this subtree can't be skipped as we need to create, prioritize and
275 // include tiles for this layer when deciding if tree can be activated.
276 if (layer
->layer_tree_impl()->IsPendingTree() &&
277 layer
->HasPotentiallyRunningOpacityAnimation())
280 // If layer has a background filter, don't skip the layer, even it the
282 if (!layer
->background_filters().IsEmpty())
285 // The opacity of a layer always applies to its children (either implicitly
286 // via a render surface or explicitly if the parent preserves 3D), so the
287 // entire subtree can be skipped if this layer is fully transparent.
288 return !layer
->opacity();
291 static inline bool SubtreeShouldBeSkipped(Layer
* layer
,
293 const TransformTree
& tree
) {
294 // If the layer transform is not invertible, it should not be drawn.
295 if (!layer
->transform_is_invertible() &&
296 !layer
->HasPotentiallyRunningTransformAnimation())
299 // When we need to do a readback/copy of a layer's output, we can not skip
300 // it or any of its ancestors.
301 if (layer
->num_layer_or_descendants_with_copy_request() > 0)
304 // If the layer is not drawn, then skip it and its subtree.
308 if (layer
->has_render_surface() && !layer
->double_sided() &&
309 !layer
->HasPotentiallyRunningTransformAnimation() &&
310 IsSurfaceBackFaceVisible(layer
, tree
))
313 // If layer has a background filter, don't skip the layer, even it the
315 if (!layer
->background_filters().IsEmpty())
318 // If the opacity is being animated then the opacity on the main thread is
319 // unreliable (since the impl thread may be using a different opacity), so it
320 // should not be trusted.
321 // In particular, it should not cause the subtree to be skipped.
322 // Similarly, for layers that might animate opacity using an impl-only
323 // animation, their subtree should also not be skipped.
324 return !layer
->opacity() && !layer
->HasPotentiallyRunningOpacityAnimation() &&
325 !layer
->OpacityCanAnimateOnImplThread();
328 template <typename LayerType
>
329 static bool LayerShouldBeSkipped(LayerType
* layer
,
331 const TransformTree
& tree
) {
332 // Layers can be skipped if any of these conditions are met.
333 // - is not drawn due to it or one of its ancestors being hidden (or having
334 // no copy requests).
335 // - does not draw content.
337 // - has empty bounds
338 // - the layer is not double-sided, but its back face is visible.
340 // Some additional conditions need to be computed at a later point after the
341 // recursion is finished.
342 // - the intersection of render_surface content and layer clip_rect is empty
343 // - the visible_layer_rect is empty
345 // Note, if the layer should not have been drawn due to being fully
346 // transparent, we would have skipped the entire subtree and never made it
347 // into this function, so it is safe to omit this check here.
351 if (!layer
->DrawsContent() || layer
->bounds().IsEmpty())
354 LayerType
* backface_test_layer
= layer
;
355 if (layer
->use_parent_backface_visibility()) {
356 DCHECK(layer
->parent());
357 DCHECK(!layer
->parent()->use_parent_backface_visibility());
358 backface_test_layer
= layer
->parent();
361 // The layer should not be drawn if (1) it is not double-sided and (2) the
362 // back of the layer is known to be facing the screen.
363 if (!backface_test_layer
->double_sided() &&
364 TransformToScreenIsKnown(backface_test_layer
, tree
) &&
365 IsLayerBackFaceVisible(backface_test_layer
, tree
))
371 template <typename LayerType
>
372 void FindLayersThatNeedUpdates(
374 const TransformTree
& tree
,
375 bool subtree_is_visible_from_ancestor
,
376 typename
LayerType::LayerListType
* update_layer_list
,
377 std::vector
<LayerType
*>* visible_layer_list
) {
378 bool layer_is_drawn
=
379 layer
->HasCopyRequest() ||
380 (subtree_is_visible_from_ancestor
&& !layer
->hide_layer_and_subtree());
382 if (layer
->parent() && SubtreeShouldBeSkipped(layer
, layer_is_drawn
, tree
))
385 if (!LayerShouldBeSkipped(layer
, layer_is_drawn
, tree
)) {
386 visible_layer_list
->push_back(layer
);
387 update_layer_list
->push_back(layer
);
390 // Append mask layers to the update layer list. They don't have valid visible
391 // rects, so need to get added after the above calculation. Replica layers
392 // don't need to be updated.
393 if (LayerType
* mask_layer
= layer
->mask_layer())
394 update_layer_list
->push_back(mask_layer
);
395 if (LayerType
* replica_layer
= layer
->replica_layer()) {
396 if (LayerType
* mask_layer
= replica_layer
->mask_layer())
397 update_layer_list
->push_back(mask_layer
);
400 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
401 FindLayersThatNeedUpdates(layer
->child_at(i
), tree
, layer_is_drawn
,
402 update_layer_list
, visible_layer_list
);
408 void ComputeClips(ClipTree
* clip_tree
, const TransformTree
& transform_tree
) {
409 if (!clip_tree
->needs_update())
411 for (int i
= 0; i
< static_cast<int>(clip_tree
->size()); ++i
) {
412 ClipNode
* clip_node
= clip_tree
->Node(i
);
413 const TransformNode
* transform_node
=
414 transform_tree
.Node(clip_node
->data
.transform_id
);
416 // Only descendants of a real clipping layer (i.e., not 0) may have their
417 // clip adjusted due to intersecting with an ancestor clip.
418 const bool is_clipped
= clip_node
->parent_id
> 0;
420 DCHECK(!clip_node
->data
.inherit_parent_target_space_clip
);
421 clip_node
->data
.combined_clip
= clip_node
->data
.clip
;
422 if (clip_node
->id
> 0) {
423 gfx::Transform to_target
= transform_node
->data
.to_target
;
424 clip_node
->data
.clip_in_target_space
=
425 MathUtil::MapClippedRect(to_target
, clip_node
->data
.combined_clip
);
430 ClipNode
* parent_clip_node
= clip_tree
->parent(clip_node
);
431 const TransformNode
* parent_transform_node
=
432 transform_tree
.Node(parent_clip_node
->data
.transform_id
);
434 // Clips must be combined in target space. We cannot, for example, combine
435 // clips in the space of the child clip. The reason is non-affine
436 // transforms. Say we have the following tree T->A->B->C, and B clips C, but
437 // draw into target T. It may be the case that A applies a perspective
438 // transform, and B and C are at different z positions. When projected into
439 // target space, the relative sizes and positions of B and C can shift.
440 // Since it's the relationship in target space that matters, that's where we
441 // must combine clips.
442 gfx::Transform parent_to_target
;
443 gfx::Transform clip_to_target
;
445 gfx::Transform target_to_clip
;
446 gfx::Transform parent_to_transform_target
;
447 gfx::Transform transform_target_to_target
;
449 // When the target is the root surface, we need to include the root
450 // transform by walking up to the root of the transform tree.
451 const int target_id
= clip_node
->data
.target_id
;
454 // When render surface applies clip, we need the clip from the target's
455 // target space. But, as the combined clip is in parent clip's target
456 // space, we need to first transform it from parent's target space to
457 // target's target space.
458 if (clip_node
->data
.inherit_parent_target_space_clip
) {
459 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
460 parent_transform_node
->id
, transform_node
->data
.target_id
,
461 &parent_to_transform_target
);
462 success
&= transform_tree
.ComputeTransformWithSourceSublayerScale(
463 transform_node
->data
.target_id
, target_id
,
464 &transform_target_to_target
);
465 transform_target_to_target
.matrix().postScale(
466 transform_node
->data
.sublayer_scale
.x(),
467 transform_node
->data
.sublayer_scale
.y(), 1.0);
468 } else if (parent_transform_node
->data
.content_target_id
==
469 clip_node
->data
.target_id
) {
470 parent_to_target
= parent_transform_node
->data
.to_target
;
472 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
473 parent_transform_node
->id
, target_id
, &parent_to_target
);
476 if (transform_node
->data
.content_target_id
== clip_node
->data
.target_id
) {
477 clip_to_target
= transform_node
->data
.to_target
;
479 success
&= transform_tree
.ComputeTransformWithDestinationSublayerScale(
480 transform_node
->id
, target_id
, &clip_to_target
);
483 if (transform_node
->data
.content_target_id
== clip_node
->data
.target_id
&&
484 transform_node
->data
.ancestors_are_invertible
) {
485 target_to_clip
= transform_node
->data
.from_target
;
487 success
&= clip_to_target
.GetInverse(&target_to_clip
);
490 // If we can't compute a transform, it's because we had to use the inverse
491 // of a singular transform. We won't draw in this case, so there's no need
497 // In order to intersect with as small a rect as possible, we do a
498 // preliminary clip in target space so that when we project back, there's
499 // less likelihood of intersecting the view plane.
500 gfx::RectF inherited_clip_in_target_space
;
501 if (clip_node
->data
.inherit_parent_target_space_clip
) {
502 gfx::RectF combined_clip_in_transform_target_space
;
503 if (parent_transform_node
->id
> transform_node
->data
.target_id
)
504 combined_clip_in_transform_target_space
= MathUtil::MapClippedRect(
505 parent_to_transform_target
, parent_clip_node
->data
.combined_clip
);
507 combined_clip_in_transform_target_space
= MathUtil::ProjectClippedRect(
508 parent_to_transform_target
, parent_clip_node
->data
.combined_clip
);
509 inherited_clip_in_target_space
= MathUtil::ProjectClippedRect(
510 transform_target_to_target
, combined_clip_in_transform_target_space
);
511 } else if (parent_transform_node
->id
> target_id
) {
512 inherited_clip_in_target_space
= MathUtil::MapClippedRect(
513 parent_to_target
, parent_clip_node
->data
.combined_clip
);
515 inherited_clip_in_target_space
= MathUtil::ProjectClippedRect(
516 parent_to_target
, parent_clip_node
->data
.combined_clip
);
519 // When render surface inherits its parent target space clip, the layer
520 // that created the clip node doesn't apply any clip. So, we shouldn't clip
521 // using the clip value stored in the clip node.
522 gfx::RectF intersected_in_target_space
;
523 if (!clip_node
->data
.inherit_parent_target_space_clip
) {
524 gfx::RectF clip_in_target_space
=
525 MathUtil::MapClippedRect(clip_to_target
, clip_node
->data
.clip
);
526 intersected_in_target_space
= gfx::IntersectRects(
527 inherited_clip_in_target_space
, clip_in_target_space
);
528 if (!clip_node
->data
.requires_tight_clip_rect
)
529 clip_node
->data
.clip_in_target_space
= clip_in_target_space
;
531 clip_node
->data
.clip_in_target_space
= intersected_in_target_space
;
533 intersected_in_target_space
= inherited_clip_in_target_space
;
534 clip_node
->data
.clip_in_target_space
= intersected_in_target_space
;
537 clip_node
->data
.combined_clip
= MathUtil::ProjectClippedRect(
538 target_to_clip
, intersected_in_target_space
);
540 if (!clip_node
->data
.inherit_parent_target_space_clip
)
541 clip_node
->data
.combined_clip
.Intersect(clip_node
->data
.clip
);
543 clip_tree
->set_needs_update(false);
546 void ComputeTransforms(TransformTree
* transform_tree
) {
547 if (!transform_tree
->needs_update())
549 for (int i
= 1; i
< static_cast<int>(transform_tree
->size()); ++i
)
550 transform_tree
->UpdateTransforms(i
);
551 transform_tree
->set_needs_update(false);
554 void ComputeOpacities(EffectTree
* effect_tree
) {
555 if (!effect_tree
->needs_update())
557 for (int i
= 1; i
< static_cast<int>(effect_tree
->size()); ++i
)
558 effect_tree
->UpdateOpacities(i
);
559 effect_tree
->set_needs_update(false);
562 template <typename LayerType
>
563 void ComputeVisibleRectsUsingPropertyTreesInternal(
564 LayerType
* root_layer
,
565 PropertyTrees
* property_trees
,
566 typename
LayerType::LayerListType
* update_layer_list
) {
567 if (property_trees
->transform_tree
.needs_update())
568 property_trees
->clip_tree
.set_needs_update(true);
569 ComputeTransforms(&property_trees
->transform_tree
);
570 ComputeClips(&property_trees
->clip_tree
, property_trees
->transform_tree
);
571 ComputeOpacities(&property_trees
->effect_tree
);
573 const bool subtree_is_visible_from_ancestor
= true;
574 std::vector
<LayerType
*> visible_layer_list
;
575 FindLayersThatNeedUpdates(root_layer
, property_trees
->transform_tree
,
576 subtree_is_visible_from_ancestor
, update_layer_list
,
577 &visible_layer_list
);
578 CalculateVisibleRects
<LayerType
>(visible_layer_list
,
579 property_trees
->clip_tree
,
580 property_trees
->transform_tree
);
583 void BuildPropertyTreesAndComputeVisibleRects(
585 const Layer
* page_scale_layer
,
586 const Layer
* inner_viewport_scroll_layer
,
587 const Layer
* outer_viewport_scroll_layer
,
588 float page_scale_factor
,
589 float device_scale_factor
,
590 const gfx::Rect
& viewport
,
591 const gfx::Transform
& device_transform
,
592 PropertyTrees
* property_trees
,
593 LayerList
* update_layer_list
) {
594 PropertyTreeBuilder::BuildPropertyTrees(
595 root_layer
, page_scale_layer
, inner_viewport_scroll_layer
,
596 outer_viewport_scroll_layer
, page_scale_factor
, device_scale_factor
,
597 viewport
, device_transform
, property_trees
);
598 ComputeVisibleRectsUsingPropertyTrees(root_layer
, property_trees
,
602 void BuildPropertyTreesAndComputeVisibleRects(
603 LayerImpl
* root_layer
,
604 const LayerImpl
* page_scale_layer
,
605 const LayerImpl
* inner_viewport_scroll_layer
,
606 const LayerImpl
* outer_viewport_scroll_layer
,
607 float page_scale_factor
,
608 float device_scale_factor
,
609 const gfx::Rect
& viewport
,
610 const gfx::Transform
& device_transform
,
611 PropertyTrees
* property_trees
,
612 LayerImplList
* update_layer_list
) {
613 PropertyTreeBuilder::BuildPropertyTrees(
614 root_layer
, page_scale_layer
, inner_viewport_scroll_layer
,
615 outer_viewport_scroll_layer
, page_scale_factor
, device_scale_factor
,
616 viewport
, device_transform
, property_trees
);
617 ComputeVisibleRectsUsingPropertyTrees(root_layer
, property_trees
,
621 void ComputeVisibleRectsUsingPropertyTrees(Layer
* root_layer
,
622 PropertyTrees
* property_trees
,
623 LayerList
* update_layer_list
) {
624 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
,
628 void ComputeVisibleRectsUsingPropertyTrees(LayerImpl
* root_layer
,
629 PropertyTrees
* property_trees
,
630 LayerImplList
* update_layer_list
) {
631 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer
, property_trees
,
635 template <typename LayerType
>
636 gfx::Transform
DrawTransformFromPropertyTreesInternal(
637 const LayerType
* layer
,
638 const TransformNode
* node
) {
639 gfx::Transform xform
;
640 const bool owns_non_root_surface
=
641 layer
->parent() && layer
->has_render_surface();
642 if (!owns_non_root_surface
) {
643 // If you're not the root, or you don't own a surface, you need to apply
644 // your local offset.
645 xform
= node
->data
.to_target
;
646 if (layer
->should_flatten_transform_from_property_tree())
648 xform
.Translate(layer
->offset_to_transform_parent().x(),
649 layer
->offset_to_transform_parent().y());
651 // Surfaces need to apply their sublayer scale.
652 xform
.Scale(node
->data
.sublayer_scale
.x(), node
->data
.sublayer_scale
.y());
657 gfx::Transform
DrawTransformFromPropertyTrees(const Layer
* layer
,
658 const TransformTree
& tree
) {
659 return DrawTransformFromPropertyTreesInternal(
660 layer
, tree
.Node(layer
->transform_tree_index()));
663 gfx::Transform
DrawTransformFromPropertyTrees(const LayerImpl
* layer
,
664 const TransformTree
& tree
) {
665 return DrawTransformFromPropertyTreesInternal(
666 layer
, tree
.Node(layer
->transform_tree_index()));
669 gfx::Transform
SurfaceDrawTransform(const RenderSurfaceImpl
* render_surface
,
670 const TransformTree
& tree
) {
671 const TransformNode
* node
= tree
.Node(render_surface
->TransformTreeIndex());
672 gfx::Transform render_surface_transform
;
673 // The draw transform of root render surface is identity tranform.
675 return render_surface_transform
;
676 const TransformNode
* target_node
= tree
.Node(node
->data
.target_id
);
677 tree
.ComputeTransformWithDestinationSublayerScale(node
->id
, target_node
->id
,
678 &render_surface_transform
);
679 if (node
->data
.sublayer_scale
.x() != 0.0 &&
680 node
->data
.sublayer_scale
.y() != 0.0)
681 render_surface_transform
.Scale(1.0 / node
->data
.sublayer_scale
.x(),
682 1.0 / node
->data
.sublayer_scale
.y());
683 return render_surface_transform
;
686 bool SurfaceIsClipped(const RenderSurfaceImpl
* render_surface
,
687 const ClipNode
* clip_node
) {
688 // If the render surface's owning layer doesn't form a clip node, it is not
690 if (render_surface
->OwningLayerId() != clip_node
->owner_id
)
692 return clip_node
->data
.render_surface_is_clipped
;
695 gfx::Rect
SurfaceClipRect(const RenderSurfaceImpl
* render_surface
,
696 const ClipNode
* parent_clip_node
,
700 return gfx::ToEnclosingRect(parent_clip_node
->data
.clip_in_target_space
);
703 gfx::Transform
SurfaceScreenSpaceTransform(
704 const RenderSurfaceImpl
* render_surface
,
705 const TransformTree
& tree
) {
706 const TransformNode
* node
= tree
.Node(render_surface
->TransformTreeIndex());
707 gfx::Transform screen_space_transform
;
708 // The screen space transform of root render surface is identity tranform.
710 return screen_space_transform
;
711 screen_space_transform
= node
->data
.to_screen
;
712 if (node
->data
.sublayer_scale
.x() != 0.0 &&
713 node
->data
.sublayer_scale
.y() != 0.0)
714 screen_space_transform
.Scale(1.0 / node
->data
.sublayer_scale
.x(),
715 1.0 / node
->data
.sublayer_scale
.y());
716 return screen_space_transform
;
719 template <typename LayerType
>
720 gfx::Transform
ScreenSpaceTransformFromPropertyTreesInternal(
722 const TransformNode
* node
) {
723 gfx::Transform
xform(1, 0, 0, 1, layer
->offset_to_transform_parent().x(),
724 layer
->offset_to_transform_parent().y());
725 gfx::Transform ssxform
= node
->data
.to_screen
;
726 xform
.ConcatTransform(ssxform
);
727 if (layer
->should_flatten_transform_from_property_tree())
732 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
734 const TransformTree
& tree
) {
735 return ScreenSpaceTransformFromPropertyTreesInternal(
736 layer
, tree
.Node(layer
->transform_tree_index()));
739 gfx::Transform
ScreenSpaceTransformFromPropertyTrees(
740 const LayerImpl
* layer
,
741 const TransformTree
& tree
) {
742 return ScreenSpaceTransformFromPropertyTreesInternal(
743 layer
, tree
.Node(layer
->transform_tree_index()));
746 float LayerDrawOpacity(const LayerImpl
* layer
, const EffectTree
& tree
) {
747 if (!layer
->render_target())
750 const EffectNode
* target_node
=
751 tree
.Node(layer
->render_target()->effect_tree_index());
752 const EffectNode
* node
= tree
.Node(layer
->effect_tree_index());
753 if (node
== target_node
)
756 float draw_opacity
= 1.f
;
757 while (node
!= target_node
) {
758 draw_opacity
*= node
->data
.opacity
;
759 node
= tree
.parent(node
);
764 float SurfaceDrawOpacity(RenderSurfaceImpl
* render_surface
,
765 const EffectTree
& tree
) {
766 const EffectNode
* node
= tree
.Node(render_surface
->EffectTreeIndex());
767 float target_opacity_tree_index
= render_surface
->TargetEffectTreeIndex();
768 if (target_opacity_tree_index
< 0)
769 return node
->data
.screen_space_opacity
;
770 const EffectNode
* target_node
= tree
.Node(target_opacity_tree_index
);
771 float draw_opacity
= 1.f
;
772 while (node
!= target_node
) {
773 draw_opacity
*= node
->data
.opacity
;
774 node
= tree
.parent(node
);
779 bool LayerCanUseLcdText(const LayerImpl
* layer
,
780 bool layers_always_allowed_lcd_text
,
781 bool can_use_lcd_text
,
782 const TransformNode
* transform_node
,
783 const EffectNode
* effect_node
) {
784 if (layers_always_allowed_lcd_text
)
786 if (!can_use_lcd_text
)
788 if (!layer
->contents_opaque())
791 if (effect_node
->data
.screen_space_opacity
!= 1.f
)
793 if (!transform_node
->data
.node_and_ancestors_have_only_integer_translation
)
795 if (static_cast<int>(layer
->offset_to_transform_parent().x()) !=
796 layer
->offset_to_transform_parent().x())
798 if (static_cast<int>(layer
->offset_to_transform_parent().y()) !=
799 layer
->offset_to_transform_parent().y())
804 gfx::Rect
LayerDrawableContentRect(
805 const LayerImpl
* layer
,
806 const gfx::Rect
& layer_bounds_in_target_space
,
807 const gfx::Rect
& clip_rect
) {
808 if (layer
->is_clipped())
809 return IntersectRects(layer_bounds_in_target_space
, clip_rect
);
811 return layer_bounds_in_target_space
;
814 gfx::Transform
ReplicaToSurfaceTransform(
815 const RenderSurfaceImpl
* render_surface
,
816 const TransformTree
& tree
) {
817 gfx::Transform replica_to_surface
;
818 if (!render_surface
->HasReplica())
819 return replica_to_surface
;
820 const LayerImpl
* replica_layer
= render_surface
->ReplicaLayer();
821 const TransformNode
* surface_transform_node
=
822 tree
.Node(render_surface
->TransformTreeIndex());
823 replica_to_surface
.Scale(surface_transform_node
->data
.sublayer_scale
.x(),
824 surface_transform_node
->data
.sublayer_scale
.y());
825 replica_to_surface
.Translate(replica_layer
->offset_to_transform_parent().x(),
826 replica_layer
->offset_to_transform_parent().y());
827 gfx::Transform replica_transform_node_to_surface
;
828 tree
.ComputeTransform(replica_layer
->transform_tree_index(),
829 render_surface
->TransformTreeIndex(),
830 &replica_transform_node_to_surface
);
831 replica_to_surface
.PreconcatTransform(replica_transform_node_to_surface
);
832 if (surface_transform_node
->data
.sublayer_scale
.x() != 0 &&
833 surface_transform_node
->data
.sublayer_scale
.y() != 0) {
834 replica_to_surface
.Scale(
835 1.0 / surface_transform_node
->data
.sublayer_scale
.x(),
836 1.0 / surface_transform_node
->data
.sublayer_scale
.y());
838 return replica_to_surface
;
841 gfx::Rect
LayerClipRect(const LayerImpl
* layer
,
842 const gfx::Rect
& layer_bounds_in_target_space
) {
843 if (layer
->is_clipped())
844 return layer
->clip_rect_in_target_space_from_property_trees();
846 return layer_bounds_in_target_space
;
849 void ComputeLayerDrawPropertiesUsingPropertyTrees(
850 const LayerImpl
* layer
,
851 const PropertyTrees
* property_trees
,
852 bool layers_always_allowed_lcd_text
,
853 bool can_use_lcd_text
,
854 DrawProperties
* draw_properties
) {
855 draw_properties
->visible_layer_rect
=
856 layer
->visible_rect_from_property_trees();
858 const TransformNode
* transform_node
=
859 property_trees
->transform_tree
.Node(layer
->transform_tree_index());
860 const EffectNode
* effect_node
=
861 property_trees
->effect_tree
.Node(layer
->effect_tree_index());
863 draw_properties
->target_space_transform
=
864 DrawTransformFromPropertyTreesInternal(layer
, transform_node
);
865 draw_properties
->screen_space_transform
=
866 ScreenSpaceTransformFromPropertyTreesInternal(layer
, transform_node
);
867 draw_properties
->screen_space_transform_is_animating
=
868 transform_node
->data
.to_screen_is_animated
;
869 if (layer
->layer_tree_impl()
871 .layer_transforms_should_scale_layer_contents
) {
872 draw_properties
->maximum_animation_contents_scale
=
873 transform_node
->data
.combined_maximum_animation_target_scale
;
874 draw_properties
->starting_animation_contents_scale
=
875 transform_node
->data
.combined_starting_animation_scale
;
877 draw_properties
->maximum_animation_contents_scale
= 0.f
;
878 draw_properties
->starting_animation_contents_scale
= 0.f
;
881 draw_properties
->opacity
=
882 LayerDrawOpacity(layer
, property_trees
->effect_tree
);
883 draw_properties
->can_use_lcd_text
=
884 LayerCanUseLcdText(layer
, layers_always_allowed_lcd_text
,
885 can_use_lcd_text
, transform_node
, effect_node
);
887 gfx::Rect bounds_in_target_space
= MathUtil::MapEnclosingClippedRect(
888 draw_properties
->target_space_transform
, gfx::Rect(layer
->bounds()));
889 draw_properties
->clip_rect
= LayerClipRect(layer
, bounds_in_target_space
);
890 draw_properties
->drawable_content_rect
= LayerDrawableContentRect(
891 layer
, bounds_in_target_space
, draw_properties
->clip_rect
);
894 void ComputeSurfaceDrawPropertiesUsingPropertyTrees(
895 RenderSurfaceImpl
* render_surface
,
896 const PropertyTrees
* property_trees
,
897 RenderSurfaceDrawProperties
* draw_properties
) {
898 const ClipNode
* clip_node
=
899 property_trees
->clip_tree
.Node(render_surface
->ClipTreeIndex());
901 draw_properties
->is_clipped
= SurfaceIsClipped(render_surface
, clip_node
);
902 draw_properties
->draw_opacity
=
903 SurfaceDrawOpacity(render_surface
, property_trees
->effect_tree
);
904 draw_properties
->draw_transform
=
905 SurfaceDrawTransform(render_surface
, property_trees
->transform_tree
);
906 draw_properties
->screen_space_transform
= SurfaceScreenSpaceTransform(
907 render_surface
, property_trees
->transform_tree
);
909 if (render_surface
->HasReplica()) {
910 gfx::Transform replica_to_surface
= ReplicaToSurfaceTransform(
911 render_surface
, property_trees
->transform_tree
);
912 draw_properties
->replica_draw_transform
=
913 draw_properties
->draw_transform
* replica_to_surface
;
914 draw_properties
->replica_screen_space_transform
=
915 draw_properties
->screen_space_transform
* replica_to_surface
;
917 draw_properties
->replica_draw_transform
.MakeIdentity();
918 draw_properties
->replica_screen_space_transform
.MakeIdentity();
921 draw_properties
->clip_rect
= SurfaceClipRect(
922 render_surface
, property_trees
->clip_tree
.parent(clip_node
),
923 draw_properties
->is_clipped
);