Register fixed position layers with ScrollingCoordinator
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Jun 2012 17:45:05 +0000 (17:45 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Jun 2012 17:45:05 +0000 (17:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=78864

Patch by Sami Kyostila <skyostil@chromium.org> on 2012-06-14
Reviewed by James Robinson.

This patch makes ScrollingCoordinator aware of page elements that are
either fixed positioned directly or through their ancestors and that
also have their own composited backing layers. This allows the
ScrollingCoordinator implementation to potentially enable fast
scrolling even if there are fixed elements on the page, because the
compositor can automatically reposition the fixed element layers after
scrolling.

Since fixed position layers need to be explicitly supported by the
ScrollingCoordinator implementation, we add a new
supportsFixedPositionLayers() query for checking this.

* page/FrameView.cpp:
(WebCore::FrameView::FrameView):
(WebCore::FrameView::useSlowRepaints):
(WebCore::FrameView::addFixedObject):
(WebCore::FrameView::removeFixedObject):
* page/FrameView.h:
(FrameView):
(WebCore::FrameView::fixedObjects):
(WebCore::FrameView::hasFixedObjects):
* page/scrolling/ScrollingCoordinator.cpp:
(WebCore::ScrollingCoordinator::frameViewFixedObjectsDidChange):
(WebCore::ScrollingCoordinator::hasNonLayerFixedObjects):
(WebCore):
(WebCore::ScrollingCoordinator::updateShouldUpdateScrollLayerPositionOnMainThread):
(WebCore::ScrollingCoordinator::setLayerIsContainerForFixedPosition):
(WebCore::ScrollingCoordinator::setLayerIsFixedToContainerLayer):
* page/scrolling/ScrollingCoordinator.h:
(ScrollingCoordinator):
* page/scrolling/chromium/ScrollingCoordinatorChromium.cpp:
(WebCore::ScrollingCoordinator::setLayerIsContainerForFixedPosition):
(WebCore):
(WebCore::ScrollingCoordinator::setLayerIsFixedToContainerLayer):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::willBeDestroyed):
(WebCore::RenderBox::styleWillChange):
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::updateBacking):
(WebCore):
(WebCore::RenderLayerCompositor::fixedPositionedByAncestor):
(WebCore::RenderLayerCompositor::ensureRootLayer):
* rendering/RenderLayerCompositor.h:

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

17 files changed:
Source/WebCore/ChangeLog
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
Source/WebCore/page/scrolling/ScrollingCoordinator.h
Source/WebCore/page/scrolling/ScrollingCoordinatorNone.cpp
Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.cpp
Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
Source/WebCore/platform/graphics/chromium/LayerChromium.h
Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h
Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp

index 412d8f0..756c9a1 100644 (file)
@@ -1,3 +1,56 @@
+2012-06-14  Sami Kyostila  <skyostil@chromium.org>
+
+        Register fixed position layers with ScrollingCoordinator
+        https://bugs.webkit.org/show_bug.cgi?id=78864
+
+        Reviewed by James Robinson.
+
+        This patch makes ScrollingCoordinator aware of page elements that are
+        either fixed positioned directly or through their ancestors and that
+        also have their own composited backing layers. This allows the
+        ScrollingCoordinator implementation to potentially enable fast
+        scrolling even if there are fixed elements on the page, because the
+        compositor can automatically reposition the fixed element layers after
+        scrolling.
+
+        Since fixed position layers need to be explicitly supported by the
+        ScrollingCoordinator implementation, we add a new
+        supportsFixedPositionLayers() query for checking this.
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::FrameView):
+        (WebCore::FrameView::useSlowRepaints):
+        (WebCore::FrameView::addFixedObject):
+        (WebCore::FrameView::removeFixedObject):
+        * page/FrameView.h:
+        (FrameView):
+        (WebCore::FrameView::fixedObjects):
+        (WebCore::FrameView::hasFixedObjects):
+        * page/scrolling/ScrollingCoordinator.cpp:
+        (WebCore::ScrollingCoordinator::frameViewFixedObjectsDidChange):
+        (WebCore::ScrollingCoordinator::hasNonLayerFixedObjects):
+        (WebCore):
+        (WebCore::ScrollingCoordinator::updateShouldUpdateScrollLayerPositionOnMainThread):
+        (WebCore::ScrollingCoordinator::setLayerIsContainerForFixedPosition):
+        (WebCore::ScrollingCoordinator::setLayerIsFixedToContainerLayer):
+        * page/scrolling/ScrollingCoordinator.h:
+        (ScrollingCoordinator):
+        * page/scrolling/chromium/ScrollingCoordinatorChromium.cpp:
+        (WebCore::ScrollingCoordinator::setLayerIsContainerForFixedPosition):
+        (WebCore):
+        (WebCore::ScrollingCoordinator::setLayerIsFixedToContainerLayer):
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::willBeDestroyed):
+        (WebCore::RenderBox::styleWillChange):
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::updateBacking):
+        (WebCore):
+        (WebCore::RenderLayerCompositor::fixedPositionedByAncestor):
+        (WebCore::RenderLayerCompositor::ensureRootLayer):
+        * rendering/RenderLayerCompositor.h:
+
 2012-06-14  Alexey Proskuryakov  <ap@apple.com>
 
         [CFNetwork] XMLHttpRequest incorrectly returns cached responses even when there is a Vary header field
index 2a0b487..caa8963 100644 (file)
@@ -136,7 +136,6 @@ FrameView::FrameView(Frame* frame)
     : m_frame(frame)
     , m_canHaveScrollbars(true)
     , m_slowRepaintObjectCount(0)
-    , m_fixedObjectCount(0)
     , m_layoutTimer(this, &FrameView::layoutTimerFired)
     , m_layoutRoot(0)
     , m_inSynchronousPostLayout(false)
@@ -1265,7 +1264,7 @@ void FrameView::adjustMediaTypeForPrinting(bool printing)
 
 bool FrameView::useSlowRepaints(bool considerOverlap) const
 {
-    bool mustBeSlow = m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0);
+    bool mustBeSlow = m_slowRepaintObjectCount > 0 || (platformWidget() && hasFixedObjects());
 
     // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
     // m_contentIsOpaque, so don't take the fast path for composited layers
@@ -1350,28 +1349,32 @@ void FrameView::removeSlowRepaintObject()
     }
 }
 
-void FrameView::addFixedObject()
+void FrameView::addFixedObject(RenderObject* object)
 {
-    if (!m_fixedObjectCount++) {
+    if (!m_fixedObjects)
+        m_fixedObjects = adoptPtr(new FixedObjectSet);
+
+    if (!m_fixedObjects->contains(object)) {
+        m_fixedObjects->add(object);
         if (platformWidget())
             updateCanBlitOnScrollRecursively();
 
         if (Page* page = m_frame->page()) {
             if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
-                scrollingCoordinator->frameViewHasFixedObjectsDidChange(this);
+                scrollingCoordinator->frameViewFixedObjectsDidChange(this);
         }
     }
 }
 
-void FrameView::removeFixedObject()
+void FrameView::removeFixedObject(RenderObject* object)
 {
-    ASSERT(m_fixedObjectCount > 0);
-    --m_fixedObjectCount;
+    ASSERT(hasFixedObjects());
 
-    if (!m_fixedObjectCount) {
+    if (m_fixedObjects->contains(object)) {
+        m_fixedObjects->remove(object);
         if (Page* page = m_frame->page()) {
             if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
-                scrollingCoordinator->frameViewHasFixedObjectsDidChange(this);
+                scrollingCoordinator->frameViewFixedObjectsDidChange(this);
         }
 
         // FIXME: In addFixedObject() we only call this if there's a platform widget,
index 536d3f3..8ccbe8c 100644 (file)
@@ -194,9 +194,11 @@ public:
     void removeSlowRepaintObject();
     bool hasSlowRepaintObjects() const { return m_slowRepaintObjectCount; }
 
-    void addFixedObject();
-    void removeFixedObject();
-    bool hasFixedObjects() const { return m_fixedObjectCount > 0; }
+    typedef HashSet<RenderObject*> FixedObjectSet;
+    void addFixedObject(RenderObject*);
+    void removeFixedObject(RenderObject*);
+    const FixedObjectSet* fixedObjects() const { return m_fixedObjects.get(); }
+    bool hasFixedObjects() const { return m_fixedObjects && m_fixedObjects->size() > 0; }
 
     // Functions for querying the current scrolled position, negating the effects of overhang
     // and adjusting for page scale.
@@ -443,7 +445,6 @@ private:
     bool m_isOverlapped;
     bool m_contentIsOpaque;
     unsigned m_slowRepaintObjectCount;
-    unsigned m_fixedObjectCount;
     int m_borderX;
     int m_borderY;
 
@@ -521,6 +522,7 @@ private:
     IntSize m_maxAutoSize;
 
     OwnPtr<ScrollableAreaSet> m_scrollableAreas;
+    OwnPtr<FixedObjectSet> m_fixedObjects;
 
     static double s_deferredRepaintDelay;
     static double s_initialDeferredRepaintDelayDuringLoading;
index d38bbd5..6d1f2a6 100644 (file)
@@ -190,7 +190,7 @@ void ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange(FrameView* fr
     updateShouldUpdateScrollLayerPositionOnMainThread();
 }
 
-void ScrollingCoordinator::frameViewHasFixedObjectsDidChange(FrameView* frameView)
+void ScrollingCoordinator::frameViewFixedObjectsDidChange(FrameView* frameView)
 {
     ASSERT(isMainThread());
     ASSERT(m_page);
@@ -337,12 +337,36 @@ void ScrollingCoordinator::recomputeWheelEventHandlerCount()
     setWheelEventHandlerCount(wheelEventHandlerCount);
 }
 
+bool ScrollingCoordinator::hasNonLayerFixedObjects(FrameView* frameView)
+{
+    const FrameView::FixedObjectSet* fixedObjects = frameView->fixedObjects();
+    if (!fixedObjects)
+        return false;
+
+#if USE(ACCELERATED_COMPOSITING)
+    for (FrameView::FixedObjectSet::const_iterator it = fixedObjects->begin(), end = fixedObjects->end(); it != end; ++it) {
+        RenderObject* fixedObject = *it;
+        if (!fixedObject->isBoxModelObject() || !fixedObject->hasLayer())
+            return true;
+        RenderBoxModelObject* fixedBoxModelObject = toRenderBoxModelObject(fixedObject);
+        if (!fixedBoxModelObject->layer()->backing())
+            return true;
+    }
+    return false;
+#else
+    return fixedObjects->size();
+#endif
+}
+
 void ScrollingCoordinator::updateShouldUpdateScrollLayerPositionOnMainThread()
 {
     FrameView* frameView = m_page->mainFrame()->view();
 
-    // FIXME: Having fixed objects on the page should not trigger the slow path.
-    setShouldUpdateScrollLayerPositionOnMainThread(m_forceMainThreadScrollLayerPositionUpdates || frameView->hasSlowRepaintObjects() || frameView->hasFixedObjects() || m_page->mainFrame()->document()->isImageDocument());
+    setShouldUpdateScrollLayerPositionOnMainThread(m_forceMainThreadScrollLayerPositionUpdates
+        || frameView->hasSlowRepaintObjects()
+        || (!supportsFixedPositionLayers() && frameView->hasFixedObjects())
+        || (supportsFixedPositionLayers() && hasNonLayerFixedObjects(frameView))
+        || m_page->mainFrame()->document()->isImageDocument());
 }
 
 void ScrollingCoordinator::setForceMainThreadScrollLayerPositionUpdates(bool forceMainThreadScrollLayerPositionUpdates)
@@ -427,6 +451,21 @@ void ScrollingCoordinator::commitTreeState()
     OwnPtr<ScrollingTreeState> treeState = m_scrollingTreeState->commit();
     ScrollingThread::dispatch(bind(&ScrollingTree::commitNewTreeState, m_scrollingTree.get(), treeState.release()));
 }
-#endif
+
+bool ScrollingCoordinator::supportsFixedPositionLayers() const
+{
+    return false;
+}
+
+void ScrollingCoordinator::setLayerIsContainerForFixedPositionLayers(GraphicsLayer*, bool)
+{
+    // FIXME: Implement!
+}
+
+void ScrollingCoordinator::setLayerIsFixedToContainerLayer(GraphicsLayer*, bool)
+{
+    // FIXME: Implement!
+}
+#endif // !ENABLE(THREADED_SCROLLING)
 
 } // namespace WebCore
index b471e2a..35649a9 100644 (file)
@@ -80,11 +80,8 @@ public:
     // Should be called whenever the slow repaint objects counter changes between zero and one.
     void frameViewHasSlowRepaintObjectsDidChange(FrameView*);
 
-    // Should be called whenever the fixed objects counter changes between zero and one.
-    // FIXME: This is a temporary workaround so that we'll fall into main thread scrolling mode
-    // if a page has fixed elements. The scrolling tree should know about the fixed elements
-    // so it can make sure they stay fixed even when we scroll on the scrolling thread.
-    void frameViewHasFixedObjectsDidChange(FrameView*);
+    // Should be called whenever the set of fixed objects changes.
+    void frameViewFixedObjectsDidChange(FrameView*);
 
     // Should be called whenever the root layer for the given frame view changes.
     void frameViewRootLayerDidChange(FrameView*);
@@ -116,10 +113,21 @@ public:
     // Force all scroll layer position updates to happen on the main thread.
     void setForceMainThreadScrollLayerPositionUpdates(bool);
 
+    // Return whether this scrolling coordinator can keep fixed position layers fixed to their
+    // containers while scrolling.
+    bool supportsFixedPositionLayers() const;
+
+    // Mark/unmark a layer as a container for fixed position layers.
+    void setLayerIsContainerForFixedPositionLayers(GraphicsLayer*, bool);
+
+    // Attach/detach layer position to ancestor fixed position container.
+    void setLayerIsFixedToContainerLayer(GraphicsLayer*, bool);
+
 private:
     explicit ScrollingCoordinator(Page*);
 
     void recomputeWheelEventHandlerCount();
+    bool hasNonLayerFixedObjects(FrameView*);
     void updateShouldUpdateScrollLayerPositionOnMainThread();
 
     void setScrollLayer(GraphicsLayer*);
index cf145dd..f0acfe0 100644 (file)
@@ -71,7 +71,18 @@ void ScrollingCoordinator::setShouldUpdateScrollLayerPositionOnMainThread(bool)
 {
 }
 
-#endif // !ENABLE(THREADED_SCROLLING)
+bool ScrollingCoordinator::supportsFixedPositionLayers() const
+{
+    return false;
+}
 
+void ScrollingCoordinator::setLayerIsContainerForFixedPositionLayers(GraphicsLayer*, bool)
+{
 }
 
+void ScrollingCoordinator::setLayerIsFixedToContainerLayer(GraphicsLayer*, bool)
+{
+}
+#endif // !ENABLE(THREADED_SCROLLING)
+
+}
index 0e77f3a..0c3b0c3 100644 (file)
@@ -184,4 +184,21 @@ void ScrollingCoordinator::setShouldUpdateScrollLayerPositionOnMainThread(bool s
         layer->setShouldScrollOnMainThread(should);
 }
 
+bool ScrollingCoordinator::supportsFixedPositionLayers() const
+{
+    return true;
+}
+
+void ScrollingCoordinator::setLayerIsContainerForFixedPositionLayers(GraphicsLayer* layer, bool enable)
+{
+    if (LayerChromium* platformLayer = layer->platformLayer())
+        platformLayer->setIsContainerForFixedPositionLayers(enable);
+}
+
+void ScrollingCoordinator::setLayerIsFixedToContainerLayer(GraphicsLayer* layer, bool enable)
+{
+    if (LayerChromium* platformLayer = layer->platformLayer())
+        platformLayer->setFixedToContainerLayer(enable);
+}
+
 }
index bc82feb..3c343a6 100644 (file)
@@ -74,7 +74,7 @@ LayerChromium::LayerChromium()
     , m_opacity(1.0)
     , m_anchorPointZ(0)
     , m_isContainerForFixedPositionLayers(false)
-    , m_fixedToContainerLayerVisibleRect(false)
+    , m_fixedToContainerLayer(false)
     , m_isDrawable(false)
     , m_masksToBounds(false)
     , m_opaque(false)
@@ -478,6 +478,37 @@ void LayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
     setNeedsCommit();
 }
 
+bool LayerChromium::descendantIsFixedToContainerLayer() const
+{
+    for (size_t i = 0; i < m_children.size(); ++i) {
+        if (m_children[i]->fixedToContainerLayer() || m_children[i]->descendantIsFixedToContainerLayer())
+            return true;
+    }
+    return false;
+}
+
+void LayerChromium::setIsContainerForFixedPositionLayers(bool isContainerForFixedPositionLayers)
+{
+    if (m_isContainerForFixedPositionLayers == isContainerForFixedPositionLayers)
+        return;
+    m_isContainerForFixedPositionLayers = isContainerForFixedPositionLayers;
+
+    if (m_layerTreeHost && m_layerTreeHost->commitRequested())
+        return;
+
+    // Only request a commit if we have a fixed positioned descendant.
+    if (descendantIsFixedToContainerLayer())
+        setNeedsCommit();
+}
+
+void LayerChromium::setFixedToContainerLayer(bool fixedToContainerLayer)
+{
+    if (m_fixedToContainerLayer == fixedToContainerLayer)
+        return;
+    m_fixedToContainerLayer = fixedToContainerLayer;
+    setNeedsCommit();
+}
+
 void LayerChromium::pushPropertiesTo(CCLayerImpl* layer)
 {
     layer->setAnchorPoint(m_anchorPoint);
@@ -510,7 +541,7 @@ void LayerChromium::pushPropertiesTo(CCLayerImpl* layer)
         layer->setOpacity(m_opacity);
     layer->setPosition(m_position);
     layer->setIsContainerForFixedPositionLayers(m_isContainerForFixedPositionLayers);
-    layer->setFixedToContainerLayerVisibleRect(m_fixedToContainerLayerVisibleRect);
+    layer->setFixedToContainerLayer(m_fixedToContainerLayer);
     layer->setPreserves3D(preserves3D());
     layer->setScrollPosition(m_scrollPosition);
     layer->setSublayerTransform(m_sublayerTransform);
index e33c2fd..ec93873 100644 (file)
@@ -130,11 +130,11 @@ public:
     void setPosition(const FloatPoint&);
     FloatPoint position() const { return m_position; }
 
-    void setIsContainerForFixedPositionLayers(bool isContainerForFixedPositionLayers) { m_isContainerForFixedPositionLayers = isContainerForFixedPositionLayers; }
+    void setIsContainerForFixedPositionLayers(bool);
     bool isContainerForFixedPositionLayers() const { return m_isContainerForFixedPositionLayers; }
 
-    void setFixedToContainerLayerVisibleRect(bool fixedToContainerLayerVisibleRect) { m_fixedToContainerLayerVisibleRect = fixedToContainerLayerVisibleRect; setNeedsCommit(); }
-    bool fixedToContainerLayerVisibleRect() const { return m_fixedToContainerLayerVisibleRect; }
+    void setFixedToContainerLayer(bool);
+    bool fixedToContainerLayer() const { return m_fixedToContainerLayer; }
 
     void setSublayerTransform(const WebKit::WebTransformationMatrix&);
     const WebKit::WebTransformationMatrix& sublayerTransform() const { return m_sublayerTransform; }
@@ -294,6 +294,7 @@ protected:
 private:
     void setParent(LayerChromium*);
     bool hasAncestor(LayerChromium*) const;
+    bool descendantIsFixedToContainerLayer() const;
 
     size_t numChildren() const { return m_children.size(); }
 
@@ -341,7 +342,7 @@ private:
     WebKit::WebFilterOperations m_backgroundFilters;
     float m_anchorPointZ;
     bool m_isContainerForFixedPositionLayers;
-    bool m_fixedToContainerLayerVisibleRect;
+    bool m_fixedToContainerLayer;
     bool m_isDrawable;
     bool m_masksToBounds;
     bool m_opaque;
index c155a48..8a53899 100644 (file)
@@ -64,7 +64,7 @@ CCLayerImpl::CCLayerImpl(int id)
     , m_drawsContent(false)
     , m_forceRenderSurface(false)
     , m_isContainerForFixedPositionLayers(false)
-    , m_fixedToContainerLayerVisibleRect(false)
+    , m_fixedToContainerLayer(false)
     , m_pageScaleDelta(1)
     , m_targetRenderSurface(0)
     , m_drawDepth(0)
index 7189963..0a23cd8 100644 (file)
@@ -134,8 +134,8 @@ public:
     void setIsContainerForFixedPositionLayers(bool isContainerForFixedPositionLayers) { m_isContainerForFixedPositionLayers = isContainerForFixedPositionLayers; }
     bool isContainerForFixedPositionLayers() const { return m_isContainerForFixedPositionLayers; }
 
-    void setFixedToContainerLayerVisibleRect(bool fixedToContainerLayerVisibleRect = true) { m_fixedToContainerLayerVisibleRect = fixedToContainerLayerVisibleRect;}
-    bool fixedToContainerLayerVisibleRect() const { return m_fixedToContainerLayerVisibleRect; }
+    void setFixedToContainerLayer(bool fixedToContainerLayer = true) { m_fixedToContainerLayer = fixedToContainerLayer;}
+    bool fixedToContainerLayer() const { return m_fixedToContainerLayer; }
 
     void setPreserves3D(bool);
     bool preserves3D() const { return m_preserves3D; }
@@ -332,7 +332,7 @@ private:
     // Set for the layer that other layers are fixed to.
     bool m_isContainerForFixedPositionLayers;
     // This is true if the layer should be fixed to the closest ancestor container.
-    bool m_fixedToContainerLayerVisibleRect;
+    bool m_fixedToContainerLayer;
 
     FloatSize m_scrollDelta;
     IntSize m_sentScrollDelta;
index 3da9219..d97fe2e 100644 (file)
@@ -533,7 +533,7 @@ static bool calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay
     WebTransformationMatrix combinedTransform = parentMatrix;
     combinedTransform.multiply(layerLocalTransform);
 
-    if (layer->fixedToContainerLayerVisibleRect()) {
+    if (layer->fixedToContainerLayer()) {
         // Special case: this layer is a composited fixed-position layer; we need to
         // explicitly compensate for all ancestors' nonzero scrollDeltas to keep this layer
         // fixed correctly.
index fcc8df7..ddca07d 100644 (file)
@@ -142,7 +142,7 @@ void RenderBox::willBeDestroyed()
         if (RenderView* view = this->view()) {
             if (FrameView* frameView = view->frameView()) {
                 if (styleToUse->position() == FixedPosition)
-                    frameView->removeFixedObject();
+                    frameView->removeFixedObject(this);
             }
         }
     }
@@ -221,9 +221,9 @@ void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyl
         bool oldStyleIsFixed = oldStyle && oldStyle->position() == FixedPosition;
         if (newStyleIsFixed != oldStyleIsFixed) {
             if (newStyleIsFixed)
-                frameView->addFixedObject();
+                frameView->addFixedObject(this);
             else
-                frameView->removeFixedObject();
+                frameView->removeFixedObject(this);
         }
     }
 
index adce4c7..d55c431 100644 (file)
@@ -51,6 +51,7 @@
 #include "RenderEmbeddedObject.h"
 #include "RenderVideo.h"
 #include "RenderView.h"
+#include "ScrollingCoordinator.h"
 #include "StyleResolver.h"
 #include "TiledBacking.h"
 
@@ -434,6 +435,20 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
     m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection());
     m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
 
+    // Register fixed position layers and their containers with the scrolling coordinator.
+    if (Page* page = renderer()->frame()->page()) {
+        if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
+            if (style->position() == FixedPosition || compositor()->fixedPositionedByAncestor(m_owningLayer))
+                scrollingCoordinator->setLayerIsFixedToContainerLayer(childForSuperlayers(), true);
+            else {
+                if (m_ancestorClippingLayer)
+                    scrollingCoordinator->setLayerIsFixedToContainerLayer(m_ancestorClippingLayer.get(), false);
+                scrollingCoordinator->setLayerIsFixedToContainerLayer(m_graphicsLayer.get(), false);
+            }
+            bool isContainer = m_owningLayer->hasTransform();
+            scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer);
+        }
+    }
     RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
     
     // We compute everything relative to the enclosing compositing layer.
@@ -1564,4 +1579,3 @@ double RenderLayerBacking::backingStoreArea() const
 } // namespace WebCore
 
 #endif // USE(ACCELERATED_COMPOSITING)
-
index 7784451..1466e39 100644 (file)
@@ -547,6 +547,11 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR
     if (layerChanged)
         layer->clearClipRectsIncludingDescendants(PaintingClipRects);
 
+    // If a fixed position layer gained/lost a backing, the scrolling coordinator needs to recalculate whether it can do fast scrolling.
+    if (layerChanged && layer->renderer()->style()->position() == FixedPosition) {
+        if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+            scrollingCoordinator->frameViewFixedObjectsDidChange(m_renderView->frameView());
+    }
     return layerChanged;
 }
 
@@ -1611,6 +1616,31 @@ bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer
            (layer->renderer()->hasOverflowClip() || layer->renderer()->hasClip());
 }
 
+// Return true if there is an ancestor layer that is fixed positioned to the view.
+// Note that if the ancestor has a stacking context and is fixed position then this method
+// will return false.
+bool RenderLayerCompositor::fixedPositionedByAncestor(const RenderLayer* layer) const
+{
+    if (!layer->isComposited() || !layer->parent())
+        return false;
+
+    const RenderLayer* compositingAncestor = layer->ancestorCompositingLayer();
+    if (!compositingAncestor)
+        return false;
+
+    const RenderLayer* curr = layer;
+    while (curr) {
+        const RenderLayer* next = curr->parent();
+        if (next == compositingAncestor)
+            return false;
+
+        if (next && next->renderer()->style()->position() == FixedPosition)
+            return true;
+        curr = next;
+    }
+    return false;
+}
+
 bool RenderLayerCompositor::requiresCompositingForScrollableFrame() const
 {
     // Need this done first to determine overflow.
@@ -2158,6 +2188,8 @@ void RenderLayerCompositor::ensureRootLayer()
 #ifndef NDEBUG
             m_scrollLayer->setName("frame scrolling");
 #endif
+            if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+                scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(m_scrollLayer.get(), true);
 
             // Hook them up
             m_overflowControlsHostLayer->addChild(m_clipLayer.get());
index 792fb01..ff24c96 100644 (file)
@@ -116,6 +116,9 @@ public:
     // Whether layer's backing needs a graphics layer to clip z-order children of the given layer.
     bool clipsCompositingDescendants(const RenderLayer*) const;
 
+    // Whether the layer is fixed positioned to the view by an ancestor layer.
+    bool fixedPositionedByAncestor(const RenderLayer*) const;
+
     // Whether the given layer needs an extra 'contents' layer.
     bool needsContentsCompositingLayer(const RenderLayer*) const;
     // Return the bounding box required for compositing layer and its childern, relative to ancestorLayer.
index dc0a177..0aad70f 100644 (file)
@@ -1234,7 +1234,7 @@ TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWit
     CCLayerImpl* grandChild = child->children()[0].get();
 
     child->setIsContainerForFixedPositionLayers(true);
-    grandChild->setFixedToContainerLayerVisibleRect(true);
+    grandChild->setFixedToContainerLayer(true);
 
     // Case 1: scrollDelta of 0, 0
     child->setScrollDelta(IntSize(0, 0));
@@ -1283,7 +1283,7 @@ TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWit
     child->setTransform(nonUniformScale);
 
     child->setIsContainerForFixedPositionLayers(true);
-    grandChild->setFixedToContainerLayerVisibleRect(true);
+    grandChild->setFixedToContainerLayer(true);
 
     // Case 1: scrollDelta of 0, 0
     child->setScrollDelta(IntSize(0, 0));
@@ -1326,7 +1326,7 @@ TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWit
 
     child->setIsContainerForFixedPositionLayers(true);
     grandChild->setPosition(FloatPoint(8, 6));
-    greatGrandChild->setFixedToContainerLayerVisibleRect(true);
+    greatGrandChild->setFixedToContainerLayer(true);
 
     // Case 1: scrollDelta of 0, 0
     child->setScrollDelta(IntSize(0, 0));
@@ -1377,7 +1377,7 @@ TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWit
     child->setTransform(rotationAboutZ);
     grandChild->setPosition(FloatPoint(8, 6));
     grandChild->setTransform(rotationAboutZ);
-    greatGrandChild->setFixedToContainerLayerVisibleRect(true); // greatGrandChild is positioned upside-down with respect to the targetRenderSurface
+    greatGrandChild->setFixedToContainerLayer(true); // greatGrandChild is positioned upside-down with respect to the targetRenderSurface
 
     // Case 1: scrollDelta of 0, 0
     child->setScrollDelta(IntSize(0, 0));
@@ -1443,7 +1443,7 @@ TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWit
     child->setTransform(rotationAboutZ);
     grandChild->setPosition(FloatPoint(8, 6));
     grandChild->setTransform(rotationAboutZ);
-    greatGrandChild->setFixedToContainerLayerVisibleRect(true); // greatGrandChild is positioned upside-down with respect to the targetRenderSurface
+    greatGrandChild->setFixedToContainerLayer(true); // greatGrandChild is positioned upside-down with respect to the targetRenderSurface
 
     // Case 1: scrollDelta of 0, 0
     child->setScrollDelta(IntSize(0, 0));
@@ -1505,7 +1505,7 @@ TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWit
     child->setIsContainerForFixedPositionLayers(true);
     grandChild->setPosition(FloatPoint(8, 6));
     grandChild->setForceRenderSurface(true);
-    greatGrandChild->setFixedToContainerLayerVisibleRect(true);
+    greatGrandChild->setFixedToContainerLayer(true);
     greatGrandChild->setDrawsContent(true);
 
     WebTransformationMatrix rotationAboutZ;
@@ -1595,7 +1595,7 @@ TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWit
     grandChild->setForceRenderSurface(true);
     greatGrandChild->setPosition(FloatPoint(140, 120));
     greatGrandChild->setForceRenderSurface(true);
-    fixedPositionChild->setFixedToContainerLayerVisibleRect(true);
+    fixedPositionChild->setFixedToContainerLayer(true);
     fixedPositionChild->setDrawsContent(true);
 
     // The additional rotations, which are non-commutative with translations, help to
@@ -1694,7 +1694,7 @@ TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWit
 
     child->setIsContainerForFixedPositionLayers(true);
     child->setForceRenderSurface(true);
-    grandChild->setFixedToContainerLayerVisibleRect(true);
+    grandChild->setFixedToContainerLayer(true);
     grandChild->setDrawsContent(true);
 
     // Case 1: scrollDelta of 0, 0
@@ -1742,7 +1742,7 @@ TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerTha
     CCLayerImpl* grandChild = child->children()[0].get();
 
     child->setIsContainerForFixedPositionLayers(true);
-    grandChild->setFixedToContainerLayerVisibleRect(true);
+    grandChild->setFixedToContainerLayer(true);
 
     // This should not confuse the grandChild. If correct, the grandChild would still be considered fixed to its container (i.e. "child").
     grandChild->setIsContainerForFixedPositionLayers(true);
@@ -1785,7 +1785,7 @@ TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerTha
     rotationByZ.rotate3d(0, 0, 90);
 
     root->setTransform(rotationByZ);
-    grandChild->setFixedToContainerLayerVisibleRect(true);
+    grandChild->setFixedToContainerLayer(true);
 
     // Case 1: root scrollDelta of 0, 0
     root->setScrollDelta(IntSize(0, 0));