Allow fixed background layers to be moved by the ScrollingCoordinator
https://bugs.webkit.org/show_bug.cgi?id=107213

Source/WebCore:

Reviewed by Tim Horton.

Start using the RenderView's RenderLayerBacking's background layer for
fixed root backgrounds (those which have background images all of which have
background-attachment: fixed).

The background-layer is contained in the RenderLayer's RenderLayerBacking's
containment view, so it gets page scale applied to it, but scrolling happens
above this layer, so the background has to be counter-scrolled. We plumb
this layer through to the ScrollingCoordinator so that this counter-scrolling
can be done on the scrolling thread.

Test: platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned.html

* WebCore.xcodeproj/project.pbxproj: Add ScrollingStateScrollingNodeMac.mm
* page/scrolling/ScrollingCoordinator.cpp:
(WebCore::ScrollingCoordinator::counterScrollingLayerForFrameView): New function to get
the counter-scrolling layer.
(WebCore::ScrollingCoordinator::updateMainFrameScrollPosition): Sync or set the position of the
counter-scrolling layer just like we do for the main scrolling layer.
* page/scrolling/ScrollingCoordinator.h:
(WebCore::ScrollingCoordinator::updateScrollingNode):
* page/scrolling/ScrollingStateNode.cpp:
(WebCore::ScrollingStateNode::ScrollingStateNode): setScrollLayer() renamed to setScrollPlatformLayer(),
and added a FIXME comment because this code is confusing and possibly wrong.
* page/scrolling/ScrollingStateNode.h: Renamed setScrollLayer() to setScrollPlatformLayer().
* page/scrolling/ScrollingStateScrollingNode.cpp:
(WebCore::ScrollingStateScrollingNode::ScrollingStateScrollingNode):
* page/scrolling/ScrollingStateScrollingNode.h:
(ScrollingStateScrollingNode): Track the counter-scrolling layer.
(WebCore::ScrollingStateScrollingNode::counterScrollingLayer):
(WebCore::ScrollingStateScrollingNode::counterScrollingLayerDidChange):
(WebCore::ScrollingStateScrollingNode::setCounterScrollingLayerDidChange):
* page/scrolling/mac/ScrollingCoordinatorMac.h:
(ScrollingCoordinatorMac): Add updateScrollingNode() which is less expensive than frameViewRootLayerDidChange()
* page/scrolling/mac/ScrollingCoordinatorMac.mm:
(WebCore::ScrollingCoordinatorMac::frameViewRootLayerDidChange): Fetch the counter-scrolling layer if we have one.
(WebCore::ScrollingCoordinatorMac::setCounterScrollingLayerForNode):
(WebCore::ScrollingCoordinatorMac::updateScrollingNode):
* page/scrolling/mac/ScrollingStateNodeMac.mm:
(WebCore::ScrollingStateNode::setScrollPlatformLayer):
* page/scrolling/mac/ScrollingStateScrollingNodeMac.mm: New file for implementation of setCounterScrollingLayer().
(WebCore::ScrollingStateScrollingNode::counterScrollingPlatformLayer):
(WebCore::ScrollingStateScrollingNode::setCounterScrollingLayer):
* page/scrolling/mac/ScrollingTreeScrollingNodeMac.h:
(ScrollingTreeScrollingNodeMac):
* page/scrolling/mac/ScrollingTreeScrollingNodeMac.mm:
(WebCore::ScrollingTreeScrollingNodeMac::update):
(WebCore::ScrollingTreeScrollingNodeMac::setScrollLayerPosition):
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::fixedBackgroundPaintsInLocalCoordinates):
(WebCore::RenderBoxModelObject::calculateBackgroundImageGeometry): If we're painting into the fixed root layer,
we want to always paint with the top,left at 0,0.
* rendering/RenderBoxModelObject.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry): In the fixed root background case,
we can make the background layer viewport-sized, and we have to set its counter-scrolled position.
(WebCore::RenderLayerBacking::updateBackgroundLayer): If the background layer was created or destroyed,
we have to tell the ScrollingCoordinator.
(WebCore::RenderLayerBacking::didCommitChangesForLayer): Send the GraphicsLayer down.
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::didFlushChangesForLayer): If the background layer changed (e.g. it became
tiled) we need to tell the ScrollingCoordinator.
(WebCore::RenderLayerCompositor::rebuildCompositingLayerTree): We failed to update the borders on new
layers sometimes; this fixes that.
(WebCore::RenderLayerCompositor::frameViewDidScroll): In the non-threaded scrolling case, if we have
a fixed background layer, we need to update its position.
(WebCore::RenderLayerCompositor::fixedRootBackgroundLayerChanged): Feed the newly created/destroyed layer
down to the ScrollingCoordinator.
(WebCore::RenderLayerCompositor::supportsFixedRootBackgroundCompositing):
(WebCore::RenderLayerCompositor::needsFixedRootBackgroundLayer):
* rendering/RenderLayerCompositor.h:
* rendering/RenderObject.cpp:
(WebCore::rendererHasBackground):
(WebCore::RenderObject::styleWillChange): If the compositor supports fixed root backgrounds, we no longer
treat these as slow repaint objects.
* rendering/RenderView.cpp:
(WebCore::RenderView::rootBackgroundIsEntirelyFixed): Helper function called by RLC.
* rendering/RenderView.h:

LayoutTests:

Reviewed by Tim Horton.

One new test and new layer trees for tests affected by fixed background changes.

* platform/mac/tiled-drawing/fixed-background/fixed-body-background-body-layer-expected.txt:
* platform/mac/tiled-drawing/fixed-background/fixed-body-background-expected.txt:
* platform/mac/tiled-drawing/fixed-background/fixed-body-background-opacity-html-expected.txt:
* platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned-expected.png: Added.
* platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned-expected.txt: Copied from LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-html-background-expected.txt.
* platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned.html: Added.
* platform/mac/tiled-drawing/fixed-background/fixed-body-background-transformed-html-expected.txt:
* platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.png:
* platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.txt:
* platform/mac/tiled-drawing/fixed-background/fixed-html-background-expected.txt:
* platform/mac/tiled-drawing/fixed-background/fixed-non-propagated-body-background-expected.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@140223 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 4314d4d..86794b7 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,24 @@
+2013-01-18  Simon Fraser  <simon.fraser@apple.com>
+
+        Allow fixed background layers to be moved by the ScrollingCoordinator
+        https://bugs.webkit.org/show_bug.cgi?id=107213
+
+        Reviewed by Tim Horton.
+        
+        One new test and new layer trees for tests affected by fixed background changes.
+
+        * platform/mac/tiled-drawing/fixed-background/fixed-body-background-body-layer-expected.txt:
+        * platform/mac/tiled-drawing/fixed-background/fixed-body-background-expected.txt:
+        * platform/mac/tiled-drawing/fixed-background/fixed-body-background-opacity-html-expected.txt:
+        * platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned-expected.png: Added.
+        * platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned-expected.txt: Copied from LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-html-background-expected.txt.
+        * platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned.html: Added.
+        * platform/mac/tiled-drawing/fixed-background/fixed-body-background-transformed-html-expected.txt:
+        * platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.png:
+        * platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.txt:
+        * platform/mac/tiled-drawing/fixed-background/fixed-html-background-expected.txt:
+        * platform/mac/tiled-drawing/fixed-background/fixed-non-propagated-body-background-expected.txt:
+
 2013-01-18  Alpha Lam  <hclam@chromium.org>
 
         [chromium] Update test expectations
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-body-layer-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-body-layer-expected.txt
index 71036e7..d3a87c3 100644
--- a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-body-layer-expected.txt
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-body-layer-expected.txt
@@ -5,8 +5,9 @@
       (bounds 785.00 1600.00)
       (children 2
         (GraphicsLayer
+          (position 0.00 200.00)
           (anchor 0.00 0.00)
-          (bounds 785.00 1600.00)
+          (bounds 785.00 600.00)
           (drawsContent 1)
           (backgroundColor #FFFFFF)
         )
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-expected.txt
index bd9db65..ad671c8 100644
--- a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-expected.txt
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-expected.txt
@@ -5,8 +5,9 @@
       (bounds 785.00 1700.00)
       (children 2
         (GraphicsLayer
+          (position 0.00 200.00)
           (anchor 0.00 0.00)
-          (bounds 785.00 1700.00)
+          (bounds 785.00 600.00)
           (drawsContent 1)
           (backgroundColor #FFFFFF)
         )
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-opacity-html-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-opacity-html-expected.txt
index bd9db65..ad671c8 100644
--- a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-opacity-html-expected.txt
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-opacity-html-expected.txt
@@ -5,8 +5,9 @@
       (bounds 785.00 1700.00)
       (children 2
         (GraphicsLayer
+          (position 0.00 200.00)
           (anchor 0.00 0.00)
-          (bounds 785.00 1700.00)
+          (bounds 785.00 600.00)
           (drawsContent 1)
           (backgroundColor #FFFFFF)
         )
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned-expected.png b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned-expected.png
new file mode 100644
index 0000000..5aa65f2
--- /dev/null
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned-expected.png
Binary files differ
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned-expected.txt
new file mode 100644
index 0000000..6d96b35
--- /dev/null
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned-expected.txt
@@ -0,0 +1,29 @@
+(GraphicsLayer
+  (bounds 785.00 3700.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 3700.00)
+      (children 2
+        (GraphicsLayer
+          (position 0.00 200.00)
+          (anchor 0.00 0.00)
+          (bounds 785.00 600.00)
+          (drawsContent 1)
+          (backgroundColor #FFFFFF)
+        )
+        (GraphicsLayer
+          (bounds 785.00 3700.00)
+          (drawsContent 1)
+          (tile cache coverage 0, 0 785 x 1200)
+          (tile size 785 x 600)
+          (top left tile 0, 0 tiles grid 1 x 2)
+          (children 1
+            (GraphicsLayer
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned.html b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned.html
new file mode 100644
index 0000000..cb28d5f
--- /dev/null
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        body {
+            margin: 100px;
+            height: 3500px;
+            background-image: url('../../../../compositing/resources/simple_image.png');
+            background-size: 200px 200px;
+            background-attachment: fixed;
+            background-repeat: no-repeat;
+            background-position: bottom right;
+        }
+        
+        .test {
+            height: 400px;
+            width: 600px;
+            background-color: rgba(0, 0, 0, 0.5);
+            border: 20px solid orange;
+        }
+        
+        #layers {
+            opacity: 0;
+        }
+    </style>
+    <script>
+    if (window.testRunner)
+        testRunner.dumpAsText(true);
+    
+    function doTest()
+    {
+        window.scrollTo(0, 200);
+
+        if (window.internals)
+            document.getElementById('layers').innerText = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_TILE_CACHES);
+    }
+    
+    window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+
+    <div class="test"></div>
+<pre id="layers"></pre>
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-transformed-html-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-transformed-html-expected.txt
index 9aa64ca..0ccdfcc 100644
--- a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-transformed-html-expected.txt
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-transformed-html-expected.txt
@@ -5,8 +5,9 @@
       (bounds 795.00 1710.00)
       (children 2
         (GraphicsLayer
+          (position 0.00 200.00)
           (anchor 0.00 0.00)
-          (bounds 795.00 1710.00)
+          (bounds 785.00 585.00)
           (drawsContent 1)
           (backgroundColor #FFFFFF)
         )
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.png b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.png
index 2597bfa..303ba49 100644
--- a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.png
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.png
Binary files differ
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.txt
index 443140e..b32440c 100644
--- a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.txt
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-body-background-zoomed-expected.txt
@@ -7,14 +7,11 @@
       (transform [2.30 0.00 0.00 0.00] [0.00 2.30 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
       (children 2
         (GraphicsLayer
+          (position 0.00 154.00)
           (anchor 0.00 0.00)
-          (bounds 785.00 1700.00)
-          (usingTiledLayer 1)
+          (bounds 785.00 585.00)
           (drawsContent 1)
           (backgroundColor #FFFFFF)
-          (tile cache coverage 0, 0 445 x 667)
-          (tile size 512 x 512)
-          (top left tile 0, 0 tiles grid 2 x 3)
         )
         (GraphicsLayer
           (bounds 785.00 1700.00)
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-html-background-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-html-background-expected.txt
index d8dfd77..df5252b 100644
--- a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-html-background-expected.txt
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-html-background-expected.txt
@@ -5,17 +5,18 @@
       (bounds 785.00 1516.00)
       (children 2
         (GraphicsLayer
+          (position 0.00 200.00)
           (anchor 0.00 0.00)
-          (bounds 785.00 1516.00)
+          (bounds 785.00 600.00)
           (drawsContent 1)
           (backgroundColor #FFFFFF)
         )
         (GraphicsLayer
           (bounds 785.00 1516.00)
           (drawsContent 1)
-          (tile cache coverage 0, 0 785 x 1200)
-          (tile size 785 x 600)
-          (top left tile 0, 0 tiles grid 1 x 2)
+          (tile cache coverage 0, 0 785 x 1516)
+          (tile size 512 x 512)
+          (top left tile 0, 0 tiles grid 2 x 3)
           (children 1
             (GraphicsLayer
             )
diff --git a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-non-propagated-body-background-expected.txt b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-non-propagated-body-background-expected.txt
index 9d8ff98..654e6ce 100644
--- a/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-non-propagated-body-background-expected.txt
+++ b/LayoutTests/platform/mac/tiled-drawing/fixed-background/fixed-non-propagated-body-background-expected.txt
@@ -5,9 +5,9 @@
       (bounds 785.00 1700.00)
       (drawsContent 1)
       (backgroundColor #C0C0C0)
-      (tile cache coverage 0, 0 785 x 1200)
-      (tile size 785 x 600)
-      (top left tile 0, 0 tiles grid 1 x 2)
+      (tile cache coverage 0, 0 785 x 1700)
+      (tile size 512 x 512)
+      (top left tile 0, 0 tiles grid 2 x 4)
       (children 1
         (GraphicsLayer
         )
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index ba4f86c..bd414dc 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,88 @@
+2013-01-18  Simon Fraser  <simon.fraser@apple.com>
+
+        Allow fixed background layers to be moved by the ScrollingCoordinator
+        https://bugs.webkit.org/show_bug.cgi?id=107213
+
+        Reviewed by Tim Horton.
+        
+        Start using the RenderView's RenderLayerBacking's background layer for
+        fixed root backgrounds (those which have background images all of which have
+        background-attachment: fixed).
+        
+        The background-layer is contained in the RenderLayer's RenderLayerBacking's
+        containment view, so it gets page scale applied to it, but scrolling happens
+        above this layer, so the background has to be counter-scrolled. We plumb
+        this layer through to the ScrollingCoordinator so that this counter-scrolling
+        can be done on the scrolling thread.
+        
+        Test: platform/mac/tiled-drawing/fixed-background/fixed-body-background-positioned.html
+
+        * WebCore.xcodeproj/project.pbxproj: Add ScrollingStateScrollingNodeMac.mm
+        * page/scrolling/ScrollingCoordinator.cpp:
+        (WebCore::ScrollingCoordinator::counterScrollingLayerForFrameView): New function to get
+        the counter-scrolling layer.
+        (WebCore::ScrollingCoordinator::updateMainFrameScrollPosition): Sync or set the position of the
+        counter-scrolling layer just like we do for the main scrolling layer.
+        * page/scrolling/ScrollingCoordinator.h:
+        (WebCore::ScrollingCoordinator::updateScrollingNode):
+        * page/scrolling/ScrollingStateNode.cpp:
+        (WebCore::ScrollingStateNode::ScrollingStateNode): setScrollLayer() renamed to setScrollPlatformLayer(),
+        and added a FIXME comment because this code is confusing and possibly wrong.
+        * page/scrolling/ScrollingStateNode.h: Renamed setScrollLayer() to setScrollPlatformLayer().
+        * page/scrolling/ScrollingStateScrollingNode.cpp:
+        (WebCore::ScrollingStateScrollingNode::ScrollingStateScrollingNode):
+        * page/scrolling/ScrollingStateScrollingNode.h:
+        (ScrollingStateScrollingNode): Track the counter-scrolling layer.
+        (WebCore::ScrollingStateScrollingNode::counterScrollingLayer):
+        (WebCore::ScrollingStateScrollingNode::counterScrollingLayerDidChange):
+        (WebCore::ScrollingStateScrollingNode::setCounterScrollingLayerDidChange):
+        * page/scrolling/mac/ScrollingCoordinatorMac.h:
+        (ScrollingCoordinatorMac): Add updateScrollingNode() which is less expensive than frameViewRootLayerDidChange()
+        * page/scrolling/mac/ScrollingCoordinatorMac.mm:
+        (WebCore::ScrollingCoordinatorMac::frameViewRootLayerDidChange): Fetch the counter-scrolling layer if we have one.
+        (WebCore::ScrollingCoordinatorMac::setCounterScrollingLayerForNode):
+        (WebCore::ScrollingCoordinatorMac::updateScrollingNode):
+        * page/scrolling/mac/ScrollingStateNodeMac.mm:
+        (WebCore::ScrollingStateNode::setScrollPlatformLayer):
+        * page/scrolling/mac/ScrollingStateScrollingNodeMac.mm: New file for implementation of setCounterScrollingLayer().
+        (WebCore::ScrollingStateScrollingNode::counterScrollingPlatformLayer):
+        (WebCore::ScrollingStateScrollingNode::setCounterScrollingLayer):
+        * page/scrolling/mac/ScrollingTreeScrollingNodeMac.h:
+        (ScrollingTreeScrollingNodeMac):
+        * page/scrolling/mac/ScrollingTreeScrollingNodeMac.mm:
+        (WebCore::ScrollingTreeScrollingNodeMac::update):
+        (WebCore::ScrollingTreeScrollingNodeMac::setScrollLayerPosition):
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::fixedBackgroundPaintsInLocalCoordinates):
+        (WebCore::RenderBoxModelObject::calculateBackgroundImageGeometry): If we're painting into the fixed root layer,
+        we want to always paint with the top,left at 0,0.
+        * rendering/RenderBoxModelObject.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry): In the fixed root background case,
+        we can make the background layer viewport-sized, and we have to set its counter-scrolled position.
+        (WebCore::RenderLayerBacking::updateBackgroundLayer): If the background layer was created or destroyed,
+        we have to tell the ScrollingCoordinator.
+        (WebCore::RenderLayerBacking::didCommitChangesForLayer): Send the GraphicsLayer down.
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::didFlushChangesForLayer): If the background layer changed (e.g. it became
+        tiled) we need to tell the ScrollingCoordinator.
+        (WebCore::RenderLayerCompositor::rebuildCompositingLayerTree): We failed to update the borders on new
+        layers sometimes; this fixes that.
+        (WebCore::RenderLayerCompositor::frameViewDidScroll): In the non-threaded scrolling case, if we have
+        a fixed background layer, we need to update its position.
+        (WebCore::RenderLayerCompositor::fixedRootBackgroundLayerChanged): Feed the newly created/destroyed layer
+        down to the ScrollingCoordinator.
+        (WebCore::RenderLayerCompositor::supportsFixedRootBackgroundCompositing):
+        (WebCore::RenderLayerCompositor::needsFixedRootBackgroundLayer):
+        * rendering/RenderLayerCompositor.h:
+        * rendering/RenderObject.cpp:
+        (WebCore::rendererHasBackground):
+        (WebCore::RenderObject::styleWillChange): If the compositor supports fixed root backgrounds, we no longer
+        treat these as slow repaint objects.
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::rootBackgroundIsEntirelyFixed): Helper function called by RLC.
+        * rendering/RenderView.h:
+
 2013-01-18  Alec Flett  <alecflett@chromium.org>
 
         IndexedDB: Switch to new createTransaction call
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index d988794..275fdeb 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -275,6 +275,7 @@
 		0F605AED15F94848004DF0C0 /* ScrollingConstraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F605AEB15F94848004DF0C0 /* ScrollingConstraints.h */; };
 		0FA24D79162DF91900A3F4C0 /* GraphicsLayerUpdater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA24D77162DF91900A3F4C0 /* GraphicsLayerUpdater.cpp */; };
 		0FA24D7A162DF91900A3F4C0 /* GraphicsLayerUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA24D78162DF91900A3F4C0 /* GraphicsLayerUpdater.h */; };
+		0FA88EBD16A8D1BD00F99984 /* ScrollingStateScrollingNodeMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FA88EBC16A8D1BD00F99984 /* ScrollingStateScrollingNodeMac.mm */; };
 		0FB8890A167D2FA10010CDA5 /* ScrollingTreeStickyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB88908167D2FA10010CDA5 /* ScrollingTreeStickyNode.h */; };
 		0FB8890B167D2FA10010CDA5 /* ScrollingTreeStickyNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FB88909167D2FA10010CDA5 /* ScrollingTreeStickyNode.mm */; };
 		0FB8890E167D30160010CDA5 /* ScrollingStateStickyNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB8890C167D30160010CDA5 /* ScrollingStateStickyNode.cpp */; };
@@ -7484,6 +7485,7 @@
 		0F605AEB15F94848004DF0C0 /* ScrollingConstraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollingConstraints.h; sourceTree = "<group>"; };
 		0FA24D77162DF91900A3F4C0 /* GraphicsLayerUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsLayerUpdater.cpp; sourceTree = "<group>"; };
 		0FA24D78162DF91900A3F4C0 /* GraphicsLayerUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GraphicsLayerUpdater.h; sourceTree = "<group>"; };
+		0FA88EBC16A8D1BD00F99984 /* ScrollingStateScrollingNodeMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollingStateScrollingNodeMac.mm; sourceTree = "<group>"; };
 		0FB88908167D2FA10010CDA5 /* ScrollingTreeStickyNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollingTreeStickyNode.h; sourceTree = "<group>"; };
 		0FB88909167D2FA10010CDA5 /* ScrollingTreeStickyNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollingTreeStickyNode.mm; sourceTree = "<group>"; };
 		0FB8890C167D30160010CDA5 /* ScrollingStateStickyNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollingStateStickyNode.cpp; sourceTree = "<group>"; };
@@ -14969,6 +14971,7 @@
 				9391A990162746CB00297330 /* ScrollingCoordinatorMac.h */,
 				1AF62EE314DA22A70041556C /* ScrollingCoordinatorMac.mm */,
 				931CBD12161A44F800E4C874 /* ScrollingStateNodeMac.mm */,
+				0FA88EBC16A8D1BD00F99984 /* ScrollingStateScrollingNodeMac.mm */,
 				1AF62F2314DAFE910041556C /* ScrollingThreadMac.mm */,
 				93C38C01164473DD00091EB2 /* ScrollingTreeFixedNode.h */,
 				93C38C02164473DD00091EB2 /* ScrollingTreeFixedNode.mm */,
@@ -28827,6 +28830,7 @@
 				931CBD0C161A44E900E4C874 /* ScrollingStateNode.cpp in Sources */,
 				931CBD13161A44F800E4C874 /* ScrollingStateNodeMac.mm in Sources */,
 				931CBD0E161A44E900E4C874 /* ScrollingStateScrollingNode.cpp in Sources */,
+				0FA88EBD16A8D1BD00F99984 /* ScrollingStateScrollingNodeMac.mm in Sources */,
 				0FB8890E167D30160010CDA5 /* ScrollingStateStickyNode.cpp in Sources */,
 				931CBD10161A44E900E4C874 /* ScrollingStateTree.cpp in Sources */,
 				1AF62F2514DAFE9E0041556C /* ScrollingThread.cpp in Sources */,
diff --git a/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp b/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
index ac93f19..06fcd7c 100644
--- a/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
+++ b/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
@@ -303,6 +303,23 @@
 #endif
 }
 
+GraphicsLayer* ScrollingCoordinator::counterScrollingLayerForFrameView(FrameView* frameView)
+{
+#if USE(ACCELERATED_COMPOSITING)
+    Frame* frame = frameView->frame();
+    if (!frame)
+        return 0;
+
+    RenderView* renderView = frame->contentRenderer();
+    if (!renderView)
+        return 0;
+    return renderView->compositor()->fixedRootBackgroundLayer();
+#else
+    UNUSED_PARAM(frameView);
+    return 0;
+#endif
+}
+
 void ScrollingCoordinator::frameViewRootLayerDidChange(FrameView* frameView)
 {
     ASSERT(isMainThread());
@@ -365,10 +382,16 @@
 
 #if USE(ACCELERATED_COMPOSITING)
     if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
-        if (programmaticScroll || scrollingLayerPositionAction == SetScrollingLayerPosition)
+        GraphicsLayer* counterScrollingLayer = counterScrollingLayerForFrameView(frameView);
+        if (programmaticScroll || scrollingLayerPositionAction == SetScrollingLayerPosition) {
             scrollLayer->setPosition(-frameView->scrollPosition());
-        else {
+            if (counterScrollingLayer)
+                counterScrollingLayer->setPosition(IntPoint(frameView->scrollOffsetForFixedPosition()));
+        } else {
             scrollLayer->syncPosition(-frameView->scrollPosition());
+            if (counterScrollingLayer)
+                counterScrollingLayer->syncPosition(IntPoint(frameView->scrollOffsetForFixedPosition()));
+
             LayoutRect viewportRect = frameView->visibleContentRect();
             viewportRect.setLocation(IntPoint(frameView->scrollOffsetForFixedPosition()));
             syncChildPositions(viewportRect);
diff --git a/Source/WebCore/page/scrolling/ScrollingCoordinator.h b/Source/WebCore/page/scrolling/ScrollingCoordinator.h
index 7ef2761..753b25f 100644
--- a/Source/WebCore/page/scrolling/ScrollingCoordinator.h
+++ b/Source/WebCore/page/scrolling/ScrollingCoordinator.h
@@ -123,6 +123,7 @@
     virtual void detachFromStateTree(ScrollingNodeID) { }
     virtual void clearStateTree() { }
     virtual void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) { }
+    virtual void updateScrollingNode(ScrollingNodeID, GraphicsLayer* /*scrollLayer*/, GraphicsLayer* /*counterScrollingLayer*/) { }
     virtual void syncChildPositions(const LayoutRect&) { }
     virtual String scrollingStateTreeAsText() const;
 
@@ -167,6 +168,7 @@
 
     unsigned computeCurrentWheelEventHandlerCount();
     GraphicsLayer* scrollLayerForFrameView(FrameView*);
+    GraphicsLayer* counterScrollingLayerForFrameView(FrameView*);
 
     Page* m_page;
 
diff --git a/Source/WebCore/page/scrolling/ScrollingStateNode.cpp b/Source/WebCore/page/scrolling/ScrollingStateNode.cpp
index b2aa8366..1cd8a20 100644
--- a/Source/WebCore/page/scrolling/ScrollingStateNode.cpp
+++ b/Source/WebCore/page/scrolling/ScrollingStateNode.cpp
@@ -53,7 +53,8 @@
     , m_parent(0)
     , m_scrollLayerDidChange(stateNode.scrollLayerDidChange())
 {
-    setScrollLayer(stateNode.platformScrollLayer());
+    // FIXME: why doesn't this set the GraphicsLayer?
+    setScrollPlatformLayer(stateNode.platformScrollLayer());
 }
 
 ScrollingStateNode::~ScrollingStateNode()
diff --git a/Source/WebCore/page/scrolling/ScrollingStateNode.h b/Source/WebCore/page/scrolling/ScrollingStateNode.h
index f10f7aa..126d896 100644
--- a/Source/WebCore/page/scrolling/ScrollingStateNode.h
+++ b/Source/WebCore/page/scrolling/ScrollingStateNode.h
@@ -67,7 +67,7 @@
     GraphicsLayer* graphicsLayer() { return m_graphicsLayer; }
     PlatformLayer* platformScrollLayer() const;
     void setScrollLayer(GraphicsLayer*);
-    void setScrollLayer(PlatformLayer*);
+    void setScrollPlatformLayer(PlatformLayer*);
 
     bool scrollLayerDidChange() const { return m_scrollLayerDidChange; }
     void setScrollLayerDidChange(bool scrollLayerDidChange) { m_scrollLayerDidChange = scrollLayerDidChange; }
diff --git a/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp b/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp
index 9368c3e..9de98bb 100644
--- a/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp
+++ b/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp
@@ -42,6 +42,7 @@
 ScrollingStateScrollingNode::ScrollingStateScrollingNode(ScrollingStateTree* stateTree, ScrollingNodeID nodeID)
     : ScrollingStateNode(stateTree, nodeID)
     , m_changedProperties(0)
+    , m_counterScrollingLayer(0)
     , m_frameScaleFactor(1)
     , m_wheelEventHandlerCount(0)
     , m_shouldUpdateScrollLayerPositionOnMainThread(0)
@@ -50,6 +51,7 @@
     , m_hasEnabledHorizontalScrollbar(false)
     , m_hasEnabledVerticalScrollbar(false)
     , m_requestedScrollPositionRepresentsProgrammaticScroll(false)
+    , m_counterScrollingLayerDidChange(false)
     , m_horizontalScrollbarMode(ScrollbarAuto)
     , m_verticalScrollbarMode(ScrollbarAuto)
 {
@@ -69,11 +71,13 @@
     , m_hasEnabledHorizontalScrollbar(stateNode.hasEnabledHorizontalScrollbar())
     , m_hasEnabledVerticalScrollbar(stateNode.hasEnabledVerticalScrollbar())
     , m_requestedScrollPositionRepresentsProgrammaticScroll(stateNode.requestedScrollPositionRepresentsProgrammaticScroll())
+    , m_counterScrollingLayerDidChange(stateNode.counterScrollingLayerDidChange())
     , m_horizontalScrollbarMode(stateNode.horizontalScrollbarMode())
     , m_verticalScrollbarMode(stateNode.verticalScrollbarMode())
     , m_requestedScrollPosition(stateNode.requestedScrollPosition())
     , m_scrollOrigin(stateNode.scrollOrigin())
 {
+    setCounterScrollingLayer(stateNode.counterScrollingLayer());
 }
 
 ScrollingStateScrollingNode::~ScrollingStateScrollingNode()
diff --git a/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h b/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h
index f45527e..91f84d0 100644
--- a/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h
+++ b/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h
@@ -60,6 +60,7 @@
         VerticalScrollbarMode = 1 << 11,
         ScrollOrigin = 1 << 12,
         RequestedScrollPosition = 1 << 13,
+        CounterScrollingLayer = 1 << 14,
     };
 
     virtual bool isScrollingNode() OVERRIDE { return true; }
@@ -110,6 +111,13 @@
     const IntPoint& scrollOrigin() const { return m_scrollOrigin; }
     void setScrollOrigin(const IntPoint&);
 
+    // This is a layer moved in the opposite direction to scrolling, for example for background-attachment:fixed
+    GraphicsLayer* counterScrollingLayer() const { return m_counterScrollingLayer; }
+    void setCounterScrollingLayer(GraphicsLayer*);
+    PlatformLayer* counterScrollingPlatformLayer() const;
+
+    bool counterScrollingLayerDidChange() const { return m_counterScrollingLayerDidChange; }
+
     bool requestedScrollPositionRepresentsProgrammaticScroll() const { return m_requestedScrollPositionRepresentsProgrammaticScroll; }
 
     virtual void dumpProperties(TextStream&, int indent) const OVERRIDE;
@@ -120,6 +128,11 @@
 
     unsigned m_changedProperties;
 
+    GraphicsLayer* m_counterScrollingLayer;
+#if PLATFORM(MAC)
+    RetainPtr<PlatformLayer> m_counterScrollingPlatformLayer;
+#endif
+    
     IntRect m_viewportRect;
     IntSize m_contentsSize;
     
@@ -137,6 +150,7 @@
     bool m_hasEnabledHorizontalScrollbar;
     bool m_hasEnabledVerticalScrollbar;
     bool m_requestedScrollPositionRepresentsProgrammaticScroll;
+    bool m_counterScrollingLayerDidChange;
 
     ScrollbarMode m_horizontalScrollbarMode;
     ScrollbarMode m_verticalScrollbarMode;
diff --git a/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h b/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h
index 7d44391..03b3875 100644
--- a/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h
+++ b/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h
@@ -83,6 +83,8 @@
     // This function will update the ScrollingStateNode for the given viewport constrained object.
     virtual void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) OVERRIDE;
 
+    virtual void updateScrollingNode(ScrollingNodeID, GraphicsLayer* scrollLayer, GraphicsLayer* counterScrollingLayer) OVERRIDE;
+
     // Called to synch the GraphicsLayer positions for child layers when their CALayers have been moved by the scrolling thread.
     virtual void syncChildPositions(const LayoutRect& viewportRect) OVERRIDE;
 
@@ -114,6 +116,7 @@
 
     void setScrollParametersForNode(const ScrollParameters&, ScrollingStateScrollingNode*);
     void setScrollLayerForNode(GraphicsLayer*, ScrollingStateNode*);
+    void setCounterScrollingLayerForNode(GraphicsLayer*, ScrollingStateScrollingNode*);
     void setNonFastScrollableRegionForNode(const Region&, ScrollingStateScrollingNode*);
     void setWheelEventHandlerCountForNode(unsigned, ScrollingStateScrollingNode*);
 
diff --git a/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm b/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm
index 5955887..fb185f3 100644
--- a/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm
+++ b/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm
@@ -156,7 +156,9 @@
 
     ScrollingCoordinator::frameViewRootLayerDidChange(frameView);
 
-    setScrollLayerForNode(scrollLayerForFrameView(frameView), stateNodeForID(frameView->scrollLayerID()));
+    ScrollingStateScrollingNode* node = toScrollingStateScrollingNode(stateNodeForID(frameView->scrollLayerID()));
+    setScrollLayerForNode(scrollLayerForFrameView(frameView), node);
+    setCounterScrollingLayerForNode(counterScrollingLayerForFrameView(frameView), node);
 }
 
 void ScrollingCoordinatorMac::frameViewHorizontalScrollbarLayerDidChange(FrameView* frameView, GraphicsLayer*)
@@ -328,6 +330,12 @@
     scheduleTreeStateCommit();
 }
 
+void ScrollingCoordinatorMac::setCounterScrollingLayerForNode(GraphicsLayer* layer, ScrollingStateScrollingNode* node)
+{
+    node->setCounterScrollingLayer(layer);
+    scheduleTreeStateCommit();
+}
+
 void ScrollingCoordinatorMac::setNonFastScrollableRegionForNode(const Region& region, ScrollingStateScrollingNode* node)
 {
     node->setNonFastScrollableRegion(region);
@@ -397,6 +405,18 @@
     }
 }
 
+void ScrollingCoordinatorMac::updateScrollingNode(ScrollingNodeID nodeID, GraphicsLayer* scrollLayer, GraphicsLayer* counterScrollingLayer)
+{
+    ScrollingStateScrollingNode* node = toScrollingStateScrollingNode(stateNodeForID(nodeID));
+    ASSERT(node);
+    if (!node)
+        return;
+
+    node->setScrollLayer(scrollLayer);
+    node->setCounterScrollingLayer(counterScrollingLayer);
+    scheduleTreeStateCommit();
+}
+
 void ScrollingCoordinatorMac::updateViewportConstrainedNode(ScrollingNodeID nodeID, const ViewportConstraints& constraints, GraphicsLayer* graphicsLayer)
 {
     ASSERT(supportsFixedPositionLayers());
diff --git a/Source/WebCore/page/scrolling/mac/ScrollingStateNodeMac.mm b/Source/WebCore/page/scrolling/mac/ScrollingStateNodeMac.mm
index 41f381b..9a16d62 100644
--- a/Source/WebCore/page/scrolling/mac/ScrollingStateNodeMac.mm
+++ b/Source/WebCore/page/scrolling/mac/ScrollingStateNodeMac.mm
@@ -38,7 +38,7 @@
     return m_platformScrollLayer.get();
 }
 
-void ScrollingStateNode::setScrollLayer(PlatformLayer* platformLayer)
+void ScrollingStateNode::setScrollPlatformLayer(PlatformLayer* platformLayer)
 {
     m_platformScrollLayer = platformLayer;
 }
diff --git a/Source/WebCore/page/scrolling/mac/ScrollingStateScrollingNodeMac.mm b/Source/WebCore/page/scrolling/mac/ScrollingStateScrollingNodeMac.mm
new file mode 100644
index 0000000..b90bbbb
--- /dev/null
+++ b/Source/WebCore/page/scrolling/mac/ScrollingStateScrollingNodeMac.mm
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScrollingStateScrollingNode.h"
+
+#include "GraphicsLayer.h"
+#include "ScrollingStateTree.h"
+
+#if ENABLE(THREADED_SCROLLING)
+
+namespace WebCore {
+
+PlatformLayer* ScrollingStateScrollingNode::counterScrollingPlatformLayer() const
+{
+    return m_counterScrollingPlatformLayer.get();
+}
+
+void ScrollingStateScrollingNode::setCounterScrollingLayer(GraphicsLayer* graphicsLayer)
+{
+    PlatformLayer* platformScrollLayer = graphicsLayer ? graphicsLayer->platformLayer() : nil;
+    if (m_counterScrollingPlatformLayer == platformScrollLayer)
+        return;
+
+    m_counterScrollingPlatformLayer = platformScrollLayer;
+    m_counterScrollingLayer = graphicsLayer;
+
+    m_counterScrollingLayerDidChange = true;
+    if (m_scrollingStateTree)
+        m_scrollingStateTree->setHasChangedProperties(true);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(THREADED_SCROLLING)
diff --git a/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeMac.h b/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeMac.h
index 486e639..da7ea3b 100644
--- a/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeMac.h
+++ b/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeMac.h
@@ -80,6 +80,7 @@
     RetainPtr<CFRunLoopTimerRef> m_snapRubberbandTimer;
 
     RetainPtr<CALayer> m_scrollLayer;
+    RetainPtr<CALayer> m_counterScrollingLayer;
     IntPoint m_probableMainThreadScrollPosition;
 };
 
diff --git a/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeMac.mm b/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeMac.mm
index af69f30..949fa3e 100644
--- a/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeMac.mm
+++ b/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeMac.mm
@@ -70,6 +70,9 @@
     if (state->scrollLayerDidChange())
         m_scrollLayer = state->platformScrollLayer();
 
+    if (state->counterScrollingLayerDidChange())
+        m_counterScrollingLayer = state->counterScrollingPlatformLayer();
+
     if (state->changedProperties() & ScrollingStateScrollingNode::RequestedScrollPosition)
         setScrollPosition(state->requestedScrollPosition());
 
@@ -276,10 +279,13 @@
     ASSERT(!shouldUpdateScrollLayerPositionOnMainThread());
     m_scrollLayer.get().position = CGPointMake(-position.x() + scrollOrigin().x(), -position.y() + scrollOrigin().y());
 
+    IntSize scrollOffsetForFixedChildren = WebCore::scrollOffsetForFixedPosition(viewportRect(), contentsSize(), position, scrollOrigin(), frameScaleFactor(), false);
+    if (m_counterScrollingLayer)
+        m_counterScrollingLayer.get().position = FloatPoint(scrollOffsetForFixedChildren);
+
     if (!m_children)
         return;
 
-    IntSize scrollOffsetForFixedChildren = WebCore::scrollOffsetForFixedPosition(viewportRect(), contentsSize(), position, scrollOrigin(), frameScaleFactor(), false);
     IntRect viewportRect = this->viewportRect();
     viewportRect.setLocation(IntPoint(scrollOffsetForFixedChildren));
 
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp
index fc33dbe..da49c11 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp
@@ -1172,7 +1172,26 @@
     return phase;
 }
 
-void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fillLayer, const LayoutRect& paintRect, 
+bool RenderBoxModelObject::fixedBackgroundPaintsInLocalCoordinates() const
+{
+#if USE(ACCELERATED_COMPOSITING)
+    if (!isRoot())
+        return false;
+
+    if (view()->frameView() && view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
+        return false;
+
+    RenderLayer* rootLayer = view()->layer();
+    if (!rootLayer || !rootLayer->isComposited())
+        return false;
+
+    return rootLayer->backing()->backgroundLayerPaintsFixedRootBackground();
+#else
+    return false;
+#endif
+}
+
+void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fillLayer, const LayoutRect& paintRect,
                                                             BackgroundImageGeometry& geometry)
 {
     LayoutUnit left = 0;
@@ -1224,8 +1243,11 @@
             positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutSize(left + right, top + bottom), paintRect.location());
     } else {
         IntRect viewportRect = pixelSnappedIntRect(viewRect());
-        if (FrameView* frameView = view()->frameView())
+        if (fixedBackgroundPaintsInLocalCoordinates())
+            viewportRect.setLocation(IntPoint());
+        else if (FrameView* frameView = view()->frameView())
             viewportRect.setLocation(IntPoint(frameView->scrollOffsetForFixedPosition()));
+        
         geometry.setDestRect(pixelSnappedIntRect(viewportRect));
         positioningAreaSize = geometry.destRect().size();
     }
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h
index e29592f..93e47d3 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.h
+++ b/Source/WebCore/rendering/RenderBoxModelObject.h
@@ -289,7 +289,8 @@
 
     RoundedRect getBackgroundRoundedRect(const LayoutRect&, InlineFlowBox*, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
         bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
-
+    
+    bool fixedBackgroundPaintsInLocalCoordinates() const;
 
     void clipBorderSidePolygon(GraphicsContext*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
                                BoxSide, bool firstEdgeMatches, bool secondEdgeMatches);
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index a2d00e2..6e5de42 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -752,14 +752,19 @@
     }
 
     if (m_backgroundLayer) {
+        FloatPoint backgroundPosition;
         FloatSize backgroundSize = contentsSize;
-        IntSize backgroundOffset = m_graphicsLayer->offsetFromRenderer();
-        m_backgroundLayer->setPosition(FloatPoint());
+        if (backgroundLayerPaintsFixedRootBackground()) {
+            FrameView* frameView = toRenderView(renderer())->frameView();
+            backgroundPosition = IntPoint(frameView->scrollOffsetForFixedPosition());
+            backgroundSize = frameView->visibleContentRect().size();
+        }
+        m_backgroundLayer->setPosition(backgroundPosition);
         if (backgroundSize != m_backgroundLayer->size()) {
             m_backgroundLayer->setSize(backgroundSize);
             m_backgroundLayer->setNeedsDisplay();
         }
-        m_backgroundLayer->setOffsetFromRenderer(backgroundOffset);
+        m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
     }
 
     if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) {
@@ -1137,7 +1142,13 @@
             m_graphicsLayer->setAppliesPageScale(true);
         }
     }
-
+    
+    if (layerChanged) {
+        // This assumes that the background layer is only used for fixed backgrounds, which is currently a correct assumption.
+        if (renderer()->view())
+            compositor()->fixedRootBackgroundLayerChanged();
+    }
+    
     return layerChanged;
 }
 
@@ -1886,9 +1897,9 @@
     return compositor()->deviceScaleFactor();
 }
 
-void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer*) const
+void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const
 {
-    compositor()->didFlushChangesForLayer(m_owningLayer);
+    compositor()->didFlushChangesForLayer(m_owningLayer, layer);
 }
 
 bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index 7d56a51..1db8573 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -340,10 +340,14 @@
     }
 }
 
-void RenderLayerCompositor::didFlushChangesForLayer(RenderLayer* layer)
+void RenderLayerCompositor::didFlushChangesForLayer(RenderLayer* layer, const GraphicsLayer* graphicsLayer)
 {
     if (m_viewportConstrainedLayers.contains(layer))
         m_viewportConstrainedLayersNeedingUpdate.add(layer);
+
+    RenderLayerBacking* backing = layer->backing();
+    if (backing->backgroundLayerPaintsFixedRootBackground() && graphicsLayer == backing->backgroundLayer())
+        fixedRootBackgroundLayerChanged();
 }
 
 void RenderLayerCompositor::notifyFlushBeforeDisplayRefresh(const GraphicsLayer*)
@@ -1066,7 +1070,9 @@
                 reflection->backing()->updateCompositedBounds();
         }
 
-        layerBacking->updateGraphicsLayerConfiguration();
+        if (layerBacking->updateGraphicsLayerConfiguration())
+            layerBacking->updateDebugIndicators(m_showDebugBorders, m_showRepaintCounter);
+        
         layerBacking->updateGraphicsLayerGeometry();
 
         if (!layer->parent())
@@ -1194,6 +1200,9 @@
     }
 
     m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
+
+    if (GraphicsLayer* fixedBackgroundLayer = fixedRootBackgroundLayer())
+        fixedBackgroundLayer->setPosition(IntPoint(frameView->scrollOffsetForFixedPosition()));
 }
 
 void RenderLayerCompositor::frameViewDidLayout()
@@ -1217,6 +1226,17 @@
         scrollingCoordinator->scrollableAreaScrollLayerDidChange(layer, backing ? backing->scrollingContentsLayer() : 0);
 }
 
+void RenderLayerCompositor::fixedRootBackgroundLayerChanged()
+{
+    if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
+        RenderLayerBacking* renderViewBacking = m_renderView->layer()->backing();
+        if (!renderViewBacking)
+            return;
+
+        scrollingCoordinator->updateScrollingNode(renderViewBacking->scrollLayerID(), scrollLayer(), fixedRootBackgroundLayer());
+    }
+}
+
 String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
 {
     updateCompositingLayers(CompositingUpdateAfterLayout);
@@ -2130,21 +2150,18 @@
     }
 }
 
+bool RenderLayerCompositor::supportsFixedRootBackgroundCompositing() const
+{
+    RenderLayerBacking* renderViewBacking = m_renderView->layer()->backing();
+    return renderViewBacking && renderViewBacking->usingTileCache();
+}
+
 bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer* layer) const
 {
     if (layer != m_renderView->layer())
         return false;
 
-    // We only create a background layer if using a TileCache, since that will allow us to adjust the fixed background layer on scrolling.
-    if (!layer->isComposited() || !layer->backing()->usingTileCache())
-        return false;
-
-    RenderObject* rootObject = m_renderView->document()->documentElement() ? m_renderView->document()->documentElement()->renderer() : 0;
-    if (!rootObject)
-        return false;
-
-    RenderObject* rootRenderer = rootObject->rendererForRootBackground();
-    return rootRenderer->hasEntirelyFixedBackground();
+    return supportsFixedRootBackgroundCompositing() && m_renderView->rootBackgroundIsEntirelyFixed();
 }
 
 GraphicsLayer* RenderLayerCompositor::fixedRootBackgroundLayer() const
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h
index 9f573bd..85a0373 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.h
+++ b/Source/WebCore/rendering/RenderLayerCompositor.h
@@ -104,7 +104,7 @@
     RenderLayerCompositor* enclosingCompositorFlushingLayers() const;
 
     // Called when the GraphicsLayer for the given RenderLayer has flushed changes inside of flushPendingLayerChanges().
-    void didFlushChangesForLayer(RenderLayer*);
+    void didFlushChangesForLayer(RenderLayer*, const GraphicsLayer*);
     
     // Rebuild the tree of compositing layers
     void updateCompositingLayers(CompositingUpdateType, RenderLayer* updateRoot = 0);
@@ -130,6 +130,7 @@
     // Whether the given layer needs an extra 'contents' layer.
     bool needsContentsCompositingLayer(const RenderLayer*) const;
 
+    bool supportsFixedRootBackgroundCompositing() const;
     bool needsFixedRootBackgroundLayer(const RenderLayer*) const;
     GraphicsLayer* fixedRootBackgroundLayer() const;
     
@@ -203,6 +204,7 @@
     void rootFixedBackgroundsChanged();
 
     void scrollingLayerDidChange(RenderLayer*);
+    void fixedRootBackgroundLayerChanged();
 
     String layerTreeAsText(LayerTreeFlags);
 
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index d5bcf22..509575a 100644
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -1832,6 +1832,11 @@
     }
 }
 
+static inline bool rendererHasBackground(const RenderObject* renderer)
+{
+    return renderer && renderer->hasBackground();
+}
+
 void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
 {
     if (m_style) {
@@ -1905,6 +1910,19 @@
 
         bool newStyleSlowScroll = newStyle && !shouldBlitOnFixedBackgroundImage && newStyle->hasFixedBackgroundImage();
         bool oldStyleSlowScroll = m_style && !shouldBlitOnFixedBackgroundImage && m_style->hasFixedBackgroundImage();
+
+#if USE(ACCELERATED_COMPOSITING)
+        bool drawsRootBackground = isRoot() || (isBody() && rendererHasBackground(document()->documentElement()->renderer()));
+        if (drawsRootBackground && !shouldBlitOnFixedBackgroundImage) {
+            if (view()->compositor()->supportsFixedRootBackgroundCompositing()) {
+                if (newStyleSlowScroll && newStyle->hasEntirelyFixedBackground())
+                    newStyleSlowScroll = false;
+
+                if (oldStyleSlowScroll && m_style->hasEntirelyFixedBackground())
+                    oldStyleSlowScroll = false;
+            }
+        }
+#endif
         if (oldStyleSlowScroll != newStyleSlowScroll) {
             if (oldStyleSlowScroll)
                 view()->frameView()->removeSlowRepaintObject();
diff --git a/Source/WebCore/rendering/RenderView.cpp b/Source/WebCore/rendering/RenderView.cpp
index 54a8833..17f4f1a 100644
--- a/Source/WebCore/rendering/RenderView.cpp
+++ b/Source/WebCore/rendering/RenderView.cpp
@@ -847,6 +847,16 @@
     return pixelSnappedIntRect(overflowRect);
 }
 
+bool RenderView::rootBackgroundIsEntirelyFixed() const
+{
+    RenderObject* rootObject = document()->documentElement() ? document()->documentElement()->renderer() : 0;
+    if (!rootObject)
+        return false;
+
+    RenderObject* rootRenderer = rootObject->rendererForRootBackground();
+    return rootRenderer->hasEntirelyFixedBackground();
+}
+
 LayoutRect RenderView::backgroundRect(RenderBox* backgroundRenderer) const
 {
     if (!hasColumns())
diff --git a/Source/WebCore/rendering/RenderView.h b/Source/WebCore/rendering/RenderView.h
index c5ff22a..9289ba5 100644
--- a/Source/WebCore/rendering/RenderView.h
+++ b/Source/WebCore/rendering/RenderView.h
@@ -202,6 +202,9 @@
 
     IntRect documentRect() const;
 
+    // Renderer that paints the root background has background-images which all have background-attachment: fixed.
+    bool rootBackgroundIsEntirelyFixed() const;
+    
     bool hasRenderNamedFlowThreads() const;
     FlowThreadController* flowThreadController();