Title: [107335] trunk/Source/WebCore
Revision
107335
Author
[email protected]
Date
2012-02-09 18:10:13 -0800 (Thu, 09 Feb 2012)

Log Message

Update the scroll layer position on the main thread when we have slow repaint objects
https://bugs.webkit.org/show_bug.cgi?id=78300
<rdar://problem/10710754>

Reviewed by Dan Bernstein.

When we have slow repaint objects (background-attachment: fixed), we need to update the
scroll layer position on the main thread, otherwise the web page will appear to jiggle.

* page/FrameView.cpp:
(WebCore::FrameView::addSlowRepaintObject):
(WebCore::FrameView::removeSlowRepaintObject):
Call ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange if needed.

* page/FrameView.h:
(WebCore::FrameView::hasSlowRepaintObjects):
Add new getter.

* page/scrolling/ScrollingCoordinator.cpp:
(WebCore::ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange):
Call ScrollingTreeNode::shouldUpdateScrollLayerPositionOnMainThread.

(WebCore::ScrollingCoordinator::updateMainFrameScrollPositionAndScrollLayerPosition):
New function that will update both the main frame scroll position and the scroll layer position.

* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::updateMainFrameScrollPositionAndScrollLayerPosition):
Dispatch a call to ScrollingCoordinator::updateMainFrameScrollPositionAndScrollLayerPosition on the main thread.

* page/scrolling/ScrollingTreeNode.cpp:
(WebCore::ScrollingTreeNode::ScrollingTreeNode):
Initialize m_shouldUpdateScrollLayerPositionOnMainThread.

(WebCore::ScrollingTreeNode::update):
Set m_shouldUpdateScrollLayerPositionOnMainThread.

* page/scrolling/ScrollingTreeState.cpp:
(WebCore::ScrollingTreeState::ScrollingTreeState):
Initialize m_shouldUpdateScrollLayerPositionOnMainThread.

(WebCore::ScrollingTreeState::setShouldUpdateScrollLayerPositionOnMainThread):
Update m_shouldUpdateScrollLayerPositionOnMainThread if needed.

* page/scrolling/mac/ScrollingTreeNodeMac.mm:
(WebCore::ScrollingTreeNodeMac::setScrollPosition):
Assert that we're not supposed to update the scroll layer position on the main thread.

(WebCore::ScrollingTreeNodeMac::scrollBy):
If we're supposed to update the scroll layer position on the main thread,
call ScrollingTree::updateMainFrameScrollPositionAndScrollLayerPosition.

* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::frameViewDidScroll):
If the frame view has its scrolling coordinated by a scrolling coordinator, don't update the scroll layer position.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (107334 => 107335)


--- trunk/Source/WebCore/ChangeLog	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/ChangeLog	2012-02-10 02:10:13 UTC (rev 107335)
@@ -1,5 +1,62 @@
 2012-02-09  Anders Carlsson  <[email protected]>
 
+        Update the scroll layer position on the main thread when we have slow repaint objects
+        https://bugs.webkit.org/show_bug.cgi?id=78300
+        <rdar://problem/10710754>
+
+        Reviewed by Dan Bernstein.
+
+        When we have slow repaint objects (background-attachment: fixed), we need to update the
+        scroll layer position on the main thread, otherwise the web page will appear to jiggle.
+    
+        * page/FrameView.cpp:
+        (WebCore::FrameView::addSlowRepaintObject):
+        (WebCore::FrameView::removeSlowRepaintObject):
+        Call ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange if needed.
+
+        * page/FrameView.h:
+        (WebCore::FrameView::hasSlowRepaintObjects):
+        Add new getter.
+
+        * page/scrolling/ScrollingCoordinator.cpp:
+        (WebCore::ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange):
+        Call ScrollingTreeNode::shouldUpdateScrollLayerPositionOnMainThread.
+
+        (WebCore::ScrollingCoordinator::updateMainFrameScrollPositionAndScrollLayerPosition):
+        New function that will update both the main frame scroll position and the scroll layer position.
+
+        * page/scrolling/ScrollingTree.cpp:
+        (WebCore::ScrollingTree::updateMainFrameScrollPositionAndScrollLayerPosition):
+        Dispatch a call to ScrollingCoordinator::updateMainFrameScrollPositionAndScrollLayerPosition on the main thread.
+
+        * page/scrolling/ScrollingTreeNode.cpp:
+        (WebCore::ScrollingTreeNode::ScrollingTreeNode):
+        Initialize m_shouldUpdateScrollLayerPositionOnMainThread.
+
+        (WebCore::ScrollingTreeNode::update):
+        Set m_shouldUpdateScrollLayerPositionOnMainThread.
+
+        * page/scrolling/ScrollingTreeState.cpp:
+        (WebCore::ScrollingTreeState::ScrollingTreeState):
+        Initialize m_shouldUpdateScrollLayerPositionOnMainThread.
+
+        (WebCore::ScrollingTreeState::setShouldUpdateScrollLayerPositionOnMainThread):
+        Update m_shouldUpdateScrollLayerPositionOnMainThread if needed.
+
+        * page/scrolling/mac/ScrollingTreeNodeMac.mm:
+        (WebCore::ScrollingTreeNodeMac::setScrollPosition):
+        Assert that we're not supposed to update the scroll layer position on the main thread.
+
+        (WebCore::ScrollingTreeNodeMac::scrollBy):
+        If we're supposed to update the scroll layer position on the main thread, 
+        call ScrollingTree::updateMainFrameScrollPositionAndScrollLayerPosition.
+
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::frameViewDidScroll):
+        If the frame view has its scrolling coordinated by a scrolling coordinator, don't update the scroll layer position.
+
+2012-02-09  Anders Carlsson  <[email protected]>
+
         FrameView::addSlowRepaintObject() doesn't update m_canBlitOnScroll correctly
         https://bugs.webkit.org/show_bug.cgi?id=78291
 

Modified: trunk/Source/WebCore/page/FrameView.cpp (107334 => 107335)


--- trunk/Source/WebCore/page/FrameView.cpp	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/FrameView.cpp	2012-02-10 02:10:13 UTC (rev 107335)
@@ -1328,16 +1328,32 @@
 
 void FrameView::addSlowRepaintObject()
 {
-    if (!m_slowRepaintObjectCount++)
+    if (!m_slowRepaintObjectCount++) {
         updateCanBlitOnScrollRecursively();
+
+#if ENABLE(THREADED_SCROLLING)
+        if (Page* page = m_frame->page()) {
+            if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
+                scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
+        }
+#endif
+    }
 }
 
 void FrameView::removeSlowRepaintObject()
 {
     ASSERT(m_slowRepaintObjectCount > 0);
     m_slowRepaintObjectCount--;
-    if (!m_slowRepaintObjectCount)
+    if (!m_slowRepaintObjectCount) {
         updateCanBlitOnScrollRecursively();
+
+#if ENABLE(THREADED_SCROLLING)
+        if (Page* page = m_frame->page()) {
+            if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
+                scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
+        }
+#endif
+    }
 }
 
 void FrameView::addFixedObject()

Modified: trunk/Source/WebCore/page/FrameView.h (107334 => 107335)


--- trunk/Source/WebCore/page/FrameView.h	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/FrameView.h	2012-02-10 02:10:13 UTC (rev 107335)
@@ -184,6 +184,7 @@
 
     void addSlowRepaintObject();
     void removeSlowRepaintObject();
+    bool hasSlowRepaintObjects() const { return m_slowRepaintObjectCount; }
 
     void addFixedObject();
     void removeFixedObject();

Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp (107334 => 107335)


--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp	2012-02-10 02:10:13 UTC (rev 107335)
@@ -35,6 +35,8 @@
 #include "Page.h"
 #include "PlatformWheelEvent.h"
 #include "Region.h"
+#include "RenderLayerCompositor.h"
+#include "RenderView.h"
 #include "ScrollAnimator.h"
 #include "ScrollingThread.h"
 #include "ScrollingTree.h"
@@ -134,6 +136,18 @@
     recomputeWheelEventHandlerCount();
 }
 
+void ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange(FrameView* frameView)
+{
+    ASSERT(isMainThread());
+    ASSERT(m_page);
+
+    if (!coordinatesScrollingForFrameView(frameView))
+        return;
+
+    m_scrollingTreeState->setShouldUpdateScrollLayerPositionOnMainThread(frameView->hasSlowRepaintObjects());
+    scheduleTreeStateCommit();
+}
+
 void ScrollingCoordinator::updateMainFrameScrollPosition(const IntPoint& scrollPosition)
 {
     ASSERT(isMainThread());
@@ -150,6 +164,25 @@
     frameView->setConstrainsScrollingToContentEdge(true);
 }
 
+void ScrollingCoordinator::updateMainFrameScrollPositionAndScrollLayerPosition(const IntPoint& scrollPosition)
+{
+    FrameView* frameView = m_page->mainFrame()->view();
+
+    RenderView* renderView = m_page->mainFrame()->contentRenderer();
+    if (!renderView)
+        return;
+
+    GraphicsLayer* scrollLayer = renderView->compositor()->scrollLayer();
+    if (!scrollLayer)
+        return;
+
+    frameView->setConstrainsScrollingToContentEdge(false);
+    frameView->scrollToOffsetWithoutAnimation(scrollPosition);
+    frameView->setConstrainsScrollingToContentEdge(true);
+
+    scrollLayer->setPosition(-frameView->scrollPosition());
+}
+
 void ScrollingCoordinator::recomputeWheelEventHandlerCount()
 {
     unsigned wheelEventHandlerCount = 0;

Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h (107334 => 107335)


--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h	2012-02-10 02:10:13 UTC (rev 107335)
@@ -71,6 +71,9 @@
     // frame view's underlying document.
     void frameViewWheelEventHandlerCountChanged(FrameView*);
 
+    // Should be called whenever the slow repaint objects counter changes between zero and one.
+    void frameViewHasSlowRepaintObjectsDidChange(FrameView*);
+
     // Should be called whenever the scroll layer for the given frame view changes.
     void frameViewScrollLayerDidChange(FrameView*, const GraphicsLayer*);
 
@@ -83,6 +86,9 @@
     // Dispatched by the scrolling tree whenever the main frame scroll position changes.
     void updateMainFrameScrollPosition(const IntPoint&);
 
+    // Dispatched by the scrolling tree whenever the main frame scroll position changes and the scroll layer position needs to be updated as well.
+    void updateMainFrameScrollPositionAndScrollLayerPosition(const IntPoint&);
+
 private:
     explicit ScrollingCoordinator(Page*);
 

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp (107334 => 107335)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2012-02-10 02:10:13 UTC (rev 107335)
@@ -120,6 +120,19 @@
     callOnMainThread(bind(&ScrollingCoordinator::updateMainFrameScrollPosition, m_scrollingCoordinator.get(), scrollPosition));
 }
 
+void ScrollingTree::updateMainFrameScrollPositionAndScrollLayerPosition(const IntPoint& scrollPosition)
+{
+    if (!m_scrollingCoordinator)
+        return;
+
+    {
+        MutexLocker lock(m_mutex);
+        m_mainFrameScrollPosition = scrollPosition;
+    }
+
+    callOnMainThread(bind(&ScrollingCoordinator::updateMainFrameScrollPositionAndScrollLayerPosition, m_scrollingCoordinator.get(), scrollPosition));
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(THREADED_SCROLLING)

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.h (107334 => 107335)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2012-02-10 02:10:13 UTC (rev 107335)
@@ -64,6 +64,7 @@
     void commitNewTreeState(PassOwnPtr<ScrollingTreeState>);
 
     void updateMainFrameScrollPosition(const IntPoint& scrollPosition);
+    void updateMainFrameScrollPositionAndScrollLayerPosition(const IntPoint& scrollPosition);
 
 private:
     explicit ScrollingTree(ScrollingCoordinator*);

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeNode.cpp (107334 => 107335)


--- trunk/Source/WebCore/page/scrolling/ScrollingTreeNode.cpp	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeNode.cpp	2012-02-10 02:10:13 UTC (rev 107335)
@@ -34,6 +34,7 @@
 
 ScrollingTreeNode::ScrollingTreeNode(ScrollingTree* scrollingTree)
     : m_scrollingTree(scrollingTree)
+    , m_shouldUpdateScrollLayerPositionOnMainThread(false)
     , m_horizontalScrollElasticity(ScrollElasticityNone)
     , m_verticalScrollElasticity(ScrollElasticityNone)
     , m_hasEnabledHorizontalScrollbar(false)
@@ -53,6 +54,9 @@
     if (state->changedProperties() & ScrollingTreeState::ContentsSize)
         m_contentsSize = state->contentsSize();
 
+    if (state->changedProperties() & ScrollingTreeState::ShouldUpdateScrollLayerPositionOnMainThread)
+        m_shouldUpdateScrollLayerPositionOnMainThread = state->shouldUpdateScrollLayerPositionOnMainThread();
+
     if (state->changedProperties() & ScrollingTreeState::HorizontalScrollElasticity)
         m_horizontalScrollElasticity = state->horizontalScrollElasticity();
 

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeNode.h (107334 => 107335)


--- trunk/Source/WebCore/page/scrolling/ScrollingTreeNode.h	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeNode.h	2012-02-10 02:10:13 UTC (rev 107335)
@@ -52,6 +52,7 @@
     ScrollingTree* scrollingTree() const { return m_scrollingTree; }
     const IntRect& viewportRect() const { return m_viewportRect; }
     const IntSize& contentsSize() const { return m_contentsSize; }
+    bool shouldUpdateScrollLayerPositionOnMainThread() const { return m_shouldUpdateScrollLayerPositionOnMainThread; }
 
 private:
     ScrollingTree* m_scrollingTree;
@@ -59,6 +60,8 @@
     IntRect m_viewportRect;
     IntSize m_contentsSize;
 
+    bool m_shouldUpdateScrollLayerPositionOnMainThread;
+
     ScrollElasticity m_horizontalScrollElasticity;
     ScrollElasticity m_verticalScrollElasticity;
     

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeState.cpp (107334 => 107335)


--- trunk/Source/WebCore/page/scrolling/ScrollingTreeState.cpp	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeState.cpp	2012-02-10 02:10:13 UTC (rev 107335)
@@ -38,6 +38,7 @@
 ScrollingTreeState::ScrollingTreeState()
     : m_changedProperties(0)
     , m_wheelEventHandlerCount(0)
+    , m_shouldUpdateScrollLayerPositionOnMainThread(false)
     , m_horizontalScrollElasticity(ScrollElasticityNone)
     , m_verticalScrollElasticity(ScrollElasticityNone)
     , m_hasEnabledHorizontalScrollbar(false)
@@ -85,6 +86,15 @@
     m_changedProperties |= WheelEventHandlerCount;
 }
 
+void ScrollingTreeState::setShouldUpdateScrollLayerPositionOnMainThread(bool shouldUpdateScrollLayerPositionOnMainThread)
+{
+    if (m_shouldUpdateScrollLayerPositionOnMainThread == shouldUpdateScrollLayerPositionOnMainThread)
+        return;
+
+    m_shouldUpdateScrollLayerPositionOnMainThread = shouldUpdateScrollLayerPositionOnMainThread;
+    m_changedProperties |= ShouldUpdateScrollLayerPositionOnMainThread;
+}
+
 void ScrollingTreeState::setHorizontalScrollElasticity(ScrollElasticity horizontalScrollElasticity)
 {
     if (m_horizontalScrollElasticity == horizontalScrollElasticity)

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeState.h (107334 => 107335)


--- trunk/Source/WebCore/page/scrolling/ScrollingTreeState.h	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeState.h	2012-02-10 02:10:13 UTC (rev 107335)
@@ -54,11 +54,12 @@
         ContentsSize = 1 << 1,
         NonFastScrollableRegion = 1 << 2,
         WheelEventHandlerCount = 1 << 3,
-        HorizontalScrollElasticity = 1 << 4,
-        VerticalScrollElasticity = 1 << 5,
-        HasEnabledHorizontalScrollbar = 1 << 6,
-        HasEnabledVerticalScrollbar = 1 << 7,
-        ScrollLayer = 1 << 8,
+        ShouldUpdateScrollLayerPositionOnMainThread = 1 << 4,
+        HorizontalScrollElasticity = 1 << 5,
+        VerticalScrollElasticity = 1 << 6,
+        HasEnabledHorizontalScrollbar = 1 << 7,
+        HasEnabledVerticalScrollbar = 1 << 8,
+        ScrollLayer = 1 << 9,
     };
 
     bool hasChangedProperties() const { return m_changedProperties; }
@@ -76,6 +77,9 @@
     unsigned wheelEventHandlerCount() const { return m_wheelEventHandlerCount; }
     void setWheelEventHandlerCount(unsigned);
 
+    bool shouldUpdateScrollLayerPositionOnMainThread() const { return m_shouldUpdateScrollLayerPositionOnMainThread; }
+    void setShouldUpdateScrollLayerPositionOnMainThread(bool);
+
     ScrollElasticity horizontalScrollElasticity() const { return m_horizontalScrollElasticity; }
     void setHorizontalScrollElasticity(ScrollElasticity);
 
@@ -106,6 +110,8 @@
 
     unsigned m_wheelEventHandlerCount;
 
+    bool m_shouldUpdateScrollLayerPositionOnMainThread;
+
     ScrollElasticity m_horizontalScrollElasticity;
     ScrollElasticity m_verticalScrollElasticity;
 

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeNodeMac.mm (107334 => 107335)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeNodeMac.mm	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeNodeMac.mm	2012-02-10 02:10:13 UTC (rev 107335)
@@ -134,14 +134,22 @@
 
 void ScrollingTreeNodeMac::setScrollPosition(const IntPoint& position)
 {
+    ASSERT(!shouldUpdateScrollLayerPositionOnMainThread());
+
     m_scrollLayer.get().position = CGPointMake(-position.x(), -position.y());
 }
 
-void ScrollingTreeNodeMac::scrollBy(const IntSize &offset)
+void ScrollingTreeNodeMac::scrollBy(const IntSize& offset)
 {
-    setScrollPosition(scrollPosition() + offset);
+    IntPoint newScrollPosition = scrollPosition() + offset;
 
-    scrollingTree()->updateMainFrameScrollPosition(scrollPosition());
+    if (shouldUpdateScrollLayerPositionOnMainThread()) {
+        scrollingTree()->updateMainFrameScrollPositionAndScrollLayerPosition(newScrollPosition);
+        return;
+    }
+
+    setScrollPosition(newScrollPosition);
+    scrollingTree()->updateMainFrameScrollPosition(newScrollPosition);
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (107334 => 107335)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2012-02-10 01:58:36 UTC (rev 107334)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2012-02-10 02:10:13 UTC (rev 107335)
@@ -983,8 +983,19 @@
     if (RenderLayerBacking* backing = rootRenderLayer()->backing())
         backing->graphicsLayer()->visibleRectChanged();
 
-    if (m_scrollLayer)
-        m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
+    if (!m_scrollLayer)
+        return;
+
+#if ENABLE(THREADED_SCROLLING)
+    // If there's a scrolling coordinator that manages scrolling for this frame view,
+    // it will also manage updating the scroll layer position.
+    if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
+        if (scrollingCoordinator->coordinatesScrollingForFrameView(frameView))
+            return;
+    }
+#endif
+
+    m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
 }
 
 String RenderLayerCompositor::layerTreeAsText(bool showDebugInfo)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to