Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Unified Diff: third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp

Issue 1774193002: New paint invalidation using paint property tree walk (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Correct tracking of paintInvalidationContainer Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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).
}
}

Powered by Google App Engine
This is Rietveld 408576698