Title: [215347] trunk
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;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to