Changeset 268898 in webkit


Ignore:
Timestamp:
Oct 22, 2020 4:15:41 PM (4 years ago)
Author:
Simon Fraser
Message:

Twitter Photo gallery incorrectly rendered after opening another modal
https://bugs.webkit.org/show_bug.cgi?id=217737
<rdar://problem/70314822>

Reviewed by Zalan Bujtas.
Source/WebCore:

If a layer with a certain configuration of clipping layers had non-zero border-radius, then
changes to zero border-radius, we'd fail to undo the composited rounded-corner masking.
This was because RenderLayerBacking::updateGeometry() didn't call setMasksToBoundsRect()
in the non-rounded corner case.

The compositing code in general tries to separate "configuration" changes (i.e. setting
up the right layer hierarchy) from "geometry" changes (setting positions and sizes).
In this area, those responsibilities were muddied because the return value from
setMasksToBoundsRect() was used to know whether the platform-specific GraphicsLayer
supports rounded-corner clips. This forced RenderLayerBacking::updateChildClippingStrategy()
to do some geometry computation.

Clean that up by adding the static GraphicsLayer::supportsRoundedClip(), and use
that to know if the platform needs a m_childClippingMaskLayer (all non-CA platforms).
Now updateChildClippingStrategy() can be purely about hierarchy, and updateGeometry()
can focus on geometry. In updateGeometry(), we are sure to call setMasksToBoundsRect()
in the non-rounded corner case too.

Test: compositing/style-change/border-radius-change.html

  • platform/graphics/GraphicsLayer.cpp:

(WebCore::GraphicsLayer::supportsRoundedClip):
(WebCore::GraphicsLayer::setMasksToBoundsRect):

  • platform/graphics/GraphicsLayer.h:

(WebCore::GraphicsLayer::setMasksToBoundsRect): Deleted.

  • platform/graphics/ca/GraphicsLayerCA.cpp:

(WebCore::GraphicsLayer::supportsRoundedClip):
(WebCore::GraphicsLayerCA::setMasksToBoundsRect):

  • platform/graphics/ca/GraphicsLayerCA.h:
  • rendering/RenderLayerBacking.cpp:

(WebCore::RenderLayerBacking::updateGeometry):
(WebCore::RenderLayerBacking::updateChildClippingStrategy):

LayoutTests:

  • compositing/style-change/border-radius-change-expected.html: Added.
  • compositing/style-change/border-radius-change.html: Added.
Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r268892 r268898  
     12020-10-22  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Twitter Photo gallery incorrectly rendered after opening another modal
     4        https://bugs.webkit.org/show_bug.cgi?id=217737
     5        <rdar://problem/70314822>
     6
     7        Reviewed by Zalan Bujtas.
     8
     9        * compositing/style-change/border-radius-change-expected.html: Added.
     10        * compositing/style-change/border-radius-change.html: Added.
     11
    1122020-10-22  Lauro Moura  <lmoura@igalia.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r268897 r268898  
     12020-10-22  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Twitter Photo gallery incorrectly rendered after opening another modal
     4        https://bugs.webkit.org/show_bug.cgi?id=217737
     5        <rdar://problem/70314822>
     6
     7        Reviewed by Zalan Bujtas.
     8       
     9        If a layer with a certain configuration of clipping layers had non-zero border-radius, then
     10        changes to zero border-radius, we'd fail to undo the composited rounded-corner masking.
     11        This was because RenderLayerBacking::updateGeometry() didn't call setMasksToBoundsRect()
     12        in the non-rounded corner case.
     13       
     14        The compositing code in general tries to separate "configuration" changes (i.e. setting
     15        up the right layer hierarchy) from "geometry" changes (setting positions and sizes).
     16        In this area, those responsibilities were muddied because the return value from
     17        setMasksToBoundsRect() was used to know whether the platform-specific GraphicsLayer
     18        supports rounded-corner clips. This forced RenderLayerBacking::updateChildClippingStrategy()
     19        to do some geometry computation.
     20       
     21        Clean that up by adding the static GraphicsLayer::supportsRoundedClip(), and use
     22        that to know if the platform needs a m_childClippingMaskLayer (all non-CA platforms).
     23        Now updateChildClippingStrategy() can be purely about hierarchy, and updateGeometry()
     24        can focus on geometry. In updateGeometry(), we are sure to call setMasksToBoundsRect()
     25        in the non-rounded corner case too.
     26
     27        Test: compositing/style-change/border-radius-change.html
     28
     29        * platform/graphics/GraphicsLayer.cpp:
     30        (WebCore::GraphicsLayer::supportsRoundedClip):
     31        (WebCore::GraphicsLayer::setMasksToBoundsRect):
     32        * platform/graphics/GraphicsLayer.h:
     33        (WebCore::GraphicsLayer::setMasksToBoundsRect): Deleted.
     34        * platform/graphics/ca/GraphicsLayerCA.cpp:
     35        (WebCore::GraphicsLayer::supportsRoundedClip):
     36        (WebCore::GraphicsLayerCA::setMasksToBoundsRect):
     37        * platform/graphics/ca/GraphicsLayerCA.h:
     38        * rendering/RenderLayerBacking.cpp:
     39        (WebCore::RenderLayerBacking::updateGeometry):
     40        (WebCore::RenderLayerBacking::updateChildClippingStrategy):
     41
    1422020-10-22  Chris Dumez  <cdumez@apple.com>
    243
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp

    r268615 r268898  
    8989}
    9090
     91bool GraphicsLayer::supportsRoundedClip()
     92{
     93    return false;
     94}
     95
    9196bool GraphicsLayer::supportsBackgroundColorContent()
    9297{
     
    381386   
    382387    m_maskLayer = WTFMove(layer);
     388}
     389
     390void GraphicsLayer::setMasksToBoundsRect(const FloatRoundedRect& roundedRect)
     391{
     392    m_masksToBoundsRect = roundedRect;
    383393}
    384394
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.h

    r268615 r268898  
    466466
    467467    // Set a rounded rect that is used to clip this layer and its descendants (implies setting masksToBounds).
    468     // Returns false if the platform can't support this rounded clip, and we should fall back to painting a mask.
     468    // Consult supportsRoundedClip() to know whether non-zero radii are supported.
    469469    FloatRoundedRect maskToBoundsRect() const { return m_masksToBoundsRect; };
    470     virtual bool setMasksToBoundsRect(const FloatRoundedRect& roundedRect) { m_masksToBoundsRect = roundedRect; return false; }
     470    virtual void setMasksToBoundsRect(const FloatRoundedRect&);
    471471
    472472    Path shapeLayerPath() const;
     
    608608    void addRepaintRect(const FloatRect&);
    609609
     610    static bool supportsRoundedClip();
    610611    static bool supportsBackgroundColorContent();
    611612    static bool supportsLayerType(Type);
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp

    r268771 r268898  
    326326}
    327327
     328bool GraphicsLayer::supportsRoundedClip()
     329{
     330    return true;
     331}
     332
    328333bool GraphicsLayer::supportsSubpixelAntialiasedLayerText()
    329334{
     
    972977}
    973978
    974 bool GraphicsLayerCA::setMasksToBoundsRect(const FloatRoundedRect& roundedRect)
     979void GraphicsLayerCA::setMasksToBoundsRect(const FloatRoundedRect& roundedRect)
    975980{
    976981    if (roundedRect == m_masksToBoundsRect)
    977         return true;
     982        return;
    978983
    979984    GraphicsLayer::setMasksToBoundsRect(roundedRect);
    980985    noteLayerPropertyChanged(MasksToBoundsRectChanged);
    981     return true;
    982986}
    983987
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h

    r268746 r268898  
    123123    WEBCORE_EXPORT void setContentsClippingRect(const FloatRoundedRect&) override;
    124124    WEBCORE_EXPORT void setContentsRectClipsDescendants(bool) override;
    125     WEBCORE_EXPORT bool setMasksToBoundsRect(const FloatRoundedRect&) override;
     125    WEBCORE_EXPORT void setMasksToBoundsRect(const FloatRoundedRect&) override;
    126126
    127127    WEBCORE_EXPORT void setShapeLayerPath(const Path&) override;
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r268712 r268898  
    13231323        clipLayer->setOffsetFromRenderer(toLayoutSize(clippingBox.location() - snappedClippingGraphicsLayer.m_snapDelta));
    13241324
    1325         if ((renderer().style().clipPath() || renderer().style().hasBorderRadius()) && !m_childClippingMaskLayer) {
    1326             FloatRoundedRect contentsClippingRect = renderBox.roundedBorderBoxRect().pixelSnappedRoundedRectForPainting(deviceScaleFactor);
    1327             contentsClippingRect.move(LayoutSize(-clipLayer->offsetFromRenderer()));
    1328             clipLayer->setMasksToBoundsRect(contentsClippingRect);
    1329         }
     1325        auto computeMasksToBoundsRect = [&] {
     1326            if ((renderer().style().clipPath() || renderer().style().hasBorderRadius()) && !m_childClippingMaskLayer) {
     1327                FloatRoundedRect contentsClippingRect = renderBox.roundedBorderBoxRect().pixelSnappedRoundedRectForPainting(deviceScaleFactor);
     1328                contentsClippingRect.move(LayoutSize(-clipLayer->offsetFromRenderer()));
     1329                return contentsClippingRect;
     1330            }
     1331
     1332            return FloatRoundedRect { FloatRect { { }, snappedClippingGraphicsLayer.m_snappedRect.size() } };
     1333        };
     1334
     1335        clipLayer->setMasksToBoundsRect(computeMasksToBoundsRect());
    13301336
    13311337        if (m_childClippingMaskLayer && !m_scrollContainerLayer) {
     
    22112217void RenderLayerBacking::updateChildClippingStrategy(bool needsDescendantsClippingLayer)
    22122218{
    2213     if (hasClippingLayer() && needsDescendantsClippingLayer) {
    2214         if (is<RenderBox>(renderer()) && (renderer().style().clipPath() || renderer().style().hasBorderRadius())) {
    2215             auto* clipLayer = clippingLayer();
    2216             FloatRoundedRect contentsClippingRect = downcast<RenderBox>(renderer()).roundedBorderBoxRect().pixelSnappedRoundedRectForPainting(deviceScaleFactor());
    2217             contentsClippingRect.move(LayoutSize(-clipLayer->offsetFromRenderer()));
    2218             // Note that we have to set this rounded rect again during the geometry update (clipLayer->offsetFromRenderer() may be stale here).
    2219             if (clipLayer->setMasksToBoundsRect(contentsClippingRect)) {
    2220                 clipLayer->setMaskLayer(nullptr);
    2221                 GraphicsLayer::clear(m_childClippingMaskLayer);
    2222                 return;
    2223             }
    2224 
    2225             if (!m_childClippingMaskLayer) {
    2226                 m_childClippingMaskLayer = createGraphicsLayer("child clipping mask");
    2227                 m_childClippingMaskLayer->setDrawsContent(true);
    2228                 m_childClippingMaskLayer->setPaintingPhase({ GraphicsLayerPaintingPhase::ChildClippingMask });
    2229                 clippingLayer()->setMaskLayer(m_childClippingMaskLayer.copyRef());
    2230             }
    2231         }
    2232     } else {
    2233         if (m_childClippingMaskLayer) {
    2234             if (hasClippingLayer())
    2235                 clippingLayer()->setMaskLayer(nullptr);
    2236             GraphicsLayer::clear(m_childClippingMaskLayer);
    2237         } else
    2238             if (hasClippingLayer())
    2239                 clippingLayer()->setMasksToBoundsRect(FloatRoundedRect(FloatRect({ }, clippingLayer()->size())));
     2219    auto needsClipMaskLayer = [&] {
     2220        return needsDescendantsClippingLayer && !GraphicsLayer::supportsRoundedClip() && is<RenderBox>(renderer()) && (renderer().style().hasBorderRadius() || renderer().style().clipPath());
     2221    };
     2222
     2223    auto* clippingLayer = this->clippingLayer();
     2224    if (needsClipMaskLayer()) {
     2225        m_childClippingMaskLayer = createGraphicsLayer("child clipping mask");
     2226        m_childClippingMaskLayer->setDrawsContent(true);
     2227        m_childClippingMaskLayer->setPaintingPhase({ GraphicsLayerPaintingPhase::ChildClippingMask });
     2228        if (clippingLayer)
     2229            clippingLayer->setMaskLayer(m_childClippingMaskLayer.copyRef());
     2230    } else if (m_childClippingMaskLayer) {
     2231        if (clippingLayer)
     2232            clippingLayer->setMaskLayer(nullptr);
     2233        GraphicsLayer::clear(m_childClippingMaskLayer);
    22402234    }
    22412235}
Note: See TracChangeset for help on using the changeset viewer.