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

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

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

Powered by Google App Engine
This is Rietveld 408576698