Changeset 266901 in webkit


Ignore:
Timestamp:
Sep 10, 2020 5:32:46 PM (4 years ago)
Author:
Alan Bujtas
Message:

[Repaint] RenderLayerModelObject::styleWillChange may issue redundant repaint
https://bugs.webkit.org/show_bug.cgi?id=216374
<rdar://problem/68657490>

Reviewed by Simon Fraser.

Source/WebCore:

Move the repaintIncludingDescendants() calls to repaintBeforeStyleChange() to avoid redundant repaints on the same renderer.

  • rendering/RenderElement.cpp:

(WebCore::RenderElement::repaintBeforeStyleChange):

  • rendering/RenderLayerModelObject.cpp:

(WebCore::RenderLayerModelObject::styleWillChange):

LayoutTests:

  • css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt:
  • platform/ios/css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt:
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r266897 r266901  
     12020-09-10  Zalan Bujtas  <zalan@apple.com>
     2
     3        [Repaint] RenderLayerModelObject::styleWillChange may issue redundant repaint
     4        https://bugs.webkit.org/show_bug.cgi?id=216374
     5        <rdar://problem/68657490>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt:
     10        * platform/ios/css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt:
     11
    1122020-09-10  Karl Rackler  <rackler@apple.com>
    213
  • trunk/LayoutTests/css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt

    r258336 r266901  
    2020  (rect 48 526 60 60)
    2121  (rect 48 408 60 60)
    22   (rect 48 408 60 60)
    2322  (rect 48 644 60 60)
    2423  (rect 68 644 60 60)
  • trunk/LayoutTests/platform/ios/css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt

    r258336 r266901  
    2020  (rect 48 536 60 60)
    2121  (rect 48 416 60 60)
    22   (rect 48 416 60 60)
    2322  (rect 48 656 60 60)
    2423  (rect 68 656 60 60)
  • trunk/Source/WebCore/ChangeLog

    r266899 r266901  
     12020-09-10  Zalan Bujtas  <zalan@apple.com>
     2
     3        [Repaint] RenderLayerModelObject::styleWillChange may issue redundant repaint
     4        https://bugs.webkit.org/show_bug.cgi?id=216374
     5        <rdar://problem/68657490>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Move the repaintIncludingDescendants() calls to repaintBeforeStyleChange() to avoid redundant repaints on the same renderer.
     10
     11        * rendering/RenderElement.cpp:
     12        (WebCore::RenderElement::repaintBeforeStyleChange):
     13        * rendering/RenderLayerModelObject.cpp:
     14        (WebCore::RenderLayerModelObject::styleWillChange):
     15
    1162020-09-10  Wenson Hsieh  <wenson_hsieh@apple.com>
    217
  • trunk/Source/WebCore/rendering/RenderElement.cpp

    r266818 r266901  
    387387        return false;
    388388    }
    389     auto shouldRepaintBeforeStyleChange = [&] {
     389    enum class RequiredRepaint { None, RendererOnly, RendererAndDescendantsRenderersWithLayers };
     390    auto shouldRepaintBeforeStyleChange = [&]() -> RequiredRepaint {
    390391        if (!parent()) {
    391392            // Can't resolve absolute coordinates.
    392             return false;
     393            return RequiredRepaint::None;
     394        }
     395        if (is<RenderLayerModelObject>(this) && hasLayer()) {
     396            if (diff == StyleDifference::RepaintLayer)
     397                return RequiredRepaint::RendererAndDescendantsRenderersWithLayers;
     398            if (diff == StyleDifference::Layout || diff == StyleDifference::SimplifiedLayout) {
     399                // Certain style changes require layer repaint, since the layer could end up being destroyed.
     400                auto layerMayGetDestroyed = oldStyle.position() != newStyle.position()
     401                    || oldStyle.usedZIndex() != newStyle.usedZIndex()
     402                    || oldStyle.hasAutoUsedZIndex() != newStyle.hasAutoUsedZIndex()
     403                    || oldStyle.clip() != newStyle.clip()
     404                    || oldStyle.hasClip() != newStyle.hasClip()
     405                    || oldStyle.opacity() != newStyle.opacity()
     406                    || oldStyle.transform() != newStyle.transform()
     407                    || oldStyle.filter() != newStyle.filter();
     408                if (layerMayGetDestroyed)
     409                    return RequiredRepaint::RendererAndDescendantsRenderersWithLayers;
     410            }
    393411        }
    394412        if (shouldRepaintForStyleDifference(diff))
    395             return true;
     413            return RequiredRepaint::RendererOnly;
    396414        if (newStyle.outlineSize() < oldStyle.outlineSize())
    397             return true;
     415            return RequiredRepaint::RendererOnly;
    398416        if (is<RenderLayerModelObject>(*this)) {
    399417            // If we don't have a layer yet, but we are going to get one because of transform or opacity, then we need to repaint the old position of the object.
     
    401419            bool willHaveLayer = newStyle.hasTransform() || newStyle.opacity() < 1 || newStyle.hasFilter() || newStyle.hasBackdropFilter();
    402420            if (!hasLayer && willHaveLayer)
    403                 return true;
     421                return RequiredRepaint::RendererOnly;
    404422        }
    405423        if (is<RenderBox>(*this)) {
    406424            if (diff == StyleDifference::Layout && oldStyle.position() != newStyle.position() && oldStyle.position() == PositionType::Static)
    407                 return true;
     425                return RequiredRepaint::RendererOnly;
    408426        }
    409427        if (diff > StyleDifference::RepaintLayer && oldStyle.visibility() != newStyle.visibility()) {
     
    411429                auto rendererWillBeHidden = newStyle.visibility() != Visibility::Visible;
    412430                if (rendererWillBeHidden && enclosingLayer->hasVisibleContent() && (this == &enclosingLayer->renderer() || enclosingLayer->renderer().style().visibility() != Visibility::Visible))
    413                     return true;
     431                    return RequiredRepaint::RendererOnly;
    414432            }
    415433        }
    416         return false;
     434        return RequiredRepaint::None;
    417435    }();
    418     if (shouldRepaintBeforeStyleChange) {
     436    if (shouldRepaintBeforeStyleChange == RequiredRepaint::RendererAndDescendantsRenderersWithLayers) {
     437        ASSERT(hasLayer());
     438        downcast<RenderLayerModelObject>(*this).layer()->repaintIncludingDescendants();
     439        return true;
     440    }
     441    if (shouldRepaintBeforeStyleChange == RequiredRepaint::RendererOnly) {
    419442        repaint();
    420443        return true;
  • trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp

    r266803 r266901  
    114114        s_layerWasSelfPainting = layer()->isSelfPaintingLayer();
    115115
    116     // If our z-index changes value or our visibility changes,
    117     // we need to dirty our stacking context's z-order list.
    118     const RenderStyle* oldStyle = hasInitializedStyle() ? &style() : nullptr;
    119     if (oldStyle) {
    120         if (parent()) {
    121             // Do a repaint with the old style first, e.g., for example if we go from
    122             // having an outline to not having an outline.
    123             if (diff == StyleDifference::RepaintLayer) {
    124                 layer()->repaintIncludingDescendants();
    125                 if (!(oldStyle->clip() == newStyle.clip()))
    126                     layer()->clearClipRectsIncludingDescendants();
    127             }
    128         }
    129 
    130         if (diff == StyleDifference::Layout || diff == StyleDifference::SimplifiedLayout) {
    131             // When a layout hint happens, we do a repaint of the layer, since the layer could end up being destroyed.
    132             if (hasLayer()) {
    133                 if (oldStyle->position() != newStyle.position()
    134                     || oldStyle->usedZIndex() != newStyle.usedZIndex()
    135                     || oldStyle->hasAutoUsedZIndex() != newStyle.hasAutoUsedZIndex()
    136                     || !(oldStyle->clip() == newStyle.clip())
    137                     || oldStyle->hasClip() != newStyle.hasClip()
    138                     || oldStyle->opacity() != newStyle.opacity()
    139                     || oldStyle->transform() != newStyle.transform()
    140                     || oldStyle->filter() != newStyle.filter()
    141                     )
    142                 layer()->repaintIncludingDescendants();
    143             }
    144         }
    145     }
    146 
     116    auto* oldStyle = hasInitializedStyle() ? &style() : nullptr;
     117    if (diff == StyleDifference::RepaintLayer && parent() && oldStyle && oldStyle->clip() != newStyle.clip())
     118        layer()->clearClipRectsIncludingDescendants();
    147119    RenderElement::styleWillChange(diff, newStyle);
    148120}
Note: See TracChangeset for help on using the changeset viewer.