REGRESSION (r183794): Garbage tiles when body background switches to fixed
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 May 2015 04:43:05 +0000 (04:43 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 May 2015 04:43:05 +0000 (04:43 +0000)
https://bugs.webkit.org/show_bug.cgi?id=145032
rdar://problem/20963679

Reviewed by Dean Jackson.

Source/WebCore:

After r183794 (or possibly an earlier commit), we failed to dynamically update
the configuration of layers that handled fixed background attachment on the root.

This would result in unpainted tiles, and non-fixed-background behavior.

Fix by calling RenderLayerCompositor::rootOrBodyStyleChanged() whenever the
style changes on the root or body renderers, and triggering a compositing update
if the fixedness of the background changes. It calls the existing rootBackgroundTransparencyChanged()
if the color changes.

Test: platform/mac-wk2/tiled-drawing/toggle-to-fixed-background.html

* rendering/RenderBox.cpp:
(WebCore::RenderBox::styleDidChange):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::rootOrBodyStyleChanged):
(WebCore::RenderLayerCompositor::rootBackgroundTransparencyChanged):
* rendering/RenderLayerCompositor.h:

LayoutTests:

Test that toggles the attachment of the body background to fixed, then dumps layers.

* platform/mac-wk2/tiled-drawing/toggle-to-fixed-background-expected.txt: Added.
* platform/mac-wk2/tiled-drawing/toggle-to-fixed-background.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/platform/mac-wk2/tiled-drawing/toggle-to-fixed-background-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-wk2/tiled-drawing/toggle-to-fixed-background.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h

index c92e97f..d004a7c 100644 (file)
@@ -1,3 +1,16 @@
+2015-05-14  Simon Fraser  <simon.fraser@apple.com>
+
+        REGRESSION (r183794): Garbage tiles when body background switches to fixed
+        https://bugs.webkit.org/show_bug.cgi?id=145032
+        rdar://problem/20963679
+
+        Reviewed by Dean Jackson.
+        
+        Test that toggles the attachment of the body background to fixed, then dumps layers.
+
+        * platform/mac-wk2/tiled-drawing/toggle-to-fixed-background-expected.txt: Added.
+        * platform/mac-wk2/tiled-drawing/toggle-to-fixed-background.html: Added.
+
 2015-05-13  Ryosuke Niwa  <rniwa@webkit.org>
 
         Crash in ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline
diff --git a/LayoutTests/platform/mac-wk2/tiled-drawing/toggle-to-fixed-background-expected.txt b/LayoutTests/platform/mac-wk2/tiled-drawing/toggle-to-fixed-background-expected.txt
new file mode 100644 (file)
index 0000000..d4e2c2b
--- /dev/null
@@ -0,0 +1,31 @@
+Toggling to a fixed background on the body should make a layer for the background.
+
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 785.00 5024.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 5024.00)
+      (children 2
+        (GraphicsLayer
+          (anchor 0.00 0.00)
+          (bounds 785.00 600.00)
+          (contentsOpaque 1)
+          (drawsContent 1)
+          (backgroundColor #FFFFFF)
+        )
+        (GraphicsLayer
+          (bounds 785.00 5024.00)
+          (children 1
+            (GraphicsLayer
+              (position 8.00 50.00)
+              (bounds 100.00 100.00)
+              (contentsOpaque 1)
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/mac-wk2/tiled-drawing/toggle-to-fixed-background.html b/LayoutTests/platform/mac-wk2/tiled-drawing/toggle-to-fixed-background.html
new file mode 100644 (file)
index 0000000..db88fdf
--- /dev/null
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        body {
+            background-image: linear-gradient(to top, blue, white);
+            height: 5000px;
+        }
+
+        body.fixed {
+            background-attachment: fixed;
+        }
+
+        #layers {
+            margin: 100px;
+            background-color: silver;
+        }
+        
+        .box {
+            height: 100px;
+            width: 100px;
+            background-color: blue;
+        }
+        .composited {
+            -webkit-transform: translateZ(0);
+        }
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function documentLoaded()
+        {
+            window.setTimeout(doTest, 0);
+        }
+        
+        function doTest()
+        {
+            document.body.classList.add('fixed');
+
+            if (window.internals)
+                document.getElementById('layers').textContent = window.internals.layerTreeAsText(document);
+            
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+        window.addEventListener('load', documentLoaded, false);
+    </script>
+</head>
+<body>
+
+<p>Toggling to a fixed background on the body should make a layer for the background.</p>
+<div class="composited box">
+    
+</div>
+<pre id="layers"></pre>
+
+</body>
+</html>
index 84725cf..c6008c9 100644 (file)
@@ -1,3 +1,30 @@
+2015-05-14  Simon Fraser  <simon.fraser@apple.com>
+
+        REGRESSION (r183794): Garbage tiles when body background switches to fixed
+        https://bugs.webkit.org/show_bug.cgi?id=145032
+        rdar://problem/20963679
+
+        Reviewed by Dean Jackson.
+        
+        After r183794 (or possibly an earlier commit), we failed to dynamically update
+        the configuration of layers that handled fixed background attachment on the root.
+        
+        This would result in unpainted tiles, and non-fixed-background behavior.
+        
+        Fix by calling RenderLayerCompositor::rootOrBodyStyleChanged() whenever the
+        style changes on the root or body renderers, and triggering a compositing update
+        if the fixedness of the background changes. It calls the existing rootBackgroundTransparencyChanged()
+        if the color changes.
+
+        Test: platform/mac-wk2/tiled-drawing/toggle-to-fixed-background.html
+
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::styleDidChange):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::rootOrBodyStyleChanged):
+        (WebCore::RenderLayerCompositor::rootBackgroundTransparencyChanged):
+        * rendering/RenderLayerCompositor.h:
+
 2015-05-14  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r184359 and r184362.
index accdc58..1db9e7b 100644 (file)
@@ -427,7 +427,7 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle
             downcast<RenderBlockFlow>(*rootRenderer).updateStylesForColumnChildren();
 
         if (diff != StyleDifferenceEqual)
-            view().compositor().rootBackgroundTransparencyChanged();
+            view().compositor().rootOrBodyStyleChanged(*this, oldStyle);
     }
 
 #if ENABLE(CSS_SHAPES)
index 675ea94..83d5d2e 100644 (file)
@@ -3166,16 +3166,37 @@ bool RenderLayerCompositor::viewHasTransparentBackground(Color* backgroundColor)
     return documentBackgroundColor.hasAlpha();
 }
 
-void RenderLayerCompositor::rootBackgroundTransparencyChanged()
+// We can't rely on getting layerStyleChanged() for a style change that affects the root background, because the style change may
+// be on the body which has no RenderLayer.
+void RenderLayerCompositor::rootOrBodyStyleChanged(RenderElement& renderer, const RenderStyle* oldStyle)
 {
     if (!inCompositingMode())
         return;
 
-    Color documentBackgroundColor = m_renderView.frameView().documentBackgroundColor();
-    if (m_lastDocumentBackgroundColor.isValid() && documentBackgroundColor.hasAlpha() == m_lastDocumentBackgroundColor.hasAlpha())
+    Color oldBackgroundColor;
+    if (oldStyle)
+        oldBackgroundColor = oldStyle->visitedDependentColor(CSSPropertyBackgroundColor);
+
+    if (oldBackgroundColor != renderer.style().visitedDependentColor(CSSPropertyBackgroundColor))
+        rootBackgroundTransparencyChanged();
+
+    bool hadFixedBackground = oldStyle && oldStyle->hasEntirelyFixedBackground();
+    if (hadFixedBackground != renderer.hasEntirelyFixedBackground()) {
+        setCompositingLayersNeedRebuild();
+        scheduleCompositingLayerUpdate();
+    }
+}
+
+void RenderLayerCompositor::rootBackgroundTransparencyChanged()
+{
+    if (!inCompositingMode())
         return;
 
+    Color documentBackgroundColor = m_renderView.frameView().documentBackgroundColor();
+    Color lastDocumentBackgroundColor = m_lastDocumentBackgroundColor;
     m_lastDocumentBackgroundColor = documentBackgroundColor;
+    if (lastDocumentBackgroundColor.isValid() && lastDocumentBackgroundColor.hasAlpha() == documentBackgroundColor.hasAlpha())
+        return;
 
     // FIXME: We should do something less expensive than a full layer rebuild.
     setCompositingLayersNeedRebuild();
index 66df7f3..3a8e1be 100644 (file)
@@ -164,7 +164,9 @@ public:
     bool supportsFixedRootBackgroundCompositing() const;
     bool needsFixedRootBackgroundLayer(const RenderLayer&) const;
     GraphicsLayer* fixedRootBackgroundLayer() const;
-    
+
+    void rootOrBodyStyleChanged(RenderElement&, const RenderStyle* oldStyle);
+
     // Called after the view transparency, or the document or base background color change.
     void rootBackgroundTransparencyChanged();