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

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

Issue 2008283003: cc: Separate computation of clip rect and visible rect to two functions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address review comments Created 4 years, 6 months 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/trees/draw_property_utils.h" 5 #include "cc/trees/draw_property_utils.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <vector> 9 #include <vector>
10 10
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 DCHECK(!IsRootLayer(layer)) << "layer: " << layer->id(); 51 DCHECK(!IsRootLayer(layer)) << "layer: " << layer->id();
52 if (EffectNodeOwner(layer)->replica_layer() == layer) 52 if (EffectNodeOwner(layer)->replica_layer() == layer)
53 return; 53 return;
54 DCHECK(!layer->mask_layer()) << "layer: " << layer->id(); 54 DCHECK(!layer->mask_layer()) << "layer: " << layer->id();
55 DCHECK(!layer->replica_layer()) << "layer: " << layer->id(); 55 DCHECK(!layer->replica_layer()) << "layer: " << layer->id();
56 } 56 }
57 57
58 #endif 58 #endif
59 59
60 template <typename LayerType> 60 template <typename LayerType>
61 void CalculateVisibleRects( 61 bool ComputeClipRectInTargetSpace(const LayerType* layer,
62 const ClipNode* clip_node,
63 const TransformTree& transform_tree,
64 int target_node_id,
65 gfx::Rect* clip_rect_in_target_space) {
66 DCHECK(layer->clip_tree_index() == clip_node->id);
67 DCHECK(clip_node->data.target_id != target_node_id);
68
69 gfx::Transform clip_to_target;
70 if (clip_node->data.target_id > target_node_id) {
71 // In this case, layer has a scroll parent. We need to keep the scale
72 // at the layer's target but remove the scale at the scroll parent's
73 // target.
74 if (transform_tree.ComputeTransformWithDestinationSublayerScale(
75 clip_node->data.target_id, target_node_id, &clip_to_target)) {
76 const TransformNode* source_node =
77 transform_tree.Node(clip_node->data.target_id);
78 if (source_node->data.sublayer_scale.x() != 0.f &&
79 source_node->data.sublayer_scale.y() != 0.f)
80 clip_to_target.Scale(1.0f / source_node->data.sublayer_scale.x(),
81 1.0f / source_node->data.sublayer_scale.y());
82 *clip_rect_in_target_space =
83 gfx::ToEnclosingRect(MathUtil::MapClippedRect(
84 clip_to_target, clip_node->data.clip_in_target_space));
85 } else {
86 return false;
87 }
88 } else {
89 if (transform_tree.ComputeTransform(clip_node->data.target_id,
90 target_node_id, &clip_to_target)) {
91 *clip_rect_in_target_space =
92 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
93 clip_to_target, clip_node->data.clip_in_target_space));
94 } else {
95 return false;
96 }
97 }
98 return true;
99 }
100
101 template <typename LayerType>
102 void CalculateClipRects(
62 const typename LayerType::LayerListType& visible_layer_list, 103 const typename LayerType::LayerListType& visible_layer_list,
63 const ClipTree& clip_tree, 104 const ClipTree& clip_tree,
64 const TransformTree& transform_tree, 105 const TransformTree& transform_tree,
65 const EffectTree& effect_tree, 106 const EffectTree& effect_tree,
66 bool non_root_surfaces_enabled) { 107 bool non_root_surfaces_enabled) {
67 for (auto& layer : visible_layer_list) { 108 for (auto& layer : visible_layer_list) {
68 gfx::Size layer_bounds = layer->bounds();
69 const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); 109 const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
70 const bool is_unclipped = clip_node->data.resets_clip && 110 // The entire layer is visible if it has copy requests.
71 !clip_node->data.applies_local_clip && 111 const EffectNode* effect_node =
72 non_root_surfaces_enabled; 112 effect_tree.Node(layer->effect_tree_index());
113 if (effect_node->data.has_copy_request &&
114 effect_node->owner_id == layer->id())
115 continue;
116
117 if (!non_root_surfaces_enabled) {
118 layer->set_clip_rect(
119 gfx::ToEnclosingRect(clip_node->data.clip_in_target_space));
120 continue;
121 }
122
73 // When both the layer and the target are unclipped, the entire layer 123 // When both the layer and the target are unclipped, the entire layer
74 // content rect is visible. 124 // content rect is visible.
75 const bool fully_visible = !clip_node->data.layers_are_clipped && 125 const bool fully_visible = !clip_node->data.layers_are_clipped &&
76 !clip_node->data.target_is_clipped && 126 !clip_node->data.target_is_clipped;
77 non_root_surfaces_enabled;
78 const TransformNode* transform_node =
79 transform_tree.Node(layer->transform_tree_index());
80 if (!is_unclipped && !fully_visible) {
81 // The entire layer is visible if it has copy requests.
82 const EffectNode* effect_node =
83 effect_tree.Node(layer->effect_tree_index());
84 if (effect_node->data.has_copy_request &&
85 effect_node->owner_id == layer->id()) {
86 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
87 continue;
88 }
89 127
90 const TransformNode* target_node = 128 if (!fully_visible) {
91 non_root_surfaces_enabled 129 const TransformNode* transform_node =
92 ? transform_tree.Node(transform_node->data.content_target_id) 130 transform_tree.Node(layer->transform_tree_index());
93 : transform_tree.Node(0); 131 int target_node_id = transform_node->data.content_target_id;
94 132
95 // The clip node stores clip rect in its target space. If required, 133 // The clip node stores clip rect in its target space.
96 // this clip rect should be mapped to the current layer's target space. 134 gfx::Rect clip_rect_in_target_space =
97 gfx::Rect clip_rect_in_target_space; 135 gfx::ToEnclosingRect(clip_node->data.clip_in_target_space);
98 gfx::Rect combined_clip_rect_in_target_space;
99 136
100 // When we only have a root surface, the clip node and the layer must 137 // If required, this clip rect should be mapped to the current layer's
101 // necessarily have the same target (the root). 138 // target space.
102 if (clip_node->data.target_id != target_node->id && 139 if (clip_node->data.target_id != target_node_id) {
103 non_root_surfaces_enabled) {
104 // In this case, layer has a clip parent or scroll parent (or shares the 140 // In this case, layer has a clip parent or scroll parent (or shares the
105 // target with an ancestor layer that has clip parent) and the clip 141 // target with an ancestor layer that has clip parent) and the clip
106 // parent's target is different from the layer's target. As the layer's 142 // parent's target is different from the layer's target. As the layer's
107 // target has unclippped descendants, it is unclippped. 143 // target has unclippped descendants, it is unclippped.
108 if (!clip_node->data.layers_are_clipped) { 144 if (!clip_node->data.layers_are_clipped)
109 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
110 continue; 145 continue;
111 } 146
112 bool success = true; 147 // Compute the clip rect in target space and store it.
113 gfx::Transform clip_to_target; 148 if (!ComputeClipRectInTargetSpace(layer, clip_node, transform_tree,
114 if (clip_node->data.target_id > target_node->id) { 149 target_node_id,
115 // In this case, layer has a scroll parent. We need to keep the scale 150 &clip_rect_in_target_space))
116 // at the layer's target but remove the scale at the scroll parent's
117 // target.
118 success = transform_tree.ComputeTransformWithDestinationSublayerScale(
119 clip_node->data.target_id, target_node->id, &clip_to_target);
120 const TransformNode* source_node =
121 transform_tree.Node(clip_node->data.target_id);
122 if (source_node->data.sublayer_scale.x() != 0.f &&
123 source_node->data.sublayer_scale.y() != 0.f)
124 clip_to_target.Scale(1.0f / source_node->data.sublayer_scale.x(),
125 1.0f / source_node->data.sublayer_scale.y());
126 } else {
127 success = transform_tree.ComputeTransform(
128 clip_node->data.target_id, target_node->id, &clip_to_target);
129 }
130 if (!success) {
131 // An animated singular transform may become non-singular during the
132 // animation, so we still need to compute a visible rect. In this
133 // situation, we treat the entire layer as visible.
134 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
135 continue; 151 continue;
136 }
137 // We use the clip node's clip_in_target_space (and not
138 // combined_clip_in_target_space) here because we want to clip
139 // with respect to clip parent's local clip and not its combined clip as
140 // the combined clip has even the clip parent's target's clip baked into
141 // it and as our target is different, we don't want to use it in our
142 // visible rect computation.
143 if (clip_node->data.target_id < target_node->id) {
144 combined_clip_rect_in_target_space =
145 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
146 clip_to_target, clip_node->data.clip_in_target_space));
147 } else {
148 combined_clip_rect_in_target_space =
149 gfx::ToEnclosingRect(MathUtil::MapClippedRect(
150 clip_to_target, clip_node->data.clip_in_target_space));
151 }
152 clip_rect_in_target_space = combined_clip_rect_in_target_space;
153 } else {
154 clip_rect_in_target_space =
155 gfx::ToEnclosingRect(clip_node->data.clip_in_target_space);
156 if (clip_node->data.target_is_clipped || !non_root_surfaces_enabled)
157 combined_clip_rect_in_target_space = gfx::ToEnclosingRect(
158 clip_node->data.combined_clip_in_target_space);
159 else
160 combined_clip_rect_in_target_space = clip_rect_in_target_space;
161 } 152 }
162 153
163 if (!clip_rect_in_target_space.IsEmpty()) { 154 if (!clip_rect_in_target_space.IsEmpty()) {
164 layer->set_clip_rect(clip_rect_in_target_space); 155 layer->set_clip_rect(clip_rect_in_target_space);
165 } else { 156 } else {
166 layer->set_clip_rect(gfx::Rect()); 157 layer->set_clip_rect(gfx::Rect());
167 } 158 }
159 }
160 }
161 }
168 162
169 // The clip rect should be intersected with layer rect in target space. 163 bool GetLayerClipRect(const scoped_refptr<Layer> layer,
170 gfx::Transform content_to_target = non_root_surfaces_enabled 164 const ClipNode* clip_node,
171 ? transform_node->data.to_target 165 const TransformTree& transform_tree,
172 : transform_node->data.to_screen; 166 int target_node_id,
167 gfx::Rect* clip_rect_in_target_space) {
168 return ComputeClipRectInTargetSpace(layer.get(), clip_node, transform_tree,
169 target_node_id,
170 clip_rect_in_target_space);
171 }
173 172
174 content_to_target.Translate(layer->offset_to_transform_parent().x(), 173 bool GetLayerClipRect(const LayerImpl* layer,
175 layer->offset_to_transform_parent().y()); 174 const ClipNode* clip_node,
176 gfx::Rect layer_content_rect = gfx::Rect(layer_bounds); 175 const TransformTree& transform_tree,
177 gfx::Rect layer_content_bounds_in_target_space = 176 int target_node_id,
178 MathUtil::MapEnclosingClippedRect(content_to_target, 177 gfx::Rect* clip_rect_in_target_space) {
179 layer_content_rect); 178 // This is equivalent of calling ComputeClipRectInTargetSpace.
180 combined_clip_rect_in_target_space.Intersect( 179 *clip_rect_in_target_space = layer->clip_rect();
181 layer_content_bounds_in_target_space); 180 return transform_tree.Node(target_node_id)->data.ancestors_are_invertible;
182 if (combined_clip_rect_in_target_space.IsEmpty()) { 181 }
183 layer->set_visible_layer_rect(gfx::Rect()); 182
184 continue; 183 template <typename LayerType>
184 void CalculateVisibleRects(
185 const typename LayerType::LayerListType& visible_layer_list,
186 const ClipTree& clip_tree,
187 const TransformTree& transform_tree,
188 const EffectTree& effect_tree,
189 bool non_root_surfaces_enabled) {
190 for (auto& layer : visible_layer_list) {
191 gfx::Size layer_bounds = layer->bounds();
192
193 const EffectNode* effect_node =
194 effect_tree.Node(layer->effect_tree_index());
195 if (effect_node->data.has_copy_request &&
196 effect_node->owner_id == layer->id()) {
197 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
198 continue;
199 }
200
201 const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
202 const TransformNode* transform_node =
203 transform_tree.Node(layer->transform_tree_index());
204 if (!non_root_surfaces_enabled) {
205 // When we only have a root surface, the clip node and the layer must
206 // necessarily have the same target (the root).
207 if (transform_node->data.ancestors_are_invertible) {
208 gfx::Rect combined_clip_rect_in_target_space =
209 gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space);
210 gfx::Transform target_to_content;
211 target_to_content.Translate(-layer->offset_to_transform_parent().x(),
212 -layer->offset_to_transform_parent().y());
213 target_to_content.PreconcatTransform(transform_node->data.from_screen);
214
215 gfx::Rect visible_rect = MathUtil::ProjectEnclosingClippedRect(
216 target_to_content, combined_clip_rect_in_target_space);
217 visible_rect.Intersect(gfx::Rect(layer_bounds));
218 layer->set_visible_layer_rect(visible_rect);
219 } else {
220 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
185 } 221 }
222 continue;
223 }
186 224
187 // If the layer is fully contained within the clip, treat it as fully 225 // When both the layer and the target are unclipped, the entire layer
188 // visible. Since clip_rect_in_target_space has already been intersected 226 // content rect is visible.
189 // with layer_content_bounds_in_target_space, the layer is fully contained 227 const bool fully_visible = !clip_node->data.layers_are_clipped &&
190 // within the clip iff these rects are equal. 228 !clip_node->data.target_is_clipped;
191 if (combined_clip_rect_in_target_space == 229
192 layer_content_bounds_in_target_space) { 230 if (fully_visible) {
231 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
232 continue;
233 }
234
235 int target_node_id = transform_node->data.content_target_id;
236
237 // The clip node stores clip rect in its target space. If required,
238 // this clip rect should be mapped to the current layer's target space.
239 gfx::Rect combined_clip_rect_in_target_space;
240
241 if (clip_node->data.target_id != target_node_id) {
242 // In this case, layer has a clip parent or scroll parent (or shares the
243 // target with an ancestor layer that has clip parent) and the clip
244 // parent's target is different from the layer's target. As the layer's
245 // target has unclippped descendants, it is unclippped.
246 if (!clip_node->data.layers_are_clipped) {
193 layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); 247 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
194 continue; 248 continue;
195 } 249 }
196 250
197 gfx::Transform target_to_content; 251 // We use the clip node's clip_in_target_space (and not
198 gfx::Transform target_to_layer; 252 // combined_clip_in_target_space) here because we want to clip
199 bool success = true; 253 // with respect to clip parent's local clip and not its combined clip as
200 if (transform_node->data.ancestors_are_invertible) { 254 // the combined clip has even the clip parent's target's clip baked into
201 target_to_layer = non_root_surfaces_enabled 255 // it and as our target is different, we don't want to use it in our
202 ? transform_node->data.from_target 256 // visible rect computation.
203 : transform_node->data.from_screen; 257 if (!GetLayerClipRect(layer, clip_node, transform_tree, target_node_id,
258 &combined_clip_rect_in_target_space)) {
259 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
260 continue;
261 }
262 } else {
263 if (clip_node->data.target_is_clipped) {
264 combined_clip_rect_in_target_space =
265 gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space);
204 } else { 266 } else {
205 success = transform_tree.ComputeTransformWithSourceSublayerScale( 267 combined_clip_rect_in_target_space =
206 target_node->id, transform_node->id, &target_to_layer); 268 gfx::ToEnclosingRect(clip_node->data.clip_in_target_space);
207 } 269 }
270 }
208 271
209 if (!success) { 272 // The clip rect should be intersected with layer rect in target space.
273 gfx::Transform content_to_target = transform_node->data.to_target;
274 content_to_target.Translate(layer->offset_to_transform_parent().x(),
275 layer->offset_to_transform_parent().y());
276 gfx::Rect layer_content_rect = gfx::Rect(layer_bounds);
277 gfx::Rect layer_content_bounds_in_target_space =
278 MathUtil::MapEnclosingClippedRect(content_to_target,
279 layer_content_rect);
280 combined_clip_rect_in_target_space.Intersect(
281 layer_content_bounds_in_target_space);
282 if (combined_clip_rect_in_target_space.IsEmpty()) {
283 layer->set_visible_layer_rect(gfx::Rect());
284 continue;
285 }
286
287 // If the layer is fully contained within the clip, treat it as fully
288 // visible. Since clip_rect_in_target_space has already been intersected
289 // with layer_content_bounds_in_target_space, the layer is fully contained
290 // within the clip iff these rects are equal.
291 if (combined_clip_rect_in_target_space ==
292 layer_content_bounds_in_target_space) {
293 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
294 continue;
295 }
296
297 gfx::Transform target_to_layer;
298 if (transform_node->data.ancestors_are_invertible) {
299 target_to_layer = transform_node->data.from_target;
300 } else {
301 if (!transform_tree.ComputeTransformWithSourceSublayerScale(
302 target_node_id, transform_node->id, &target_to_layer)) {
210 // An animated singular transform may become non-singular during the 303 // An animated singular transform may become non-singular during the
211 // animation, so we still need to compute a visible rect. In this 304 // animation, so we still need to compute a visible rect. In this
212 // situation, we treat the entire layer as visible. 305 // situation, we treat the entire layer as visible.
213 layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); 306 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
214 continue; 307 continue;
215 } 308 }
309 }
216 310
217 target_to_content.Translate(-layer->offset_to_transform_parent().x(), 311 gfx::Transform target_to_content;
218 -layer->offset_to_transform_parent().y()); 312 target_to_content.Translate(-layer->offset_to_transform_parent().x(),
219 target_to_content.PreconcatTransform(target_to_layer); 313 -layer->offset_to_transform_parent().y());
314 target_to_content.PreconcatTransform(target_to_layer);
220 315
221 gfx::Rect visible_rect = MathUtil::ProjectEnclosingClippedRect( 316 gfx::Rect visible_rect = MathUtil::ProjectEnclosingClippedRect(
222 target_to_content, combined_clip_rect_in_target_space); 317 target_to_content, combined_clip_rect_in_target_space);
223 318 visible_rect.Intersect(gfx::Rect(layer_bounds));
224 visible_rect.Intersect(gfx::Rect(layer_bounds)); 319 layer->set_visible_layer_rect(visible_rect);
225
226 layer->set_visible_layer_rect(visible_rect);
227 } else {
228 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
229 }
230 } 320 }
231 } 321 }
232 322
233 static bool HasSingularTransform(int transform_tree_index, 323 static bool HasSingularTransform(int transform_tree_index,
234 const TransformTree& tree) { 324 const TransformTree& tree) {
235 const TransformNode* node = tree.Node(transform_tree_index); 325 const TransformNode* node = tree.Node(transform_tree_index);
236 return !node->data.is_invertible || !node->data.ancestors_are_invertible; 326 return !node->data.is_invertible || !node->data.ancestors_are_invertible;
237 } 327 }
238 328
239 template <typename LayerType> 329 template <typename LayerType>
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 UpdateRenderTarget(&property_trees->effect_tree, 853 UpdateRenderTarget(&property_trees->effect_tree,
764 property_trees->non_root_surfaces_enabled); 854 property_trees->non_root_surfaces_enabled);
765 ComputeTransforms(&property_trees->transform_tree); 855 ComputeTransforms(&property_trees->transform_tree);
766 ComputeClips(&property_trees->clip_tree, property_trees->transform_tree, 856 ComputeClips(&property_trees->clip_tree, property_trees->transform_tree,
767 can_render_to_separate_surface); 857 can_render_to_separate_surface);
768 ComputeEffects(&property_trees->effect_tree); 858 ComputeEffects(&property_trees->effect_tree);
769 859
770 FindLayersThatNeedUpdates(root_layer->layer_tree_impl(), 860 FindLayersThatNeedUpdates(root_layer->layer_tree_impl(),
771 property_trees->transform_tree, 861 property_trees->transform_tree,
772 property_trees->effect_tree, visible_layer_list); 862 property_trees->effect_tree, visible_layer_list);
863 CalculateClipRects<LayerImpl>(*visible_layer_list, property_trees->clip_tree,
864 property_trees->transform_tree,
865 property_trees->effect_tree,
866 can_render_to_separate_surface);
773 CalculateVisibleRects<LayerImpl>( 867 CalculateVisibleRects<LayerImpl>(
774 *visible_layer_list, property_trees->clip_tree, 868 *visible_layer_list, property_trees->clip_tree,
775 property_trees->transform_tree, property_trees->effect_tree, 869 property_trees->transform_tree, property_trees->effect_tree,
776 can_render_to_separate_surface); 870 can_render_to_separate_surface);
777 } 871 }
778 872
779 void UpdatePropertyTrees(PropertyTrees* property_trees, 873 void UpdatePropertyTrees(PropertyTrees* property_trees,
780 bool can_render_to_separate_surface) { 874 bool can_render_to_separate_surface) {
781 if (property_trees->non_root_surfaces_enabled != 875 if (property_trees->non_root_surfaces_enabled !=
782 can_render_to_separate_surface) { 876 can_render_to_separate_surface) {
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
1214 void UpdateElasticOverscroll(PropertyTrees* property_trees, 1308 void UpdateElasticOverscroll(PropertyTrees* property_trees,
1215 const Layer* overscroll_elasticity_layer, 1309 const Layer* overscroll_elasticity_layer,
1216 const gfx::Vector2dF& elastic_overscroll) { 1310 const gfx::Vector2dF& elastic_overscroll) {
1217 UpdateElasticOverscrollInternal(property_trees, overscroll_elasticity_layer, 1311 UpdateElasticOverscrollInternal(property_trees, overscroll_elasticity_layer,
1218 elastic_overscroll); 1312 elastic_overscroll);
1219 } 1313 }
1220 1314
1221 } // namespace draw_property_utils 1315 } // namespace draw_property_utils
1222 1316
1223 } // namespace cc 1317 } // namespace cc
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698