Diff
Modified: trunk/Source/WebCore/ChangeLog (220478 => 220479)
--- trunk/Source/WebCore/ChangeLog 2017-08-09 21:02:23 UTC (rev 220478)
+++ trunk/Source/WebCore/ChangeLog 2017-08-09 21:03:03 UTC (rev 220479)
@@ -1,3 +1,41 @@
+2017-08-09 Dave Hyatt <hy...@apple.com>
+
+ [Repaint from Layout Removal] Move layer repaint rects into a map
+ https://bugs.webkit.org/show_bug.cgi?id=175393
+
+ Reviewed by Zalan Bujtas.
+
+ Move the two repaint rects held by RenderLayer into a RenderLayerModelObject -> RepaintLayoutRects hash map.
+ RepaintLayoutRects is a new struct that holds both rects.
+
+ Eventually more objects than just self painting layers will be caching repaint rects, so this takes a first
+ step towards having a common cache for these repaint rects. In addition this change saves memory, since
+ layers that aren't self-painting no longer have empty repaint rects taking up space in RenderLayer.
+
+ * rendering/RenderBlockLineLayout.cpp:
+ (WebCore::RenderBlockFlow::layoutRunsAndFloats):
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::RenderLayer):
+ (WebCore::RenderLayer::updateLayerPositions):
+ (WebCore::RenderLayer::repaintRectIncludingNonCompositingDescendants):
+ (WebCore::RenderLayer::computeRepaintRects):
+ (WebCore::RenderLayer::clearRepaintRects):
+ (WebCore::RenderLayer::updateLayerPositionsAfterScroll):
+ (WebCore::RenderLayer::scrollTo):
+ * rendering/RenderLayer.h:
+ * rendering/RenderLayerModelObject.cpp:
+ (WebCore::RepaintLayoutRects::RepaintLayoutRects):
+ (WebCore::RenderLayerModelObject::willBeDestroyed):
+ (WebCore::RenderLayerModelObject::destroyLayer):
+ (WebCore::RenderLayerModelObject::styleDidChange):
+ (WebCore::RenderLayerModelObject::hasRepaintLayoutRects):
+ (WebCore::RenderLayerModelObject::setRepaintLayoutRects):
+ (WebCore::RenderLayerModelObject::clearRepaintLayoutRects):
+ (WebCore::RenderLayerModelObject::repaintLayoutRects):
+ (WebCore::RenderLayerModelObject::computeRepaintLayoutRects):
+ * rendering/RenderLayerModelObject.h:
+ (WebCore::RepaintLayoutRects::RepaintLayoutRects):
+
2017-08-09 Sam Weinig <s...@webkit.org>
WTF::Function does not allow for reference / non-default constructible return types
Modified: trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp (220478 => 220479)
--- trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp 2017-08-09 21:02:23 UTC (rev 220478)
+++ trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp 2017-08-09 21:03:03 UTC (rev 220479)
@@ -1281,12 +1281,12 @@
// determineStartPosition first will break fast/repaint/line-flow-with-floats-9.html.
if (layoutState.isFullLayout() && hasInlineChild && !selfNeedsLayout()) {
setNeedsLayout(MarkOnlyThis); // Mark as needing a full layout to force us to repaint.
- if (!view().doingFullRepaint() && hasSelfPaintingLayer() && layer()->hasComputedRepaintRect()) {
+ if (!view().doingFullRepaint() && hasSelfPaintingLayer() && hasRepaintLayoutRects()) {
// Because we waited until we were already inside layout to discover
// that the block really needed a full layout, we missed our chance to repaint the layer
// before layout started. Luckily the layer has cached the repaint rect for its original
// position and size, and so we can use that to make a repaint happen now.
- repaintUsingContainer(containerForRepaint(), layer()->repaintRect());
+ repaintUsingContainer(containerForRepaint(), repaintLayoutRects().m_repaintRect);
}
}
Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (220478 => 220479)
--- trunk/Source/WebCore/rendering/RenderLayer.cpp 2017-08-09 21:02:23 UTC (rev 220478)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp 2017-08-09 21:03:03 UTC (rev 220479)
@@ -310,7 +310,6 @@
, m_layerListMutationAllowed(true)
#endif
, m_hasFilterInfo(false)
- , m_hasComputedRepaintRect(false)
#if ENABLE(CSS_COMPOSITING)
, m_blendMode(BlendModeNormal)
, m_hasNotIsolatedCompositedBlendingDescendants(false)
@@ -516,23 +515,29 @@
ASSERT(!renderer().view().layoutStateEnabled());
RenderLayerModelObject* repaintContainer = renderer().containerForRepaint();
- LayoutRect oldRepaintRect = m_repaintRect;
- LayoutRect oldOutlineBox = m_outlineBox;
+
+ auto hadRepaintLayoutRects = renderer().hasRepaintLayoutRects();
+ RepaintLayoutRects oldRects = hadRepaintLayoutRects ? renderer().repaintLayoutRects() : RepaintLayoutRects();
computeRepaintRects(repaintContainer, geometryMap);
-
+
+ auto hasRepaintLayoutRects = renderer().hasRepaintLayoutRects();
+ RepaintLayoutRects newRects = hasRepaintLayoutRects ? renderer().repaintLayoutRects() : RepaintLayoutRects();
// FIXME: Should ASSERT that value calculated for m_outlineBox using the cached offset is the same
// as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048
- if ((flags & CheckForRepaint) && m_hasComputedRepaintRect) {
+ if ((flags & CheckForRepaint) && hasRepaintLayoutRects) {
if (!renderer().view().printing()) {
bool didRepaint = false;
if (m_repaintStatus & NeedsFullRepaint) {
- renderer().repaintUsingContainer(repaintContainer, oldRepaintRect);
- if (m_repaintRect != oldRepaintRect) {
- renderer().repaintUsingContainer(repaintContainer, m_repaintRect);
+ if (hadRepaintLayoutRects)
+ renderer().repaintUsingContainer(repaintContainer, oldRects.m_repaintRect);
+ if (!hadRepaintLayoutRects || newRects.m_repaintRect != oldRects.m_repaintRect) {
+ renderer().repaintUsingContainer(repaintContainer, newRects.m_repaintRect);
didRepaint = true;
}
} else if (shouldRepaintAfterLayout()) {
- renderer().repaintAfterLayoutIfNeeded(repaintContainer, oldRepaintRect, oldOutlineBox, &m_repaintRect, &m_outlineBox);
+ // FIXME: We will convert this to just take the old and new RepaintLayoutRects once
+ // we change other callers to use RepaintLayoutRects.
+ renderer().repaintAfterLayoutIfNeeded(repaintContainer, oldRects.m_repaintRect, oldRects.m_outlineBox, &newRects.m_repaintRect, &newRects.m_outlineBox);
didRepaint = true;
}
@@ -601,7 +606,7 @@
LayoutRect RenderLayer::repaintRectIncludingNonCompositingDescendants() const
{
- LayoutRect repaintRect = m_repaintRect;
+ LayoutRect repaintRect = renderer().repaintLayoutRects().m_repaintRect;
for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
// Don't include repaint rects for composited child layers; they will paint themselves and have a different origin.
if (child->isComposited())
@@ -797,18 +802,9 @@
void RenderLayer::computeRepaintRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap)
{
ASSERT(!m_visibleContentStatusDirty);
-
- if (!isSelfPaintingLayer()) {
- clearRepaintRects();
- return;
- }
-
- m_hasComputedRepaintRect = true;
- m_repaintRect = renderer().clippedOverflowRectForRepaint(repaintContainer);
- m_outlineBox = renderer().outlineBoundsForRepaint(repaintContainer, geometryMap);
+ renderer().computeRepaintLayoutRects(repaintContainer, geometryMap);
}
-
void RenderLayer::computeRepaintRectsIncludingDescendants()
{
// FIXME: computeRepaintRects() has to walk up the parent chain for every layer to compute the rects.
@@ -824,9 +820,7 @@
{
ASSERT(!m_visibleContentStatusDirty);
- m_hasComputedRepaintRect = false;
- m_repaintRect = LayoutRect();
- m_outlineBox = LayoutRect();
+ renderer().clearRepaintLayoutRects();
}
void RenderLayer::updateLayerPositionsAfterDocumentScroll()
@@ -889,8 +883,8 @@
computeRepaintRects(renderer().containerForRepaint(), geometryMap);
} else {
// Check that our cached rects are correct.
- ASSERT(!m_hasComputedRepaintRect || (m_repaintRect == renderer().clippedOverflowRectForRepaint(renderer().containerForRepaint())));
- ASSERT(!m_hasComputedRepaintRect || m_outlineBox == renderer().outlineBoundsForRepaint(renderer().containerForRepaint()));
+ ASSERT(!renderer().hasRepaintLayoutRects() || renderer().repaintLayoutRects().m_repaintRect == renderer().clippedOverflowRectForRepaint(renderer().containerForRepaint()));
+ ASSERT(!renderer().hasRepaintLayoutRects() || renderer().repaintLayoutRects().m_outlineBox == renderer().outlineBoundsForRepaint(renderer().containerForRepaint()));
}
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
@@ -2440,7 +2434,7 @@
// The caret rect needs to be invalidated after scrolling
frame.selection().setCaretRectNeedsUpdate();
- LayoutRect rectForRepaint = m_hasComputedRepaintRect ? m_repaintRect : renderer().clippedOverflowRectForRepaint(repaintContainer);
+ LayoutRect rectForRepaint = renderer().hasRepaintLayoutRects() ? renderer().repaintLayoutRects().m_repaintRect : renderer().clippedOverflowRectForRepaint(repaintContainer);
FloatQuad quadForFakeMouseMoveEvent = FloatQuad(rectForRepaint);
if (repaintContainer)
Modified: trunk/Source/WebCore/rendering/RenderLayer.h (220478 => 220479)
--- trunk/Source/WebCore/rendering/RenderLayer.h 2017-08-09 21:02:23 UTC (rev 220478)
+++ trunk/Source/WebCore/rendering/RenderLayer.h 2017-08-09 21:03:03 UTC (rev 220479)
@@ -581,8 +581,7 @@
LayoutRect calculateLayerBounds(const RenderLayer* ancestorLayer, const LayoutSize& offsetFromRoot, CalculateLayerBoundsFlags = DefaultCalculateLayerBoundsFlags) const;
// Return a cached repaint rect, computed relative to the layer renderer's containerForRepaint.
- bool hasComputedRepaintRect() const { return m_hasComputedRepaintRect; }
- LayoutRect repaintRect() const { ASSERT(hasComputedRepaintRect()); return m_repaintRect; }
+ bool hasComputedRepaintRects() const { return renderer().hasRepaintLayoutRects(); }
LayoutRect repaintRectIncludingNonCompositingDescendants() const;
void setRepaintStatus(RepaintStatus status) { m_repaintStatus = status; }
@@ -1115,8 +1114,6 @@
#endif
bool m_hasFilterInfo : 1;
-
- bool m_hasComputedRepaintRect : 1;
#if ENABLE(CSS_COMPOSITING)
unsigned m_blendMode : 5;
@@ -1133,9 +1130,6 @@
RenderLayer* m_first;
RenderLayer* m_last;
- LayoutRect m_repaintRect; // Cached repaint rects. Used by layout.
- LayoutRect m_outlineBox;
-
// Our current relative position offset.
LayoutSize m_offsetForInFlowPosition;
Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp (220478 => 220479)
--- trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp 2017-08-09 21:02:23 UTC (rev 220478)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp 2017-08-09 21:03:03 UTC (rev 220479)
@@ -38,6 +38,15 @@
bool RenderLayerModelObject::s_hadTransform = false;
bool RenderLayerModelObject::s_layerWasSelfPainting = false;
+typedef WTF::HashMap<const RenderLayerModelObject*, RepaintLayoutRects> RepaintLayoutRectsMap;
+static RepaintLayoutRectsMap* gRepaintLayoutRectsMap = nullptr;
+
+RepaintLayoutRects::RepaintLayoutRects(const RenderLayerModelObject& renderer, const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap)
+ : m_repaintRect(renderer.clippedOverflowRectForRepaint(repaintContainer))
+ , m_outlineBox(renderer.outlineBoundsForRepaint(repaintContainer, geometryMap))
+{
+}
+
RenderLayerModelObject::RenderLayerModelObject(Element& element, RenderStyle&& style, BaseTypeFlags baseTypeFlags)
: RenderElement(element, WTFMove(style), baseTypeFlags | RenderLayerModelObjectFlag)
{
@@ -61,7 +70,9 @@
}
RenderElement::willBeDestroyed();
-
+
+ clearRepaintLayoutRects();
+
// Our layer should have been destroyed and cleared by now
ASSERT(!hasLayer());
ASSERT(!m_layer);
@@ -71,6 +82,8 @@
{
ASSERT(!hasLayer()); // Callers should have already called setHasLayer(false)
ASSERT(m_layer);
+ if (m_layer->isSelfPaintingLayer())
+ clearRepaintLayoutRects();
m_layer = nullptr;
}
@@ -166,8 +179,8 @@
setHasTransformRelatedProperty(false); // All transform-related propeties force layers, so we know we don't have one or the object doesn't support them.
setHasReflection(false);
// Repaint the about to be destroyed self-painting layer when style change also triggers repaint.
- if (layer()->isSelfPaintingLayer() && layer()->repaintStatus() == NeedsFullRepaint && layer()->hasComputedRepaintRect())
- repaintUsingContainer(containerForRepaint(), layer()->repaintRect());
+ if (layer()->isSelfPaintingLayer() && layer()->repaintStatus() == NeedsFullRepaint && hasRepaintLayoutRects())
+ repaintUsingContainer(containerForRepaint(), repaintLayoutRects().m_repaintRect);
layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
if (s_wasFloating && isFloating())
setChildNeedsLayout();
@@ -235,5 +248,38 @@
#endif
}
+bool RenderLayerModelObject::hasRepaintLayoutRects() const
+{
+ return gRepaintLayoutRectsMap && gRepaintLayoutRectsMap->contains(this);
+}
+
+void RenderLayerModelObject::setRepaintLayoutRects(const RepaintLayoutRects& rects)
+{
+ if (!gRepaintLayoutRectsMap)
+ gRepaintLayoutRectsMap = new RepaintLayoutRectsMap();
+ gRepaintLayoutRectsMap->set(this, rects);
+}
+
+void RenderLayerModelObject::clearRepaintLayoutRects()
+{
+ if (gRepaintLayoutRectsMap)
+ gRepaintLayoutRectsMap->remove(this);
+}
+
+RepaintLayoutRects RenderLayerModelObject::repaintLayoutRects() const
+{
+ if (!hasRepaintLayoutRects())
+ return RepaintLayoutRects();
+ return gRepaintLayoutRectsMap->get(this);
+}
+
+void RenderLayerModelObject::computeRepaintLayoutRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap)
+{
+ if (!m_layer || !m_layer->isSelfPaintingLayer())
+ clearRepaintLayoutRects();
+ else
+ setRepaintLayoutRects(RepaintLayoutRects(*this, repaintContainer, geometryMap));
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.h (220478 => 220479)
--- trunk/Source/WebCore/rendering/RenderLayerModelObject.h 2017-08-09 21:02:23 UTC (rev 220478)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.h 2017-08-09 21:03:03 UTC (rev 220479)
@@ -28,6 +28,14 @@
class RenderLayer;
+struct RepaintLayoutRects {
+ LayoutRect m_repaintRect; // This rect is clipped by enclosing objects (e.g., overflow:hidden).
+ LayoutRect m_outlineBox; // This rect is unclipped.
+
+ RepaintLayoutRects(const RenderLayerModelObject& renderer, const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* = nullptr);
+ RepaintLayoutRects() { };
+};
+
class RenderLayerModelObject : public RenderElement {
public:
virtual ~RenderLayerModelObject();
@@ -51,7 +59,15 @@
virtual bool isScrollableOrRubberbandableBox() const { return false; }
bool shouldPlaceBlockDirectionScrollbarOnLeft() const;
+
+ void computeRepaintLayoutRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* = nullptr);
+ RepaintLayoutRects repaintLayoutRects() const;
+
+ bool hasRepaintLayoutRects() const;
+ void setRepaintLayoutRects(const RepaintLayoutRects&);
+ void clearRepaintLayoutRects();
+
protected:
RenderLayerModelObject(Element&, RenderStyle&&, BaseTypeFlags);
RenderLayerModelObject(Document&, RenderStyle&&, BaseTypeFlags);