| 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 "config.h" | 5 #include "config.h" |
| 6 #include "core/layout/compositing/CompositingInputsUpdater.h" | 6 #include "core/layout/compositing/CompositingInputsUpdater.h" |
| 7 | 7 |
| 8 #include "core/layout/Layer.h" |
| 8 #include "core/layout/compositing/CompositedLayerMapping.h" | 9 #include "core/layout/compositing/CompositedLayerMapping.h" |
| 9 #include "core/layout/compositing/RenderLayerCompositor.h" | 10 #include "core/layout/compositing/LayerCompositor.h" |
| 10 #include "core/rendering/RenderBlock.h" | 11 #include "core/rendering/RenderBlock.h" |
| 11 #include "core/rendering/RenderLayer.h" | |
| 12 #include "platform/TraceEvent.h" | 12 #include "platform/TraceEvent.h" |
| 13 | 13 |
| 14 namespace blink { | 14 namespace blink { |
| 15 | 15 |
| 16 CompositingInputsUpdater::CompositingInputsUpdater(RenderLayer* rootRenderLayer) | 16 CompositingInputsUpdater::CompositingInputsUpdater(Layer* rootLayer) |
| 17 : m_geometryMap(UseTransforms) | 17 : m_geometryMap(UseTransforms) |
| 18 , m_rootRenderLayer(rootRenderLayer) | 18 , m_rootLayer(rootLayer) |
| 19 { | 19 { |
| 20 } | 20 } |
| 21 | 21 |
| 22 CompositingInputsUpdater::~CompositingInputsUpdater() | 22 CompositingInputsUpdater::~CompositingInputsUpdater() |
| 23 { | 23 { |
| 24 } | 24 } |
| 25 | 25 |
| 26 void CompositingInputsUpdater::update() | 26 void CompositingInputsUpdater::update() |
| 27 { | 27 { |
| 28 TRACE_EVENT0("blink", "CompositingInputsUpdater::update"); | 28 TRACE_EVENT0("blink", "CompositingInputsUpdater::update"); |
| 29 updateRecursive(m_rootRenderLayer, DoNotForceUpdate, AncestorInfo()); | 29 updateRecursive(m_rootLayer, DoNotForceUpdate, AncestorInfo()); |
| 30 } | 30 } |
| 31 | 31 |
| 32 static const RenderLayer* findParentLayerOnClippingContainerChain(const RenderLa
yer* layer) | 32 static const Layer* findParentLayerOnClippingContainerChain(const Layer* layer) |
| 33 { | 33 { |
| 34 RenderObject* current = layer->renderer(); | 34 RenderObject* current = layer->renderer(); |
| 35 while (current) { | 35 while (current) { |
| 36 if (current->style()->position() == FixedPosition) { | 36 if (current->style()->position() == FixedPosition) { |
| 37 for (current = current->parent(); current && !current->canContainFix
edPositionObjects(); current = current->parent()) { | 37 for (current = current->parent(); current && !current->canContainFix
edPositionObjects(); current = current->parent()) { |
| 38 // All types of clips apply to fixed-position descendants of oth
er fixed-position elements. | 38 // All types of clips apply to fixed-position descendants of oth
er fixed-position elements. |
| 39 // Note: it's unclear whether this is what the spec says. Firefo
x does not clip, but Chrome does. | 39 // Note: it's unclear whether this is what the spec says. Firefo
x does not clip, but Chrome does. |
| 40 if (current->style()->position() == FixedPosition && current->ha
sClipOrOverflowClip()) { | 40 if (current->style()->position() == FixedPosition && current->ha
sClipOrOverflowClip()) { |
| 41 ASSERT(current->hasLayer()); | 41 ASSERT(current->hasLayer()); |
| 42 return static_cast<const RenderLayerModelObject*>(current)->
layer(); | 42 return static_cast<const LayoutLayerModelObject*>(current)->
layer(); |
| 43 } | 43 } |
| 44 | 44 |
| 45 // CSS clip applies to fixed position elements even for ancestor
s that are not what the | 45 // CSS clip applies to fixed position elements even for ancestor
s that are not what the |
| 46 // fixed element is positioned with respect to. | 46 // fixed element is positioned with respect to. |
| 47 if (current->hasClip()) { | 47 if (current->hasClip()) { |
| 48 ASSERT(current->hasLayer()); | 48 ASSERT(current->hasLayer()); |
| 49 return static_cast<const RenderLayerModelObject*>(current)->
layer(); | 49 return static_cast<const LayoutLayerModelObject*>(current)->
layer(); |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 } else { | 52 } else { |
| 53 current = current->containingBlock(); | 53 current = current->containingBlock(); |
| 54 } | 54 } |
| 55 | 55 |
| 56 if (current->hasLayer()) | 56 if (current->hasLayer()) |
| 57 return static_cast<const RenderLayerModelObject*>(current)->layer(); | 57 return static_cast<const LayoutLayerModelObject*>(current)->layer(); |
| 58 // Having clip or overflow clip forces the RenderObject to become a laye
r. | 58 // Having clip or overflow clip forces the RenderObject to become a laye
r. |
| 59 ASSERT(!current->hasClipOrOverflowClip()); | 59 ASSERT(!current->hasClipOrOverflowClip()); |
| 60 } | 60 } |
| 61 ASSERT_NOT_REACHED(); | 61 ASSERT_NOT_REACHED(); |
| 62 return 0; | 62 return 0; |
| 63 } | 63 } |
| 64 | 64 |
| 65 static const RenderLayer* findParentLayerOnContainingBlockChain(const RenderObje
ct* object) | 65 static const Layer* findParentLayerOnContainingBlockChain(const RenderObject* ob
ject) |
| 66 { | 66 { |
| 67 for (const RenderObject* current = object; current; current = current->conta
iningBlock()) { | 67 for (const RenderObject* current = object; current; current = current->conta
iningBlock()) { |
| 68 if (current->hasLayer()) | 68 if (current->hasLayer()) |
| 69 return static_cast<const RenderLayerModelObject*>(current)->layer(); | 69 return static_cast<const LayoutLayerModelObject*>(current)->layer(); |
| 70 } | 70 } |
| 71 ASSERT_NOT_REACHED(); | 71 ASSERT_NOT_REACHED(); |
| 72 return 0; | 72 return 0; |
| 73 } | 73 } |
| 74 | 74 |
| 75 static bool hasClippedStackingAncestor(const RenderLayer* layer, const RenderLay
er* clippingLayer) | 75 static bool hasClippedStackingAncestor(const Layer* layer, const Layer* clipping
Layer) |
| 76 { | 76 { |
| 77 if (layer == clippingLayer) | 77 if (layer == clippingLayer) |
| 78 return false; | 78 return false; |
| 79 const RenderObject* clippingRenderer = clippingLayer->renderer(); | 79 const RenderObject* clippingRenderer = clippingLayer->renderer(); |
| 80 for (const RenderLayer* current = layer->compositingContainer(); current &&
current != clippingLayer; current = current->compositingContainer()) { | 80 for (const Layer* current = layer->compositingContainer(); current && curren
t != clippingLayer; current = current->compositingContainer()) { |
| 81 if (current->renderer()->hasClipOrOverflowClip() && !clippingRenderer->i
sDescendantOf(current->renderer())) | 81 if (current->renderer()->hasClipOrOverflowClip() && !clippingRenderer->i
sDescendantOf(current->renderer())) |
| 82 return true; | 82 return true; |
| 83 | 83 |
| 84 if (const RenderObject* container = current->clippingContainer()) { | 84 if (const RenderObject* container = current->clippingContainer()) { |
| 85 if (clippingRenderer != container && !clippingRenderer->isDescendant
Of(container)) | 85 if (clippingRenderer != container && !clippingRenderer->isDescendant
Of(container)) |
| 86 return true; | 86 return true; |
| 87 } | 87 } |
| 88 } | 88 } |
| 89 return false; | 89 return false; |
| 90 } | 90 } |
| 91 | 91 |
| 92 void CompositingInputsUpdater::updateRecursive(RenderLayer* layer, UpdateType up
dateType, AncestorInfo info) | 92 void CompositingInputsUpdater::updateRecursive(Layer* layer, UpdateType updateTy
pe, AncestorInfo info) |
| 93 { | 93 { |
| 94 if (!layer->childNeedsCompositingInputsUpdate() && updateType != ForceUpdate
) | 94 if (!layer->childNeedsCompositingInputsUpdate() && updateType != ForceUpdate
) |
| 95 return; | 95 return; |
| 96 | 96 |
| 97 m_geometryMap.pushMappingsToAncestor(layer, layer->parent()); | 97 m_geometryMap.pushMappingsToAncestor(layer, layer->parent()); |
| 98 | 98 |
| 99 if (layer->hasCompositedLayerMapping()) | 99 if (layer->hasCompositedLayerMapping()) |
| 100 info.enclosingCompositedLayer = layer; | 100 info.enclosingCompositedLayer = layer; |
| 101 | 101 |
| 102 if (layer->needsCompositingInputsUpdate()) { | 102 if (layer->needsCompositingInputsUpdate()) { |
| 103 if (info.enclosingCompositedLayer) | 103 if (info.enclosingCompositedLayer) |
| 104 info.enclosingCompositedLayer->compositedLayerMapping()->setNeedsGra
phicsLayerUpdate(GraphicsLayerUpdateSubtree); | 104 info.enclosingCompositedLayer->compositedLayerMapping()->setNeedsGra
phicsLayerUpdate(GraphicsLayerUpdateSubtree); |
| 105 updateType = ForceUpdate; | 105 updateType = ForceUpdate; |
| 106 } | 106 } |
| 107 | 107 |
| 108 if (updateType == ForceUpdate) { | 108 if (updateType == ForceUpdate) { |
| 109 RenderLayer::AncestorDependentCompositingInputs properties; | 109 Layer::AncestorDependentCompositingInputs properties; |
| 110 | 110 |
| 111 if (!layer->isRootLayer()) { | 111 if (!layer->isRootLayer()) { |
| 112 properties.clippedAbsoluteBoundingBox = enclosingIntRect(m_geometryM
ap.absoluteRect(layer->boundingBoxForCompositingOverlapTest())); | 112 properties.clippedAbsoluteBoundingBox = enclosingIntRect(m_geometryM
ap.absoluteRect(layer->boundingBoxForCompositingOverlapTest())); |
| 113 // FIXME: Setting the absBounds to 1x1 instead of 0x0 makes very lit
tle sense, | 113 // FIXME: Setting the absBounds to 1x1 instead of 0x0 makes very lit
tle sense, |
| 114 // but removing this code will make JSGameBench sad. | 114 // but removing this code will make JSGameBench sad. |
| 115 // See https://codereview.chromium.org/13912020/ | 115 // See https://codereview.chromium.org/13912020/ |
| 116 if (properties.clippedAbsoluteBoundingBox.isEmpty()) | 116 if (properties.clippedAbsoluteBoundingBox.isEmpty()) |
| 117 properties.clippedAbsoluteBoundingBox.setSize(IntSize(1, 1)); | 117 properties.clippedAbsoluteBoundingBox.setSize(IntSize(1, 1)); |
| 118 | 118 |
| 119 IntRect clipRect = pixelSnappedIntRect(layer->clipper().backgroundCl
ipRect(ClipRectsContext(m_rootRenderLayer, AbsoluteClipRects)).rect()); | 119 IntRect clipRect = pixelSnappedIntRect(layer->clipper().backgroundCl
ipRect(ClipRectsContext(m_rootLayer, AbsoluteClipRects)).rect()); |
| 120 properties.clippedAbsoluteBoundingBox.intersect(clipRect); | 120 properties.clippedAbsoluteBoundingBox.intersect(clipRect); |
| 121 | 121 |
| 122 const RenderLayer* parent = layer->parent(); | 122 const Layer* parent = layer->parent(); |
| 123 properties.opacityAncestor = parent->isTransparent() ? parent : pare
nt->opacityAncestor(); | 123 properties.opacityAncestor = parent->isTransparent() ? parent : pare
nt->opacityAncestor(); |
| 124 properties.transformAncestor = parent->hasTransformRelatedProperty()
? parent : parent->transformAncestor(); | 124 properties.transformAncestor = parent->hasTransformRelatedProperty()
? parent : parent->transformAncestor(); |
| 125 properties.filterAncestor = parent->hasFilter() ? parent : parent->f
ilterAncestor(); | 125 properties.filterAncestor = parent->hasFilter() ? parent : parent->f
ilterAncestor(); |
| 126 | 126 |
| 127 if (info.hasAncestorWithClipOrOverflowClip) { | 127 if (info.hasAncestorWithClipOrOverflowClip) { |
| 128 const RenderLayer* parentLayerOnClippingContainerChain = findPar
entLayerOnClippingContainerChain(layer); | 128 const Layer* parentLayerOnClippingContainerChain = findParentLay
erOnClippingContainerChain(layer); |
| 129 const bool parentHasClipOrOverflowClip = parentLayerOnClippingCo
ntainerChain->renderer()->hasClipOrOverflowClip(); | 129 const bool parentHasClipOrOverflowClip = parentLayerOnClippingCo
ntainerChain->renderer()->hasClipOrOverflowClip(); |
| 130 properties.clippingContainer = parentHasClipOrOverflowClip ? par
entLayerOnClippingContainerChain->renderer() : parentLayerOnClippingContainerCha
in->clippingContainer(); | 130 properties.clippingContainer = parentHasClipOrOverflowClip ? par
entLayerOnClippingContainerChain->renderer() : parentLayerOnClippingContainerCha
in->clippingContainer(); |
| 131 } | 131 } |
| 132 | 132 |
| 133 if (info.lastScrollingAncestor) { | 133 if (info.lastScrollingAncestor) { |
| 134 const RenderObject* containingBlock = layer->renderer()->contain
ingBlock(); | 134 const RenderObject* containingBlock = layer->renderer()->contain
ingBlock(); |
| 135 const RenderLayer* parentLayerOnContainingBlockChain = findParen
tLayerOnContainingBlockChain(containingBlock); | 135 const Layer* parentLayerOnContainingBlockChain = findParentLayer
OnContainingBlockChain(containingBlock); |
| 136 | 136 |
| 137 properties.ancestorScrollingLayer = parentLayerOnContainingBlock
Chain->ancestorScrollingLayer(); | 137 properties.ancestorScrollingLayer = parentLayerOnContainingBlock
Chain->ancestorScrollingLayer(); |
| 138 if (parentLayerOnContainingBlockChain->scrollsOverflow()) | 138 if (parentLayerOnContainingBlockChain->scrollsOverflow()) |
| 139 properties.ancestorScrollingLayer = parentLayerOnContainingB
lockChain; | 139 properties.ancestorScrollingLayer = parentLayerOnContainingB
lockChain; |
| 140 | 140 |
| 141 if (layer->renderer()->isOutOfFlowPositioned() && !layer->subtre
eIsInvisible()) { | 141 if (layer->renderer()->isOutOfFlowPositioned() && !layer->subtre
eIsInvisible()) { |
| 142 const RenderLayer* clippingLayer = properties.clippingContai
ner ? properties.clippingContainer->enclosingLayer() : layer->compositor()->root
RenderLayer(); | 142 const Layer* clippingLayer = properties.clippingContainer ?
properties.clippingContainer->enclosingLayer() : layer->compositor()->rootLayer(
); |
| 143 if (hasClippedStackingAncestor(layer, clippingLayer)) | 143 if (hasClippedStackingAncestor(layer, clippingLayer)) |
| 144 properties.clipParent = clippingLayer; | 144 properties.clipParent = clippingLayer; |
| 145 } | 145 } |
| 146 | 146 |
| 147 if (!layer->stackingNode()->isNormalFlowOnly() | 147 if (!layer->stackingNode()->isNormalFlowOnly() |
| 148 && properties.ancestorScrollingLayer | 148 && properties.ancestorScrollingLayer |
| 149 && !info.ancestorStackingContext->renderer()->isDescendantOf
(properties.ancestorScrollingLayer->renderer())) | 149 && !info.ancestorStackingContext->renderer()->isDescendantOf
(properties.ancestorScrollingLayer->renderer())) |
| 150 properties.scrollParent = properties.ancestorScrollingLayer; | 150 properties.scrollParent = properties.ancestorScrollingLayer; |
| 151 } | 151 } |
| 152 } | 152 } |
| 153 | 153 |
| 154 properties.hasAncestorWithClipPath = info.hasAncestorWithClipPath; | 154 properties.hasAncestorWithClipPath = info.hasAncestorWithClipPath; |
| 155 layer->updateAncestorDependentCompositingInputs(properties); | 155 layer->updateAncestorDependentCompositingInputs(properties); |
| 156 } | 156 } |
| 157 | 157 |
| 158 if (layer->stackingNode()->isStackingContext()) | 158 if (layer->stackingNode()->isStackingContext()) |
| 159 info.ancestorStackingContext = layer; | 159 info.ancestorStackingContext = layer; |
| 160 | 160 |
| 161 if (layer->scrollsOverflow()) | 161 if (layer->scrollsOverflow()) |
| 162 info.lastScrollingAncestor = layer; | 162 info.lastScrollingAncestor = layer; |
| 163 | 163 |
| 164 if (layer->renderer()->hasClipOrOverflowClip()) | 164 if (layer->renderer()->hasClipOrOverflowClip()) |
| 165 info.hasAncestorWithClipOrOverflowClip = true; | 165 info.hasAncestorWithClipOrOverflowClip = true; |
| 166 | 166 |
| 167 if (layer->renderer()->hasClipPath()) | 167 if (layer->renderer()->hasClipPath()) |
| 168 info.hasAncestorWithClipPath = true; | 168 info.hasAncestorWithClipPath = true; |
| 169 | 169 |
| 170 RenderLayer::DescendantDependentCompositingInputs descendantProperties; | 170 Layer::DescendantDependentCompositingInputs descendantProperties; |
| 171 for (RenderLayer* child = layer->firstChild(); child; child = child->nextSib
ling()) { | 171 for (Layer* child = layer->firstChild(); child; child = child->nextSibling()
) { |
| 172 updateRecursive(child, updateType, info); | 172 updateRecursive(child, updateType, info); |
| 173 | 173 |
| 174 descendantProperties.hasDescendantWithClipPath |= child->hasDescendantWi
thClipPath() || child->renderer()->hasClipPath(); | 174 descendantProperties.hasDescendantWithClipPath |= child->hasDescendantWi
thClipPath() || child->renderer()->hasClipPath(); |
| 175 descendantProperties.hasNonIsolatedDescendantWithBlendMode |= (!child->s
tackingNode()->isStackingContext() && child->hasNonIsolatedDescendantWithBlendMo
de()) || child->renderer()->style()->hasBlendMode(); | 175 descendantProperties.hasNonIsolatedDescendantWithBlendMode |= (!child->s
tackingNode()->isStackingContext() && child->hasNonIsolatedDescendantWithBlendMo
de()) || child->renderer()->style()->hasBlendMode(); |
| 176 } | 176 } |
| 177 | 177 |
| 178 layer->updateDescendantDependentCompositingInputs(descendantProperties); | 178 layer->updateDescendantDependentCompositingInputs(descendantProperties); |
| 179 layer->didUpdateCompositingInputs(); | 179 layer->didUpdateCompositingInputs(); |
| 180 | 180 |
| 181 m_geometryMap.popMappingsToAncestor(layer->parent()); | 181 m_geometryMap.popMappingsToAncestor(layer->parent()); |
| 182 } | 182 } |
| 183 | 183 |
| 184 #if ENABLE(ASSERT) | 184 #if ENABLE(ASSERT) |
| 185 | 185 |
| 186 void CompositingInputsUpdater::assertNeedsCompositingInputsUpdateBitsCleared(Ren
derLayer* layer) | 186 void CompositingInputsUpdater::assertNeedsCompositingInputsUpdateBitsCleared(Lay
er* layer) |
| 187 { | 187 { |
| 188 ASSERT(!layer->childNeedsCompositingInputsUpdate()); | 188 ASSERT(!layer->childNeedsCompositingInputsUpdate()); |
| 189 ASSERT(!layer->needsCompositingInputsUpdate()); | 189 ASSERT(!layer->needsCompositingInputsUpdate()); |
| 190 | 190 |
| 191 for (RenderLayer* child = layer->firstChild(); child; child = child->nextSib
ling()) | 191 for (Layer* child = layer->firstChild(); child; child = child->nextSibling()
) |
| 192 assertNeedsCompositingInputsUpdateBitsCleared(child); | 192 assertNeedsCompositingInputsUpdateBitsCleared(child); |
| 193 } | 193 } |
| 194 | 194 |
| 195 #endif | 195 #endif |
| 196 | 196 |
| 197 } // namespace blink | 197 } // namespace blink |
| OLD | NEW |