| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 if (clip_node->data.target_id < target_node->id) { | 155 if (clip_node->data.target_id < target_node->id) { |
| 156 combined_clip_rect_in_target_space = | 156 combined_clip_rect_in_target_space = |
| 157 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( | 157 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( |
| 158 clip_to_target, clip_node->data.clip_in_target_space)); | 158 clip_to_target, clip_node->data.clip_in_target_space)); |
| 159 } else { | 159 } else { |
| 160 combined_clip_rect_in_target_space = | 160 combined_clip_rect_in_target_space = |
| 161 gfx::ToEnclosingRect(MathUtil::MapClippedRect( | 161 gfx::ToEnclosingRect(MathUtil::MapClippedRect( |
| 162 clip_to_target, clip_node->data.clip_in_target_space)); | 162 clip_to_target, clip_node->data.clip_in_target_space)); |
| 163 } | 163 } |
| 164 clip_rect_in_target_space = combined_clip_rect_in_target_space; | 164 clip_rect_in_target_space = combined_clip_rect_in_target_space; |
| 165 | |
| 166 } else { | 165 } else { |
| 167 clip_rect_in_target_space = | 166 clip_rect_in_target_space = |
| 168 gfx::ToEnclosingRect(clip_node->data.clip_in_target_space); | 167 gfx::ToEnclosingRect(clip_node->data.clip_in_target_space); |
| 169 if (clip_node->data.target_is_clipped || !non_root_surfaces_enabled) | 168 if (clip_node->data.target_is_clipped || !non_root_surfaces_enabled) |
| 170 combined_clip_rect_in_target_space = gfx::ToEnclosingRect( | 169 combined_clip_rect_in_target_space = gfx::ToEnclosingRect( |
| 171 clip_node->data.combined_clip_in_target_space); | 170 clip_node->data.combined_clip_in_target_space); |
| 172 else | 171 else |
| 173 combined_clip_rect_in_target_space = clip_rect_in_target_space; | 172 combined_clip_rect_in_target_space = clip_rect_in_target_space; |
| 174 } | 173 } |
| 175 | 174 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 return; | 359 return; |
| 361 } | 360 } |
| 362 | 361 |
| 363 EffectNode* node = effect_tree->Node(layer->effect_tree_index()); | 362 EffectNode* node = effect_tree->Node(layer->effect_tree_index()); |
| 364 | 363 |
| 365 if (node->owner_id == layer->id() && node->data.has_render_surface) | 364 if (node->owner_id == layer->id() && node->data.has_render_surface) |
| 366 layer->SetHasRenderSurface(true); | 365 layer->SetHasRenderSurface(true); |
| 367 else | 366 else |
| 368 layer->SetHasRenderSurface(false); | 367 layer->SetHasRenderSurface(false); |
| 369 } | 368 } |
| 370 | |
| 371 } // namespace | 369 } // namespace |
| 372 | 370 |
| 373 template <typename LayerType> | 371 template <typename LayerType> |
| 374 static inline bool LayerShouldBeSkippedInternal( | 372 static inline bool LayerShouldBeSkippedInternal( |
| 375 LayerType* layer, | 373 LayerType* layer, |
| 376 bool layer_is_drawn, | 374 bool layer_is_drawn, |
| 377 const TransformTree& transform_tree, | 375 const TransformTree& transform_tree, |
| 378 const EffectTree& effect_tree) { | 376 const EffectTree& effect_tree) { |
| 379 const TransformNode* transform_node = | 377 const TransformNode* transform_node = |
| 380 transform_tree.Node(layer->transform_tree_index()); | 378 transform_tree.Node(layer->transform_tree_index()); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 } | 606 } |
| 609 | 607 |
| 610 void ComputeEffects(EffectTree* effect_tree) { | 608 void ComputeEffects(EffectTree* effect_tree) { |
| 611 if (!effect_tree->needs_update()) | 609 if (!effect_tree->needs_update()) |
| 612 return; | 610 return; |
| 613 for (int i = 1; i < static_cast<int>(effect_tree->size()); ++i) | 611 for (int i = 1; i < static_cast<int>(effect_tree->size()); ++i) |
| 614 effect_tree->UpdateEffects(i); | 612 effect_tree->UpdateEffects(i); |
| 615 effect_tree->set_needs_update(false); | 613 effect_tree->set_needs_update(false); |
| 616 } | 614 } |
| 617 | 615 |
| 616 static gfx::RectF ComputeCurrentClip(const ClipNode* clip_node, |
| 617 const TransformTree& transform_tree, |
| 618 int target_transform_id) { |
| 619 if (clip_node->data.transform_id != target_transform_id) { |
| 620 gfx::Transform current_to_target; |
| 621 if (!transform_tree.ComputeTransformWithDestinationSublayerScale( |
| 622 clip_node->data.transform_id, target_transform_id, |
| 623 ¤t_to_target)) |
| 624 return gfx::RectF(); |
| 625 if (clip_node->data.transform_id > target_transform_id) |
| 626 return MathUtil::MapClippedRect(current_to_target, clip_node->data.clip); |
| 627 else |
| 628 return MathUtil::ProjectClippedRect(current_to_target, |
| 629 clip_node->data.clip); |
| 630 } else { |
| 631 gfx::RectF current_clip = clip_node->data.clip; |
| 632 gfx::Vector2dF sublayer_scale = |
| 633 transform_tree.Node(target_transform_id)->data.sublayer_scale; |
| 634 if (sublayer_scale.x() > 0 && sublayer_scale.y() > 0) { |
| 635 current_clip.Scale(sublayer_scale.x(), sublayer_scale.y()); |
| 636 } |
| 637 return current_clip; |
| 638 } |
| 639 } |
| 640 |
| 641 static gfx::RectF ComputeAccumulatedClip(const ClipTree& clip_tree, |
| 642 int local_clip_id, |
| 643 const EffectTree& effect_tree, |
| 644 int target_id, |
| 645 const TransformTree& transform_tree) { |
| 646 const ClipNode* clip_node = clip_tree.Node(local_clip_id); |
| 647 const EffectNode* target_node = effect_tree.Node(target_id); |
| 648 int target_transform_id = target_node->data.transform_id; |
| 649 |
| 650 // Collect all the clips that need to be accumulated. |
| 651 std::stack<const ClipNode*> parent_chain; |
| 652 |
| 653 // If target is not direct ancestor of clip, this will find least common |
| 654 // ancestor between the target and the clip. |
| 655 while (target_node->id >= 0 && clip_node->id >= 0) { |
| 656 while (target_node->data.clip_id > clip_node->id || |
| 657 target_node->data.has_unclipped_descendants) { |
| 658 target_node = effect_tree.Node(target_node->data.target_id); |
| 659 } |
| 660 if (target_node->data.clip_id == clip_node->id) |
| 661 break; |
| 662 while (target_node->data.clip_id < clip_node->id) { |
| 663 parent_chain.push(clip_node); |
| 664 clip_node = clip_tree.parent(clip_node); |
| 665 } |
| 666 if (target_node->data.clip_id == clip_node->id) { |
| 667 clip_node = parent_chain.top(); |
| 668 parent_chain.pop(); |
| 669 break; |
| 670 } |
| 671 } |
| 672 |
| 673 // TODO(weiliangc): If we don't create clip for render surface, we don't need |
| 674 // to check applies_local_clip. |
| 675 while (!clip_node->data.applies_local_clip && parent_chain.size() > 0) { |
| 676 clip_node = parent_chain.top(); |
| 677 parent_chain.pop(); |
| 678 } |
| 679 |
| 680 if (!clip_node->data.applies_local_clip) |
| 681 return gfx::RectF(); |
| 682 |
| 683 gfx::RectF accumulated_clip = |
| 684 ComputeCurrentClip(clip_node, transform_tree, target_transform_id); |
| 685 |
| 686 while (parent_chain.size() > 0) { |
| 687 clip_node = parent_chain.top(); |
| 688 parent_chain.pop(); |
| 689 if (!clip_node->data.applies_local_clip) { |
| 690 continue; |
| 691 } |
| 692 gfx::RectF current_clip = |
| 693 ComputeCurrentClip(clip_node, transform_tree, target_transform_id); |
| 694 |
| 695 if (current_clip.IsEmpty()) |
| 696 return gfx::RectF(); |
| 697 |
| 698 accumulated_clip = gfx::IntersectRects(accumulated_clip, current_clip); |
| 699 } |
| 700 |
| 701 return accumulated_clip.IsEmpty() ? gfx::RectF() : accumulated_clip; |
| 702 } |
| 703 |
| 704 static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) { |
| 705 EffectTree* effect_tree = &property_trees->effect_tree; |
| 706 const ClipTree* clip_tree = &property_trees->clip_tree; |
| 707 const TransformTree* transform_tree = &property_trees->transform_tree; |
| 708 EffectNode* root_effect_node = effect_tree->Node(1); |
| 709 const RenderSurfaceImpl* root_render_surface = |
| 710 root_effect_node->data.render_surface; |
| 711 gfx::Rect root_clip = gfx::ToEnclosingRect( |
| 712 clip_tree->Node(root_effect_node->data.clip_id)->data.clip); |
| 713 if (root_render_surface->is_clipped()) |
| 714 DCHECK(root_clip == root_render_surface->clip_rect()) |
| 715 << "clip on root render surface: " |
| 716 << root_render_surface->clip_rect().ToString() |
| 717 << " v.s. root effect node's clip: " << root_clip.ToString(); |
| 718 for (int i = 2; i < static_cast<int>(effect_tree->size()); ++i) { |
| 719 EffectNode* effect_node = effect_tree->Node(i); |
| 720 const EffectNode* target_node = |
| 721 effect_tree->Node(effect_node->data.target_id); |
| 722 gfx::RectF accumulated_clip = |
| 723 ComputeAccumulatedClip(*clip_tree, effect_node->data.clip_id, |
| 724 *effect_tree, target_node->id, *transform_tree); |
| 725 const RenderSurfaceImpl* render_surface = effect_node->data.render_surface; |
| 726 if (render_surface && render_surface->is_clipped()) { |
| 727 DCHECK(gfx::ToEnclosingRect(accumulated_clip) == |
| 728 render_surface->clip_rect()) |
| 729 << " render surface's clip rect: " |
| 730 << render_surface->clip_rect().ToString() |
| 731 << " v.s. accumulated clip: " |
| 732 << gfx::ToEnclosingRect(accumulated_clip).ToString(); |
| 733 } |
| 734 } |
| 735 } |
| 736 |
| 737 static void ComputeLayerClipRect(const PropertyTrees* property_trees, |
| 738 const LayerImpl* layer) { |
| 739 const EffectTree* effect_tree = &property_trees->effect_tree; |
| 740 const ClipTree* clip_tree = &property_trees->clip_tree; |
| 741 const TransformTree* transform_tree = &property_trees->transform_tree; |
| 742 const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); |
| 743 const EffectNode* target_node = |
| 744 effect_node->data.has_render_surface |
| 745 ? effect_node |
| 746 : effect_tree->Node(effect_node->data.target_id); |
| 747 // TODO(weiliangc): When effect node has up to date render surface info on |
| 748 // compositor thread, no need to check for resourceless draw mode |
| 749 if (!property_trees->non_root_surfaces_enabled) { |
| 750 target_node = effect_tree->Node(1); |
| 751 } |
| 752 |
| 753 gfx::RectF accumulated_clip = |
| 754 ComputeAccumulatedClip(*clip_tree, layer->clip_tree_index(), *effect_tree, |
| 755 target_node->id, *transform_tree); |
| 756 |
| 757 if ((!property_trees->non_root_surfaces_enabled && |
| 758 clip_tree->Node(layer->clip_tree_index()) |
| 759 ->data.layers_are_clipped_when_surfaces_disabled) || |
| 760 clip_tree->Node(layer->clip_tree_index())->data.layers_are_clipped) { |
| 761 DCHECK(layer->clip_rect() == gfx::ToEnclosingRect(accumulated_clip)) |
| 762 << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index() |
| 763 << " layer clip: " << layer->clip_rect().ToString() << " v.s. " |
| 764 << gfx::ToEnclosingRect(accumulated_clip).ToString() |
| 765 << " and clip node clip: " |
| 766 << gfx::ToEnclosingRect(clip_tree->Node(layer->clip_tree_index()) |
| 767 ->data.clip_in_target_space) |
| 768 .ToString(); |
| 769 } |
| 770 } |
| 771 |
| 618 static void ComputeVisibleRectsInternal( | 772 static void ComputeVisibleRectsInternal( |
| 619 LayerImpl* root_layer, | 773 LayerImpl* root_layer, |
| 620 PropertyTrees* property_trees, | 774 PropertyTrees* property_trees, |
| 621 bool can_render_to_separate_surface, | 775 bool can_render_to_separate_surface, |
| 622 LayerImplList* update_layer_list, | 776 LayerImplList* update_layer_list, |
| 623 std::vector<LayerImpl*>* visible_layer_list) { | 777 std::vector<LayerImpl*>* visible_layer_list) { |
| 624 if (property_trees->non_root_surfaces_enabled != | 778 if (property_trees->non_root_surfaces_enabled != |
| 625 can_render_to_separate_surface) { | 779 can_render_to_separate_surface) { |
| 626 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; | 780 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; |
| 627 property_trees->transform_tree.set_needs_update(true); | 781 property_trees->transform_tree.set_needs_update(true); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 638 FindLayersThatNeedUpdates( | 792 FindLayersThatNeedUpdates( |
| 639 root_layer->layer_tree_impl(), property_trees->transform_tree, | 793 root_layer->layer_tree_impl(), property_trees->transform_tree, |
| 640 property_trees->effect_tree, update_layer_list, visible_layer_list); | 794 property_trees->effect_tree, update_layer_list, visible_layer_list); |
| 641 CalculateVisibleRects<LayerImpl>( | 795 CalculateVisibleRects<LayerImpl>( |
| 642 *visible_layer_list, property_trees->clip_tree, | 796 *visible_layer_list, property_trees->clip_tree, |
| 643 property_trees->transform_tree, can_render_to_separate_surface); | 797 property_trees->transform_tree, can_render_to_separate_surface); |
| 644 } | 798 } |
| 645 | 799 |
| 646 void UpdateRenderSurfaces(Layer* root_layer, PropertyTrees* property_trees) { | 800 void UpdateRenderSurfaces(Layer* root_layer, PropertyTrees* property_trees) { |
| 647 for (auto* layer : *root_layer->layer_tree_host()) { | 801 for (auto* layer : *root_layer->layer_tree_host()) { |
| 648 UpdateRenderSurfaceForLayer(&property_trees->effect_tree, true, layer); | 802 UpdateRenderSurfaceForLayer(&property_trees->effect_tree, |
| 803 property_trees->non_root_surfaces_enabled, |
| 804 layer); |
| 649 #if DCHECK_IS_ON() | 805 #if DCHECK_IS_ON() |
| 650 ValidateRenderSurfaceForLayer(layer); | 806 ValidateRenderSurfaceForLayer(layer); |
| 651 #endif | 807 #endif |
| 652 } | 808 } |
| 653 } | 809 } |
| 654 | 810 |
| 655 void UpdatePropertyTrees(PropertyTrees* property_trees, | 811 void UpdatePropertyTrees(PropertyTrees* property_trees, |
| 656 bool can_render_to_separate_surface) { | 812 bool can_render_to_separate_surface) { |
| 657 if (property_trees->non_root_surfaces_enabled != | 813 if (property_trees->non_root_surfaces_enabled != |
| 658 can_render_to_separate_surface) { | 814 can_render_to_separate_surface) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 LayerImplList* visible_layer_list) { | 847 LayerImplList* visible_layer_list) { |
| 692 PropertyTreeBuilder::BuildPropertyTrees( | 848 PropertyTreeBuilder::BuildPropertyTrees( |
| 693 root_layer, page_scale_layer, inner_viewport_scroll_layer, | 849 root_layer, page_scale_layer, inner_viewport_scroll_layer, |
| 694 outer_viewport_scroll_layer, overscroll_elasticity_layer, | 850 outer_viewport_scroll_layer, overscroll_elasticity_layer, |
| 695 elastic_overscroll, page_scale_factor, device_scale_factor, viewport, | 851 elastic_overscroll, page_scale_factor, device_scale_factor, viewport, |
| 696 device_transform, property_trees); | 852 device_transform, property_trees); |
| 697 ComputeVisibleRects(root_layer, property_trees, | 853 ComputeVisibleRects(root_layer, property_trees, |
| 698 can_render_to_separate_surface, visible_layer_list); | 854 can_render_to_separate_surface, visible_layer_list); |
| 699 } | 855 } |
| 700 | 856 |
| 857 void VerifyClipTreeCalculations(const LayerImplList& layer_list, |
| 858 PropertyTrees* property_trees) { |
| 859 if (property_trees->non_root_surfaces_enabled) { |
| 860 ComputeClipsWithEffectTree(property_trees); |
| 861 } |
| 862 for (auto layer : layer_list) |
| 863 ComputeLayerClipRect(property_trees, layer); |
| 864 } |
| 865 |
| 701 void ComputeVisibleRects(LayerImpl* root_layer, | 866 void ComputeVisibleRects(LayerImpl* root_layer, |
| 702 PropertyTrees* property_trees, | 867 PropertyTrees* property_trees, |
| 703 bool can_render_to_separate_surface, | 868 bool can_render_to_separate_surface, |
| 704 LayerImplList* visible_layer_list) { | 869 LayerImplList* visible_layer_list) { |
| 705 for (auto* layer : *root_layer->layer_tree_impl()) { | 870 for (auto* layer : *root_layer->layer_tree_impl()) { |
| 706 UpdateRenderSurfaceForLayer(&property_trees->effect_tree, | 871 UpdateRenderSurfaceForLayer(&property_trees->effect_tree, |
| 707 can_render_to_separate_surface, layer); | 872 can_render_to_separate_surface, layer); |
| 708 EffectNode* node = | 873 EffectNode* node = |
| 709 property_trees->effect_tree.Node(layer->effect_tree_index()); | 874 property_trees->effect_tree.Node(layer->effect_tree_index()); |
| 710 if (node->owner_id == layer->id()) | 875 if (node->owner_id == layer->id()) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 768 &render_surface_transform); | 933 &render_surface_transform); |
| 769 if (node->data.sublayer_scale.x() != 0.0 && | 934 if (node->data.sublayer_scale.x() != 0.0 && |
| 770 node->data.sublayer_scale.y() != 0.0) | 935 node->data.sublayer_scale.y() != 0.0) |
| 771 render_surface_transform.Scale(1.0 / node->data.sublayer_scale.x(), | 936 render_surface_transform.Scale(1.0 / node->data.sublayer_scale.x(), |
| 772 1.0 / node->data.sublayer_scale.y()); | 937 1.0 / node->data.sublayer_scale.y()); |
| 773 render_surface->SetDrawTransform(render_surface_transform); | 938 render_surface->SetDrawTransform(render_surface_transform); |
| 774 } | 939 } |
| 775 | 940 |
| 776 static void SetSurfaceIsClipped(const ClipNode* clip_node, | 941 static void SetSurfaceIsClipped(const ClipNode* clip_node, |
| 777 RenderSurfaceImpl* render_surface) { | 942 RenderSurfaceImpl* render_surface) { |
| 778 // If the render surface's owning layer doesn't form a clip node, it is not | 943 DCHECK(render_surface->OwningLayerId() == clip_node->owner_id) |
| 779 // clipped. | 944 << "we now create clip node for every render surface"; |
| 780 if (render_surface->OwningLayerId() != clip_node->owner_id) | 945 |
| 781 render_surface->SetIsClipped(false); | 946 render_surface->SetIsClipped(clip_node->data.target_is_clipped); |
| 782 else | |
| 783 render_surface->SetIsClipped(clip_node->data.target_is_clipped); | |
| 784 } | 947 } |
| 785 | 948 |
| 786 static void SetSurfaceClipRect(const ClipNode* parent_clip_node, | 949 static void SetSurfaceClipRect(const ClipNode* parent_clip_node, |
| 787 const TransformTree& transform_tree, | 950 const TransformTree& transform_tree, |
| 788 RenderSurfaceImpl* render_surface) { | 951 RenderSurfaceImpl* render_surface) { |
| 789 if (!render_surface->is_clipped()) { | 952 if (!render_surface->is_clipped()) { |
| 790 render_surface->SetClipRect(gfx::Rect()); | 953 render_surface->SetClipRect(gfx::Rect()); |
| 791 return; | 954 return; |
| 792 } | 955 } |
| 793 | 956 |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1113 void UpdateElasticOverscroll(PropertyTrees* property_trees, | 1276 void UpdateElasticOverscroll(PropertyTrees* property_trees, |
| 1114 const Layer* overscroll_elasticity_layer, | 1277 const Layer* overscroll_elasticity_layer, |
| 1115 const gfx::Vector2dF& elastic_overscroll) { | 1278 const gfx::Vector2dF& elastic_overscroll) { |
| 1116 UpdateElasticOverscrollInternal(property_trees, overscroll_elasticity_layer, | 1279 UpdateElasticOverscrollInternal(property_trees, overscroll_elasticity_layer, |
| 1117 elastic_overscroll); | 1280 elastic_overscroll); |
| 1118 } | 1281 } |
| 1119 | 1282 |
| 1120 } // namespace draw_property_utils | 1283 } // namespace draw_property_utils |
| 1121 | 1284 |
| 1122 } // namespace cc | 1285 } // namespace cc |
| OLD | NEW |