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

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

Issue 2539693002: Early-out from the prepaint tree walk (Closed)
Patch Set: Address chrishtrs comments Created 4 years 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
« no previous file with comments | « third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 f7764be657a11a07f087c0ff90a6194ff99e8be5..265fd62f90a6feb6bd50962ad12898aed6003819 100644
--- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
@@ -20,7 +20,6 @@ struct PrePaintTreeWalkContext {
paintInvalidatorContext(treeBuilderContext,
parentContext.paintInvalidatorContext) {}
- bool needToUpdatePaintPropertySubtree = false;
PaintPropertyTreeBuilderContext treeBuilderContext;
PaintInvalidatorContext paintInvalidatorContext;
};
@@ -36,75 +35,65 @@ void PrePaintTreeWalk::walk(FrameView& rootFrame) {
m_paintInvalidator.processPendingDelayedPaintInvalidations();
}
-void PrePaintTreeWalk::walk(FrameView& frameView,
+bool PrePaintTreeWalk::walk(FrameView& frameView,
const PrePaintTreeWalkContext& context) {
- if (frameView.shouldThrottleRendering())
- return;
-
- PrePaintTreeWalkContext localContext(context);
-
- // Check whether we need to update the paint property trees.
- if (!localContext.needToUpdatePaintPropertySubtree) {
- if (context.paintInvalidatorContext.forcedSubtreeInvalidationFlags) {
- // forcedSubtreeInvalidationFlags will be true if locations have changed
- // which will affect paint properties (e.g., PaintOffset).
- localContext.needToUpdatePaintPropertySubtree = true;
- } else if (frameView.needsPaintPropertyUpdate()) {
- localContext.needToUpdatePaintPropertySubtree = true;
- }
+ if (frameView.shouldThrottleRendering()) {
+ // The walk was interrupted by throttled rendering so this subtree was not
+ // fully updated.
+ return false;
}
- // Paint properties can depend on their ancestor properties so ensure the
- // entire subtree is rebuilt on any changes.
- // TODO(pdr): Add additional granularity to the needs update approach such as
- // the ability to do local updates that don't change the subtree.
- if (localContext.needToUpdatePaintPropertySubtree)
- frameView.setNeedsPaintPropertyUpdate();
+ PrePaintTreeWalkContext localContext(context);
m_propertyTreeBuilder.updateProperties(frameView,
localContext.treeBuilderContext);
-
m_paintInvalidator.invalidatePaintIfNeeded(
frameView, localContext.paintInvalidatorContext);
- if (LayoutView* layoutView = frameView.layoutView())
- walk(*layoutView, localContext);
-
+ LayoutView* view = frameView.layoutView();
+ bool descendantsFullyUpdated = view ? walk(*view, localContext) : true;
+ if (descendantsFullyUpdated) {
#if DCHECK_IS_ON()
- frameView.layoutView()->assertSubtreeClearedPaintInvalidationFlags();
+ frameView.layoutView()->assertSubtreeClearedPaintInvalidationFlags();
#endif
-
- frameView.clearNeedsPaintPropertyUpdate();
+ // If descendants were not fully updated, do not clear flags. During the
+ // next PrePaintTreeWalk, these flags will be used again.
+ frameView.clearNeedsPaintPropertyUpdate();
+ }
+ return descendantsFullyUpdated;
}
-void PrePaintTreeWalk::walk(const LayoutObject& object,
+bool PrePaintTreeWalk::walk(const LayoutObject& object,
const PrePaintTreeWalkContext& context) {
- PrePaintTreeWalkContext localContext(context);
-
- // Check whether we need to update the paint property trees.
- if (!localContext.needToUpdatePaintPropertySubtree) {
- if (context.paintInvalidatorContext.forcedSubtreeInvalidationFlags) {
- // forcedSubtreeInvalidationFlags will be true if locations have changed
- // which will affect paint properties (e.g., PaintOffset).
- localContext.needToUpdatePaintPropertySubtree = true;
- } else if (object.needsPaintPropertyUpdate()) {
- localContext.needToUpdatePaintPropertySubtree = true;
- } else if (object.mayNeedPaintInvalidation()) {
- // mayNeedpaintInvalidation will be true when locations change which will
- // affect paint properties (e.g., PaintOffset).
- localContext.needToUpdatePaintPropertySubtree = true;
- } else if (object.shouldDoFullPaintInvalidation()) {
- // shouldDoFullPaintInvalidation will be true when locations or overflow
- // changes which will affect paint properties (e.g., PaintOffset, scroll).
- localContext.needToUpdatePaintPropertySubtree = true;
- }
+ // Early out from the treewalk if possible.
+ if (!object.needsPaintPropertyUpdate() &&
+ !object.descendantNeedsPaintPropertyUpdate() &&
+ !context.treeBuilderContext.forceSubtreeUpdate &&
+ !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags &&
+ !object
+ .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) {
+ // Even though the subtree was not walked, we know that a walk will not
+ // change anything and can return true as if the subtree was fully updated.
+ return true;
}
- // Paint properties can depend on their ancestor properties so ensure the
- // entire subtree is rebuilt on any changes.
- // TODO(pdr): Add additional granularity to the needs update approach such as
- // the ability to do local updates that don't change the subtree.
- if (localContext.needToUpdatePaintPropertySubtree)
+ PrePaintTreeWalkContext localContext(context);
+
+ // TODO(pdr): These should be removable once paint offset changes mark an
+ // object as needing a paint property update. Below, we temporarily re-use
+ // paint invalidation flags to detect paint offset changes.
+ if (localContext.paintInvalidatorContext.forcedSubtreeInvalidationFlags) {
+ // forcedSubtreeInvalidationFlags will be true if locations have changed
+ // which will affect paint properties (e.g., PaintOffset).
+ localContext.treeBuilderContext.forceSubtreeUpdate = true;
+ } else if (object.shouldDoFullPaintInvalidation()) {
+ // shouldDoFullPaintInvalidation will be true when locations or overflow
+ // changes which will affect paint properties (e.g., PaintOffset, scroll).
+ object.getMutableForPainting().setNeedsPaintPropertyUpdate();
+ } else if (object.mayNeedPaintInvalidation()) {
+ // mayNeedpaintInvalidation will be true when locations change which will
+ // affect paint properties (e.g., PaintOffset).
object.getMutableForPainting().setNeedsPaintPropertyUpdate();
+ }
// TODO(pdr): Ensure multi column works with incremental property tree
// construction.
@@ -114,13 +103,18 @@ void PrePaintTreeWalk::walk(const LayoutObject& object,
// positioned descendants if their containers are between the multi-column
// container and the spanner. See PaintPropertyTreeBuilder for details.
localContext.treeBuilderContext.isUnderMultiColumnSpanner = true;
- walk(*toLayoutMultiColumnSpannerPlaceholder(object)
- .layoutObjectInFlowThread(),
- localContext);
- object.getMutableForPainting().clearPaintInvalidationFlags();
- object.getMutableForPainting().clearNeedsPaintPropertyUpdate();
- object.getMutableForPainting().clearDescendantNeedsPaintPropertyUpdate();
- return;
+ bool descendantsFullyUpdated =
+ walk(*toLayoutMultiColumnSpannerPlaceholder(object)
+ .layoutObjectInFlowThread(),
+ localContext);
+ if (descendantsFullyUpdated) {
+ // If descendants were not fully updated, do not clear flags. During the
+ // next PrePaintTreeWalk, these flags will be used again.
+ object.getMutableForPainting().clearPaintInvalidationFlags();
+ object.getMutableForPainting().clearNeedsPaintPropertyUpdate();
+ object.getMutableForPainting().clearDescendantNeedsPaintPropertyUpdate();
+ }
+ return descendantsFullyUpdated;
}
m_propertyTreeBuilder.updatePropertiesForSelf(
@@ -130,12 +124,15 @@ void PrePaintTreeWalk::walk(const LayoutObject& object,
m_propertyTreeBuilder.updatePropertiesForChildren(
object, localContext.treeBuilderContext);
+ bool descendantsFullyUpdated = true;
for (const LayoutObject* child = object.slowFirstChild(); child;
child = child->nextSibling()) {
// Column spanners are walked through their placeholders. See above.
if (child->isColumnSpanAll())
continue;
- walk(*child, localContext);
+ bool childFullyUpdated = walk(*child, localContext);
+ if (!childFullyUpdated)
+ descendantsFullyUpdated = false;
}
if (object.isLayoutPart()) {
@@ -147,14 +144,21 @@ void PrePaintTreeWalk::walk(const LayoutObject& object,
widget->frameRect().location();
localContext.treeBuilderContext.current.paintOffset =
roundedIntPoint(localContext.treeBuilderContext.current.paintOffset);
- walk(*toFrameView(widget), localContext);
+ bool frameFullyUpdated = walk(*toFrameView(widget), localContext);
+ if (!frameFullyUpdated)
+ descendantsFullyUpdated = false;
}
// TODO(pdr): Investigate RemoteFrameView (crbug.com/579281).
}
- object.getMutableForPainting().clearPaintInvalidationFlags();
- object.getMutableForPainting().clearNeedsPaintPropertyUpdate();
- object.getMutableForPainting().clearDescendantNeedsPaintPropertyUpdate();
+ if (descendantsFullyUpdated) {
+ // If descendants were not updated, do not clear flags. During the next
+ // PrePaintTreeWalk, these flags will be used again.
+ object.getMutableForPainting().clearPaintInvalidationFlags();
+ object.getMutableForPainting().clearNeedsPaintPropertyUpdate();
+ object.getMutableForPainting().clearDescendantNeedsPaintPropertyUpdate();
+ }
+ return descendantsFullyUpdated;
}
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698