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

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

Issue 2495893002: Implement incremental paint property tree rebuilding (Closed)
Patch Set: Suppress main thread scrolling invalidation failures Created 4 years, 1 month 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 7809718197662d42c7d098da2a81de3594935373..2ca46226fd107407f6a2125a858841a3d2dd0040 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -10,6 +10,7 @@
#include "core/layout/LayoutInline.h"
#include "core/layout/LayoutView.h"
#include "core/layout/svg/LayoutSVGRoot.h"
+#include "core/paint/FindPropertiesNeedingUpdate.h"
#include "core/paint/ObjectPaintProperties.h"
#include "core/paint/PaintLayer.h"
#include "core/paint/SVGRootPainter.h"
@@ -101,7 +102,7 @@ void updateFrameViewScroll(
}
}
-void PaintPropertyTreeBuilder::updateFramePropertiesAndContext(
+void PaintPropertyTreeBuilder::updateProperties(
FrameView& frameView,
PaintPropertyTreeBuilderContext& context) {
if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
@@ -118,38 +119,44 @@ void PaintPropertyTreeBuilder::updateFramePropertiesAndContext(
return;
}
- TransformationMatrix frameTranslate;
- frameTranslate.translate(frameView.x() + context.current.paintOffset.x(),
- frameView.y() + context.current.paintOffset.y());
- updateFrameViewPreTranslation(frameView, context.current.transform,
- frameTranslate, FloatPoint3D());
-
- FloatRoundedRect contentClip(
- IntRect(IntPoint(), frameView.visibleContentSize()));
- updateFrameViewContentClip(frameView, context.current.clip,
- frameView.preTranslation(), contentClip);
-
- ScrollOffset scrollOffset = frameView.scrollOffset();
- if (frameView.isScrollable() || !scrollOffset.isZero()) {
- TransformationMatrix frameScroll;
- frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
- updateFrameViewScrollTranslation(frameView, frameView.preTranslation(),
- frameScroll, FloatPoint3D());
-
- IntSize scrollClip = frameView.visibleContentSize();
- IntSize scrollBounds = frameView.contentsSize();
- bool userScrollableHorizontal =
- frameView.userInputScrollable(HorizontalScrollbar);
- bool userScrollableVertical =
- frameView.userInputScrollable(VerticalScrollbar);
- updateFrameViewScroll(frameView, context.current.scroll,
- frameView.scrollTranslation(), scrollClip,
- scrollBounds, userScrollableHorizontal,
- userScrollableVertical);
- } else {
- // Ensure pre-existing properties are cleared when there is no scrolling.
- frameView.setScrollTranslation(nullptr);
- frameView.setScroll(nullptr);
+#if DCHECK_IS_ON()
+ FindFrameViewPropertiesNeedingUpdateScope checkNeedsUpdateScope(&frameView);
+#endif
+
+ if (frameView.needsPaintPropertyUpdate()) {
+ TransformationMatrix frameTranslate;
+ frameTranslate.translate(frameView.x() + context.current.paintOffset.x(),
+ frameView.y() + context.current.paintOffset.y());
+ updateFrameViewPreTranslation(frameView, context.current.transform,
+ frameTranslate, FloatPoint3D());
+
+ FloatRoundedRect contentClip(
+ IntRect(IntPoint(), frameView.visibleContentSize()));
+ updateFrameViewContentClip(frameView, context.current.clip,
+ frameView.preTranslation(), contentClip);
+
+ ScrollOffset scrollOffset = frameView.scrollOffset();
+ if (frameView.isScrollable() || !scrollOffset.isZero()) {
+ TransformationMatrix frameScroll;
+ frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
+ updateFrameViewScrollTranslation(frameView, frameView.preTranslation(),
+ frameScroll, FloatPoint3D());
+
+ IntSize scrollClip = frameView.visibleContentSize();
+ IntSize scrollBounds = frameView.contentsSize();
+ bool userScrollableHorizontal =
+ frameView.userInputScrollable(HorizontalScrollbar);
+ bool userScrollableVertical =
+ frameView.userInputScrollable(VerticalScrollbar);
+ updateFrameViewScroll(frameView, context.current.scroll,
+ frameView.scrollTranslation(), scrollClip,
+ scrollBounds, userScrollableHorizontal,
+ userScrollableVertical);
+ } else {
+ // Ensure pre-existing properties are cleared when there is no scrolling.
+ frameView.setScrollTranslation(nullptr);
+ frameView.setScroll(nullptr);
+ }
}
// Initialize the context for current, absolute and fixed position cases.
@@ -210,18 +217,20 @@ void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(
LayoutPoint fractionalPaintOffset =
LayoutPoint(context.current.paintOffset - roundedPaintOffset);
- if (usesPaintOffsetTranslation) {
- object.getMutableForPainting()
- .ensurePaintProperties()
- .updatePaintOffsetTranslation(
- context.current.transform,
- TransformationMatrix().translate(roundedPaintOffset.x(),
- roundedPaintOffset.y()),
- FloatPoint3D(), context.current.shouldFlattenInheritedTransform,
- context.current.renderingContextID);
- } else {
- if (auto* properties = object.getMutableForPainting().paintProperties())
- properties->clearPaintOffsetTranslation();
+ if (object.needsPaintPropertyUpdate()) {
+ if (usesPaintOffsetTranslation) {
+ object.getMutableForPainting()
+ .ensurePaintProperties()
+ .updatePaintOffsetTranslation(
+ context.current.transform,
+ TransformationMatrix().translate(roundedPaintOffset.x(),
+ roundedPaintOffset.y()),
+ FloatPoint3D(), context.current.shouldFlattenInheritedTransform,
+ context.current.renderingContextID);
+ } else {
+ if (auto* properties = object.getMutableForPainting().paintProperties())
+ properties->clearPaintOffsetTranslation();
+ }
}
const auto* properties = object.paintProperties();
@@ -257,23 +266,25 @@ void PaintPropertyTreeBuilder::updateTransformForNonRootSVG(
DCHECK(object.isSVGForeignObject() ||
context.current.paintOffset == LayoutPoint());
- // TODO(pdr): Refactor this so all non-root SVG objects use the same
- // transform function.
- const AffineTransform& transform = object.isSVGForeignObject()
- ? object.localSVGTransform()
- : object.localToSVGParentTransform();
- // TODO(pdr): Check for the presence of a transform instead of the value.
- // Checking for an identity matrix will cause the property tree structure
- // to change during animations if the animation passes through the
- // identity matrix.
- if (!transform.isIdentity()) {
- // The origin is included in the local transform, so leave origin empty.
- object.getMutableForPainting().ensurePaintProperties().updateTransform(
- context.current.transform, TransformationMatrix(transform),
- FloatPoint3D());
- } else {
- if (auto* properties = object.getMutableForPainting().paintProperties())
- properties->clearTransform();
+ if (object.needsPaintPropertyUpdate()) {
+ // TODO(pdr): Refactor this so all non-root SVG objects use the same
+ // transform function.
+ const AffineTransform& transform = object.isSVGForeignObject()
+ ? object.localSVGTransform()
+ : object.localToSVGParentTransform();
+ // TODO(pdr): Check for the presence of a transform instead of the value.
+ // Checking for an identity matrix will cause the property tree structure
+ // to change during animations if the animation passes through the
+ // identity matrix.
+ if (!transform.isIdentity()) {
+ // The origin is included in the local transform, so leave origin empty.
+ object.getMutableForPainting().ensurePaintProperties().updateTransform(
+ context.current.transform, TransformationMatrix(transform),
+ FloatPoint3D());
+ } else {
+ if (auto* properties = object.getMutableForPainting().paintProperties())
+ properties->clearTransform();
+ }
}
if (object.paintProperties() && object.paintProperties()->transform()) {
@@ -291,28 +302,32 @@ void PaintPropertyTreeBuilder::updateTransform(
return;
}
- const ComputedStyle& style = object.styleRef();
- if (object.isBox() && (style.hasTransform() || style.preserves3D())) {
- TransformationMatrix matrix;
- style.applyTransform(matrix, toLayoutBox(object).size(),
- ComputedStyle::ExcludeTransformOrigin,
- ComputedStyle::IncludeMotionPath,
- ComputedStyle::IncludeIndependentTransformProperties);
-
- // TODO(trchen): transform-style should only be respected if a PaintLayer
- // is created.
- // If a node with transform-style: preserve-3d does not exist in an
- // existing rendering context, it establishes a new one.
- unsigned renderingContextID = context.current.renderingContextID;
- if (style.preserves3D() && !renderingContextID)
- renderingContextID = PtrHash<const LayoutObject>::hash(&object);
-
- object.getMutableForPainting().ensurePaintProperties().updateTransform(
- context.current.transform, matrix, transformOrigin(toLayoutBox(object)),
- context.current.shouldFlattenInheritedTransform, renderingContextID);
- } else {
- if (auto* properties = object.getMutableForPainting().paintProperties())
- properties->clearTransform();
+ if (object.needsPaintPropertyUpdate()) {
+ const ComputedStyle& style = object.styleRef();
+ if (object.isBox() && (style.hasTransform() || style.preserves3D())) {
+ TransformationMatrix matrix;
+ style.applyTransform(
+ matrix, toLayoutBox(object).size(),
+ ComputedStyle::ExcludeTransformOrigin,
+ ComputedStyle::IncludeMotionPath,
+ ComputedStyle::IncludeIndependentTransformProperties);
+
+ // TODO(trchen): transform-style should only be respected if a PaintLayer
+ // is created.
+ // If a node with transform-style: preserve-3d does not exist in an
+ // existing rendering context, it establishes a new one.
+ unsigned renderingContextID = context.current.renderingContextID;
+ if (style.preserves3D() && !renderingContextID)
+ renderingContextID = PtrHash<const LayoutObject>::hash(&object);
+
+ object.getMutableForPainting().ensurePaintProperties().updateTransform(
+ context.current.transform, matrix,
+ transformOrigin(toLayoutBox(object)),
+ context.current.shouldFlattenInheritedTransform, renderingContextID);
+ } else {
+ if (auto* properties = object.getMutableForPainting().paintProperties())
+ properties->clearTransform();
+ }
}
const auto* properties = object.paintProperties();
@@ -335,62 +350,66 @@ void PaintPropertyTreeBuilder::updateEffect(
const ComputedStyle& style = object.styleRef();
if (!style.isStackingContext()) {
- if (auto* properties = object.getMutableForPainting().paintProperties())
- properties->clearEffect();
+ if (object.needsPaintPropertyUpdate()) {
+ if (auto* properties = object.getMutableForPainting().paintProperties())
+ properties->clearEffect();
+ }
return;
}
// TODO(trchen): Can't omit effect node if we have 3D children.
// TODO(trchen): Can't omit effect node if we have blending children.
- bool effectNodeNeeded = false;
+ if (object.needsPaintPropertyUpdate()) {
+ bool effectNodeNeeded = false;
+
+ float opacity = style.opacity();
+ if (opacity != 1.0f)
+ effectNodeNeeded = true;
+
+ CompositorFilterOperations filter;
+ if (object.isSVG() && !object.isSVGRoot()) {
+ // TODO(trchen): SVG caches filters in SVGResources. Implement it.
+ } else if (PaintLayer* layer = toLayoutBoxModelObject(object).layer()) {
+ // TODO(trchen): Eliminate PaintLayer dependency.
+ filter = layer->createCompositorFilterOperationsForFilter(style);
+ }
- float opacity = style.opacity();
- if (opacity != 1.0f)
- effectNodeNeeded = true;
+ const ClipPaintPropertyNode* outputClip = ClipPaintPropertyNode::root();
+ // The CSS filter spec didn't specify how filters interact with overflow
+ // clips. The implementation here mimics the old Blink/WebKit behavior for
+ // backward compatibility.
+ // Basically the output of the filter will be affected by clips that applies
+ // to the current element. The descendants that paints into the input of the
+ // filter ignores any clips collected so far. For example:
+ // <div style="overflow:scroll">
+ // <div style="filter:blur(1px);">
+ // <div>A</div>
+ // <div style="position:absolute;">B</div>
+ // </div>
+ // </div>
+ // In this example "A" should be clipped if the filter was not present.
+ // With the filter, "A" will be rastered without clipping, but instead
+ // the blurred result will be clipped.
+ // On the other hand, "B" should not be clipped because the overflow clip is
+ // not in its containing block chain, but as the filter output will be
+ // clipped, so a blurred "B" may still be invisible.
+ if (!filter.isEmpty()) {
+ effectNodeNeeded = true;
+ outputClip = context.current.clip;
+
+ // TODO(trchen): A filter may contain spatial operations such that an
+ // output pixel may depend on an input pixel outside of the output clip.
+ // We should generate a special clip node to represent this expansion.
+ }
- CompositorFilterOperations filter;
- if (object.isSVG() && !object.isSVGRoot()) {
- // TODO(trchen): SVG caches filters in SVGResources. Implement it.
- } else if (PaintLayer* layer = toLayoutBoxModelObject(object).layer()) {
- // TODO(trchen): Eliminate PaintLayer dependency.
- filter = layer->createCompositorFilterOperationsForFilter(style);
- }
-
- const ClipPaintPropertyNode* outputClip = ClipPaintPropertyNode::root();
- // The CSS filter spec didn't specify how filters interact with overflow
- // clips. The implementation here mimics the old Blink/WebKit behavior for
- // backward compatibility.
- // Basically the output of the filter will be affected by clips that applies
- // to the current element. The descendants that paints into the input of the
- // filter ignores any clips collected so far. For example:
- // <div style="overflow:scroll">
- // <div style="filter:blur(1px);">
- // <div>A</div>
- // <div style="position:absolute;">B</div>
- // </div>
- // </div>
- // In this example "A" should be clipped if the filter was not present.
- // With the filter, "A" will be rastered without clipping, but instead
- // the blurred result will be clipped.
- // On the other hand, "B" should not be clipped because the overflow clip is
- // not in its containing block chain, but as the filter output will be
- // clipped, so a blurred "B" may still be invisible.
- if (!filter.isEmpty()) {
- effectNodeNeeded = true;
- outputClip = context.current.clip;
-
- // TODO(trchen): A filter may contain spatial operations such that an
- // output pixel may depend on an input pixel outside of the output clip.
- // We should generate a special clip node to represent this expansion.
- }
-
- if (effectNodeNeeded) {
- object.getMutableForPainting().ensurePaintProperties().updateEffect(
- context.currentEffect, context.current.transform, outputClip,
- std::move(filter), opacity);
- } else {
- if (auto* properties = object.getMutableForPainting().paintProperties())
- properties->clearEffect();
+ if (effectNodeNeeded) {
+ object.getMutableForPainting().ensurePaintProperties().updateEffect(
+ context.currentEffect, context.current.transform, outputClip,
+ std::move(filter), opacity);
+ } else {
+ if (auto* properties = object.getMutableForPainting().paintProperties())
+ properties->clearEffect();
+ }
}
const auto* properties = object.paintProperties();
@@ -407,20 +426,22 @@ void PaintPropertyTreeBuilder::updateEffect(
void PaintPropertyTreeBuilder::updateCssClip(
const LayoutObject& object,
PaintPropertyTreeBuilderContext& context) {
- if (object.hasClip()) {
- // Create clip node for descendants that are not fixed position.
- // We don't have to setup context.absolutePosition.clip here because this
- // object must be a container for absolute position descendants, and will
- // copy from in-flow context later at updateOutOfFlowContext() step.
- DCHECK(object.canContainAbsolutePositionObjects());
- LayoutRect clipRect =
- toLayoutBox(object).clipRect(context.current.paintOffset);
- object.getMutableForPainting().ensurePaintProperties().updateCssClip(
- context.current.clip, context.current.transform,
- FloatRoundedRect(FloatRect(clipRect)));
- } else {
- if (auto* properties = object.getMutableForPainting().paintProperties())
- properties->clearCssClip();
+ if (object.needsPaintPropertyUpdate()) {
+ if (object.hasClip()) {
+ // Create clip node for descendants that are not fixed position.
+ // We don't have to setup context.absolutePosition.clip here because this
+ // object must be a container for absolute position descendants, and will
+ // copy from in-flow context later at updateOutOfFlowContext() step.
+ DCHECK(object.canContainAbsolutePositionObjects());
+ LayoutRect clipRect =
+ toLayoutBox(object).clipRect(context.current.paintOffset);
+ object.getMutableForPainting().ensurePaintProperties().updateCssClip(
+ context.current.clip, context.current.transform,
+ FloatRoundedRect(FloatRect(clipRect)));
+ } else {
+ if (auto* properties = object.getMutableForPainting().paintProperties())
+ properties->clearCssClip();
+ }
}
const auto* properties = object.paintProperties();
@@ -431,6 +452,9 @@ void PaintPropertyTreeBuilder::updateCssClip(
void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(
const LayoutObject& object,
PaintPropertyTreeBuilderContext& context) {
+ if (!object.needsPaintPropertyUpdate())
+ return;
+
// Avoid adding an ObjectPaintProperties for non-boxes to save memory, since
// we don't need them at the moment.
if (!object.isBox() && !object.hasLayer()) {
@@ -454,6 +478,9 @@ void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(
void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(
const LayoutObject& object,
const PaintPropertyTreeBuilderContext& context) {
+ if (!object.needsPaintPropertyUpdate())
+ return;
+
bool needsScrollbarPaintOffset = false;
IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
if (roundedPaintOffset != IntPoint() && object.isBoxModelObject()) {
@@ -478,6 +505,10 @@ void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(
void PaintPropertyTreeBuilder::updateMainThreadScrollingReasons(
const LayoutObject& object,
PaintPropertyTreeBuilderContext& context) {
+ // TODO(pdr): Mark properties as needing an update for main thread scroll
+ // reasons and ensure reason changes are propagated to ancestors to account
+ // for the parent walk below. https://crbug.com/664672.
+
if (context.current.scroll &&
!object.document().settings()->threadedScrollingEnabled()) {
context.current.scroll->addMainThreadScrollingReasons(
@@ -502,46 +533,49 @@ void PaintPropertyTreeBuilder::updateOverflowClip(
PaintPropertyTreeBuilderContext& context) {
if (!object.isBox())
return;
- const LayoutBox& box = toLayoutBox(object);
- // The <input> elements can't have contents thus CSS overflow property
- // doesn't apply. However for layout purposes we do generate child layout
- // objects for them, e.g. button label. We should clip the overflow from
- // those children. This is called control clip and we technically treat them
- // like overflow clip.
- LayoutRect clipRect;
- if (box.hasControlClip()) {
- clipRect = box.controlClipRect(context.current.paintOffset);
- } else if (box.hasOverflowClip() || box.styleRef().containsPaint() ||
- (box.isSVGRoot() &&
- toLayoutSVGRoot(box).shouldApplyViewportClip())) {
- clipRect = LayoutRect(
- pixelSnappedIntRect(box.overflowClipRect(context.current.paintOffset)));
- } else {
- if (auto* properties = object.getMutableForPainting().paintProperties()) {
+
+ if (object.needsPaintPropertyUpdate()) {
+ const LayoutBox& box = toLayoutBox(object);
+ // The <input> elements can't have contents thus CSS overflow property
+ // doesn't apply. However for layout purposes we do generate child layout
+ // objects for them, e.g. button label. We should clip the overflow from
+ // those children. This is called control clip and we technically treat them
+ // like overflow clip.
+ LayoutRect clipRect;
+ if (box.hasControlClip()) {
+ clipRect = box.controlClipRect(context.current.paintOffset);
+ } else if (box.hasOverflowClip() || box.styleRef().containsPaint() ||
+ (box.isSVGRoot() &&
+ toLayoutSVGRoot(box).shouldApplyViewportClip())) {
+ clipRect = LayoutRect(pixelSnappedIntRect(
+ box.overflowClipRect(context.current.paintOffset)));
+ } else {
+ if (auto* properties = object.getMutableForPainting().paintProperties()) {
+ properties->clearInnerBorderRadiusClip();
+ properties->clearOverflowClip();
+ }
+ return;
+ }
+
+ const auto* currentClip = context.current.clip;
+ if (box.styleRef().hasBorderRadius()) {
+ auto innerBorder = box.styleRef().getRoundedInnerBorderFor(
+ LayoutRect(context.current.paintOffset, box.size()));
+ object.getMutableForPainting()
+ .ensurePaintProperties()
+ .updateInnerBorderRadiusClip(context.current.clip,
+ context.current.transform, innerBorder);
+ currentClip = object.paintProperties()->innerBorderRadiusClip();
+ } else if (auto* properties =
+ object.getMutableForPainting().paintProperties()) {
properties->clearInnerBorderRadiusClip();
- properties->clearOverflowClip();
}
- return;
- }
- const auto* currentClip = context.current.clip;
- if (box.styleRef().hasBorderRadius()) {
- auto innerBorder = box.styleRef().getRoundedInnerBorderFor(
- LayoutRect(context.current.paintOffset, box.size()));
- object.getMutableForPainting()
- .ensurePaintProperties()
- .updateInnerBorderRadiusClip(context.current.clip,
- context.current.transform, innerBorder);
- currentClip = object.paintProperties()->innerBorderRadiusClip();
- } else if (auto* properties =
- object.getMutableForPainting().paintProperties()) {
- properties->clearInnerBorderRadiusClip();
+ object.getMutableForPainting().ensurePaintProperties().updateOverflowClip(
+ currentClip, context.current.transform,
+ FloatRoundedRect(FloatRect(clipRect)));
}
- object.getMutableForPainting().ensurePaintProperties().updateOverflowClip(
- currentClip, context.current.transform,
- FloatRoundedRect(FloatRect(clipRect)));
-
const auto* properties = object.paintProperties();
if (properties && properties->overflowClip())
context.current.clip = properties->overflowClip();
@@ -558,22 +592,24 @@ static FloatPoint perspectiveOrigin(const LayoutBox& box) {
void PaintPropertyTreeBuilder::updatePerspective(
const LayoutObject& object,
PaintPropertyTreeBuilderContext& context) {
- const ComputedStyle& style = object.styleRef();
- if (object.isBox() && style.hasPerspective()) {
- // The perspective node must not flatten (else nothing will get
- // perspective), but it should still extend the rendering context as
- // most transform nodes do.
- TransformationMatrix matrix =
- TransformationMatrix().applyPerspective(style.perspective());
- FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) +
- toLayoutSize(context.current.paintOffset);
- object.getMutableForPainting().ensurePaintProperties().updatePerspective(
- context.current.transform, matrix, origin,
- context.current.shouldFlattenInheritedTransform,
- context.current.renderingContextID);
- } else {
- if (auto* properties = object.getMutableForPainting().paintProperties())
- properties->clearPerspective();
+ if (object.needsPaintPropertyUpdate()) {
+ const ComputedStyle& style = object.styleRef();
+ if (object.isBox() && style.hasPerspective()) {
+ // The perspective node must not flatten (else nothing will get
+ // perspective), but it should still extend the rendering context as
+ // most transform nodes do.
+ TransformationMatrix matrix =
+ TransformationMatrix().applyPerspective(style.perspective());
+ FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) +
+ toLayoutSize(context.current.paintOffset);
+ object.getMutableForPainting().ensurePaintProperties().updatePerspective(
+ context.current.transform, matrix, origin,
+ context.current.shouldFlattenInheritedTransform,
+ context.current.renderingContextID);
+ } else {
+ if (auto* properties = object.getMutableForPainting().paintProperties())
+ properties->clearPerspective();
+ }
}
const auto* properties = object.paintProperties();
@@ -589,17 +625,19 @@ void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(
if (!object.isSVGRoot())
return;
- AffineTransform transformToBorderBox =
- SVGRootPainter(toLayoutSVGRoot(object))
- .transformToPixelSnappedBorderBox(context.current.paintOffset);
- if (!transformToBorderBox.isIdentity()) {
- object.getMutableForPainting()
- .ensurePaintProperties()
- .updateSvgLocalToBorderBoxTransform(
- context.current.transform, transformToBorderBox, FloatPoint3D());
- } else {
- if (auto* properties = object.getMutableForPainting().paintProperties())
- properties->clearSvgLocalToBorderBoxTransform();
+ if (object.needsPaintPropertyUpdate()) {
+ AffineTransform transformToBorderBox =
+ SVGRootPainter(toLayoutSVGRoot(object))
+ .transformToPixelSnappedBorderBox(context.current.paintOffset);
+ if (!transformToBorderBox.isIdentity()) {
+ object.getMutableForPainting()
+ .ensurePaintProperties()
+ .updateSvgLocalToBorderBoxTransform(
+ context.current.transform, transformToBorderBox, FloatPoint3D());
+ } else {
+ if (auto* properties = object.getMutableForPainting().paintProperties())
+ properties->clearSvgLocalToBorderBoxTransform();
+ }
}
const auto* properties = object.paintProperties();
@@ -616,37 +654,39 @@ void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(
void PaintPropertyTreeBuilder::updateScrollAndScrollTranslation(
const LayoutObject& object,
PaintPropertyTreeBuilderContext& context) {
- if (object.hasOverflowClip()) {
- const LayoutBox& box = toLayoutBox(object);
- const PaintLayerScrollableArea* scrollableArea = box.getScrollableArea();
- IntSize scrollOffset = box.scrolledContentOffset();
- if (!scrollOffset.isZero() || scrollableArea->scrollsOverflow()) {
- TransformationMatrix matrix = TransformationMatrix().translate(
- -scrollOffset.width(), -scrollOffset.height());
- object.getMutableForPainting()
- .ensurePaintProperties()
- .updateScrollTranslation(
- context.current.transform, matrix, FloatPoint3D(),
- context.current.shouldFlattenInheritedTransform,
- context.current.renderingContextID);
-
- IntSize scrollClip = scrollableArea->visibleContentRect().size();
- IntSize scrollBounds = scrollableArea->contentsSize();
- bool userScrollableHorizontal =
- scrollableArea->userInputScrollable(HorizontalScrollbar);
- bool userScrollableVertical =
- scrollableArea->userInputScrollable(VerticalScrollbar);
- object.getMutableForPainting().ensurePaintProperties().updateScroll(
- context.current.scroll, object.paintProperties()->scrollTranslation(),
- scrollClip, scrollBounds, userScrollableHorizontal,
- userScrollableVertical);
- } else {
- // Ensure pre-existing properties are cleared when there is no
- // scrolling.
- auto* properties = object.getMutableForPainting().paintProperties();
- if (properties) {
- properties->clearScrollTranslation();
- properties->clearScroll();
+ if (object.needsPaintPropertyUpdate()) {
+ if (object.hasOverflowClip()) {
+ const LayoutBox& box = toLayoutBox(object);
+ const PaintLayerScrollableArea* scrollableArea = box.getScrollableArea();
+ IntSize scrollOffset = box.scrolledContentOffset();
+ if (!scrollOffset.isZero() || scrollableArea->scrollsOverflow()) {
+ TransformationMatrix matrix = TransformationMatrix().translate(
+ -scrollOffset.width(), -scrollOffset.height());
+ object.getMutableForPainting()
+ .ensurePaintProperties()
+ .updateScrollTranslation(
+ context.current.transform, matrix, FloatPoint3D(),
+ context.current.shouldFlattenInheritedTransform,
+ context.current.renderingContextID);
+
+ IntSize scrollClip = scrollableArea->visibleContentRect().size();
+ IntSize scrollBounds = scrollableArea->contentsSize();
+ bool userScrollableHorizontal =
+ scrollableArea->userInputScrollable(HorizontalScrollbar);
+ bool userScrollableVertical =
+ scrollableArea->userInputScrollable(VerticalScrollbar);
+ object.getMutableForPainting().ensurePaintProperties().updateScroll(
+ context.current.scroll,
+ object.paintProperties()->scrollTranslation(), scrollClip,
+ scrollBounds, userScrollableHorizontal, userScrollableVertical);
+ } else {
+ // Ensure pre-existing properties are cleared when there is no
+ // scrolling.
+ auto* properties = object.getMutableForPainting().paintProperties();
+ if (properties) {
+ properties->clearScrollTranslation();
+ properties->clearScroll();
+ }
}
}
}
@@ -696,12 +736,14 @@ void PaintPropertyTreeBuilder::updateOutOfFlowContext(
if (context.fixedPosition.clip == cssClip->parent()) {
context.fixedPosition.clip = cssClip;
} else {
- object.getMutableForPainting()
- .ensurePaintProperties()
- .updateCssClipFixedPosition(context.fixedPosition.clip,
- const_cast<TransformPaintPropertyNode*>(
- cssClip->localTransformSpace()),
- cssClip->clipRect());
+ if (object.needsPaintPropertyUpdate()) {
+ object.getMutableForPainting()
+ .ensurePaintProperties()
+ .updateCssClipFixedPosition(context.fixedPosition.clip,
+ const_cast<TransformPaintPropertyNode*>(
+ cssClip->localTransformSpace()),
+ cssClip->clipRect());
+ }
const auto* properties = object.paintProperties();
if (properties && properties->cssClipFixedPosition())
context.fixedPosition.clip = properties->cssClipFixedPosition();
@@ -709,8 +751,10 @@ void PaintPropertyTreeBuilder::updateOutOfFlowContext(
}
}
- if (auto* properties = object.getMutableForPainting().paintProperties())
- properties->clearCssClipFixedPosition();
+ if (object.needsPaintPropertyUpdate()) {
+ if (auto* properties = object.getMutableForPainting().paintProperties())
+ properties->clearCssClipFixedPosition();
+ }
}
// Override ContainingBlockContext based on the properties of a containing block
@@ -835,12 +879,16 @@ static void deriveBorderBoxFromContainerContext(
}
}
-void PaintPropertyTreeBuilder::updatePropertiesAndContextForSelf(
+void PaintPropertyTreeBuilder::updatePropertiesForSelf(
const LayoutObject& object,
PaintPropertyTreeBuilderContext& context) {
if (!object.isBoxModelObject() && !object.isSVG())
return;
+#if DCHECK_IS_ON()
+ FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object);
+#endif
+
deriveBorderBoxFromContainerContext(object, context);
updatePaintOffsetTranslation(object, context);
@@ -852,12 +900,16 @@ void PaintPropertyTreeBuilder::updatePropertiesAndContextForSelf(
updateMainThreadScrollingReasons(object, context);
}
-void PaintPropertyTreeBuilder::updatePropertiesAndContextForChildren(
+void PaintPropertyTreeBuilder::updatePropertiesForChildren(
const LayoutObject& object,
PaintPropertyTreeBuilderContext& context) {
if (!object.isBoxModelObject() && !object.isSVG())
return;
+#if DCHECK_IS_ON()
+ FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object);
+#endif
+
updateOverflowClip(object, context);
updatePerspective(object, context);
updateSvgLocalToBorderBoxTransform(object, context);

Powered by Google App Engine
This is Rietveld 408576698