Changeset 215393 in webkit


Ignore:
Timestamp:
Apr 15, 2017 6:15:37 AM (7 years ago)
Author:
Antti Koivisto
Message:

GraphicsLayerCA::recursiveCommitChanges should not descend into subtrees without changes
https://bugs.webkit.org/show_bug.cgi?id=170851

Reviewed by Simon Fraser.

With lots of layers this can be very slow as it always traverses the entire layer tree.
For example GIF animations on tumblr.com trigger expensive commits where almost nothing changes.

This patch adds m_hasDescendantsWithUncommittedChanges bit to GraphicsLayerCA. With this
we can avoid descending to branches without changes when committing.

  • platform/graphics/ca/GraphicsLayerCA.cpp:

(WebCore::GraphicsLayerCA::setVisibleAndCoverageRects):

Do all setting of m_uncommittedChanges bits via addUncommittedChanges function.

(WebCore::GraphicsLayerCA::recursiveCommitChanges):

Bail out if neither the current layer nor any of its descendants have any uncommited changes
and none of the ancestors had changes.

(WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
(WebCore::GraphicsLayerCA::ensureStructuralLayer):
(WebCore::GraphicsLayerCA::changeLayerTypeTo):
(WebCore::GraphicsLayerCA::addUncommittedChanges):

Set m_hasDescendantsWithUncommittedChanges bit in ancestors when mutating m_uncommittedChanges.

(WebCore::GraphicsLayerCA::noteLayerPropertyChanged):

  • platform/graphics/ca/GraphicsLayerCA.h:

(WebCore::RenderLayerCompositor::frameViewDidScroll):

Tell the scrolling layer that it needs to recompute coverage.
This also schedules a layer flush so no need to do that separately.

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r215392 r215393  
     12017-04-14  Antti Koivisto  <antti@apple.com>
     2
     3        GraphicsLayerCA::recursiveCommitChanges should not descend into subtrees without changes
     4        https://bugs.webkit.org/show_bug.cgi?id=170851
     5
     6        Reviewed by Simon Fraser.
     7
     8        With lots of layers this can be very slow as it always traverses the entire layer tree.
     9        For example GIF animations on tumblr.com trigger expensive commits where almost nothing changes.
     10
     11        This patch adds m_hasDescendantsWithUncommittedChanges bit to GraphicsLayerCA. With this
     12        we can avoid descending to branches without changes when committing.
     13
     14        * platform/graphics/ca/GraphicsLayerCA.cpp:
     15        (WebCore::GraphicsLayerCA::setVisibleAndCoverageRects):
     16
     17            Do all setting of m_uncommittedChanges bits via addUncommittedChanges function.
     18
     19        (WebCore::GraphicsLayerCA::recursiveCommitChanges):
     20
     21            Bail out if neither the current layer nor any of its descendants have any uncommited changes
     22            and none of the ancestors had changes.
     23
     24        (WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
     25        (WebCore::GraphicsLayerCA::ensureStructuralLayer):
     26        (WebCore::GraphicsLayerCA::changeLayerTypeTo):
     27        (WebCore::GraphicsLayerCA::addUncommittedChanges):
     28
     29            Set m_hasDescendantsWithUncommittedChanges bit in ancestors when mutating m_uncommittedChanges.
     30
     31        (WebCore::GraphicsLayerCA::noteLayerPropertyChanged):
     32        * platform/graphics/ca/GraphicsLayerCA.h:
     33        (WebCore::RenderLayerCompositor::frameViewDidScroll):
     34
     35            Tell the scrolling layer that it needs to recompute coverage.
     36            This also schedules a layer flush so no need to do that separately.
     37
    1382017-04-15  Wenson Hsieh  <wenson_hsieh@apple.com>
    239
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.h

    r213466 r215393  
    566566    virtual bool isCoordinatedGraphicsLayer() const { return false; }
    567567
     568    virtual void setScrollPositionChanged() { }
     569
    568570    static void traverse(GraphicsLayer&, std::function<void (GraphicsLayer&)>);
    569571
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp

    r213466 r215393  
    12421242}
    12431243
     1244void GraphicsLayerCA::setScrollPositionChanged()
     1245{
     1246    // This invalidates the layer so the coverage rects gets updated.
     1247    noteLayerPropertyChanged(ScrollPositionChanged);
     1248}
     1249
    12441250TransformationMatrix GraphicsLayerCA::layerTransform(const FloatPoint& position, const TransformationMatrix* customTransform) const
    12451251{
     
    13551361    bool intersectsCoverageRect = isViewportConstrained || rects.coverageRect.intersects(FloatRect(m_boundsOrigin, size()));
    13561362    if (intersectsCoverageRect != m_intersectsCoverageRect) {
    1357         m_uncommittedChanges |= CoverageRectChanged;
     1363        addUncommittedChanges(CoverageRectChanged);
    13581364        m_intersectsCoverageRect = intersectsCoverageRect;
    13591365    }
    13601366
    13611367    if (visibleRectChanged) {
    1362         m_uncommittedChanges |= CoverageRectChanged;
     1368        addUncommittedChanges(CoverageRectChanged);
    13631369        m_visibleRect = rects.visibleRect;
    13641370    }
    13651371
    13661372    if (coverageRectChanged) {
    1367         m_uncommittedChanges |= CoverageRectChanged;
     1373        addUncommittedChanges(CoverageRectChanged);
    13681374        m_coverageRect = rects.coverageRect;
    13691375    }
     
    13741380void GraphicsLayerCA::recursiveCommitChanges(const CommitState& commitState, const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale)
    13751381{
     1382    if (!commitState.ancestorHadChanges && !m_uncommittedChanges && !hasDescendantsWithUncommittedChanges())
     1383        return;
     1384
    13761385    TransformState localState = state;
    13771386    CommitState childCommitState = commitState;
     1387
    13781388    bool affectedByTransformAnimation = commitState.ancestorHasTransformAnimation;
    13791389
     
    14121422
    14131423    bool hadChanges = m_uncommittedChanges;
    1414    
     1424
     1425    // FIXME: This could be more fine-grained. Only some types of changes have impact on sublayers.
     1426    if (!childCommitState.ancestorHadChanges)
     1427        childCommitState.ancestorHadChanges = hadChanges;
     1428
    14151429    if (appliesPageScale()) {
    14161430        pageScaleFactor = this->pageScaleFactor();
     
    14501464    if (GraphicsLayerCA* maskLayer = downcast<GraphicsLayerCA>(m_maskLayer))
    14511465        maskLayer->commitLayerChangesAfterSublayers(childCommitState);
     1466
     1467    setHasDescendantsWithUncommittedChanges(false);
    14521468
    14531469    bool hadDirtyRects = m_uncommittedChanges & DirtyRectsChanged;
     
    15651581        // Ensure that we cap layer depth in commitLayerChangesAfterSublayers().
    15661582        if (commitState.treeDepth > cMaxLayerTreeDepth)
    1567             m_uncommittedChanges |= ChildrenChanged;
     1583            addUncommittedChanges(ChildrenChanged);
    15681584    }
    15691585
     
    17071723    // Ensure that we cap layer depth in commitLayerChangesAfterSublayers().
    17081724    if (commitState.treeDepth > cMaxLayerTreeDepth)
    1709         m_uncommittedChanges |= ChildrenChanged;
     1725        addUncommittedChanges(ChildrenChanged);
    17101726}
    17111727
     
    21172133            m_structuralLayer = nullptr;
    21182134
    2119             m_uncommittedChanges |= structuralLayerChangeFlags;
     2135            addUncommittedChanges(structuralLayerChangeFlags);
    21202136        }
    21212137        return;
     
    21452161        return;
    21462162   
    2147     m_uncommittedChanges |= structuralLayerChangeFlags;
     2163    addUncommittedChanges(structuralLayerChangeFlags);
    21482164
    21492165    // We've changed the layer that our parent added to its sublayer list, so tell it to update
     
    36163632    }
    36173633
    3618     m_uncommittedChanges |= ChildrenChanged
     3634    addUncommittedChanges(ChildrenChanged
    36193635        | GeometryChanged
    36203636        | TransformChanged
     
    36323648        | OpacityChanged
    36333649        | NameChanged
    3634         | DebugIndicatorsChanged;
     3650        | DebugIndicatorsChanged);
    36353651   
    36363652    if (isTiledLayer)
    3637         m_uncommittedChanges |= CoverageRectChanged;
     3653        addUncommittedChanges(CoverageRectChanged);
    36383654
    36393655    moveAnimations(oldLayer.get(), m_layer.get());
     
    40094025}
    40104026
     4027void GraphicsLayerCA::addUncommittedChanges(LayerChangeFlags flags)
     4028{
     4029    m_uncommittedChanges |= flags;
     4030
     4031    if (m_isCommittingChanges)
     4032        return;
     4033
     4034    for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
     4035        auto& ancestorCA = static_cast<GraphicsLayerCA&>(*ancestor);
     4036        ASSERT(!ancestorCA.m_isCommittingChanges);
     4037        if (ancestorCA.hasDescendantsWithUncommittedChanges())
     4038            return;
     4039        ancestorCA.setHasDescendantsWithUncommittedChanges(true);
     4040    }
     4041}
     4042
     4043void GraphicsLayerCA::setHasDescendantsWithUncommittedChanges(bool value)
     4044{
     4045    m_hasDescendantsWithUncommittedChanges = value;
     4046}
     4047
    40114048void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags, ScheduleFlushOrNot scheduleFlush)
    40124049{
     
    40144051    bool oldCanThrottleLayerFlush = canThrottleLayerFlush();
    40154052
    4016     m_uncommittedChanges |= flags;
     4053    addUncommittedChanges(flags);
    40174054
    40184055    if (scheduleFlush == ScheduleFlush) {
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h

    r212776 r215393  
    153153    struct CommitState {
    154154        int treeDepth { 0 };
     155        bool ancestorHadChanges { false };
    155156        bool ancestorHasTransformAnimation { false };
    156157        bool ancestorIsViewportConstrained { false };
     
    164165
    165166    WEBCORE_EXPORT TiledBacking* tiledBacking() const override;
     167
     168    WEBCORE_EXPORT void setScrollPositionChanged() override;
    166169
    167170protected:
     
    495498        WindRuleChanged                         = 1LLU << 37,
    496499        UserInteractionEnabledChanged           = 1LLU << 38,
     500        ScrollPositionChanged                   = 1LLU << 39,
    497501    };
    498502    typedef uint64_t LayerChangeFlags;
     503    void addUncommittedChanges(LayerChangeFlags);
     504    bool hasDescendantsWithUncommittedChanges() const { return m_hasDescendantsWithUncommittedChanges; }
     505    void setHasDescendantsWithUncommittedChanges(bool);
    499506    enum ScheduleFlushOrNot { ScheduleFlush, DontScheduleFlush };
    500507    void noteLayerPropertyChanged(LayerChangeFlags, ScheduleFlushOrNot = ScheduleFlush);
     
    597604    LayerChangeFlags m_uncommittedChanges { CoverageRectChanged };
    598605#endif
     606    bool m_hasDescendantsWithUncommittedChanges { false };
    599607
    600608    bool m_isCommittingChanges { false };
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r215347 r215393  
    17571757    // it will also manage updating the scroll layer position.
    17581758    if (hasCoordinatedScrolling()) {
    1759         // We have to schedule a flush in order for the main TiledBacking to update its tile coverage.
    1760         scheduleLayerFlushNow();
     1759        m_scrollLayer->setScrollPositionChanged();
    17611760        return;
    17621761    }
Note: See TracChangeset for help on using the changeset viewer.