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

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

Issue 1252313004: Add ClipNode when Render Surface Inherits Clip (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Layout tests pass , unit test added , comments on patch 11 Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/trees/draw_property_utils.h" 5 #include "cc/trees/draw_property_utils.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "cc/base/math_util.h" 9 #include "cc/base/math_util.h"
10 #include "cc/layers/layer.h" 10 #include "cc/layers/layer.h"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 50
51 gfx::Rect clip_rect_in_target_space; 51 gfx::Rect clip_rect_in_target_space;
52 gfx::Transform clip_to_target; 52 gfx::Transform clip_to_target;
53 bool success = true; 53 bool success = true;
54 if (clip_transform_node->data.target_id == target_node->id) { 54 if (clip_transform_node->data.target_id == target_node->id) {
55 clip_to_target = clip_transform_node->data.to_target; 55 clip_to_target = clip_transform_node->data.to_target;
56 } else { 56 } else {
57 success = transform_tree.ComputeTransformWithDestinationSublayerScale( 57 success = transform_tree.ComputeTransformWithDestinationSublayerScale(
58 clip_transform_node->id, target_node->id, &clip_to_target); 58 clip_transform_node->id, target_node->id, &clip_to_target);
59 } 59 }
60
61 if (target_node->id > clip_node->data.transform_id) { 60 if (target_node->id > clip_node->data.transform_id) {
62 if (!success) { 61 if (!success) {
63 DCHECK(target_node->data.to_screen_is_animated); 62 DCHECK(target_node->data.to_screen_is_animated);
64 63
65 // An animated singular transform may become non-singular during the 64 // An animated singular transform may become non-singular during the
66 // animation, so we still need to compute a visible rect. In this 65 // animation, so we still need to compute a visible rect. In this
67 // situation, we treat the entire layer as visible. 66 // situation, we treat the entire layer as visible.
68 layer->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds)); 67 layer->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds));
69 continue; 68 continue;
70 } 69 }
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) { 382 void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) {
384 if (!clip_tree->needs_update()) 383 if (!clip_tree->needs_update())
385 return; 384 return;
386 for (int i = 0; i < static_cast<int>(clip_tree->size()); ++i) { 385 for (int i = 0; i < static_cast<int>(clip_tree->size()); ++i) {
387 ClipNode* clip_node = clip_tree->Node(i); 386 ClipNode* clip_node = clip_tree->Node(i);
388 387
389 // Only descendants of a real clipping layer (i.e., not 0) may have their 388 // Only descendants of a real clipping layer (i.e., not 0) may have their
390 // clip adjusted due to intersecting with an ancestor clip. 389 // clip adjusted due to intersecting with an ancestor clip.
391 const bool is_clipped = clip_node->parent_id > 0; 390 const bool is_clipped = clip_node->parent_id > 0;
392 if (!is_clipped) { 391 if (!is_clipped) {
392 DCHECK(!clip_node->data.inherit_parent_target_space_clip);
393 clip_node->data.combined_clip = clip_node->data.clip; 393 clip_node->data.combined_clip = clip_node->data.clip;
394 continue; 394 continue;
395 } 395 }
396 396
397 ClipNode* parent_clip_node = clip_tree->parent(clip_node); 397 ClipNode* parent_clip_node = clip_tree->parent(clip_node);
398 const TransformNode* parent_transform_node = 398 const TransformNode* parent_transform_node =
399 transform_tree.Node(parent_clip_node->data.transform_id); 399 transform_tree.Node(parent_clip_node->data.transform_id);
400 const TransformNode* transform_node = 400 const TransformNode* transform_node =
401 transform_tree.Node(clip_node->data.transform_id); 401 transform_tree.Node(clip_node->data.transform_id);
402 402
403 // Clips must be combined in target space. We cannot, for example, combine 403 // Clips must be combined in target space. We cannot, for example, combine
404 // clips in the space of the child clip. The reason is non-affine 404 // clips in the space of the child clip. The reason is non-affine
405 // transforms. Say we have the following tree T->A->B->C, and B clips C, but 405 // transforms. Say we have the following tree T->A->B->C, and B clips C, but
406 // draw into target T. It may be the case that A applies a perspective 406 // draw into target T. It may be the case that A applies a perspective
407 // transform, and B and C are at different z positions. When projected into 407 // transform, and B and C are at different z positions. When projected into
408 // target space, the relative sizes and positions of B and C can shift. 408 // target space, the relative sizes and positions of B and C can shift.
409 // Since it's the relationship in target space that matters, that's where we 409 // Since it's the relationship in target space that matters, that's where we
410 // must combine clips. 410 // must combine clips.
411 gfx::Transform parent_to_target; 411 gfx::Transform parent_to_target;
412 gfx::Transform clip_to_target; 412 gfx::Transform clip_to_target;
413 gfx::Transform target_to_clip; 413 gfx::Transform target_to_clip;
414 gfx::Transform parent_to_transform_target;
415 gfx::Transform transform_target_to_target;
414 416
415 const bool target_is_root_surface = clip_node->data.target_id == 1; 417 const bool target_is_root_surface = clip_node->data.target_id == 1;
416 // When the target is the root surface, we need to include the root 418 // When the target is the root surface, we need to include the root
417 // transform by walking up to the root of the transform tree. 419 // transform by walking up to the root of the transform tree.
418 const int target_id = 420 const int target_id =
419 target_is_root_surface ? 0 : clip_node->data.target_id; 421 target_is_root_surface ? 0 : clip_node->data.target_id;
420 422
421 bool success = true; 423 bool success = true;
422 if (parent_transform_node->data.content_target_id == 424 // When render surface applies clip, we need the clip from the target's
423 clip_node->data.target_id) { 425 // target space. But, as the combined clip is in parent clip's target
426 // space, we need to first transform it from parent's target space to
427 // target's target space.
428 if (clip_node->data.inherit_parent_target_space_clip) {
429 success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
430 parent_transform_node->id, transform_node->data.target_id,
431 &parent_to_transform_target);
432 success &= transform_tree.ComputeTransformWithSourceSublayerScale(
433 transform_node->data.target_id, target_id,
434 &transform_target_to_target);
435 transform_target_to_target.matrix().postScale(
436 transform_node->data.sublayer_scale.x(),
437 transform_node->data.sublayer_scale.y(), 1.0);
438 } else if (parent_transform_node->data.content_target_id ==
439 clip_node->data.target_id) {
424 parent_to_target = parent_transform_node->data.to_target; 440 parent_to_target = parent_transform_node->data.to_target;
425 } else { 441 } else {
426 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( 442 success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
427 parent_transform_node->id, target_id, &parent_to_target); 443 parent_transform_node->id, target_id, &parent_to_target);
428 } 444 }
429 445
430 if (transform_node->data.content_target_id == clip_node->data.target_id) { 446 if (transform_node->data.content_target_id == clip_node->data.target_id) {
431 clip_to_target = transform_node->data.to_target; 447 clip_to_target = transform_node->data.to_target;
432 } else { 448 } else {
433 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( 449 success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
434 transform_node->id, target_id, &clip_to_target); 450 transform_node->id, target_id, &clip_to_target);
435 } 451 }
436 452
437 if (transform_node->data.content_target_id == clip_node->data.target_id && 453 if (transform_node->data.content_target_id == clip_node->data.target_id &&
438 transform_node->data.ancestors_are_invertible) { 454 transform_node->data.ancestors_are_invertible) {
439 target_to_clip = transform_node->data.from_target; 455 target_to_clip = transform_node->data.from_target;
440 } else { 456 } else {
441 success &= clip_to_target.GetInverse(&target_to_clip); 457 success &= clip_to_target.GetInverse(&target_to_clip);
442 } 458 }
443 459
444 // If we can't compute a transform, it's because we had to use the inverse 460 // If we can't compute a transform, it's because we had to use the inverse
445 // of a singular transform. We won't draw in this case, so there's no need 461 // of a singular transform. We won't draw in this case, so there's no need
446 // to compute clips. 462 // to compute clips.
447 if (!success) 463 if (!success) {
448 continue; 464 continue;
465 }
449 466
450 // In order to intersect with as small a rect as possible, we do a 467 // In order to intersect with as small a rect as possible, we do a
451 // preliminary clip in target space so that when we project back, there's 468 // preliminary clip in target space so that when we project back, there's
452 // less likelihood of intersecting the view plane. 469 // less likelihood of intersecting the view plane.
453 gfx::RectF inherited_clip_in_target_space = MathUtil::MapClippedRect( 470 gfx::RectF inherited_clip_in_target_space;
454 parent_to_target, parent_clip_node->data.combined_clip); 471 if (clip_node->data.inherit_parent_target_space_clip) {
472 gfx::RectF combined_clip_in_transform_target_space;
473 if (parent_transform_node->id > transform_node->data.target_id)
474 combined_clip_in_transform_target_space = MathUtil::MapClippedRect(
475 parent_to_transform_target, parent_clip_node->data.combined_clip);
476 else
477 combined_clip_in_transform_target_space = MathUtil::ProjectClippedRect(
478 parent_to_transform_target, parent_clip_node->data.combined_clip);
479 inherited_clip_in_target_space = MathUtil::ProjectClippedRect(
480 transform_target_to_target, combined_clip_in_transform_target_space);
481 } else if (parent_transform_node->id > target_id) {
482 inherited_clip_in_target_space = MathUtil::MapClippedRect(
483 parent_to_target, parent_clip_node->data.combined_clip);
484 } else {
485 inherited_clip_in_target_space = MathUtil::ProjectClippedRect(
486 parent_to_target, parent_clip_node->data.combined_clip);
487 }
455 488
456 gfx::RectF clip_in_target_space = 489 // When render surface inherits its parent target space clip, the layer
457 MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip); 490 // that created the clip node doesn't apply any clip. So, we shouldn't clip
491 // using the clip value stored in the clip node.
492 gfx::RectF intersected_in_target_space;
493 if (!clip_node->data.inherit_parent_target_space_clip) {
494 gfx::RectF clip_in_target_space =
495 MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip);
458 496
459 gfx::RectF intersected_in_target_space = gfx::IntersectRects( 497 intersected_in_target_space = gfx::IntersectRects(
460 inherited_clip_in_target_space, clip_in_target_space); 498 inherited_clip_in_target_space, clip_in_target_space);
499 } else {
500 intersected_in_target_space = inherited_clip_in_target_space;
501 }
461 502
462 clip_node->data.combined_clip = MathUtil::ProjectClippedRect( 503 clip_node->data.combined_clip = MathUtil::ProjectClippedRect(
463 target_to_clip, intersected_in_target_space); 504 target_to_clip, intersected_in_target_space);
464 505
465 clip_node->data.combined_clip.Intersect(clip_node->data.clip); 506 if (!clip_node->data.inherit_parent_target_space_clip)
507 clip_node->data.combined_clip.Intersect(clip_node->data.clip);
466 } 508 }
467 clip_tree->set_needs_update(false); 509 clip_tree->set_needs_update(false);
468 } 510 }
469 511
470 void ComputeTransforms(TransformTree* transform_tree) { 512 void ComputeTransforms(TransformTree* transform_tree) {
471 if (!transform_tree->needs_update()) 513 if (!transform_tree->needs_update())
472 return; 514 return;
473 for (int i = 1; i < static_cast<int>(transform_tree->size()); ++i) 515 for (int i = 1; i < static_cast<int>(transform_tree->size()); ++i)
474 transform_tree->UpdateTransforms(i); 516 transform_tree->UpdateTransforms(i);
475 transform_tree->set_needs_update(false); 517 transform_tree->set_needs_update(false);
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 if (static_cast<int>(layer->offset_to_transform_parent().x()) != 750 if (static_cast<int>(layer->offset_to_transform_parent().x()) !=
709 layer->offset_to_transform_parent().x()) 751 layer->offset_to_transform_parent().x())
710 return false; 752 return false;
711 if (static_cast<int>(layer->offset_to_transform_parent().y()) != 753 if (static_cast<int>(layer->offset_to_transform_parent().y()) !=
712 layer->offset_to_transform_parent().y()) 754 layer->offset_to_transform_parent().y())
713 return false; 755 return false;
714 return true; 756 return true;
715 } 757 }
716 758
717 } // namespace cc 759 } // namespace cc
OLDNEW
« no previous file with comments | « no previous file | cc/trees/layer_tree_host_common_unittest.cc » ('j') | cc/trees/layer_tree_host_common_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698