Roll src/third_party/skia 99c7c07:4af6580
[chromium-blink-merge.git] / cc / trees / draw_property_utils.cc
blob50b91cb37b1bd432cefb3cf3a4c3bbf2a1156c42
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"
7 #include <vector>
9 #include "cc/base/math_util.h"
10 #include "cc/layers/layer.h"
11 #include "cc/layers/layer_impl.h"
12 #include "cc/trees/layer_tree_impl.h"
13 #include "cc/trees/property_tree.h"
14 #include "cc/trees/property_tree_builder.h"
15 #include "ui/gfx/geometry/rect_conversions.h"
17 namespace cc {
19 namespace {
21 template <typename LayerType>
22 void CalculateVisibleRects(
23 const std::vector<LayerType*>& layers_that_need_visible_rects,
24 const ClipTree& clip_tree,
25 const TransformTree& transform_tree) {
26 for (size_t i = 0; i < layers_that_need_visible_rects.size(); ++i) {
27 LayerType* layer = layers_that_need_visible_rects[i];
29 // TODO(ajuma): Compute content_scale rather than using it. Note that for
30 // PictureLayer and PictureImageLayers, content_bounds == bounds and
31 // content_scale_x == content_scale_y == 1.0, so once impl painting is on
32 // everywhere, this code will be unnecessary.
33 gfx::Size layer_content_bounds = layer->content_bounds();
34 float contents_scale_x = layer->contents_scale_x();
35 float contents_scale_y = layer->contents_scale_y();
36 const bool has_clip = layer->clip_tree_index() > 0;
37 const TransformNode* transform_node =
38 transform_tree.Node(layer->transform_tree_index());
39 if (has_clip) {
40 const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
41 const TransformNode* clip_transform_node =
42 transform_tree.Node(clip_node->data.transform_id);
43 const bool target_is_root_surface =
44 transform_node->data.content_target_id == 1;
45 // When the target is the root surface, we need to include the root
46 // transform by walking up to the root of the transform tree.
47 const int target_id =
48 target_is_root_surface ? 0 : transform_node->data.content_target_id;
49 const TransformNode* target_node = transform_tree.Node(target_id);
51 gfx::Transform content_to_target = transform_node->data.to_target;
53 content_to_target.Translate(layer->offset_to_transform_parent().x(),
54 layer->offset_to_transform_parent().y());
55 content_to_target.Scale(1.0 / contents_scale_x, 1.0 / contents_scale_y);
57 gfx::Rect clip_rect_in_target_space;
58 gfx::Transform clip_to_target;
59 bool success = true;
60 if (clip_transform_node->data.target_id == target_node->id) {
61 clip_to_target = clip_transform_node->data.to_target;
62 } else {
63 success = transform_tree.ComputeTransformWithDestinationSublayerScale(
64 clip_transform_node->id, target_node->id, &clip_to_target);
67 if (target_node->id > clip_node->data.transform_id) {
68 if (!success) {
69 DCHECK(target_node->data.to_screen_is_animated);
71 // An animated singular transform may become non-singular during the
72 // animation, so we still need to compute a visible rect. In this
73 // situation, we treat the entire layer as visible.
74 layer->set_visible_rect_from_property_trees(
75 gfx::Rect(layer_content_bounds));
76 continue;
79 clip_rect_in_target_space =
80 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
81 clip_to_target, clip_node->data.combined_clip));
82 } else {
83 // Computing a transform to an ancestor should always succeed.
84 DCHECK(success);
85 clip_rect_in_target_space =
86 gfx::ToEnclosingRect(MathUtil::MapClippedRect(
87 clip_to_target, clip_node->data.combined_clip));
90 gfx::Rect layer_content_rect = gfx::Rect(layer_content_bounds);
91 gfx::Rect layer_content_bounds_in_target_space =
92 MathUtil::MapEnclosingClippedRect(content_to_target,
93 layer_content_rect);
94 clip_rect_in_target_space.Intersect(layer_content_bounds_in_target_space);
95 if (clip_rect_in_target_space.IsEmpty()) {
96 layer->set_visible_rect_from_property_trees(gfx::Rect());
97 continue;
100 gfx::Transform target_to_content;
101 gfx::Transform target_to_layer;
103 if (transform_node->data.ancestors_are_invertible) {
104 target_to_layer = transform_node->data.from_target;
105 success = true;
106 } else {
107 success = transform_tree.ComputeTransformWithSourceSublayerScale(
108 target_node->id, transform_node->id, &target_to_layer);
111 if (!success) {
112 DCHECK(transform_node->data.to_screen_is_animated);
114 // An animated singular transform may become non-singular during the
115 // animation, so we still need to compute a visible rect. In this
116 // situation, we treat the entire layer as visible.
117 layer->set_visible_rect_from_property_trees(
118 gfx::Rect(layer_content_bounds));
119 continue;
122 target_to_content.Scale(contents_scale_x, contents_scale_y);
123 target_to_content.Translate(-layer->offset_to_transform_parent().x(),
124 -layer->offset_to_transform_parent().y());
125 target_to_content.PreconcatTransform(target_to_layer);
127 gfx::Rect visible_rect = MathUtil::ProjectEnclosingClippedRect(
128 target_to_content, clip_rect_in_target_space);
130 visible_rect.Intersect(gfx::Rect(layer_content_bounds));
132 layer->set_visible_rect_from_property_trees(visible_rect);
133 } else {
134 layer->set_visible_rect_from_property_trees(
135 gfx::Rect(layer_content_bounds));
140 template <typename LayerType>
141 static bool IsRootLayerOfNewRenderingContext(LayerType* layer) {
142 if (layer->parent())
143 return !layer->parent()->Is3dSorted() && layer->Is3dSorted();
144 return layer->Is3dSorted();
147 template <typename LayerType>
148 static inline bool LayerIsInExisting3DRenderingContext(LayerType* layer) {
149 return layer->Is3dSorted() && layer->parent() &&
150 layer->parent()->Is3dSorted();
153 template <typename LayerType>
154 static bool TransformToScreenIsKnown(LayerType* layer,
155 const TransformTree& tree) {
156 const TransformNode* node = tree.Node(layer->transform_tree_index());
157 return !node->data.to_screen_is_animated;
160 template <typename LayerType>
161 static bool HasSingularTransform(LayerType* layer, const TransformTree& tree) {
162 const TransformNode* node = tree.Node(layer->transform_tree_index());
163 return !node->data.is_invertible || !node->data.ancestors_are_invertible;
166 template <typename LayerType>
167 static bool IsLayerBackFaceVisible(LayerType* layer,
168 const TransformTree& tree) {
169 // The current W3C spec on CSS transforms says that backface visibility should
170 // be determined differently depending on whether the layer is in a "3d
171 // rendering context" or not. For Chromium code, we can determine whether we
172 // are in a 3d rendering context by checking if the parent preserves 3d.
174 if (LayerIsInExisting3DRenderingContext(layer))
175 return DrawTransformFromPropertyTrees(layer, tree).IsBackFaceVisible();
177 // In this case, either the layer establishes a new 3d rendering context, or
178 // is not in a 3d rendering context at all.
179 return layer->transform().IsBackFaceVisible();
182 template <typename LayerType>
183 static bool IsAnimatingTransformToScreen(LayerType* layer,
184 const TransformTree& tree) {
185 const TransformNode* node = tree.Node(layer->transform_tree_index());
186 return node->data.to_screen_is_animated;
189 static inline bool TransformToScreenIsKnown(Layer* layer,
190 const TransformTree& tree) {
191 return !IsAnimatingTransformToScreen(layer, tree);
194 static inline bool TransformToScreenIsKnown(LayerImpl* layer,
195 const TransformTree& tree) {
196 return true;
199 template <typename LayerType>
200 static bool HasInvertibleOrAnimatedTransform(LayerType* layer) {
201 return layer->transform_is_invertible() || layer->TransformIsAnimating();
204 static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
205 bool layer_is_drawn) {
206 // If the layer transform is not invertible, it should not be drawn.
207 // TODO(ajuma): Correctly process subtrees with singular transform for the
208 // case where we may animate to a non-singular transform and wish to
209 // pre-raster.
210 if (!HasInvertibleOrAnimatedTransform(layer))
211 return true;
213 // When we need to do a readback/copy of a layer's output, we can not skip
214 // it or any of its ancestors.
215 if (layer->draw_properties().layer_or_descendant_has_copy_request)
216 return false;
218 // We cannot skip the the subtree if a descendant has a wheel or touch handler
219 // or the hit testing code will break (it requires fresh transforms, etc).
220 if (layer->draw_properties().layer_or_descendant_has_input_handler)
221 return false;
223 // If the layer is not drawn, then skip it and its subtree.
224 if (!layer_is_drawn)
225 return true;
227 // If layer is on the pending tree and opacity is being animated then
228 // this subtree can't be skipped as we need to create, prioritize and
229 // include tiles for this layer when deciding if tree can be activated.
230 if (layer->layer_tree_impl()->IsPendingTree() && layer->OpacityIsAnimating())
231 return false;
233 // The opacity of a layer always applies to its children (either implicitly
234 // via a render surface or explicitly if the parent preserves 3D), so the
235 // entire subtree can be skipped if this layer is fully transparent.
236 return !layer->opacity();
239 static inline bool SubtreeShouldBeSkipped(Layer* layer, bool layer_is_drawn) {
240 // If the layer transform is not invertible, it should not be drawn.
241 if (!layer->transform_is_invertible() && !layer->TransformIsAnimating())
242 return true;
244 // When we need to do a readback/copy of a layer's output, we can not skip
245 // it or any of its ancestors.
246 if (layer->draw_properties().layer_or_descendant_has_copy_request)
247 return false;
249 // We cannot skip the the subtree if a descendant has a wheel or touch handler
250 // or the hit testing code will break (it requires fresh transforms, etc).
251 if (layer->draw_properties().layer_or_descendant_has_input_handler)
252 return false;
254 // If the layer is not drawn, then skip it and its subtree.
255 if (!layer_is_drawn)
256 return true;
258 // If the opacity is being animated then the opacity on the main thread is
259 // unreliable (since the impl thread may be using a different opacity), so it
260 // should not be trusted.
261 // In particular, it should not cause the subtree to be skipped.
262 // Similarly, for layers that might animate opacity using an impl-only
263 // animation, their subtree should also not be skipped.
264 return !layer->opacity() && !layer->OpacityIsAnimating() &&
265 !layer->OpacityCanAnimateOnImplThread();
268 template <typename LayerType>
269 static bool LayerShouldBeSkipped(LayerType* layer,
270 bool layer_is_drawn,
271 const TransformTree& tree) {
272 // Layers can be skipped if any of these conditions are met.
273 // - is not drawn due to it or one of its ancestors being hidden (or having
274 // no copy requests).
275 // - does not draw content.
276 // - is transparent.
277 // - has empty bounds
278 // - the layer is not double-sided, but its back face is visible.
280 // Some additional conditions need to be computed at a later point after the
281 // recursion is finished.
282 // - the intersection of render_surface content and layer clip_rect is empty
283 // - the visible_content_rect is empty
285 // Note, if the layer should not have been drawn due to being fully
286 // transparent, we would have skipped the entire subtree and never made it
287 // into this function, so it is safe to omit this check here.
288 if (!layer_is_drawn)
289 return true;
291 if (!layer->DrawsContent() || layer->bounds().IsEmpty())
292 return true;
294 LayerType* backface_test_layer = layer;
295 if (layer->use_parent_backface_visibility()) {
296 DCHECK(layer->parent());
297 DCHECK(!layer->parent()->use_parent_backface_visibility());
298 backface_test_layer = layer->parent();
301 // The layer should not be drawn if (1) it is not double-sided and (2) the
302 // back of the layer is known to be facing the screen.
303 if (!backface_test_layer->double_sided() &&
304 TransformToScreenIsKnown(backface_test_layer, tree) &&
305 IsLayerBackFaceVisible(backface_test_layer, tree))
306 return true;
308 return false;
311 template <typename LayerType>
312 void FindLayersThatNeedVisibleRects(LayerType* layer,
313 const TransformTree& tree,
314 bool subtree_is_visible_from_ancestor,
315 std::vector<LayerType*>* layers_to_update) {
316 bool layer_is_drawn =
317 layer->HasCopyRequest() ||
318 (subtree_is_visible_from_ancestor && !layer->hide_layer_and_subtree());
320 if (layer->parent() && SubtreeShouldBeSkipped(layer, layer_is_drawn))
321 return;
323 if (!LayerShouldBeSkipped(layer, layer_is_drawn, tree))
324 layers_to_update->push_back(layer);
326 for (size_t i = 0; i < layer->children().size(); ++i) {
327 FindLayersThatNeedVisibleRects(layer->child_at(i), tree, layer_is_drawn,
328 layers_to_update);
332 } // namespace
334 void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) {
335 if (!clip_tree->needs_update())
336 return;
337 for (int i = 0; i < static_cast<int>(clip_tree->size()); ++i) {
338 ClipNode* clip_node = clip_tree->Node(i);
340 // Only descendants of a real clipping layer (i.e., not 0) may have their
341 // clip adjusted due to intersecting with an ancestor clip.
342 const bool is_clipped = clip_node->parent_id > 0;
343 if (!is_clipped) {
344 clip_node->data.combined_clip = clip_node->data.clip;
345 continue;
348 ClipNode* parent_clip_node = clip_tree->parent(clip_node);
349 const TransformNode* parent_transform_node =
350 transform_tree.Node(parent_clip_node->data.transform_id);
351 const TransformNode* transform_node =
352 transform_tree.Node(clip_node->data.transform_id);
354 // Clips must be combined in target space. We cannot, for example, combine
355 // clips in the space of the child clip. The reason is non-affine
356 // transforms. Say we have the following tree T->A->B->C, and B clips C, but
357 // draw into target T. It may be the case that A applies a perspective
358 // transform, and B and C are at different z positions. When projected into
359 // target space, the relative sizes and positions of B and C can shift.
360 // Since it's the relationship in target space that matters, that's where we
361 // must combine clips.
362 gfx::Transform parent_to_target;
363 gfx::Transform clip_to_target;
364 gfx::Transform target_to_clip;
366 const bool target_is_root_surface = clip_node->data.target_id == 1;
367 // When the target is the root surface, we need to include the root
368 // transform by walking up to the root of the transform tree.
369 const int target_id =
370 target_is_root_surface ? 0 : clip_node->data.target_id;
372 bool success = true;
373 if (parent_transform_node->data.content_target_id ==
374 clip_node->data.target_id) {
375 parent_to_target = parent_transform_node->data.to_target;
376 } else {
377 success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
378 parent_transform_node->id, target_id, &parent_to_target);
381 if (transform_node->data.content_target_id == clip_node->data.target_id) {
382 clip_to_target = transform_node->data.to_target;
383 } else {
384 success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
385 transform_node->id, target_id, &clip_to_target);
388 if (transform_node->data.content_target_id == clip_node->data.target_id &&
389 transform_node->data.ancestors_are_invertible) {
390 target_to_clip = transform_node->data.from_target;
391 } else {
392 success &= clip_to_target.GetInverse(&target_to_clip);
395 // If we can't compute a transform, it's because we had to use the inverse
396 // of a singular transform. We won't draw in this case, so there's no need
397 // to compute clips.
398 if (!success)
399 continue;
401 // In order to intersect with as small a rect as possible, we do a
402 // preliminary clip in target space so that when we project back, there's
403 // less likelihood of intersecting the view plane.
404 gfx::RectF inherited_clip_in_target_space = MathUtil::MapClippedRect(
405 parent_to_target, parent_clip_node->data.combined_clip);
407 gfx::RectF clip_in_target_space =
408 MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip);
410 gfx::RectF intersected_in_target_space = gfx::IntersectRects(
411 inherited_clip_in_target_space, clip_in_target_space);
413 clip_node->data.combined_clip = MathUtil::ProjectClippedRect(
414 target_to_clip, intersected_in_target_space);
416 clip_node->data.combined_clip.Intersect(clip_node->data.clip);
418 clip_tree->set_needs_update(false);
421 void ComputeTransforms(TransformTree* transform_tree) {
422 if (!transform_tree->needs_update())
423 return;
424 for (int i = 1; i < static_cast<int>(transform_tree->size()); ++i)
425 transform_tree->UpdateTransforms(i);
426 transform_tree->set_needs_update(false);
429 template <typename LayerType>
430 void ComputeVisibleRectsUsingPropertyTreesInternal(
431 LayerType* root_layer,
432 PropertyTrees* property_trees) {
433 if (property_trees->transform_tree.needs_update())
434 property_trees->clip_tree.set_needs_update(true);
435 ComputeTransforms(&property_trees->transform_tree);
436 ComputeClips(&property_trees->clip_tree, property_trees->transform_tree);
438 std::vector<LayerType*> layers_to_update;
439 const bool subtree_is_visible_from_ancestor = true;
440 FindLayersThatNeedVisibleRects(root_layer, property_trees->transform_tree,
441 subtree_is_visible_from_ancestor,
442 &layers_to_update);
443 CalculateVisibleRects(layers_to_update, property_trees->clip_tree,
444 property_trees->transform_tree);
447 void BuildPropertyTreesAndComputeVisibleRects(
448 Layer* root_layer,
449 const Layer* page_scale_layer,
450 float page_scale_factor,
451 float device_scale_factor,
452 const gfx::Rect& viewport,
453 const gfx::Transform& device_transform,
454 PropertyTrees* property_trees) {
455 PropertyTreeBuilder::BuildPropertyTrees(
456 root_layer, page_scale_layer, page_scale_factor, device_scale_factor,
457 viewport, device_transform, property_trees);
458 ComputeVisibleRectsUsingPropertyTrees(root_layer, property_trees);
461 void BuildPropertyTreesAndComputeVisibleRects(
462 LayerImpl* root_layer,
463 const LayerImpl* page_scale_layer,
464 float page_scale_factor,
465 float device_scale_factor,
466 const gfx::Rect& viewport,
467 const gfx::Transform& device_transform,
468 PropertyTrees* property_trees) {
469 PropertyTreeBuilder::BuildPropertyTrees(
470 root_layer, page_scale_layer, page_scale_factor, device_scale_factor,
471 viewport, device_transform, property_trees);
472 ComputeVisibleRectsUsingPropertyTrees(root_layer, property_trees);
475 void ComputeVisibleRectsUsingPropertyTrees(Layer* root_layer,
476 PropertyTrees* property_trees) {
477 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer, property_trees);
480 void ComputeVisibleRectsUsingPropertyTrees(LayerImpl* root_layer,
481 PropertyTrees* property_trees) {
482 ComputeVisibleRectsUsingPropertyTreesInternal(root_layer, property_trees);
485 template <typename LayerType>
486 gfx::Transform DrawTransformFromPropertyTreesInternal(
487 const LayerType* layer,
488 const TransformTree& tree) {
489 const TransformNode* node = tree.Node(layer->transform_tree_index());
490 // TODO(vollick): ultimately we'll need to find this information (whether or
491 // not we establish a render surface) somewhere other than the layer.
492 const TransformNode* target_node =
493 layer->render_surface() ? node : tree.Node(node->data.content_target_id);
495 gfx::Transform xform;
496 const bool owns_non_root_surface = layer->parent() && layer->render_surface();
497 if (!owns_non_root_surface) {
498 // If you're not the root, or you don't own a surface, you need to apply
499 // your local offset.
500 xform = node->data.to_target;
501 if (layer->should_flatten_transform_from_property_tree())
502 xform.FlattenTo2d();
503 xform.Translate(layer->offset_to_transform_parent().x(),
504 layer->offset_to_transform_parent().y());
505 // A fixed-position layer does not necessarily have the same render target
506 // as its transform node. In particular, its transform node may be an
507 // ancestor of its render target's transform node. For example, given layer
508 // tree R->S->F, suppose F is fixed and S owns a render surface (e.g., say S
509 // has opacity 0.9 and both S and F draw content). Then F's transform node
510 // is the root node, so the target space transform from that node is defined
511 // with respect to the root render surface. But F will render to S's
512 // surface, so must apply a change of basis transform to the target space
513 // transform from its transform node.
514 if (layer->position_constraint().is_fixed_position()) {
515 gfx::Transform tree_target_to_render_target;
516 tree.ComputeTransform(node->data.content_target_id,
517 layer->render_target()->transform_tree_index(),
518 &tree_target_to_render_target);
519 xform.ConcatTransform(tree_target_to_render_target);
521 } else {
522 // Surfaces need to apply their sublayer scale.
523 xform.Scale(target_node->data.sublayer_scale.x(),
524 target_node->data.sublayer_scale.y());
526 xform.Scale(1.0 / layer->contents_scale_x(), 1.0 / layer->contents_scale_y());
527 return xform;
530 gfx::Transform DrawTransformFromPropertyTrees(const Layer* layer,
531 const TransformTree& tree) {
532 return DrawTransformFromPropertyTreesInternal(layer, tree);
535 gfx::Transform DrawTransformFromPropertyTrees(const LayerImpl* layer,
536 const TransformTree& tree) {
537 return DrawTransformFromPropertyTreesInternal(layer, tree);
540 template <typename LayerType>
541 gfx::Transform ScreenSpaceTransformFromPropertyTreesInternal(
542 LayerType* layer,
543 const TransformTree& tree) {
544 gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(),
545 layer->offset_to_transform_parent().y());
546 if (layer->transform_tree_index() >= 0) {
547 gfx::Transform ssxform =
548 tree.Node(layer->transform_tree_index())->data.to_screen;
549 xform.ConcatTransform(ssxform);
550 if (layer->should_flatten_transform_from_property_tree())
551 xform.FlattenTo2d();
553 xform.Scale(1.0 / layer->contents_scale_x(), 1.0 / layer->contents_scale_y());
554 return xform;
557 gfx::Transform ScreenSpaceTransformFromPropertyTrees(
558 const Layer* layer,
559 const TransformTree& tree) {
560 return ScreenSpaceTransformFromPropertyTreesInternal(layer, tree);
563 gfx::Transform ScreenSpaceTransformFromPropertyTrees(
564 const LayerImpl* layer,
565 const TransformTree& tree) {
566 return ScreenSpaceTransformFromPropertyTreesInternal(layer, tree);
569 template <typename LayerType>
570 float DrawOpacityFromPropertyTreesInternal(LayerType layer,
571 const OpacityTree& tree) {
572 if (!layer->render_target())
573 return 0.f;
575 const OpacityNode* target_node =
576 tree.Node(layer->render_target()->opacity_tree_index());
577 const OpacityNode* node = tree.Node(layer->opacity_tree_index());
578 if (node == target_node)
579 return 1.f;
581 float draw_opacity = 1.f;
582 while (node != target_node) {
583 draw_opacity *= node->data;
584 node = tree.parent(node);
586 return draw_opacity;
589 float DrawOpacityFromPropertyTrees(const Layer* layer,
590 const OpacityTree& tree) {
591 return DrawOpacityFromPropertyTreesInternal(layer, tree);
594 float DrawOpacityFromPropertyTrees(const LayerImpl* layer,
595 const OpacityTree& tree) {
596 return DrawOpacityFromPropertyTreesInternal(layer, tree);
599 } // namespace cc