Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp

Issue 2578393002: Update paint property subtrees on paint offset changes (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698