Title: [218735] trunk
Revision
218735
Author
[email protected]
Date
2017-06-22 21:34:14 -0700 (Thu, 22 Jun 2017)

Log Message

REGRESSION(r217695): Offscreen/overflowed items not being rendered while translating in-frame
https://bugs.webkit.org/show_bug.cgi?id=173732

Reviewed by Simon Fraser.

Source/WebCore:

If an accelerated animation starts completely outside the view we fail to create backing for it
when it moves into view.

Fix by computing the full extent rect of the animation when it starts and doing the viewport overlap
testing with that.

Test: compositing/backing/transform-transition-from-outside-view.html

* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::animationExtent):
(WebCore::GraphicsLayer::setAnimationExtent):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::computeVisibleAndCoverageRect):

    Return the current animation transformation matrix so we can use it elsewhere without recomputing.

(WebCore::GraphicsLayerCA::setVisibleAndCoverageRects):

    If we have animation extent use it instead of bounds for visibility testing.

(WebCore::GraphicsLayerCA::recursiveCommitChanges):

    Track if theres is a visible ancestor layer with a transition animation.

(WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
(WebCore::GraphicsLayerCA::updateCoverage):

    For simplicity create backing for all sublayers of a visible transform animated layer.

* platform/graphics/ca/GraphicsLayerCA.h:
(WebCore::GraphicsLayerCA::VisibleAndCoverageRects::VisibleAndCoverageRects): Deleted.
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateGeometry):

    Pass the animation extent (including descendants) to GraphicsLayer.

LayoutTests:

* compositing/backing/transform-transition-from-outside-view-expected.txt: Added.
* compositing/backing/transform-transition-from-outside-view.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (218734 => 218735)


--- trunk/LayoutTests/ChangeLog	2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/LayoutTests/ChangeLog	2017-06-23 04:34:14 UTC (rev 218735)
@@ -1,3 +1,13 @@
+2017-06-22  Antti Koivisto  <[email protected]>
+
+        REGRESSION(r217695): Offscreen/overflowed items not being rendered while translating in-frame
+        https://bugs.webkit.org/show_bug.cgi?id=173732
+
+        Reviewed by Simon Fraser.
+
+        * compositing/backing/transform-transition-from-outside-view-expected.txt: Added.
+        * compositing/backing/transform-transition-from-outside-view.html: Added.
+
 2017-06-22  Myles C. Maxfield  <[email protected]>
 
         @font-face rules with invalid primary fonts never download their secondary fonts

Added: trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view-expected.txt (0 => 218735)


--- trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view-expected.txt	2017-06-23 04:34:14 UTC (rev 218735)
@@ -0,0 +1,28 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 600.00)
+  (backingStoreAttached 1)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (contentsOpaque 1)
+      (backingStoreAttached 1)
+      (children 1
+        (GraphicsLayer
+          (position 94.00 86.00)
+          (bounds 148.00 128.00)
+          (drawsContent 1)
+          (backingStoreAttached 1)
+          (children 1
+            (GraphicsLayer
+              (bounds 48.00 48.00)
+              (drawsContent 1)
+              (backingStoreAttached 1)
+            )
+          )
+        )
+      )
+    )
+  )
+)
+

Added: trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view.html (0 => 218735)


--- trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view.html	2017-06-23 04:34:14 UTC (rev 218735)
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        .box {
+            width: 120px;
+            height: 100px;
+            background-color: blue;
+            margin: 100px 100px;
+            position: relative;
+            box-shadow: 0 0 10px black;
+            transition: transform 5s;
+            transform: translateX(-400px);
+        }
+
+        .sublayer {
+            width: 20px;
+            height: 20px;
+            background-color: green;
+            position: relative;
+            box-shadow: 0 0 10px black;
+            will-change: transform;
+        }
+        
+        body.changed .box {
+            transform: translateX(0px);
+        }
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function dumpLayers()
+        {
+            if (window.testRunner) {
+                output.innerText = window.internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_BACKING_STORE_ATTACHED);
+                testRunner.notifyDone();
+            }
+        }
+
+        window.addEventListener("load", function() {
+            document.body.classList.add('changed');
+            window.setTimeout(dumpLayers, 0);
+        });
+    </script>
+</head>
+<body>
+
+    <div class="box">
+        <div class="sublayer"></div>
+    </div>
+<pre id="output"></pre>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (218734 => 218735)


--- trunk/Source/WebCore/ChangeLog	2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/Source/WebCore/ChangeLog	2017-06-23 04:34:14 UTC (rev 218735)
@@ -1,3 +1,46 @@
+2017-06-22  Antti Koivisto  <[email protected]>
+
+        REGRESSION(r217695): Offscreen/overflowed items not being rendered while translating in-frame
+        https://bugs.webkit.org/show_bug.cgi?id=173732
+
+        Reviewed by Simon Fraser.
+
+        If an accelerated animation starts completely outside the view we fail to create backing for it
+        when it moves into view.
+
+        Fix by computing the full extent rect of the animation when it starts and doing the viewport overlap
+        testing with that.
+
+        Test: compositing/backing/transform-transition-from-outside-view.html
+
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::animationExtent):
+        (WebCore::GraphicsLayer::setAnimationExtent):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::computeVisibleAndCoverageRect):
+
+            Return the current animation transformation matrix so we can use it elsewhere without recomputing.
+
+        (WebCore::GraphicsLayerCA::setVisibleAndCoverageRects):
+
+            If we have animation extent use it instead of bounds for visibility testing.
+
+        (WebCore::GraphicsLayerCA::recursiveCommitChanges):
+
+            Track if theres is a visible ancestor layer with a transition animation.
+
+        (WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
+        (WebCore::GraphicsLayerCA::updateCoverage):
+
+            For simplicity create backing for all sublayers of a visible transform animated layer.
+
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        (WebCore::GraphicsLayerCA::VisibleAndCoverageRects::VisibleAndCoverageRects): Deleted.
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateGeometry):
+
+            Pass the animation extent (including descendants) to GraphicsLayer.
+
 2017-06-22  Chris Dumez  <[email protected]>
 
         ResourceLoadStatisticsStore should be ThreadSafeRefCounted

Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.h (218734 => 218735)


--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.h	2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.h	2017-06-23 04:34:14 UTC (rev 218735)
@@ -571,6 +571,9 @@
     virtual bool isGraphicsLayerTextureMapper() const { return false; }
     virtual bool isCoordinatedGraphicsLayer() const { return false; }
 
+    const std::optional<FloatRect>& animationExtent() const { return m_animationExtent; }
+    void setAnimationExtent(std::optional<FloatRect> animationExtent) { m_animationExtent = animationExtent; }
+
     static void traverse(GraphicsLayer&, const WTF::Function<void (GraphicsLayer&)>&);
 
 protected:
@@ -676,6 +679,7 @@
     FloatSize m_contentsTilePhase;
     FloatSize m_contentsTileSize;
     FloatRoundedRect m_backdropFiltersRect;
+    std::optional<FloatRect> m_animationExtent;
 
     int m_repaintCount;
     CustomAppearance m_customAppearance;

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (218734 => 218735)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2017-06-23 04:34:14 UTC (rev 218735)
@@ -1343,7 +1343,7 @@
     FloatRect clipRectForSelf(boundsOrigin, m_size);
     if (!applyWasClamped && !mapWasClamped)
         clipRectForSelf.intersect(clipRectForChildren);
-    
+
     if (masksToBounds()) {
         ASSERT(accumulation == TransformState::FlattenTransform);
         // Flatten, and replace the quad in the TransformState with one that is clipped to this layer's bounds.
@@ -1360,7 +1360,7 @@
     if (quad && !mapWasClamped && !applyWasClamped)
         coverageRect = (*quad).boundingBox();
 
-    return VisibleAndCoverageRects(clipRectForSelf, coverageRect);
+    return { clipRectForSelf, coverageRect, currentTransform };
 }
 
 bool GraphicsLayerCA::adjustCoverageRect(VisibleAndCoverageRects& rects, const FloatRect& oldVisibleRect) const
@@ -1392,11 +1392,17 @@
 {
     bool visibleRectChanged = rects.visibleRect != m_visibleRect;
     bool coverageRectChanged = rects.coverageRect != m_coverageRect;
-    if (!visibleRectChanged && !coverageRectChanged)
+    if (!visibleRectChanged && !coverageRectChanged && !animationExtent())
         return;
 
+    auto bounds = FloatRect(m_boundsOrigin, size());
+    if (auto extent = animationExtent()) {
+        // Adjust the animation extent to match the current animation position.
+        bounds = rects.animatingTransform.inverse().value_or(TransformationMatrix()).mapRect(*extent);
+    }
+
     // FIXME: we need to take reflections into account when determining whether this layer intersects the coverage rect.
-    bool intersectsCoverageRect = isViewportConstrained || rects.coverageRect.intersects(FloatRect(m_boundsOrigin, size()));
+    bool intersectsCoverageRect = isViewportConstrained || rects.coverageRect.intersects(bounds);
     if (intersectsCoverageRect != m_intersectsCoverageRect) {
         addUncommittedChanges(CoverageRectChanged);
         m_intersectsCoverageRect = intersectsCoverageRect;
@@ -1490,11 +1496,13 @@
     FloatPoint baseRelativePosition = positionRelativeToBase;
     if (affectedByPageScale)
         baseRelativePosition += m_position;
-    
+
     commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition);
 
     if (isRunningTransformAnimation()) {
         childCommitState.ancestorHasTransformAnimation = true;
+        if (m_intersectsCoverageRect)
+            childCommitState.ancestorWithTransformAnimationIntersectsCoverageRect = true;
         affectedByTransformAnimation = true;
     }
     
@@ -1744,7 +1752,7 @@
         updateContentsScale(pageScaleFactor);
 
     if (m_uncommittedChanges & CoverageRectChanged)
-        updateCoverage();
+        updateCoverage(commitState);
 
     if (m_uncommittedChanges & TilingAreaChanged) // Needs to happen after CoverageRectChanged, ContentsScaleChanged
         updateTiles();
@@ -2282,7 +2290,7 @@
     }
 }
 
-void GraphicsLayerCA::updateCoverage()
+void GraphicsLayerCA::updateCoverage(const CommitState& commitState)
 {
     // FIXME: Need to set coverage on clone layers too.
     if (TiledBacking* backing = tiledBacking()) {
@@ -2291,10 +2299,14 @@
     }
 
     if (canDetachBackingStore()) {
-        m_layer->setBackingStoreAttached(m_intersectsCoverageRect);
+        bool requiresBacking = m_intersectsCoverageRect
+            || commitState.ancestorWithTransformAnimationIntersectsCoverageRect // FIXME: Compute backing exactly for descendants of animating layers.
+            || (isRunningTransformAnimation() && !animationExtent()); // Create backing if we don't know the animation extent.
+
+        m_layer->setBackingStoreAttached(requiresBacking);
         if (m_layerClones) {
             for (auto& it : *m_layerClones)
-                it.value->setBackingStoreAttached(m_intersectsCoverageRect);
+                it.value->setBackingStoreAttached(requiresBacking);
         }
     }
 

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h (218734 => 218735)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h	2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h	2017-06-23 04:34:14 UTC (rev 218735)
@@ -157,6 +157,7 @@
         int treeDepth { 0 };
         bool ancestorHadChanges { false };
         bool ancestorHasTransformAnimation { false };
+        bool ancestorWithTransformAnimationIntersectsCoverageRect { false };
         bool ancestorIsViewportConstrained { false };
     };
     bool needsCommit(const CommitState&);
@@ -299,12 +300,7 @@
     struct VisibleAndCoverageRects {
         FloatRect visibleRect;
         FloatRect coverageRect;
-        
-        VisibleAndCoverageRects(const FloatRect& visRect, const FloatRect& covRect)
-            : visibleRect(visRect)
-            , coverageRect(covRect)
-        {
-        }
+        TransformationMatrix animatingTransform;
     };
     
     VisibleAndCoverageRects computeVisibleAndCoverageRect(TransformState&, bool accumulateTransform, ComputeVisibleRectFlags = RespectAnimatingTransforms) const;
@@ -400,7 +396,7 @@
     void updateBackfaceVisibility();
     void updateStructuralLayer();
     void updateDrawsContent();
-    void updateCoverage();
+    void updateCoverage(const CommitState&);
     void updateBackgroundColor();
     void updateUserInteractionEnabled();
 

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (218734 => 218735)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2017-06-23 04:34:14 UTC (rev 218735)
@@ -945,13 +945,17 @@
         return;
 
     const RenderStyle& style = renderer().style();
+
+    bool isRunningAcceleratedTransformAnimation = renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform, AnimationBase::Running | AnimationBase::Paused);
+    bool isRunningAcceleratedOpacityAnimation = renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity, AnimationBase::Running | AnimationBase::Paused);
+
     // Set transform property, if it is not animating. We have to do this here because the transform
     // is affected by the layer dimensions.
-    if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform, AnimationBase::Running | AnimationBase::Paused))
+    if (!isRunningAcceleratedTransformAnimation)
         updateTransform(style);
 
     // Set opacity, if it is not animating.
-    if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity, AnimationBase::Running | AnimationBase::Paused))
+    if (!isRunningAcceleratedOpacityAnimation)
         updateOpacity(style);
 
     updateFilters(style);
@@ -978,6 +982,14 @@
     m_graphicsLayer->setPosition(primaryGraphicsLayerRect.location());
     m_graphicsLayer->setSize(primaryGraphicsLayerRect.size());
 
+    auto computeAnimationExtent = [&] () -> std::optional<FloatRect> {
+        LayoutRect animatedBounds;
+        if (isRunningAcceleratedTransformAnimation && m_owningLayer.getOverlapBoundsIncludingChildrenAccountingForTransformAnimations(animatedBounds))
+            return FloatRect(animatedBounds);
+        return { };
+    };
+    m_graphicsLayer->setAnimationExtent(computeAnimationExtent());
+
     ComputedOffsets rendererOffset(m_owningLayer, LayoutRect(), parentGraphicsLayerRect, primaryGraphicsLayerRect);
     if (m_ancestorClippingLayer) {
         // Clipping layer is parented in the ancestor layer.
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to