| 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).
|
|
|