Skip to content

Commit

Permalink
Merge r220479 - [Repaint from Layout Removal] Move layer repaint rect…
Browse files Browse the repository at this point in the history
…s 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):
  • Loading branch information
David Hyatt authored and carlosgcampos committed Aug 14, 2017
1 parent 2974cd5 commit 4ab2fc4
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 38 deletions.
38 changes: 38 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,41 @@
2017-08-09 Dave Hyatt <hyatt@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 Kirill Ovchinnikov <kirill.ovchinnikov@lge.com>

Old subtitle track is not deleted on 'src' attribute change event
Expand Down
4 changes: 2 additions & 2 deletions Source/WebCore/rendering/RenderBlockLineLayout.cpp
Expand Up @@ -1281,12 +1281,12 @@ void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState, bool has
// 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);
}
}

Expand Down
46 changes: 20 additions & 26 deletions Source/WebCore/rendering/RenderLayer.cpp
Expand Up @@ -310,7 +310,6 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
, m_layerListMutationAllowed(true)
#endif
, m_hasFilterInfo(false)
, m_hasComputedRepaintRect(false)
#if ENABLE(CSS_COMPOSITING)
, m_blendMode(BlendModeNormal)
, m_hasNotIsolatedCompositedBlendingDescendants(false)
Expand Down Expand Up @@ -516,23 +515,29 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, UpdateLay
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;
}

Expand Down Expand Up @@ -601,7 +606,7 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, UpdateLay

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())
Expand Down Expand Up @@ -797,18 +802,9 @@ void RenderLayer::updateDescendantsAreContiguousInStackingOrderRecursive(const H
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.
Expand All @@ -824,9 +820,7 @@ void RenderLayer::clearRepaintRects()
{
ASSERT(!m_visibleContentStatusDirty);

m_hasComputedRepaintRect = false;
m_repaintRect = LayoutRect();
m_outlineBox = LayoutRect();
renderer().clearRepaintLayoutRects();
}

void RenderLayer::updateLayerPositionsAfterDocumentScroll()
Expand Down Expand Up @@ -889,8 +883,8 @@ void RenderLayer::updateLayerPositionsAfterScroll(RenderGeometryMap* geometryMap
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())
Expand Down Expand Up @@ -2440,7 +2434,7 @@ void RenderLayer::scrollTo(const ScrollPosition& position)
// 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)
Expand Down
8 changes: 1 addition & 7 deletions Source/WebCore/rendering/RenderLayer.h
Expand Up @@ -581,8 +581,7 @@ class RenderLayer final : public ScrollableArea {
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; }
Expand Down Expand Up @@ -1115,8 +1114,6 @@ class RenderLayer final : public ScrollableArea {
#endif

bool m_hasFilterInfo : 1;

bool m_hasComputedRepaintRect : 1;

#if ENABLE(CSS_COMPOSITING)
unsigned m_blendMode : 5;
Expand All @@ -1133,9 +1130,6 @@ class RenderLayer final : public ScrollableArea {
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;

Expand Down
52 changes: 49 additions & 3 deletions Source/WebCore/rendering/RenderLayerModelObject.cpp
Expand Up @@ -38,6 +38,15 @@ bool RenderLayerModelObject::s_hadLayer = false;
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)
{
Expand All @@ -61,7 +70,9 @@ void RenderLayerModelObject::willBeDestroyed()
}

RenderElement::willBeDestroyed();


clearRepaintLayoutRects();

// Our layer should have been destroyed and cleared by now
ASSERT(!hasLayer());
ASSERT(!m_layer);
Expand All @@ -71,6 +82,8 @@ void RenderLayerModelObject::destroyLayer()
{
ASSERT(!hasLayer()); // Callers should have already called setHasLayer(false)
ASSERT(m_layer);
if (m_layer->isSelfPaintingLayer())
clearRepaintLayoutRects();
m_layer = nullptr;
}

Expand Down Expand Up @@ -166,8 +179,8 @@ void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderSt
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();
Expand Down Expand Up @@ -235,5 +248,38 @@ bool RenderLayerModelObject::shouldPlaceBlockDirectionScrollbarOnLeft() const
#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

16 changes: 16 additions & 0 deletions Source/WebCore/rendering/RenderLayerModelObject.h
Expand Up @@ -28,6 +28,14 @@ namespace WebCore {

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();
Expand All @@ -51,6 +59,14 @@ class RenderLayerModelObject : public RenderElement {
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);
Expand Down

0 comments on commit 4ab2fc4

Please sign in to comment.