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( |
| 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 Loading... |
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 |
OLD | NEW |