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

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

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