- Revision
- 215347
- Author
- [email protected]
- Date
- 2017-04-13 16:20:50 -0700 (Thu, 13 Apr 2017)
Log Message
Don't invalidate composition for style changes in non-composited layers
https://bugs.webkit.org/show_bug.cgi?id=170805
<rdar://problem/31606185>
Reviewed by Simon Fraser.
Source/WebCore:
Test: compositing/updates/animation-non-composited.html
In most cases they can't affect composition. Composition updates are expensive, this can
save a lot of work (tumblr.com animations hit this at the moment).
* rendering/RenderElement.h:
(WebCore::RenderElement::createsGroup):
(WebCore::RenderElement::createsGroupForStyle):
Factor to a static function so we can test style directly.
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::layerStyleChanged):
(WebCore::RenderLayerCompositor::styleChangeMayAffectIndirectCompositingReasons):
Test if style change might cause compositing change that can't be determined without compositing update.
* rendering/RenderLayerCompositor.h:
LayoutTests:
* compositing/updates/animation-non-composited-expected.txt: Added.
* compositing/updates/animation-non-composited.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (215346 => 215347)
--- trunk/LayoutTests/ChangeLog 2017-04-13 23:20:03 UTC (rev 215346)
+++ trunk/LayoutTests/ChangeLog 2017-04-13 23:20:50 UTC (rev 215347)
@@ -1,3 +1,14 @@
+2017-04-13 Antti Koivisto <[email protected]>
+
+ Don't invalidate composition for style changes in non-composited layers
+ https://bugs.webkit.org/show_bug.cgi?id=170805
+ <rdar://problem/31606185>
+
+ Reviewed by Simon Fraser.
+
+ * compositing/updates/animation-non-composited-expected.txt: Added.
+ * compositing/updates/animation-non-composited.html: Added.
+
2017-04-13 Ryan Haddad <[email protected]>
Mark webrtc/video-mute.html as flaky.
Added: trunk/LayoutTests/compositing/updates/animation-non-composited-expected.txt (0 => 215347)
--- trunk/LayoutTests/compositing/updates/animation-non-composited-expected.txt (rev 0)
+++ trunk/LayoutTests/compositing/updates/animation-non-composited-expected.txt 2017-04-13 23:20:50 UTC (rev 215347)
@@ -0,0 +1,2 @@
+Test that a simple animation on an element with a layer doesn't generate compositing updates.
+compositingUpdateCount: 0
Added: trunk/LayoutTests/compositing/updates/animation-non-composited.html (0 => 215347)
--- trunk/LayoutTests/compositing/updates/animation-non-composited.html (rev 0)
+++ trunk/LayoutTests/compositing/updates/animation-non-composited.html 2017-04-13 23:20:50 UTC (rev 215347)
@@ -0,0 +1,43 @@
+<script>
+if (testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+</script>
+<style>
+@keyframes color-keyframes {
+ from { color: red; }
+ to { color: green; }
+}
+.color-animation {
+ animation-duration: 0.5s;
+ animation-name: color-keyframes;
+}
+#test { position: relative; }
+</style>
+<div id=test>
+Test that a simple animation on an element with a layer doesn't generate compositing updates.
+</div>
+<script>
+let initialCompositingUpdateCount = 0;
+
+if (window.internals)
+ internals.updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks();
+
+setTimeout(() => {
+ test.className = "color-animation";
+ if (window.internals) {
+ internals.updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks();
+ initialCompositingUpdateCount = internals.compositingUpdateCount();
+ }
+}, 0);
+
+test._onanimationend_ = () => {
+ if (!window.internals)
+ return;
+ log.innerHTML += `compositingUpdateCount: ${internals.compositingUpdateCount() - initialCompositingUpdateCount}`;
+ testRunner.notifyDone();
+};
+
+</script>
+<div id=log></div>
Modified: trunk/Source/WebCore/ChangeLog (215346 => 215347)
--- trunk/Source/WebCore/ChangeLog 2017-04-13 23:20:03 UTC (rev 215346)
+++ trunk/Source/WebCore/ChangeLog 2017-04-13 23:20:50 UTC (rev 215347)
@@ -1,3 +1,30 @@
+2017-04-13 Antti Koivisto <[email protected]>
+
+ Don't invalidate composition for style changes in non-composited layers
+ https://bugs.webkit.org/show_bug.cgi?id=170805
+ <rdar://problem/31606185>
+
+ Reviewed by Simon Fraser.
+
+ Test: compositing/updates/animation-non-composited.html
+
+ In most cases they can't affect composition. Composition updates are expensive, this can
+ save a lot of work (tumblr.com animations hit this at the moment).
+
+ * rendering/RenderElement.h:
+ (WebCore::RenderElement::createsGroup):
+ (WebCore::RenderElement::createsGroupForStyle):
+
+ Factor to a static function so we can test style directly.
+
+ * rendering/RenderLayerCompositor.cpp:
+ (WebCore::RenderLayerCompositor::layerStyleChanged):
+ (WebCore::RenderLayerCompositor::styleChangeMayAffectIndirectCompositingReasons):
+
+ Test if style change might cause compositing change that can't be determined without compositing update.
+
+ * rendering/RenderLayerCompositor.h:
+
2017-04-13 JF Bastien <[email protected]>
WebAssembly: manage memory better
Modified: trunk/Source/WebCore/rendering/RenderElement.h (215346 => 215347)
--- trunk/Source/WebCore/rendering/RenderElement.h 2017-04-13 23:20:03 UTC (rev 215346)
+++ trunk/Source/WebCore/rendering/RenderElement.h 2017-04-13 23:20:50 UTC (rev 215347)
@@ -140,7 +140,8 @@
bool mayCauseRepaintInsideViewport(const IntRect* visibleRect = nullptr) const;
// Returns true if this renderer requires a new stacking context.
- bool createsGroup() const { return isTransparent() || hasMask() || hasClipPath() || hasFilter() || hasBackdropFilter() || hasBlendMode(); }
+ static bool createsGroupForStyle(const RenderStyle&);
+ bool createsGroup() const { return createsGroupForStyle(style()); }
bool isTransparent() const { return style().opacity() < 1.0f; }
float opacity() const { return style().opacity(); }
@@ -444,6 +445,11 @@
|| isRenderView();
}
+inline bool RenderElement::createsGroupForStyle(const RenderStyle& style)
+{
+ return style.opacity() < 1.0f || style.hasMask() || style.clipPath() || style.hasFilter() || style.hasBackdropFilter() || style.hasBlendMode();
+}
+
inline bool RenderObject::isRenderLayerModelObject() const
{
return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderLayerModelObject();
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (215346 => 215347)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2017-04-13 23:20:03 UTC (rev 215346)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2017-04-13 23:20:50 UTC (rev 215347)
@@ -924,16 +924,31 @@
if (diff == StyleDifferenceEqual)
return;
- m_layerNeedsCompositingUpdate = true;
-
const RenderStyle& newStyle = layer.renderer().style();
- if (updateLayerCompositingState(layer) || (oldStyle && styleChangeRequiresLayerRebuild(layer, *oldStyle, newStyle)))
+ if (updateLayerCompositingState(layer) || (oldStyle && styleChangeRequiresLayerRebuild(layer, *oldStyle, newStyle))) {
setCompositingLayersNeedRebuild();
- else if (layer.isComposited()) {
+ m_layerNeedsCompositingUpdate = true;
+ return;
+ }
+
+ if (layer.isComposited()) {
// FIXME: updating geometry here is potentially harmful, because layout is not up-to-date.
layer.backing()->updateGeometry();
layer.backing()->updateAfterDescendants();
+ m_layerNeedsCompositingUpdate = true;
+ return;
}
+
+ // We don't have any direct reasons for this style change to affect layer composition. Test if it might affect things indirectly.
+ if (oldStyle && styleChangeMayAffectIndirectCompositingReasons(layer.renderer(), *oldStyle)) {
+ m_layerNeedsCompositingUpdate = true;
+ return;
+ }
+
+ if (layer.isRootLayer()) {
+ // Needed for scroll bars.
+ m_layerNeedsCompositingUpdate = true;
+ }
}
bool RenderLayerCompositor::canCompositeClipPath(const RenderLayer& layer)
@@ -2600,6 +2615,28 @@
return false;
}
+bool RenderLayerCompositor::styleChangeMayAffectIndirectCompositingReasons(const RenderLayerModelObject& renderer, const RenderStyle& oldStyle)
+{
+ if (renderer.isRenderNamedFlowFragmentContainer())
+ return true;
+
+ auto& style = renderer.style();
+ if (RenderElement::createsGroupForStyle(style) != RenderElement::createsGroupForStyle(oldStyle))
+ return true;
+ if (style.isolation() != oldStyle.isolation())
+ return true;
+ if (style.hasTransform() != oldStyle.hasTransform())
+ return true;
+ if (style.boxReflect() != oldStyle.boxReflect())
+ return true;
+ if (style.transformStyle3D() != oldStyle.transformStyle3D())
+ return true;
+ if (style.hasPerspective() != oldStyle.hasPerspective())
+ return true;
+
+ return false;
+}
+
bool RenderLayerCompositor::requiresCompositingForFilters(RenderLayerModelObject& renderer) const
{
#if ENABLE(FILTERS_LEVEL_2)
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.h (215346 => 215347)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.h 2017-04-13 23:20:03 UTC (rev 215346)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.h 2017-04-13 23:20:50 UTC (rev 215347)
@@ -431,6 +431,7 @@
bool requiresCompositingForPosition(RenderLayerModelObject&, const RenderLayer&, RenderLayer::ViewportConstrainedNotCompositedReason* = nullptr) const;
bool requiresCompositingForOverflowScrolling(const RenderLayer&) const;
bool requiresCompositingForIndirectReason(RenderLayerModelObject&, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const;
+ static bool styleChangeMayAffectIndirectCompositingReasons(const RenderLayerModelObject& renderer, const RenderStyle& oldStyle);
#if PLATFORM(IOS)
bool requiresCompositingForScrolling(const RenderLayer&) const;