| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "platform/graphics/compositing/PaintArtifactCompositor.h" | 5 #include "platform/graphics/compositing/PaintArtifactCompositor.h" |
| 6 | 6 |
| 7 #include "cc/layers/content_layer_client.h" | 7 #include "cc/layers/content_layer_client.h" |
| 8 #include "cc/layers/layer.h" | 8 #include "cc/layers/layer.h" |
| 9 #include "cc/layers/picture_layer.h" | 9 #include "cc/layers/picture_layer.h" |
| 10 #include "cc/playback/compositing_display_item.h" | 10 #include "cc/playback/compositing_display_item.h" |
| 11 #include "cc/playback/display_item_list.h" | 11 #include "cc/playback/display_item_list.h" |
| 12 #include "cc/playback/display_item_list_settings.h" | 12 #include "cc/playback/display_item_list_settings.h" |
| 13 #include "cc/playback/drawing_display_item.h" | 13 #include "cc/playback/drawing_display_item.h" |
| 14 #include "cc/playback/filter_display_item.h" | 14 #include "cc/playback/filter_display_item.h" |
| 15 #include "cc/playback/float_clip_display_item.h" | 15 #include "cc/playback/float_clip_display_item.h" |
| 16 #include "cc/playback/transform_display_item.h" | 16 #include "cc/playback/transform_display_item.h" |
| 17 #include "cc/trees/clip_node.h" | |
| 18 #include "cc/trees/effect_node.h" | |
| 19 #include "cc/trees/layer_tree_host.h" | |
| 20 #include "cc/trees/property_tree.h" | |
| 21 #include "cc/trees/scroll_node.h" | |
| 22 #include "cc/trees/transform_node.h" | |
| 23 #include "platform/RuntimeEnabledFeatures.h" | 17 #include "platform/RuntimeEnabledFeatures.h" |
| 18 #include "platform/graphics/compositing/PropertyTreeManager.h" |
| 24 #include "platform/graphics/paint/ClipPaintPropertyNode.h" | 19 #include "platform/graphics/paint/ClipPaintPropertyNode.h" |
| 25 #include "platform/graphics/paint/DisplayItem.h" | 20 #include "platform/graphics/paint/DisplayItem.h" |
| 26 #include "platform/graphics/paint/DrawingDisplayItem.h" | 21 #include "platform/graphics/paint/DrawingDisplayItem.h" |
| 27 #include "platform/graphics/paint/ForeignLayerDisplayItem.h" | 22 #include "platform/graphics/paint/ForeignLayerDisplayItem.h" |
| 28 #include "platform/graphics/paint/GeometryMapper.h" | 23 #include "platform/graphics/paint/GeometryMapper.h" |
| 29 #include "platform/graphics/paint/PaintArtifact.h" | 24 #include "platform/graphics/paint/PaintArtifact.h" |
| 30 #include "platform/graphics/paint/PropertyTreeState.h" | 25 #include "platform/graphics/paint/PropertyTreeState.h" |
| 31 #include "platform/graphics/paint/RasterInvalidationTracking.h" | 26 #include "platform/graphics/paint/RasterInvalidationTracking.h" |
| 32 #include "platform/graphics/paint/ScrollPaintPropertyNode.h" | 27 #include "platform/graphics/paint/ScrollPaintPropertyNode.h" |
| 33 #include "platform/graphics/paint/TransformPaintPropertyNode.h" | 28 #include "platform/graphics/paint/TransformPaintPropertyNode.h" |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 const auto& foreignLayerDisplayItem = | 251 const auto& foreignLayerDisplayItem = |
| 257 static_cast<const ForeignLayerDisplayItem&>(displayItem); | 252 static_cast<const ForeignLayerDisplayItem&>(displayItem); |
| 258 layerOffset = gfx::Vector2dF(foreignLayerDisplayItem.location().x(), | 253 layerOffset = gfx::Vector2dF(foreignLayerDisplayItem.location().x(), |
| 259 foreignLayerDisplayItem.location().y()); | 254 foreignLayerDisplayItem.location().y()); |
| 260 scoped_refptr<cc::Layer> layer = foreignLayerDisplayItem.layer(); | 255 scoped_refptr<cc::Layer> layer = foreignLayerDisplayItem.layer(); |
| 261 layer->SetBounds(foreignLayerDisplayItem.bounds()); | 256 layer->SetBounds(foreignLayerDisplayItem.bounds()); |
| 262 layer->SetIsDrawable(true); | 257 layer->SetIsDrawable(true); |
| 263 return layer; | 258 return layer; |
| 264 } | 259 } |
| 265 | 260 |
| 266 constexpr int kInvalidNodeId = -1; | |
| 267 // cc's property trees use 0 for the root node (always non-null). | |
| 268 constexpr int kRealRootNodeId = 0; | |
| 269 // cc allocates special nodes for root effects such as the device scale. | |
| 270 constexpr int kSecondaryRootNodeId = 1; | |
| 271 constexpr int kPropertyTreeSequenceNumber = 1; | |
| 272 | |
| 273 enum EndDisplayItemType { EndTransform, EndClip, EndEffect }; | 261 enum EndDisplayItemType { EndTransform, EndClip, EndEffect }; |
| 274 | 262 |
| 275 // Applies the clips between |localState| and |ancestorState| into a single | 263 // Applies the clips between |localState| and |ancestorState| into a single |
| 276 // combined cc::FloatClipDisplayItem on |ccList|. | 264 // combined cc::FloatClipDisplayItem on |ccList|. |
| 277 static void applyClipsBetweenStates(const PropertyTreeState& localState, | 265 static void applyClipsBetweenStates(const PropertyTreeState& localState, |
| 278 const PropertyTreeState& ancestorState, | 266 const PropertyTreeState& ancestorState, |
| 279 cc::DisplayItemList& ccList, | 267 cc::DisplayItemList& ccList, |
| 280 Vector<EndDisplayItemType>& endDisplayItems, | 268 Vector<EndDisplayItemType>& endDisplayItems, |
| 281 GeometryMapper& geometryMapper) { | 269 GeometryMapper& geometryMapper) { |
| 282 DCHECK(localState.transform() == ancestorState.transform()); | 270 DCHECK(localState.transform() == ancestorState.transform()); |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 ccInvalidationRect, | 556 ccInvalidationRect, |
| 569 rasterTracking ? &rasterTracking->trackedRasterInvalidations[index] | 557 rasterTracking ? &rasterTracking->trackedRasterInvalidations[index] |
| 570 : nullptr); | 558 : nullptr); |
| 571 } | 559 } |
| 572 } | 560 } |
| 573 | 561 |
| 574 newContentLayerClients.push_back(std::move(contentLayerClient)); | 562 newContentLayerClients.push_back(std::move(contentLayerClient)); |
| 575 return ccPictureLayer; | 563 return ccPictureLayer; |
| 576 } | 564 } |
| 577 | 565 |
| 578 namespace { | |
| 579 | |
| 580 class PropertyTreeManager { | |
| 581 WTF_MAKE_NONCOPYABLE(PropertyTreeManager); | |
| 582 | |
| 583 public: | |
| 584 PropertyTreeManager(cc::PropertyTrees& propertyTrees, cc::Layer* rootLayer) | |
| 585 : m_propertyTrees(propertyTrees), | |
| 586 m_rootLayer(rootLayer) | |
| 587 { | |
| 588 setupRootTransformNode(); | |
| 589 setupRootClipNode(); | |
| 590 setupRootEffectNode(); | |
| 591 setupRootScrollNode(); | |
| 592 } | |
| 593 | |
| 594 void setupRootTransformNode(); | |
| 595 void setupRootClipNode(); | |
| 596 void setupRootEffectNode(); | |
| 597 void setupRootScrollNode(); | |
| 598 | |
| 599 // A brief discourse on cc property tree nodes, identifiers, and current and | |
| 600 // future design evolution envisioned: | |
| 601 // | |
| 602 // cc property trees identify nodes by their |id|, which implementation-wise | |
| 603 // is actually its index in the property tree's vector of its node type. More | |
| 604 // recent cc code now refers to these as 'node indices', or 'property tree | |
| 605 // indices'. |parent_id| is the same sort of 'node index' of that node's | |
| 606 // parent. | |
| 607 // | |
| 608 // Note there are two other primary types of 'ids' referenced in cc property | |
| 609 // tree related logic: (1) ElementId, also known Blink-side as | |
| 610 // CompositorElementId, used by the animation system to allow tying an element | |
| 611 // to its respective layer, and (2) layer ids. There are other ancillary ids | |
| 612 // not relevant to any of the above, such as | |
| 613 // cc::TransformNode::sorting_context_id | |
| 614 // (a.k.a. blink::TransformPaintPropertyNode::renderingContextId()). | |
| 615 // | |
| 616 // There is a vision to move toward a world where cc property nodes have no | |
| 617 // association with layers and instead have a |stable_id|. The id could come | |
| 618 // from an ElementId in turn derived from the layout object responsible for | |
| 619 // creating the property node. | |
| 620 // | |
| 621 // We would also like to explore moving to use a single shared property tree | |
| 622 // representation across both cc and Blink. See | |
| 623 // platform/graphics/paint/README.md for more. | |
| 624 // | |
| 625 // With the above as background, we can now state more clearly a description | |
| 626 // of the below set of compositor node methods: they take Blink paint property | |
| 627 // tree nodes as input, create a corresponding compositor property tree node | |
| 628 // if none yet exists, and return the compositor node's 'node id', a.k.a., | |
| 629 // 'node index'. | |
| 630 | |
| 631 int ensureCompositorTransformNode(const TransformPaintPropertyNode*); | |
| 632 int ensureCompositorClipNode(const ClipPaintPropertyNode*); | |
| 633 int ensureCompositorScrollNode(const ScrollPaintPropertyNode*); | |
| 634 | |
| 635 int switchToEffectNode(const EffectPaintPropertyNode& nextEffect); | |
| 636 int getCurrentCompositorEffectNodeIndex() const { | |
| 637 return m_effectStack.back().id; | |
| 638 } | |
| 639 | |
| 640 // Scroll offset has special treatment in the transform and scroll trees. | |
| 641 void updateScrollOffset(int layerId, int scrollId); | |
| 642 | |
| 643 private: | |
| 644 void buildEffectNodesRecursively(const EffectPaintPropertyNode* nextEffect); | |
| 645 | |
| 646 cc::TransformTree& transformTree() { return m_propertyTrees.transform_tree; } | |
| 647 cc::ClipTree& clipTree() { return m_propertyTrees.clip_tree; } | |
| 648 cc::EffectTree& effectTree() { return m_propertyTrees.effect_tree; } | |
| 649 cc::ScrollTree& scrollTree() { return m_propertyTrees.scroll_tree; } | |
| 650 | |
| 651 const EffectPaintPropertyNode* currentEffectNode() const { | |
| 652 return m_effectStack.back().effect; | |
| 653 } | |
| 654 | |
| 655 // Property trees which should be updated by the manager. | |
| 656 cc::PropertyTrees& m_propertyTrees; | |
| 657 | |
| 658 // Layer to which transform "owner" layers should be added. These will not | |
| 659 // have any actual children, but at present must exist in the tree. | |
| 660 cc::Layer* m_rootLayer; | |
| 661 | |
| 662 // Maps from Blink-side property tree nodes to cc property node indices. | |
| 663 HashMap<const TransformPaintPropertyNode*, int> m_transformNodeMap; | |
| 664 HashMap<const ClipPaintPropertyNode*, int> m_clipNodeMap; | |
| 665 HashMap<const ScrollPaintPropertyNode*, int> m_scrollNodeMap; | |
| 666 | |
| 667 struct BlinkEffectAndCcIdPair { | |
| 668 const EffectPaintPropertyNode* effect; | |
| 669 // The cc property tree effect node id, or 'node index', for the cc effect | |
| 670 // node corresponding to the above Blink effect paint property node. | |
| 671 int id; | |
| 672 }; | |
| 673 Vector<BlinkEffectAndCcIdPair> m_effectStack; | |
| 674 | |
| 675 #if DCHECK_IS_ON() | |
| 676 HashSet<const EffectPaintPropertyNode*> m_effectNodesConverted; | |
| 677 #endif | |
| 678 }; | |
| 679 | |
| 680 void PropertyTreeManager::setupRootTransformNode() { | |
| 681 // cc is hardcoded to use transform node index 1 for device scale and | |
| 682 // transform. | |
| 683 cc::TransformTree& transformTree = m_propertyTrees.transform_tree; | |
| 684 transformTree.clear(); | |
| 685 cc::TransformNode& transformNode = *transformTree.Node( | |
| 686 transformTree.Insert(cc::TransformNode(), kRealRootNodeId)); | |
| 687 DCHECK_EQ(transformNode.id, kSecondaryRootNodeId); | |
| 688 transformNode.source_node_id = transformNode.parent_id; | |
| 689 transformTree.SetTargetId(transformNode.id, kRealRootNodeId); | |
| 690 transformTree.SetContentTargetId(transformNode.id, kRealRootNodeId); | |
| 691 | |
| 692 // TODO(jaydasika): We shouldn't set ToScreen and FromScreen of root | |
| 693 // transform node here. They should be set while updating transform tree in | |
| 694 // cc. | |
| 695 float deviceScaleFactor = m_rootLayer->GetLayerTree()->device_scale_factor(); | |
| 696 gfx::Transform toScreen; | |
| 697 toScreen.Scale(deviceScaleFactor, deviceScaleFactor); | |
| 698 transformTree.SetToScreen(kRealRootNodeId, toScreen); | |
| 699 gfx::Transform fromScreen; | |
| 700 bool invertible = toScreen.GetInverse(&fromScreen); | |
| 701 DCHECK(invertible); | |
| 702 transformTree.SetFromScreen(kRealRootNodeId, fromScreen); | |
| 703 transformTree.set_needs_update(true); | |
| 704 | |
| 705 m_transformNodeMap.set(TransformPaintPropertyNode::root(), transformNode.id); | |
| 706 m_rootLayer->SetTransformTreeIndex(transformNode.id); | |
| 707 } | |
| 708 | |
| 709 void PropertyTreeManager::setupRootClipNode() { | |
| 710 // cc is hardcoded to use clip node index 1 for viewport clip. | |
| 711 cc::ClipTree& clipTree = m_propertyTrees.clip_tree; | |
| 712 clipTree.clear(); | |
| 713 m_propertyTrees.layer_id_to_clip_node_index.clear(); | |
| 714 cc::ClipNode& clipNode = | |
| 715 *clipTree.Node(clipTree.Insert(cc::ClipNode(), kRealRootNodeId)); | |
| 716 DCHECK_EQ(clipNode.id, kSecondaryRootNodeId); | |
| 717 | |
| 718 clipNode.resets_clip = true; | |
| 719 clipNode.owning_layer_id = m_rootLayer->id(); | |
| 720 clipNode.clip_type = cc::ClipNode::ClipType::APPLIES_LOCAL_CLIP; | |
| 721 clipNode.clip = gfx::RectF( | |
| 722 gfx::SizeF(m_rootLayer->GetLayerTree()->device_viewport_size())); | |
| 723 clipNode.transform_id = kRealRootNodeId; | |
| 724 clipNode.target_transform_id = kRealRootNodeId; | |
| 725 clipNode.target_effect_id = kSecondaryRootNodeId; | |
| 726 m_propertyTrees.layer_id_to_clip_node_index[clipNode.owning_layer_id] = | |
| 727 clipNode.id; | |
| 728 | |
| 729 m_clipNodeMap.set(ClipPaintPropertyNode::root(), clipNode.id); | |
| 730 m_rootLayer->SetClipTreeIndex(clipNode.id); | |
| 731 } | |
| 732 | |
| 733 void PropertyTreeManager::setupRootEffectNode() { | |
| 734 // cc is hardcoded to use effect node index 1 for root render surface. | |
| 735 cc::EffectTree& effectTree = m_propertyTrees.effect_tree; | |
| 736 effectTree.clear(); | |
| 737 m_propertyTrees.layer_id_to_effect_node_index.clear(); | |
| 738 cc::EffectNode& effectNode = | |
| 739 *effectTree.Node(effectTree.Insert(cc::EffectNode(), kInvalidNodeId)); | |
| 740 DCHECK_EQ(effectNode.id, kSecondaryRootNodeId); | |
| 741 effectNode.owning_layer_id = m_rootLayer->id(); | |
| 742 effectNode.transform_id = kRealRootNodeId; | |
| 743 effectNode.clip_id = kSecondaryRootNodeId; | |
| 744 effectNode.has_render_surface = true; | |
| 745 m_propertyTrees.layer_id_to_effect_node_index[effectNode.owning_layer_id] = | |
| 746 effectNode.id; | |
| 747 | |
| 748 m_effectStack.push_back( | |
| 749 BlinkEffectAndCcIdPair{EffectPaintPropertyNode::root(), effectNode.id}); | |
| 750 m_rootLayer->SetEffectTreeIndex(effectNode.id); | |
| 751 } | |
| 752 | |
| 753 void PropertyTreeManager::setupRootScrollNode() { | |
| 754 cc::ScrollTree& scrollTree = m_propertyTrees.scroll_tree; | |
| 755 scrollTree.clear(); | |
| 756 m_propertyTrees.layer_id_to_scroll_node_index.clear(); | |
| 757 cc::ScrollNode& scrollNode = | |
| 758 *scrollTree.Node(scrollTree.Insert(cc::ScrollNode(), kRealRootNodeId)); | |
| 759 DCHECK_EQ(scrollNode.id, kSecondaryRootNodeId); | |
| 760 scrollNode.owning_layer_id = m_rootLayer->id(); | |
| 761 scrollNode.transform_id = kSecondaryRootNodeId; | |
| 762 m_propertyTrees.layer_id_to_scroll_node_index[scrollNode.owning_layer_id] = | |
| 763 scrollNode.id; | |
| 764 | |
| 765 m_scrollNodeMap.set(ScrollPaintPropertyNode::root(), scrollNode.id); | |
| 766 m_rootLayer->SetScrollTreeIndex(scrollNode.id); | |
| 767 } | |
| 768 | |
| 769 int PropertyTreeManager::ensureCompositorTransformNode( | |
| 770 const TransformPaintPropertyNode* transformNode) { | |
| 771 DCHECK(transformNode); | |
| 772 // TODO(crbug.com/645615): Remove the failsafe here. | |
| 773 if (!transformNode) | |
| 774 return kSecondaryRootNodeId; | |
| 775 | |
| 776 auto it = m_transformNodeMap.find(transformNode); | |
| 777 if (it != m_transformNodeMap.end()) | |
| 778 return it->value; | |
| 779 | |
| 780 scoped_refptr<cc::Layer> dummyLayer = cc::Layer::Create(); | |
| 781 int parentId = ensureCompositorTransformNode(transformNode->parent()); | |
| 782 int id = transformTree().Insert(cc::TransformNode(), parentId); | |
| 783 | |
| 784 cc::TransformNode& compositorNode = *transformTree().Node(id); | |
| 785 transformTree().SetTargetId(id, kRealRootNodeId); | |
| 786 transformTree().SetContentTargetId(id, kRealRootNodeId); | |
| 787 compositorNode.source_node_id = parentId; | |
| 788 | |
| 789 FloatPoint3D origin = transformNode->origin(); | |
| 790 compositorNode.pre_local.matrix().setTranslate(-origin.x(), -origin.y(), | |
| 791 -origin.z()); | |
| 792 compositorNode.local.matrix() = | |
| 793 TransformationMatrix::toSkMatrix44(transformNode->matrix()); | |
| 794 compositorNode.post_local.matrix().setTranslate(origin.x(), origin.y(), | |
| 795 origin.z()); | |
| 796 compositorNode.needs_local_transform_update = true; | |
| 797 compositorNode.flattens_inherited_transform = | |
| 798 transformNode->flattensInheritedTransform(); | |
| 799 compositorNode.sorting_context_id = transformNode->renderingContextId(); | |
| 800 | |
| 801 m_rootLayer->AddChild(dummyLayer); | |
| 802 dummyLayer->SetTransformTreeIndex(id); | |
| 803 dummyLayer->SetClipTreeIndex(kSecondaryRootNodeId); | |
| 804 dummyLayer->SetEffectTreeIndex(kSecondaryRootNodeId); | |
| 805 dummyLayer->SetScrollTreeIndex(kRealRootNodeId); | |
| 806 dummyLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); | |
| 807 | |
| 808 auto result = m_transformNodeMap.set(transformNode, id); | |
| 809 DCHECK(result.isNewEntry); | |
| 810 transformTree().set_needs_update(true); | |
| 811 return id; | |
| 812 } | |
| 813 | |
| 814 int PropertyTreeManager::ensureCompositorClipNode( | |
| 815 const ClipPaintPropertyNode* clipNode) { | |
| 816 DCHECK(clipNode); | |
| 817 // TODO(crbug.com/645615): Remove the failsafe here. | |
| 818 if (!clipNode) | |
| 819 return kSecondaryRootNodeId; | |
| 820 | |
| 821 auto it = m_clipNodeMap.find(clipNode); | |
| 822 if (it != m_clipNodeMap.end()) | |
| 823 return it->value; | |
| 824 | |
| 825 scoped_refptr<cc::Layer> dummyLayer = cc::Layer::Create(); | |
| 826 int parentId = ensureCompositorClipNode(clipNode->parent()); | |
| 827 int id = clipTree().Insert(cc::ClipNode(), parentId); | |
| 828 | |
| 829 cc::ClipNode& compositorNode = *clipTree().Node(id); | |
| 830 compositorNode.owning_layer_id = dummyLayer->id(); | |
| 831 m_propertyTrees.layer_id_to_clip_node_index[compositorNode.owning_layer_id] = | |
| 832 id; | |
| 833 | |
| 834 // TODO(jbroman): Don't discard rounded corners. | |
| 835 compositorNode.clip = clipNode->clipRect().rect(); | |
| 836 compositorNode.transform_id = | |
| 837 ensureCompositorTransformNode(clipNode->localTransformSpace()); | |
| 838 compositorNode.target_transform_id = kRealRootNodeId; | |
| 839 compositorNode.target_effect_id = kSecondaryRootNodeId; | |
| 840 compositorNode.clip_type = cc::ClipNode::ClipType::APPLIES_LOCAL_CLIP; | |
| 841 compositorNode.layers_are_clipped = true; | |
| 842 compositorNode.layers_are_clipped_when_surfaces_disabled = true; | |
| 843 | |
| 844 m_rootLayer->AddChild(dummyLayer); | |
| 845 dummyLayer->SetTransformTreeIndex(compositorNode.transform_id); | |
| 846 dummyLayer->SetClipTreeIndex(id); | |
| 847 dummyLayer->SetEffectTreeIndex(kSecondaryRootNodeId); | |
| 848 dummyLayer->SetScrollTreeIndex(kRealRootNodeId); | |
| 849 dummyLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); | |
| 850 | |
| 851 auto result = m_clipNodeMap.set(clipNode, id); | |
| 852 DCHECK(result.isNewEntry); | |
| 853 clipTree().set_needs_update(true); | |
| 854 return id; | |
| 855 } | |
| 856 | |
| 857 int PropertyTreeManager::ensureCompositorScrollNode( | |
| 858 const ScrollPaintPropertyNode* scrollNode) { | |
| 859 DCHECK(scrollNode); | |
| 860 // TODO(crbug.com/645615): Remove the failsafe here. | |
| 861 if (!scrollNode) | |
| 862 return kSecondaryRootNodeId; | |
| 863 | |
| 864 auto it = m_scrollNodeMap.find(scrollNode); | |
| 865 if (it != m_scrollNodeMap.end()) | |
| 866 return it->value; | |
| 867 | |
| 868 int parentId = ensureCompositorScrollNode(scrollNode->parent()); | |
| 869 int id = scrollTree().Insert(cc::ScrollNode(), parentId); | |
| 870 | |
| 871 cc::ScrollNode& compositorNode = *scrollTree().Node(id); | |
| 872 compositorNode.owning_layer_id = parentId; | |
| 873 m_propertyTrees | |
| 874 .layer_id_to_scroll_node_index[compositorNode.owning_layer_id] = id; | |
| 875 | |
| 876 compositorNode.scrollable = true; | |
| 877 | |
| 878 compositorNode.scroll_clip_layer_bounds.SetSize(scrollNode->clip().width(), | |
| 879 scrollNode->clip().height()); | |
| 880 compositorNode.bounds.SetSize(scrollNode->bounds().width(), | |
| 881 scrollNode->bounds().height()); | |
| 882 compositorNode.user_scrollable_horizontal = | |
| 883 scrollNode->userScrollableHorizontal(); | |
| 884 compositorNode.user_scrollable_vertical = | |
| 885 scrollNode->userScrollableVertical(); | |
| 886 compositorNode.transform_id = | |
| 887 ensureCompositorTransformNode(scrollNode->scrollOffsetTranslation()); | |
| 888 compositorNode.main_thread_scrolling_reasons = | |
| 889 scrollNode->mainThreadScrollingReasons(); | |
| 890 | |
| 891 auto result = m_scrollNodeMap.set(scrollNode, id); | |
| 892 DCHECK(result.isNewEntry); | |
| 893 scrollTree().set_needs_update(true); | |
| 894 | |
| 895 return id; | |
| 896 } | |
| 897 | |
| 898 void PropertyTreeManager::updateScrollOffset(int layerId, int scrollId) { | |
| 899 cc::ScrollNode& scrollNode = *scrollTree().Node(scrollId); | |
| 900 cc::TransformNode& transformNode = | |
| 901 *transformTree().Node(scrollNode.transform_id); | |
| 902 | |
| 903 transformNode.scrolls = true; | |
| 904 | |
| 905 // Blink creates a 2d transform node just for scroll offset whereas cc's | |
| 906 // transform node has a special scroll offset field. To handle this we | |
| 907 // adjust cc's transform node to remove the 2d scroll translation and | |
| 908 // let the cc scroll tree update the cc scroll offset. | |
| 909 DCHECK(transformNode.local.IsIdentityOr2DTranslation()); | |
| 910 auto offset = transformNode.local.To2dTranslation(); | |
| 911 transformNode.local.MakeIdentity(); | |
| 912 scrollTree().SetScrollOffset(layerId, | |
| 913 gfx::ScrollOffset(-offset.x(), -offset.y())); | |
| 914 scrollTree().set_needs_update(true); | |
| 915 } | |
| 916 | |
| 917 unsigned depth(const EffectPaintPropertyNode* node) { | |
| 918 unsigned result = 0; | |
| 919 for (; node; node = node->parent()) | |
| 920 result++; | |
| 921 return result; | |
| 922 } | |
| 923 | |
| 924 // TODO(chrishtr): templatize this to avoid duplication of | |
| 925 // GeometryMapper::leastCommonAncestor. | |
| 926 const EffectPaintPropertyNode* lowestCommonAncestor( | |
| 927 const EffectPaintPropertyNode* nodeA, | |
| 928 const EffectPaintPropertyNode* nodeB) { | |
| 929 // Optimized common case. | |
| 930 if (nodeA == nodeB) | |
| 931 return nodeA; | |
| 932 | |
| 933 unsigned depthA = depth(nodeA), depthB = depth(nodeB); | |
| 934 while (depthA > depthB) { | |
| 935 nodeA = nodeA->parent(); | |
| 936 depthA--; | |
| 937 } | |
| 938 while (depthB > depthA) { | |
| 939 nodeB = nodeB->parent(); | |
| 940 depthB--; | |
| 941 } | |
| 942 DCHECK_EQ(depthA, depthB); | |
| 943 while (nodeA != nodeB) { | |
| 944 nodeA = nodeA->parent(); | |
| 945 nodeB = nodeB->parent(); | |
| 946 } | |
| 947 return nodeA; | |
| 948 } | |
| 949 | |
| 950 int PropertyTreeManager::switchToEffectNode( | |
| 951 const EffectPaintPropertyNode& nextEffect) { | |
| 952 const EffectPaintPropertyNode* ancestor = | |
| 953 lowestCommonAncestor(currentEffectNode(), &nextEffect); | |
| 954 DCHECK(ancestor) << "Malformed effect tree. All nodes must be descendant of " | |
| 955 "EffectPaintPropertyNode::root()."; | |
| 956 while (currentEffectNode() != ancestor) | |
| 957 m_effectStack.pop_back(); | |
| 958 | |
| 959 // Now the current effect is the lowest common ancestor of previous effect | |
| 960 // and the next effect. That implies it is an existing node that already has | |
| 961 // at least one paint chunk or child effect, and we are going to either attach | |
| 962 // another paint chunk or child effect to it. We can no longer omit render | |
| 963 // surface for it even for opacity-only nodes. | |
| 964 // See comments in PropertyTreeManager::buildEffectNodesRecursively(). | |
| 965 // TODO(crbug.com/504464): Remove premature optimization here. | |
| 966 if (currentEffectNode() && currentEffectNode()->opacity() != 1.f) { | |
| 967 effectTree() | |
| 968 .Node(getCurrentCompositorEffectNodeIndex()) | |
| 969 ->has_render_surface = true; | |
| 970 } | |
| 971 | |
| 972 buildEffectNodesRecursively(&nextEffect); | |
| 973 | |
| 974 return getCurrentCompositorEffectNodeIndex(); | |
| 975 } | |
| 976 | |
| 977 void PropertyTreeManager::buildEffectNodesRecursively( | |
| 978 const EffectPaintPropertyNode* nextEffect) { | |
| 979 if (nextEffect == currentEffectNode()) | |
| 980 return; | |
| 981 DCHECK(nextEffect); | |
| 982 | |
| 983 buildEffectNodesRecursively(nextEffect->parent()); | |
| 984 DCHECK_EQ(nextEffect->parent(), currentEffectNode()); | |
| 985 | |
| 986 #if DCHECK_IS_ON() | |
| 987 DCHECK(!m_effectNodesConverted.contains(nextEffect)) | |
| 988 << "Malformed paint artifact. Paint chunks under the same effect should " | |
| 989 "be contiguous."; | |
| 990 m_effectNodesConverted.add(nextEffect); | |
| 991 #endif | |
| 992 | |
| 993 // An effect node can't omit render surface if it has child with exotic | |
| 994 // blending mode. See comments below for more detail. | |
| 995 // TODO(crbug.com/504464): Remove premature optimization here. | |
| 996 if (nextEffect->blendMode() != SkBlendMode::kSrcOver) { | |
| 997 effectTree() | |
| 998 .Node(getCurrentCompositorEffectNodeIndex()) | |
| 999 ->has_render_surface = true; | |
| 1000 } | |
| 1001 | |
| 1002 // We currently create dummy layers to host effect nodes and corresponding | |
| 1003 // render surfaces. This should be removed once cc implements better support | |
| 1004 // for freestanding property trees. | |
| 1005 scoped_refptr<cc::Layer> dummyLayer = nextEffect->ensureDummyLayer(); | |
| 1006 m_rootLayer->AddChild(dummyLayer); | |
| 1007 | |
| 1008 int outputClipId = ensureCompositorClipNode(nextEffect->outputClip()); | |
| 1009 | |
| 1010 cc::EffectNode& effectNode = *effectTree().Node(effectTree().Insert( | |
| 1011 cc::EffectNode(), getCurrentCompositorEffectNodeIndex())); | |
| 1012 effectNode.owning_layer_id = dummyLayer->id(); | |
| 1013 effectNode.clip_id = outputClipId; | |
| 1014 // Every effect is supposed to have render surface enabled for grouping, | |
| 1015 // but we can get away without one if the effect is opacity-only and has only | |
| 1016 // one compositing child with kSrcOver blend mode. This is both for | |
| 1017 // optimization and not introducing sub-pixel differences in layout tests. | |
| 1018 // See PropertyTreeManager::switchToEffectNode() and above where we | |
| 1019 // retrospectively enable render surface when more than one compositing child | |
| 1020 // or a child with exotic blend mode is detected. | |
| 1021 // TODO(crbug.com/504464): There is ongoing work in cc to delay render surface | |
| 1022 // decision until later phase of the pipeline. Remove premature optimization | |
| 1023 // here once the work is ready. | |
| 1024 if (!nextEffect->filter().isEmpty() || | |
| 1025 nextEffect->blendMode() != SkBlendMode::kSrcOver) | |
| 1026 effectNode.has_render_surface = true; | |
| 1027 effectNode.opacity = nextEffect->opacity(); | |
| 1028 effectNode.filters = nextEffect->filter().asCcFilterOperations(); | |
| 1029 effectNode.blend_mode = nextEffect->blendMode(); | |
| 1030 m_propertyTrees.layer_id_to_effect_node_index[effectNode.owning_layer_id] = | |
| 1031 effectNode.id; | |
| 1032 m_effectStack.push_back(BlinkEffectAndCcIdPair{nextEffect, effectNode.id}); | |
| 1033 | |
| 1034 dummyLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); | |
| 1035 dummyLayer->SetTransformTreeIndex(kSecondaryRootNodeId); | |
| 1036 dummyLayer->SetClipTreeIndex(outputClipId); | |
| 1037 dummyLayer->SetEffectTreeIndex(effectNode.id); | |
| 1038 dummyLayer->SetScrollTreeIndex(kRealRootNodeId); | |
| 1039 } | |
| 1040 | |
| 1041 } // namespace | |
| 1042 | |
| 1043 bool PaintArtifactCompositor::canMergeInto( | 566 bool PaintArtifactCompositor::canMergeInto( |
| 1044 const PaintArtifact& paintArtifact, | 567 const PaintArtifact& paintArtifact, |
| 1045 const PaintChunk& newChunk, | 568 const PaintChunk& newChunk, |
| 1046 const PendingLayer& candidatePendingLayer) { | 569 const PendingLayer& candidatePendingLayer) { |
| 1047 const PaintChunk& pendingLayerFirstChunk = | 570 const PaintChunk& pendingLayerFirstChunk = |
| 1048 *candidatePendingLayer.paintChunks[0]; | 571 *candidatePendingLayer.paintChunks[0]; |
| 1049 if (paintArtifact.getDisplayItemList()[newChunk.beginIndex].isForeignLayer()) | 572 if (paintArtifact.getDisplayItemList()[newChunk.beginIndex].isForeignLayer()) |
| 1050 return false; | 573 return false; |
| 1051 | 574 |
| 1052 if (paintArtifact.getDisplayItemList()[pendingLayerFirstChunk.beginIndex] | 575 if (paintArtifact.getDisplayItemList()[pendingLayerFirstChunk.beginIndex] |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1160 | 683 |
| 1161 // The tree will be null after detaching and this update can be ignored. | 684 // The tree will be null after detaching and this update can be ignored. |
| 1162 // See: WebViewImpl::detachPaintArtifactCompositor(). | 685 // See: WebViewImpl::detachPaintArtifactCompositor(). |
| 1163 if (!layerTree) | 686 if (!layerTree) |
| 1164 return; | 687 return; |
| 1165 | 688 |
| 1166 if (m_extraDataForTestingEnabled) | 689 if (m_extraDataForTestingEnabled) |
| 1167 m_extraDataForTesting = WTF::wrapUnique(new ExtraDataForTesting); | 690 m_extraDataForTesting = WTF::wrapUnique(new ExtraDataForTesting); |
| 1168 | 691 |
| 1169 m_rootLayer->RemoveAllChildren(); | 692 m_rootLayer->RemoveAllChildren(); |
| 1170 m_rootLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); | 693 m_rootLayer->set_property_tree_sequence_number( |
| 694 PropertyTreeManager::kPropertyTreeSequenceNumber); |
| 1171 | 695 |
| 1172 PropertyTreeManager propertyTreeManager(*layerTree->property_trees(), | 696 PropertyTreeManager propertyTreeManager(*layerTree->property_trees(), |
| 1173 m_rootLayer.get()); | 697 m_rootLayer.get()); |
| 1174 | 698 |
| 1175 Vector<PendingLayer, 0> pendingLayers; | 699 Vector<PendingLayer, 0> pendingLayers; |
| 1176 GeometryMapper geometryMapper; | 700 GeometryMapper geometryMapper; |
| 1177 collectPendingLayers(paintArtifact, pendingLayers, geometryMapper); | 701 collectPendingLayers(paintArtifact, pendingLayers, geometryMapper); |
| 1178 | 702 |
| 1179 Vector<std::unique_ptr<ContentLayerClientImpl>> newContentLayerClients; | 703 Vector<std::unique_ptr<ContentLayerClientImpl>> newContentLayerClients; |
| 1180 newContentLayerClients.reserveCapacity(paintArtifact.paintChunks().size()); | 704 newContentLayerClients.reserveCapacity(paintArtifact.paintChunks().size()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1191 int clipId = propertyTreeManager.ensureCompositorClipNode( | 715 int clipId = propertyTreeManager.ensureCompositorClipNode( |
| 1192 pendingLayer.propertyTreeState.clip()); | 716 pendingLayer.propertyTreeState.clip()); |
| 1193 int effectId = propertyTreeManager.switchToEffectNode( | 717 int effectId = propertyTreeManager.switchToEffectNode( |
| 1194 *pendingLayer.propertyTreeState.effect()); | 718 *pendingLayer.propertyTreeState.effect()); |
| 1195 | 719 |
| 1196 propertyTreeManager.updateScrollOffset(layer->id(), scrollId); | 720 propertyTreeManager.updateScrollOffset(layer->id(), scrollId); |
| 1197 | 721 |
| 1198 layer->set_offset_to_transform_parent(layerOffset); | 722 layer->set_offset_to_transform_parent(layerOffset); |
| 1199 | 723 |
| 1200 m_rootLayer->AddChild(layer); | 724 m_rootLayer->AddChild(layer); |
| 1201 layer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); | 725 layer->set_property_tree_sequence_number( |
| 726 PropertyTreeManager::kPropertyTreeSequenceNumber); |
| 1202 layer->SetTransformTreeIndex(transformId); | 727 layer->SetTransformTreeIndex(transformId); |
| 1203 layer->SetClipTreeIndex(clipId); | 728 layer->SetClipTreeIndex(clipId); |
| 1204 layer->SetEffectTreeIndex(effectId); | 729 layer->SetEffectTreeIndex(effectId); |
| 1205 layer->SetScrollTreeIndex(scrollId); | 730 layer->SetScrollTreeIndex(scrollId); |
| 1206 | 731 |
| 1207 layer->SetShouldCheckBackfaceVisibility(pendingLayer.backfaceHidden); | 732 layer->SetShouldCheckBackfaceVisibility(pendingLayer.backfaceHidden); |
| 1208 | 733 |
| 1209 if (m_extraDataForTestingEnabled) | 734 if (m_extraDataForTestingEnabled) |
| 1210 m_extraDataForTesting->contentLayers.push_back(layer); | 735 m_extraDataForTesting->contentLayers.push_back(layer); |
| 1211 } | 736 } |
| 1212 m_contentLayerClients.clear(); | 737 m_contentLayerClients.clear(); |
| 1213 m_contentLayerClients.swap(newContentLayerClients); | 738 m_contentLayerClients.swap(newContentLayerClients); |
| 1214 | 739 |
| 1215 // Mark the property trees as having been rebuilt. | 740 // Mark the property trees as having been rebuilt. |
| 1216 layerTree->property_trees()->sequence_number = kPropertyTreeSequenceNumber; | 741 layerTree->property_trees()->sequence_number = |
| 742 PropertyTreeManager::kPropertyTreeSequenceNumber; |
| 1217 layerTree->property_trees()->needs_rebuild = false; | 743 layerTree->property_trees()->needs_rebuild = false; |
| 1218 layerTree->property_trees()->ResetCachedData(); | 744 layerTree->property_trees()->ResetCachedData(); |
| 1219 } | 745 } |
| 1220 | 746 |
| 1221 #ifndef NDEBUG | 747 #ifndef NDEBUG |
| 1222 void PaintArtifactCompositor::showDebugData() { | 748 void PaintArtifactCompositor::showDebugData() { |
| 1223 LOG(ERROR) << layersAsJSON(LayerTreeIncludesDebugInfo) | 749 LOG(ERROR) << layersAsJSON(LayerTreeIncludesDebugInfo) |
| 1224 ->toPrettyJSONString() | 750 ->toPrettyJSONString() |
| 1225 .utf8() | 751 .utf8() |
| 1226 .data(); | 752 .data(); |
| 1227 } | 753 } |
| 1228 #endif | 754 #endif |
| 1229 | 755 |
| 1230 } // namespace blink | 756 } // namespace blink |
| OLD | NEW |