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

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

Issue 2655233006: cc : Clean up cc clip tree (Closed)
Patch Set: blink_tests Created 3 years, 9 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
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 16 matching lines...) Expand all
27 namespace { 27 namespace {
28 28
29 static bool IsRootLayer(const Layer* layer) { 29 static bool IsRootLayer(const Layer* layer) {
30 return !layer->parent(); 30 return !layer->parent();
31 } 31 }
32 32
33 static bool IsRootLayer(const LayerImpl* layer) { 33 static bool IsRootLayer(const LayerImpl* layer) {
34 return layer->layer_tree_impl()->IsRootLayer(layer); 34 return layer->layer_tree_impl()->IsRootLayer(layer);
35 } 35 }
36 36
37 static const EffectNode* ContentsTargetEffectNode(
38 const int effect_tree_index,
39 const EffectTree& effect_tree) {
40 const EffectNode* effect_node = effect_tree.Node(effect_tree_index);
41 return effect_tree.GetRenderSurface(effect_tree_index)
42 ? effect_node
43 : effect_tree.Node(effect_node->target_id);
44 }
45
46 static bool ConvertRectBetweenSurfaceSpaces(const PropertyTrees* property_trees, 37 static bool ConvertRectBetweenSurfaceSpaces(const PropertyTrees* property_trees,
47 int source_effect_id, 38 int source_effect_id,
48 int dest_effect_id, 39 int dest_effect_id,
49 gfx::RectF clip_in_source_space, 40 gfx::RectF clip_in_source_space,
50 gfx::RectF* clip_in_dest_space) { 41 gfx::RectF* clip_in_dest_space) {
51 const EffectNode* source_effect_node = 42 const EffectNode* source_effect_node =
52 property_trees->effect_tree.Node(source_effect_id); 43 property_trees->effect_tree.Node(source_effect_id);
53 int source_transform_id = source_effect_node->transform_id; 44 int source_transform_id = source_effect_node->transform_id;
54 const EffectNode* dest_effect_node = 45 const EffectNode* dest_effect_node =
55 property_trees->effect_tree.Node(dest_effect_id); 46 property_trees->effect_tree.Node(dest_effect_id);
(...skipping 14 matching lines...) Expand all
70 PostConcatSurfaceContentsScale(dest_effect_node, &source_to_dest); 61 PostConcatSurfaceContentsScale(dest_effect_node, &source_to_dest);
71 *clip_in_dest_space = 62 *clip_in_dest_space =
72 MathUtil::ProjectClippedRect(source_to_dest, clip_in_source_space); 63 MathUtil::ProjectClippedRect(source_to_dest, clip_in_source_space);
73 } else { 64 } else {
74 return false; 65 return false;
75 } 66 }
76 } 67 }
77 return true; 68 return true;
78 } 69 }
79 70
80 bool ComputeClipRectInTargetSpace(const LayerImpl* layer,
81 const ClipNode* clip_node,
82 const PropertyTrees* property_trees,
83 int target_node_id,
84 bool for_visible_rect_calculation,
85 gfx::RectF* clip_rect_in_target_space) {
86 DCHECK(layer->clip_tree_index() == clip_node->id);
87 DCHECK(clip_node->target_transform_id != target_node_id);
88
89 const EffectTree& effect_tree = property_trees->effect_tree;
90 const EffectNode* target_effect_node =
91 ContentsTargetEffectNode(layer->effect_tree_index(), effect_tree);
92 gfx::Transform clip_to_target;
93 // We use the local clip for clip rect calculation and combined clip for
94 // visible rect calculation.
95 gfx::RectF clip_from_clip_node =
96 for_visible_rect_calculation ? clip_node->combined_clip_in_target_space
97 : clip_node->clip_in_target_space;
98
99 return ConvertRectBetweenSurfaceSpaces(
100 property_trees, clip_node->target_effect_id, target_effect_node->id,
101 clip_from_clip_node, clip_rect_in_target_space);
102 }
103
104 struct ConditionalClip {
105 bool is_clipped;
106 gfx::RectF clip_rect;
107 };
108
109 static ConditionalClip ComputeTargetRectInLocalSpace( 71 static ConditionalClip ComputeTargetRectInLocalSpace(
110 gfx::RectF rect, 72 gfx::RectF rect,
111 const PropertyTrees* property_trees, 73 const PropertyTrees* property_trees,
112 int target_transform_id, 74 int target_transform_id,
113 int local_transform_id, 75 int local_transform_id,
114 const int target_effect_id) { 76 const int target_effect_id) {
115 gfx::Transform target_to_local; 77 gfx::Transform target_to_local;
116 bool success = property_trees->GetFromTarget( 78 const TransformNode* node =
117 local_transform_id, target_effect_id, &target_to_local); 79 property_trees->transform_tree.Node(local_transform_id);
118 if (!success) 80 if (target_transform_id == TransformTree::kRootNodeId &&
119 // If transform is not invertible, cannot apply clip. 81 node->ancestors_are_invertible) {
120 return ConditionalClip{false, gfx::RectF()}; 82 target_to_local = property_trees->transform_tree.FromScreen(node->id);
83 } else {
84 bool success = property_trees->GetFromTarget(
85 local_transform_id, target_effect_id, &target_to_local);
86 if (!success)
87 // If transform is not invertible, cannot apply clip.
88 return ConditionalClip{false, gfx::RectF()};
89 }
121 90
122 if (target_transform_id > local_transform_id) 91 if (target_transform_id > local_transform_id)
123 return ConditionalClip{true, // is_clipped. 92 return ConditionalClip{true, // is_clipped.
124 MathUtil::MapClippedRect(target_to_local, rect)}; 93 MathUtil::MapClippedRect(target_to_local, rect)};
125 94
126 return ConditionalClip{true, // is_clipped. 95 return ConditionalClip{true, // is_clipped.
127 MathUtil::ProjectClippedRect(target_to_local, rect)}; 96 MathUtil::ProjectClippedRect(target_to_local, rect)};
128 } 97 }
129 98
130 static ConditionalClip ComputeLocalRectInTargetSpace( 99 static ConditionalClip ComputeLocalRectInTargetSpace(
131 gfx::RectF rect, 100 gfx::RectF rect,
132 const PropertyTrees* property_trees, 101 const PropertyTrees* property_trees,
133 int current_transform_id, 102 int current_transform_id,
134 int target_transform_id, 103 int target_transform_id,
135 int target_effect_id) { 104 int target_effect_id) {
136 gfx::Transform current_to_target; 105 gfx::Transform current_to_target;
137 if (!property_trees->GetToTarget(current_transform_id, target_effect_id, 106 if (target_transform_id == TransformTree::kRootNodeId) {
weiliangc 2017/03/14 22:04:30 Is it possible to make this logic part of GetToTar
jaydasika 2017/03/16 20:33:31 Ah, that makes sense, I added this to speed up tra
138 &current_to_target)) { 107 current_to_target =
108 property_trees->transform_tree.ToScreen(current_transform_id);
109 } else if (!property_trees->GetToTarget(
110 current_transform_id, target_effect_id, &current_to_target)) {
139 // If transform is not invertible, cannot apply clip. 111 // If transform is not invertible, cannot apply clip.
140 return ConditionalClip{false, gfx::RectF()}; 112 return ConditionalClip{false, gfx::RectF()};
141 } 113 }
142 114
143 if (current_transform_id > target_transform_id) 115 if (current_transform_id > target_transform_id)
144 return ConditionalClip{true, // is_clipped. 116 return ConditionalClip{true, // is_clipped.
145 MathUtil::MapClippedRect(current_to_target, rect)}; 117 MathUtil::MapClippedRect(current_to_target, rect)};
146 118
147 return ConditionalClip{true, // is_clipped. 119 return ConditionalClip{true, // is_clipped.
148 MathUtil::ProjectClippedRect(current_to_target, rect)}; 120 MathUtil::ProjectClippedRect(current_to_target, rect)};
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 183
212 // Put the expanded clip back into the original target space. 184 // Put the expanded clip back into the original target space.
213 success = ConvertRectBetweenSurfaceSpaces( 185 success = ConvertRectBetweenSurfaceSpaces(
214 property_trees, expanding_effect_node->id, target_id, 186 property_trees, expanding_effect_node->id, target_id,
215 expanded_clip_in_expanding_space, accumulated_clip); 187 expanded_clip_in_expanding_space, accumulated_clip);
216 // If transform is not invertible, no clip will be applied. 188 // If transform is not invertible, no clip will be applied.
217 if (!success) 189 if (!success)
218 return false; 190 return false;
219 return true; 191 return true;
220 } 192 }
221 case ClipNode::ClipType::NONE:
222 return true;
223 } 193 }
224 NOTREACHED(); 194 NOTREACHED();
225 return true; 195 return true;
226 } 196 }
227 197
228 static ConditionalClip ComputeAccumulatedClip( 198 static ConditionalClip ComputeAccumulatedClip(PropertyTrees* property_trees,
229 const PropertyTrees* property_trees, 199 bool include_expanding_clips,
230 bool include_viewport_clip, 200 int local_clip_id,
231 bool include_expanding_clips, 201 int target_id) {
232 int local_clip_id, 202 ClipRectData& cached_data =
233 int target_id) { 203 property_trees->FetchClipRectFromCache(local_clip_id, target_id);
234 DCHECK(!include_viewport_clip || 204 if (cached_data.target_id != EffectTree::kInvalidNodeId) {
235 target_id == EffectTree::kContentsRootNodeId); 205 // Cache hit
206 return cached_data.clip;
207 }
208 cached_data.target_id = target_id;
209
236 const ClipTree& clip_tree = property_trees->clip_tree; 210 const ClipTree& clip_tree = property_trees->clip_tree;
211 const ClipNode* clip_node = clip_tree.Node(local_clip_id);
237 const EffectTree& effect_tree = property_trees->effect_tree; 212 const EffectTree& effect_tree = property_trees->effect_tree;
238
239 const ClipNode* clip_node = clip_tree.Node(local_clip_id);
240 const EffectNode* target_node = effect_tree.Node(target_id); 213 const EffectNode* target_node = effect_tree.Node(target_id);
241 int target_transform_id = target_node->transform_id; 214 int target_transform_id = target_node->transform_id;
242 215
216 bool cache_hit = false;
217 ConditionalClip cached_clip = ConditionalClip{false, gfx::RectF()};
218 ConditionalClip unclipped = ConditionalClip{false, gfx::RectF()};
219
243 // Collect all the clips that need to be accumulated. 220 // Collect all the clips that need to be accumulated.
244 std::stack<const ClipNode*> parent_chain; 221 std::stack<const ClipNode*, std::vector<const ClipNode*>> parent_chain;
245 222
246 // If target is not direct ancestor of clip, this will find least common 223 // If target is not direct ancestor of clip, this will find least common
247 // ancestor between the target and the clip. 224 // ancestor between the target and the clip.
248 while (target_node->clip_id > clip_node->id || 225 while (target_node->clip_id > clip_node->id ||
249 target_node->has_unclipped_descendants) { 226 target_node->has_unclipped_descendants) {
250 target_node = effect_tree.Node(target_node->target_id); 227 target_node = effect_tree.Node(target_node->target_id);
251 } 228 }
252 229
253 // Collect clip nodes up to the least common ancestor. 230 // Collect clip nodes up to the least common ancestor or till we get a cache
231 // hit.
254 while (target_node->clip_id < clip_node->id) { 232 while (target_node->clip_id < clip_node->id) {
233 if (parent_chain.size() > 0) {
234 // Search the cache.
235 for (auto& data : clip_node->cached_clip_rects) {
236 if (data.target_id == target_id) {
237 cache_hit = true;
238 cached_clip = data.clip;
239 }
240 }
241 }
255 parent_chain.push(clip_node); 242 parent_chain.push(clip_node);
256 clip_node = clip_tree.parent(clip_node); 243 clip_node = clip_tree.parent(clip_node);
257 } 244 }
258 DCHECK_EQ(target_node->clip_id, clip_node->id);
259 245
260 if (!include_viewport_clip && parent_chain.size() == 0) { 246 if (parent_chain.size() == 0) {
261 // There aren't any clips to apply. 247 // No accumulated clip nodes.
262 return ConditionalClip{false, gfx::RectF()}; 248 cached_data.clip = unclipped;
249 return unclipped;
263 } 250 }
264 251
265 if (!include_viewport_clip) { 252 clip_node = parent_chain.top();
266 clip_node = parent_chain.top(); 253 parent_chain.pop();
267 parent_chain.pop(); 254
255 gfx::RectF accumulated_clip;
256 if (cache_hit && cached_clip.is_clipped) {
257 // Apply the first clip in parent_chain to the cached clip.
258 accumulated_clip = cached_clip.clip_rect;
259 bool success = ApplyClipNodeToAccumulatedClip(
260 property_trees, include_expanding_clips, target_id, target_transform_id,
261 clip_node, &accumulated_clip);
262 if (!success) {
263 // Singular transform
264 cached_data.clip = unclipped;
265 return unclipped;
266 }
267 } else {
268 // No cache hit or the cached clip has no clip to apply. We need to find
269 // the first clip that applies clip as there is no clip to expand.
270 while (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP &&
271 parent_chain.size() > 0) {
272 clip_node = parent_chain.top();
273 parent_chain.pop();
274 }
275
276 if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) {
277 // No clip to apply.
278 cached_data.clip = unclipped;
279 return unclipped;
280 }
281 ConditionalClip current_clip = ComputeCurrentClip(
282 clip_node, property_trees, target_transform_id, target_id);
283 if (!current_clip.is_clipped) {
284 // Singular transform
285 cached_data.clip = unclipped;
286 return unclipped;
287 }
288 accumulated_clip = current_clip.clip_rect;
268 } 289 }
269 290
270 // Find the first clip in the chain that we need to apply. 291 // Apply remaining clips
271 while (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP &&
272 parent_chain.size() > 0) {
273 clip_node = parent_chain.top();
274 parent_chain.pop();
275 }
276
277 if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) {
278 // No clip node applying clip in between.
279 return ConditionalClip{false, gfx::RectF()};
280 }
281
282 ConditionalClip current_clip = ComputeCurrentClip(
283 clip_node, property_trees, target_transform_id, target_id);
284
285 // If transform is not invertible, no clip will be applied.
286 if (!current_clip.is_clipped)
287 return ConditionalClip{false, gfx::RectF()};
288 gfx::RectF accumulated_clip = current_clip.clip_rect;
289
290 while (parent_chain.size() > 0) { 292 while (parent_chain.size() > 0) {
291 clip_node = parent_chain.top(); 293 clip_node = parent_chain.top();
292 parent_chain.pop(); 294 parent_chain.pop();
293 bool success = ApplyClipNodeToAccumulatedClip( 295 bool success = ApplyClipNodeToAccumulatedClip(
294 property_trees, include_expanding_clips, target_id, target_transform_id, 296 property_trees, include_expanding_clips, target_id, target_transform_id,
295 clip_node, &accumulated_clip); 297 clip_node, &accumulated_clip);
296 298 if (!success) {
297 // Failure to apply the clip means we encountered an uninvertible transform, 299 // Singular transform
298 // so no clip will be applied. 300 cached_data.clip = unclipped;
299 if (!success) 301 return unclipped;
300 return ConditionalClip{false /* is_clipped */, gfx::RectF()}; 302 }
301 } 303 }
302 304
303 return ConditionalClip{true /* is_clipped */, accumulated_clip.IsEmpty() 305 ConditionalClip clip = ConditionalClip{
304 ? gfx::RectF() 306 true /* is_clipped */,
305 : accumulated_clip}; 307 accumulated_clip.IsEmpty() ? gfx::RectF() : accumulated_clip};
306 } 308 cached_data.clip = clip;
307 309 return clip;
308 static gfx::RectF ComputeAccumulatedClipInRootSpaceForVisibleRect(
309 const PropertyTrees* property_trees,
310 int local_clip_id) {
311 const int root_effect_id = EffectTree::kContentsRootNodeId;
312 bool include_viewport_clip = true;
313 bool include_expanding_clips = true;
314 ConditionalClip accumulated_clip = ComputeAccumulatedClip(
315 property_trees, include_viewport_clip, include_expanding_clips,
316 local_clip_id, root_effect_id);
317 DCHECK(accumulated_clip.is_clipped);
318 return accumulated_clip.clip_rect;
319 }
320
321 void CalculateClipRects(const std::vector<LayerImpl*>& visible_layer_list,
322 const PropertyTrees* property_trees,
323 bool non_root_surfaces_enabled) {
324 const ClipTree& clip_tree = property_trees->clip_tree;
325 for (auto* layer : visible_layer_list) {
326 const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
327 bool layer_needs_clip_rect =
328 non_root_surfaces_enabled
329 ? clip_node->layers_are_clipped
330 : clip_node->layers_are_clipped_when_surfaces_disabled;
331 if (!layer_needs_clip_rect) {
332 layer->set_clip_rect(gfx::Rect());
333 continue;
334 }
335 if (!non_root_surfaces_enabled) {
336 layer->set_clip_rect(
337 gfx::ToEnclosingRect(clip_node->clip_in_target_space));
338 continue;
339 }
340
341 const TransformTree& transform_tree = property_trees->transform_tree;
342 const TransformNode* transform_node =
343 transform_tree.Node(layer->transform_tree_index());
344 int target_node_id = transform_tree.ContentTargetId(transform_node->id);
345
346 // The clip node stores clip rect in its target space.
347 gfx::RectF clip_rect_in_target_space = clip_node->clip_in_target_space;
348
349 // If required, this clip rect should be mapped to the current layer's
350 // target space.
351 if (clip_node->target_transform_id != target_node_id) {
352 // In this case, layer has a clip parent or scroll parent (or shares the
353 // target with an ancestor layer that has clip parent) and the clip
354 // parent's target is different from the layer's target. As the layer's
355 // target has unclippped descendants, it is unclippped.
356 if (!clip_node->layers_are_clipped)
357 continue;
358
359 // Compute the clip rect in target space and store it.
360 bool for_visible_rect_calculation = false;
361 if (!ComputeClipRectInTargetSpace(
362 layer, clip_node, property_trees, target_node_id,
363 for_visible_rect_calculation, &clip_rect_in_target_space))
364 continue;
365 }
366
367 if (!clip_rect_in_target_space.IsEmpty()) {
368 layer->set_clip_rect(gfx::ToEnclosingRect(clip_rect_in_target_space));
369 } else {
370 layer->set_clip_rect(gfx::Rect());
371 }
372 }
373 }
374
375 void CalculateVisibleRects(const LayerImplList& visible_layer_list,
376 const PropertyTrees* property_trees,
377 bool non_root_surfaces_enabled) {
378 const EffectTree& effect_tree = property_trees->effect_tree;
379 const TransformTree& transform_tree = property_trees->transform_tree;
380 const ClipTree& clip_tree = property_trees->clip_tree;
381 for (auto* layer : visible_layer_list) {
382 gfx::Size layer_bounds = layer->bounds();
383
384 int effect_ancestor_with_copy_request =
385 effect_tree.ClosestAncestorWithCopyRequest(layer->effect_tree_index());
386 if (effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId) {
387 // Non root copy request.
388 bool include_viewport_clip = false;
389 bool include_expanding_clips = true;
390 ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip(
391 property_trees, include_viewport_clip, include_expanding_clips,
392 layer->clip_tree_index(), effect_ancestor_with_copy_request);
393 if (!accumulated_clip_rect.is_clipped) {
394 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
395 continue;
396 }
397
398 gfx::RectF accumulated_clip_in_copy_request_space =
399 accumulated_clip_rect.clip_rect;
400
401 const EffectNode* copy_request_effect_node =
402 effect_tree.Node(effect_ancestor_with_copy_request);
403 ConditionalClip clip_in_layer_space = ComputeTargetRectInLocalSpace(
404 accumulated_clip_in_copy_request_space, property_trees,
405 copy_request_effect_node->transform_id, layer->transform_tree_index(),
406 copy_request_effect_node->id);
407
408 if (clip_in_layer_space.is_clipped) {
409 gfx::RectF clip_rect = clip_in_layer_space.clip_rect;
410 clip_rect.Offset(-layer->offset_to_transform_parent());
411 gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_rect);
412 visible_rect.Intersect(gfx::Rect(layer_bounds));
413 layer->set_visible_layer_rect(visible_rect);
414 } else {
415 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
416 }
417 continue;
418 }
419
420 const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
421 const TransformNode* transform_node =
422 transform_tree.Node(layer->transform_tree_index());
423 if (!non_root_surfaces_enabled) {
424 // When we only have a root surface, the clip node and the layer must
425 // necessarily have the same target (the root).
426 if (transform_node->ancestors_are_invertible) {
427 gfx::RectF combined_clip_rect_in_target_space =
428 clip_node->combined_clip_in_target_space;
429 gfx::Transform target_to_content;
430 target_to_content.Translate(-layer->offset_to_transform_parent().x(),
431 -layer->offset_to_transform_parent().y());
432 target_to_content.PreconcatTransform(
433 transform_tree.FromScreen(transform_node->id));
434
435 gfx::Rect visible_rect =
436 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
437 target_to_content, combined_clip_rect_in_target_space));
438 visible_rect.Intersect(gfx::Rect(layer_bounds));
439 layer->set_visible_layer_rect(visible_rect);
440 } else {
441 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
442 }
443 continue;
444 }
445
446 // When both the layer and the target are unclipped, we only have to apply
447 // the viewport clip.
448 const bool fully_visible =
449 !clip_node->layers_are_clipped &&
450 !effect_tree.Node(clip_node->target_effect_id)->surface_is_clipped;
451
452 if (fully_visible) {
453 if (!transform_node->ancestors_are_invertible) {
454 // An animated singular transform may become non-singular during the
455 // animation, so we still need to compute a visible rect. In this
456 // situation, we treat the entire layer as visible.
457 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
458 } else {
459 gfx::Transform from_screen;
460 from_screen.Translate(-layer->offset_to_transform_parent().x(),
461 -layer->offset_to_transform_parent().y());
462 from_screen.PreconcatTransform(
463 property_trees->transform_tree.FromScreen(transform_node->id));
464 gfx::Rect visible_rect =
465 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
466 from_screen, property_trees->clip_tree.ViewportClip()));
467 visible_rect.Intersect(gfx::Rect(layer_bounds));
468 layer->set_visible_layer_rect(visible_rect);
469 }
470 continue;
471 }
472
473 int target_node_id = transform_tree.ContentTargetId(transform_node->id);
474
475 // The clip node stores clip rect in its target space. If required,
476 // this clip rect should be mapped to the current layer's target space.
477 gfx::RectF combined_clip_rect_in_target_space;
478
479 if (clip_node->target_transform_id != target_node_id) {
480 // In this case, layer has a clip parent or scroll parent (or shares the
481 // target with an ancestor layer that has clip parent) and the clip
482 // parent's target is different from the layer's target. As the layer's
483 // target has unclippped descendants, it is unclippped.
484 if (!clip_node->layers_are_clipped) {
485 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
486 continue;
487 }
488
489 bool for_visible_rect_calculation = true;
490 if (!ComputeClipRectInTargetSpace(layer, clip_node, property_trees,
491 target_node_id,
492 for_visible_rect_calculation,
493 &combined_clip_rect_in_target_space)) {
494 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
495 continue;
496 }
497 } else {
498 combined_clip_rect_in_target_space =
499 clip_node->combined_clip_in_target_space;
500 }
501
502 // The clip rect should be intersected with layer rect in target space.
503 gfx::Transform content_to_target;
504 property_trees->GetToTarget(transform_node->id,
505 layer->render_target_effect_tree_index(),
506 &content_to_target);
507 content_to_target.Translate(layer->offset_to_transform_parent().x(),
508 layer->offset_to_transform_parent().y());
509 gfx::Rect layer_content_rect = gfx::Rect(layer_bounds);
510 gfx::RectF layer_content_bounds_in_target_space = MathUtil::MapClippedRect(
511 content_to_target, gfx::RectF(layer_content_rect));
512 // If the layer is fully contained within the clip, treat it as fully
513 // visible.
514 if (!layer_content_bounds_in_target_space.IsEmpty() &&
515 combined_clip_rect_in_target_space.Contains(
516 layer_content_bounds_in_target_space)) {
517 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
518 continue;
519 }
520
521 combined_clip_rect_in_target_space.Intersect(
522 layer_content_bounds_in_target_space);
523 if (combined_clip_rect_in_target_space.IsEmpty()) {
524 layer->set_visible_layer_rect(gfx::Rect());
525 continue;
526 }
527
528 gfx::Transform target_to_layer;
529 const EffectNode* target_effect_node =
530 ContentsTargetEffectNode(layer->effect_tree_index(), effect_tree);
531 bool success = property_trees->GetFromTarget(
532 transform_node->id, target_effect_node->id, &target_to_layer);
533 if (!success) {
534 // An animated singular transform may become non-singular during the
535 // animation, so we still need to compute a visible rect. In this
536 // situation, we treat the entire layer as visible.
537 layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
538 continue;
539 }
540 gfx::Transform target_to_content;
541 target_to_content.Translate(-layer->offset_to_transform_parent().x(),
542 -layer->offset_to_transform_parent().y());
543 target_to_content.PreconcatTransform(target_to_layer);
544
545 gfx::Rect visible_rect = gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
546 target_to_content, combined_clip_rect_in_target_space));
547 visible_rect.Intersect(gfx::Rect(layer_bounds));
548 layer->set_visible_layer_rect(visible_rect);
549 }
550 } 310 }
551 311
552 static bool HasSingularTransform(int transform_tree_index, 312 static bool HasSingularTransform(int transform_tree_index,
553 const TransformTree& tree) { 313 const TransformTree& tree) {
554 const TransformNode* node = tree.Node(transform_tree_index); 314 const TransformNode* node = tree.Node(transform_tree_index);
555 return !node->is_invertible || !node->ancestors_are_invertible; 315 return !node->is_invertible || !node->ancestors_are_invertible;
556 } 316 }
557 317
558 template <typename LayerType> 318 template <typename LayerType>
559 static int TransformTreeIndexForBackfaceVisibility(LayerType* layer, 319 static int TransformTreeIndexForBackfaceVisibility(LayerType* layer,
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 // backface is not visible. 406 // backface is not visible.
647 if (TransformToScreenIsKnown(layer, backface_transform_id, tree) && 407 if (TransformToScreenIsKnown(layer, backface_transform_id, tree) &&
648 !HasSingularTransform(backface_transform_id, tree) && 408 !HasSingularTransform(backface_transform_id, tree) &&
649 IsLayerBackFaceVisible(layer, backface_transform_id, property_trees)) 409 IsLayerBackFaceVisible(layer, backface_transform_id, property_trees))
650 return false; 410 return false;
651 } 411 }
652 412
653 return true; 413 return true;
654 } 414 }
655 415
656 void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl,
657 const PropertyTrees* property_trees,
658 std::vector<LayerImpl*>* visible_layer_list) {
659 const TransformTree& transform_tree = property_trees->transform_tree;
660 const EffectTree& effect_tree = property_trees->effect_tree;
661 416
662 for (auto* layer_impl : *layer_tree_impl) {
663 if (!IsRootLayer(layer_impl) &&
664 LayerShouldBeSkipped(layer_impl, transform_tree, effect_tree))
665 continue;
666
667 bool layer_is_drawn =
668 effect_tree.Node(layer_impl->effect_tree_index())->is_drawn;
669
670 if (LayerNeedsUpdate(layer_impl, layer_is_drawn, property_trees))
671 visible_layer_list->push_back(layer_impl);
672 }
673 }
674 417
675 } // namespace 418 } // namespace
676 419
677 template <typename LayerType> 420 template <typename LayerType>
678 static inline bool LayerShouldBeSkippedInternal( 421 static inline bool LayerShouldBeSkippedInternal(
679 LayerType* layer, 422 LayerType* layer,
680 const TransformTree& transform_tree, 423 const TransformTree& transform_tree,
681 const EffectTree& effect_tree) { 424 const EffectTree& effect_tree) {
682 const TransformNode* transform_node = 425 const TransformNode* transform_node =
683 transform_tree.Node(layer->transform_tree_index()); 426 transform_tree.Node(layer->transform_tree_index());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 update_layer_list->push_back(layer); 466 update_layer_list->push_back(layer);
724 } 467 }
725 468
726 // Append mask layers to the update layer list. They don't have valid 469 // Append mask layers to the update layer list. They don't have valid
727 // visible rects, so need to get added after the above calculation. 470 // visible rects, so need to get added after the above calculation.
728 if (Layer* mask_layer = layer->mask_layer()) 471 if (Layer* mask_layer = layer->mask_layer())
729 update_layer_list->push_back(mask_layer); 472 update_layer_list->push_back(mask_layer);
730 } 473 }
731 } 474 }
732 475
733 static void ResetIfHasNanCoordinate(gfx::RectF* rect) { 476 void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl,
734 if (std::isnan(rect->x()) || std::isnan(rect->y()) || 477 const PropertyTrees* property_trees,
735 std::isnan(rect->right()) || std::isnan(rect->bottom())) 478 std::vector<LayerImpl*>* visible_layer_list) {
736 *rect = gfx::RectF(); 479 const TransformTree& transform_tree = property_trees->transform_tree;
480 const EffectTree& effect_tree = property_trees->effect_tree;
481
482 for (auto* layer_impl : *layer_tree_impl) {
483 if (!IsRootLayer(layer_impl) &&
484 LayerShouldBeSkipped(layer_impl, transform_tree, effect_tree))
485 continue;
486
487 bool layer_is_drawn =
488 effect_tree.Node(layer_impl->effect_tree_index())->is_drawn;
489
490 if (LayerNeedsUpdate(layer_impl, layer_is_drawn, property_trees))
491 visible_layer_list->push_back(layer_impl);
492 }
737 } 493 }
738 494
739 void PostConcatSurfaceContentsScale(const EffectNode* effect_node, 495 void PostConcatSurfaceContentsScale(const EffectNode* effect_node,
740 gfx::Transform* transform) { 496 gfx::Transform* transform) {
741 if (!effect_node) { 497 if (!effect_node) {
742 // This can happen when PaintArtifactCompositor builds property trees as it 498 // This can happen when PaintArtifactCompositor builds property trees as it
743 // doesn't set effect ids on clip nodes. 499 // doesn't set effect ids on clip nodes.
744 return; 500 return;
745 } 501 }
746 DCHECK(effect_node->has_render_surface); 502 DCHECK(effect_node->has_render_surface);
747 transform->matrix().postScale(effect_node->surface_contents_scale.x(), 503 transform->matrix().postScale(effect_node->surface_contents_scale.x(),
748 effect_node->surface_contents_scale.y(), 1.f); 504 effect_node->surface_contents_scale.y(), 1.f);
749 } 505 }
750 506
751 void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, 507 void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node,
752 gfx::Transform* transform) { 508 gfx::Transform* transform) {
753 DCHECK(effect_node->has_render_surface); 509 DCHECK(effect_node->has_render_surface);
754 if (effect_node->surface_contents_scale.x() != 0.0 && 510 if (effect_node->surface_contents_scale.x() != 0.0 &&
755 effect_node->surface_contents_scale.y() != 0.0) 511 effect_node->surface_contents_scale.y() != 0.0)
756 transform->Scale(1.0 / effect_node->surface_contents_scale.x(), 512 transform->Scale(1.0 / effect_node->surface_contents_scale.x(),
757 1.0 / effect_node->surface_contents_scale.y()); 513 1.0 / effect_node->surface_contents_scale.y());
758 } 514 }
759 515
760 void ComputeClips(PropertyTrees* property_trees,
761 bool non_root_surfaces_enabled) {
762 ClipTree* clip_tree = &property_trees->clip_tree;
763 if (!clip_tree->needs_update())
764 return;
765 for (int i = ClipTree::kViewportNodeId;
766 i < static_cast<int>(clip_tree->size()); ++i) {
767 ClipNode* clip_node = clip_tree->Node(i);
768
769 if (clip_node->id == ClipTree::kViewportNodeId) {
770 ResetIfHasNanCoordinate(&clip_node->clip);
771 clip_node->clip_in_target_space = clip_node->clip;
772 clip_node->combined_clip_in_target_space = clip_node->clip;
773 continue;
774 }
775 const TransformTree& transform_tree = property_trees->transform_tree;
776 const EffectTree& effect_tree = property_trees->effect_tree;
777 const TransformNode* transform_node =
778 transform_tree.Node(clip_node->transform_id);
779 ClipNode* parent_clip_node = clip_tree->parent(clip_node);
780
781 bool target_is_clipped =
782 effect_tree.Node(clip_node->target_effect_id)->surface_is_clipped;
783
784 gfx::Transform parent_to_current;
785 const TransformNode* parent_target_transform_node =
786 transform_tree.Node(parent_clip_node->target_transform_id);
787 bool success = true;
788
789 // Clips must be combined in target space. We cannot, for example, combine
790 // clips in the space of the child clip. The reason is non-affine
791 // transforms. Say we have the following tree T->A->B->C, and B clips C, but
792 // draw into target T. It may be the case that A applies a perspective
793 // transform, and B and C are at different z positions. When projected into
794 // target space, the relative sizes and positions of B and C can shift.
795 // Since it's the relationship in target space that matters, that's where we
796 // must combine clips. For each clip node, we save the clip rects in its
797 // target space. So, we need to get the ancestor clip rect in the current
798 // clip node's target space.
799 gfx::RectF parent_combined_clip_in_target_space =
800 parent_clip_node->combined_clip_in_target_space;
801 gfx::RectF parent_clip_in_target_space =
802 parent_clip_node->clip_in_target_space;
803 if (parent_target_transform_node &&
804 parent_target_transform_node->id != clip_node->target_transform_id &&
805 non_root_surfaces_enabled) {
806 success &= ConvertRectBetweenSurfaceSpaces(
807 property_trees, parent_clip_node->target_effect_id,
808 clip_node->target_effect_id,
809 parent_clip_node->combined_clip_in_target_space,
810 &parent_combined_clip_in_target_space);
811 // If we can't compute a transform, it's because we had to use the inverse
812 // of a singular transform. We won't draw in this case, so there's no need
813 // to compute clips.
814 if (!success)
815 continue;
816 if (clip_node->clip_type == ClipNode::ClipType::EXPANDS_CLIP) {
817 parent_combined_clip_in_target_space =
818 gfx::RectF(clip_node->clip_expander->MapRectReverse(
819 gfx::ToEnclosingRect(parent_combined_clip_in_target_space),
820 property_trees));
821 }
822 ConvertRectBetweenSurfaceSpaces(
823 property_trees, parent_clip_node->target_effect_id,
824 clip_node->target_effect_id, parent_clip_node->clip_in_target_space,
825 &parent_clip_in_target_space);
826 }
827 // Only nodes affected by ancestor clips will have their clip adjusted due
828 // to intersecting with an ancestor clip. But, we still need to propagate
829 // the combined clip to our children because if they are clipped, they may
830 // need to clip using our parent clip and if we don't propagate it here,
831 // it will be lost.
832 if (clip_node->resets_clip && non_root_surfaces_enabled) {
833 if (clip_node->clip_type == ClipNode::ClipType::APPLIES_LOCAL_CLIP) {
834 gfx::Transform to_target;
835 property_trees->GetToTarget(clip_node->transform_id,
836 clip_node->target_effect_id, &to_target);
837 clip_node->clip_in_target_space =
838 MathUtil::MapClippedRect(to_target, clip_node->clip);
839 ResetIfHasNanCoordinate(&clip_node->clip_in_target_space);
840 clip_node->combined_clip_in_target_space =
841 gfx::IntersectRects(clip_node->clip_in_target_space,
842 parent_combined_clip_in_target_space);
843 } else {
844 DCHECK(!target_is_clipped);
845 DCHECK(!clip_node->layers_are_clipped);
846 clip_node->combined_clip_in_target_space =
847 parent_combined_clip_in_target_space;
848 }
849 ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space);
850 continue;
851 }
852 bool use_only_parent_clip =
853 clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP;
854 if (use_only_parent_clip) {
855 clip_node->combined_clip_in_target_space =
856 parent_combined_clip_in_target_space;
857 if (!non_root_surfaces_enabled) {
858 clip_node->clip_in_target_space =
859 parent_clip_node->clip_in_target_space;
860 } else if (!target_is_clipped) {
861 clip_node->clip_in_target_space = parent_clip_in_target_space;
862 } else {
863 // Render Surface applies clip and the owning layer itself applies
864 // no clip. So, clip_in_target_space is not used and hence we can set
865 // it to an empty rect.
866 clip_node->clip_in_target_space = gfx::RectF();
867 }
868 } else {
869 gfx::Transform source_to_target;
870
871 if (!non_root_surfaces_enabled) {
872 source_to_target = transform_tree.ToScreen(clip_node->transform_id);
873 } else if (transform_tree.ContentTargetId(transform_node->id) ==
874 clip_node->target_transform_id) {
875 property_trees->GetToTarget(clip_node->transform_id,
876 clip_node->target_effect_id,
877 &source_to_target);
878 } else {
879 success = property_trees->GetToTarget(
880 transform_node->id, clip_node->target_effect_id, &source_to_target);
881 // source_to_target computation should be successful as target is an
882 // ancestor of the transform node.
883 DCHECK(success);
884 }
885
886 gfx::RectF source_clip_in_target_space =
887 MathUtil::MapClippedRect(source_to_target, clip_node->clip);
888
889 // With surfaces disabled, the only case where we use only the local clip
890 // for layer clipping is the case where no non-viewport ancestor node
891 // applies a local clip.
892 bool layer_clipping_uses_only_local_clip =
893 non_root_surfaces_enabled
894 ? clip_node->layer_clipping_uses_only_local_clip
895 : !parent_clip_node->layers_are_clipped_when_surfaces_disabled;
896 if (!layer_clipping_uses_only_local_clip) {
897 clip_node->clip_in_target_space = gfx::IntersectRects(
898 parent_clip_in_target_space, source_clip_in_target_space);
899 } else {
900 clip_node->clip_in_target_space = source_clip_in_target_space;
901 }
902
903 clip_node->combined_clip_in_target_space = gfx::IntersectRects(
904 parent_combined_clip_in_target_space, source_clip_in_target_space);
905 }
906 ResetIfHasNanCoordinate(&clip_node->clip_in_target_space);
907 ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space);
908 }
909 clip_tree->set_needs_update(false);
910 }
911
912 void ComputeTransforms(TransformTree* transform_tree) { 516 void ComputeTransforms(TransformTree* transform_tree) {
913 if (!transform_tree->needs_update()) 517 if (!transform_tree->needs_update())
914 return; 518 return;
915 for (int i = TransformTree::kContentsRootNodeId; 519 for (int i = TransformTree::kContentsRootNodeId;
916 i < static_cast<int>(transform_tree->size()); ++i) 520 i < static_cast<int>(transform_tree->size()); ++i)
917 transform_tree->UpdateTransforms(i); 521 transform_tree->UpdateTransforms(i);
918 transform_tree->set_needs_update(false); 522 transform_tree->set_needs_update(false);
919 } 523 }
920 524
921 void UpdateRenderTarget(EffectTree* effect_tree, 525 void UpdateRenderTarget(EffectTree* effect_tree,
(...skipping 16 matching lines...) Expand all
938 542
939 void ComputeEffects(EffectTree* effect_tree) { 543 void ComputeEffects(EffectTree* effect_tree) {
940 if (!effect_tree->needs_update()) 544 if (!effect_tree->needs_update())
941 return; 545 return;
942 for (int i = EffectTree::kContentsRootNodeId; 546 for (int i = EffectTree::kContentsRootNodeId;
943 i < static_cast<int>(effect_tree->size()); ++i) 547 i < static_cast<int>(effect_tree->size()); ++i)
944 effect_tree->UpdateEffects(i); 548 effect_tree->UpdateEffects(i);
945 effect_tree->set_needs_update(false); 549 effect_tree->set_needs_update(false);
946 } 550 }
947 551
948 static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) { 552 void ComputeClips(PropertyTrees* property_trees) {
949 EffectTree* effect_tree = &property_trees->effect_tree; 553 ClipTree* clip_tree = &property_trees->clip_tree;
950 const ClipTree* clip_tree = &property_trees->clip_tree; 554 if (!clip_tree->needs_update())
951 EffectNode* root_effect_node = 555 return;
952 effect_tree->Node(EffectTree::kContentsRootNodeId); 556 const int target_effect_id = EffectTree::kContentsRootNodeId;
953 const RenderSurfaceImpl* root_render_surface = 557 const int target_transform_id = TransformTree::kRootNodeId;
954 effect_tree->GetRenderSurface(EffectTree::kContentsRootNodeId); 558 const bool include_expanding_clips = true;
955 gfx::Rect root_clip = 559 for (int i = ClipTree::kViewportNodeId;
956 gfx::ToEnclosingRect(clip_tree->Node(root_effect_node->clip_id)->clip); 560 i < static_cast<int>(clip_tree->size()); ++i) {
957 if (root_render_surface->is_clipped()) 561 ClipNode* clip_node = clip_tree->Node(i);
958 DCHECK(root_clip == root_render_surface->clip_rect()) 562 // Clear the clip rect cache
959 << "clip on root render surface: " 563 clip_node->cached_clip_rects = std::vector<ClipRectData>(1);
960 << root_render_surface->clip_rect().ToString() 564 if (clip_node->id == ClipTree::kViewportNodeId) {
961 << " v.s. root effect node's clip: " << root_clip.ToString(); 565 clip_node->accumulated_rect_in_screen_space = clip_node->clip;
962 for (int i = 2; i < static_cast<int>(effect_tree->size()); ++i) { 566 continue;
963 EffectNode* effect_node = effect_tree->Node(i);
964 const EffectNode* target_node = effect_tree->Node(effect_node->target_id);
965 bool include_viewport_clip = false;
966 bool include_expanding_clips = false;
967 ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip(
968 property_trees, include_viewport_clip, include_expanding_clips,
969 effect_node->clip_id, target_node->id);
970 gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect;
971 const RenderSurfaceImpl* render_surface = effect_tree->GetRenderSurface(i);
972 if (render_surface && render_surface->is_clipped()) {
973 DCHECK(gfx::ToEnclosingRect(accumulated_clip) ==
974 render_surface->clip_rect())
975 << " render surface's clip rect: "
976 << render_surface->clip_rect().ToString()
977 << " v.s. accumulated clip: "
978 << gfx::ToEnclosingRect(accumulated_clip).ToString();
979 } 567 }
568 ClipNode* parent_clip_node = clip_tree->parent(clip_node);
569 DCHECK(parent_clip_node);
570 gfx::RectF accumulated_clip =
571 parent_clip_node->accumulated_rect_in_screen_space;
572 bool success = ApplyClipNodeToAccumulatedClip(
573 property_trees, include_expanding_clips, target_effect_id,
574 target_transform_id, clip_node, &accumulated_clip);
575 DCHECK(success);
576 clip_node->accumulated_rect_in_screen_space = accumulated_clip;
weiliangc 2017/03/14 22:04:30 Have you tried not calculating acculated_rect_in_s
jaydasika 2017/03/16 20:33:31 I tried that. The performance was almost same. I d
980 } 577 }
578 clip_tree->set_needs_update(false);
981 } 579 }
982 580
983 static void ComputeLayerClipRect(const PropertyTrees* property_trees, 581 static ConditionalClip LayerClipRect(PropertyTrees* property_trees,
984 const LayerImpl* layer) { 582 LayerImpl* layer) {
985 const EffectTree* effect_tree = &property_trees->effect_tree; 583 const EffectTree* effect_tree = &property_trees->effect_tree;
986 const ClipTree* clip_tree = &property_trees->clip_tree;
987 const ClipNode* clip_node = clip_tree->Node(layer->clip_tree_index());
988 const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); 584 const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index());
989 const EffectNode* target_node = 585 const EffectNode* target_node =
990 effect_node->has_render_surface 586 effect_node->has_render_surface
991 ? effect_node 587 ? effect_node
992 : effect_tree->Node(effect_node->target_id); 588 : effect_tree->Node(effect_node->target_id);
993 // TODO(weiliangc): When effect node has up to date render surface info on 589 // TODO(weiliangc): When effect node has up to date render surface info on
994 // compositor thread, no need to check for resourceless draw mode 590 // compositor thread, no need to check for resourceless draw mode
995 if (!property_trees->non_root_surfaces_enabled) { 591 if (!property_trees->non_root_surfaces_enabled) {
996 target_node = effect_tree->Node(1); 592 target_node = effect_tree->Node(1);
997 } 593 }
998 594
999 bool include_viewport_clip = false;
1000 bool include_expanding_clips = false; 595 bool include_expanding_clips = false;
1001 ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( 596 return ComputeAccumulatedClip(property_trees, include_expanding_clips,
1002 property_trees, include_viewport_clip, include_expanding_clips, 597 layer->clip_tree_index(), target_node->id);
1003 layer->clip_tree_index(), target_node->id);
1004
1005 bool is_clipped_from_clip_tree =
1006 property_trees->non_root_surfaces_enabled
1007 ? clip_node->layers_are_clipped
1008 : clip_node->layers_are_clipped_when_surfaces_disabled;
1009 DCHECK_EQ(is_clipped_from_clip_tree, accumulated_clip_rect.is_clipped);
1010
1011 gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect;
1012
1013 DCHECK(layer->clip_rect() == gfx::ToEnclosingRect(accumulated_clip))
1014 << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index()
1015 << " layer clip: " << layer->clip_rect().ToString() << " v.s. "
1016 << gfx::ToEnclosingRect(accumulated_clip).ToString()
1017 << " and clip node clip: "
1018 << gfx::ToEnclosingRect(clip_node->clip_in_target_space).ToString();
1019 } 598 }
1020 599
1021 void ComputeVisibleRects(LayerImpl* root_layer, 600 static gfx::Rect LayerVisibleRect(PropertyTrees* property_trees,
1022 PropertyTrees* property_trees, 601 LayerImpl* layer) {
1023 bool can_render_to_separate_surface,
1024 LayerImplList* visible_layer_list) {
1025 bool render_surfaces_need_update = false;
1026 if (property_trees->non_root_surfaces_enabled !=
1027 can_render_to_separate_surface) {
1028 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface;
1029 property_trees->transform_tree.set_needs_update(true);
1030 render_surfaces_need_update = true;
1031 }
1032 if (property_trees->transform_tree.needs_update()) {
1033 property_trees->clip_tree.set_needs_update(true);
1034 property_trees->effect_tree.set_needs_update(true);
1035 }
1036
1037 if (render_surfaces_need_update) {
1038 property_trees->effect_tree.UpdateRenderSurfaces(
1039 root_layer->layer_tree_impl(),
1040 property_trees->non_root_surfaces_enabled);
1041 }
1042 UpdateRenderTarget(&property_trees->effect_tree,
1043 property_trees->non_root_surfaces_enabled);
1044 ComputeTransforms(&property_trees->transform_tree);
1045 // Computation of clips uses surface contents scale which is updated while
1046 // computing effects. So, ComputeEffects should be before ComputeClips.
1047 ComputeEffects(&property_trees->effect_tree);
1048 ComputeClips(property_trees, can_render_to_separate_surface);
1049
1050 FindLayersThatNeedUpdates(root_layer->layer_tree_impl(), property_trees,
1051 visible_layer_list);
1052 CalculateClipRects(*visible_layer_list, property_trees,
1053 can_render_to_separate_surface);
1054 CalculateVisibleRects(*visible_layer_list, property_trees,
1055 can_render_to_separate_surface);
1056 }
1057
1058 void UpdatePropertyTrees(PropertyTrees* property_trees,
1059 bool can_render_to_separate_surface) {
1060 if (property_trees->non_root_surfaces_enabled !=
1061 can_render_to_separate_surface) {
1062 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface;
1063 property_trees->transform_tree.set_needs_update(true);
1064 }
1065 if (property_trees->transform_tree.needs_update()) {
1066 property_trees->clip_tree.set_needs_update(true);
1067 property_trees->effect_tree.set_needs_update(true);
1068 }
1069 ComputeTransforms(&property_trees->transform_tree);
1070 // Computation of clips uses surface contents scale which is updated while
1071 // computing effects. So, ComputeEffects should be before ComputeClips.
1072 ComputeEffects(&property_trees->effect_tree);
1073 ComputeClips(property_trees, can_render_to_separate_surface);
1074 }
1075
1076 void BuildPropertyTreesAndComputeVisibleRects(
1077 LayerImpl* root_layer,
1078 const LayerImpl* page_scale_layer,
1079 const LayerImpl* inner_viewport_scroll_layer,
1080 const LayerImpl* outer_viewport_scroll_layer,
1081 const LayerImpl* overscroll_elasticity_layer,
1082 const gfx::Vector2dF& elastic_overscroll,
1083 float page_scale_factor,
1084 float device_scale_factor,
1085 const gfx::Rect& viewport,
1086 const gfx::Transform& device_transform,
1087 bool can_render_to_separate_surface,
1088 PropertyTrees* property_trees,
1089 LayerImplList* visible_layer_list) {
1090 PropertyTreeBuilder::BuildPropertyTrees(
1091 root_layer, page_scale_layer, inner_viewport_scroll_layer,
1092 outer_viewport_scroll_layer, overscroll_elasticity_layer,
1093 elastic_overscroll, page_scale_factor, device_scale_factor, viewport,
1094 device_transform, property_trees);
1095 ComputeVisibleRects(root_layer, property_trees,
1096 can_render_to_separate_surface, visible_layer_list);
1097 }
1098
1099 void VerifyClipTreeCalculations(const LayerImplList& layer_list,
1100 PropertyTrees* property_trees) {
1101 if (property_trees->non_root_surfaces_enabled) {
1102 ComputeClipsWithEffectTree(property_trees);
1103 }
1104 for (auto* layer : layer_list)
1105 ComputeLayerClipRect(property_trees, layer);
1106 }
1107
1108 gfx::Rect ComputeLayerVisibleRectDynamic(const PropertyTrees* property_trees,
1109 const LayerImpl* layer) {
1110 int effect_ancestor_with_copy_request = 602 int effect_ancestor_with_copy_request =
1111 property_trees->effect_tree.ClosestAncestorWithCopyRequest( 603 property_trees->effect_tree.ClosestAncestorWithCopyRequest(
1112 layer->effect_tree_index()); 604 layer->effect_tree_index());
1113 bool non_root_copy_request = 605 bool non_root_copy_request =
1114 effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId; 606 effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId;
1115 gfx::Rect layer_content_rect = gfx::Rect(layer->bounds()); 607 gfx::Rect layer_content_rect = gfx::Rect(layer->bounds());
1116 gfx::RectF accumulated_clip_in_root_space; 608 gfx::RectF accumulated_clip_in_root_space;
1117 if (non_root_copy_request) { 609 if (non_root_copy_request) {
1118 bool include_viewport_clip = false;
1119 bool include_expanding_clips = true; 610 bool include_expanding_clips = true;
1120 ConditionalClip accumulated_clip = ComputeAccumulatedClip( 611 ConditionalClip accumulated_clip = ComputeAccumulatedClip(
1121 property_trees, include_viewport_clip, include_expanding_clips, 612 property_trees, include_expanding_clips, layer->clip_tree_index(),
1122 layer->clip_tree_index(), effect_ancestor_with_copy_request); 613 effect_ancestor_with_copy_request);
1123 if (!accumulated_clip.is_clipped) 614 if (!accumulated_clip.is_clipped)
1124 return layer_content_rect; 615 return layer_content_rect;
1125 accumulated_clip_in_root_space = accumulated_clip.clip_rect; 616 accumulated_clip_in_root_space = accumulated_clip.clip_rect;
1126 } else { 617 } else {
618 const ClipNode* clip_node =
619 property_trees->clip_tree.Node(layer->clip_tree_index());
1127 accumulated_clip_in_root_space = 620 accumulated_clip_in_root_space =
1128 ComputeAccumulatedClipInRootSpaceForVisibleRect( 621 clip_node->accumulated_rect_in_screen_space;
1129 property_trees, layer->clip_tree_index());
1130 } 622 }
1131 623
1132 const EffectNode* root_effect_node = 624 const EffectNode* root_effect_node =
1133 non_root_copy_request 625 non_root_copy_request
1134 ? property_trees->effect_tree.Node(effect_ancestor_with_copy_request) 626 ? property_trees->effect_tree.Node(effect_ancestor_with_copy_request)
1135 : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId); 627 : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId);
1136 ConditionalClip accumulated_clip_in_layer_space = 628 ConditionalClip accumulated_clip_in_layer_space =
1137 ComputeTargetRectInLocalSpace( 629 ComputeTargetRectInLocalSpace(
1138 accumulated_clip_in_root_space, property_trees, 630 accumulated_clip_in_root_space, property_trees,
1139 root_effect_node->transform_id, layer->transform_tree_index(), 631 root_effect_node->transform_id, layer->transform_tree_index(),
1140 root_effect_node->id); 632 root_effect_node->id);
1141 if (!accumulated_clip_in_layer_space.is_clipped) 633 if (!accumulated_clip_in_layer_space.is_clipped) {
1142 return layer_content_rect; 634 return layer_content_rect;
635 }
1143 gfx::RectF clip_in_layer_space = accumulated_clip_in_layer_space.clip_rect; 636 gfx::RectF clip_in_layer_space = accumulated_clip_in_layer_space.clip_rect;
1144 clip_in_layer_space.Offset(-layer->offset_to_transform_parent()); 637 clip_in_layer_space.Offset(-layer->offset_to_transform_parent());
1145 638
1146 gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_in_layer_space); 639 gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_in_layer_space);
1147 visible_rect.Intersect(layer_content_rect); 640 visible_rect.Intersect(layer_content_rect);
1148 return visible_rect; 641 return visible_rect;
1149 } 642 }
1150 643
1151 void VerifyVisibleRectsCalculations(const LayerImplList& layer_list, 644 void UpdatePropertyTrees(PropertyTrees* property_trees,
1152 const PropertyTrees* property_trees) { 645 bool can_render_to_separate_surface) {
1153 for (auto* layer : layer_list) { 646 if (property_trees->non_root_surfaces_enabled !=
1154 gfx::Rect visible_rect_dynamic = 647 can_render_to_separate_surface) {
1155 ComputeLayerVisibleRectDynamic(property_trees, layer); 648 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface;
1156 DCHECK(layer->visible_layer_rect() == visible_rect_dynamic) 649 property_trees->transform_tree.set_needs_update(true);
1157 << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index()
1158 << " visible rect cached: " << layer->visible_layer_rect().ToString()
1159 << " v.s. "
1160 << " visible rect dynamic: " << visible_rect_dynamic.ToString();
1161 } 650 }
651 if (property_trees->transform_tree.needs_update()) {
652 property_trees->clip_tree.set_needs_update(true);
653 property_trees->effect_tree.set_needs_update(true);
654 }
655 ComputeTransforms(&property_trees->transform_tree);
656 // Computation of clips uses surface contents scale which is updated while
657 // computing effects. So, ComputeEffects should be before ComputeClips.
658 ComputeEffects(&property_trees->effect_tree);
659 ComputeClips(property_trees);
weiliangc 2017/03/14 22:04:29 Also DCHECK in ComputeClips that effect tree doesn
jaydasika 2017/03/16 20:33:31 Actually, after creating a fast-path of using ToSc
660 }
661
662 void UpdatePropertyTreesAndRenderSurfaces(LayerImpl* root_layer,
663 PropertyTrees* property_trees,
664 bool can_render_to_separate_surface) {
665 bool render_surfaces_need_update = false;
666 if (property_trees->non_root_surfaces_enabled !=
667 can_render_to_separate_surface) {
668 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface;
669 property_trees->transform_tree.set_needs_update(true);
670 render_surfaces_need_update = true;
671 }
672 if (property_trees->transform_tree.needs_update()) {
673 property_trees->clip_tree.set_needs_update(true);
674 property_trees->effect_tree.set_needs_update(true);
675 }
676 if (render_surfaces_need_update) {
677 property_trees->effect_tree.UpdateRenderSurfaces(
678 root_layer->layer_tree_impl(),
679 property_trees->non_root_surfaces_enabled);
680 }
681 UpdateRenderTarget(&property_trees->effect_tree,
682 property_trees->non_root_surfaces_enabled);
683
684 ComputeTransforms(&property_trees->transform_tree);
685 // Computation of clips uses surface contents scale which is updated while
686 // computing effects. So, ComputeEffects should be before ComputeClips.
687 ComputeEffects(&property_trees->effect_tree);
688 ComputeClips(property_trees);
weiliangc 2017/03/14 22:04:30 DCHECK like above.
jaydasika 2017/03/16 20:33:30 Done.
1162 } 689 }
1163 690
1164 bool LayerNeedsUpdate(Layer* layer, 691 bool LayerNeedsUpdate(Layer* layer,
1165 bool layer_is_drawn, 692 bool layer_is_drawn,
1166 const PropertyTrees* property_trees) { 693 const PropertyTrees* property_trees) {
1167 return LayerNeedsUpdateInternal(layer, layer_is_drawn, property_trees); 694 return LayerNeedsUpdateInternal(layer, layer_is_drawn, property_trees);
1168 } 695 }
1169 696
1170 bool LayerNeedsUpdate(LayerImpl* layer, 697 bool LayerNeedsUpdate(LayerImpl* layer,
1171 bool layer_is_drawn, 698 bool layer_is_drawn,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 const EffectNode* target_effect_node = 738 const EffectNode* target_effect_node =
1212 effect_tree.Node(effect_node->target_id); 739 effect_tree.Node(effect_node->target_id);
1213 property_trees->GetToTarget(transform_node->id, target_effect_node->id, 740 property_trees->GetToTarget(transform_node->id, target_effect_node->id,
1214 &render_surface_transform); 741 &render_surface_transform);
1215 742
1216 ConcatInverseSurfaceContentsScale(effect_node, &render_surface_transform); 743 ConcatInverseSurfaceContentsScale(effect_node, &render_surface_transform);
1217 render_surface->SetDrawTransform(render_surface_transform); 744 render_surface->SetDrawTransform(render_surface_transform);
1218 } 745 }
1219 746
1220 static void SetSurfaceClipRect(const ClipNode* parent_clip_node, 747 static void SetSurfaceClipRect(const ClipNode* parent_clip_node,
1221 const PropertyTrees* property_trees, 748 PropertyTrees* property_trees,
1222 RenderSurfaceImpl* render_surface) { 749 RenderSurfaceImpl* render_surface) {
1223 if (!render_surface->is_clipped()) { 750 if (!render_surface->is_clipped()) {
1224 render_surface->SetClipRect(gfx::Rect()); 751 render_surface->SetClipRect(gfx::Rect());
1225 return; 752 return;
1226 } 753 }
1227 754
1228 const EffectTree& effect_tree = property_trees->effect_tree; 755 const EffectTree& effect_tree = property_trees->effect_tree;
1229 const TransformTree& transform_tree = property_trees->transform_tree; 756 const ClipTree& clip_tree = property_trees->clip_tree;
1230 const TransformNode* transform_node =
1231 transform_tree.Node(render_surface->TransformTreeIndex());
1232 if (transform_tree.TargetId(transform_node->id) ==
1233 parent_clip_node->target_transform_id) {
1234 render_surface->SetClipRect(
1235 gfx::ToEnclosingRect(parent_clip_node->clip_in_target_space));
1236 return;
1237 }
1238
1239 // In this case, the clip child has reset the clip node for subtree and hence
1240 // the parent clip node's clip rect is in clip parent's target space and not
1241 // our target space. We need to transform it to our target space.
1242 const EffectNode* effect_node = 757 const EffectNode* effect_node =
1243 effect_tree.Node(render_surface->EffectTreeIndex()); 758 effect_tree.Node(render_surface->EffectTreeIndex());
1244 int target_effect_id = effect_node->target_id; 759 const EffectNode* target_node = effect_tree.Node(effect_node->target_id);
1245 gfx::RectF clip_rect; 760 bool include_expanding_clips = false;
1246 const bool success = ConvertRectBetweenSurfaceSpaces( 761 if (render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId) {
1247 property_trees, parent_clip_node->target_effect_id, target_effect_id, 762 render_surface->SetClipRect(
1248 parent_clip_node->clip_in_target_space, &clip_rect); 763 gfx::ToEnclosingRect(clip_tree.Node(effect_node->clip_id)->clip));
1249 764 } else {
1250 if (!success) { 765 ConditionalClip accumulated_clip_rect =
1251 render_surface->SetClipRect(gfx::Rect()); 766 ComputeAccumulatedClip(property_trees, include_expanding_clips,
1252 return; 767 effect_node->clip_id, target_node->id);
768 render_surface->SetClipRect(
769 gfx::ToEnclosingRect(accumulated_clip_rect.clip_rect));
1253 } 770 }
1254 render_surface->SetClipRect(gfx::ToEnclosingRect(clip_rect));
1255 } 771 }
1256 772
1257 template <typename LayerType> 773 template <typename LayerType>
1258 static gfx::Transform ScreenSpaceTransformInternal(LayerType* layer, 774 static gfx::Transform ScreenSpaceTransformInternal(LayerType* layer,
1259 const TransformTree& tree) { 775 const TransformTree& tree) {
1260 gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(), 776 gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(),
1261 layer->offset_to_transform_parent().y()); 777 layer->offset_to_transform_parent().y());
1262 gfx::Transform ssxform = tree.ToScreen(layer->transform_tree_index()); 778 gfx::Transform ssxform = tree.ToScreen(layer->transform_tree_index());
1263 xform.ConcatTransform(ssxform); 779 xform.ConcatTransform(ssxform);
1264 if (layer->should_flatten_transform_from_property_tree()) 780 if (layer->should_flatten_transform_from_property_tree())
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1311 const LayerImpl* layer, 827 const LayerImpl* layer,
1312 const gfx::Rect& layer_bounds_in_target_space, 828 const gfx::Rect& layer_bounds_in_target_space,
1313 const gfx::Rect& clip_rect) { 829 const gfx::Rect& clip_rect) {
1314 if (layer->is_clipped()) 830 if (layer->is_clipped())
1315 return IntersectRects(layer_bounds_in_target_space, clip_rect); 831 return IntersectRects(layer_bounds_in_target_space, clip_rect);
1316 832
1317 return layer_bounds_in_target_space; 833 return layer_bounds_in_target_space;
1318 } 834 }
1319 835
1320 void ComputeLayerDrawProperties(LayerImpl* layer, 836 void ComputeLayerDrawProperties(LayerImpl* layer,
1321 const PropertyTrees* property_trees) { 837 PropertyTrees* property_trees) {
1322 const TransformNode* transform_node = 838 const TransformNode* transform_node =
1323 property_trees->transform_tree.Node(layer->transform_tree_index()); 839 property_trees->transform_tree.Node(layer->transform_tree_index());
1324 const ClipNode* clip_node =
1325 property_trees->clip_tree.Node(layer->clip_tree_index());
1326 840
1327 layer->draw_properties().screen_space_transform = 841 layer->draw_properties().screen_space_transform =
1328 ScreenSpaceTransformInternal(layer, property_trees->transform_tree); 842 ScreenSpaceTransformInternal(layer, property_trees->transform_tree);
1329 layer->draw_properties().target_space_transform = DrawTransform( 843 layer->draw_properties().target_space_transform = DrawTransform(
1330 layer, property_trees->transform_tree, property_trees->effect_tree); 844 layer, property_trees->transform_tree, property_trees->effect_tree);
1331 layer->draw_properties().screen_space_transform_is_animating = 845 layer->draw_properties().screen_space_transform_is_animating =
1332 transform_node->to_screen_is_potentially_animated; 846 transform_node->to_screen_is_potentially_animated;
1333 847
1334 layer->draw_properties().opacity = 848 layer->draw_properties().opacity =
1335 LayerDrawOpacity(layer, property_trees->effect_tree); 849 LayerDrawOpacity(layer, property_trees->effect_tree);
1336 if (property_trees->non_root_surfaces_enabled) {
1337 layer->draw_properties().is_clipped = clip_node->layers_are_clipped;
1338 } else {
1339 layer->draw_properties().is_clipped =
1340 clip_node->layers_are_clipped_when_surfaces_disabled;
1341 }
1342 850
1343 gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect( 851 gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect(
1344 layer->draw_properties().target_space_transform, 852 layer->draw_properties().target_space_transform,
1345 gfx::Rect(layer->bounds())); 853 gfx::Rect(layer->bounds()));
854 ConditionalClip clip = LayerClipRect(property_trees, layer);
855 layer->draw_properties().is_clipped = clip.is_clipped;
856 layer->draw_properties().clip_rect = gfx::ToEnclosingRect(clip.clip_rect);
857 layer->draw_properties().visible_layer_rect =
858 LayerVisibleRect(property_trees, layer);
1346 layer->draw_properties().drawable_content_rect = LayerDrawableContentRect( 859 layer->draw_properties().drawable_content_rect = LayerDrawableContentRect(
1347 layer, bounds_in_target_space, layer->draw_properties().clip_rect); 860 layer, bounds_in_target_space, layer->draw_properties().clip_rect);
1348 } 861 }
1349 862
1350 void ComputeMaskDrawProperties(LayerImpl* mask_layer, 863 void ComputeMaskDrawProperties(LayerImpl* mask_layer,
1351 const PropertyTrees* property_trees) { 864 const PropertyTrees* property_trees) {
1352 // Mask draw properties are used only for rastering, so most of the draw 865 // Mask draw properties are used only for rastering, so most of the draw
1353 // properties computed for other layers are not needed. 866 // properties computed for other layers are not needed.
1354 mask_layer->draw_properties().screen_space_transform = 867 mask_layer->draw_properties().screen_space_transform =
1355 ScreenSpaceTransformInternal(mask_layer, 868 ScreenSpaceTransformInternal(mask_layer,
1356 property_trees->transform_tree); 869 property_trees->transform_tree);
1357 mask_layer->draw_properties().visible_layer_rect = 870 mask_layer->draw_properties().visible_layer_rect =
1358 gfx::Rect(mask_layer->bounds()); 871 gfx::Rect(mask_layer->bounds());
1359 } 872 }
1360 873
1361 void ComputeSurfaceDrawProperties(const PropertyTrees* property_trees, 874 void ComputeSurfaceDrawProperties(PropertyTrees* property_trees,
1362 RenderSurfaceImpl* render_surface) { 875 RenderSurfaceImpl* render_surface) {
1363 const EffectNode* effect_node = 876 const EffectNode* effect_node =
1364 property_trees->effect_tree.Node(render_surface->EffectTreeIndex()); 877 property_trees->effect_tree.Node(render_surface->EffectTreeIndex());
1365 render_surface->SetIsClipped(effect_node->surface_is_clipped); 878 render_surface->SetIsClipped(effect_node->surface_is_clipped);
1366 SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); 879 SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface);
1367 SetSurfaceDrawTransform(property_trees, render_surface); 880 SetSurfaceDrawTransform(property_trees, render_surface);
1368 render_surface->SetScreenSpaceTransform( 881 render_surface->SetScreenSpaceTransform(
1369 property_trees->ToScreenSpaceTransformWithoutSurfaceContentsScale( 882 property_trees->ToScreenSpaceTransformWithoutSurfaceContentsScale(
1370 render_surface->TransformTreeIndex(), 883 render_surface->TransformTreeIndex(),
1371 render_surface->EffectTreeIndex())); 884 render_surface->EffectTreeIndex()));
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1471 void UpdateElasticOverscroll(PropertyTrees* property_trees, 984 void UpdateElasticOverscroll(PropertyTrees* property_trees,
1472 const Layer* overscroll_elasticity_layer, 985 const Layer* overscroll_elasticity_layer,
1473 const gfx::Vector2dF& elastic_overscroll) { 986 const gfx::Vector2dF& elastic_overscroll) {
1474 UpdateElasticOverscrollInternal(property_trees, overscroll_elasticity_layer, 987 UpdateElasticOverscrollInternal(property_trees, overscroll_elasticity_layer,
1475 elastic_overscroll); 988 elastic_overscroll);
1476 } 989 }
1477 990
1478 } // namespace draw_property_utils 991 } // namespace draw_property_utils
1479 992
1480 } // namespace cc 993 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698