Chromium Code Reviews| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include "cc/layers/content_layer_client.h" | 10 #include "cc/layers/content_layer_client.h" |
| (...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 567 } | 567 } |
| 568 } | 568 } |
| 569 | 569 |
| 570 newContentLayerClients.push_back(std::move(contentLayerClient)); | 570 newContentLayerClients.push_back(std::move(contentLayerClient)); |
| 571 return ccPictureLayer; | 571 return ccPictureLayer; |
| 572 } | 572 } |
| 573 | 573 |
| 574 bool PaintArtifactCompositor::canMergeInto( | 574 bool PaintArtifactCompositor::canMergeInto( |
| 575 const PaintArtifact& paintArtifact, | 575 const PaintArtifact& paintArtifact, |
| 576 const PaintChunk& newChunk, | 576 const PaintChunk& newChunk, |
| 577 const PendingLayer& candidatePendingLayer) { | 577 const PendingLayer& candidatePendingLayer, |
| 578 const HashSet<const EffectPaintPropertyNode*>* compositedEffectNodes) { | |
| 578 const PaintChunk& pendingLayerFirstChunk = | 579 const PaintChunk& pendingLayerFirstChunk = |
| 579 *candidatePendingLayer.paintChunks[0]; | 580 *candidatePendingLayer.paintChunks[0]; |
| 580 if (paintArtifact.getDisplayItemList()[newChunk.beginIndex].isForeignLayer()) | 581 if (paintArtifact.getDisplayItemList()[newChunk.beginIndex].isForeignLayer()) |
| 581 return false; | 582 return false; |
| 582 | 583 |
| 583 if (paintArtifact.getDisplayItemList()[pendingLayerFirstChunk.beginIndex] | 584 if (paintArtifact.getDisplayItemList()[pendingLayerFirstChunk.beginIndex] |
| 584 .isForeignLayer()) | 585 .isForeignLayer()) |
| 585 return false; | 586 return false; |
| 586 | 587 |
| 587 if (newChunk.properties.backfaceHidden != | 588 if (newChunk.properties.backfaceHidden != |
| 588 pendingLayerFirstChunk.properties.backfaceHidden) | 589 pendingLayerFirstChunk.properties.backfaceHidden) |
| 589 return false; | 590 return false; |
| 590 | 591 |
| 591 DCHECK_GE(candidatePendingLayer.paintChunks.size(), 1u); | 592 DCHECK_GE(candidatePendingLayer.paintChunks.size(), 1u); |
| 592 PropertyTreeStateIterator iterator(newChunk.properties.propertyTreeState); | 593 PropertyTreeStateIterator iterator(newChunk.properties.propertyTreeState); |
| 593 for (const PropertyTreeState* currentState = | 594 for (const PropertyTreeState* currentState = |
| 594 &newChunk.properties.propertyTreeState; | 595 &newChunk.properties.propertyTreeState; |
| 595 currentState; currentState = iterator.next()) { | 596 currentState; currentState = iterator.next()) { |
| 596 if (*currentState == candidatePendingLayer.propertyTreeState) | 597 if (*currentState == candidatePendingLayer.propertyTreeState) |
| 597 return true; | 598 return true; |
| 598 if (currentState->hasDirectCompositingReasons()) | 599 if (currentState->hasDirectCompositingReasons()) |
| 599 return false; | 600 return false; |
| 601 if (compositedEffectNodes && | |
| 602 compositedEffectNodes->find(currentState->effect()) != | |
| 603 compositedEffectNodes->end()) { | |
|
trchen
2017/03/01 23:02:59
I think this line will over-composite many of the
| |
| 604 LOG(ERROR) << "newly composited"; | |
| 605 return false; | |
| 606 } | |
| 600 } | 607 } |
| 601 return false; | 608 return false; |
| 602 } | 609 } |
| 603 | 610 |
| 604 bool PaintArtifactCompositor::mightOverlap( | 611 bool PaintArtifactCompositor::mightOverlap( |
| 605 const PaintChunk& paintChunk, | 612 const PaintChunk& paintChunk, |
| 606 const PendingLayer& candidatePendingLayer, | 613 const PendingLayer& candidatePendingLayer, |
| 607 GeometryMapper& geometryMapper) { | 614 GeometryMapper& geometryMapper) { |
| 608 PropertyTreeState rootPropertyTreeState(TransformPaintPropertyNode::root(), | 615 PropertyTreeState rootPropertyTreeState(TransformPaintPropertyNode::root(), |
| 609 ClipPaintPropertyNode::root(), | 616 ClipPaintPropertyNode::root(), |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 651 if (bounds.size() != paintChunk.bounds.size()) | 658 if (bounds.size() != paintChunk.bounds.size()) |
| 652 knownToBeOpaque = false; | 659 knownToBeOpaque = false; |
| 653 else | 660 else |
| 654 knownToBeOpaque = paintChunk.knownToBeOpaque; | 661 knownToBeOpaque = paintChunk.knownToBeOpaque; |
| 655 } | 662 } |
| 656 } | 663 } |
| 657 | 664 |
| 658 void PaintArtifactCompositor::collectPendingLayers( | 665 void PaintArtifactCompositor::collectPendingLayers( |
| 659 const PaintArtifact& paintArtifact, | 666 const PaintArtifact& paintArtifact, |
| 660 Vector<PendingLayer>& pendingLayers, | 667 Vector<PendingLayer>& pendingLayers, |
| 661 GeometryMapper& geometryMapper) { | 668 GeometryMapper& geometryMapper, |
| 669 const HashSet<const EffectPaintPropertyNode*>& compositedEffectNodes) { | |
| 662 // n = # of paint chunks. Memoizing canMergeInto() can get it to O(n^2), and | 670 // n = # of paint chunks. Memoizing canMergeInto() can get it to O(n^2), and |
| 663 // other heuristics can make worst-case behavior better. | 671 // other heuristics can make worst-case behavior better. |
| 664 for (const PaintChunk& paintChunk : paintArtifact.paintChunks()) { | 672 for (const PaintChunk& paintChunk : paintArtifact.paintChunks()) { |
| 665 bool createNew = true; | 673 bool createNew = true; |
| 666 for (Vector<PendingLayer>::reverse_iterator candidatePendingLayer = | 674 for (Vector<PendingLayer>::reverse_iterator candidatePendingLayer = |
| 667 pendingLayers.rbegin(); | 675 pendingLayers.rbegin(); |
| 668 candidatePendingLayer != pendingLayers.rend(); | 676 candidatePendingLayer != pendingLayers.rend(); |
| 669 ++candidatePendingLayer) { | 677 ++candidatePendingLayer) { |
| 670 if (canMergeInto(paintArtifact, paintChunk, *candidatePendingLayer)) { | 678 if (canMergeInto(paintArtifact, paintChunk, *candidatePendingLayer, |
| 679 &compositedEffectNodes)) { | |
| 671 candidatePendingLayer->add(paintChunk, &geometryMapper); | 680 candidatePendingLayer->add(paintChunk, &geometryMapper); |
| 672 createNew = false; | 681 createNew = false; |
| 673 break; | 682 break; |
| 674 } | 683 } |
| 675 if (mightOverlap(paintChunk, *candidatePendingLayer, geometryMapper)) { | 684 if (mightOverlap(paintChunk, *candidatePendingLayer, geometryMapper)) { |
| 676 break; | 685 break; |
| 677 } | 686 } |
| 678 } | 687 } |
| 679 if (createNew) | 688 if (createNew) |
| 680 pendingLayers.push_back(PendingLayer(paintChunk)); | 689 pendingLayers.push_back(PendingLayer(paintChunk)); |
| 681 } | 690 } |
| 682 } | 691 } |
| 683 | 692 |
| 693 static void addEffectNodesUpToRoot( | |
| 694 const PaintChunk& paintChunk, | |
| 695 HashSet<const EffectPaintPropertyNode*>& compositedEffectNodes) { | |
| 696 const EffectPaintPropertyNode* effect = | |
| 697 paintChunk.properties.propertyTreeState.effect(); | |
| 698 while (effect) { | |
| 699 compositedEffectNodes.insert(effect); | |
| 700 effect = effect->parent(); | |
| 701 } | |
| 702 } | |
| 703 | |
| 704 static void checkEffectNodesUpToRoot( | |
| 705 const PaintChunk& paintChunk, | |
| 706 unsigned currentIndex, | |
| 707 HashSet<const EffectPaintPropertyNode*>& compositedEffectNodes, | |
| 708 HashMap<const EffectPaintPropertyNode*, unsigned>& effectNodeLayerIndex) { | |
| 709 const EffectPaintPropertyNode* effect = | |
| 710 paintChunk.properties.propertyTreeState.effect(); | |
| 711 while (effect) { | |
| 712 auto it = effectNodeLayerIndex.find(effect); | |
| 713 if (it != effectNodeLayerIndex.end() && it->value != currentIndex) | |
| 714 compositedEffectNodes.insert(effect); | |
| 715 else | |
| 716 effectNodeLayerIndex.set(effect, currentIndex); | |
| 717 effect = effect->parent(); | |
| 718 } | |
| 719 } | |
| 720 | |
| 721 void PaintArtifactCompositor::collectCompositedEffectNodes( | |
| 722 const Vector<PendingLayer>& pendingLayers, | |
| 723 HashSet<const EffectPaintPropertyNode*>& compositedEffectNodes) { | |
| 724 HashMap<const EffectPaintPropertyNode*, unsigned> effectNodeLayerIndex; | |
| 725 for (unsigned currentIndex = 0; currentIndex < pendingLayers.size(); | |
| 726 ++currentIndex) { | |
| 727 const PendingLayer& pendingLayer = pendingLayers[currentIndex]; | |
| 728 for (const auto* paintChunk : pendingLayer.paintChunks) { | |
| 729 if (paintChunk->properties.propertyTreeState | |
| 730 .hasDirectCompositingReasons()) { | |
|
trchen
2017/03/01 23:02:59
propertyTreeState.hasDirectCompositingReasons() on
| |
| 731 addEffectNodesUpToRoot(*paintChunk, compositedEffectNodes); | |
| 732 } else { | |
| 733 checkEffectNodesUpToRoot(*paintChunk, currentIndex, | |
| 734 compositedEffectNodes, effectNodeLayerIndex); | |
| 735 } | |
| 736 } | |
| 737 } | |
| 738 } | |
| 739 | |
| 684 void PaintArtifactCompositor::update( | 740 void PaintArtifactCompositor::update( |
| 685 const PaintArtifact& paintArtifact, | 741 const PaintArtifact& paintArtifact, |
| 686 RasterInvalidationTrackingMap<const PaintChunk>* rasterChunkInvalidations, | 742 RasterInvalidationTrackingMap<const PaintChunk>* rasterChunkInvalidations, |
| 687 bool storeDebugInfo, | 743 bool storeDebugInfo, |
| 688 GeometryMapper& geometryMapper) { | 744 GeometryMapper& geometryMapper) { |
| 689 #ifndef NDEBUG | 745 #ifndef NDEBUG |
| 690 storeDebugInfo = true; | 746 storeDebugInfo = true; |
| 691 #endif | 747 #endif |
| 692 | 748 |
| 693 DCHECK(m_rootLayer); | 749 DCHECK(m_rootLayer); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 704 | 760 |
| 705 m_rootLayer->RemoveAllChildren(); | 761 m_rootLayer->RemoveAllChildren(); |
| 706 | 762 |
| 707 m_rootLayer->set_property_tree_sequence_number(sPropertyTreeSequenceNumber); | 763 m_rootLayer->set_property_tree_sequence_number(sPropertyTreeSequenceNumber); |
| 708 | 764 |
| 709 PropertyTreeManager propertyTreeManager(*layerTreeHost->property_trees(), | 765 PropertyTreeManager propertyTreeManager(*layerTreeHost->property_trees(), |
| 710 m_rootLayer.get(), | 766 m_rootLayer.get(), |
| 711 sPropertyTreeSequenceNumber); | 767 sPropertyTreeSequenceNumber); |
| 712 | 768 |
| 713 Vector<PendingLayer, 0> pendingLayers; | 769 Vector<PendingLayer, 0> pendingLayers; |
| 714 collectPendingLayers(paintArtifact, pendingLayers, geometryMapper); | 770 { |
| 771 HashSet<const EffectPaintPropertyNode*> compositedEffectNodes; | |
| 772 Vector<PendingLayer, 0> tentativePendingLayers; | |
| 773 LOG(ERROR) << "first pass"; | |
| 774 collectPendingLayers(paintArtifact, tentativePendingLayers, geometryMapper, | |
| 775 compositedEffectNodes); | |
| 776 collectCompositedEffectNodes(tentativePendingLayers, compositedEffectNodes); | |
| 777 LOG(ERROR) << "# composited effect nodes: " << compositedEffectNodes.size(); | |
| 778 LOG(ERROR) << "second pass"; | |
| 779 collectPendingLayers(paintArtifact, pendingLayers, geometryMapper, | |
| 780 compositedEffectNodes); | |
| 781 } | |
| 715 | 782 |
| 716 Vector<std::unique_ptr<ContentLayerClientImpl>> newContentLayerClients; | 783 Vector<std::unique_ptr<ContentLayerClientImpl>> newContentLayerClients; |
| 717 newContentLayerClients.reserveCapacity(paintArtifact.paintChunks().size()); | 784 newContentLayerClients.reserveCapacity(paintArtifact.paintChunks().size()); |
| 718 for (const PendingLayer& pendingLayer : pendingLayers) { | 785 for (const PendingLayer& pendingLayer : pendingLayers) { |
| 719 gfx::Vector2dF layerOffset; | 786 gfx::Vector2dF layerOffset; |
| 720 scoped_refptr<cc::Layer> layer = compositedLayerForPendingLayer( | 787 scoped_refptr<cc::Layer> layer = compositedLayerForPendingLayer( |
| 721 paintArtifact, pendingLayer, layerOffset, newContentLayerClients, | 788 paintArtifact, pendingLayer, layerOffset, newContentLayerClients, |
| 722 rasterChunkInvalidations, storeDebugInfo, geometryMapper); | 789 rasterChunkInvalidations, storeDebugInfo, geometryMapper); |
| 723 | 790 |
| 724 const auto* transform = pendingLayer.propertyTreeState.transform(); | 791 const auto* transform = pendingLayer.propertyTreeState.transform(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 759 #ifndef NDEBUG | 826 #ifndef NDEBUG |
| 760 void PaintArtifactCompositor::showDebugData() { | 827 void PaintArtifactCompositor::showDebugData() { |
| 761 LOG(ERROR) << layersAsJSON(LayerTreeIncludesDebugInfo) | 828 LOG(ERROR) << layersAsJSON(LayerTreeIncludesDebugInfo) |
| 762 ->toPrettyJSONString() | 829 ->toPrettyJSONString() |
| 763 .utf8() | 830 .utf8() |
| 764 .data(); | 831 .data(); |
| 765 } | 832 } |
| 766 #endif | 833 #endif |
| 767 | 834 |
| 768 } // namespace blink | 835 } // namespace blink |
| OLD | NEW |