Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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( | |
|
ajuma
2015/08/06 14:25:45
ComputeTransformWithSourceSublayerScale can divide
jaydasika
2015/08/06 16:39:34
Done.
| |
| 433 transform_node->data.target_id, target_id, | |
| 434 &transform_target_to_target); | |
| 435 transform_target_to_target.Scale(transform_node->data.sublayer_scale.x(), | |
| 436 transform_node->data.sublayer_scale.y()); | |
| 437 } else if (parent_transform_node->data.content_target_id == | |
| 438 clip_node->data.target_id) { | |
| 424 parent_to_target = parent_transform_node->data.to_target; | 439 parent_to_target = parent_transform_node->data.to_target; |
| 425 } else { | 440 } else { |
| 426 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( | 441 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( |
| 427 parent_transform_node->id, target_id, &parent_to_target); | 442 parent_transform_node->id, target_id, &parent_to_target); |
| 428 } | 443 } |
| 429 | 444 |
| 430 if (transform_node->data.content_target_id == clip_node->data.target_id) { | 445 if (transform_node->data.content_target_id == clip_node->data.target_id) { |
| 431 clip_to_target = transform_node->data.to_target; | 446 clip_to_target = transform_node->data.to_target; |
| 432 } else { | 447 } else { |
| 433 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( | 448 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( |
| 434 transform_node->id, target_id, &clip_to_target); | 449 transform_node->id, target_id, &clip_to_target); |
| 435 } | 450 } |
| 436 | 451 |
| 437 if (transform_node->data.content_target_id == clip_node->data.target_id && | 452 if (transform_node->data.content_target_id == clip_node->data.target_id && |
| 438 transform_node->data.ancestors_are_invertible) { | 453 transform_node->data.ancestors_are_invertible) { |
| 439 target_to_clip = transform_node->data.from_target; | 454 target_to_clip = transform_node->data.from_target; |
| 440 } else { | 455 } else { |
| 441 success &= clip_to_target.GetInverse(&target_to_clip); | 456 success &= clip_to_target.GetInverse(&target_to_clip); |
| 442 } | 457 } |
| 443 | 458 |
| 444 // If we can't compute a transform, it's because we had to use the inverse | 459 // 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 | 460 // of a singular transform. We won't draw in this case, so there's no need |
| 446 // to compute clips. | 461 // to compute clips. |
| 447 if (!success) | 462 if (!success) { |
| 448 continue; | 463 continue; |
| 464 } | |
| 449 | 465 |
| 450 // In order to intersect with as small a rect as possible, we do a | 466 // 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 | 467 // preliminary clip in target space so that when we project back, there's |
| 452 // less likelihood of intersecting the view plane. | 468 // less likelihood of intersecting the view plane. |
| 453 gfx::RectF inherited_clip_in_target_space = MathUtil::MapClippedRect( | 469 gfx::RectF inherited_clip_in_target_space; |
| 454 parent_to_target, parent_clip_node->data.combined_clip); | 470 if (clip_node->data.inherit_parent_target_space_clip) { |
| 471 gfx::RectF combined_clip_in_transform_target_space; | |
| 472 if (parent_transform_node->id > transform_node->data.target_id) | |
| 473 combined_clip_in_transform_target_space = MathUtil::MapClippedRect( | |
| 474 parent_to_transform_target, parent_clip_node->data.combined_clip); | |
| 475 else | |
| 476 combined_clip_in_transform_target_space = MathUtil::ProjectClippedRect( | |
| 477 parent_to_transform_target, parent_clip_node->data.combined_clip); | |
| 478 inherited_clip_in_target_space = MathUtil::ProjectClippedRect( | |
| 479 transform_target_to_target, combined_clip_in_transform_target_space); | |
| 480 } else if (parent_transform_node->id > target_id) { | |
| 481 inherited_clip_in_target_space = MathUtil::MapClippedRect( | |
| 482 parent_to_target, parent_clip_node->data.combined_clip); | |
| 483 } else { | |
| 484 inherited_clip_in_target_space = MathUtil::ProjectClippedRect( | |
| 485 parent_to_target, parent_clip_node->data.combined_clip); | |
| 486 } | |
| 455 | 487 |
| 456 gfx::RectF clip_in_target_space = | 488 // When render surface applies clip, the layer that created the clip node |
|
ajuma
2015/08/06 14:25:45
s/applies clip/inherits its parent's target space
jaydasika
2015/08/06 16:39:34
Done.
| |
| 457 MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip); | 489 // doesn't apply any clip. So, we should clip using the clip value |
|
ajuma
2015/08/06 14:25:45
Do you mean "we shouldn't clip" instead? (Since in
jaydasika
2015/08/06 16:39:34
Done.
| |
| 490 // stored in the clip node. | |
| 491 gfx::RectF intersected_in_target_space; | |
| 492 if (!clip_node->data.inherit_parent_target_space_clip) { | |
| 493 gfx::RectF clip_in_target_space = | |
| 494 MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip); | |
| 458 | 495 |
| 459 gfx::RectF intersected_in_target_space = gfx::IntersectRects( | 496 intersected_in_target_space = gfx::IntersectRects( |
| 460 inherited_clip_in_target_space, clip_in_target_space); | 497 inherited_clip_in_target_space, clip_in_target_space); |
| 498 } else { | |
| 499 intersected_in_target_space = inherited_clip_in_target_space; | |
| 500 } | |
| 461 | 501 |
| 462 clip_node->data.combined_clip = MathUtil::ProjectClippedRect( | 502 clip_node->data.combined_clip = MathUtil::ProjectClippedRect( |
| 463 target_to_clip, intersected_in_target_space); | 503 target_to_clip, intersected_in_target_space); |
| 464 | 504 |
| 465 clip_node->data.combined_clip.Intersect(clip_node->data.clip); | 505 if (!clip_node->data.inherit_parent_target_space_clip) |
| 506 clip_node->data.combined_clip.Intersect(clip_node->data.clip); | |
| 466 } | 507 } |
| 467 clip_tree->set_needs_update(false); | 508 clip_tree->set_needs_update(false); |
| 468 } | 509 } |
| 469 | 510 |
| 470 void ComputeTransforms(TransformTree* transform_tree) { | 511 void ComputeTransforms(TransformTree* transform_tree) { |
| 471 if (!transform_tree->needs_update()) | 512 if (!transform_tree->needs_update()) |
| 472 return; | 513 return; |
| 473 for (int i = 1; i < static_cast<int>(transform_tree->size()); ++i) | 514 for (int i = 1; i < static_cast<int>(transform_tree->size()); ++i) |
| 474 transform_tree->UpdateTransforms(i); | 515 transform_tree->UpdateTransforms(i); |
| 475 transform_tree->set_needs_update(false); | 516 transform_tree->set_needs_update(false); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 708 if (static_cast<int>(layer->offset_to_transform_parent().x()) != | 749 if (static_cast<int>(layer->offset_to_transform_parent().x()) != |
| 709 layer->offset_to_transform_parent().x()) | 750 layer->offset_to_transform_parent().x()) |
| 710 return false; | 751 return false; |
| 711 if (static_cast<int>(layer->offset_to_transform_parent().y()) != | 752 if (static_cast<int>(layer->offset_to_transform_parent().y()) != |
| 712 layer->offset_to_transform_parent().y()) | 753 layer->offset_to_transform_parent().y()) |
| 713 return false; | 754 return false; |
| 714 return true; | 755 return true; |
| 715 } | 756 } |
| 716 | 757 |
| 717 } // namespace cc | 758 } // namespace cc |
| OLD | NEW |