Chromium Code Reviews| 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 |