⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 284684 in webkit


Ignore:
Timestamp:
Oct 22, 2021, 8:50:23 AM (5 years ago)
Author:
Simon Fraser
Message:

Do GrpahicsContext and EventRegion clipping-related save/restore via RAII objects
https://bugs.webkit.org/show_bug.cgi?id=231985

Reviewed by Antti Koivisto.

Remove all but one of the bare context.save() calls in RenderLayer by passing a
GraphicsContextStateSaver to clipToRect() and setupClipPath().

Also pass a EventRegionContextStateSaver for the equivalent save/restore on EventRegionContext.

This allows us to remove restoreClip() entirely.

  • rendering/EventRegion.h:

(WebCore::EventRegionContextStateSaver::EventRegionContextStateSaver):
(WebCore::EventRegionContextStateSaver::~EventRegionContextStateSaver):
(WebCore::EventRegionContextStateSaver::pushClip):
(WebCore::EventRegionContextStateSaver::context const):

  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::clipToRect):
(WebCore::RenderLayer::paintLayerWithEffects):
(WebCore::RenderLayer::setupClipPath):
(WebCore::RenderLayer::applyFilters):
(WebCore::RenderLayer::paintLayerContents):
(WebCore::RenderLayer::paintTransformedLayerIntoFragments):
(WebCore::RenderLayer::paintBackgroundForFragments):
(WebCore::RenderLayer::paintForegroundForFragments):
(WebCore::RenderLayer::paintForegroundForFragmentsWithPhase):
(WebCore::RenderLayer::paintOutlineForFragments):
(WebCore::RenderLayer::paintMaskForFragments):
(WebCore::RenderLayer::paintChildClippingMaskForFragments):
(WebCore::RenderLayer::paintOverflowControlsForFragments):
(WebCore::RenderLayer::restoreClip): Deleted.

  • rendering/RenderLayer.h:
Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r284683 r284684  
     12021-10-22  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Do GrpahicsContext and EventRegion clipping-related save/restore via RAII objects
     4        https://bugs.webkit.org/show_bug.cgi?id=231985
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Remove all but one of the bare context.save() calls in RenderLayer by passing a
     9        GraphicsContextStateSaver to clipToRect() and setupClipPath().
     10
     11        Also pass a EventRegionContextStateSaver for the equivalent save/restore on EventRegionContext.
     12
     13        This allows us to remove restoreClip() entirely.
     14
     15        * rendering/EventRegion.h:
     16        (WebCore::EventRegionContextStateSaver::EventRegionContextStateSaver):
     17        (WebCore::EventRegionContextStateSaver::~EventRegionContextStateSaver):
     18        (WebCore::EventRegionContextStateSaver::pushClip):
     19        (WebCore::EventRegionContextStateSaver::context const):
     20        * rendering/RenderLayer.cpp:
     21        (WebCore::RenderLayer::clipToRect):
     22        (WebCore::RenderLayer::paintLayerWithEffects):
     23        (WebCore::RenderLayer::setupClipPath):
     24        (WebCore::RenderLayer::applyFilters):
     25        (WebCore::RenderLayer::paintLayerContents):
     26        (WebCore::RenderLayer::paintTransformedLayerIntoFragments):
     27        (WebCore::RenderLayer::paintBackgroundForFragments):
     28        (WebCore::RenderLayer::paintForegroundForFragments):
     29        (WebCore::RenderLayer::paintForegroundForFragmentsWithPhase):
     30        (WebCore::RenderLayer::paintOutlineForFragments):
     31        (WebCore::RenderLayer::paintMaskForFragments):
     32        (WebCore::RenderLayer::paintChildClippingMaskForFragments):
     33        (WebCore::RenderLayer::paintOverflowControlsForFragments):
     34        (WebCore::RenderLayer::restoreClip): Deleted.
     35        * rendering/RenderLayer.h:
     36
    1372021-10-22  Alan Bujtas  <zalan@apple.com>
    238
  • trunk/Source/WebCore/rendering/EventRegion.h

    r278253 r284684  
    5757};
    5858
     59class EventRegionContextStateSaver {
     60public:
     61    EventRegionContextStateSaver(EventRegionContext* context)
     62        : m_context(context)
     63    {
     64    }
     65   
     66    ~EventRegionContextStateSaver()
     67    {
     68        if (!m_context)
     69            return;
     70
     71        if (m_pushedClip)
     72            m_context->popClip();
     73    }
     74   
     75    void pushClip(const IntRect& clipRect)
     76    {
     77        ASSERT(!m_pushedClip);
     78        if (m_context)
     79            m_context->pushClip(clipRect);
     80        m_pushedClip = true;
     81    }
     82
     83    EventRegionContext* context() const { return m_context; }
     84
     85private:
     86    EventRegionContext* m_context;
     87    bool m_pushedClip { false };
     88};
     89
    5990class EventRegion {
    6091public:
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r284655 r284684  
    29052905}
    29062906
    2907 void RenderLayer::clipToRect(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, OptionSet<PaintBehavior> paintBehavior, const ClipRect& clipRect, BorderRadiusClippingRule rule)
     2907void RenderLayer::clipToRect(GraphicsContext& context, GraphicsContextStateSaver& stateSaver, EventRegionContextStateSaver& eventRegionStateSaver, const LayerPaintingInfo& paintingInfo, OptionSet<PaintBehavior> paintBehavior, const ClipRect& clipRect, BorderRadiusClippingRule rule)
    29082908{
    29092909    float deviceScaleFactor = renderer().document().deviceScaleFactor();
    29102910    bool needsClipping = !clipRect.isInfinite() && clipRect.rect() != paintingInfo.paintDirtyRect;
    29112911    if (needsClipping || clipRect.affectedByRadius())
    2912         context.save();
     2912        stateSaver.save();
    29132913
    29142914    if (needsClipping) {
     
    29172917        auto snappedClipRect = snapRectToDevicePixels(adjustedClipRect, deviceScaleFactor);
    29182918        context.clip(snappedClipRect);
    2919 
    2920         if (paintingInfo.eventRegionContext)
    2921             paintingInfo.eventRegionContext->pushClip(enclosingIntRect(snappedClipRect));
     2919        eventRegionStateSaver.pushClip(enclosingIntRect(snappedClipRect));
    29222920    }
    29232921
     
    29462944}
    29472945
    2948 void RenderLayer::restoreClip(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, const ClipRect& clipRect)
    2949 {
    2950     bool needsClipping = !clipRect.isInfinite() && clipRect.rect() != paintingInfo.paintDirtyRect;
    2951     if (needsClipping || clipRect.affectedByRadius())
    2952         context.restore();
    2953 
    2954     if (needsClipping && paintingInfo.eventRegionContext)
    2955         paintingInfo.eventRegionContext->popClip();
    2956 }
    2957 
    29582946static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer)
    29592947{
     
    30723060        // Make sure the parent's clip rects have been calculated.
    30733061        ClipRect clipRect = paintingInfo.paintDirtyRect;
     3062        GraphicsContextStateSaver stateSaver(context, false);
     3063        EventRegionContextStateSaver eventRegionStateSaver(paintingInfo.eventRegionContext);
    30743064        if (parent()) {
    30753065            ClipRectsContext clipRectsContext(paintingInfo.rootLayer, (paintFlags & PaintLayerFlag::TemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
     
    30833073
    30843074            // Push the parent coordinate space's clip.
    3085             parent()->clipToRect(context, paintingInfo, paintBehavior, clipRect);
     3075            parent()->clipToRect(context, stateSaver, eventRegionStateSaver, paintingInfo, paintBehavior, clipRect);
    30863076        }
    30873077
    30883078        paintLayerByApplyingTransform(context, paintingInfo, paintFlags);
    3089 
    3090         // Restore the clip.
    3091         if (parent())
    3092             parent()->restoreClip(context, paintingInfo, clipRect);
    3093 
    30943079        return;
    30953080    }
     
    31723157}
    31733158
    3174 bool RenderLayer::setupClipPath(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, const LayoutSize& offsetFromRoot)
     3159void RenderLayer::setupClipPath(GraphicsContext& context, GraphicsContextStateSaver& stateSaver, const LayerPaintingInfo& paintingInfo, const LayoutSize& offsetFromRoot)
    31753160{
    31763161    if (!renderer().hasClipPath() || context.paintingDisabled() || paintingInfo.paintDirtyRect.isEmpty())
    3177         return false;
     3162        return;
    31783163
    31793164    // SVG elements get clipped in SVG code.
    31803165    if (is<RenderSVGRoot>(renderer()))
    3181         return false;
     3166        return;
    31823167
    31833168    auto clippedContentBounds = calculateLayerBounds(paintingInfo.rootLayer, offsetFromRoot, { UseLocalClipRectIfPossible });
     
    31893174        // clippedContentBounds is used as the reference box for inlines, which is also poorly specified: https://github.com/w3c/csswg-drafts/issues/6383.
    31903175        auto [path, windRule] = computeClipPath(paintingOffsetFromRoot, clippedContentBounds);
    3191         context.save();
     3176        stateSaver.save();
    31923177        context.clipPath(path, windRule);
    3193         return true;
    31943178    }
    31953179
     
    32063190            snappedClippingBounds.moveBy(-offset);
    32073191
    3208             context.save();
     3192            stateSaver.save();
    32093193            context.translate(offset);
    32103194            FloatRect clipPathReferenceBox { { }, referenceBox.size() };
    32113195            clipperRenderer->applyClippingToContext(context, renderer(), clipPathReferenceBox, snappedClippingBounds, renderer().style().effectiveZoom());
    32123196            context.translate(-offset);
    3213             return true;
    3214         }
    3215     }
    3216 
    3217     return false;
     3197        }
     3198    }
    32183199}
    32193200
     
    32663247    // FIXME: Handle more than one fragment.
    32673248    ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
    3268     clipToRect(originalContext, paintingInfo, behavior, backgroundRect);
     3249
     3250    GraphicsContextStateSaver stateSaver(originalContext, false);
     3251    EventRegionContextStateSaver eventRegionStateSaver(paintingInfo.eventRegionContext);
     3252
     3253    clipToRect(originalContext, stateSaver, eventRegionStateSaver, paintingInfo, behavior, backgroundRect);
    32693254    m_filters->applyFilterEffect(originalContext);
    3270     restoreClip(originalContext, paintingInfo, backgroundRect);
    32713255}
    32723256
     
    33273311        columnAwareOffsetFromRoot = toLayoutSize(convertToLayerCoords(paintingInfo.rootLayer, LayoutPoint(), AdjustForColumns));
    33283312
    3329     bool hasClipPath = false;
     3313    GraphicsContextStateSaver stateSaver(context, false);
    33303314    if (shouldApplyClipPath(paintingInfo.paintBehavior, localPaintFlags))
    3331         hasClipPath = setupClipPath(context, paintingInfo, columnAwareOffsetFromRoot);
     3315        setupClipPath(context, stateSaver, paintingInfo, columnAwareOffsetFromRoot);
    33323316
    33333317    bool selectionAndBackgroundsOnly = paintingInfo.paintBehavior.contains(PaintBehavior::SelectionAndBackgroundsOnly);
     
    34803464    if (needToAdjustSubpixelQuantization)
    34813465        context.setShouldSubpixelQuantizeFonts(didQuantizeFonts);
    3482 
    3483     if (hasClipPath)
    3484         context.restore();
    34853466}
    34863467
     
    37333714            paintBehavior.add(PaintBehavior::CompositedOverflowScrollContent);
    37343715
    3735         parent()->clipToRect(context, paintingInfo, paintBehavior, clipRect);
     3716        GraphicsContextStateSaver stateSaver(context, false);
     3717        EventRegionContextStateSaver eventRegionStateSaver(paintingInfo.eventRegionContext);
     3718
     3719        parent()->clipToRect(context, stateSaver, eventRegionStateSaver, paintingInfo, paintBehavior, clipRect);
    37363720        paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset);
    3737         parent()->restoreClip(context, paintingInfo, clipRect);
    37383721    }
    37393722}
     
    37513734            beginTransparencyLayers(contextForTransparencyLayer, localPaintingInfo, transparencyPaintDirtyRect);
    37523735   
     3736        GraphicsContextStateSaver stateSaver(context, false);
     3737        EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
     3738
    37533739        if (localPaintingInfo.clipToDirtyRect) {
    37543740            // Paint our background first, before painting any child layers.
    37553741            // Establish the clip used to paint our background.
    3756             clipToRect(context, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
     3742            clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
    37573743        }
    37583744       
     
    37613747        PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::BlockBackground, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this);
    37623748        renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
    3763 
    3764         if (localPaintingInfo.clipToDirtyRect)
    3765             restoreClip(context, localPaintingInfo, fragment.backgroundRect);
    37663749    }
    37673750}
     
    38023785        localPaintBehavior.add(PaintBehavior::CompositedOverflowScrollContent);
    38033786
     3787    GraphicsContextStateSaver stateSaver(context, false);
     3788    EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
     3789
    38043790    // Optimize clipping for the single fragment case.
    38053791    bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty();
    3806     ClipRect clippedRect;
    3807     if (shouldClip) {
    3808         clippedRect = layerFragments[0].foregroundRect;
    3809         clipToRect(context, localPaintingInfo, localPaintBehavior, clippedRect);
    3810     }
     3792    if (shouldClip)
     3793        clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, localPaintBehavior, layerFragments[0].foregroundRect);
    38113794   
    38123795    // We have to loop through every fragment multiple times, since we have to repaint in each specific phase in order for
     
    38253808        paintForegroundForFragmentsWithPhase(PaintPhase::ChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer);
    38263809    }
    3827    
    3828     if (shouldClip)
    3829         restoreClip(context, localPaintingInfo, clippedRect);
    38303810}
    38313811
     
    38383818        if (!fragment.shouldPaintContent || fragment.foregroundRect.isEmpty())
    38393819            continue;
    3840        
     3820
     3821        GraphicsContextStateSaver stateSaver(context, false);
     3822        EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
     3823
    38413824        if (shouldClip)
    3842             clipToRect(context, localPaintingInfo, paintBehavior, fragment.foregroundRect);
     3825            clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.foregroundRect);
    38433826   
    38443827        PaintInfo paintInfo(context, fragment.foregroundRect.rect(), phase, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this, localPaintingInfo.requireSecurityOriginAccessForWidgets);
     
    38463829            paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests;
    38473830        renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
    3848        
    3849         if (shouldClip)
    3850             restoreClip(context, localPaintingInfo, fragment.foregroundRect);
    38513831    }
    38523832}
     
    38613841        // Paint our own outline
    38623842        PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::SelfOutline, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this);
    3863         clipToRect(context, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius);
     3843
     3844        GraphicsContextStateSaver stateSaver(context, false);
     3845        EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
     3846
     3847        clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius);
    38643848        renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
    3865         restoreClip(context, localPaintingInfo, fragment.backgroundRect);
    38663849    }
    38673850}
     
    38743857            continue;
    38753858
     3859        GraphicsContextStateSaver stateSaver(context, false);
     3860        EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
     3861
    38763862        if (localPaintingInfo.clipToDirtyRect)
    3877             clipToRect(context, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
     3863            clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
    38783864       
    38793865        // Paint the mask.
     
    38813867        PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::Mask, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this);
    38823868        renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
    3883        
    3884         if (localPaintingInfo.clipToDirtyRect)
    3885             restoreClip(context, localPaintingInfo, fragment.backgroundRect);
    38863869    }
    38873870}
     
    38933876            continue;
    38943877
     3878        GraphicsContextStateSaver stateSaver(context, false);
     3879        EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
     3880
    38953881        if (localPaintingInfo.clipToDirtyRect)
    3896             clipToRect(context, localPaintingInfo, paintBehavior, fragment.foregroundRect, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
     3882            clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.foregroundRect, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
    38973883
    38983884        // Paint the clipped mask.
    38993885        PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::ClippingMask, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this);
    39003886        renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
    3901 
    3902         if (localPaintingInfo.clipToDirtyRect)
    3903             restoreClip(context, localPaintingInfo, fragment.foregroundRect);
    39043887    }
    39053888}
     
    39123895        if (fragment.backgroundRect.isEmpty())
    39133896            continue;
    3914         clipToRect(context, localPaintingInfo, { }, fragment.backgroundRect);
    3915         m_scrollableArea->paintOverflowControls(context, roundedIntPoint(toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)),
    3916             snappedIntRect(fragment.backgroundRect.rect()), true);
    3917         restoreClip(context, localPaintingInfo, fragment.backgroundRect);
     3897
     3898        GraphicsContextStateSaver stateSaver(context, false);
     3899        EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
     3900
     3901        clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, { }, fragment.backgroundRect);
     3902        m_scrollableArea->paintOverflowControls(context, roundedIntPoint(toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)), snappedIntRect(fragment.backgroundRect.rect()), true);
    39183903    }
    39193904}
  • trunk/Source/WebCore/rendering/RenderLayer.h

    r284490 r284684  
    931931    LayoutRect clipRectRelativeToAncestor(RenderLayer* ancestor, LayoutSize offsetFromAncestor, const LayoutRect& constrainingRect) const;
    932932
    933     void clipToRect(GraphicsContext&, const LayerPaintingInfo&, OptionSet<PaintBehavior>, const ClipRect&, BorderRadiusClippingRule = IncludeSelfForBorderRadius);
    934     void restoreClip(GraphicsContext&, const LayerPaintingInfo&, const ClipRect&);
     933    void clipToRect(GraphicsContext&, GraphicsContextStateSaver&, EventRegionContextStateSaver&, const LayerPaintingInfo&, OptionSet<PaintBehavior>, const ClipRect&, BorderRadiusClippingRule = IncludeSelfForBorderRadius);
    935934
    936935    bool shouldRepaintAfterLayout() const;
     
    971970    std::pair<Path, WindRule> computeClipPath(const LayoutSize& offsetFromRoot, const LayoutRect& rootRelativeBoundsForNonBoxes) const;
    972971
    973     bool setupClipPath(GraphicsContext&, const LayerPaintingInfo&, const LayoutSize& offsetFromRoot);
     972    void setupClipPath(GraphicsContext&, GraphicsContextStateSaver&, const LayerPaintingInfo&, const LayoutSize& offsetFromRoot);
    974973
    975974    void ensureLayerFilters();
Note: See TracChangeset for help on using the changeset viewer.