Index: third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp |
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp |
index 3cc8cc1208933e5c5ff79ece7e85c47243cfdc71..c56ecac648d0489273ca0533e08ac78ce1ff38d0 100644 |
--- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp |
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp |
@@ -18,17 +18,28 @@ struct PrePaintTreeWalkContext { |
PrePaintTreeWalkContext(GeometryMapper& geometryMapper) |
: treeBuilderContext( |
WTF::wrapUnique(new PaintPropertyTreeBuilderContext)), |
- paintInvalidatorContext(*treeBuilderContext, geometryMapper), |
+ paintInvalidatorContext(treeBuilderContext.get(), geometryMapper), |
ancestorOverflowPaintLayer(nullptr), |
ancestorTransformedOrRootPaintLayer(nullptr) {} |
- PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parentContext) |
- : treeBuilderContext(WTF::wrapUnique(new PaintPropertyTreeBuilderContext( |
- *parentContext.treeBuilderContext))), |
- paintInvalidatorContext(*treeBuilderContext, |
+ |
+ PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parentContext, |
+ bool needsTreeBuilderContext) |
+ : treeBuilderContext( |
+ WTF::wrapUnique(needsTreeBuilderContext || DCHECK_IS_ON() |
+ ? new PaintPropertyTreeBuilderContext( |
+ *parentContext.treeBuilderContext) |
+ : nullptr)), |
+ paintInvalidatorContext(treeBuilderContext.get(), |
parentContext.paintInvalidatorContext), |
ancestorOverflowPaintLayer(parentContext.ancestorOverflowPaintLayer), |
ancestorTransformedOrRootPaintLayer( |
- parentContext.ancestorTransformedOrRootPaintLayer) {} |
+ parentContext.ancestorTransformedOrRootPaintLayer) { |
+#if DCHECK_IS_ON() |
+ if (needsTreeBuilderContext) |
+ DCHECK(parentContext.treeBuilderContext->isActuallyNeeded); |
+ treeBuilderContext->isActuallyNeeded = needsTreeBuilderContext; |
+#endif |
+ } |
// PaintPropertyTreeBuilderContext is large and can lead to stack overflows |
// when recursion is deep so this context object is allocated on the heap. |
@@ -53,9 +64,7 @@ void PrePaintTreeWalk::walk(FrameView& rootFrame) { |
rootFrame.layoutView()->layer(); |
// GeometryMapper depends on paint properties. |
- if (rootFrame.needsPaintPropertyUpdate() || |
- (rootFrame.layoutView() && |
- !shouldEndWalkBefore(*rootFrame.layoutView(), initialContext))) |
+ if (needsTreeBuilderContextUpdate(rootFrame, initialContext)) |
m_geometryMapper.clearCache(); |
walk(rootFrame, initialContext); |
@@ -69,11 +78,15 @@ void PrePaintTreeWalk::walk(FrameView& frameView, |
return; |
} |
- PrePaintTreeWalkContext context(parentContext); |
+ bool needsTreeBuilderContextUpdate = |
+ this->needsTreeBuilderContextUpdate(frameView, parentContext); |
+ PrePaintTreeWalkContext context(parentContext, needsTreeBuilderContextUpdate); |
// ancestorOverflowLayer does not cross frame boundaries. |
context.ancestorOverflowPaintLayer = nullptr; |
- m_propertyTreeBuilder.updateProperties(frameView, |
- *context.treeBuilderContext); |
+ if (context.treeBuilderContext) { |
+ m_propertyTreeBuilder.updateProperties(frameView, |
+ *context.treeBuilderContext); |
+ } |
m_paintInvalidator.invalidatePaintIfNeeded(frameView, |
context.paintInvalidatorContext); |
@@ -224,41 +237,61 @@ void PrePaintTreeWalk::invalidatePaintLayerOptimizationsIfNeeded( |
// All subsequences which are contained below this paintLayer must also |
// be checked. |
context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= |
- PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; |
+ PaintInvalidatorContext::ForcedSubtreeVisualRectUpdate; |
} |
paintLayer.setPreviousPaintingClipRects(*clipRects); |
} |
-bool PrePaintTreeWalk::shouldEndWalkBefore( |
- const LayoutObject& object, |
+bool PrePaintTreeWalk::needsTreeBuilderContextUpdate( |
+ const FrameView& frameView, |
const PrePaintTreeWalkContext& context) { |
- return !object.needsPaintPropertyUpdate() && |
- !object.descendantNeedsPaintPropertyUpdate() && |
- !context.treeBuilderContext->forceSubtreeUpdate && |
- !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags && |
- !object.shouldCheckForPaintInvalidation(); |
+ return frameView.needsPaintPropertyUpdate() || |
+ (frameView.layoutView() && |
+ needsTreeBuilderContextUpdate(*frameView.layoutView(), context)); |
+} |
+ |
+bool PrePaintTreeWalk::needsTreeBuilderContextUpdate( |
+ const LayoutObject& object, |
+ const PrePaintTreeWalkContext& parentContext) { |
+ return object.needsPaintPropertyUpdate() || |
+ object.descendantNeedsPaintPropertyUpdate() || |
+ (parentContext.treeBuilderContext && |
+ parentContext.treeBuilderContext->forceSubtreeUpdate) || |
+ // If the object needs visual rect update, we should update tree |
+ // builder context which is needed by visual rect update. |
+ parentContext.paintInvalidatorContext.needsVisualRectUpdate(object); |
} |
void PrePaintTreeWalk::walk(const LayoutObject& object, |
const PrePaintTreeWalkContext& parentContext) { |
- if (shouldEndWalkBefore(object, parentContext)) |
+ // Early out from the tree walk if possible. |
+ bool needsTreeBuilderContextUpdate = |
+ this->needsTreeBuilderContextUpdate(object, parentContext); |
+ if (!needsTreeBuilderContextUpdate && |
+ !object.shouldCheckForPaintInvalidation()) |
return; |
- PrePaintTreeWalkContext context(parentContext); |
+ PrePaintTreeWalkContext context(parentContext, needsTreeBuilderContextUpdate); |
// This must happen before updatePropertiesForSelf, because the latter reads |
// some of the state computed here. |
updateAuxiliaryObjectProperties(object, context); |
- m_propertyTreeBuilder.updatePropertiesForSelf(object, |
- *context.treeBuilderContext); |
+ if (context.treeBuilderContext) { |
+ DCHECK(context.treeBuilderContext); |
+ m_propertyTreeBuilder.updatePropertiesForSelf(object, |
+ *context.treeBuilderContext); |
+ } |
+ |
m_paintInvalidator.invalidatePaintIfNeeded(object, |
context.paintInvalidatorContext); |
- m_propertyTreeBuilder.updatePropertiesForChildren( |
- object, *context.treeBuilderContext); |
- invalidatePaintLayerOptimizationsIfNeeded(object, context); |
+ if (context.treeBuilderContext) { |
+ m_propertyTreeBuilder.updatePropertiesForChildren( |
+ object, *context.treeBuilderContext); |
+ invalidatePaintLayerOptimizationsIfNeeded(object, context); |
+ } |
for (const LayoutObject* child = object.slowFirstChild(); child; |
child = child->nextSibling()) { |
@@ -273,11 +306,13 @@ void PrePaintTreeWalk::walk(const LayoutObject& object, |
const LayoutPart& layoutPart = toLayoutPart(object); |
FrameViewBase* frameViewBase = layoutPart.frameViewBase(); |
if (frameViewBase && frameViewBase->isFrameView()) { |
- context.treeBuilderContext->current.paintOffset += |
- layoutPart.replacedContentRect().location() - |
- frameViewBase->frameRect().location(); |
- context.treeBuilderContext->current.paintOffset = |
- roundedIntPoint(context.treeBuilderContext->current.paintOffset); |
+ if (context.treeBuilderContext) { |
+ context.treeBuilderContext->current.paintOffset += |
+ layoutPart.replacedContentRect().location() - |
+ frameViewBase->frameRect().location(); |
+ context.treeBuilderContext->current.paintOffset = |
+ roundedIntPoint(context.treeBuilderContext->current.paintOffset); |
+ } |
walk(*toFrameView(frameViewBase), context); |
} |
// TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |