Chromium Code Reviews| Index: third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
| diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
| index c8b5e3cd9fb9ae154c4737c2e3a84efcc47be584..f40b199e55d748c803328be78de97d62b5e51c9b 100644 |
| --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
| +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
| @@ -21,25 +21,24 @@ namespace blink { |
| // container seen. |
| struct PaintPropertyTreeBuilderContext { |
| PaintPropertyTreeBuilderContext() |
| - : currentTransform(nullptr) |
| - , currentClip(nullptr) |
| - , transformForAbsolutePosition(nullptr) |
| - , clipForAbsolutePosition(nullptr) |
| - , transformForFixedPosition(nullptr) |
| - , clipForFixedPosition(nullptr) |
| - , currentEffect(nullptr) { } |
| + : paintInvalidationContainer(nullptr) |
| + , paintInvalidationContainerForOutOfFlowPositioned(nullptr) |
| + { } |
| + |
| + // TODO(wangxianzhu): The RefPtrs are needed for SPv1 which doesn't save the properties |
| + // into LayoutObjects. Change them to normal pointers for SPv2. |
| // The combination of a transform and paint offset describes a linear space. |
| // When a layout object recur to its children, the main context is expected to refer |
| // the object's border box, then the callee will derive its own border box by translating |
| // the space with its own layout location. |
| - TransformPaintPropertyNode* currentTransform; |
| + RefPtr<TransformPaintPropertyNode> currentTransform; |
| LayoutPoint paintOffset; |
| // The clip node describes the accumulated raster clip for the current subtree. |
| // Note that the computed raster region in canvas space for a clip node is independent from |
| // the transform and paint offset above. Also the actual raster region may be affected |
| // by layerization and occlusion tracking. |
| - ClipPaintPropertyNode* currentClip; |
| + RefPtr<ClipPaintPropertyNode> currentClip; |
| // Separate context for out-of-flow positioned and fixed positioned elements are needed |
| // because they don't use DOM parent as their containing block. |
| @@ -48,26 +47,29 @@ struct PaintPropertyTreeBuilderContext { |
| // positioned descendants. |
| // Overflow clips are also inherited by containing block tree instead of DOM tree, thus they |
| // are included in the additional context too. |
| - TransformPaintPropertyNode* transformForAbsolutePosition; |
| + RefPtr<TransformPaintPropertyNode> transformForAbsolutePosition; |
| LayoutPoint paintOffsetForAbsolutePosition; |
| - ClipPaintPropertyNode* clipForAbsolutePosition; |
| + RefPtr<ClipPaintPropertyNode> clipForAbsolutePosition; |
| - TransformPaintPropertyNode* transformForFixedPosition; |
| + RefPtr<TransformPaintPropertyNode> transformForFixedPosition; |
| LayoutPoint paintOffsetForFixedPosition; |
| - ClipPaintPropertyNode* clipForFixedPosition; |
| + RefPtr<ClipPaintPropertyNode> clipForFixedPosition; |
| // The effect hierarchy is applied by the stacking context tree. It is guaranteed that every |
| // DOM descendant is also a stacking context descendant. Therefore, we don't need extra |
| // bookkeeping for effect nodes and can generate the effect tree from a DOM-order traversal. |
| - EffectPaintPropertyNode* currentEffect; |
| + RefPtr<EffectPaintPropertyNode> currentEffect; |
| + |
| + const LayoutBoxModelObject* paintInvalidationContainer; |
|
pdr.
2016/03/11 02:56:41
Even when spv2 and spinvalidation are both enabled
Xianzhu
2016/03/11 20:03:44
The paintInvalidationContainer fields are for spv1
|
| + const LayoutBoxModelObject* paintInvalidationContainerForOutOfFlowPositioned; |
| }; |
| void PaintPropertyTreeBuilder::buildPropertyTrees(FrameView& rootFrame) |
| { |
| - walk(rootFrame, PaintPropertyTreeBuilderContext()); |
| + walk(rootFrame, PaintPropertyTreeBuilderContext(), nullptr); |
| } |
| -void PaintPropertyTreeBuilder::walk(FrameView& frameView, const PaintPropertyTreeBuilderContext& context) |
| +void PaintPropertyTreeBuilder::walk(FrameView& frameView, const PaintPropertyTreeBuilderContext& context, const PaintInvalidationState* paintInvalidationState) |
| { |
| PaintPropertyTreeBuilderContext localContext(context); |
| @@ -97,39 +99,40 @@ void PaintPropertyTreeBuilder::walk(FrameView& frameView, const PaintPropertyTre |
| frameView.setContentClip(newClipNodeForContentClip.release()); |
| if (LayoutView* layoutView = frameView.layoutView()) |
| - walk(*layoutView, localContext); |
| + walk(*layoutView, localContext, paintInvalidationState); |
| } |
| -static void deriveBorderBoxFromContainerContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +static void adjustContainerContextForPosition(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| { |
| - if (!object.isBoxModelObject()) |
| - return; |
| - |
| - const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); |
| - |
| - // TODO(trchen): There is some insanity going on with tables. Double check results. |
| switch (object.styleRef().position()) { |
| - case StaticPosition: |
| - break; |
| - case RelativePosition: |
| - context.paintOffset += boxModelObject.offsetForInFlowPosition(); |
| - break; |
| case AbsolutePosition: |
| context.currentTransform = context.transformForAbsolutePosition; |
| context.paintOffset = context.paintOffsetForAbsolutePosition; |
| context.currentClip = context.clipForAbsolutePosition; |
| - break; |
| - case StickyPosition: |
| - context.paintOffset += boxModelObject.offsetForInFlowPosition(); |
| + context.paintInvalidationContainer = context.paintInvalidationContainerForOutOfFlowPositioned; |
| break; |
| case FixedPosition: |
| context.currentTransform = context.transformForFixedPosition; |
| context.paintOffset = context.paintOffsetForFixedPosition; |
| context.currentClip = context.clipForFixedPosition; |
| + context.paintInvalidationContainer = context.paintInvalidationContainerForOutOfFlowPositioned; |
| break; |
| default: |
| - ASSERT_NOT_REACHED(); |
| + break; |
| } |
| +} |
| + |
| +static void deriveBorderBoxFromContainerContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +{ |
| + if (!object.isBoxModelObject()) |
| + return; |
| + |
| + const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); |
| + |
| + // TODO(trchen): There is some insanity going on with tables. Double check results. |
| + if (object.isInFlowPositioned()) |
| + context.paintOffset += boxModelObject.offsetForInFlowPosition(); |
| + |
| if (boxModelObject.isBox()) |
| context.paintOffset += toLayoutBox(boxModelObject).locationOffset(); |
| } |
| @@ -236,7 +239,7 @@ static PassRefPtr<ClipPaintPropertyNode> createOverflowClipIfNeeded(const Layout |
| RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = ClipPaintPropertyNode::create( |
| context.currentTransform, |
| FloatRoundedRect(FloatRect(clipRect)), |
| - newClipNodeForBorderRadiusClip ? newClipNodeForBorderRadiusClip.release() : context.currentClip); |
| + newClipNodeForBorderRadiusClip ? newClipNodeForBorderRadiusClip.release() : PassRefPtr<ClipPaintPropertyNode>(context.currentClip)); |
| context.currentClip = newClipNodeForOverflowClip.get(); |
| return newClipNodeForOverflowClip.release(); |
| } |
| @@ -303,7 +306,7 @@ static void updateOutOfFlowContext(const LayoutObject& object, PaintPropertyTree |
| } |
| } |
| -static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeContextIfNeeded(LayoutObject& object, const PaintPropertyTreeBuilderContext& context) |
| +static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeContextIfNeeded(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context) |
| { |
| // Note: Currently only layer painter makes use of the pre-computed context. |
| // This condition may be loosened with no adverse effects beside memory use. |
| @@ -318,45 +321,94 @@ static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeCon |
| return recordedContext.release(); |
| } |
| -void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTreeBuilderContext& context) |
| +static void updatePaintInvalidationContainer(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +{ |
| + if (!object.isPaintInvalidationContainer()) { |
| + if (context.paintInvalidationContainer) |
| + return; |
| + ASSERT(object.isLayoutView()); |
| + } |
| + |
| + context.currentTransform = nullptr; |
| + context.paintOffset = LayoutPoint(); |
| + context.currentClip = nullptr; |
| + context.paintInvalidationContainer = &toLayoutBoxModelObject(object); |
| + |
| + if (object.styleRef().isStackingContext() || !context.paintInvalidationContainerForOutOfFlowPositioned) { |
|
pdr.
2016/03/11 02:56:41
Can you help me understand why this is needed?
We
Xianzhu
2016/03/11 20:03:44
This is for SPv1 only in which we need to keep sep
|
| + // TODO(wangxianzhu): The following may be incorrect for some complex cases. Investigate if we could |
| + // make it correct for all cases or have to use ForceHorriblySlowRectMapping. |
| + context.transformForAbsolutePosition = nullptr; |
| + context.paintOffsetForAbsolutePosition = LayoutPoint(); |
| + context.clipForAbsolutePosition = nullptr; |
| + context.transformForFixedPosition = nullptr; |
| + context.paintOffsetForFixedPosition = LayoutPoint(); |
| + context.clipForFixedPosition = nullptr; |
| + context.paintInvalidationContainerForOutOfFlowPositioned = &toLayoutBoxModelObject(object); |
| + } |
| +} |
| + |
| +void PaintPropertyTreeBuilder::walk(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context, const PaintInvalidationState* parentPaintInvalidationState) |
| { |
| PaintPropertyTreeBuilderContext localContext(context); |
| + adjustContainerContextForPosition(object, localContext); |
| + |
| + Optional<PaintInvalidationState> paintInvalidationState; |
| + if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) { |
| + if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| + updatePaintInvalidationContainer(object, localContext); |
| + paintInvalidationState.emplace(parentPaintInvalidationState, object, *localContext.paintInvalidationContainer, localContext.paintOffset); |
| + if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && !object.shouldCheckForPaintInvalidation(*paintInvalidationState)) |
| + return; |
| + |
| + PaintInvalidationReason reason = object.getMutableForPainting().invalidatePaintIfNeeded(*paintInvalidationState, *localContext.paintInvalidationContainer); |
| + object.getMutableForPainting().clearPaintInvalidationState(*paintInvalidationState); |
| + if (reason == PaintInvalidationDelayedFull) |
| + m_pendingDelayedPaintInvalidations.append(const_cast<LayoutObject*>(&object)); |
| + } |
| - deriveBorderBoxFromContainerContext(object, localContext); |
| - RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext); |
| - RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTransformIfNeeded(object, localContext); |
| - RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); |
| - OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> newRecordedContext = recordTreeContextIfNeeded(object, localContext); |
| - RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = createOverflowClipIfNeeded(object, localContext); |
| - // TODO(trchen): Insert flattening transform here, as specified by |
| - // http://www.w3.org/TR/css3-transforms/#transform-style-property |
| - RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPerspectiveIfNeeded(object, localContext); |
| - RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext); |
| - updateOutOfFlowContext(object, localContext); |
| - |
| - if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransform || newEffectNode || newClipNodeForOverflowClip || newTransformNodeForPerspective || newTransformNodeForScrollTranslation || newRecordedContext) { |
| - OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProperties::create( |
| - newTransformNodeForPaintOffsetTranslation.release(), |
| - newTransformNodeForTransform.release(), |
| - newEffectNode.release(), |
| - newClipNodeForOverflowClip.release(), |
| - newTransformNodeForPerspective.release(), |
| - newTransformNodeForScrollTranslation.release(), |
| - newRecordedContext.release()); |
| - object.setObjectPaintProperties(updatedPaintProperties.release()); |
| - } else { |
| - object.clearObjectPaintProperties(); |
| + if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() || !object.isPaintInvalidationContainer()) { |
| + deriveBorderBoxFromContainerContext(object, localContext); |
| + RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext); |
| + RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTransformIfNeeded(object, localContext); |
| + RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); |
| + OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> newRecordedContext = recordTreeContextIfNeeded(object, localContext); |
| + RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = createOverflowClipIfNeeded(object, localContext); |
| + // TODO(trchen): Insert flattening transform here, as specified by |
| + // http://www.w3.org/TR/css3-transforms/#transform-style-property |
| + RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPerspectiveIfNeeded(object, localContext); |
| + RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext); |
| + updateOutOfFlowContext(object, localContext); |
| + |
| + if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| + if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransform || newEffectNode || newClipNodeForOverflowClip || newTransformNodeForPerspective || newTransformNodeForScrollTranslation || newRecordedContext) { |
| + OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProperties::create( |
| + newTransformNodeForPaintOffsetTranslation.release(), |
| + newTransformNodeForTransform.release(), |
| + newEffectNode.release(), |
| + newClipNodeForOverflowClip.release(), |
| + newTransformNodeForPerspective.release(), |
| + newTransformNodeForScrollTranslation.release(), |
| + newRecordedContext.release()); |
| + object.getMutableForPainting().setObjectPaintProperties(updatedPaintProperties.release()); |
| + } else { |
| + object.getMutableForPainting().clearObjectPaintProperties(); |
| + } |
| + } |
| } |
| - for (LayoutObject* child = object.slowFirstChild(); child; child = child->nextSibling()) { |
| - if (child->isBoxModelObject() || child->isSVG()) |
| - walk(*child, localContext); |
| + for (const LayoutObject* child = object.slowFirstChild(); child; child = child->nextSibling()) { |
| + if (child->isBoxModelObject() || child->isSVG()) { |
| + walk(*child, localContext, paintInvalidationState.get()); |
| + } else if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() && child->shouldCheckForPaintInvalidation(*paintInvalidationState)) { |
| + child->getMutableForPainting().invalidatePaintIfNeeded(*paintInvalidationState, *localContext.paintInvalidationContainer); |
| + child->getMutableForPainting().clearPaintInvalidationState(*paintInvalidationState); |
| + } |
| } |
| if (object.isLayoutPart()) { |
| Widget* widget = toLayoutPart(object).widget(); |
| if (widget && widget->isFrameView()) |
| - walk(*toFrameView(widget), localContext); |
| + walk(*toFrameView(widget), localContext, paintInvalidationState.get()); |
| // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
| } |
| } |