| Differences between
and this patch
- a/Source/WebCore/ChangeLog +35 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2021-07-07  Cameron McCormack  <heycam@apple.com>
2
3
        Stop GraphicsLayerCA::recursiveCommitChanges recursion once cMaxLayerTreeDepth is reached
4
        https://bugs.webkit.org/show_bug.cgi?id=227738
5
        <rdar://42584284>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        To avoid stack overflow in some configurations, stop
10
        recursiveCommitChange recursion when we reach the same level that we
11
        stop hooking up PlatformCALayers. This will leave GraphicsLayerCAs in
12
        the tree with m_uncommittedChanges, but if we ever do another call to
13
        recursiveCommitChange where the GraphicsLayerCA is now at an
14
        appropriate depth (because some ancestors lost their structural
15
        layers, for example), then we'll process the uncommitted changes at
16
        that point.
17
18
        Pull up the increment of commitState.treeDepth from
19
        commitLayerChangesBeforeSublayers to recursiveCommitChanges so that
20
        the commitLayerChangesBeforeSublayers call for a mask layer doesn't
21
        contribute to the depth count.
22
23
        Use structuralLayerPurpose() rather than null-checking
24
        m_structuralLayer to determine whether we count an additional depth
25
        level, since m_structuralLayer reflects whether we already have a
26
        structural layer (which may or may not go away), and
27
        structuralLayerPurpose() can tell us whether we will have a structural
28
        layer.
29
30
        Test: fast/layers/deep-layer-update.html
31
32
        * platform/graphics/ca/GraphicsLayerCA.cpp:
33
        (WebCore::GraphicsLayerCA::recursiveCommitChanges):
34
        (WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
35
1
2021-07-07  Cameron McCormack  <heycam@apple.com>
36
2021-07-07  Cameron McCormack  <heycam@apple.com>
2
37
3
        Add logging for GraphicsLayerCA::m_uncommittedChanges
38
        Add logging for GraphicsLayerCA::m_uncommittedChanges
- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp -12 / +12 lines
Lines 1648-1655 bool GraphicsLayerCA::needsCommit(const CommitState& commitState) a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp_sec1
1648
    return false;
1648
    return false;
1649
}
1649
}
1650
1650
1651
// rootRelativeTransformForScaling is a transform from the root, but for layers with transform animations, it cherry-picked the state of the
1652
// animation that contributes maximally to the scale (on every layer with animations down the hierarchy).
1653
void GraphicsLayerCA::recursiveCommitChanges(CommitState& commitState, const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale)
1651
void GraphicsLayerCA::recursiveCommitChanges(CommitState& commitState, const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale)
1654
{
1652
{
1655
    if (!needsCommit(commitState))
1653
    if (!needsCommit(commitState))
Lines 1658-1663 void GraphicsLayerCA::recursiveCommitChanges(CommitState& commitState, const Tra a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp_sec2
1658
    TransformState localState = state;
1656
    TransformState localState = state;
1659
    CommitState childCommitState = commitState;
1657
    CommitState childCommitState = commitState;
1660
1658
1659
    ++childCommitState.treeDepth;
1660
    if (structuralLayerPurpose() != NoStructuralLayer)
1661
        ++childCommitState.treeDepth;
1662
1661
    bool affectedByTransformAnimation = commitState.ancestorHasTransformAnimation;
1663
    bool affectedByTransformAnimation = commitState.ancestorHasTransformAnimation;
1662
1664
1663
    bool accumulateTransform = accumulatesTransform(*this);
1665
    bool accumulateTransform = accumulatesTransform(*this);
Lines 1734-1746 void GraphicsLayerCA::recursiveCommitChanges(CommitState& commitState, const Tra a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp_sec3
1734
    }
1736
    }
1735
1737
1736
    bool hasDescendantsWithRunningTransformAnimations = false;
1738
    bool hasDescendantsWithRunningTransformAnimations = false;
1737
    
1738
    for (auto& layer : children()) {
1739
        auto& currentChild = downcast<GraphicsLayerCA>(layer.get());
1740
        currentChild.recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
1741
1739
1742
        if (currentChild.isRunningTransformAnimation() || currentChild.hasDescendantsWithRunningTransformAnimations())
1740
    if (childCommitState.treeDepth <= cMaxLayerTreeDepth) {
1743
            hasDescendantsWithRunningTransformAnimations = true;
1741
        for (auto& layer : children()) {
1742
            auto& currentChild = downcast<GraphicsLayerCA>(layer.get());
1743
            currentChild.recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
1744
1745
            if (currentChild.isRunningTransformAnimation() || currentChild.hasDescendantsWithRunningTransformAnimations())
1746
                hasDescendantsWithRunningTransformAnimations = true;
1747
        }
1744
    }
1748
    }
1745
1749
1746
    commitState.totalBackdropFilterArea = childCommitState.totalBackdropFilterArea;
1750
    commitState.totalBackdropFilterArea = childCommitState.totalBackdropFilterArea;
Lines 1858-1867 void GraphicsLayerCA::commitLayerChangesBeforeSublayers(CommitState& commitState a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp_sec4
1858
{
1862
{
1859
    SetForScope<bool> committingChangesChange(m_isCommittingChanges, true);
1863
    SetForScope<bool> committingChangesChange(m_isCommittingChanges, true);
1860
1864
1861
    ++commitState.treeDepth;
1862
    if (m_structuralLayer)
1863
        ++commitState.treeDepth;
1864
1865
    if (!m_uncommittedChanges) {
1865
    if (!m_uncommittedChanges) {
1866
        // Ensure that we cap layer depth in commitLayerChangesAfterSublayers().
1866
        // Ensure that we cap layer depth in commitLayerChangesAfterSublayers().
1867
        if (commitState.treeDepth > cMaxLayerTreeDepth)
1867
        if (commitState.treeDepth > cMaxLayerTreeDepth)
- a/LayoutTests/ChangeLog +14 lines
Lines 1-3 a/LayoutTests/ChangeLog_sec1
1
2021-07-07  Cameron McCormack  <heycam@apple.com>
2
3
        Stop GraphicsLayerCA::recursiveCommitChanges recursion once cMaxLayerTreeDepth is reached
4
        https://bugs.webkit.org/show_bug.cgi?id=227738
5
        <rdar://42584284>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Add a test that changes made to GraphicsLayerCAs that are too deep
10
        in the tree will be committed if they later become not too deep.
11
12
        * fast/layers/deep-layer-update-expected.html: Added.
13
        * fast/layers/deep-layer-update.html: Added.
14
1
2021-07-04  Rob Buis  <rbuis@igalia.com>
15
2021-07-04  Rob Buis  <rbuis@igalia.com>
2
16
3
        Resync web-platform-tests/css/css-sizing/aspect-ratio from upstream
17
        Resync web-platform-tests/css/css-sizing/aspect-ratio from upstream
- a/LayoutTests/fast/layers/deep-layer-update-expected.html +5 lines
Line 0 a/LayoutTests/fast/layers/deep-layer-update-expected.html_sec1
1
<!DOCTYPE html>
2
<style>
3
div { will-change: transform; opacity: 0.5; }
4
</style>
5
<div>Test passes if this text is shown at 0.5 opacity.</div>
- a/LayoutTests/fast/layers/deep-layer-update.html +53 lines
Line 0 a/LayoutTests/fast/layers/deep-layer-update.html_sec1
1
<!DOCTYPE html>
2
<style>
3
.induce-structural-layers div { transform: translateZ(0); transform-style: preserve-3d; }
4
div { will-change: transform; }
5
</style>
6
<body class="induce-structural-layers" onload="run()">
7
<script>
8
const cMaxLayerTreeDepth = 128; // from GraphicsLayerCA.cpp
9
10
function buildDeepLayerTree() {
11
    let innermostDiv = document.createElement("div");
12
    innermostDiv.textContent = "Test passes if this text is shown at 0.5 opacity.";
13
14
    // Set up a layer tree that, if each div has a structural layer, has a depth
15
    // that is greater than cMaxLayerTreeDepth, but without any structural layers,
16
    // will be within the depth limit.
17
    let e = innermostDiv;
18
    for (let i = 0; i < cMaxLayerTreeDepth * 0.75; ++i) {
19
        let f = document.createElement("div");
20
        f.append(e);
21
        e = f;
22
    }
23
    document.body.append(e);
24
25
    return innermostDiv;
26
}
27
28
function removeStructuralLayers() {
29
    document.body.className = '';
30
}
31
32
function nextAnimationFrame() {
33
    return new Promise(requestAnimationFrame);
34
}
35
36
async function run() {
37
    if (window.testRunner)
38
        testRunner.waitUntilDone();
39
40
    let innermostDiv = buildDeepLayerTree();
41
    await nextAnimationFrame();
42
43
    innermostDiv.style.opacity = 0.5; // Change to a layer that is too deep.
44
    await nextAnimationFrame();
45
46
    removeStructuralLayers();
47
    await nextAnimationFrame();
48
49
    document.documentElement.className = '';
50
    if (window.testRunner)
51
        testRunner.notifyDone();
52
}
53
</script>

Return to Bug 227738