| 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 eca81e847a11fdab77a40a570d0fe25197748e85..6715959df4a1d838404810a8a61a82fefffe728d 100644
|
| --- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
|
| +++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
|
| @@ -19,17 +19,28 @@ struct PrePaintTreeWalkContext {
|
| PrePaintTreeWalkContext()
|
| : treeBuilderContext(
|
| WTF::wrapUnique(new PaintPropertyTreeBuilderContext)),
|
| - paintInvalidatorContext(*treeBuilderContext),
|
| + paintInvalidatorContext(treeBuilderContext.get()),
|
| 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,10 +64,8 @@ void PrePaintTreeWalk::walk(FrameView& rootFrame) {
|
| initialContext.ancestorTransformedOrRootPaintLayer =
|
| rootFrame.layoutView()->layer();
|
|
|
| - // GeometryMapper caches depend on paint properties.
|
| - if (rootFrame.needsPaintPropertyUpdate() ||
|
| - (rootFrame.layoutView() &&
|
| - !shouldEndWalkBefore(*rootFrame.layoutView(), initialContext)))
|
| + // GeometryMapper depends on paint properties.
|
| + if (needsTreeBuilderContextUpdate(rootFrame, initialContext))
|
| GeometryMapper::clearCache();
|
|
|
| walk(rootFrame, initialContext);
|
| @@ -70,11 +79,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);
|
|
|
| @@ -204,41 +217,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()) {
|
| @@ -253,11 +286,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).
|
|
|