⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 234330 in webkit


Ignore:
Timestamp:
Jul 27, 2018, 3:20:26 PM (8 years ago)
Author:
Simon Fraser
Message:

Be more conservative with compositing layer creation when memory is low
https://bugs.webkit.org/show_bug.cgi?id=187866
rdar://problem/42366345

Reviewed by Zalan Bujtas.

Source/WebCore:

When process physical footprint is above a fraction of the jetsam limit, be more conservative in making
compositing layers. We avoid compositing for these situations:

  1. Layers with 3D transforms which are affine (like translateZ(0)).
  2. Layers with will-change
  3. Layers for canvases (other than WebGL/WebGPU)

We reuse some macOS code in MemoryPressureHandler() but choose different thresholds for iOS,
falling into "conservative mode" at 50% of jetsam limit, and "strict mode" at 65%.
Compositing chooses to be more conservative in either "conservative" or "strict" memory modes.

Plumb through a "compositingPolicyOverride" both so that on-device testing isn't
flakily falling into a different mode, and so that we can impose the conservative
mode for testing.

Test: compositing/layer-creation/compositing-policy.html

  • page/Page.h:

(WebCore::Page::compositingPolicyOverride const):
(WebCore::Page::setCompositingPolicyOverride):

  • platform/graphics/transforms/Matrix3DTransformOperation.cpp:

(WebCore::Matrix3DTransformOperation::isRepresentableIn2D const):

  • platform/graphics/transforms/Matrix3DTransformOperation.h:
  • platform/graphics/transforms/PerspectiveTransformOperation.h:
  • platform/graphics/transforms/RotateTransformOperation.h:
  • platform/graphics/transforms/ScaleTransformOperation.h:
  • platform/graphics/transforms/TransformOperation.h:

(WebCore::TransformOperation::isRepresentableIn2D const):

  • platform/graphics/transforms/TransformOperations.h:

(WebCore::TransformOperations::has3DOperation const):
(WebCore::TransformOperations::isRepresentableIn2D const):

  • platform/graphics/transforms/TranslateTransformOperation.h:
  • rendering/RenderLayerBacking.cpp:

(WebCore::RenderLayerBacking::updateGeometry):

  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::cacheAcceleratedCompositingFlags):
(WebCore::RenderLayerCompositor::updateCompositingPolicy):
(WebCore::RenderLayerCompositor::updateCompositingLayers):
(WebCore::RenderLayerCompositor::requiresCompositingForTransform const):
(WebCore::RenderLayerCompositor::requiresCompositingForVideo const):
(WebCore::RenderLayerCompositor::requiresCompositingForCanvas const):
(WebCore::RenderLayerCompositor::requiresCompositingForPlugin const):
(WebCore::RenderLayerCompositor::requiresCompositingForWillChange const):
(WebCore::RenderLayerCompositor::needsFixedRootBackgroundLayer const):
(WebCore::operator<<):

  • rendering/RenderLayerCompositor.h:
  • testing/Internals.cpp:

(WebCore::Internals::setCompositingPolicyOverride):
(WebCore::Internals::compositingPolicyOverride const):

  • testing/Internals.h:
  • testing/Internals.idl:

Source/WebKit:

When process physical footprint is above a fraction of the jetsam limit, be more conservative in making
compositing layers. We avoid compositing for these situations:

  1. Layers with 3D transforms which are affine (like translateZ(0)).
  2. Layers with will-change
  3. Layers for canvases (other than WebGL/WebGPU)

We reuse some macOS code in MemoryPressureHandler() but choose different thresholds for iOS,
falling into "conservative mode" at 50% of jetsam limit, and "strict mode" at 65%.
Compositing chooses to be more conservative in either "conservative" or "strict" memory modes.

Plumb through a "compositingPolicyOverride" both so that on-device testing isn't
flakily falling into a different mode, and so that we can impose the conservative
mode for testing.

  • WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:

(WKBundlePageSetCompositingPolicyOverride):

  • WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h:

Source/WTF:

When process physical footprint is above a fraction of the jetsam limit, be more conservative in making
compositing layers. We avoid compositing for these situations:

  1. Layers with 3D transforms which are affine (like translateZ(0)).
  2. Layers with will-change
  3. Layers for canvases (other than WebGL/WebGPU)

We reuse some macOS code in MemoryPressureHandler() but choose different thresholds for iOS,
falling into "conservative mode" at 50% of jetsam limit, and "strict mode" at 65%.
Compositing chooses to be more conservative in either "conservative" or "strict" memory modes.

Plumb through a "compositingPolicyOverride" both so that on-device testing isn't
flakily falling into a different mode, and so that we can impose the conservative
mode for testing.

  • wtf/MemoryPressureHandler.cpp:

(WTF::thresholdForPolicy):
(WTF::MemoryPressureHandler::currentMemoryUsagePolicy):

  • wtf/MemoryPressureHandler.h:

Tools:

When process physical footprint is above a fraction of the jetsam limit, be more conservative in making
compositing layers. We avoid compositing for these situations:

  1. Layers with 3D transforms which are affine (like translateZ(0)).
  2. Layers with will-change
  3. Layers for canvases (other than WebGL/WebGPU)

We reuse some macOS code in MemoryPressureHandler() but choose different thresholds for iOS,
falling into "conservative mode" at 50% of jetsam limit, and "strict mode" at 65%.
Compositing chooses to be more conservative in either "conservative" or "strict" memory modes.

Plumb through a "compositingPolicyOverride" both so that on-device testing isn't
flakily falling into a different mode, and so that we can impose the conservative
mode for testing.

  • WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:

(WTR::InjectedBundlePage::prepare):

LayoutTests:

  • compositing/layer-creation/compositing-policy-expected.txt: Added.
  • compositing/layer-creation/compositing-policy.html: Added.
Location:
trunk
Files:
2 added
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r234329 r234330  
     12018-07-27  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        rdar://problem/42366345
     6
     7        Reviewed by Zalan Bujtas.
     8       
     9        * compositing/layer-creation/compositing-policy-expected.txt: Added.
     10        * compositing/layer-creation/compositing-policy.html: Added.
     11
    1122018-07-27  Zalan Bujtas  <zalan@apple.com>
    213
  • trunk/Source/WTF/ChangeLog

    r234293 r234330  
     12018-07-27  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        rdar://problem/42366345
     6
     7        Reviewed by Zalan Bujtas.
     8       
     9        When process physical footprint is above a fraction of the jetsam limit, be more conservative in making
     10        compositing layers. We avoid compositing for these situations:
     11        1. Layers with 3D transforms which are affine (like translateZ(0)).
     12        2. Layers with will-change
     13        3. Layers for canvases (other than WebGL/WebGPU)
     14       
     15        We reuse some macOS code in MemoryPressureHandler() but choose different thresholds for iOS,
     16        falling into "conservative mode" at 50% of jetsam limit, and "strict mode" at 65%.
     17        Compositing chooses to be more conservative in either "conservative" or "strict" memory modes.
     18       
     19        Plumb through a "compositingPolicyOverride" both so that on-device testing isn't
     20        flakily falling into a different mode, and so that we can impose the conservative
     21        mode for testing.
     22
     23        * wtf/MemoryPressureHandler.cpp:
     24        (WTF::thresholdForPolicy):
     25        (WTF::MemoryPressureHandler::currentMemoryUsagePolicy):
     26        * wtf/MemoryPressureHandler.h:
     27
    1282018-07-26  Andy VanWagoner  <andy@vanwagoner.family>
    229
  • trunk/Source/WTF/wtf/MemoryPressureHandler.cpp

    r233380 r234330  
    114114{
    115115    const size_t baseThresholdForPolicy = std::min(3 * GB, ramSize());
     116
     117#if PLATFORM(IOS)
     118    const double conservativeThresholdFraction = 0.5;
     119    const double strictThresholdFraction = 0.65;
     120#else
     121    const double conservativeThresholdFraction = 0.33;
     122    const double strictThresholdFraction = 0.5;
     123#endif
     124
    116125    switch (policy) {
     126    case MemoryUsagePolicy::Unrestricted:
     127        return 0;
    117128    case MemoryUsagePolicy::Conservative:
    118         return baseThresholdForPolicy / 3;
     129        return baseThresholdForPolicy * conservativeThresholdFraction;
    119130    case MemoryUsagePolicy::Strict:
    120         return baseThresholdForPolicy / 2;
    121     case MemoryUsagePolicy::Unrestricted:
     131        return baseThresholdForPolicy * strictThresholdFraction;
    122132    default:
    123133        ASSERT_NOT_REACHED();
     
    133143        return MemoryUsagePolicy::Conservative;
    134144    return MemoryUsagePolicy::Unrestricted;
     145}
     146
     147MemoryUsagePolicy MemoryPressureHandler::currentMemoryUsagePolicy()
     148{
     149    return policyForFootprint(memoryFootprint().value_or(0));
    135150}
    136151
  • trunk/Source/WTF/wtf/MemoryPressureHandler.h

    r232176 r234330  
    9393    void setUnderMemoryPressure(bool);
    9494
     95    WTF_EXPORT_PRIVATE static MemoryUsagePolicy currentMemoryUsagePolicy();
     96
    9597    class ReliefLogger {
    9698    public:
  • trunk/Source/WebCore/ChangeLog

    r234329 r234330  
     12018-07-27  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        rdar://problem/42366345
     6
     7        Reviewed by Zalan Bujtas.
     8       
     9        When process physical footprint is above a fraction of the jetsam limit, be more conservative in making
     10        compositing layers. We avoid compositing for these situations:
     11        1. Layers with 3D transforms which are affine (like translateZ(0)).
     12        2. Layers with will-change
     13        3. Layers for canvases (other than WebGL/WebGPU)
     14       
     15        We reuse some macOS code in MemoryPressureHandler() but choose different thresholds for iOS,
     16        falling into "conservative mode" at 50% of jetsam limit, and "strict mode" at 65%.
     17        Compositing chooses to be more conservative in either "conservative" or "strict" memory modes.
     18       
     19        Plumb through a "compositingPolicyOverride" both so that on-device testing isn't
     20        flakily falling into a different mode, and so that we can impose the conservative
     21        mode for testing.
     22
     23        Test: compositing/layer-creation/compositing-policy.html
     24
     25        * page/Page.h:
     26        (WebCore::Page::compositingPolicyOverride const):
     27        (WebCore::Page::setCompositingPolicyOverride):
     28        * platform/graphics/transforms/Matrix3DTransformOperation.cpp:
     29        (WebCore::Matrix3DTransformOperation::isRepresentableIn2D const):
     30        * platform/graphics/transforms/Matrix3DTransformOperation.h:
     31        * platform/graphics/transforms/PerspectiveTransformOperation.h:
     32        * platform/graphics/transforms/RotateTransformOperation.h:
     33        * platform/graphics/transforms/ScaleTransformOperation.h:
     34        * platform/graphics/transforms/TransformOperation.h:
     35        (WebCore::TransformOperation::isRepresentableIn2D const):
     36        * platform/graphics/transforms/TransformOperations.h:
     37        (WebCore::TransformOperations::has3DOperation const):
     38        (WebCore::TransformOperations::isRepresentableIn2D const):
     39        * platform/graphics/transforms/TranslateTransformOperation.h:
     40        * rendering/RenderLayerBacking.cpp:
     41        (WebCore::RenderLayerBacking::updateGeometry):
     42        * rendering/RenderLayerCompositor.cpp:
     43        (WebCore::RenderLayerCompositor::cacheAcceleratedCompositingFlags):
     44        (WebCore::RenderLayerCompositor::updateCompositingPolicy):
     45        (WebCore::RenderLayerCompositor::updateCompositingLayers):
     46        (WebCore::RenderLayerCompositor::requiresCompositingForTransform const):
     47        (WebCore::RenderLayerCompositor::requiresCompositingForVideo const):
     48        (WebCore::RenderLayerCompositor::requiresCompositingForCanvas const):
     49        (WebCore::RenderLayerCompositor::requiresCompositingForPlugin const):
     50        (WebCore::RenderLayerCompositor::requiresCompositingForWillChange const):
     51        (WebCore::RenderLayerCompositor::needsFixedRootBackgroundLayer const):
     52        (WebCore::operator<<):
     53        * rendering/RenderLayerCompositor.h:
     54        * testing/Internals.cpp:
     55        (WebCore::Internals::setCompositingPolicyOverride):
     56        (WebCore::Internals::compositingPolicyOverride const):
     57        * testing/Internals.h:
     58        * testing/Internals.idl:
     59
    1602018-07-27  Zalan Bujtas  <zalan@apple.com>
    261
  • trunk/Source/WebCore/page/Page.h

    r234211 r234330  
    155155};
    156156
     157enum class CompositingPolicy : uint8_t {
     158    Normal,
     159    Conservative, // Used in low memory situations.
     160};
     161
    157162enum class CanWrap : bool;
    158163enum class DidWrap : bool;
     
    637642    void setEventThrottlingBehaviorOverride(std::optional<EventThrottlingBehavior> throttling) { m_eventThrottlingBehaviorOverride = throttling; }
    638643
     644    std::optional<CompositingPolicy> compositingPolicyOverride() const { return m_compositingPolicyOverride; }
     645    void setCompositingPolicyOverride(std::optional<CompositingPolicy> policy) { m_compositingPolicyOverride = policy; }
     646
    639647    WebGLStateTracker* webGLStateTracker() const { return m_webGLStateTracker.get(); }
    640648
     
    874882    // For testing.
    875883    std::optional<EventThrottlingBehavior> m_eventThrottlingBehaviorOverride;
     884    std::optional<CompositingPolicy> m_compositingPolicyOverride;
    876885
    877886    std::unique_ptr<PerformanceMonitor> m_performanceMonitor;
  • trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp

    r220503 r234330  
    6262}
    6363
     64bool Matrix3DTransformOperation::isRepresentableIn2D() const
     65{
     66    return m_matrix.isAffine();
     67}
     68
    6469void Matrix3DTransformOperation::dump(TextStream& ts) const
    6570{
  • trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h

    r220503 r234330  
    4747private:   
    4848    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;
    5052
    5153    bool operator==(const TransformOperation&) const override;
  • trunk/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h

    r220503 r234330  
    5050    bool isIdentity() const override { return !floatValueForLength(m_p, 1); }
    5151    bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
     52    bool isRepresentableIn2D() const final { return false; }
    5253
    5354    bool operator==(const TransformOperation&) const override;
  • trunk/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h

    r220503 r234330  
    5555    bool isIdentity() const override { return m_angle == 0; }
    5656    bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
     57    bool isRepresentableIn2D() const final { return (!m_x && !m_y) || !m_angle; }
    5758
    5859    bool operator==(const TransformOperation&) const override;
  • trunk/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h

    r220503 r234330  
    5454    bool isIdentity() const override { return m_x == 1 &&  m_y == 1 &&  m_z == 1; }
    5555    bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
     56    bool isRepresentableIn2D() const final { return m_z == 1; }
    5657
    5758    bool operator==(const TransformOperation&) const override;
  • trunk/Source/WebCore/platform/graphics/transforms/TransformOperation.h

    r223728 r234330  
    8888               opType == PERSPECTIVE;
    8989    }
     90   
     91    virtual bool isRepresentableIn2D() const { return true; }
    9092
    9193    bool isRotateTransformOperationType() const
  • trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.h

    r220503 r234330  
    2323 */
    2424
    25 #ifndef TransformOperations_h
    26 #define TransformOperations_h
     25#pragma once
    2726
    2827#include "LayoutSize.h"
     
    5453    bool has3DOperation() const
    5554    {
    56         for (unsigned i = 0; i < m_operations.size(); ++i)
    57             if (m_operations[i]->is3DOperation())
     55        for (const auto& operation : m_operations) {
     56            if (operation->is3DOperation())
    5857                return true;
     58        }
    5959        return false;
    6060    }
    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
    6271    bool operationsMatch(const TransformOperations&) const;
    6372   
     
    8796} // namespace WebCore
    8897
    89 #endif // TransformOperations_h
  • trunk/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h

    r220503 r234330  
    6060    bool isIdentity() const override { return !floatValueForLength(m_x, 1) && !floatValueForLength(m_y, 1) && !floatValueForLength(m_z, 1); }
    6161
     62    bool isRepresentableIn2D() const final { return m_z.isZero(); }
     63
    6264    bool operator==(const TransformOperation&) const override;
    6365
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r234203 r234330  
    951951void RenderLayerBacking::updateGeometry()
    952952{
    953     LOG_WITH_STREAM(Compositing, stream << "updateGeometry " << m_owningLayer);
    954 
    955953    // If we haven't built z-order lists yet, wait until later.
    956954    if (m_owningLayer.isStackingContainer() && m_owningLayer.m_zOrderListsDirty)
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r234291 r234330  
    6161#include "TiledBacking.h"
    6262#include "TransformState.h"
     63#include <wtf/MemoryPressureHandler.h>
    6364#include <wtf/SetForScope.h>
    6465#include <wtf/text/CString.h>
     
    347348            m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
    348349    }
     350   
     351    if (updateCompositingPolicy())
     352        setCompositingLayersNeedRebuild();
    349353}
    350354
     
    361365        setCompositingLayersNeedRebuild();
    362366    }
     367}
     368
     369bool RenderLayerCompositor::updateCompositingPolicy()
     370{
     371    auto currentPolicy = m_compositingPolicy;
     372    if (page().compositingPolicyOverride()) {
     373        m_compositingPolicy = page().compositingPolicyOverride().value();
     374        return m_compositingPolicy != currentPolicy;
     375    }
     376   
     377    auto memoryPolicy = MemoryPressureHandler::currentMemoryUsagePolicy();
     378    m_compositingPolicy = memoryPolicy == WTF::MemoryUsagePolicy::Unrestricted ? CompositingPolicy::Normal : CompositingPolicy::Conservative;
     379    return m_compositingPolicy != currentPolicy;
    363380}
    364381
     
    733750        auto& frame = m_renderView.frameView().frame();
    734751        bool isMainFrame = isMainFrameCompositor();
    735         LOG(Compositing, "\nUpdate %d of %s.\n", m_rootLayerUpdateCount, isMainFrame ? "main frame" : frame.tree().uniqueName().string().utf8().data());
     752        LOG_WITH_STREAM(Compositing, stream << "\nUpdate " << m_rootLayerUpdateCount << " of " << (isMainFrame ? "main frame" : frame.tree().uniqueName().string().utf8().data()) << " - compositing policy is " << m_compositingPolicy);
    736753    }
    737754#endif
     
    23902407    // Note that we ask the renderer if it has a transform, because the style may have transforms,
    23912408    // but the renderer may be an inline that doesn't suppport them.
    2392     return renderer.hasTransform() && renderer.style().transform().has3DOperation();
     2409    if (!renderer.hasTransform())
     2410        return false;
     2411   
     2412    switch (m_compositingPolicy) {
     2413    case CompositingPolicy::Normal:
     2414        return renderer.style().transform().has3DOperation();
     2415    case CompositingPolicy::Conservative:
     2416        // Continue to allow pages to avoid the very slow software filter path.
     2417        if (renderer.style().transform().has3DOperation() && renderer.hasFilter())
     2418            return true;
     2419        return !renderer.style().transform().isRepresentableIn2D();
     2420    }
     2421    return false;
    23932422}
    23942423
     
    24162445    if (!(m_compositingTriggers & ChromeClient::VideoTrigger))
    24172446        return false;
     2447
    24182448#if ENABLE(VIDEO)
    2419     if (is<RenderVideo>(renderer)) {
    2420         auto& video = downcast<RenderVideo>(renderer);
    2421         return (video.requiresImmediateCompositing() || video.shouldDisplayVideo()) && canAccelerateVideoRendering(video);
    2422     }
     2449    if (!is<RenderVideo>(renderer))
     2450        return false;
     2451
     2452    auto& video = downcast<RenderVideo>(renderer);
     2453    return (video.requiresImmediateCompositing() || video.shouldDisplayVideo()) && canAccelerateVideoRendering(video);
    24232454#else
    24242455    UNUSED_PARAM(renderer);
    2425 #endif
    24262456    return false;
     2457#endif
    24272458}
    24282459
     
    24322463        return false;
    24332464
    2434     if (renderer.isCanvas()) {
    2435 #if USE(COMPOSITING_FOR_SMALL_CANVASES)
    2436         bool isCanvasLargeEnoughToForceCompositing = true;
    2437 #else
    2438         auto* canvas = downcast<HTMLCanvasElement>(renderer.element());
    2439         auto canvasArea = canvas->size().area<RecordOverflow>();
    2440         bool isCanvasLargeEnoughToForceCompositing = !canvasArea.hasOverflowed() && canvasArea.unsafeGet() >= canvasAreaThresholdRequiringCompositing;
    2441 #endif
    2442         CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer);
    2443         return compositingStrategy == CanvasAsLayerContents || (compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing);
    2444     }
     2465    if (!renderer.isCanvas())
     2466        return false;
     2467
     2468    bool isCanvasLargeEnoughToForceCompositing = true;
     2469#if !USE(COMPOSITING_FOR_SMALL_CANVASES)
     2470    auto* canvas = downcast<HTMLCanvasElement>(renderer.element());
     2471    auto canvasArea = canvas->size().area<RecordOverflow>();
     2472    isCanvasLargeEnoughToForceCompositing = !canvasArea.hasOverflowed() && canvasArea.unsafeGet() >= canvasAreaThresholdRequiringCompositing;
     2473#endif
     2474
     2475    CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer);
     2476    if (compositingStrategy == CanvasAsLayerContents)
     2477        return true;
     2478
     2479    if (m_compositingPolicy == CompositingPolicy::Normal)
     2480        return compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing;
    24452481
    24462482    return false;
     
    24522488        return false;
    24532489
    2454     bool composite = is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
    2455     if (!composite)
     2490    bool isCompositedPlugin = is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
     2491    if (!isCompositedPlugin)
    24562492        return false;
    24572493
     
    25902626#endif
    25912627
     2628    if (m_compositingPolicy == CompositingPolicy::Conservative)
     2629        return false;
     2630
    25922631    if (is<RenderBox>(renderer))
    25932632        return true;
     
    28362875    if (m_renderView.settings().fixedBackgroundsPaintRelativeToDocument())
    28372876        return false;
    2838 
    2839     LOG(Compositing, "RenderLayerCompositor %p needsFixedRootBackgroundLayer returning %d", this, supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed());
    28402877
    28412878    return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed();
     
    41214158}
    41224159
     4160TextStream& operator<<(TextStream& ts, CompositingPolicy compositingPolicy)
     4161{
     4162    switch (compositingPolicy) {
     4163    case CompositingPolicy::Normal: ts << "normal"; break;
     4164    case CompositingPolicy::Conservative: ts << "conservative"; break;
     4165    }
     4166    return ts;
     4167}
     4168
    41234169} // namespace WebCore
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.h

    r232991 r234330  
    334334    struct OverlapExtent;
    335335
     336    // Returns true if the policy changed.
     337    bool updateCompositingPolicy();
     338   
    336339    // GraphicsLayerClient implementation
    337340    void notifyFlushRequired(const GraphicsLayer*) override;
     
    491494    ChromeClient::CompositingTriggerFlags m_compositingTriggers { static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers) };
    492495    bool m_hasAcceleratedCompositing { true };
     496   
     497    CompositingPolicy m_compositingPolicy { CompositingPolicy::Normal };
    493498
    494499    bool m_showDebugBorders { false };
     
    573578
    574579WTF::TextStream& operator<<(WTF::TextStream&, CompositingUpdateType);
     580WTF::TextStream& operator<<(WTF::TextStream&, CompositingPolicy);
    575581
    576582} // namespace WebCore
  • trunk/Source/WebCore/testing/Internals.cpp

    r234111 r234330  
    30023002}
    30033003
     3004ExceptionOr<void> Internals::setCompositingPolicyOverride(std::optional<CompositingPolicy> policyOverride)
     3005{
     3006    Document* document = contextDocument();
     3007    if (!document)
     3008        return Exception { InvalidAccessError };
     3009
     3010    if (!policyOverride) {
     3011        document->page()->setCompositingPolicyOverride(std::nullopt);
     3012        return { };
     3013    }
     3014
     3015    switch (policyOverride.value()) {
     3016    case Internals::CompositingPolicy::Normal:
     3017        document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Normal);
     3018        break;
     3019    case Internals::CompositingPolicy::Conservative:
     3020        document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Conservative);
     3021        break;
     3022    }
     3023   
     3024    return { };
     3025}
     3026
     3027ExceptionOr<std::optional<Internals::CompositingPolicy>> Internals::compositingPolicyOverride() const
     3028{
     3029    Document* document = contextDocument();
     3030    if (!document)
     3031        return Exception { InvalidAccessError };
     3032
     3033    auto policyOverride = document->page()->compositingPolicyOverride();
     3034    if (!policyOverride)
     3035        return { std::nullopt };
     3036
     3037    switch (policyOverride.value()) {
     3038    case WebCore::CompositingPolicy::Normal:
     3039        return { Internals::CompositingPolicy::Normal };
     3040    case WebCore::CompositingPolicy::Conservative:
     3041        return { Internals::CompositingPolicy::Conservative };
     3042    }
     3043
     3044    return { Internals::CompositingPolicy::Normal };
     3045}
     3046
    30043047ExceptionOr<void> Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node)
    30053048{
  • trunk/Source/WebCore/testing/Internals.h

    r234111 r234330  
    441441    ExceptionOr<unsigned> compositingUpdateCount();
    442442
     443    enum CompositingPolicy { Normal, Conservative };
     444    ExceptionOr<void> setCompositingPolicyOverride(std::optional<CompositingPolicy>);
     445    ExceptionOr<std::optional<CompositingPolicy>> compositingPolicyOverride() const;
     446
    443447    ExceptionOr<void> updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node*);
    444448    unsigned layoutCount() const;
  • trunk/Source/WebCore/testing/Internals.idl

    r234111 r234330  
    8282};
    8383
     84enum CompositingPolicy {
     85    "normal",
     86    "conservative"
     87};
     88
    8489[Conditional=VIDEO] enum PlaybackControlsPurpose {
    8590    "ControlsManager",
     
    433438    [MayThrowException] void startTrackingCompositingUpdates();
    434439    [MayThrowException] unsigned long compositingUpdateCount();
     440
     441    attribute CompositingPolicy? compositingPolicyOverride;
    435442
    436443    // |node| should be Document, HTMLIFrameElement, or unspecified.
  • trunk/Source/WebKit/ChangeLog

    r234327 r234330  
     12018-07-27  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        rdar://problem/42366345
     6
     7        Reviewed by Zalan Bujtas.
     8       
     9        When process physical footprint is above a fraction of the jetsam limit, be more conservative in making
     10        compositing layers. We avoid compositing for these situations:
     11        1. Layers with 3D transforms which are affine (like translateZ(0)).
     12        2. Layers with will-change
     13        3. Layers for canvases (other than WebGL/WebGPU)
     14       
     15        We reuse some macOS code in MemoryPressureHandler() but choose different thresholds for iOS,
     16        falling into "conservative mode" at 50% of jetsam limit, and "strict mode" at 65%.
     17        Compositing chooses to be more conservative in either "conservative" or "strict" memory modes.
     18       
     19        Plumb through a "compositingPolicyOverride" both so that on-device testing isn't
     20        flakily falling into a different mode, and so that we can impose the conservative
     21        mode for testing.
     22
     23        * WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:
     24        (WKBundlePageSetCompositingPolicyOverride):
     25        * WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h:
     26
    1272018-07-27  Alex Christensen  <achristensen@webkit.org>
    228
  • trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp

    r232192 r234330  
    6464#include <WebCore/PageOverlay.h>
    6565#include <WebCore/PageOverlayController.h>
     66#include <WebCore/RenderLayerCompositor.h>
    6667#include <WebCore/SecurityOriginData.h>
    6768#include <WebCore/URL.h>
     
    714715    toImpl(page)->corePage()->setEventThrottlingBehaviorOverride(behaviorValue);
    715716}
     717
     718void WKBundlePageSetCompositingPolicyOverride(WKBundlePageRef page, WKCompositingPolicy* policy)
     719{
     720    std::optional<WebCore::CompositingPolicy> policyValue;
     721    if (policy) {
     722        switch (*policy) {
     723        case kWKCompositingPolicyNormal:
     724            policyValue = WebCore::CompositingPolicy::Normal;
     725            break;
     726        case kWKCompositingPolicyConservative:
     727            policyValue = WebCore::CompositingPolicy::Conservative;
     728            break;
     729        }
     730    }
     731
     732    toImpl(page)->corePage()->setCompositingPolicyOverride(policyValue);
     733}
     734
  • trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h

    r226753 r234330  
    121121WK_EXPORT void WKBundlePageSetEventThrottlingBehaviorOverride(WKBundlePageRef, WKEventThrottlingBehavior*);
    122122
     123enum {
     124    kWKCompositingPolicyNormal = 0,
     125    kWKCompositingPolicyConservative
     126};
     127
     128typedef uint32_t WKCompositingPolicy;
     129
     130// Passing null in the second parameter clears the override.
     131WK_EXPORT void WKBundlePageSetCompositingPolicyOverride(WKBundlePageRef, WKCompositingPolicy*);
     132
    123133#if TARGET_OS_IPHONE
    124134WK_EXPORT void WKBundlePageSetUseTestingViewportConfiguration(WKBundlePageRef, bool);
  • trunk/Tools/ChangeLog

    r234325 r234330  
     12018-07-27  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        rdar://problem/42366345
     6
     7        Reviewed by Zalan Bujtas.
     8       
     9        When process physical footprint is above a fraction of the jetsam limit, be more conservative in making
     10        compositing layers. We avoid compositing for these situations:
     11        1. Layers with 3D transforms which are affine (like translateZ(0)).
     12        2. Layers with will-change
     13        3. Layers for canvases (other than WebGL/WebGPU)
     14       
     15        We reuse some macOS code in MemoryPressureHandler() but choose different thresholds for iOS,
     16        falling into "conservative mode" at 50% of jetsam limit, and "strict mode" at 65%.
     17        Compositing chooses to be more conservative in either "conservative" or "strict" memory modes.
     18       
     19        Plumb through a "compositingPolicyOverride" both so that on-device testing isn't
     20        flakily falling into a different mode, and so that we can impose the conservative
     21        mode for testing.
     22
     23        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
     24        (WTR::InjectedBundlePage::prepare):
     25
    1262018-07-27  Michael Catanzaro  <mcatanzaro@igalia.com>
    227
  • trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp

    r233782 r234330  
    427427    WKEventThrottlingBehavior behavior = kWKEventThrottlingBehaviorResponsive;
    428428    WKBundlePageSetEventThrottlingBehaviorOverride(m_page, &behavior);
     429   
     430    // Force consistent compositing behavior, even if the test runner is under memory pressure. Tests can override via internals.
     431    WKCompositingPolicy policy = kWKCompositingPolicyNormal;
     432    WKBundlePageSetCompositingPolicyOverride(m_page, &policy);
    429433}
    430434
Note: See TracChangeset for help on using the changeset viewer.