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

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

Issue 1774193002: New paint invalidation using paint property tree walk (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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/PrePaintTreeWalk.cpp
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
similarity index 63%
rename from third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
rename to third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
index 224f99c3872452f09416b9b52931a5de571633fb..fb5c2e8f970ed62a08e7e650eba428708692d6e4 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "core/paint/PaintPropertyTreeBuilder.h"
+#include "core/paint/PrePaintTreeWalk.h"
#include "core/frame/FrameView.h"
#include "core/layout/LayoutPart.h"
@@ -19,27 +19,26 @@ namespace blink {
// The walk will be done in the primary tree order (= DOM order), thus the context will also be
// responsible for bookkeeping tree state in other order, for example, the most recent position
// container seen.
-struct PaintPropertyTreeBuilderContext {
- PaintPropertyTreeBuilderContext()
- : currentTransform(nullptr)
- , currentClip(nullptr)
- , transformForAbsolutePosition(nullptr)
- , clipForAbsolutePosition(nullptr)
- , transformForFixedPosition(nullptr)
- , clipForFixedPosition(nullptr)
- , currentEffect(nullptr) { }
+struct PrePaintTreeWalkContext {
+ PrePaintTreeWalkContext()
+ : paintInvalidationContainer(nullptr)
+ , paintInvalidationContainerForOutOfFlowPositioned(nullptr)
trchen 2016/03/11 23:09:39 The name of the variable isn't accurate. Paint inv
+ { }
+
+ // 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,28 +47,32 @@ 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;
+
+ // For SPv1 only.
+ const LayoutBoxModelObject* paintInvalidationContainer;
+ const LayoutBoxModelObject* paintInvalidationContainerForOutOfFlowPositioned;
};
-void PaintPropertyTreeBuilder::buildPropertyTrees(FrameView& rootFrame)
+void PrePaintTreeWalk::buildPropertyTreesAndInvalidatePaint(FrameView& rootFrame)
{
- walk(rootFrame, PaintPropertyTreeBuilderContext());
+ walk(rootFrame, PrePaintTreeWalkContext(), nullptr);
}
-void PaintPropertyTreeBuilder::walk(FrameView& frameView, const PaintPropertyTreeBuilderContext& context)
+void PrePaintTreeWalk::walk(FrameView& frameView, const PrePaintTreeWalkContext& context, const PaintInvalidationState* paintInvalidationState)
{
- PaintPropertyTreeBuilderContext localContext(context);
+ PrePaintTreeWalkContext localContext(context);
// TODO(pdr): Creating paint properties for FrameView here will not be
// needed once settings()->rootLayerScrolls() is enabled.
@@ -97,44 +100,45 @@ 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, PrePaintTreeWalkContext& 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;
trchen 2016/03/11 23:36:19 Per the previous comment, it is not the right plac
break;
case FixedPosition:
context.currentTransform = context.transformForFixedPosition;
context.paintOffset = context.paintOffsetForFixedPosition;
context.currentClip = context.clipForFixedPosition;
+ context.paintInvalidationContainer = context.paintInvalidationContainerForOutOfFlowPositioned;
trchen 2016/03/11 23:36:19 Ditto.
break;
default:
- ASSERT_NOT_REACHED();
+ break;
}
+}
+
+static void deriveBorderBoxFromContainerContext(const LayoutObject& object, PrePaintTreeWalkContext& 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())
trchen 2016/03/11 23:36:19 While this refactoring is appreciated, can we do t
+ context.paintOffset += boxModelObject.offsetForInFlowPosition();
+
if (boxModelObject.isBox())
context.paintOffset += toLayoutBox(boxModelObject).locationOffset();
}
-static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeeded(const LayoutObject& object, PrePaintTreeWalkContext& context)
{
bool shouldCreatePaintOffsetTranslationNode = false;
if (object.isSVGRoot()) {
@@ -167,7 +171,7 @@ static FloatPoint3D transformOrigin(const LayoutBox& box)
style.transformOriginZ());
}
-static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const LayoutObject& object, PrePaintTreeWalkContext& context)
{
if (object.isSVG() && !object.isSVGRoot()) {
const AffineTransform& transform = object.localToParentTransform();
@@ -196,7 +200,7 @@ static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const Layo
return newTransformNodeForTransform.release();
}
-static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObject& object, PrePaintTreeWalkContext& context)
{
const ComputedStyle& style = object.styleRef();
if (!style.hasOpacity())
@@ -206,7 +210,7 @@ static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObje
return newEffectNode.release();
}
-static PassRefPtr<ClipPaintPropertyNode> createOverflowClipIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<ClipPaintPropertyNode> createOverflowClipIfNeeded(const LayoutObject& object, PrePaintTreeWalkContext& context)
{
if (!object.isBox())
return nullptr;
@@ -236,7 +240,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();
}
@@ -250,7 +254,7 @@ static FloatPoint perspectiveOrigin(const LayoutBox& box)
floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height()));
}
-static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const LayoutObject& object, PrePaintTreeWalkContext& context)
{
const ComputedStyle& style = object.styleRef();
if (!object.isBox() || !style.hasPerspective())
@@ -263,7 +267,7 @@ static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const La
return newTransformNodeForPerspective.release();
}
-static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
+static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(const LayoutObject& object, PrePaintTreeWalkContext& context)
{
if (!object.isBoxModelObject() || !object.hasOverflowClip())
return nullptr;
@@ -281,7 +285,7 @@ static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(co
return newTransformNodeForScrollTranslation.release();
}
-static void updateOutOfFlowContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
+static void updateOutOfFlowContext(const LayoutObject& object, PrePaintTreeWalkContext& context)
{
// At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is
// up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning
@@ -303,7 +307,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 PrePaintTreeWalkContext& 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 +322,99 @@ static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeCon
return recordedContext.release();
}
-void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTreeBuilderContext& context)
+static void updatePaintInvalidationContainer(const LayoutObject& object, PrePaintTreeWalkContext& context)
{
- PaintPropertyTreeBuilderContext localContext(context);
-
- 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();
+ // Paint invalidation container is a SPv1-only concept.
+ ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled());
+
+ if (!object.isPaintInvalidationContainer()) {
trchen 2016/03/11 23:36:19 This doesn't look right. I think it should be if
+ if (context.paintInvalidationContainer)
+ return;
+ ASSERT(object.isLayoutView());
+ }
+
+ context.currentTransform = nullptr;
+ context.paintOffset = LayoutPoint();
+ context.currentClip = nullptr;
+ context.paintInvalidationContainer = &toLayoutBoxModelObject(object);
+
+ // A composited stacking context establishes new paint invalidation container for
+ // out-of-flow-positioned descendants.
+ if (object.styleRef().isStackingContext() || !context.paintInvalidationContainerForOutOfFlowPositioned) {
+ // 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.
trchen 2016/03/11 23:36:19 As pdr@ already pointed out, I don't think it make
+ context.transformForAbsolutePosition = nullptr;
+ context.paintOffsetForAbsolutePosition = LayoutPoint();
+ context.clipForAbsolutePosition = nullptr;
+ context.transformForFixedPosition = nullptr;
+ context.paintOffsetForFixedPosition = LayoutPoint();
+ context.clipForFixedPosition = nullptr;
+ context.paintInvalidationContainerForOutOfFlowPositioned = &toLayoutBoxModelObject(object);
+ }
+}
+
+void PrePaintTreeWalk::walk(const LayoutObject& object, const PrePaintTreeWalkContext& context, const PaintInvalidationState* parentPaintInvalidationState)
+{
+ PrePaintTreeWalkContext 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;
trchen 2016/03/11 23:36:19 The early return check is too late, and the semant
+
+ PaintInvalidationReason reason = object.getMutableForPainting().invalidatePaintIfNeeded(*paintInvalidationState, *localContext.paintInvalidationContainer);
+ object.getMutableForPainting().clearPaintInvalidationState(*paintInvalidationState);
+ if (reason == PaintInvalidationDelayedFull)
+ m_pendingDelayedPaintInvalidations.append(const_cast<LayoutObject*>(&object));
+ }
+
+ 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).
}
}
« no previous file with comments | « third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h ('k') | third_party/WebKit/Source/core/paint/PrePaintTreeWalkTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698