Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: cc/trees/draw_property_utils.cc

Issue 816543004: Update from https://crrev.com/308996 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/trees/draw_property_utils.h ('k') | cc/trees/layer_tree_host.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "cc/trees/draw_property_utils.h"
6
7 #include <vector>
8
9 #include "cc/base/math_util.h"
10 #include "cc/layers/layer.h"
11 #include "cc/trees/property_tree.h"
12 #include "cc/trees/property_tree_builder.h"
13 #include "ui/gfx/geometry/rect_conversions.h"
14
15 namespace cc {
16
17 namespace {
18
19 void CalculateVisibleRects(
20 const std::vector<Layer*>& layers_that_need_visible_rects,
21 const ClipTree& clip_tree,
22 const TransformTree& transform_tree) {
23 for (size_t i = 0; i < layers_that_need_visible_rects.size(); ++i) {
24 Layer* layer = layers_that_need_visible_rects[i];
25
26 // TODO(ajuma): Compute content_scale rather than using it. Note that for
27 // PictureLayer and PictureImageLayers, content_bounds == bounds and
28 // content_scale_x == content_scale_y == 1.0, so once impl painting is on
29 // everywhere, this code will be unnecessary.
30 gfx::Size layer_content_bounds = layer->content_bounds();
31 float contents_scale_x = layer->contents_scale_x();
32 float contents_scale_y = layer->contents_scale_y();
33 const bool has_clip = layer->clip_tree_index() > 0;
34 const TransformNode* transform_node =
35 transform_tree.Node(layer->transform_tree_index());
36 if (has_clip) {
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 TransformNode* target_node =
41 transform_tree.Node(layer->render_target()->transform_tree_index());
42
43 gfx::Transform clip_to_target;
44 gfx::Transform content_to_target;
45 gfx::Transform target_to_content;
46 gfx::Transform target_to_layer;
47
48 bool success =
49 transform_tree.ComputeTransform(clip_transform_node->id,
50 target_node->id, &clip_to_target) &&
51 transform_tree.ComputeTransform(transform_node->id, target_node->id,
52 &content_to_target) &&
53 transform_tree.ComputeTransform(target_node->id, transform_node->id,
54 &target_to_layer);
55
56 // This should only fail if we somehow got here with a singular ancestor.
57 DCHECK(success);
58
59 target_to_content.Scale(contents_scale_x, contents_scale_y);
60 target_to_content.Translate(-layer->offset_to_transform_parent().x(),
61 -layer->offset_to_transform_parent().y());
62 target_to_content.PreconcatTransform(target_to_layer);
63
64 content_to_target.Translate(layer->offset_to_transform_parent().x(),
65 layer->offset_to_transform_parent().y());
66 content_to_target.Scale(1.0 / contents_scale_x, 1.0 / contents_scale_y);
67
68 gfx::Rect layer_content_rect = gfx::Rect(layer_content_bounds);
69 gfx::RectF layer_content_bounds_in_target_space =
70 MathUtil::MapClippedRect(content_to_target, layer_content_rect);
71 gfx::RectF clip_rect_in_target_space;
72 if (target_node->id > clip_node->id) {
73 clip_rect_in_target_space = MathUtil::ProjectClippedRect(
74 clip_to_target, clip_node->data.combined_clip);
75 } else {
76 clip_rect_in_target_space = MathUtil::MapClippedRect(
77 clip_to_target, clip_node->data.combined_clip);
78 }
79
80 clip_rect_in_target_space.Intersect(layer_content_bounds_in_target_space);
81
82 gfx::Rect visible_rect =
83 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
84 target_to_content, clip_rect_in_target_space));
85
86 visible_rect.Intersect(gfx::Rect(layer_content_bounds));
87
88 layer->set_visible_rect_from_property_trees(visible_rect);
89 } else {
90 layer->set_visible_rect_from_property_trees(
91 gfx::Rect(layer_content_bounds));
92 }
93 }
94 }
95
96 static bool IsRootLayerOfNewRenderingContext(Layer* layer) {
97 if (layer->parent())
98 return !layer->parent()->Is3dSorted() && layer->Is3dSorted();
99 return layer->Is3dSorted();
100 }
101
102 static inline bool LayerIsInExisting3DRenderingContext(Layer* layer) {
103 return layer->Is3dSorted() && layer->parent() &&
104 layer->parent()->Is3dSorted();
105 }
106
107 static bool TransformToScreenIsKnown(Layer* layer, const TransformTree& tree) {
108 const TransformNode* node = tree.Node(layer->transform_tree_index());
109 return !node->data.to_screen_is_animated;
110 }
111
112 static bool IsLayerBackFaceExposed(Layer* layer, const TransformTree& tree) {
113 if (!TransformToScreenIsKnown(layer, tree))
114 return false;
115 if (LayerIsInExisting3DRenderingContext(layer))
116 return layer->draw_transform_from_property_trees(tree).IsBackFaceVisible();
117 return layer->transform().IsBackFaceVisible();
118 }
119
120 static bool IsSurfaceBackFaceExposed(Layer* layer,
121 const TransformTree& tree) {
122 if (!TransformToScreenIsKnown(layer, tree))
123 return false;
124 if (LayerIsInExisting3DRenderingContext(layer))
125 return layer->draw_transform_from_property_trees(tree).IsBackFaceVisible();
126
127 if (IsRootLayerOfNewRenderingContext(layer))
128 return layer->transform().IsBackFaceVisible();
129
130 // If the render_surface is not part of a new or existing rendering context,
131 // then the layers that contribute to this surface will decide back-face
132 // visibility for themselves.
133 return false;
134 }
135
136 static bool HasSingularTransform(Layer* layer, const TransformTree& tree) {
137 const TransformNode* node = tree.Node(layer->transform_tree_index());
138 return !node->data.is_invertible || !node->data.ancestors_are_invertible;
139 }
140
141 static bool IsBackFaceInvisible(Layer* layer, const TransformTree& tree) {
142 Layer* backface_test_layer = layer;
143 if (layer->use_parent_backface_visibility()) {
144 DCHECK(layer->parent());
145 DCHECK(!layer->parent()->use_parent_backface_visibility());
146 backface_test_layer = layer->parent();
147 }
148 return !backface_test_layer->double_sided() &&
149 IsLayerBackFaceExposed(backface_test_layer, tree);
150 }
151
152 static bool IsInvisibleDueToTransform(Layer* layer, const TransformTree& tree) {
153 return HasSingularTransform(layer, tree) || IsBackFaceInvisible(layer, tree);
154 }
155
156 void FindLayersThatNeedVisibleRects(Layer* layer,
157 const TransformTree& tree,
158 bool subtree_is_visible_from_ancestor,
159 std::vector<Layer*>* layers_to_update) {
160 const bool subtree_is_invisble =
161 layer->opacity() == 0.0f ||
162 (layer->has_render_surface() && !layer->double_sided() &&
163 IsSurfaceBackFaceExposed(layer, tree));
164
165 if (subtree_is_invisble)
166 return;
167
168 bool layer_is_drawn =
169 layer->HasCopyRequest() ||
170 (subtree_is_visible_from_ancestor && !layer->hide_layer_and_subtree());
171
172 if (layer_is_drawn && layer->DrawsContent()) {
173 const bool visible = !IsInvisibleDueToTransform(layer, tree);
174 if (visible)
175 layers_to_update->push_back(layer);
176 }
177
178 for (size_t i = 0; i < layer->children().size(); ++i) {
179 FindLayersThatNeedVisibleRects(layer->children()[i].get(),
180 tree,
181 layer_is_drawn,
182 layers_to_update);
183 }
184 }
185
186 } // namespace
187
188 void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) {
189 for (int i = 0; i < static_cast<int>(clip_tree->size()); ++i) {
190 ClipNode* clip_node = clip_tree->Node(i);
191
192 // Only descendants of a real clipping layer (i.e., not 0) may have their
193 // clip adjusted due to intersecting with an ancestor clip.
194 const bool is_clipped = clip_node->parent_id > 0;
195 if (!is_clipped) {
196 clip_node->data.combined_clip = clip_node->data.clip;
197 continue;
198 }
199
200 ClipNode* parent_clip_node = clip_tree->parent(clip_node);
201 const TransformNode* parent_transform_node =
202 transform_tree.Node(parent_clip_node->data.transform_id);
203 const TransformNode* transform_node =
204 transform_tree.Node(clip_node->data.transform_id);
205
206 // Clips must be combined in target space. We cannot, for example, combine
207 // clips in the space of the child clip. The reason is non-affine
208 // transforms. Say we have the following tree T->A->B->C, and B clips C, but
209 // draw into target T. It may be the case that A applies a perspective
210 // transform, and B and C are at different z positions. When projected into
211 // target space, the relative sizes and positions of B and C can shift.
212 // Since it's the relationship in target space that matters, that's where we
213 // must combine clips.
214 gfx::Transform parent_to_target;
215 gfx::Transform clip_to_target;
216 gfx::Transform target_to_clip;
217
218 bool success =
219 transform_tree.ComputeTransform(parent_transform_node->id,
220 clip_node->data.target_id,
221 &parent_to_target) &&
222 transform_tree.ComputeTransform(
223 transform_node->id, clip_node->data.target_id, &clip_to_target) &&
224 transform_tree.ComputeTransform(clip_node->data.target_id,
225 transform_node->id, &target_to_clip);
226
227 // If we can't compute a transform, it's because we had to use the inverse
228 // of a singular transform. We won't draw in this case, so there's no need
229 // to compute clips.
230 if (!success)
231 continue;
232
233 // In order to intersect with as small a rect as possible, we do a
234 // preliminary clip in target space so that when we project back, there's
235 // less likelihood of intersecting the view plane.
236 gfx::RectF inherited_clip_in_target_space = MathUtil::MapClippedRect(
237 parent_to_target, parent_clip_node->data.combined_clip);
238
239 gfx::RectF clip_in_target_space =
240 MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip);
241
242 gfx::RectF intersected_in_target_space = gfx::IntersectRects(
243 inherited_clip_in_target_space, clip_in_target_space);
244
245 clip_node->data.combined_clip = MathUtil::ProjectClippedRect(
246 target_to_clip, intersected_in_target_space);
247
248 clip_node->data.combined_clip.Intersect(clip_node->data.clip);
249 }
250 }
251
252 void ComputeTransforms(TransformTree* transform_tree) {
253 for (int i = 0; i < static_cast<int>(transform_tree->size()); ++i)
254 transform_tree->UpdateScreenSpaceTransform(i);
255 }
256
257 void ComputeVisibleRectsUsingPropertyTrees(
258 Layer* root_layer,
259 const Layer* page_scale_layer,
260 float page_scale_factor,
261 float device_scale_factor,
262 const gfx::Rect& viewport,
263 const gfx::Transform& device_transform,
264 TransformTree* transform_tree,
265 ClipTree* clip_tree) {
266 PropertyTreeBuilder::BuildPropertyTrees(
267 root_layer, page_scale_layer, page_scale_factor, device_scale_factor,
268 viewport, device_transform, transform_tree, clip_tree);
269 ComputeTransforms(transform_tree);
270 ComputeClips(clip_tree, *transform_tree);
271
272 std::vector<Layer*> layers_to_update;
273 const bool subtree_is_visible_from_ancestor = true;
274 FindLayersThatNeedVisibleRects(root_layer, *transform_tree,
275 subtree_is_visible_from_ancestor,
276 &layers_to_update);
277 CalculateVisibleRects(layers_to_update, *clip_tree, *transform_tree);
278 }
279
280 } // namespace cc
OLDNEW
« no previous file with comments | « cc/trees/draw_property_utils.h ('k') | cc/trees/layer_tree_host.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698