<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[183970] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/183970">183970</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2015-05-07 18:46:59 -0700 (Thu, 07 May 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>REGRESSION (<a href="http://trac.webkit.org/projects/webkit/changeset/183300">r183300</a>): Fixed elements flash when scrolling
https://bugs.webkit.org/show_bug.cgi?id=144778
rdar://problem/20769741

Reviewed by Dean Jackson.

After <a href="http://trac.webkit.org/projects/webkit/changeset/183300">r183300</a> 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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsGraphicsLayerh">trunk/Source/WebCore/platform/graphics/GraphicsLayer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscaGraphicsLayerCAcpp">trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscaGraphicsLayerCAh">trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderLayerBackingcpp">trunk/Source/WebCore/rendering/RenderLayerBacking.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderLayerBackingh">trunk/Source/WebCore/rendering/RenderLayerBacking.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (183969 => 183970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-05-08 01:23:49 UTC (rev 183969)
+++ trunk/Source/WebCore/ChangeLog        2015-05-08 01:46:59 UTC (rev 183970)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2015-05-07  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        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.
+
</ins><span class="cx"> 2015-05-07  Sam Weinig  &lt;sam@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Consider implementing Document.scrollingElement
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsGraphicsLayerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.h (183969 => 183970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.h        2015-05-08 01:23:49 UTC (rev 183969)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.h        2015-05-08 01:46:59 UTC (rev 183970)
</span><span class="lines">@@ -490,6 +490,10 @@
</span><span class="cx"> 
</span><span class="cx">     float pageScaleFactor() const { return m_client.pageScaleFactor(); }
</span><span class="cx">     float deviceScaleFactor() const { return m_client.deviceScaleFactor(); }
</span><ins>+    
+    // Whether this layer (and descendants) can detach backing store when outside the coverage area.
+    virtual void setAllowsBackingStoreDetachment(bool) { }
+    virtual bool allowsBackingStoreDetachment() const { return true; }
</ins><span class="cx"> 
</span><span class="cx">     virtual void deviceOrPageScaleFactorChanged() { }
</span><span class="cx">     WEBCORE_EXPORT void noteDeviceOrPageScaleFactorChangedIncludingDescendants();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscaGraphicsLayerCAcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (183969 => 183970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp        2015-05-08 01:23:49 UTC (rev 183969)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp        2015-05-08 01:46:59 UTC (rev 183970)
</span><span class="lines">@@ -353,6 +353,7 @@
</span><span class="cx">     : GraphicsLayer(layerType, client)
</span><span class="cx">     , m_needsFullRepaint(false)
</span><span class="cx">     , m_usingBackdropLayerType(false)
</span><ins>+    , m_allowsBackingStoreDetachment(true)
</ins><span class="cx">     , m_intersectsCoverageRect(true)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -1252,7 +1253,7 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void GraphicsLayerCA::setVisibleAndCoverageRects(const VisibleAndCoverageRects&amp; rects)
</del><ins>+void GraphicsLayerCA::setVisibleAndCoverageRects(const VisibleAndCoverageRects&amp; rects, bool allowBackingStoreDetachment)
</ins><span class="cx"> {
</span><span class="cx">     bool visibleRectChanged = rects.visibleRect != m_visibleRect;
</span><span class="cx">     bool coverageRectChanged = rects.coverageRect != m_coverageRect;
</span><span class="lines">@@ -1275,7 +1276,7 @@
</span><span class="cx">         m_coverageRect = rects.coverageRect;
</span><span class="cx"> 
</span><span class="cx">         // FIXME: we need to take reflections into account when determining whether this layer intersects the coverage rect.
</span><del>-        m_intersectsCoverageRect = m_coverageRect.intersects(FloatRect(m_boundsOrigin, size()));
</del><ins>+        m_intersectsCoverageRect = !allowBackingStoreDetachment || m_coverageRect.intersects(FloatRect(m_boundsOrigin, size()));
</ins><span class="cx"> 
</span><span class="cx">         if (GraphicsLayerCA* maskLayer = downcast&lt;GraphicsLayerCA&gt;(m_maskLayer)) {
</span><span class="cx">             maskLayer-&gt;m_uncommittedChanges |= CoverageRectChanged;
</span><span class="lines">@@ -1300,7 +1301,7 @@
</span><span class="cx">             localState.setLastPlanarSecondaryQuad(&amp;secondaryQuad);
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    setVisibleAndCoverageRects(rects);
</del><ins>+    setVisibleAndCoverageRects(rects, m_allowsBackingStoreDetachment &amp;&amp; commitState.ancestorsAllowBackingStoreDetachment);
</ins><span class="cx"> 
</span><span class="cx"> #ifdef VISIBLE_TILE_WASH
</span><span class="cx">     // Use having a transform as a key to making the tile wash layer. If every layer gets a wash,
</span><span class="lines">@@ -1343,6 +1344,8 @@
</span><span class="cx">         childCommitState.ancestorHasTransformAnimation = true;
</span><span class="cx">         affectedByTransformAnimation = true;
</span><span class="cx">     }
</span><ins>+    
+    childCommitState.ancestorsAllowBackingStoreDetachment &amp;= m_allowsBackingStoreDetachment;
</ins><span class="cx"> 
</span><span class="cx">     if (GraphicsLayerCA* maskLayer = downcast&lt;GraphicsLayerCA&gt;(m_maskLayer))
</span><span class="cx">         maskLayer-&gt;commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition);
</span><span class="lines">@@ -3625,6 +3628,15 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void GraphicsLayerCA::setAllowsBackingStoreDetachment(bool allowDetachment)
+{
+    if (allowDetachment == m_allowsBackingStoreDetachment)
+        return;
+
+    m_allowsBackingStoreDetachment = allowDetachment;
+    noteLayerPropertyChanged(CoverageRectChanged);
+}
+
</ins><span class="cx"> void GraphicsLayerCA::deviceOrPageScaleFactorChanged()
</span><span class="cx"> {
</span><span class="cx">     noteChangesForScaleSensitiveProperties();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscaGraphicsLayerCAh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h (183969 => 183970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h        2015-05-08 01:23:49 UTC (rev 183969)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h        2015-05-08 01:46:59 UTC (rev 183970)
</span><span class="lines">@@ -148,12 +148,9 @@
</span><span class="cx">     virtual FloatSize pixelAlignmentOffset() const override { return m_pixelAlignmentOffset; }
</span><span class="cx"> 
</span><span class="cx">     struct CommitState {
</span><del>-        bool ancestorHasTransformAnimation;
-        int treeDepth;
-        CommitState()
-            : ancestorHasTransformAnimation(false)
-            , treeDepth(0)
-        { }
</del><ins>+        int treeDepth { 0 };
+        bool ancestorHasTransformAnimation { false };
+        bool ancestorsAllowBackingStoreDetachment { true };
</ins><span class="cx">     };
</span><span class="cx">     void recursiveCommitChanges(const CommitState&amp;, const TransformState&amp;, float pageScaleFactor = 1, const FloatPoint&amp; positionRelativeToBase = FloatPoint(), bool affectedByPageScale = false);
</span><span class="cx"> 
</span><span class="lines">@@ -197,6 +194,9 @@
</span><span class="cx"> 
</span><span class="cx">     virtual bool isCommittingChanges() const override { return m_isCommittingChanges; }
</span><span class="cx"> 
</span><ins>+    WEBCORE_EXPORT virtual void setAllowsBackingStoreDetachment(bool) override;
+    WEBCORE_EXPORT virtual bool allowsBackingStoreDetachment() const override { return m_allowsBackingStoreDetachment; }
+
</ins><span class="cx">     WEBCORE_EXPORT virtual double backingStoreMemoryEstimate() const override;
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT virtual bool shouldRepaintOnSizeChange() const override;
</span><span class="lines">@@ -293,7 +293,7 @@
</span><span class="cx">     const FloatRect&amp; visibleRect() const { return m_visibleRect; }
</span><span class="cx">     const FloatRect&amp; coverageRect() const { return m_coverageRect; }
</span><span class="cx"> 
</span><del>-    void setVisibleAndCoverageRects(const VisibleAndCoverageRects&amp;);
</del><ins>+    void setVisibleAndCoverageRects(const VisibleAndCoverageRects&amp;, bool allowBackingStoreDetachment);
</ins><span class="cx">     
</span><span class="cx">     static FloatRect adjustTiledLayerVisibleRect(TiledBacking*, const FloatRect&amp; oldVisibleRect, const FloatRect&amp; newVisibleRect, const FloatSize&amp; oldSize, const FloatSize&amp; newSize);
</span><span class="cx"> 
</span><span class="lines">@@ -510,6 +510,7 @@
</span><span class="cx">     ContentsLayerPurpose m_contentsLayerPurpose { NoContentsLayer };
</span><span class="cx">     bool m_needsFullRepaint : 1;
</span><span class="cx">     bool m_usingBackdropLayerType : 1;
</span><ins>+    bool m_allowsBackingStoreDetachment : 1;
</ins><span class="cx">     bool m_intersectsCoverageRect : 1;
</span><span class="cx"> 
</span><span class="cx">     Color m_contentsSolidColor;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderLayerBackingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (183969 => 183970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp        2015-05-08 01:23:49 UTC (rev 183969)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp        2015-05-08 01:46:59 UTC (rev 183970)
</span><span class="lines">@@ -1569,6 +1569,11 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole(bool viewportCoordinated)
+{
+    m_graphicsLayer-&gt;setAllowsBackingStoreDetachment(!viewportCoordinated);
+}
+
</ins><span class="cx"> GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
</span><span class="cx"> {
</span><span class="cx">     unsigned phase = 0;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderLayerBackingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.h (183969 => 183970)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderLayerBacking.h        2015-05-08 01:23:49 UTC (rev 183969)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.h        2015-05-08 01:46:59 UTC (rev 183970)
</span><span class="lines">@@ -126,12 +126,15 @@
</span><span class="cx">             break;
</span><span class="cx">         case ViewportConstrained:
</span><span class="cx">             m_viewportConstrainedNodeID = nodeID;
</span><ins>+            setIsScrollCoordinatedWithViewportConstrainedRole(nodeID);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     ScrollingNodeID scrollingNodeIDForChildren() const { return m_scrollingNodeID ? m_scrollingNodeID : m_viewportConstrainedNodeID; }
</span><span class="cx"> 
</span><ins>+    void setIsScrollCoordinatedWithViewportConstrainedRole(bool);
+
</ins><span class="cx">     bool hasMaskLayer() const { return m_maskLayer != 0; }
</span><span class="cx">     bool hasChildClippingMaskLayer() const { return m_childClippingMaskLayer != nullptr; }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>