| Index: third_party/WebKit/Source/core/layout/LayoutObject.cpp
|
| diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
|
| index 8d60773a2c63bd627934d9dc81a5ca65c9aab528..b81e11e8b07566ad3a39aa191c3938e3253a106e 100644
|
| --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
|
| +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
|
| @@ -69,6 +69,7 @@
|
| #include "core/layout/ng/layout_ng_block_flow.h"
|
| #include "core/page/AutoscrollController.h"
|
| #include "core/page/Page.h"
|
| +#include "core/paint/ObjectPaintInvalidator.h"
|
| #include "core/paint/ObjectPaintProperties.h"
|
| #include "core/paint/PaintLayer.h"
|
| #include "core/style/ContentData.h"
|
| @@ -133,9 +134,6 @@ static_assert(sizeof(LayoutObject) == sizeof(SameSizeAsLayoutObject), "LayoutObj
|
|
|
| bool LayoutObject::s_affectsParentBlock = false;
|
|
|
| -typedef HashMap<const LayoutObject*, LayoutRect> SelectionPaintInvalidationMap;
|
| -static SelectionPaintInvalidationMap* selectionPaintInvalidationMap = nullptr;
|
| -
|
| // The pointer to paint properties is implemented as a global hash map temporarily,
|
| // to avoid memory regression during the transition towards SPv2.
|
| typedef HashMap<const LayoutObject*, std::unique_ptr<ObjectPaintProperties>> ObjectPaintPropertiesMap;
|
| @@ -1108,15 +1106,6 @@ void addJsonObjectForRect(TracedValue* value, const char* name, const T& rect)
|
| value->endDictionary();
|
| }
|
|
|
| -template <typename T>
|
| -void addJsonObjectForPoint(TracedValue* value, const char* name, const T& point)
|
| -{
|
| - value->beginDictionary(name);
|
| - value->setDouble("x", point.x());
|
| - value->setDouble("y", point.y());
|
| - value->endDictionary();
|
| -}
|
| -
|
| static std::unique_ptr<TracedValue> jsonObjectForPaintInvalidationInfo(const LayoutRect& rect, const String& invalidationReason)
|
| {
|
| std::unique_ptr<TracedValue> value = TracedValue::create();
|
| @@ -1207,12 +1196,6 @@ void LayoutObject::invalidateDisplayItemClients(PaintInvalidationReason reason)
|
| invalidateDisplayItemClient(*this, reason);
|
| }
|
|
|
| -void LayoutObject::invalidateDisplayItemClientsWithPaintInvalidationState(const PaintInvalidationState& paintInvalidationState, PaintInvalidationReason reason) const
|
| -{
|
| - paintInvalidationState.paintingLayer().setNeedsRepaint();
|
| - invalidateDisplayItemClients(reason);
|
| -}
|
| -
|
| bool LayoutObject::compositedScrollsWithRespectTo(const LayoutBoxModelObject& paintInvalidationContainer) const
|
| {
|
| return paintInvalidationContainer.usesCompositedScrolling() && this != &paintInvalidationContainer;
|
| @@ -1253,7 +1236,7 @@ void LayoutObject::invalidatePaintRectangle(const LayoutRect& dirtyRect) const
|
|
|
| void LayoutObject::invalidateTreeIfNeeded(const PaintInvalidationState& paintInvalidationState)
|
| {
|
| - ASSERT(!needsLayout());
|
| + ensureIsReadyForPaintInvalidation();
|
|
|
| // If we didn't need paint invalidation then our children don't need as well.
|
| // Skip walking down the tree as everything should be fine below us.
|
| @@ -1266,7 +1249,7 @@ void LayoutObject::invalidateTreeIfNeeded(const PaintInvalidationState& paintInv
|
| newPaintInvalidationState.setForceSubtreeInvalidationCheckingWithinContainer();
|
|
|
| PaintInvalidationReason reason = invalidatePaintIfNeeded(newPaintInvalidationState);
|
| - clearPaintInvalidationFlags(newPaintInvalidationState);
|
| + clearPaintInvalidationFlags();
|
|
|
| newPaintInvalidationState.updateForChildren(reason);
|
| invalidatePaintOfSubtreesIfNeeded(newPaintInvalidationState);
|
| @@ -1283,16 +1266,6 @@ void LayoutObject::invalidatePaintOfSubtreesIfNeeded(const PaintInvalidationStat
|
| }
|
| }
|
|
|
| -static std::unique_ptr<TracedValue> jsonObjectForOldAndNewRects(const LayoutRect& oldRect, const LayoutPoint& oldLocation, const LayoutRect& newRect, const LayoutPoint& newLocation)
|
| -{
|
| - std::unique_ptr<TracedValue> value = TracedValue::create();
|
| - addJsonObjectForRect(value.get(), "oldRect", oldRect);
|
| - addJsonObjectForPoint(value.get(), "oldLocation", oldLocation);
|
| - addJsonObjectForRect(value.get(), "newRect", newRect);
|
| - addJsonObjectForPoint(value.get(), "newLocation", newLocation);
|
| - return value;
|
| -}
|
| -
|
| LayoutRect LayoutObject::selectionRectInViewCoordinates() const
|
| {
|
| LayoutRect selectionRect = localSelectionRect();
|
| @@ -1301,54 +1274,9 @@ LayoutRect LayoutObject::selectionRectInViewCoordinates() const
|
| return selectionRect;
|
| }
|
|
|
| -LayoutRect LayoutObject::previousSelectionRectForPaintInvalidation() const
|
| -{
|
| - if (!selectionPaintInvalidationMap)
|
| - return LayoutRect();
|
| -
|
| - return selectionPaintInvalidationMap->get(this);
|
| -}
|
| -
|
| -void LayoutObject::setPreviousSelectionRectForPaintInvalidation(const LayoutRect& selectionRect)
|
| -{
|
| - if (!selectionPaintInvalidationMap) {
|
| - if (selectionRect.isEmpty())
|
| - return;
|
| - selectionPaintInvalidationMap = new SelectionPaintInvalidationMap();
|
| - }
|
| -
|
| - if (selectionRect.isEmpty())
|
| - selectionPaintInvalidationMap->remove(this);
|
| - else
|
| - selectionPaintInvalidationMap->set(this, selectionRect);
|
| -}
|
| -
|
| -inline void LayoutObject::invalidateSelectionIfNeeded(const LayoutBoxModelObject& paintInvalidationContainer, const PaintInvalidationState& paintInvalidationState, PaintInvalidationReason invalidationReason)
|
| -{
|
| - // Update selection rect when we are doing full invalidation (in case that the object is moved, composite status changed, etc.)
|
| - // or shouldInvalidationSelection is set (in case that the selection itself changed).
|
| - bool fullInvalidation = isFullPaintInvalidationReason(invalidationReason);
|
| - if (!fullInvalidation && !shouldInvalidateSelection())
|
| - return;
|
| -
|
| - LayoutRect oldSelectionRect = previousSelectionRectForPaintInvalidation();
|
| - LayoutRect newSelectionRect = localSelectionRect();
|
| - if (!newSelectionRect.isEmpty())
|
| - paintInvalidationState.mapLocalRectToPaintInvalidationBacking(newSelectionRect);
|
| -
|
| - newSelectionRect.move(scrollAdjustmentForPaintInvalidation(paintInvalidationContainer));
|
| -
|
| - setPreviousSelectionRectForPaintInvalidation(newSelectionRect);
|
| -
|
| - if (!fullInvalidation) {
|
| - fullyInvalidatePaint(paintInvalidationContainer, PaintInvalidationSelection, oldSelectionRect, newSelectionRect);
|
| - invalidateDisplayItemClientsWithPaintInvalidationState(paintInvalidationState, PaintInvalidationSelection);
|
| - }
|
| -}
|
| -
|
| PaintInvalidationReason LayoutObject::invalidatePaintIfNeeded(const PaintInvalidationState& paintInvalidationState)
|
| {
|
| - ASSERT(&paintInvalidationState.currentObject() == this);
|
| + DCHECK(&paintInvalidationState.currentObject() == this);
|
|
|
| if (styleRef().hasOutline()) {
|
| PaintLayer& layer = paintInvalidationState.paintingLayer();
|
| @@ -1360,107 +1288,34 @@ PaintInvalidationReason LayoutObject::invalidatePaintIfNeeded(const PaintInvalid
|
| if (v->document().printing())
|
| return PaintInvalidationNone; // Don't invalidate paints if we're printing.
|
|
|
| + PaintInvalidatorContextAdapter context(paintInvalidationState);
|
| +
|
| const LayoutBoxModelObject& paintInvalidationContainer = paintInvalidationState.paintInvalidationContainer();
|
| - ASSERT(paintInvalidationContainer == containerForPaintInvalidation());
|
| + DCHECK(paintInvalidationContainer == containerForPaintInvalidation());
|
|
|
| - const LayoutRect oldBounds = previousPaintInvalidationRect();
|
| - const LayoutPoint oldLocation = RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() ? LayoutPoint() : previousPositionFromPaintInvalidationBacking();
|
| - LayoutRect newBounds = paintInvalidationState.computePaintInvalidationRectInBacking();
|
| - LayoutPoint newLocation = RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() ? LayoutPoint() : paintInvalidationState.computePositionFromPaintInvalidationBacking();
|
| + context.oldBounds = previousPaintInvalidationRect();
|
| + context.oldLocation = previousPositionFromPaintInvalidationBacking();
|
| + context.newBounds = paintInvalidationState.computePaintInvalidationRectInBacking();
|
| + context.newLocation = paintInvalidationState.computePositionFromPaintInvalidationBacking();
|
|
|
| IntSize adjustment = scrollAdjustmentForPaintInvalidation(paintInvalidationContainer);
|
| - newLocation.move(adjustment);
|
| - newBounds.move(adjustment);
|
| + context.newLocation.move(adjustment);
|
| + context.newBounds.move(adjustment);
|
|
|
| - setPreviousPaintInvalidationRect(newBounds);
|
| - if (!RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled())
|
| - setPreviousPositionFromPaintInvalidationBacking(newLocation);
|
| + setPreviousPaintInvalidationRect(context.newBounds);
|
| + setPreviousPositionFromPaintInvalidationBacking(context.newLocation);
|
|
|
| if (!shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState() && paintInvalidationState.forcedSubtreeInvalidationRectUpdateWithinContainerOnly()) {
|
| // We are done updating the paint invalidation rect. No other paint invalidation work to do for this object.
|
| return PaintInvalidationNone;
|
| }
|
|
|
| - PaintInvalidationReason invalidationReason = getPaintInvalidationReason(paintInvalidationState, oldBounds, oldLocation, newBounds, newLocation);
|
| -
|
| - // We need to invalidate the selection before checking for whether we are doing a full invalidation.
|
| - // This is because we need to update the old rect regardless.
|
| - invalidateSelectionIfNeeded(paintInvalidationContainer, paintInvalidationState, invalidationReason);
|
| -
|
| - TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "LayoutObject::invalidatePaintIfNeeded()",
|
| - "object", this->debugName().ascii(),
|
| - "info", jsonObjectForOldAndNewRects(oldBounds, oldLocation, newBounds, newLocation));
|
| -
|
| - bool backgroundObscured = backgroundIsKnownToBeObscured();
|
| - if (!isFullPaintInvalidationReason(invalidationReason) && backgroundObscured != m_bitfields.previousBackgroundObscured())
|
| - invalidationReason = PaintInvalidationBackgroundObscurationChange;
|
| - m_bitfields.setPreviousBackgroundObscured(backgroundObscured);
|
| -
|
| - if (invalidationReason == PaintInvalidationNone || invalidationReason == PaintInvalidationDelayedFull) {
|
| - // TODO(trchen): Currently we don't keep track of paint offset of layout objects.
|
| - // There are corner cases that the display items need to be invalidated for paint offset
|
| - // mutation, but incurs no pixel difference (i.e. bounds stay the same) so no rect-based
|
| - // invalidation is issued. See crbug.com/508383 and crbug.com/515977.
|
| - // This is a workaround to force display items to update paint offset.
|
| - if (!RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() && paintInvalidationState.forcedSubtreeInvalidationCheckingWithinContainer())
|
| - invalidateDisplayItemClientsWithPaintInvalidationState(paintInvalidationState, PaintInvalidationLocationChange);
|
| -
|
| - return invalidationReason;
|
| - }
|
| -
|
| - if (invalidationReason == PaintInvalidationIncremental)
|
| - incrementallyInvalidatePaint(paintInvalidationContainer, oldBounds, newBounds, newLocation);
|
| - else
|
| - fullyInvalidatePaint(paintInvalidationContainer, invalidationReason, oldBounds, newBounds);
|
| -
|
| - invalidateDisplayItemClientsWithPaintInvalidationState(paintInvalidationState, invalidationReason);
|
| - return invalidationReason;
|
| + return invalidatePaintIfNeeded(context);
|
| }
|
|
|
| -PaintInvalidationReason LayoutObject::getPaintInvalidationReason(const PaintInvalidationState& paintInvalidationState,
|
| - const LayoutRect& oldBounds, const LayoutPoint& oldPositionFromPaintInvalidationBacking,
|
| - const LayoutRect& newBounds, const LayoutPoint& newPositionFromPaintInvalidationBacking) const
|
| +PaintInvalidationReason LayoutObject::invalidatePaintIfNeeded(const PaintInvalidatorContext& context) const
|
| {
|
| - if (paintInvalidationState.forcedSubtreeFullInvalidationWithinContainer())
|
| - return PaintInvalidationSubtree;
|
| -
|
| - if (shouldDoFullPaintInvalidation())
|
| - return m_bitfields.fullPaintInvalidationReason();
|
| -
|
| - if (paintedOutputOfObjectHasNoEffect())
|
| - return PaintInvalidationNone;
|
| -
|
| - // The outline may change shape because of position change of descendants. For simplicity,
|
| - // just force full paint invalidation if this object is marked for checking paint invalidation
|
| - // for any reason.
|
| - if (styleRef().hasOutline())
|
| - return PaintInvalidationOutline;
|
| -
|
| - bool locationChanged = newPositionFromPaintInvalidationBacking != oldPositionFromPaintInvalidationBacking;
|
| -
|
| - // If the bounds are the same then we know that none of the statements below
|
| - // can match, so we can early out.
|
| - if (oldBounds == newBounds)
|
| - return locationChanged && !oldBounds.isEmpty() ? PaintInvalidationLocationChange : PaintInvalidationNone;
|
| -
|
| - // If we shifted, we don't know the exact reason so we are conservative and trigger a full invalidation. Shifting could
|
| - // be caused by some layout property (left / top) or some in-flow layoutObject inserted / removed before us in the tree.
|
| - if (newBounds.location() != oldBounds.location())
|
| - return PaintInvalidationBoundsChange;
|
| -
|
| - // If the size is zero on one of our bounds then we know we're going to have
|
| - // to do a full invalidation of either old bounds or new bounds. If we fall
|
| - // into the incremental invalidation we'll issue two invalidations instead
|
| - // of one.
|
| - if (oldBounds.isEmpty())
|
| - return PaintInvalidationBecameVisible;
|
| - if (newBounds.isEmpty())
|
| - return PaintInvalidationBecameInvisible;
|
| -
|
| - if (locationChanged)
|
| - return PaintInvalidationLocationChange;
|
| -
|
| - return PaintInvalidationIncremental;
|
| + return ObjectPaintInvalidator(*this, context).invalidatePaintIfNeeded();
|
| }
|
|
|
| void LayoutObject::adjustInvalidationRectForCompositedScrolling(LayoutRect& rect, const LayoutBoxModelObject& paintInvalidationContainer) const
|
| @@ -1492,44 +1347,6 @@ void LayoutObject::clearPreviousPaintInvalidationRects()
|
| setShouldDoFullPaintInvalidation();
|
| }
|
|
|
| -void LayoutObject::incrementallyInvalidatePaint(const LayoutBoxModelObject& paintInvalidationContainer, const LayoutRect& oldBounds, const LayoutRect& newBounds, const LayoutPoint& positionFromPaintInvalidationBacking)
|
| -{
|
| - ASSERT(oldBounds.location() == newBounds.location());
|
| -
|
| - LayoutUnit deltaRight = newBounds.maxX() - oldBounds.maxX();
|
| - if (deltaRight > 0) {
|
| - LayoutRect invalidationRect(oldBounds.maxX(), newBounds.y(), deltaRight, newBounds.height());
|
| - invalidatePaintUsingContainer(paintInvalidationContainer, invalidationRect, PaintInvalidationIncremental);
|
| - } else if (deltaRight < 0) {
|
| - LayoutRect invalidationRect(newBounds.maxX(), oldBounds.y(), -deltaRight, oldBounds.height());
|
| - invalidatePaintUsingContainer(paintInvalidationContainer, invalidationRect, PaintInvalidationIncremental);
|
| - }
|
| -
|
| - LayoutUnit deltaBottom = newBounds.maxY() - oldBounds.maxY();
|
| - if (deltaBottom > 0) {
|
| - LayoutRect invalidationRect(newBounds.x(), oldBounds.maxY(), newBounds.width(), deltaBottom);
|
| - invalidatePaintUsingContainer(paintInvalidationContainer, invalidationRect, PaintInvalidationIncremental);
|
| - } else if (deltaBottom < 0) {
|
| - LayoutRect invalidationRect(oldBounds.x(), newBounds.maxY(), oldBounds.width(), -deltaBottom);
|
| - invalidatePaintUsingContainer(paintInvalidationContainer, invalidationRect, PaintInvalidationIncremental);
|
| - }
|
| -}
|
| -
|
| -void LayoutObject::fullyInvalidatePaint(const LayoutBoxModelObject& paintInvalidationContainer, PaintInvalidationReason invalidationReason, const LayoutRect& oldBounds, const LayoutRect& newBounds)
|
| -{
|
| - // The following logic avoids invalidating twice if one set of bounds contains the other.
|
| - if (!newBounds.contains(oldBounds)) {
|
| - LayoutRect invalidationRect = oldBounds;
|
| - invalidatePaintUsingContainer(paintInvalidationContainer, invalidationRect, invalidationReason);
|
| -
|
| - if (oldBounds.contains(newBounds))
|
| - return;
|
| - }
|
| -
|
| - LayoutRect invalidationRect = newBounds;
|
| - invalidatePaintUsingContainer(paintInvalidationContainer, invalidationRect, invalidationReason);
|
| -}
|
| -
|
| LayoutRect LayoutObject::absoluteClippedOverflowRect() const
|
| {
|
| LayoutRect rect = localOverflowRectForPaintInvalidation();
|
| @@ -2615,8 +2432,7 @@ void LayoutObject::willBeDestroyed()
|
|
|
| setAncestorLineBoxDirty(false);
|
|
|
| - if (selectionPaintInvalidationMap)
|
| - selectionPaintInvalidationMap->remove(this);
|
| + ObjectPaintInvalidator::objectWillBeDestroyed(*this);
|
|
|
| if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
|
| objectPaintPropertiesMap().remove(this);
|
| @@ -3437,7 +3253,7 @@ void LayoutObject::setMayNeedPaintInvalidationAnimatgedBackgroundImage()
|
| setMayNeedPaintInvalidation();
|
| }
|
|
|
| -void LayoutObject::clearPaintInvalidationFlags(const PaintInvalidationState& paintInvalidationState)
|
| +void LayoutObject::clearPaintInvalidationFlags()
|
| {
|
| // paintInvalidationStateIsDirty should be kept in sync with the
|
| // booleans that are cleared below.
|
|
|