| Differences between
and this patch
- a/Source/WebCore/ChangeLog +41 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2018-07-20  Simon Fraser  <simon.fraser@apple.com>
2
3
        Be more conservative with compositing layer creation when memory is low
4
        https://bugs.webkit.org/show_bug.cgi?id=187866
5
6
        Reviewed by NOBODY (OOPS!).
7
        
8
        When the amount of free memory is below some TBD limit, be more conservative in making
9
        compositing layers. We can avoid compositing for these situations:
10
        1. Layers with 3D transforms which are affine (like translateZ(0)).
11
        2. Layers with will-change
12
        3. Layers for canvases (other than WebGL/WebGPU)
13
14
        No new tests yet (OOPS!).
15
16
        * platform/graphics/transforms/Matrix3DTransformOperation.cpp:
17
        (WebCore::Matrix3DTransformOperation::isRepresentableIn2D const):
18
        * platform/graphics/transforms/Matrix3DTransformOperation.h:
19
        * platform/graphics/transforms/PerspectiveTransformOperation.h:
20
        * platform/graphics/transforms/RotateTransformOperation.h:
21
        * platform/graphics/transforms/ScaleTransformOperation.h:
22
        * platform/graphics/transforms/TransformOperation.h:
23
        (WebCore::TransformOperation::isRepresentableIn2D const):
24
        * platform/graphics/transforms/TransformOperations.h:
25
        (WebCore::TransformOperations::has3DOperation const):
26
        (WebCore::TransformOperations::isRepresentableIn2D const):
27
        * platform/graphics/transforms/TranslateTransformOperation.h:
28
        * rendering/RenderLayerBacking.cpp:
29
        (WebCore::RenderLayerBacking::updateGeometry):
30
        * rendering/RenderLayerCompositor.cpp:
31
        (WebCore::RenderLayerCompositor::cacheAcceleratedCompositingFlags):
32
        (WebCore::RenderLayerCompositor::updateCompositingLayers):
33
        (WebCore::RenderLayerCompositor::requiresCompositingForTransform const):
34
        (WebCore::RenderLayerCompositor::requiresCompositingForVideo const):
35
        (WebCore::RenderLayerCompositor::requiresCompositingForCanvas const):
36
        (WebCore::RenderLayerCompositor::requiresCompositingForPlugin const):
37
        (WebCore::RenderLayerCompositor::requiresCompositingForWillChange const):
38
        (WebCore::RenderLayerCompositor::needsFixedRootBackgroundLayer const):
39
        (WebCore::operator<<):
40
        * rendering/RenderLayerCompositor.h:
41
1
2018-07-19  Antoine Quint  <graouts@apple.com>
42
2018-07-19  Antoine Quint  <graouts@apple.com>
2
43
3
        Flaky crash in AnimationTimeline::cancelOrRemoveDeclarativeAnimation
44
        Flaky crash in AnimationTimeline::cancelOrRemoveDeclarativeAnimation
- a/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp +5 lines
Lines 61-66 Ref<TransformOperation> Matrix3DTransformOperation::blend(const TransformOperati a/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp_sec1
61
    return createOperation(toT, fromT, progress);
61
    return createOperation(toT, fromT, progress);
62
}
62
}
63
63
64
bool Matrix3DTransformOperation::isRepresentableIn2D() const
65
{
66
    return m_matrix.isAffine();
67
}
68
64
void Matrix3DTransformOperation::dump(TextStream& ts) const
69
void Matrix3DTransformOperation::dump(TextStream& ts) const
65
{
70
{
66
    ts << type() << "(" << m_matrix << ")";
71
    ts << type() << "(" << m_matrix << ")";
- a/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h -1 / +3 lines
Lines 46-52 public: a/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h_sec1
46
46
47
private:    
47
private:    
48
    bool isIdentity() const override { return m_matrix.isIdentity(); }
48
    bool isIdentity() const override { return m_matrix.isIdentity(); }
49
    bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
49
    bool isAffectedByTransformOrigin() const final { return !isIdentity(); }
50
51
    bool isRepresentableIn2D() const final;
50
52
51
    bool operator==(const TransformOperation&) const override;
53
    bool operator==(const TransformOperation&) const override;
52
54
- a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h +1 lines
Lines 49-54 public: a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h_sec1
49
private:
49
private:
50
    bool isIdentity() const override { return !floatValueForLength(m_p, 1); }
50
    bool isIdentity() const override { return !floatValueForLength(m_p, 1); }
51
    bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
51
    bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
52
    bool isRepresentableIn2D() const final { return false; }
52
53
53
    bool operator==(const TransformOperation&) const override;
54
    bool operator==(const TransformOperation&) const override;
54
55
- a/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h +1 lines
Lines 54-59 public: a/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h_sec1
54
private:
54
private:
55
    bool isIdentity() const override { return m_angle == 0; }
55
    bool isIdentity() const override { return m_angle == 0; }
56
    bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
56
    bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
57
    bool isRepresentableIn2D() const final { return (!m_x && !m_y) || !m_angle; }
57
58
58
    bool operator==(const TransformOperation&) const override;
59
    bool operator==(const TransformOperation&) const override;
59
60
- a/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h +1 lines
Lines 53-58 public: a/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h_sec1
53
private:
53
private:
54
    bool isIdentity() const override { return m_x == 1 &&  m_y == 1 &&  m_z == 1; }
54
    bool isIdentity() const override { return m_x == 1 &&  m_y == 1 &&  m_z == 1; }
55
    bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
55
    bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
56
    bool isRepresentableIn2D() const final { return m_z == 1; }
56
57
57
    bool operator==(const TransformOperation&) const override;
58
    bool operator==(const TransformOperation&) const override;
58
59
- a/Source/WebCore/platform/graphics/transforms/TransformOperation.h +2 lines
Lines 87-92 public: a/Source/WebCore/platform/graphics/transforms/TransformOperation.h_sec1
87
               opType == MATRIX_3D ||
87
               opType == MATRIX_3D ||
88
               opType == PERSPECTIVE;
88
               opType == PERSPECTIVE;
89
    }
89
    }
90
    
91
    virtual bool isRepresentableIn2D() const { return true; }
90
92
91
    bool isRotateTransformOperationType() const
93
    bool isRotateTransformOperationType() const
92
    {
94
    {
- a/Source/WebCore/platform/graphics/transforms/TransformOperations.h -6 / +14 lines
Lines 22-29 a/Source/WebCore/platform/graphics/transforms/TransformOperations.h_sec1
22
 *
22
 *
23
 */
23
 */
24
24
25
#ifndef TransformOperations_h
25
#pragma once
26
#define TransformOperations_h
27
26
28
#include "LayoutSize.h"
27
#include "LayoutSize.h"
29
#include "TransformOperation.h"
28
#include "TransformOperation.h"
Lines 53-64 public: a/Source/WebCore/platform/graphics/transforms/TransformOperations.h_sec2
53
    // values describe affine transforms)
52
    // values describe affine transforms)
54
    bool has3DOperation() const
53
    bool has3DOperation() const
55
    {
54
    {
56
        for (unsigned i = 0; i < m_operations.size(); ++i)
55
        for (const auto& operation : m_operations) {
57
            if (m_operations[i]->is3DOperation())
56
            if (operation->is3DOperation())
58
                return true;
57
                return true;
58
        }
59
        return false;
59
        return false;
60
    }
60
    }
61
    
61
62
    bool isRepresentableIn2D() const
63
    {
64
        for (const auto& operation : m_operations) {
65
            if (!operation->isRepresentableIn2D())
66
                return false;
67
        }
68
        return true;
69
    }
70
62
    bool operationsMatch(const TransformOperations&) const;
71
    bool operationsMatch(const TransformOperations&) const;
63
    
72
    
64
    void clear()
73
    void clear()
Lines 86-89 WTF::TextStream& operator<<(WTF::TextStream&, const TransformOperations&); a/Source/WebCore/platform/graphics/transforms/TransformOperations.h_sec3
86
95
87
} // namespace WebCore
96
} // namespace WebCore
88
97
89
#endif // TransformOperations_h
- a/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h +2 lines
Lines 59-64 public: a/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h_sec1
59
private:
59
private:
60
    bool isIdentity() const override { return !floatValueForLength(m_x, 1) && !floatValueForLength(m_y, 1) && !floatValueForLength(m_z, 1); }
60
    bool isIdentity() const override { return !floatValueForLength(m_x, 1) && !floatValueForLength(m_y, 1) && !floatValueForLength(m_z, 1); }
61
61
62
    bool isRepresentableIn2D() const final { return m_z.isZero(); }
63
62
    bool operator==(const TransformOperation&) const override;
64
    bool operator==(const TransformOperation&) const override;
63
65
64
    bool apply(TransformationMatrix& transform, const FloatSize& borderBoxSize) const override
66
    bool apply(TransformationMatrix& transform, const FloatSize& borderBoxSize) const override
- a/Source/WebCore/rendering/RenderLayerBacking.cpp -2 lines
Lines 950-957 LayoutRect RenderLayerBacking::computeParentGraphicsLayerRect(RenderLayer* compo a/Source/WebCore/rendering/RenderLayerBacking.cpp_sec1
950
950
951
void RenderLayerBacking::updateGeometry()
951
void RenderLayerBacking::updateGeometry()
952
{
952
{
953
    LOG_WITH_STREAM(Compositing, stream << "updateGeometry " << m_owningLayer);
954
955
    // If we haven't built z-order lists yet, wait until later.
953
    // If we haven't built z-order lists yet, wait until later.
956
    if (m_owningLayer.isStackingContainer() && m_owningLayer.m_zOrderListsDirty)
954
    if (m_owningLayer.isStackingContainer() && m_owningLayer.m_zOrderListsDirty)
957
        return;
955
        return;
- a/Source/WebCore/rendering/RenderLayerCompositor.cpp -21 / +53 lines
Lines 346-351 void RenderLayerCompositor::cacheAcceleratedCompositingFlags() a/Source/WebCore/rendering/RenderLayerCompositor.cpp_sec1
346
        if (m_layerForScrollCorner)
346
        if (m_layerForScrollCorner)
347
            m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
347
            m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
348
    }
348
    }
349
    
350
    // FIXME: add some hysteresis.
351
    m_compositingPolicy = CompositingPolicy::Conservative; // MemoryPressureHandler::singleton().isUnderMemoryPressure() ? CompositingPolicy::Conservative : CompositingPolicy::Normal;
349
}
352
}
350
353
351
void RenderLayerCompositor::cacheAcceleratedCompositingFlagsAfterLayout()
354
void RenderLayerCompositor::cacheAcceleratedCompositingFlagsAfterLayout()
Lines 732-738 bool RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update a/Source/WebCore/rendering/RenderLayerCompositor.cpp_sec2
732
735
733
        auto& frame = m_renderView.frameView().frame();
736
        auto& frame = m_renderView.frameView().frame();
734
        bool isMainFrame = isMainFrameCompositor();
737
        bool isMainFrame = isMainFrameCompositor();
735
        LOG(Compositing, "\nUpdate %d of %s.\n", m_rootLayerUpdateCount, isMainFrame ? "main frame" : frame.tree().uniqueName().string().utf8().data());
738
        LOG_WITH_STREAM(Compositing, stream << "\nUpdate " << m_rootLayerUpdateCount << " of " << (isMainFrame ? "main frame" : frame.tree().uniqueName().string().utf8().data()) << " - compositing policy is " << m_compositingPolicy);
736
    }
739
    }
737
#endif
740
#endif
738
741
Lines 2368-2376 bool RenderLayerCompositor::requiresCompositingForTransform(RenderLayerModelObje a/Source/WebCore/rendering/RenderLayerCompositor.cpp_sec3
2368
    if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger))
2371
    if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger))
2369
        return false;
2372
        return false;
2370
2373
2374
    if (!renderer.hasTransform())
2375
        return false;
2376
    
2371
    // Note that we ask the renderer if it has a transform, because the style may have transforms,
2377
    // Note that we ask the renderer if it has a transform, because the style may have transforms,
2372
    // but the renderer may be an inline that doesn't suppport them.
2378
    // but the renderer may be an inline that doesn't suppport them.
2373
    return renderer.hasTransform() && renderer.style().transform().has3DOperation();
2379
    if (m_compositingPolicy == CompositingPolicy::Normal)
2380
        return renderer.style().transform().has3DOperation();
2381
    
2382
    switch (m_compositingPolicy) {
2383
    case CompositingPolicy::Normal:
2384
        return renderer.style().transform().has3DOperation();
2385
    case CompositingPolicy::Conservative:
2386
        return !renderer.style().transform().isRepresentableIn2D();
2387
    }
2388
    return false;
2374
}
2389
}
2375
2390
2376
bool RenderLayerCompositor::requiresCompositingForBackfaceVisibility(RenderLayerModelObject& renderer) const
2391
bool RenderLayerCompositor::requiresCompositingForBackfaceVisibility(RenderLayerModelObject& renderer) const
Lines 2396-2410 bool RenderLayerCompositor::requiresCompositingForVideo(RenderLayerModelObject& a/Source/WebCore/rendering/RenderLayerCompositor.cpp_sec4
2396
{
2411
{
2397
    if (!(m_compositingTriggers & ChromeClient::VideoTrigger))
2412
    if (!(m_compositingTriggers & ChromeClient::VideoTrigger))
2398
        return false;
2413
        return false;
2414
2399
#if ENABLE(VIDEO)
2415
#if ENABLE(VIDEO)
2400
    if (is<RenderVideo>(renderer)) {
2416
    if (!is<RenderVideo>(renderer))
2401
        auto& video = downcast<RenderVideo>(renderer);
2417
        return false;
2402
        return (video.requiresImmediateCompositing() || video.shouldDisplayVideo()) && canAccelerateVideoRendering(video);
2418
2403
    }
2419
    auto& video = downcast<RenderVideo>(renderer);
2420
    return (video.requiresImmediateCompositing() || video.shouldDisplayVideo()) && canAccelerateVideoRendering(video);
2404
#else
2421
#else
2405
    UNUSED_PARAM(renderer);
2422
    UNUSED_PARAM(renderer);
2406
#endif
2407
    return false;
2423
    return false;
2424
#endif
2408
}
2425
}
2409
2426
2410
bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject& renderer) const
2427
bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject& renderer) const
Lines 2412-2428 bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject& a/Source/WebCore/rendering/RenderLayerCompositor.cpp_sec5
2412
    if (!(m_compositingTriggers & ChromeClient::CanvasTrigger))
2429
    if (!(m_compositingTriggers & ChromeClient::CanvasTrigger))
2413
        return false;
2430
        return false;
2414
2431
2415
    if (renderer.isCanvas()) {
2432
    if (!renderer.isCanvas())
2416
#if USE(COMPOSITING_FOR_SMALL_CANVASES)
2433
        return false;
2417
        bool isCanvasLargeEnoughToForceCompositing = true;
2434
2418
#else
2435
    bool isCanvasLargeEnoughToForceCompositing = true;
2419
        auto* canvas = downcast<HTMLCanvasElement>(renderer.element());
2436
#if !USE(COMPOSITING_FOR_SMALL_CANVASES)
2420
        auto canvasArea = canvas->size().area<RecordOverflow>();
2437
    auto* canvas = downcast<HTMLCanvasElement>(renderer.element());
2421
        bool isCanvasLargeEnoughToForceCompositing = !canvasArea.hasOverflowed() && canvasArea.unsafeGet() >= canvasAreaThresholdRequiringCompositing;
2438
    auto canvasArea = canvas->size().area<RecordOverflow>();
2439
    isCanvasLargeEnoughToForceCompositing = !canvasArea.hasOverflowed() && canvasArea.unsafeGet() >= canvasAreaThresholdRequiringCompositing;
2422
#endif
2440
#endif
2423
        CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer);
2441
2424
        return compositingStrategy == CanvasAsLayerContents || (compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing);
2442
    CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer);
2425
    }
2443
    if (compositingStrategy == CanvasAsLayerContents)
2444
        return true;
2445
2446
    if (m_compositingPolicy == CompositingPolicy::Normal)
2447
        return compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing;
2426
2448
2427
    return false;
2449
    return false;
2428
}
2450
}
Lines 2432-2439 bool RenderLayerCompositor::requiresCompositingForPlugin(RenderLayerModelObject& a/Source/WebCore/rendering/RenderLayerCompositor.cpp_sec6
2432
    if (!(m_compositingTriggers & ChromeClient::PluginTrigger))
2454
    if (!(m_compositingTriggers & ChromeClient::PluginTrigger))
2433
        return false;
2455
        return false;
2434
2456
2435
    bool composite = is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
2457
    bool isCompositedPlugin = is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
2436
    if (!composite)
2458
    if (!isCompositedPlugin)
2437
        return false;
2459
        return false;
2438
2460
2439
    m_reevaluateCompositingAfterLayout = true;
2461
    m_reevaluateCompositingAfterLayout = true;
Lines 2565-2570 bool RenderLayerCompositor::requiresCompositingForWillChange(RenderLayerModelObj a/Source/WebCore/rendering/RenderLayerCompositor.cpp_sec7
2565
    if (!renderer.style().willChange() || !renderer.style().willChange()->canTriggerCompositing())
2587
    if (!renderer.style().willChange() || !renderer.style().willChange()->canTriggerCompositing())
2566
        return false;
2588
        return false;
2567
2589
2590
    if (m_compositingPolicy == CompositingPolicy::Conservative)
2591
        return false;
2592
2568
    if (is<RenderBox>(renderer))
2593
    if (is<RenderBox>(renderer))
2569
        return true;
2594
        return true;
2570
2595
Lines 2807-2814 bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer& lay a/Source/WebCore/rendering/RenderLayerCompositor.cpp_sec8
2807
    if (m_renderView.settings().fixedBackgroundsPaintRelativeToDocument())
2832
    if (m_renderView.settings().fixedBackgroundsPaintRelativeToDocument())
2808
        return false;
2833
        return false;
2809
2834
2810
    LOG(Compositing, "RenderLayerCompositor %p needsFixedRootBackgroundLayer returning %d", this, supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed());
2811
2812
    return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed();
2835
    return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed();
2813
}
2836
}
2814
2837
Lines 4091-4094 TextStream& operator<<(TextStream& ts, CompositingUpdateType updateType) a/Source/WebCore/rendering/RenderLayerCompositor.cpp_sec9
4091
    return ts;
4114
    return ts;
4092
}
4115
}
4093
4116
4117
TextStream& operator<<(TextStream& ts, CompositingPolicy compositingPolicy)
4118
{
4119
    switch (compositingPolicy) {
4120
    case CompositingPolicy::Normal: ts << "normal"; break;
4121
    case CompositingPolicy::Conservative: ts << "conservative"; break;
4122
    }
4123
    return ts;
4124
}
4125
4094
} // namespace WebCore
4126
} // namespace WebCore
- a/Source/WebCore/rendering/RenderLayerCompositor.h +8 lines
Lines 83-88 enum class CompositingReason { a/Source/WebCore/rendering/RenderLayerCompositor.h_sec1
83
    IsolatesCompositedBlendingDescendants  = 1 << 25,
83
    IsolatesCompositedBlendingDescendants  = 1 << 25,
84
};
84
};
85
85
86
enum class CompositingPolicy : uint8_t {
87
    Normal,
88
    Conservative, // Used in low memory situations.
89
};
90
86
// RenderLayerCompositor manages the hierarchy of
91
// RenderLayerCompositor manages the hierarchy of
87
// composited RenderLayers. It determines which RenderLayers
92
// composited RenderLayers. It determines which RenderLayers
88
// become compositing, and creates and maintains a hierarchy of
93
// become compositing, and creates and maintains a hierarchy of
Lines 490-495 private: a/Source/WebCore/rendering/RenderLayerCompositor.h_sec2
490
495
491
    ChromeClient::CompositingTriggerFlags m_compositingTriggers { static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers) };
496
    ChromeClient::CompositingTriggerFlags m_compositingTriggers { static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers) };
492
    bool m_hasAcceleratedCompositing { true };
497
    bool m_hasAcceleratedCompositing { true };
498
    
499
    CompositingPolicy m_compositingPolicy { CompositingPolicy::Normal };
493
500
494
    bool m_showDebugBorders { false };
501
    bool m_showDebugBorders { false };
495
    bool m_showRepaintCounter { false };
502
    bool m_showRepaintCounter { false };
Lines 572-576 private: a/Source/WebCore/rendering/RenderLayerCompositor.h_sec3
572
void paintScrollbar(Scrollbar*, GraphicsContext&, const IntRect& clip);
579
void paintScrollbar(Scrollbar*, GraphicsContext&, const IntRect& clip);
573
580
574
WTF::TextStream& operator<<(WTF::TextStream&, CompositingUpdateType);
581
WTF::TextStream& operator<<(WTF::TextStream&, CompositingUpdateType);
582
WTF::TextStream& operator<<(WTF::TextStream&, CompositingPolicy);
575
583
576
} // namespace WebCore
584
} // namespace WebCore

Return to Bug 187866