WebKit Bugzilla
Attachment 345821 Details for
Bug 187866
: Be more conservative with compositing layer creation when memory is low
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-187866-20180725215305.patch (text/plain), 33.82 KB, created by
Simon Fraser (smfr)
on 2018-07-25 21:53:06 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Simon Fraser (smfr)
Created:
2018-07-25 21:53:06 PDT
Size:
33.82 KB
patch
obsolete
>Subversion Revision: 234073 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index b30d10f700c0a6755e500f7459ccca233566230f..e40bc097ec2131c89a509995a5330225a75b027d 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,54 @@ >+2018-07-20 Simon Fraser <simon.fraser@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 NOBODY (OOPS!). >+ >+ When process physical footprint is above a fraction of the jetsam limit (currently >+ hardcoded to be 840MB), 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 >+ >+ * 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::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: >+ > 2018-07-19 Simon Fraser <simon.fraser@apple.com> > > Remove completed animations from GraphicsLayer, thus avoiding excessive backing store allocation >diff --git a/Source/WTF/wtf/MemoryPressureHandler.cpp b/Source/WTF/wtf/MemoryPressureHandler.cpp >index caf388e29e3c1ef9e0e6ab9a2f6cea27fce41f32..0f4fd09f059061fdf184185a1282aaf7cad2a9d7 100644 >--- a/Source/WTF/wtf/MemoryPressureHandler.cpp >+++ b/Source/WTF/wtf/MemoryPressureHandler.cpp >@@ -113,12 +113,22 @@ size_t MemoryPressureHandler::thresholdForMemoryKill() > 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 @@ static MemoryUsagePolicy policyForFootprint(size_t footprint) > 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."); >diff --git a/Source/WTF/wtf/MemoryPressureHandler.h b/Source/WTF/wtf/MemoryPressureHandler.h >index 0039d054b0dbf06e6c6731081fb51479133dd551..83ff69996f4afb161a035b4d688ec0fc8f5bf0c7 100644 >--- a/Source/WTF/wtf/MemoryPressureHandler.h >+++ b/Source/WTF/wtf/MemoryPressureHandler.h >@@ -92,6 +92,8 @@ public: > } > void setUnderMemoryPressure(bool); > >+ WTF_EXPORT_PRIVATE static MemoryUsagePolicy currentMemoryUsagePolicy(); >+ > class ReliefLogger { > public: > explicit ReliefLogger(const char *log) >diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h >index 0d16963ddea1dd02d2cdf7b8fdc59b004d3ec134..4cb00eea5c362d0bb8fdb64696214b95e7c63ab7 100644 >--- a/Source/WebCore/page/Page.h >+++ b/Source/WebCore/page/Page.h >@@ -154,6 +154,11 @@ enum class EventThrottlingBehavior { > Unresponsive > }; > >+enum class CompositingPolicy : uint8_t { >+ Normal, >+ Conservative, // Used in low memory situations. >+}; >+ > enum class CanWrap : bool; > enum class DidWrap : bool; > enum class RouteSharingPolicy; >@@ -633,6 +638,9 @@ public: > 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; >@@ -869,6 +877,7 @@ private: > > // For testing. > std::optional<EventThrottlingBehavior> m_eventThrottlingBehaviorOverride; >+ std::optional<CompositingPolicy> m_compositingPolicyOverride; > > std::unique_ptr<PerformanceMonitor> m_performanceMonitor; > std::unique_ptr<LowPowerModeNotifier> m_lowPowerModeNotifier; >diff --git a/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp b/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp >index 08db7707d22ad9897eb8eee1982876626eeacd74..247e2d3d838b7013b744a5e9bbdff236212c9c2a 100644 >--- a/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp >+++ b/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp >@@ -61,6 +61,11 @@ Ref<TransformOperation> Matrix3DTransformOperation::blend(const TransformOperati > return createOperation(toT, fromT, progress); > } > >+bool Matrix3DTransformOperation::isRepresentableIn2D() const >+{ >+ return m_matrix.isAffine(); >+} >+ > void Matrix3DTransformOperation::dump(TextStream& ts) const > { > ts << type() << "(" << m_matrix << ")"; >diff --git a/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h b/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h >index 8f3fa9879de51140ad63ceff7bf12e46805e55d3..05288c38c077498ca496b2885ecad760a5af3b20 100644 >--- a/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h >+++ b/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h >@@ -46,7 +46,9 @@ public: > > 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; > >diff --git a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h b/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h >index 1cd7a190f27d139360b87402276bef582b79c0af..89d096f3dc8a19c6e9fcf81015cdce5333b63fc8 100644 >--- a/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h >+++ b/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h >@@ -49,6 +49,7 @@ public: > 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; > >diff --git a/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h b/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h >index fdde053f978b03b0a2ff2720c0d4148c3618084d..763daa0387482f7e46b9fd0bae69f5182c62fb20 100644 >--- a/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h >+++ b/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h >@@ -54,6 +54,7 @@ public: > 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; > >diff --git a/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h b/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h >index 6e21c75bcff9a0ce15eaa8f77d1bc98f607f3e77..3d5a07c748e4a1fa09d472ea8ca492e491cf5fcc 100644 >--- a/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h >+++ b/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h >@@ -53,6 +53,7 @@ public: > 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; > >diff --git a/Source/WebCore/platform/graphics/transforms/TransformOperation.h b/Source/WebCore/platform/graphics/transforms/TransformOperation.h >index 3cd6a5aaf50fd6a403c64fa00cf68fa07896041b..0574a54f70574923807a18d6a289e7379655d244 100644 >--- a/Source/WebCore/platform/graphics/transforms/TransformOperation.h >+++ b/Source/WebCore/platform/graphics/transforms/TransformOperation.h >@@ -87,6 +87,8 @@ public: > opType == MATRIX_3D || > opType == PERSPECTIVE; > } >+ >+ virtual bool isRepresentableIn2D() const { return true; } > > bool isRotateTransformOperationType() const > { >diff --git a/Source/WebCore/platform/graphics/transforms/TransformOperations.h b/Source/WebCore/platform/graphics/transforms/TransformOperations.h >index 8d070f7d753b1720c3e7acf31450b8bb0a5f405e..1f88d8171c17ff8205a1afe0f42a8f9c524ded80 100644 >--- a/Source/WebCore/platform/graphics/transforms/TransformOperations.h >+++ b/Source/WebCore/platform/graphics/transforms/TransformOperations.h >@@ -22,8 +22,7 @@ > * > */ > >-#ifndef TransformOperations_h >-#define TransformOperations_h >+#pragma once > > #include "LayoutSize.h" > #include "TransformOperation.h" >@@ -53,12 +52,22 @@ public: > // 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 @@ WTF::TextStream& operator<<(WTF::TextStream&, const TransformOperations&); > > } // namespace WebCore > >-#endif // TransformOperations_h >diff --git a/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h b/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h >index 02e4b7fd9c62d3e909126ea5204229746face588..e2b43e65c56d0ad5781549ba2886cefb34c347a8 100644 >--- a/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h >+++ b/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h >@@ -59,6 +59,8 @@ public: > 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 >diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp >index 1c625511deaf73dcfc1b371bf705b807576eab1f..6737ac5b2b79c12eed15e7e87d0cf10a3a90049b 100644 >--- a/Source/WebCore/rendering/RenderLayerBacking.cpp >+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp >@@ -950,8 +950,6 @@ LayoutRect RenderLayerBacking::computeParentGraphicsLayerRect(RenderLayer* compo > > 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; >diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp >index 41a63846d7d85a8a131814bbdf0c64787636d4e2..89cfe9fa6aa7f5c4c1a3682e9872067fb7c60971 100644 >--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp >+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp >@@ -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,8 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags() > if (m_layerForScrollCorner) > m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders); > } >+ >+ computeCompositingPolicy(); > } > > void RenderLayerCompositor::cacheAcceleratedCompositingFlagsAfterLayout() >@@ -362,6 +365,35 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlagsAfterLayout() > } > } > >+void RenderLayerCompositor::setCompositingPolicy(CompositingPolicy policy) >+{ >+ if (policy == m_compositingPolicy) >+ return; >+ >+ m_compositingPolicy = policy; >+ compositingPolicyChanged(); >+} >+ >+void RenderLayerCompositor::compositingPolicyChanged() >+{ >+ LOG_WITH_STREAM(Compositing, stream << "RenderLayerCompositor " << this << " compositingPolicyChanged - current policy is " << m_compositingPolicy); >+ >+ scheduleCompositingLayerUpdate(); >+} >+ >+void RenderLayerCompositor::computeCompositingPolicy() >+{ >+ if (page().compositingPolicyOverride()) { >+ setCompositingPolicy(page().compositingPolicyOverride().value()); >+ return; >+ } >+ >+ auto memoryPolicy = MemoryPressureHandler::currentMemoryUsagePolicy(); >+ setCompositingPolicy(memoryPolicy == WTF::MemoryUsagePolicy::Unrestricted ? CompositingPolicy::Normal : CompositingPolicy::Conservative); >+ >+ WTFLogAlways("SMFR - RenderLayerCompositor %p computeCompositingPolicy - under memory pressure %d, memory policy %d, compositing policy %d", this, MemoryPressureHandler::singleton().isUnderMemoryPressure(), static_cast<int>(memoryPolicy), static_cast<int>(m_compositingPolicy)); >+} >+ > bool RenderLayerCompositor::canRender3DTransforms() const > { > return hasAcceleratedCompositing() && (m_compositingTriggers & ChromeClient::ThreeDTransformTrigger); >@@ -732,7 +764,7 @@ bool RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update > > 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 > >@@ -2370,7 +2402,16 @@ bool RenderLayerCompositor::requiresCompositingForTransform(RenderLayerModelObje > > // 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: >+ return !renderer.style().transform().isRepresentableIn2D(); >+ } >+ return false; > } > > bool RenderLayerCompositor::requiresCompositingForBackfaceVisibility(RenderLayerModelObject& renderer) const >@@ -2396,15 +2437,17 @@ bool RenderLayerCompositor::requiresCompositingForVideo(RenderLayerModelObject& > { > 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); >-#endif > return false; >+#endif > } > > bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject& renderer) const >@@ -2412,17 +2455,22 @@ bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject& > 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; > } >@@ -2432,8 +2480,8 @@ bool RenderLayerCompositor::requiresCompositingForPlugin(RenderLayerModelObject& > 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; >@@ -2565,6 +2613,9 @@ bool RenderLayerCompositor::requiresCompositingForWillChange(RenderLayerModelObj > if (!renderer.style().willChange() || !renderer.style().willChange()->canTriggerCompositing()) > return false; > >+ if (m_compositingPolicy == CompositingPolicy::Conservative) >+ return false; >+ > if (is<RenderBox>(renderer)) > return true; > >@@ -2807,8 +2858,6 @@ bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer& lay > if (m_renderView.settings().fixedBackgroundsPaintRelativeToDocument()) > return false; > >- LOG(Compositing, "RenderLayerCompositor %p needsFixedRootBackgroundLayer returning %d", this, supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed()); >- > return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed(); > } > >@@ -4091,4 +4140,13 @@ TextStream& operator<<(TextStream& ts, CompositingUpdateType updateType) > 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 >diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h >index 35c3174fe784edc98aa78063f8b387a06b86f7ad..a8f9fd5fa45de3bbc8635b54df7b2f6b16a22ecd 100644 >--- a/Source/WebCore/rendering/RenderLayerCompositor.h >+++ b/Source/WebCore/rendering/RenderLayerCompositor.h >@@ -333,6 +333,10 @@ private: > struct CompositingState; > struct OverlapExtent; > >+ void setCompositingPolicy(CompositingPolicy); >+ void compositingPolicyChanged(); >+ void computeCompositingPolicy(); >+ > // GraphicsLayerClient implementation > void notifyFlushRequired(const GraphicsLayer*) override; > void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const FloatRect&, GraphicsLayerPaintBehavior) override; >@@ -490,6 +494,8 @@ private: > > 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 +578,6 @@ private: > void paintScrollbar(Scrollbar*, GraphicsContext&, const IntRect& clip); > > WTF::TextStream& operator<<(WTF::TextStream&, CompositingUpdateType); >+WTF::TextStream& operator<<(WTF::TextStream&, CompositingPolicy); > > } // namespace WebCore >diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp >index 2ca23cd245666642c73af9eba93493b48493a0dc..2eb414375fffa377f22a10270d7ccf97094e58da 100644 >--- a/Source/WebCore/testing/Internals.cpp >+++ b/Source/WebCore/testing/Internals.cpp >@@ -3001,6 +3001,49 @@ ExceptionOr<unsigned> Internals::compositingUpdateCount() > 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; >diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h >index e25c2fc6a046700ae63093e3a7f2bd120cde4634..af2757b49beeb20968eef1b6675c79624be6335a 100644 >--- a/Source/WebCore/testing/Internals.h >+++ b/Source/WebCore/testing/Internals.h >@@ -440,6 +440,10 @@ public: > 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; > >diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl >index 0fb9bb37286c6536c435b0b62ad0fae454304341..56ed01014f008b7e2d7ef4c00b90e61b2124a81f 100644 >--- a/Source/WebCore/testing/Internals.idl >+++ b/Source/WebCore/testing/Internals.idl >@@ -81,6 +81,11 @@ enum EventThrottlingBehavior { > "unresponsive" > }; > >+enum CompositingPolicy { >+ "normal", >+ "conservative" >+}; >+ > [Conditional=VIDEO] enum PlaybackControlsPurpose { > "ControlsManager", > "NowPlaying" >@@ -433,6 +438,8 @@ enum EventThrottlingBehavior { > [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. >diff --git a/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp b/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp >index a0ea4ec53e6beaeeea0901faabfbde053b0c710c..b84d5ab3a1a20b57fa2fb0ad10d6064da8843b2c 100644 >--- a/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp >+++ b/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp >@@ -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 @@ void WKBundlePageSetEventThrottlingBehaviorOverride(WKBundlePageRef page, WKEven > > 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); >+} >+ >diff --git a/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h b/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h >index f5088c5b4ba8b4465d0e5b2efdbd56ceb1488576..8414bcdb03c256ad3774a6d314cdd17e280006ec 100644 >--- a/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h >+++ b/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h >@@ -120,6 +120,16 @@ typedef uint32_t WKEventThrottlingBehavior; > // 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 >diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp >index 0f5865f6c153190d2f876c3f902fe6b2f7d886d7..26efa88ed5f5bf5514d13b7bb26ef6097a000ea9 100644 >--- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp >+++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp >@@ -426,6 +426,10 @@ void InjectedBundlePage::prepare() > // 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() >diff --git a/LayoutTests/compositing/layer-creation/compositing-policy-expected.txt b/LayoutTests/compositing/layer-creation/compositing-policy-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..082b1e3d0af0dcc2c8527bb59b139fafa8b9ea9c >--- /dev/null >+++ b/LayoutTests/compositing/layer-creation/compositing-policy-expected.txt >@@ -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]) >+ ) >+ ) >+ ) >+ ) >+) >+ >diff --git a/LayoutTests/compositing/layer-creation/compositing-policy.html b/LayoutTests/compositing/layer-creation/compositing-policy.html >new file mode 100644 >index 0000000000000000000000000000000000000000..919fbbbbe737858d8de8bff2bb27b5c90f6e3c77 >--- /dev/null >+++ b/LayoutTests/compositing/layer-creation/compositing-policy.html >@@ -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>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
zalan
:
review+
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 187866
:
345464
|
345468
|
345469
|
345471
| 345821