OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/PaintInvalidator.h" | 5 #include "core/paint/PaintInvalidator.h" |
6 | 6 |
7 #include "core/editing/FrameSelection.h" | 7 #include "core/editing/FrameSelection.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/frame/Settings.h" | 10 #include "core/frame/Settings.h" |
11 #include "core/layout/LayoutBlockFlow.h" | 11 #include "core/layout/LayoutBlockFlow.h" |
12 #include "core/layout/LayoutObject.h" | 12 #include "core/layout/LayoutObject.h" |
13 #include "core/layout/LayoutTable.h" | 13 #include "core/layout/LayoutTable.h" |
14 #include "core/layout/LayoutView.h" | 14 #include "core/layout/LayoutView.h" |
15 #include "core/layout/svg/SVGLayoutSupport.h" | 15 #include "core/layout/svg/SVGLayoutSupport.h" |
16 #include "core/paint/ObjectPaintProperties.h" | 16 #include "core/paint/ObjectPaintProperties.h" |
17 #include "core/paint/PaintLayer.h" | 17 #include "core/paint/PaintLayer.h" |
18 #include "core/paint/PaintLayerScrollableArea.h" | 18 #include "core/paint/PaintLayerScrollableArea.h" |
19 #include "core/paint/PaintPropertyTreeBuilder.h" | 19 #include "core/paint/PaintPropertyTreeBuilder.h" |
20 | 20 |
21 namespace blink { | 21 namespace blink { |
22 | 22 |
23 static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const LayoutBoxModelObject& ancestor, LayoutRect& rect) | |
24 { | |
25 if (object.isLayoutView()) | |
26 toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, Inp utIsInFrameCoordinates, DefaultVisualRectFlags); | |
27 else | |
28 object.mapToVisualRectInAncestorSpace(&ancestor, rect); | |
29 } | |
30 | |
23 // TODO(wangxianzhu): Combine this into PaintInvalidator::mapLocalRectToPaintInv alidationBacking() when removing PaintInvalidationState. | 31 // TODO(wangxianzhu): Combine this into PaintInvalidator::mapLocalRectToPaintInv alidationBacking() when removing PaintInvalidationState. |
24 static LayoutRect mapLocalRectToPaintInvalidationBacking(GeometryMapper& geometr yMapper, const LayoutObject& object, const FloatRect& localRect, const PaintInva lidatorContext& context) | 32 static LayoutRect mapLocalRectToPaintInvalidationBacking(GeometryMapper& geometr yMapper, const LayoutObject& object, const FloatRect& localRect, const PaintInva lidatorContext& context) |
25 { | 33 { |
26 // TODO(wkorman): The flip below is required because visual rects are | 34 // TODO(wkorman): The flip below is required because visual rects are |
27 // currently in "physical coordinates with flipped block-flow direction" | 35 // currently in "physical coordinates with flipped block-flow direction" |
28 // (see LayoutBoxModelObject.h) but we need them to be in physical | 36 // (see LayoutBoxModelObject.h) but we need them to be in physical |
29 // coordinates. | 37 // coordinates. |
30 FloatRect rect = localRect; | 38 FloatRect rect = localRect; |
31 if (object.isBox()) | 39 if (object.isBox()) |
32 toLayoutBox(object).flipForWritingMode(rect); | 40 toLayoutBox(object).flipForWritingMode(rect); |
33 | 41 |
34 LayoutRect result; | 42 LayoutRect result; |
35 if (object == context.paintInvalidationContainer) { | 43 if (context.forcedSubtreeInvalidationFlags & PaintInvalidatorContext::Forced SubtreeSlowPathRect) { |
44 result = LayoutRect(rect); | |
45 slowMapToVisualRectInAncestorSpace(object, *context.paintInvalidationCon tainer, result); | |
46 } else if (object == context.paintInvalidationContainer) { | |
36 result = LayoutRect(rect); | 47 result = LayoutRect(rect); |
37 } else { | 48 } else { |
38 rect.moveBy(FloatPoint(context.treeBuilderContext.current.paintOffset)); | |
39 | |
40 bool success = false; | |
41 PropertyTreeState currentTreeState(context.treeBuilderContext.current.tr ansform, context.treeBuilderContext.current.clip, context.treeBuilderContext.cur rentEffect); | 49 PropertyTreeState currentTreeState(context.treeBuilderContext.current.tr ansform, context.treeBuilderContext.current.clip, context.treeBuilderContext.cur rentEffect); |
42 PropertyTreeState containerTreeState; | 50 PropertyTreeState containerTreeState; |
43 context.paintInvalidationContainer->objectPaintProperties()->getContents Properties(containerTreeState); | 51 const ObjectPaintProperties* containerPaintProperties = context.paintInv alidationContainer->objectPaintProperties(); |
52 containerPaintProperties->getContentsProperties(containerTreeState); | |
53 | |
54 rect.moveBy(FloatPoint(context.treeBuilderContext.current.paintOffset)); | |
55 bool success = false; | |
44 result = LayoutRect(geometryMapper.mapToVisualRectInDestinationSpace(rec t, currentTreeState, containerTreeState, success)); | 56 result = LayoutRect(geometryMapper.mapToVisualRectInDestinationSpace(rec t, currentTreeState, containerTreeState, success)); |
45 DCHECK(success); | 57 DCHECK(success); |
58 result.moveBy(-containerPaintProperties->localBorderBoxProperties()->pai ntOffset); | |
chrishtr
2016/09/13 23:30:03
This was a straight-up bug in slimmingPaintInvalid
Xianzhu
2016/09/13 23:47:15
Yes, this was a bug, but didn't notice it because
chrishtr
2016/09/13 23:54:25
Ah yes, makes sense.
| |
46 } | 59 } |
47 | 60 |
48 if (context.paintInvalidationContainer->layer()->groupedMapping()) | 61 if (context.paintInvalidationContainer->layer()->groupedMapping()) |
49 PaintLayer::mapRectInPaintInvalidationContainerToBacking(*context.paintI nvalidationContainer, result); | 62 PaintLayer::mapRectInPaintInvalidationContainerToBacking(*context.paintI nvalidationContainer, result); |
50 return result; | 63 return result; |
51 } | 64 } |
52 | 65 |
53 void PaintInvalidatorContext::mapLocalRectToPaintInvalidationBacking(const Layou tObject& object, LayoutRect& rect) const | 66 void PaintInvalidatorContext::mapLocalRectToPaintInvalidationBacking(const Layou tObject& object, LayoutRect& rect) const |
54 { | 67 { |
55 GeometryMapper geometryMapper; | 68 GeometryMapper geometryMapper; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
154 context.forcedSubtreeInvalidationFlags = 0; | 167 context.forcedSubtreeInvalidationFlags = 0; |
155 } | 168 } |
156 } | 169 } |
157 | 170 |
158 DCHECK(context.paintInvalidationContainer == object.containerForPaintInvalid ation()); | 171 DCHECK(context.paintInvalidationContainer == object.containerForPaintInvalid ation()); |
159 DCHECK(context.paintingLayer == object.paintingLayer()); | 172 DCHECK(context.paintingLayer == object.paintingLayer()); |
160 | 173 |
161 if (object.mayNeedPaintInvalidationSubtree()) | 174 if (object.mayNeedPaintInvalidationSubtree()) |
162 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; | 175 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; |
163 | 176 |
177 // TODO(crbug.com/637313): This is temporary before we support filters in pa int property tree. | |
178 if (object.hasFilterInducingProperty()) | |
179 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeSlowPathRect; | |
180 | |
164 context.oldBounds = object.previousPaintInvalidationRect(); | 181 context.oldBounds = object.previousPaintInvalidationRect(); |
165 context.oldLocation = object.previousPositionFromPaintInvalidationBacking(); | 182 context.oldLocation = object.previousPositionFromPaintInvalidationBacking(); |
166 context.newBounds = computePaintInvalidationRectInBacking(object, context); | 183 context.newBounds = computePaintInvalidationRectInBacking(object, context); |
167 context.newLocation = computeLocationFromPaintInvalidationBacking(object, co ntext); | 184 context.newLocation = computeLocationFromPaintInvalidationBacking(object, co ntext); |
168 | 185 |
169 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation(*context.pa intInvalidationContainer); | 186 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation(*context.pa intInvalidationContainer); |
170 context.newLocation.move(adjustment); | 187 context.newLocation.move(adjustment); |
171 context.newBounds.move(adjustment); | 188 context.newBounds.move(adjustment); |
172 | 189 |
173 object.getMutableForPainting().setPreviousPaintInvalidationRect(context.newB ounds); | 190 object.getMutableForPainting().setPreviousPaintInvalidationRect(context.newB ounds); |
(...skipping 14 matching lines...) Expand all Loading... | |
188 if (frameView.frame().selection().isCaretBoundsDirty()) | 205 if (frameView.frame().selection().isCaretBoundsDirty()) |
189 frameView.frame().selection().invalidateCaretRect(); | 206 frameView.frame().selection().invalidateCaretRect(); |
190 | 207 |
191 // Temporary callback for crbug.com/487345,402044 | 208 // Temporary callback for crbug.com/487345,402044 |
192 // TODO(ojan): Make this more general to be used by PositionObserver | 209 // TODO(ojan): Make this more general to be used by PositionObserver |
193 // and rAF throttling. | 210 // and rAF throttling. |
194 IntRect visibleRect = frameView.rootFrameToContents(frameView.computeVisible Area()); | 211 IntRect visibleRect = frameView.rootFrameToContents(frameView.computeVisible Area()); |
195 layoutView->sendMediaPositionChangeNotifications(visibleRect); | 212 layoutView->sendMediaPositionChangeNotifications(visibleRect); |
196 } | 213 } |
197 | 214 |
215 static bool hasPercentageTransform(const ComputedStyle& style) | |
216 { | |
217 if (TransformOperation* translate = style.translate()) { | |
218 if (translate->dependsOnBoxSize()) | |
219 return true; | |
220 } | |
221 return style.transform().dependsOnBoxSize() | |
222 || (style.transformOriginX() != Length(50, Percent) && style.transformOr iginX().isPercentOrCalc()) | |
chrishtr
2016/09/13 23:30:03
There's no canonical way to detect non-default tra
Xianzhu
2016/09/13 23:47:15
We only need to check non-default percentage trans
| |
223 || (style.transformOriginY() != Length(50, Percent) && style.transformOr iginY().isPercentOrCalc()); | |
224 } | |
225 | |
198 void PaintInvalidator::invalidatePaintIfNeeded(const LayoutObject& object, Paint InvalidatorContext& context) | 226 void PaintInvalidator::invalidatePaintIfNeeded(const LayoutObject& object, Paint InvalidatorContext& context) |
199 { | 227 { |
200 object.getMutableForPainting().ensureIsReadyForPaintInvalidation(); | 228 object.getMutableForPainting().ensureIsReadyForPaintInvalidation(); |
201 | 229 |
202 if (!context.forcedSubtreeInvalidationFlags && !object.shouldCheckForPaintIn validationRegardlessOfPaintInvalidationState()) | 230 if (!context.forcedSubtreeInvalidationFlags && !object.shouldCheckForPaintIn validationRegardlessOfPaintInvalidationState()) |
203 return; | 231 return; |
204 | 232 |
205 updatePaintingLayer(object, context); | 233 updatePaintingLayer(object, context); |
206 | 234 |
207 if (object.document().printing()) | 235 if (object.document().printing()) |
208 return; // Don't invalidate paints if we're printing. | 236 return; // Don't invalidate paints if we're printing. |
209 | 237 |
210 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "PaintInvalida tor::invalidatePaintIfNeeded()", "object", object.debugName().ascii()); | 238 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "PaintInvalida tor::invalidatePaintIfNeeded()", "object", object.debugName().ascii()); |
211 | 239 |
212 updateContext(object, context); | 240 updateContext(object, context); |
213 | 241 |
214 if (!object.shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationStat e() && context.forcedSubtreeInvalidationFlags == PaintInvalidatorContext::Forced SubtreeInvalidationRectUpdate) { | 242 if (!object.shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationStat e() && context.forcedSubtreeInvalidationFlags == PaintInvalidatorContext::Forced SubtreeInvalidationRectUpdate) { |
215 // We are done updating the paint invalidation rect. No other paint inva lidation work to do for this object. | 243 // We are done updating the paint invalidation rect. No other paint inva lidation work to do for this object. |
216 return; | 244 return; |
217 } | 245 } |
218 | 246 |
219 switch (object.invalidatePaintIfNeeded(context)) { | 247 PaintInvalidationReason reason = object.invalidatePaintIfNeeded(context); |
248 switch (reason) { | |
220 case PaintInvalidationDelayedFull: | 249 case PaintInvalidationDelayedFull: |
221 m_pendingDelayedPaintInvalidations.append(&object); | 250 m_pendingDelayedPaintInvalidations.append(&object); |
222 break; | 251 break; |
223 case PaintInvalidationSubtree: | 252 case PaintInvalidationSubtree: |
224 context.forcedSubtreeInvalidationFlags |= (PaintInvalidatorContext::Forc edSubtreeFullInvalidation | PaintInvalidatorContext::ForcedSubtreeFullInvalidati onForStackedContents); | 253 context.forcedSubtreeInvalidationFlags |= (PaintInvalidatorContext::Forc edSubtreeFullInvalidation | PaintInvalidatorContext::ForcedSubtreeFullInvalidati onForStackedContents); |
225 break; | 254 break; |
226 case PaintInvalidationSVGResourceChange: | 255 case PaintInvalidationSVGResourceChange: |
227 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; | 256 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; |
228 break; | 257 break; |
229 default: | 258 default: |
230 break; | 259 break; |
231 } | 260 } |
232 | 261 |
233 if (context.oldLocation != context.newLocation) | 262 if (context.oldLocation != context.newLocation) |
234 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; | 263 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; |
235 | 264 |
265 // TODO(crbug.com/533277): This is a workaround for the bug. Remove when we detect paint offset change. | |
266 if (reason != PaintInvalidationNone && hasPercentageTransform(object.styleRe f())) | |
267 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; | |
268 | |
269 // TODO(crbug.com/490725): This is a workaround for the bug, to force descen dant to update paint invalidation | |
270 // rects on clipping change. | |
271 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() | |
272 && context.oldBounds != context.newBounds | |
273 // Note that isLayoutView() below becomes unnecessary after the launch o f root layer scrolling. | |
274 && (object.hasOverflowClip() || object.isLayoutView()) | |
275 && !toLayoutBox(object).usesCompositedScrolling()) | |
276 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationRectUpdate; | |
277 | |
236 object.getMutableForPainting().clearPaintInvalidationFlags(); | 278 object.getMutableForPainting().clearPaintInvalidationFlags(); |
237 } | 279 } |
238 | 280 |
239 void PaintInvalidator::processPendingDelayedPaintInvalidations() | 281 void PaintInvalidator::processPendingDelayedPaintInvalidations() |
240 { | 282 { |
241 for (auto target : m_pendingDelayedPaintInvalidations) | 283 for (auto target : m_pendingDelayedPaintInvalidations) |
242 target->getMutableForPainting().setShouldDoFullPaintInvalidation(PaintIn validationDelayedFull); | 284 target->getMutableForPainting().setShouldDoFullPaintInvalidation(PaintIn validationDelayedFull); |
243 } | 285 } |
244 | 286 |
245 } // namespace blink | 287 } // namespace blink |
OLD | NEW |