REGRESSION (r183300): Fixed elements flash when scrolling
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 May 2015 01:46:59 +0000 (01:46 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 May 2015 01:46:59 +0000 (01:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=144778
rdar://problem/20769741

Reviewed by Dean Jackson.

After r183300 we can detached layer backing store when outside the coverage region.
However, position:fixed layers are moved around by the ScrollingCoordinator behind
GraphicsLayer's back, so we can do layer flushes with stale information about layer
geometry.

To avoid dropping backing store for layers in this situation, prevent backing
store detachment on layers registered with the ScrollingCoordinator as viewport-constrained
layers. Preventing detachment on a layer also prevents detachment on all descendant
layers.

* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::setAllowsBackingStoreDetachment):
(WebCore::GraphicsLayer::allowsBackingStoreDetachment):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::GraphicsLayerCA):
(WebCore::GraphicsLayerCA::setVisibleAndCoverageRects): Set m_intersectsCoverageRect to true
if backing store detachment is prevented.
(WebCore::GraphicsLayerCA::recursiveCommitChanges): Set a bit in the CommitState to
communicate to descendants that detachment is prevented.
* platform/graphics/ca/GraphicsLayerCA.h:
(WebCore::GraphicsLayerCA::CommitState::CommitState): Deleted.
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole):
* rendering/RenderLayerBacking.h:
(WebCore::RenderLayerBacking::setScrollingNodeIDForRole): If registering with a non-zero
nodeID for the ViewportConstrained role, turn off backing store detachment.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@183970 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/GraphicsLayer.h
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h

index 680480c20ded5cc45f2048488559e132f1170cda..5ded62f6a064bc85d1eb9b93914e321c48ef9cc3 100644 (file)
@@ -1,3 +1,38 @@
+2015-05-07  Simon Fraser  <simon.fraser@apple.com>
+
+        REGRESSION (r183300): Fixed elements flash when scrolling
+        https://bugs.webkit.org/show_bug.cgi?id=144778
+        rdar://problem/20769741
+
+        Reviewed by Dean Jackson.
+
+        After r183300 we can detached layer backing store when outside the coverage region.
+        However, position:fixed layers are moved around by the ScrollingCoordinator behind
+        GraphicsLayer's back, so we can do layer flushes with stale information about layer
+        geometry.
+        
+        To avoid dropping backing store for layers in this situation, prevent backing
+        store detachment on layers registered with the ScrollingCoordinator as viewport-constrained
+        layers. Preventing detachment on a layer also prevents detachment on all descendant
+        layers.
+
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::setAllowsBackingStoreDetachment):
+        (WebCore::GraphicsLayer::allowsBackingStoreDetachment):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::GraphicsLayerCA):
+        (WebCore::GraphicsLayerCA::setVisibleAndCoverageRects): Set m_intersectsCoverageRect to true
+        if backing store detachment is prevented.
+        (WebCore::GraphicsLayerCA::recursiveCommitChanges): Set a bit in the CommitState to 
+        communicate to descendants that detachment is prevented.
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        (WebCore::GraphicsLayerCA::CommitState::CommitState): Deleted.
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole):
+        * rendering/RenderLayerBacking.h:
+        (WebCore::RenderLayerBacking::setScrollingNodeIDForRole): If registering with a non-zero
+        nodeID for the ViewportConstrained role, turn off backing store detachment.
+
 2015-05-07  Sam Weinig  <sam@webkit.org>
 
         Consider implementing Document.scrollingElement
index 275d3f0fea9c0e1b9dbbe1a58f519b41b3501bd1..9fa72513b236bad59a06d8e3082bf8243a15751a 100644 (file)
@@ -490,6 +490,10 @@ public:
 
     float pageScaleFactor() const { return m_client.pageScaleFactor(); }
     float deviceScaleFactor() const { return m_client.deviceScaleFactor(); }
+    
+    // Whether this layer (and descendants) can detach backing store when outside the coverage area.
+    virtual void setAllowsBackingStoreDetachment(bool) { }
+    virtual bool allowsBackingStoreDetachment() const { return true; }
 
     virtual void deviceOrPageScaleFactorChanged() { }
     WEBCORE_EXPORT void noteDeviceOrPageScaleFactorChangedIncludingDescendants();
index bd6400f7d01eac3b0e10c3099753c5cec3faf69d..a5e2c178c34602e9f69c1f58655c918bf17b8aac 100644 (file)
@@ -353,6 +353,7 @@ GraphicsLayerCA::GraphicsLayerCA(Type layerType, GraphicsLayerClient& client)
     : GraphicsLayer(layerType, client)
     , m_needsFullRepaint(false)
     , m_usingBackdropLayerType(false)
+    , m_allowsBackingStoreDetachment(true)
     , m_intersectsCoverageRect(true)
 {
 }
@@ -1252,7 +1253,7 @@ bool GraphicsLayerCA::adjustCoverageRect(VisibleAndCoverageRects& rects, const F
     return true;
 }
 
-void GraphicsLayerCA::setVisibleAndCoverageRects(const VisibleAndCoverageRects& rects)
+void GraphicsLayerCA::setVisibleAndCoverageRects(const VisibleAndCoverageRects& rects, bool allowBackingStoreDetachment)
 {
     bool visibleRectChanged = rects.visibleRect != m_visibleRect;
     bool coverageRectChanged = rects.coverageRect != m_coverageRect;
@@ -1275,7 +1276,7 @@ void GraphicsLayerCA::setVisibleAndCoverageRects(const VisibleAndCoverageRects&
         m_coverageRect = rects.coverageRect;
 
         // FIXME: we need to take reflections into account when determining whether this layer intersects the coverage rect.
-        m_intersectsCoverageRect = m_coverageRect.intersects(FloatRect(m_boundsOrigin, size()));
+        m_intersectsCoverageRect = !allowBackingStoreDetachment || m_coverageRect.intersects(FloatRect(m_boundsOrigin, size()));
 
         if (GraphicsLayerCA* maskLayer = downcast<GraphicsLayerCA>(m_maskLayer)) {
             maskLayer->m_uncommittedChanges |= CoverageRectChanged;
@@ -1300,7 +1301,7 @@ void GraphicsLayerCA::recursiveCommitChanges(const CommitState& commitState, con
             localState.setLastPlanarSecondaryQuad(&secondaryQuad);
         }
     }
-    setVisibleAndCoverageRects(rects);
+    setVisibleAndCoverageRects(rects, m_allowsBackingStoreDetachment && commitState.ancestorsAllowBackingStoreDetachment);
 
 #ifdef VISIBLE_TILE_WASH
     // Use having a transform as a key to making the tile wash layer. If every layer gets a wash,
@@ -1343,6 +1344,8 @@ void GraphicsLayerCA::recursiveCommitChanges(const CommitState& commitState, con
         childCommitState.ancestorHasTransformAnimation = true;
         affectedByTransformAnimation = true;
     }
+    
+    childCommitState.ancestorsAllowBackingStoreDetachment &= m_allowsBackingStoreDetachment;
 
     if (GraphicsLayerCA* maskLayer = downcast<GraphicsLayerCA>(m_maskLayer))
         maskLayer->commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition);
@@ -3625,6 +3628,15 @@ void GraphicsLayerCA::updateOpacityOnLayer()
     }
 }
 
+void GraphicsLayerCA::setAllowsBackingStoreDetachment(bool allowDetachment)
+{
+    if (allowDetachment == m_allowsBackingStoreDetachment)
+        return;
+
+    m_allowsBackingStoreDetachment = allowDetachment;
+    noteLayerPropertyChanged(CoverageRectChanged);
+}
+
 void GraphicsLayerCA::deviceOrPageScaleFactorChanged()
 {
     noteChangesForScaleSensitiveProperties();
index 42112e9d968bf2ee0a06e68f76d61e5579ed7ea9..4f0e6a77b4afaec3ec68b6ce56591e06041d98f3 100644 (file)
@@ -148,12 +148,9 @@ public:
     virtual FloatSize pixelAlignmentOffset() const override { return m_pixelAlignmentOffset; }
 
     struct CommitState {
-        bool ancestorHasTransformAnimation;
-        int treeDepth;
-        CommitState()
-            : ancestorHasTransformAnimation(false)
-            , treeDepth(0)
-        { }
+        int treeDepth { 0 };
+        bool ancestorHasTransformAnimation { false };
+        bool ancestorsAllowBackingStoreDetachment { true };
     };
     void recursiveCommitChanges(const CommitState&, const TransformState&, float pageScaleFactor = 1, const FloatPoint& positionRelativeToBase = FloatPoint(), bool affectedByPageScale = false);
 
@@ -197,6 +194,9 @@ private:
 
     virtual bool isCommittingChanges() const override { return m_isCommittingChanges; }
 
+    WEBCORE_EXPORT virtual void setAllowsBackingStoreDetachment(bool) override;
+    WEBCORE_EXPORT virtual bool allowsBackingStoreDetachment() const override { return m_allowsBackingStoreDetachment; }
+
     WEBCORE_EXPORT virtual double backingStoreMemoryEstimate() const override;
 
     WEBCORE_EXPORT virtual bool shouldRepaintOnSizeChange() const override;
@@ -293,7 +293,7 @@ private:
     const FloatRect& visibleRect() const { return m_visibleRect; }
     const FloatRect& coverageRect() const { return m_coverageRect; }
 
-    void setVisibleAndCoverageRects(const VisibleAndCoverageRects&);
+    void setVisibleAndCoverageRects(const VisibleAndCoverageRects&, bool allowBackingStoreDetachment);
     
     static FloatRect adjustTiledLayerVisibleRect(TiledBacking*, const FloatRect& oldVisibleRect, const FloatRect& newVisibleRect, const FloatSize& oldSize, const FloatSize& newSize);
 
@@ -510,6 +510,7 @@ private:
     ContentsLayerPurpose m_contentsLayerPurpose { NoContentsLayer };
     bool m_needsFullRepaint : 1;
     bool m_usingBackdropLayerType : 1;
+    bool m_allowsBackingStoreDetachment : 1;
     bool m_intersectsCoverageRect : 1;
 
     Color m_contentsSolidColor;
index 7a45d2a6c8058f69f1b5252e7531fcd64a58540b..afd5f35d053b4e796a2eeab0176699501421a198 100644 (file)
@@ -1569,6 +1569,11 @@ void RenderLayerBacking::detachFromScrollingCoordinator(LayerScrollCoordinationR
     }
 }
 
+void RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole(bool viewportCoordinated)
+{
+    m_graphicsLayer->setAllowsBackingStoreDetachment(!viewportCoordinated);
+}
+
 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
 {
     unsigned phase = 0;
index 9868a5365dadd8288367dd49d994146986649a23..7ca629c84813297524f40259d8e8ce8b3cc32140 100644 (file)
@@ -126,12 +126,15 @@ public:
             break;
         case ViewportConstrained:
             m_viewportConstrainedNodeID = nodeID;
+            setIsScrollCoordinatedWithViewportConstrainedRole(nodeID);
             break;
         }
     }
     
     ScrollingNodeID scrollingNodeIDForChildren() const { return m_scrollingNodeID ? m_scrollingNodeID : m_viewportConstrainedNodeID; }
 
+    void setIsScrollCoordinatedWithViewportConstrainedRole(bool);
+
     bool hasMaskLayer() const { return m_maskLayer != 0; }
     bool hasChildClippingMaskLayer() const { return m_childClippingMaskLayer != nullptr; }