Changeset 284684 in webkit
- Timestamp:
- Oct 22, 2021, 8:50:23 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
-
ChangeLog (modified) (1 diff)
-
rendering/EventRegion.h (modified) (1 diff)
-
rendering/RenderLayer.cpp (modified) (23 diffs)
-
rendering/RenderLayer.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r284683 r284684 1 2021-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 1 37 2021-10-22 Alan Bujtas <zalan@apple.com> 2 38 -
trunk/Source/WebCore/rendering/EventRegion.h
r278253 r284684 57 57 }; 58 58 59 class EventRegionContextStateSaver { 60 public: 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 85 private: 86 EventRegionContext* m_context; 87 bool m_pushedClip { false }; 88 }; 89 59 90 class EventRegion { 60 91 public: -
trunk/Source/WebCore/rendering/RenderLayer.cpp
r284655 r284684 2905 2905 } 2906 2906 2907 void RenderLayer::clipToRect(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, OptionSet<PaintBehavior> paintBehavior, const ClipRect& clipRect, BorderRadiusClippingRule rule)2907 void RenderLayer::clipToRect(GraphicsContext& context, GraphicsContextStateSaver& stateSaver, EventRegionContextStateSaver& eventRegionStateSaver, const LayerPaintingInfo& paintingInfo, OptionSet<PaintBehavior> paintBehavior, const ClipRect& clipRect, BorderRadiusClippingRule rule) 2908 2908 { 2909 2909 float deviceScaleFactor = renderer().document().deviceScaleFactor(); 2910 2910 bool needsClipping = !clipRect.isInfinite() && clipRect.rect() != paintingInfo.paintDirtyRect; 2911 2911 if (needsClipping || clipRect.affectedByRadius()) 2912 context.save();2912 stateSaver.save(); 2913 2913 2914 2914 if (needsClipping) { … … 2917 2917 auto snappedClipRect = snapRectToDevicePixels(adjustedClipRect, deviceScaleFactor); 2918 2918 context.clip(snappedClipRect); 2919 2920 if (paintingInfo.eventRegionContext) 2921 paintingInfo.eventRegionContext->pushClip(enclosingIntRect(snappedClipRect)); 2919 eventRegionStateSaver.pushClip(enclosingIntRect(snappedClipRect)); 2922 2920 } 2923 2921 … … 2946 2944 } 2947 2945 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 2958 2946 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer) 2959 2947 { … … 3072 3060 // Make sure the parent's clip rects have been calculated. 3073 3061 ClipRect clipRect = paintingInfo.paintDirtyRect; 3062 GraphicsContextStateSaver stateSaver(context, false); 3063 EventRegionContextStateSaver eventRegionStateSaver(paintingInfo.eventRegionContext); 3074 3064 if (parent()) { 3075 3065 ClipRectsContext clipRectsContext(paintingInfo.rootLayer, (paintFlags & PaintLayerFlag::TemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, … … 3083 3073 3084 3074 // Push the parent coordinate space's clip. 3085 parent()->clipToRect(context, paintingInfo, paintBehavior, clipRect);3075 parent()->clipToRect(context, stateSaver, eventRegionStateSaver, paintingInfo, paintBehavior, clipRect); 3086 3076 } 3087 3077 3088 3078 paintLayerByApplyingTransform(context, paintingInfo, paintFlags); 3089 3090 // Restore the clip.3091 if (parent())3092 parent()->restoreClip(context, paintingInfo, clipRect);3093 3094 3079 return; 3095 3080 } … … 3172 3157 } 3173 3158 3174 bool RenderLayer::setupClipPath(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, const LayoutSize& offsetFromRoot)3159 void RenderLayer::setupClipPath(GraphicsContext& context, GraphicsContextStateSaver& stateSaver, const LayerPaintingInfo& paintingInfo, const LayoutSize& offsetFromRoot) 3175 3160 { 3176 3161 if (!renderer().hasClipPath() || context.paintingDisabled() || paintingInfo.paintDirtyRect.isEmpty()) 3177 return false;3162 return; 3178 3163 3179 3164 // SVG elements get clipped in SVG code. 3180 3165 if (is<RenderSVGRoot>(renderer())) 3181 return false;3166 return; 3182 3167 3183 3168 auto clippedContentBounds = calculateLayerBounds(paintingInfo.rootLayer, offsetFromRoot, { UseLocalClipRectIfPossible }); … … 3189 3174 // clippedContentBounds is used as the reference box for inlines, which is also poorly specified: https://github.com/w3c/csswg-drafts/issues/6383. 3190 3175 auto [path, windRule] = computeClipPath(paintingOffsetFromRoot, clippedContentBounds); 3191 context.save();3176 stateSaver.save(); 3192 3177 context.clipPath(path, windRule); 3193 return true;3194 3178 } 3195 3179 … … 3206 3190 snappedClippingBounds.moveBy(-offset); 3207 3191 3208 context.save();3192 stateSaver.save(); 3209 3193 context.translate(offset); 3210 3194 FloatRect clipPathReferenceBox { { }, referenceBox.size() }; 3211 3195 clipperRenderer->applyClippingToContext(context, renderer(), clipPathReferenceBox, snappedClippingBounds, renderer().style().effectiveZoom()); 3212 3196 context.translate(-offset); 3213 return true; 3214 } 3215 } 3216 3217 return false; 3197 } 3198 } 3218 3199 } 3219 3200 … … 3266 3247 // FIXME: Handle more than one fragment. 3267 3248 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); 3269 3254 m_filters->applyFilterEffect(originalContext); 3270 restoreClip(originalContext, paintingInfo, backgroundRect);3271 3255 } 3272 3256 … … 3327 3311 columnAwareOffsetFromRoot = toLayoutSize(convertToLayerCoords(paintingInfo.rootLayer, LayoutPoint(), AdjustForColumns)); 3328 3312 3329 bool hasClipPath = false;3313 GraphicsContextStateSaver stateSaver(context, false); 3330 3314 if (shouldApplyClipPath(paintingInfo.paintBehavior, localPaintFlags)) 3331 hasClipPath = setupClipPath(context, paintingInfo, columnAwareOffsetFromRoot);3315 setupClipPath(context, stateSaver, paintingInfo, columnAwareOffsetFromRoot); 3332 3316 3333 3317 bool selectionAndBackgroundsOnly = paintingInfo.paintBehavior.contains(PaintBehavior::SelectionAndBackgroundsOnly); … … 3480 3464 if (needToAdjustSubpixelQuantization) 3481 3465 context.setShouldSubpixelQuantizeFonts(didQuantizeFonts); 3482 3483 if (hasClipPath)3484 context.restore();3485 3466 } 3486 3467 … … 3733 3714 paintBehavior.add(PaintBehavior::CompositedOverflowScrollContent); 3734 3715 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); 3736 3720 paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset); 3737 parent()->restoreClip(context, paintingInfo, clipRect);3738 3721 } 3739 3722 } … … 3751 3734 beginTransparencyLayers(contextForTransparencyLayer, localPaintingInfo, transparencyPaintDirtyRect); 3752 3735 3736 GraphicsContextStateSaver stateSaver(context, false); 3737 EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext); 3738 3753 3739 if (localPaintingInfo.clipToDirtyRect) { 3754 3740 // Paint our background first, before painting any child layers. 3755 3741 // 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. 3757 3743 } 3758 3744 … … 3761 3747 PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::BlockBackground, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this); 3762 3748 renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)); 3763 3764 if (localPaintingInfo.clipToDirtyRect)3765 restoreClip(context, localPaintingInfo, fragment.backgroundRect);3766 3749 } 3767 3750 } … … 3802 3785 localPaintBehavior.add(PaintBehavior::CompositedOverflowScrollContent); 3803 3786 3787 GraphicsContextStateSaver stateSaver(context, false); 3788 EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext); 3789 3804 3790 // Optimize clipping for the single fragment case. 3805 3791 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); 3811 3794 3812 3795 // We have to loop through every fragment multiple times, since we have to repaint in each specific phase in order for … … 3825 3808 paintForegroundForFragmentsWithPhase(PaintPhase::ChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer); 3826 3809 } 3827 3828 if (shouldClip)3829 restoreClip(context, localPaintingInfo, clippedRect);3830 3810 } 3831 3811 … … 3838 3818 if (!fragment.shouldPaintContent || fragment.foregroundRect.isEmpty()) 3839 3819 continue; 3840 3820 3821 GraphicsContextStateSaver stateSaver(context, false); 3822 EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext); 3823 3841 3824 if (shouldClip) 3842 clipToRect(context, localPaintingInfo, paintBehavior, fragment.foregroundRect);3825 clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.foregroundRect); 3843 3826 3844 3827 PaintInfo paintInfo(context, fragment.foregroundRect.rect(), phase, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this, localPaintingInfo.requireSecurityOriginAccessForWidgets); … … 3846 3829 paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests; 3847 3830 renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)); 3848 3849 if (shouldClip)3850 restoreClip(context, localPaintingInfo, fragment.foregroundRect);3851 3831 } 3852 3832 } … … 3861 3841 // Paint our own outline 3862 3842 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); 3864 3848 renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)); 3865 restoreClip(context, localPaintingInfo, fragment.backgroundRect);3866 3849 } 3867 3850 } … … 3874 3857 continue; 3875 3858 3859 GraphicsContextStateSaver stateSaver(context, false); 3860 EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext); 3861 3876 3862 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. 3878 3864 3879 3865 // Paint the mask. … … 3881 3867 PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::Mask, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this); 3882 3868 renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)); 3883 3884 if (localPaintingInfo.clipToDirtyRect)3885 restoreClip(context, localPaintingInfo, fragment.backgroundRect);3886 3869 } 3887 3870 } … … 3893 3876 continue; 3894 3877 3878 GraphicsContextStateSaver stateSaver(context, false); 3879 EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext); 3880 3895 3881 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. 3897 3883 3898 3884 // Paint the clipped mask. 3899 3885 PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::ClippingMask, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this); 3900 3886 renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)); 3901 3902 if (localPaintingInfo.clipToDirtyRect)3903 restoreClip(context, localPaintingInfo, fragment.foregroundRect);3904 3887 } 3905 3888 } … … 3912 3895 if (fragment.backgroundRect.isEmpty()) 3913 3896 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); 3918 3903 } 3919 3904 } -
trunk/Source/WebCore/rendering/RenderLayer.h
r284490 r284684 931 931 LayoutRect clipRectRelativeToAncestor(RenderLayer* ancestor, LayoutSize offsetFromAncestor, const LayoutRect& constrainingRect) const; 932 932 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); 935 934 936 935 bool shouldRepaintAfterLayout() const; … … 971 970 std::pair<Path, WindRule> computeClipPath(const LayoutSize& offsetFromRoot, const LayoutRect& rootRelativeBoundsForNonBoxes) const; 972 971 973 bool setupClipPath(GraphicsContext&, const LayerPaintingInfo&, const LayoutSize& offsetFromRoot);972 void setupClipPath(GraphicsContext&, GraphicsContextStateSaver&, const LayerPaintingInfo&, const LayoutSize& offsetFromRoot); 974 973 975 974 void ensureLayerFilters();
Note:
See TracChangeset
for help on using the changeset viewer.