Chromium Code Reviews| Index: third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp |
| diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp |
| index 0eb639fbf389ffe8fadbaeda3df2d29ee8cf53d3..89e6e757d85e39633d6c4db0292ab1bc3a23bca1 100644 |
| --- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp |
| +++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp |
| @@ -342,14 +342,27 @@ class PropertyTreeManager { |
| public: |
| PropertyTreeManager(cc::PropertyTrees& propertyTrees, cc::Layer* rootLayer) |
| : m_propertyTrees(propertyTrees) |
| - , m_rootLayer(rootLayer) {} |
| + , m_rootLayer(rootLayer) |
| +#if DCHECK_IS_ON() |
| + , m_isFirstEffectEver(true) |
| +#endif |
| + { |
| + m_effectStack.append(BlinkEffectAndCcIdPair{nullptr, kSecondaryRootNodeId}); |
| + } |
| int compositorIdForTransformNode(const TransformPaintPropertyNode*); |
| int compositorIdForClipNode(const ClipPaintPropertyNode*); |
| + void switchToEffectNode(const EffectPaintPropertyNode& nextEffect); |
| + int compositorIdForCurrentEffectNode() const { return m_effectStack.last().id; } |
| private: |
| + void buildEffectNodesRecursively(const EffectPaintPropertyNode* nextEffect); |
| + |
| cc::TransformTree& transformTree() { return m_propertyTrees.transform_tree; } |
| cc::ClipTree& clipTree() { return m_propertyTrees.clip_tree; } |
| + cc::EffectTree& effectTree() { return m_propertyTrees.effect_tree; } |
| + |
| + const EffectPaintPropertyNode* currentEffectNode() { return m_effectStack.last().effect; } |
|
jbroman
2016/07/08 18:32:34
super-nit: for consistency with compositorIdForCur
trchen
2016/07/09 01:09:24
Done.
|
| // Property trees which should be updated by the manager. |
| cc::PropertyTrees& m_propertyTrees; |
| @@ -361,6 +374,17 @@ private: |
| // Maps from Blink-side property tree nodes to cc property node indices. |
| HashMap<const TransformPaintPropertyNode*, int> m_transformNodeMap; |
| HashMap<const ClipPaintPropertyNode*, int> m_clipNodeMap; |
| + |
| + struct BlinkEffectAndCcIdPair { |
| + const EffectPaintPropertyNode* effect; |
| + int id; |
| + }; |
| + Vector<BlinkEffectAndCcIdPair> m_effectStack; |
| + |
| +#if DCHECK_IS_ON() |
| + HashSet<const EffectPaintPropertyNode*> m_effectNodesConverted; |
| + bool m_isFirstEffectEver; |
| +#endif |
| }; |
| int PropertyTreeManager::compositorIdForTransformNode(const TransformPaintPropertyNode* transformNode) |
| @@ -439,6 +463,88 @@ int PropertyTreeManager::compositorIdForClipNode(const ClipPaintPropertyNode* cl |
| return id; |
| } |
| +unsigned depth(const EffectPaintPropertyNode* node) |
| +{ |
| + unsigned result = 0; |
| + for (; node; node = node->parent()) |
| + result++; |
| + return result; |
| +} |
| +const EffectPaintPropertyNode* lowestCommonAncestor(const EffectPaintPropertyNode* nodeA, const EffectPaintPropertyNode* nodeB) |
|
jbroman
2016/07/08 18:32:34
super-nit: blank line above this function please
trchen
2016/07/09 01:09:25
Done.
|
| +{ |
| + // Optimized common case. |
| + if (nodeA == nodeB) |
| + return nodeA; |
| + |
| + unsigned depthA = depth(nodeA), depthB = depth(nodeB); |
| + while (depthA > depthB) { |
| + nodeA = nodeA->parent(); |
| + depthA--; |
| + } |
| + while (depthB > depthA) { |
| + nodeB = nodeB->parent(); |
| + depthB--; |
| + } |
| + DCHECK_EQ(depthA, depthB); |
| + while (nodeA != nodeB) { |
| + nodeA = nodeA->parent(); |
| + nodeB = nodeB->parent(); |
| + } |
| + return nodeA; |
| +} |
| + |
| +void PropertyTreeManager::switchToEffectNode(const EffectPaintPropertyNode& nextEffect) |
| +{ |
| + const EffectPaintPropertyNode* ancestor = lowestCommonAncestor(currentEffectNode(), &nextEffect); |
| + while (currentEffectNode() != ancestor) |
| + m_effectStack.removeLast(); |
| + |
| +#if DCHECK_IS_ON() |
| + DCHECK(m_isFirstEffectEver || currentEffectNode()) << "Malformed effect tree. Nodes in the same property tree should have common root."; |
| + m_isFirstEffectEver = false; |
| +#endif |
| + buildEffectNodesRecursively(&nextEffect); |
| +} |
| + |
| +void PropertyTreeManager::buildEffectNodesRecursively(const EffectPaintPropertyNode* nextEffect) |
| +{ |
| + if (nextEffect == currentEffectNode()) |
| + return; |
| + DCHECK(nextEffect); |
| + |
| + buildEffectNodesRecursively(nextEffect->parent()); |
| + DCHECK_EQ(nextEffect->parent(), currentEffectNode()); |
| + |
| +#if DCHECK_IS_ON() |
| + DCHECK(!m_effectNodesConverted.contains(nextEffect)) << "Malformed paint artifact. Paint chunks under the same effect should be contiguous."; |
| + m_effectNodesConverted.add(nextEffect); |
| +#endif |
| + |
| + // We currently create dummy layers to host effect nodes and corresponding render surface. |
| + // This should be removed once cc implements better support for freestanding property trees. |
| + scoped_refptr<cc::Layer> dummyLayer = cc::Layer::Create(); |
| + m_rootLayer->AddChild(dummyLayer); |
| + |
| + // Also cc assumes a clip node is always created by a layer that creates render surface. |
| + cc::ClipNode& dummyClip = *clipTree().Node(clipTree().Insert(cc::ClipNode(), kSecondaryRootNodeId)); |
| + dummyClip.owner_id = dummyLayer->id(); |
| + dummyClip.data.transform_id = kRealRootNodeId; |
|
jbroman
2016/07/08 18:32:34
It looks like they don't yet exist on EffectPaintP
trchen
2016/07/09 01:09:25
I don't think the dummy clip should even exist. Mo
jbroman
2016/07/09 20:25:24
That's fair, but the effect will have an associate
|
| + dummyClip.data.target_id = kRealRootNodeId; |
| + |
| + cc::EffectNode& effectNode = *effectTree().Node(effectTree().Insert(cc::EffectNode(), compositorIdForCurrentEffectNode())); |
| + effectNode.owner_id = dummyLayer->id(); |
| + effectNode.data.clip_id = dummyClip.id; |
| + effectNode.data.has_render_surface = true; |
| + effectNode.data.opacity = nextEffect->opacity(); |
| + m_effectStack.append(BlinkEffectAndCcIdPair{nextEffect, effectNode.id}); |
| + |
| + dummyLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); |
| + dummyLayer->SetTransformTreeIndex(kSecondaryRootNodeId); |
| + dummyLayer->SetClipTreeIndex(dummyClip.id); |
| + dummyLayer->SetEffectTreeIndex(effectNode.id); |
| + dummyLayer->SetScrollTreeIndex(kRealRootNodeId); |
| +} |
| + |
| } // namespace |
| void PaintArtifactCompositor::updateInLayerListMode(const PaintArtifact& paintArtifact) |
| @@ -457,6 +563,7 @@ void PaintArtifactCompositor::updateInLayerListMode(const PaintArtifact& paintAr |
| m_contentLayerClients.clear(); |
| m_contentLayerClients.reserveCapacity(paintArtifact.paintChunks().size()); |
| for (const PaintChunk& paintChunk : paintArtifact.paintChunks()) { |
| + propertyTreeManager.switchToEffectNode(*paintChunk.properties.effect.get()); |
|
jbroman
2016/07/08 18:32:34
nit: is there a reason this has to happen above th
trchen
2016/07/09 01:09:25
Done.
|
| gfx::Vector2dF layerOffset; |
| scoped_refptr<cc::Layer> layer = layerForPaintChunk(paintArtifact, paintChunk, layerOffset); |
| @@ -469,7 +576,7 @@ void PaintArtifactCompositor::updateInLayerListMode(const PaintArtifact& paintAr |
| layer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); |
| layer->SetTransformTreeIndex(transformId); |
| layer->SetClipTreeIndex(clipId); |
| - layer->SetEffectTreeIndex(kSecondaryRootNodeId); |
| + layer->SetEffectTreeIndex(propertyTreeManager.compositorIdForCurrentEffectNode()); |
| layer->SetScrollTreeIndex(kRealRootNodeId); |
| if (m_extraDataForTestingEnabled) |