Support swap promises that are pinned to a particular layer tree.
[chromium-blink-merge.git] / cc / layers / layer_utils.cc
blob42d0e1b1d756e25dafc5636afa8acbc00e45d186
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/layers/layer_utils.h"
7 #include "cc/layers/layer_impl.h"
8 #include "cc/trees/layer_tree_host_common.h"
9 #include "ui/gfx/geometry/box_f.h"
11 namespace cc {
13 namespace {
15 bool HasAnimationThatInflatesBounds(const LayerImpl& layer) {
16 return layer.HasAnimationThatInflatesBounds();
19 bool HasFilterAnimationThatInflatesBounds(const LayerImpl& layer) {
20 return layer.HasFilterAnimationThatInflatesBounds();
23 bool HasTransformAnimationThatInflatesBounds(const LayerImpl& layer) {
24 return layer.HasTransformAnimationThatInflatesBounds();
27 inline bool HasAncestorTransformAnimation(const LayerImpl& layer) {
28 return layer.screen_space_transform_is_animating();
31 inline bool HasAncestorFilterAnimation(const LayerImpl& layer) {
32 for (const LayerImpl* current = &layer; current;
33 current = current->parent()) {
34 if (HasFilterAnimationThatInflatesBounds(*current))
35 return true;
38 return false;
41 } // namespace
43 bool LayerUtils::GetAnimationBounds(const LayerImpl& layer_in, gfx::BoxF* out) {
44 // We don't care about animated bounds for invisible layers.
45 if (!layer_in.DrawsContent())
46 return false;
48 // We also don't care for layers that are not animated or a child of an
49 // animated layer.
50 if (!HasAncestorTransformAnimation(layer_in) &&
51 !HasAncestorFilterAnimation(layer_in))
52 return false;
54 // To compute the inflated bounds for a layer, we start by taking its bounds
55 // and converting it to a 3d box, and then we transform or inflate it
56 // repeatedly as we walk up the layer tree to the root.
58 // At each layer we apply the following transformations to the box:
59 // 1) We translate so that the anchor point is the origin.
60 // 2) We either apply the layer's transform or inflate if the layer's
61 // transform is animated.
62 // 3) We undo the translation from step 1 and apply a second translation
63 // to account for the layer's position.
65 gfx::BoxF box(layer_in.bounds().width(), layer_in.bounds().height(), 0.f);
67 // We want to inflate/transform the box as few times as possible. Each time
68 // we do this, we have to make the box axis aligned again, so if we make many
69 // small adjustments to the box by transforming it repeatedly rather than
70 // once by the product of all these matrices, we will accumulate a bunch of
71 // unnecessary inflation because of the the many axis-alignment fixes. This
72 // matrix stores said product.
73 gfx::Transform coalesced_transform;
75 for (const LayerImpl* layer = &layer_in; layer; layer = layer->parent()) {
76 int transform_origin_x = layer->transform_origin().x();
77 int transform_origin_y = layer->transform_origin().y();
78 int transform_origin_z = layer->transform_origin().z();
80 gfx::PointF position = layer->position();
81 if (layer->parent() && !HasAnimationThatInflatesBounds(*layer)) {
82 // |composite_layer_transform| contains 1 - 4 mentioned above. We compute
83 // it separately and apply afterwards because it's a bit more efficient
84 // because post-multiplication appears a bit more expensive, so we want
85 // to do it only once.
86 gfx::Transform composite_layer_transform;
88 composite_layer_transform.Translate3d(transform_origin_x + position.x(),
89 transform_origin_y + position.y(),
90 transform_origin_z);
91 composite_layer_transform.PreconcatTransform(layer->transform());
92 composite_layer_transform.Translate3d(
93 -transform_origin_x, -transform_origin_y, -transform_origin_z);
95 // Add this layer's contributions to the |coalesced_transform|.
96 coalesced_transform.ConcatTransform(composite_layer_transform);
97 continue;
100 // First, apply coalesced transform we've been building and reset it.
101 coalesced_transform.TransformBox(&box);
102 coalesced_transform.MakeIdentity();
104 // We need to apply the inflation about the layer's anchor point. Rather
105 // than doing this via transforms, we'll just shift the box directly.
106 box.set_origin(box.origin() + gfx::Vector3dF(-transform_origin_x,
107 -transform_origin_y,
108 -transform_origin_z));
110 // Perform the inflation
111 if (HasFilterAnimationThatInflatesBounds(*layer)) {
112 gfx::BoxF inflated;
113 if (!layer->FilterAnimationBoundsForBox(box, &inflated))
114 return false;
115 box = inflated;
118 if (HasTransformAnimationThatInflatesBounds(*layer)) {
119 gfx::BoxF inflated;
120 if (!layer->TransformAnimationBoundsForBox(box, &inflated))
121 return false;
122 box = inflated;
125 // Apply step 3) mentioned above.
126 box.set_origin(box.origin() +
127 gfx::Vector3dF(transform_origin_x + position.x(),
128 transform_origin_y + position.y(),
129 transform_origin_z));
132 // If we've got an unapplied coalesced transform at this point, it must still
133 // be applied.
134 if (!coalesced_transform.IsIdentity())
135 coalesced_transform.TransformBox(&box);
137 *out = box;
139 return true;
142 } // namespace cc