| 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 "core/paint/PrePaintTreeWalk.h" | 5 #include "core/paint/PrePaintTreeWalk.h" |
| 6 | 6 |
| 7 #include "core/dom/DocumentLifecycle.h" | 7 #include "core/dom/DocumentLifecycle.h" |
| 8 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
| 9 #include "core/frame/LocalFrame.h" | 9 #include "core/frame/LocalFrame.h" |
| 10 #include "core/layout/LayoutMultiColumnSpannerPlaceholder.h" | 10 #include "core/layout/LayoutMultiColumnSpannerPlaceholder.h" |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 DocumentLifecycle::InPrePaint); | 38 DocumentLifecycle::InPrePaint); |
| 39 | 39 |
| 40 PrePaintTreeWalkContext initialContext; | 40 PrePaintTreeWalkContext initialContext; |
| 41 initialContext.treeBuilderContext = | 41 initialContext.treeBuilderContext = |
| 42 m_propertyTreeBuilder.setupInitialContext(); | 42 m_propertyTreeBuilder.setupInitialContext(); |
| 43 walk(rootFrame, initialContext); | 43 walk(rootFrame, initialContext); |
| 44 m_paintInvalidator.processPendingDelayedPaintInvalidations(); | 44 m_paintInvalidator.processPendingDelayedPaintInvalidations(); |
| 45 } | 45 } |
| 46 | 46 |
| 47 bool PrePaintTreeWalk::walk(FrameView& frameView, | 47 bool PrePaintTreeWalk::walk(FrameView& frameView, |
| 48 const PrePaintTreeWalkContext& context) { | 48 const PrePaintTreeWalkContext& parentContext) { |
| 49 if (frameView.shouldThrottleRendering()) { | 49 if (frameView.shouldThrottleRendering()) { |
| 50 // The walk was interrupted by throttled rendering so this subtree was not | 50 // The walk was interrupted by throttled rendering so this subtree was not |
| 51 // fully updated. | 51 // fully updated. |
| 52 return false; | 52 return false; |
| 53 } | 53 } |
| 54 | 54 |
| 55 PrePaintTreeWalkContext localContext(context); | 55 PrePaintTreeWalkContext context(parentContext); |
| 56 | 56 |
| 57 if (frameView.shouldInvalidateAllPaintAndPaintProperties()) { | 57 if (frameView.shouldInvalidateAllPaintAndPaintProperties()) { |
| 58 localContext.treeBuilderContext.forceSubtreeUpdate = true; | 58 context.treeBuilderContext.forceSubtreeUpdate = true; |
| 59 localContext.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= | 59 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= |
| 60 PaintInvalidatorContext::ForcedWholeTreeFullInvalidation; | 60 PaintInvalidatorContext::ForcedWholeTreeFullInvalidation; |
| 61 frameView.clearShouldInvalidateAllPaintAndPaintProperties(); | 61 frameView.clearShouldInvalidateAllPaintAndPaintProperties(); |
| 62 } | 62 } |
| 63 | 63 |
| 64 m_propertyTreeBuilder.updateProperties(frameView, | 64 m_propertyTreeBuilder.updateProperties(frameView, context.treeBuilderContext); |
| 65 localContext.treeBuilderContext); | 65 m_paintInvalidator.invalidatePaintIfNeeded(frameView, |
| 66 m_paintInvalidator.invalidatePaintIfNeeded( | 66 context.paintInvalidatorContext); |
| 67 frameView, localContext.paintInvalidatorContext); | |
| 68 | 67 |
| 69 LayoutView* view = frameView.layoutView(); | 68 LayoutView* view = frameView.layoutView(); |
| 70 bool descendantsFullyUpdated = view ? walk(*view, localContext) : true; | 69 bool descendantsFullyUpdated = view ? walk(*view, context) : true; |
| 71 if (descendantsFullyUpdated) { | 70 if (descendantsFullyUpdated) { |
| 72 #if DCHECK_IS_ON() | 71 #if DCHECK_IS_ON() |
| 73 frameView.layoutView()->assertSubtreeClearedPaintInvalidationFlags(); | 72 frameView.layoutView()->assertSubtreeClearedPaintInvalidationFlags(); |
| 74 #endif | 73 #endif |
| 75 // If descendants were not fully updated, do not clear flags. During the | 74 // If descendants were not fully updated, do not clear flags. During the |
| 76 // next PrePaintTreeWalk, these flags will be used again. | 75 // next PrePaintTreeWalk, these flags will be used again. |
| 77 frameView.clearNeedsPaintPropertyUpdate(); | 76 frameView.clearNeedsPaintPropertyUpdate(); |
| 78 } | 77 } |
| 79 return descendantsFullyUpdated; | 78 return descendantsFullyUpdated; |
| 80 } | 79 } |
| 81 | 80 |
| 82 static void updateAuxiliaryObjectProperties( | 81 static void updateAuxiliaryObjectProperties(const LayoutObject& object, |
| 83 const LayoutObject& object, | 82 PrePaintTreeWalkContext& context) { |
| 84 PrePaintTreeWalkContext& localContext) { | |
| 85 PaintLayer* paintLayer = nullptr; | 83 PaintLayer* paintLayer = nullptr; |
| 86 | 84 |
| 87 if (object.isBoxModelObject() && object.hasLayer()) | 85 if (object.isBoxModelObject() && object.hasLayer()) |
| 88 paintLayer = object.enclosingLayer(); | 86 paintLayer = object.enclosingLayer(); |
| 89 | 87 |
| 90 if (paintLayer) { | 88 if (paintLayer) { |
| 91 paintLayer->updateAncestorOverflowLayer( | 89 paintLayer->updateAncestorOverflowLayer(context.ancestorOverflowPaintLayer); |
| 92 localContext.ancestorOverflowPaintLayer); | |
| 93 } | 90 } |
| 94 | 91 |
| 95 if (object.styleRef().position() == StickyPosition && paintLayer) { | 92 if (object.styleRef().position() == StickyPosition && paintLayer) { |
| 96 paintLayer->layoutObject()->updateStickyPositionConstraints(); | 93 paintLayer->layoutObject()->updateStickyPositionConstraints(); |
| 97 | 94 |
| 98 // Sticky position constraints and ancestor overflow scroller affect | 95 // Sticky position constraints and ancestor overflow scroller affect |
| 99 // the sticky layer position, so we need to update it again here. | 96 // the sticky layer position, so we need to update it again here. |
| 100 // TODO(flackr): This should be refactored in the future to be clearer | 97 // TODO(flackr): This should be refactored in the future to be clearer |
| 101 // (i.e. update layer position and ancestor inputs updates in the | 98 // (i.e. update layer position and ancestor inputs updates in the |
| 102 // same walk) | 99 // same walk) |
| 103 paintLayer->updateLayerPosition(); | 100 paintLayer->updateLayerPosition(); |
| 104 } | 101 } |
| 105 | 102 |
| 106 if (object.hasOverflowClip() || (paintLayer && paintLayer->isRootLayer())) { | 103 if (object.hasOverflowClip() || (paintLayer && paintLayer->isRootLayer())) { |
| 107 DCHECK(paintLayer); | 104 DCHECK(paintLayer); |
| 108 localContext.ancestorOverflowPaintLayer = paintLayer; | 105 context.ancestorOverflowPaintLayer = paintLayer; |
| 109 } | 106 } |
| 110 } | 107 } |
| 111 | 108 |
| 112 bool PrePaintTreeWalk::walk(const LayoutObject& object, | 109 bool PrePaintTreeWalk::walk(const LayoutObject& object, |
| 113 const PrePaintTreeWalkContext& context) { | 110 const PrePaintTreeWalkContext& parentContext) { |
| 114 PrePaintTreeWalkContext localContext(context); | 111 PrePaintTreeWalkContext context(parentContext); |
| 115 | 112 |
| 116 // TODO(pdr): Ensure multi column works with incremental property tree | 113 // TODO(pdr): Ensure multi column works with incremental property tree |
| 117 // construction. | 114 // construction. |
| 118 if (object.isLayoutMultiColumnSpannerPlaceholder()) { | 115 if (object.isLayoutMultiColumnSpannerPlaceholder()) { |
| 119 // Walk multi-column spanner as if it replaces the placeholder. | 116 // Walk multi-column spanner as if it replaces the placeholder. |
| 120 // Set the flag so that the tree builder can specially handle out-of-flow | 117 // Set the flag so that the tree builder can specially handle out-of-flow |
| 121 // positioned descendants if their containers are between the multi-column | 118 // positioned descendants if their containers are between the multi-column |
| 122 // container and the spanner. See PaintPropertyTreeBuilder for details. | 119 // container and the spanner. See PaintPropertyTreeBuilder for details. |
| 123 localContext.treeBuilderContext.isUnderMultiColumnSpanner = true; | 120 context.treeBuilderContext.isUnderMultiColumnSpanner = true; |
| 124 const auto& placeholder = toLayoutMultiColumnSpannerPlaceholder(object); | 121 const auto& placeholder = toLayoutMultiColumnSpannerPlaceholder(object); |
| 125 bool descendantsFullyUpdated = | 122 bool descendantsFullyUpdated = |
| 126 walk(*placeholder.layoutObjectInFlowThread(), localContext); | 123 walk(*placeholder.layoutObjectInFlowThread(), context); |
| 127 if (descendantsFullyUpdated) { | 124 if (descendantsFullyUpdated) { |
| 128 // If descendants were not fully updated, do not clear flags. During the | 125 // If descendants were not fully updated, do not clear flags. During the |
| 129 // next PrePaintTreeWalk, these flags will be used again. | 126 // next PrePaintTreeWalk, these flags will be used again. |
| 130 object.getMutableForPainting().clearPaintFlags(); | 127 object.getMutableForPainting().clearPaintFlags(); |
| 131 } | 128 } |
| 132 return descendantsFullyUpdated; | 129 return descendantsFullyUpdated; |
| 133 } | 130 } |
| 134 | 131 |
| 135 // This must happen before updateContextForBoxPosition, because the | 132 // This must happen before updateContextForBoxPosition, because the |
| 136 // latter reads some of the state computed uere. | 133 // latter reads some of the state computed uere. |
| 137 updateAuxiliaryObjectProperties(object, localContext); | 134 updateAuxiliaryObjectProperties(object, context); |
| 138 | 135 |
| 139 // Ensure the current context takes into account the box position. This can | 136 // Ensure the current context takes into account the box's position. This can |
| 140 // change the current context's paint offset so it must precede the paint | 137 // force a subtree update due to paint offset changes and must precede any |
| 141 // offset property update check. | 138 // early out from the treewalk. |
| 142 m_propertyTreeBuilder.updateContextForBoxPosition( | 139 m_propertyTreeBuilder.updateContextForBoxPosition(object, |
| 143 object, localContext.treeBuilderContext); | 140 context.treeBuilderContext); |
| 144 // Many paint properties depend on paint offset so we force an update of | |
| 145 // properties if the paint offset changes. | |
| 146 if (object.previousPaintOffset() != | |
| 147 localContext.treeBuilderContext.current.paintOffset) { | |
| 148 object.getMutableForPainting().setNeedsPaintPropertyUpdate(); | |
| 149 } | |
| 150 | 141 |
| 151 // Early out from the treewalk if possible. | 142 // Early out from the treewalk if possible. |
| 152 if (!object.needsPaintPropertyUpdate() && | 143 if (!object.needsPaintPropertyUpdate() && |
| 153 !object.descendantNeedsPaintPropertyUpdate() && | 144 !object.descendantNeedsPaintPropertyUpdate() && |
| 154 !localContext.treeBuilderContext.forceSubtreeUpdate && | 145 !context.treeBuilderContext.forceSubtreeUpdate && |
| 155 !localContext.paintInvalidatorContext.forcedSubtreeInvalidationFlags && | 146 !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags && |
| 156 !object | 147 !object |
| 157 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState())
{ | 148 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState())
{ |
| 158 // Even though the subtree was not walked, we know that a walk will not | 149 // Even though the subtree was not walked, we know that a walk will not |
| 159 // change anything and can return true as if the subtree was fully updated. | 150 // change anything and can return true as if the subtree was fully updated. |
| 160 return true; | 151 return true; |
| 161 } | 152 } |
| 162 | 153 |
| 163 m_propertyTreeBuilder.updatePropertiesForSelf( | 154 m_propertyTreeBuilder.updatePropertiesForSelf(object, |
| 164 object, localContext.treeBuilderContext); | 155 context.treeBuilderContext); |
| 165 m_paintInvalidator.invalidatePaintIfNeeded( | 156 m_paintInvalidator.invalidatePaintIfNeeded(object, |
| 166 object, localContext.paintInvalidatorContext); | 157 context.paintInvalidatorContext); |
| 167 m_propertyTreeBuilder.updatePropertiesForChildren( | 158 m_propertyTreeBuilder.updatePropertiesForChildren(object, |
| 168 object, localContext.treeBuilderContext); | 159 context.treeBuilderContext); |
| 169 | 160 |
| 170 bool descendantsFullyUpdated = true; | 161 bool descendantsFullyUpdated = true; |
| 171 for (const LayoutObject* child = object.slowFirstChild(); child; | 162 for (const LayoutObject* child = object.slowFirstChild(); child; |
| 172 child = child->nextSibling()) { | 163 child = child->nextSibling()) { |
| 173 // Column spanners are walked through their placeholders. See above. | 164 // Column spanners are walked through their placeholders. See above. |
| 174 if (child->isColumnSpanAll()) | 165 if (child->isColumnSpanAll()) |
| 175 continue; | 166 continue; |
| 176 bool childFullyUpdated = walk(*child, localContext); | 167 bool childFullyUpdated = walk(*child, context); |
| 177 if (!childFullyUpdated) | 168 if (!childFullyUpdated) |
| 178 descendantsFullyUpdated = false; | 169 descendantsFullyUpdated = false; |
| 179 } | 170 } |
| 180 | 171 |
| 181 if (object.isLayoutPart()) { | 172 if (object.isLayoutPart()) { |
| 182 const LayoutPart& layoutPart = toLayoutPart(object); | 173 const LayoutPart& layoutPart = toLayoutPart(object); |
| 183 Widget* widget = layoutPart.widget(); | 174 Widget* widget = layoutPart.widget(); |
| 184 if (widget && widget->isFrameView()) { | 175 if (widget && widget->isFrameView()) { |
| 185 localContext.treeBuilderContext.current.paintOffset += | 176 context.treeBuilderContext.current.paintOffset += |
| 186 layoutPart.replacedContentRect().location() - | 177 layoutPart.replacedContentRect().location() - |
| 187 widget->frameRect().location(); | 178 widget->frameRect().location(); |
| 188 localContext.treeBuilderContext.current.paintOffset = | 179 context.treeBuilderContext.current.paintOffset = |
| 189 roundedIntPoint(localContext.treeBuilderContext.current.paintOffset); | 180 roundedIntPoint(context.treeBuilderContext.current.paintOffset); |
| 190 bool frameFullyUpdated = walk(*toFrameView(widget), localContext); | 181 bool frameFullyUpdated = walk(*toFrameView(widget), context); |
| 191 if (!frameFullyUpdated) | 182 if (!frameFullyUpdated) |
| 192 descendantsFullyUpdated = false; | 183 descendantsFullyUpdated = false; |
| 193 } | 184 } |
| 194 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). | 185 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
| 195 } | 186 } |
| 196 | 187 |
| 197 if (descendantsFullyUpdated) { | 188 if (descendantsFullyUpdated) { |
| 198 // If descendants were not updated, do not clear flags. During the next | 189 // If descendants were not updated, do not clear flags. During the next |
| 199 // PrePaintTreeWalk, these flags will be used again. | 190 // PrePaintTreeWalk, these flags will be used again. |
| 200 object.getMutableForPainting().clearPaintFlags(); | 191 object.getMutableForPainting().clearPaintFlags(); |
| 201 } | 192 } |
| 202 return descendantsFullyUpdated; | 193 return descendantsFullyUpdated; |
| 203 } | 194 } |
| 204 | 195 |
| 205 } // namespace blink | 196 } // namespace blink |
| OLD | NEW |