Ignore:
Timestamp:
May 26, 2022, 3:22:08 PM (3 years ago)
Author:
Alan Bujtas
Message:

Do not issue repaint when the ancestor layer has already been scheduled for one
https://bugs.webkit.org/show_bug.cgi?id=240728

Reviewed by Simon Fraser.

When a renderer needs repaint, we walk the layer tree to search for the repaint container (root for all the paints).
If we find a layer between the renderer and the repaint container that has already been scheduled for a full repaint
we know that this repaint is redundant and will be covered by the ancestor layer.
Since layers paint their overflow content, this works even when the renderer "sticks out" of the ancestor layer's renderer's border box (i.e. produces ink/scrollable overflow).

  • Source/WebCore/rendering/RenderLayer.cpp:

(WebCore::RenderLayer::enclosingCompositingLayerForRepaint const):
(WebCore::RenderLayer::clipCrossesPaintingBoundary const):
(WebCore::RenderLayer::calculateClipRects const):

  • Source/WebCore/rendering/RenderLayer.h:

(WebCore::RenderLayer::needsFullRepaint const):

  • Source/WebCore/rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::repaintInCompositedAncestor):

  • Source/WebCore/rendering/RenderObject.cpp:

(WebCore::RenderObject::containerForRepaint const):
(WebCore::fullRepaintIsScheduled): This covers the cases when the content is embedded inside an iframe and the iframe's view is not composited.
(WebCore::RenderObject::repaint const):
(WebCore::RenderObject::repaintRectangle const):

  • Source/WebCore/rendering/RenderView.cpp:

(WebCore::RenderView::paintBoxDecorations):

Canonical link: https://commits.webkit.org/251025@main

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r294699 r294902  
    861861{
    862862    RenderLayerModelObject* repaintContainer = nullptr;
     863    auto fullRepaintAlreadyScheduled = false;
    863864
    864865    if (view().usesCompositing()) {
    865         if (RenderLayer* parentLayer = enclosingLayer()) {
    866             RenderLayer* compLayer = parentLayer->enclosingCompositingLayerForRepaint();
    867             if (compLayer)
    868                 repaintContainer = &compLayer->renderer();
     866        if (auto* parentLayer = enclosingLayer()) {
     867            auto compLayerStatus = parentLayer->enclosingCompositingLayerForRepaint();
     868            if (compLayerStatus.layer) {
     869                repaintContainer = &compLayerStatus.layer->renderer();
     870                fullRepaintAlreadyScheduled = compLayerStatus.fullRepaintAlreadyScheduled;
     871            }
    869872        }
    870873    }
    871874    if (view().hasSoftwareFilters()) {
    872         if (RenderLayer* parentLayer = enclosingLayer()) {
    873             RenderLayer* enclosingFilterLayer = parentLayer->enclosingFilterLayer();
    874             if (enclosingFilterLayer)
    875                 return { false, &enclosingFilterLayer->renderer() };
     875        if (auto* parentLayer = enclosingLayer()) {
     876            auto* enclosingFilterLayer = parentLayer->enclosingFilterLayer();
     877            if (enclosingFilterLayer) {
     878                fullRepaintAlreadyScheduled = parentLayer->needsFullRepaint();
     879                return { fullRepaintAlreadyScheduled, &enclosingFilterLayer->renderer() };
     880            }
    876881        }
    877882    }
     
    888893            repaintContainer = parentRenderFragmentedFlow;
    889894    }
    890     return { false, repaintContainer };
     895    return { fullRepaintAlreadyScheduled, repaintContainer };
    891896}
    892897
     
    962967}
    963968
     969static inline bool fullRepaintIsScheduled(const RenderObject& renderer)
     970{
     971    if (!renderer.view().usesCompositing() && !renderer.document().ownerElement())
     972        return false;
     973    for (auto* ancestorLayer = renderer.enclosingLayer(); ancestorLayer; ancestorLayer = ancestorLayer->paintOrderParent()) {
     974        if (ancestorLayer->needsFullRepaint())
     975            return true;
     976    }
     977    return false;
     978}
     979
    964980void RenderObject::repaint() const
    965981{
     
    973989
    974990    auto repaintContainer = containerForRepaint();
     991    if (!repaintContainer.renderer)
     992        repaintContainer = { fullRepaintIsScheduled(*this), &view };
     993
    975994    if (!repaintContainer.fullRepaintIsScheduled)
    976995        repaintUsingContainer(repaintContainer.renderer, clippedOverflowRectForRepaint(repaintContainer.renderer));
     
    9931012
    9941013    auto repaintContainer = containerForRepaint();
     1014    if (!repaintContainer.renderer)
     1015        repaintContainer = { fullRepaintIsScheduled(*this), &view };
     1016
    9951017    if (!repaintContainer.fullRepaintIsScheduled)
    9961018        repaintUsingContainer(repaintContainer.renderer, computeRectForRepaint(dirtyRect, repaintContainer.renderer), shouldClipToLayer);
Note: See TracChangeset for help on using the changeset viewer.