Diff
Modified: trunk/LayoutTests/ChangeLog (234329 => 234330)
--- trunk/LayoutTests/ChangeLog 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/LayoutTests/ChangeLog 2018-07-27 22:20:26 UTC (rev 234330)
@@ -1,3 +1,14 @@
+2018-07-27 Simon Fraser <simon.fra...@apple.com>
+
+ 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.
+
+ * compositing/layer-creation/compositing-policy-expected.txt: Added.
+ * compositing/layer-creation/compositing-policy.html: Added.
+
2018-07-27 Zalan Bujtas <za...@apple.com>
[WK1] ASSERTION FAILED: renderer().repaintLayoutRects().m_repaintRect == renderer().clippedOverflowRectForRepaint(renderer().containerForRepaint()) in WebCore::RenderLayer::updateLayerPositionsAfterScroll
Added: trunk/LayoutTests/compositing/layer-creation/compositing-policy-expected.txt (0 => 234330)
--- trunk/LayoutTests/compositing/layer-creation/compositing-policy-expected.txt (rev 0)
+++ trunk/LayoutTests/compositing/layer-creation/compositing-policy-expected.txt 2018-07-27 22:20:26 UTC (rev 234330)
@@ -0,0 +1,28 @@
+transform: translate3d(10px, 1px, 1px)
+Has backing under low memory.
+transform: translateZ(0)
+translateZ(0): No backing under low memory.
+transform: translate3d(10px, 1px, 0)
+No backing under low memory.
+will-change: transform
+No backing under low memory.
+ (GraphicsLayer
+ (anchor 0.00 0.00)
+ (bounds 800.00 1018.00)
+ (children 1
+ (GraphicsLayer
+ (bounds 800.00 1018.00)
+ (contentsOpaque 1)
+ (children 1
+ (GraphicsLayer
+ (position 18.00 10.00)
+ (bounds 308.00 108.00)
+ (contentsOpaque 1)
+ (drawsContent 1)
+ (transform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [0.00 0.00 1.00 0.00] [10.00 1.00 1.00 1.00])
+ )
+ )
+ )
+ )
+)
+
Added: trunk/LayoutTests/compositing/layer-creation/compositing-policy.html (0 => 234330)
--- trunk/LayoutTests/compositing/layer-creation/compositing-policy.html (rev 0)
+++ trunk/LayoutTests/compositing/layer-creation/compositing-policy.html 2018-07-27 22:20:26 UTC (rev 234330)
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+ <style>
+ body {
+ overflow:hidden; /* prevent scrollbars and document height from affecting test output */
+ height: 1000px;
+ }
+ .box {
+ margin: 10px;
+ height: 100px;
+ width: 300px;
+ padding: 4px;
+ background-color: silver;
+ }
+ </style>
+ <script>
+ if (window.testRunner)
+ testRunner.dumpAsText();
+
+ if (window.internals)
+ internals.compositingPolicyOverride = 'conservative';
+
+ function dumpLayers()
+ {
+ let canvas = document.getElementsByTagName('canvas')[0];
+ var ctx = canvas.getContext('2d');
+ ctx.fillStyle = 'white';
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ if (window.testRunner)
+ document.getElementById('layers').innerText = window.internals.layerTreeAsText(document);
+ }
+
+ window.addEventListener('load', dumpLayers, false);
+ </script>
+</head>
+<body>
+
+<div class="box" style="transform: translate3d(10px, 1px, 1px)">
+ <pre>transform: translate3d(10px, 1px, 1px)</pre>
+ Has backing under low memory.
+</div>
+
+<div class="box" style="transform: translateZ(0)">
+ <pre>transform: translateZ(0)</pre>
+ translateZ(0): No backing under low memory.
+</div>
+
+<div class="box" style="transform: translate3d(10px, 1px, 0)">
+ <pre>transform: translate3d(10px, 1px, 0)</pre>
+ No backing under low memory.
+</div>
+
+<div class="box" style="will-change: transform">
+ <pre>will-change: transform</pre>
+ No backing under low memory.
+</div>
+
+<canvas class="box" style="box-shadow: 0 0 10px black">
+</canvas>
+
+<pre id="layers"></pre>
+
+</body>
+</html>
Modified: trunk/Source/WTF/ChangeLog (234329 => 234330)
--- trunk/Source/WTF/ChangeLog 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WTF/ChangeLog 2018-07-27 22:20:26 UTC (rev 234330)
@@ -1,3 +1,30 @@
+2018-07-27 Simon Fraser <simon.fra...@apple.com>
+
+ 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.
+
+ 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:
+
2018-07-26 Andy VanWagoner <andy@vanwagoner.family>
[INTL] Remove INTL sub-feature compile flags
Modified: trunk/Source/WTF/wtf/MemoryPressureHandler.cpp (234329 => 234330)
--- trunk/Source/WTF/wtf/MemoryPressureHandler.cpp 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WTF/wtf/MemoryPressureHandler.cpp 2018-07-27 22:20:26 UTC (rev 234330)
@@ -113,12 +113,22 @@
static size_t thresholdForPolicy(MemoryUsagePolicy policy)
{
const size_t baseThresholdForPolicy = std::min(3 * GB, ramSize());
+
+#if PLATFORM(IOS)
+ const double conservativeThresholdFraction = 0.5;
+ const double strictThresholdFraction = 0.65;
+#else
+ const double conservativeThresholdFraction = 0.33;
+ const double strictThresholdFraction = 0.5;
+#endif
+
switch (policy) {
+ case MemoryUsagePolicy::Unrestricted:
+ return 0;
case MemoryUsagePolicy::Conservative:
- return baseThresholdForPolicy / 3;
+ return baseThresholdForPolicy * conservativeThresholdFraction;
case MemoryUsagePolicy::Strict:
- return baseThresholdForPolicy / 2;
- case MemoryUsagePolicy::Unrestricted:
+ return baseThresholdForPolicy * strictThresholdFraction;
default:
ASSERT_NOT_REACHED();
return 0;
@@ -134,6 +144,11 @@
return MemoryUsagePolicy::Unrestricted;
}
+MemoryUsagePolicy MemoryPressureHandler::currentMemoryUsagePolicy()
+{
+ return policyForFootprint(memoryFootprint().value_or(0));
+}
+
void MemoryPressureHandler::shrinkOrDie()
{
RELEASE_LOG(MemoryPressure, "Process is above the memory kill threshold. Trying to shrink down.");
Modified: trunk/Source/WTF/wtf/MemoryPressureHandler.h (234329 => 234330)
--- trunk/Source/WTF/wtf/MemoryPressureHandler.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WTF/wtf/MemoryPressureHandler.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -92,6 +92,8 @@
}
void setUnderMemoryPressure(bool);
+ WTF_EXPORT_PRIVATE static MemoryUsagePolicy currentMemoryUsagePolicy();
+
class ReliefLogger {
public:
explicit ReliefLogger(const char *log)
Modified: trunk/Source/WebCore/ChangeLog (234329 => 234330)
--- trunk/Source/WebCore/ChangeLog 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/ChangeLog 2018-07-27 22:20:26 UTC (rev 234330)
@@ -1,3 +1,62 @@
+2018-07-27 Simon Fraser <simon.fra...@apple.com>
+
+ 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.
+
+ 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:
+
2018-07-27 Zalan Bujtas <za...@apple.com>
[WK1] ASSERTION FAILED: renderer().repaintLayoutRects().m_repaintRect == renderer().clippedOverflowRectForRepaint(renderer().containerForRepaint()) in WebCore::RenderLayer::updateLayerPositionsAfterScroll
Modified: trunk/Source/WebCore/page/Page.h (234329 => 234330)
--- trunk/Source/WebCore/page/Page.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/page/Page.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -154,6 +154,11 @@
Unresponsive
};
+enum class CompositingPolicy : uint8_t {
+ Normal,
+ Conservative, // Used in low memory situations.
+};
+
enum class CanWrap : bool;
enum class DidWrap : bool;
enum class RouteSharingPolicy;
@@ -636,6 +641,9 @@
std::optional<EventThrottlingBehavior> eventThrottlingBehaviorOverride() const { return m_eventThrottlingBehaviorOverride; }
void setEventThrottlingBehaviorOverride(std::optional<EventThrottlingBehavior> throttling) { m_eventThrottlingBehaviorOverride = throttling; }
+ std::optional<CompositingPolicy> compositingPolicyOverride() const { return m_compositingPolicyOverride; }
+ void setCompositingPolicyOverride(std::optional<CompositingPolicy> policy) { m_compositingPolicyOverride = policy; }
+
WebGLStateTracker* webGLStateTracker() const { return m_webGLStateTracker.get(); }
bool isOnlyNonUtilityPage() const;
@@ -873,6 +881,7 @@
// For testing.
std::optional<EventThrottlingBehavior> m_eventThrottlingBehaviorOverride;
+ std::optional<CompositingPolicy> m_compositingPolicyOverride;
std::unique_ptr<PerformanceMonitor> m_performanceMonitor;
std::unique_ptr<LowPowerModeNotifier> m_lowPowerModeNotifier;
Modified: trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp (234329 => 234330)
--- trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp 2018-07-27 22:20:26 UTC (rev 234330)
@@ -61,6 +61,11 @@
return createOperation(toT, fromT, progress);
}
+bool Matrix3DTransformOperation::isRepresentableIn2D() const
+{
+ return m_matrix.isAffine();
+}
+
void Matrix3DTransformOperation::dump(TextStream& ts) const
{
ts << type() << "(" << m_matrix << ")";
Modified: trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h (234329 => 234330)
--- trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -46,8 +46,10 @@
private:
bool isIdentity() const override { return m_matrix.isIdentity(); }
- bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
+ bool isAffectedByTransformOrigin() const final { return !isIdentity(); }
+ bool isRepresentableIn2D() const final;
+
bool operator==(const TransformOperation&) const override;
bool apply(TransformationMatrix& transform, const FloatSize&) const override
Modified: trunk/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h (234329 => 234330)
--- trunk/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -49,6 +49,7 @@
private:
bool isIdentity() const override { return !floatValueForLength(m_p, 1); }
bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
+ bool isRepresentableIn2D() const final { return false; }
bool operator==(const TransformOperation&) const override;
Modified: trunk/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h (234329 => 234330)
--- trunk/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -54,6 +54,7 @@
private:
bool isIdentity() const override { return m_angle == 0; }
bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
+ bool isRepresentableIn2D() const final { return (!m_x && !m_y) || !m_angle; }
bool operator==(const TransformOperation&) const override;
Modified: trunk/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h (234329 => 234330)
--- trunk/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -53,6 +53,7 @@
private:
bool isIdentity() const override { return m_x == 1 && m_y == 1 && m_z == 1; }
bool isAffectedByTransformOrigin() const override { return !isIdentity(); }
+ bool isRepresentableIn2D() const final { return m_z == 1; }
bool operator==(const TransformOperation&) const override;
Modified: trunk/Source/WebCore/platform/graphics/transforms/TransformOperation.h (234329 => 234330)
--- trunk/Source/WebCore/platform/graphics/transforms/TransformOperation.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/platform/graphics/transforms/TransformOperation.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -87,6 +87,8 @@
opType == MATRIX_3D ||
opType == PERSPECTIVE;
}
+
+ virtual bool isRepresentableIn2D() const { return true; }
bool isRotateTransformOperationType() const
{
Modified: trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.h (234329 => 234330)
--- trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -22,8 +22,7 @@
*
*/
-#ifndef TransformOperations_h
-#define TransformOperations_h
+#pragma once
#include "LayoutSize.h"
#include "TransformOperation.h"
@@ -53,12 +52,22 @@
// values describe affine transforms)
bool has3DOperation() const
{
- for (unsigned i = 0; i < m_operations.size(); ++i)
- if (m_operations[i]->is3DOperation())
+ for (const auto& operation : m_operations) {
+ if (operation->is3DOperation())
return true;
+ }
return false;
}
-
+
+ bool isRepresentableIn2D() const
+ {
+ for (const auto& operation : m_operations) {
+ if (!operation->isRepresentableIn2D())
+ return false;
+ }
+ return true;
+ }
+
bool operationsMatch(const TransformOperations&) const;
void clear()
@@ -86,4 +95,3 @@
} // namespace WebCore
-#endif // TransformOperations_h
Modified: trunk/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h (234329 => 234330)
--- trunk/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -59,6 +59,8 @@
private:
bool isIdentity() const override { return !floatValueForLength(m_x, 1) && !floatValueForLength(m_y, 1) && !floatValueForLength(m_z, 1); }
+ bool isRepresentableIn2D() const final { return m_z.isZero(); }
+
bool operator==(const TransformOperation&) const override;
bool apply(TransformationMatrix& transform, const FloatSize& borderBoxSize) const override
Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (234329 => 234330)
--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2018-07-27 22:20:26 UTC (rev 234330)
@@ -950,8 +950,6 @@
void RenderLayerBacking::updateGeometry()
{
- LOG_WITH_STREAM(Compositing, stream << "updateGeometry " << m_owningLayer);
-
// If we haven't built z-order lists yet, wait until later.
if (m_owningLayer.isStackingContainer() && m_owningLayer.m_zOrderListsDirty)
return;
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (234329 => 234330)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2018-07-27 22:20:26 UTC (rev 234330)
@@ -60,6 +60,7 @@
#include "Settings.h"
#include "TiledBacking.h"
#include "TransformState.h"
+#include <wtf/MemoryPressureHandler.h>
#include <wtf/SetForScope.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
@@ -346,6 +347,9 @@
if (m_layerForScrollCorner)
m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
}
+
+ if (updateCompositingPolicy())
+ setCompositingLayersNeedRebuild();
}
void RenderLayerCompositor::cacheAcceleratedCompositingFlagsAfterLayout()
@@ -362,6 +366,19 @@
}
}
+bool RenderLayerCompositor::updateCompositingPolicy()
+{
+ auto currentPolicy = m_compositingPolicy;
+ if (page().compositingPolicyOverride()) {
+ m_compositingPolicy = page().compositingPolicyOverride().value();
+ return m_compositingPolicy != currentPolicy;
+ }
+
+ auto memoryPolicy = MemoryPressureHandler::currentMemoryUsagePolicy();
+ m_compositingPolicy = memoryPolicy == WTF::MemoryUsagePolicy::Unrestricted ? CompositingPolicy::Normal : CompositingPolicy::Conservative;
+ return m_compositingPolicy != currentPolicy;
+}
+
bool RenderLayerCompositor::canRender3DTransforms() const
{
return hasAcceleratedCompositing() && (m_compositingTriggers & ChromeClient::ThreeDTransformTrigger);
@@ -732,7 +749,7 @@
auto& frame = m_renderView.frameView().frame();
bool isMainFrame = isMainFrameCompositor();
- LOG(Compositing, "\nUpdate %d of %s.\n", m_rootLayerUpdateCount, isMainFrame ? "main frame" : frame.tree().uniqueName().string().utf8().data());
+ LOG_WITH_STREAM(Compositing, stream << "\nUpdate " << m_rootLayerUpdateCount << " of " << (isMainFrame ? "main frame" : frame.tree().uniqueName().string().utf8().data()) << " - compositing policy is " << m_compositingPolicy);
}
#endif
@@ -2389,7 +2406,19 @@
// Note that we ask the renderer if it has a transform, because the style may have transforms,
// but the renderer may be an inline that doesn't suppport them.
- return renderer.hasTransform() && renderer.style().transform().has3DOperation();
+ if (!renderer.hasTransform())
+ return false;
+
+ switch (m_compositingPolicy) {
+ case CompositingPolicy::Normal:
+ return renderer.style().transform().has3DOperation();
+ case CompositingPolicy::Conservative:
+ // Continue to allow pages to avoid the very slow software filter path.
+ if (renderer.style().transform().has3DOperation() && renderer.hasFilter())
+ return true;
+ return !renderer.style().transform().isRepresentableIn2D();
+ }
+ return false;
}
bool RenderLayerCompositor::requiresCompositingForBackfaceVisibility(RenderLayerModelObject& renderer) const
@@ -2415,15 +2444,17 @@
{
if (!(m_compositingTriggers & ChromeClient::VideoTrigger))
return false;
+
#if ENABLE(VIDEO)
- if (is<RenderVideo>(renderer)) {
- auto& video = downcast<RenderVideo>(renderer);
- return (video.requiresImmediateCompositing() || video.shouldDisplayVideo()) && canAccelerateVideoRendering(video);
- }
+ if (!is<RenderVideo>(renderer))
+ return false;
+
+ auto& video = downcast<RenderVideo>(renderer);
+ return (video.requiresImmediateCompositing() || video.shouldDisplayVideo()) && canAccelerateVideoRendering(video);
#else
UNUSED_PARAM(renderer);
+ return false;
#endif
- return false;
}
bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject& renderer) const
@@ -2431,18 +2462,23 @@
if (!(m_compositingTriggers & ChromeClient::CanvasTrigger))
return false;
- if (renderer.isCanvas()) {
-#if USE(COMPOSITING_FOR_SMALL_CANVASES)
- bool isCanvasLargeEnoughToForceCompositing = true;
-#else
- auto* canvas = downcast<HTMLCanvasElement>(renderer.element());
- auto canvasArea = canvas->size().area<RecordOverflow>();
- bool isCanvasLargeEnoughToForceCompositing = !canvasArea.hasOverflowed() && canvasArea.unsafeGet() >= canvasAreaThresholdRequiringCompositing;
+ if (!renderer.isCanvas())
+ return false;
+
+ bool isCanvasLargeEnoughToForceCompositing = true;
+#if !USE(COMPOSITING_FOR_SMALL_CANVASES)
+ auto* canvas = downcast<HTMLCanvasElement>(renderer.element());
+ auto canvasArea = canvas->size().area<RecordOverflow>();
+ isCanvasLargeEnoughToForceCompositing = !canvasArea.hasOverflowed() && canvasArea.unsafeGet() >= canvasAreaThresholdRequiringCompositing;
#endif
- CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer);
- return compositingStrategy == CanvasAsLayerContents || (compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing);
- }
+ CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer);
+ if (compositingStrategy == CanvasAsLayerContents)
+ return true;
+
+ if (m_compositingPolicy == CompositingPolicy::Normal)
+ return compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing;
+
return false;
}
@@ -2451,8 +2487,8 @@
if (!(m_compositingTriggers & ChromeClient::PluginTrigger))
return false;
- bool composite = is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
- if (!composite)
+ bool isCompositedPlugin = is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
+ if (!isCompositedPlugin)
return false;
m_reevaluateCompositingAfterLayout = true;
@@ -2589,6 +2625,9 @@
return false;
#endif
+ if (m_compositingPolicy == CompositingPolicy::Conservative)
+ return false;
+
if (is<RenderBox>(renderer))
return true;
@@ -2836,8 +2875,6 @@
if (m_renderView.settings().fixedBackgroundsPaintRelativeToDocument())
return false;
- LOG(Compositing, "RenderLayerCompositor %p needsFixedRootBackgroundLayer returning %d", this, supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed());
-
return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed();
}
@@ -4120,4 +4157,13 @@
return ts;
}
+TextStream& operator<<(TextStream& ts, CompositingPolicy compositingPolicy)
+{
+ switch (compositingPolicy) {
+ case CompositingPolicy::Normal: ts << "normal"; break;
+ case CompositingPolicy::Conservative: ts << "conservative"; break;
+ }
+ return ts;
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.h (234329 => 234330)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -333,6 +333,9 @@
struct CompositingState;
struct OverlapExtent;
+ // Returns true if the policy changed.
+ bool updateCompositingPolicy();
+
// GraphicsLayerClient implementation
void notifyFlushRequired(const GraphicsLayer*) override;
void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const FloatRect&, GraphicsLayerPaintBehavior) override;
@@ -490,6 +493,8 @@
ChromeClient::CompositingTriggerFlags m_compositingTriggers { static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers) };
bool m_hasAcceleratedCompositing { true };
+
+ CompositingPolicy m_compositingPolicy { CompositingPolicy::Normal };
bool m_showDebugBorders { false };
bool m_showRepaintCounter { false };
@@ -572,5 +577,6 @@
void paintScrollbar(Scrollbar*, GraphicsContext&, const IntRect& clip);
WTF::TextStream& operator<<(WTF::TextStream&, CompositingUpdateType);
+WTF::TextStream& operator<<(WTF::TextStream&, CompositingPolicy);
} // namespace WebCore
Modified: trunk/Source/WebCore/testing/Internals.cpp (234329 => 234330)
--- trunk/Source/WebCore/testing/Internals.cpp 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/testing/Internals.cpp 2018-07-27 22:20:26 UTC (rev 234330)
@@ -3001,6 +3001,49 @@
return document->renderView()->compositor().compositingUpdateCount();
}
+ExceptionOr<void> Internals::setCompositingPolicyOverride(std::optional<CompositingPolicy> policyOverride)
+{
+ Document* document = contextDocument();
+ if (!document)
+ return Exception { InvalidAccessError };
+
+ if (!policyOverride) {
+ document->page()->setCompositingPolicyOverride(std::nullopt);
+ return { };
+ }
+
+ switch (policyOverride.value()) {
+ case Internals::CompositingPolicy::Normal:
+ document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Normal);
+ break;
+ case Internals::CompositingPolicy::Conservative:
+ document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Conservative);
+ break;
+ }
+
+ return { };
+}
+
+ExceptionOr<std::optional<Internals::CompositingPolicy>> Internals::compositingPolicyOverride() const
+{
+ Document* document = contextDocument();
+ if (!document)
+ return Exception { InvalidAccessError };
+
+ auto policyOverride = document->page()->compositingPolicyOverride();
+ if (!policyOverride)
+ return { std::nullopt };
+
+ switch (policyOverride.value()) {
+ case WebCore::CompositingPolicy::Normal:
+ return { Internals::CompositingPolicy::Normal };
+ case WebCore::CompositingPolicy::Conservative:
+ return { Internals::CompositingPolicy::Conservative };
+ }
+
+ return { Internals::CompositingPolicy::Normal };
+}
+
ExceptionOr<void> Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node)
{
Document* document;
Modified: trunk/Source/WebCore/testing/Internals.h (234329 => 234330)
--- trunk/Source/WebCore/testing/Internals.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/testing/Internals.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -440,6 +440,10 @@
ExceptionOr<void> startTrackingCompositingUpdates();
ExceptionOr<unsigned> compositingUpdateCount();
+ enum CompositingPolicy { Normal, Conservative };
+ ExceptionOr<void> setCompositingPolicyOverride(std::optional<CompositingPolicy>);
+ ExceptionOr<std::optional<CompositingPolicy>> compositingPolicyOverride() const;
+
ExceptionOr<void> updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node*);
unsigned layoutCount() const;
Modified: trunk/Source/WebCore/testing/Internals.idl (234329 => 234330)
--- trunk/Source/WebCore/testing/Internals.idl 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebCore/testing/Internals.idl 2018-07-27 22:20:26 UTC (rev 234330)
@@ -81,6 +81,11 @@
"unresponsive"
};
+enum CompositingPolicy {
+ "normal",
+ "conservative"
+};
+
[Conditional=VIDEO] enum PlaybackControlsPurpose {
"ControlsManager",
"NowPlaying"
@@ -433,6 +438,8 @@
[MayThrowException] void startTrackingCompositingUpdates();
[MayThrowException] unsigned long compositingUpdateCount();
+ attribute CompositingPolicy? compositingPolicyOverride;
+
// |node| should be Document, HTMLIFrameElement, or unspecified.
// If |node| is an HTMLIFrameElement, it assumes node.contentDocument is
// specified without security checks. Unspecified or null means this document.
Modified: trunk/Source/WebKit/ChangeLog (234329 => 234330)
--- trunk/Source/WebKit/ChangeLog 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebKit/ChangeLog 2018-07-27 22:20:26 UTC (rev 234330)
@@ -1,3 +1,29 @@
+2018-07-27 Simon Fraser <simon.fra...@apple.com>
+
+ 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.
+
+ 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:
+
2018-07-27 Alex Christensen <achristen...@webkit.org>
Add RefCounted CompletionHandler wrapping abstraction for sending policy decisions back to WebProcess
Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp (234329 => 234330)
--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp 2018-07-27 22:20:26 UTC (rev 234330)
@@ -63,6 +63,7 @@
#include <WebCore/Page.h>
#include <WebCore/PageOverlay.h>
#include <WebCore/PageOverlayController.h>
+#include <WebCore/RenderLayerCompositor.h>
#include <WebCore/SecurityOriginData.h>
#include <WebCore/URL.h>
#include <WebCore/WheelEventTestTrigger.h>
@@ -713,3 +714,21 @@
toImpl(page)->corePage()->setEventThrottlingBehaviorOverride(behaviorValue);
}
+
+void WKBundlePageSetCompositingPolicyOverride(WKBundlePageRef page, WKCompositingPolicy* policy)
+{
+ std::optional<WebCore::CompositingPolicy> policyValue;
+ if (policy) {
+ switch (*policy) {
+ case kWKCompositingPolicyNormal:
+ policyValue = WebCore::CompositingPolicy::Normal;
+ break;
+ case kWKCompositingPolicyConservative:
+ policyValue = WebCore::CompositingPolicy::Conservative;
+ break;
+ }
+ }
+
+ toImpl(page)->corePage()->setCompositingPolicyOverride(policyValue);
+}
+
Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h (234329 => 234330)
--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h 2018-07-27 22:20:26 UTC (rev 234330)
@@ -120,6 +120,16 @@
// Passing null in the second parameter clears the override.
WK_EXPORT void WKBundlePageSetEventThrottlingBehaviorOverride(WKBundlePageRef, WKEventThrottlingBehavior*);
+enum {
+ kWKCompositingPolicyNormal = 0,
+ kWKCompositingPolicyConservative
+};
+
+typedef uint32_t WKCompositingPolicy;
+
+// Passing null in the second parameter clears the override.
+WK_EXPORT void WKBundlePageSetCompositingPolicyOverride(WKBundlePageRef, WKCompositingPolicy*);
+
#if TARGET_OS_IPHONE
WK_EXPORT void WKBundlePageSetUseTestingViewportConfiguration(WKBundlePageRef, bool);
#endif
Modified: trunk/Tools/ChangeLog (234329 => 234330)
--- trunk/Tools/ChangeLog 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Tools/ChangeLog 2018-07-27 22:20:26 UTC (rev 234330)
@@ -1,3 +1,28 @@
+2018-07-27 Simon Fraser <simon.fra...@apple.com>
+
+ 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.
+
+ 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):
+
2018-07-27 Michael Catanzaro <mcatanz...@igalia.com>
Unreviewed GTK test gardening
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp (234329 => 234330)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp 2018-07-27 22:11:32 UTC (rev 234329)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp 2018-07-27 22:20:26 UTC (rev 234330)
@@ -426,6 +426,10 @@
// Force consistent "responsive" behavior for WebPage::eventThrottlingDelay() for testing. Tests can override via internals.
WKEventThrottlingBehavior behavior = kWKEventThrottlingBehaviorResponsive;
WKBundlePageSetEventThrottlingBehaviorOverride(m_page, &behavior);
+
+ // Force consistent compositing behavior, even if the test runner is under memory pressure. Tests can override via internals.
+ WKCompositingPolicy policy = kWKCompositingPolicyNormal;
+ WKBundlePageSetCompositingPolicyOverride(m_page, &policy);
}
void InjectedBundlePage::resetAfterTest()