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 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) { | 380 void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) { |
| 382 if (!clip_tree->needs_update()) | 381 if (!clip_tree->needs_update()) |
| 383 return; | 382 return; |
| 384 for (int i = 0; i < static_cast<int>(clip_tree->size()); ++i) { | 383 for (int i = 0; i < static_cast<int>(clip_tree->size()); ++i) { |
| 385 ClipNode* clip_node = clip_tree->Node(i); | 384 ClipNode* clip_node = clip_tree->Node(i); |
| 386 | 385 |
| 387 // Only descendants of a real clipping layer (i.e., not 0) may have their | 386 // Only descendants of a real clipping layer (i.e., not 0) may have their |
| 388 // clip adjusted due to intersecting with an ancestor clip. | 387 // clip adjusted due to intersecting with an ancestor clip. |
| 389 const bool is_clipped = clip_node->parent_id > 0; | 388 const bool is_clipped = clip_node->parent_id > 0; |
| 390 if (!is_clipped) { | 389 if (!is_clipped) { |
| 390 DCHECK(!clip_node->data.inherit_parent_target_space_clip); | |
| 391 clip_node->data.combined_clip = clip_node->data.clip; | 391 clip_node->data.combined_clip = clip_node->data.clip; |
| 392 continue; | 392 continue; |
| 393 } | 393 } |
| 394 | 394 |
| 395 ClipNode* parent_clip_node = clip_tree->parent(clip_node); | 395 ClipNode* parent_clip_node = clip_tree->parent(clip_node); |
| 396 const TransformNode* parent_transform_node = | 396 const TransformNode* parent_transform_node = |
| 397 transform_tree.Node(parent_clip_node->data.transform_id); | 397 transform_tree.Node(parent_clip_node->data.transform_id); |
| 398 const TransformNode* transform_node = | 398 const TransformNode* transform_node = |
| 399 transform_tree.Node(clip_node->data.transform_id); | 399 transform_tree.Node(clip_node->data.transform_id); |
| 400 | 400 |
| 401 // Clips must be combined in target space. We cannot, for example, combine | 401 // Clips must be combined in target space. We cannot, for example, combine |
| 402 // clips in the space of the child clip. The reason is non-affine | 402 // clips in the space of the child clip. The reason is non-affine |
| 403 // transforms. Say we have the following tree T->A->B->C, and B clips C, but | 403 // transforms. Say we have the following tree T->A->B->C, and B clips C, but |
| 404 // draw into target T. It may be the case that A applies a perspective | 404 // draw into target T. It may be the case that A applies a perspective |
| 405 // transform, and B and C are at different z positions. When projected into | 405 // transform, and B and C are at different z positions. When projected into |
| 406 // target space, the relative sizes and positions of B and C can shift. | 406 // target space, the relative sizes and positions of B and C can shift. |
| 407 // Since it's the relationship in target space that matters, that's where we | 407 // Since it's the relationship in target space that matters, that's where we |
| 408 // must combine clips. | 408 // must combine clips. |
| 409 gfx::Transform parent_to_target; | 409 gfx::Transform parent_to_target; |
| 410 gfx::Transform clip_to_target; | 410 gfx::Transform clip_to_target; |
| 411 gfx::Transform target_to_clip; | 411 gfx::Transform target_to_clip; |
| 412 gfx::Transform parent_to_transform_target; | |
| 413 gfx::Transform transform_target_to_target; | |
| 412 | 414 |
| 413 const bool target_is_root_surface = clip_node->data.target_id == 1; | 415 const bool target_is_root_surface = clip_node->data.target_id == 1; |
| 414 // When the target is the root surface, we need to include the root | 416 // When the target is the root surface, we need to include the root |
| 415 // transform by walking up to the root of the transform tree. | 417 // transform by walking up to the root of the transform tree. |
| 416 const int target_id = | 418 const int target_id = |
| 417 target_is_root_surface ? 0 : clip_node->data.target_id; | 419 target_is_root_surface ? 0 : clip_node->data.target_id; |
| 418 | 420 |
| 419 bool success = true; | 421 bool success = true; |
| 420 if (parent_transform_node->data.content_target_id == | 422 // When render surface applies clip, we need the clip from the target's |
| 421 clip_node->data.target_id) { | 423 // target space. But, as the combined clip is in parent clip's target |
| 424 // space, we need to first transform it from parent's target space to | |
| 425 // target's target space. | |
| 426 if (clip_node->data.inherit_parent_target_space_clip) { | |
| 427 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( | |
| 428 parent_transform_node->id, transform_node->data.target_id, | |
| 429 &parent_to_transform_target); | |
| 430 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( | |
| 431 transform_node->data.target_id, target_id, | |
| 432 &transform_target_to_target); | |
| 433 } else if (parent_transform_node->data.content_target_id == | |
| 434 clip_node->data.target_id) { | |
| 422 parent_to_target = parent_transform_node->data.to_target; | 435 parent_to_target = parent_transform_node->data.to_target; |
| 423 } else { | 436 } else { |
| 424 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( | 437 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( |
| 425 parent_transform_node->id, target_id, &parent_to_target); | 438 parent_transform_node->id, target_id, &parent_to_target); |
| 426 } | 439 } |
| 427 | 440 |
| 428 if (transform_node->data.content_target_id == clip_node->data.target_id) { | 441 if (transform_node->data.content_target_id == clip_node->data.target_id) { |
| 429 clip_to_target = transform_node->data.to_target; | 442 clip_to_target = transform_node->data.to_target; |
| 430 } else { | 443 } else { |
| 431 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( | 444 success &= transform_tree.ComputeTransformWithDestinationSublayerScale( |
| 432 transform_node->id, target_id, &clip_to_target); | 445 transform_node->id, target_id, &clip_to_target); |
| 433 } | 446 } |
| 434 | 447 |
| 435 if (transform_node->data.content_target_id == clip_node->data.target_id && | 448 if (transform_node->data.content_target_id == clip_node->data.target_id && |
| 436 transform_node->data.ancestors_are_invertible) { | 449 transform_node->data.ancestors_are_invertible) { |
| 437 target_to_clip = transform_node->data.from_target; | 450 target_to_clip = transform_node->data.from_target; |
| 438 } else { | 451 } else { |
| 439 success &= clip_to_target.GetInverse(&target_to_clip); | 452 success &= clip_to_target.GetInverse(&target_to_clip); |
| 440 } | 453 } |
| 441 | 454 |
| 442 // If we can't compute a transform, it's because we had to use the inverse | 455 // If we can't compute a transform, it's because we had to use the inverse |
| 443 // of a singular transform. We won't draw in this case, so there's no need | 456 // of a singular transform. We won't draw in this case, so there's no need |
| 444 // to compute clips. | 457 // to compute clips. |
| 445 if (!success) | 458 if (!success) { |
| 459 if (clip_node->data.inherit_parent_target_space_clip) { | |
| 460 clip_node->data.transform_id = parent_clip_node->data.transform_id; | |
|
ajuma
2015/08/05 13:51:09
I don't think we should be changing the transform
jaydasika
2015/08/05 15:07:20
Ah, I see the problem. But I am still not sure wha
ajuma
2015/08/05 15:21:58
If we reach this point, we have an uninvertible tr
jaydasika
2015/08/05 21:50:11
Done.
| |
| 461 clip_node->data.combined_clip = parent_clip_node->data.combined_clip; | |
| 462 } else { | |
| 463 clip_node->data.combined_clip = clip_node->data.clip; | |
| 464 } | |
| 446 continue; | 465 continue; |
| 466 } | |
| 447 | 467 |
| 448 // In order to intersect with as small a rect as possible, we do a | 468 // In order to intersect with as small a rect as possible, we do a |
| 449 // preliminary clip in target space so that when we project back, there's | 469 // preliminary clip in target space so that when we project back, there's |
| 450 // less likelihood of intersecting the view plane. | 470 // less likelihood of intersecting the view plane. |
| 451 gfx::RectF inherited_clip_in_target_space = MathUtil::MapClippedRect( | 471 gfx::RectF inherited_clip_in_target_space; |
| 452 parent_to_target, parent_clip_node->data.combined_clip); | 472 if (clip_node->data.inherit_parent_target_space_clip) { |
| 473 gfx::RectF combined_clip_in_transform_target_space; | |
| 474 if (parent_transform_node->id > transform_node->data.target_id) | |
| 475 combined_clip_in_transform_target_space = MathUtil::MapClippedRect( | |
| 476 parent_to_transform_target, parent_clip_node->data.combined_clip); | |
| 477 else | |
| 478 combined_clip_in_transform_target_space = MathUtil::ProjectClippedRect( | |
| 479 parent_to_transform_target, parent_clip_node->data.combined_clip); | |
| 480 inherited_clip_in_target_space = MathUtil::ProjectClippedRect( | |
| 481 transform_target_to_target, combined_clip_in_transform_target_space); | |
| 482 } else if (parent_transform_node->id > target_id) { | |
| 483 inherited_clip_in_target_space = MathUtil::MapClippedRect( | |
| 484 parent_to_target, parent_clip_node->data.combined_clip); | |
| 485 } else { | |
| 486 inherited_clip_in_target_space = MathUtil::ProjectClippedRect( | |
| 487 parent_to_target, parent_clip_node->data.combined_clip); | |
| 488 } | |
| 453 | 489 |
| 454 gfx::RectF clip_in_target_space = | 490 // When render surface applies clip, the layer that created the clip node |
| 455 MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip); | 491 // doesn't apply any clip. So, we should clip using the clip value |
| 492 // stored in the clip node. | |
| 493 gfx::RectF intersected_in_target_space; | |
| 494 if (!clip_node->data.inherit_parent_target_space_clip) { | |
| 495 gfx::RectF clip_in_target_space = | |
| 496 MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip); | |
| 456 | 497 |
| 457 gfx::RectF intersected_in_target_space = gfx::IntersectRects( | 498 intersected_in_target_space = gfx::IntersectRects( |
| 458 inherited_clip_in_target_space, clip_in_target_space); | 499 inherited_clip_in_target_space, clip_in_target_space); |
| 500 } else { | |
| 501 intersected_in_target_space = inherited_clip_in_target_space; | |
| 502 } | |
| 459 | 503 |
| 460 clip_node->data.combined_clip = MathUtil::ProjectClippedRect( | 504 clip_node->data.combined_clip = MathUtil::ProjectClippedRect( |
| 461 target_to_clip, intersected_in_target_space); | 505 target_to_clip, intersected_in_target_space); |
| 462 | 506 |
| 463 clip_node->data.combined_clip.Intersect(clip_node->data.clip); | 507 if (!clip_node->data.inherit_parent_target_space_clip) |
| 508 clip_node->data.combined_clip.Intersect(clip_node->data.clip); | |
| 464 } | 509 } |
| 465 clip_tree->set_needs_update(false); | 510 clip_tree->set_needs_update(false); |
| 466 } | 511 } |
| 467 | 512 |
| 468 void ComputeTransforms(TransformTree* transform_tree) { | 513 void ComputeTransforms(TransformTree* transform_tree) { |
| 469 if (!transform_tree->needs_update()) | 514 if (!transform_tree->needs_update()) |
| 470 return; | 515 return; |
| 471 for (int i = 1; i < static_cast<int>(transform_tree->size()); ++i) | 516 for (int i = 1; i < static_cast<int>(transform_tree->size()); ++i) |
| 472 transform_tree->UpdateTransforms(i); | 517 transform_tree->UpdateTransforms(i); |
| 473 transform_tree->set_needs_update(false); | 518 transform_tree->set_needs_update(false); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 687 if (static_cast<int>(layer->offset_to_transform_parent().x()) != | 732 if (static_cast<int>(layer->offset_to_transform_parent().x()) != |
| 688 layer->offset_to_transform_parent().x()) | 733 layer->offset_to_transform_parent().x()) |
| 689 return false; | 734 return false; |
| 690 if (static_cast<int>(layer->offset_to_transform_parent().y()) != | 735 if (static_cast<int>(layer->offset_to_transform_parent().y()) != |
| 691 layer->offset_to_transform_parent().y()) | 736 layer->offset_to_transform_parent().y()) |
| 692 return false; | 737 return false; |
| 693 return true; | 738 return true; |
| 694 } | 739 } |
| 695 | 740 |
| 696 } // namespace cc | 741 } // namespace cc |
| OLD | NEW |