Changeset 168338 in webkit


Ignore:
Timestamp:
May 5, 2014 6:10:30 PM (10 years ago)
Author:
Simon Fraser
Message:

[iOS WK2] Flickery scrolling inside overflow-scrolling: touch
https://bugs.webkit.org/show_bug.cgi?id=132591
<rdar://problem/16760466>

Reviewed by Tim Horton.

Source/WebCore:

Avoid triggering layer tree commits that touch the layer's boundsOrigin
while the user is scrolling in the UI process.

Fix the WKOverflowScrollViewDelegate to pass along an "inUserInteration"
flag to the ScrollingTree to say that we're in the middle of a user interaction
(and also to send a final non-interactive update). That gets passed along
to the web process, and turned into "SyncScrollingLayerPosition" update.
AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll() consults
this, and uses it to set a flag on the ScrollableArea to say that the scroll
is a user scroll.

RenderLayerBacking then makes use of this (in existing code, shared with WK1)
to avoid triggering layer bounds setting. Instead, it now just calls syncBoundsOrigin(),
which updates the GraphicsLayer without touching platform layers. This is necessary
so that GraphicsLayer geometry is up-to-date (used for tiled layer visibility
computations).

Finally, a hack in GraphicsLayerCA::computeVisibleRect() is conditionalized
for WebKit1 by checking the type of platform layer.

  • WebCore.exp.in:
  • page/scrolling/AsyncScrollingCoordinator.cpp:

(WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):

  • page/scrolling/ScrollingTree.cpp:

(WebCore::ScrollingTree::scrollPositionChangedViaDelegatedScrolling):

  • page/scrolling/ScrollingTree.h:
  • platform/graphics/GraphicsLayer.h:

(WebCore::GraphicsLayer::syncBoundsOrigin):

  • platform/graphics/ca/GraphicsLayerCA.cpp:

(WebCore::GraphicsLayerCA::computeVisibleRect):

  • rendering/RenderLayerBacking.cpp:

(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):

Source/WebKit2:

Avoid triggering layer tree commits that touch the layer's boundsOrigin
while the user is scrolling in the UI process.

Fix the WKOverflowScrollViewDelegate to pass along an "inUserInteration"
flag to the ScrollingTree to say that we're in the middle of a user interaction
(and also to send a final non-interactive update). That gets passed along
to the web process, and turned into "SyncScrollingLayerPosition" update.
AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll() consults
this, and uses it to set a flag on the ScrollableArea to say that the scroll
is a user scroll.

RenderLayerBacking then makes use of this (in existing code, shared with WK1)
to avoid triggering layer bounds setting. Instead, it now just calls syncBoundsOrigin(),
which updates the GraphicsLayer without touching platform layers. This is necessary
so that GraphicsLayer geometry is up-to-date (used for tiled layer visibility
computations).

Finally, a hack in GraphicsLayerCA::computeVisibleRect() is conditionalized
for WebKit1 by checking the type of platform layer.

  • UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp:

(WebKit::RemoteScrollingCoordinatorProxy::rootScrollingNodeID):
(WebKit::RemoteScrollingCoordinatorProxy::isPointInNonFastScrollableRegion):
(WebKit::RemoteScrollingCoordinatorProxy::viewportChangedViaDelegatedScrolling):
(WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll):

  • UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
  • UIProcess/Scrolling/RemoteScrollingTree.cpp:

(WebKit::RemoteScrollingTree::scrollingTreeNodeDidScroll):

  • UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h:
  • UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:

(-[WKOverflowScrollViewDelegate scrollViewDidScroll:]):
(-[WKOverflowScrollViewDelegate scrollViewDidEndDragging:willDecelerate:]):
(-[WKOverflowScrollViewDelegate scrollViewDidEndDecelerating:]):
(WebKit::ScrollingTreeOverflowScrollingNodeIOS::scrollViewDidScroll):

  • WebProcess/Scrolling/RemoteScrollingCoordinator.h:
  • WebProcess/Scrolling/RemoteScrollingCoordinator.messages.in:
  • WebProcess/Scrolling/RemoteScrollingCoordinator.mm:

(WebKit::RemoteScrollingCoordinator::scrollPositionChangedForNode):

Location:
trunk/Source
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r168333 r168338  
     12014-05-05  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [iOS WK2] Flickery scrolling inside overflow-scrolling: touch
     4        https://bugs.webkit.org/show_bug.cgi?id=132591
     5        <rdar://problem/16760466>
     6
     7        Reviewed by Tim Horton.
     8
     9        Avoid triggering layer tree commits that touch the layer's boundsOrigin
     10        while the user is scrolling in the UI process.
     11       
     12        Fix the WKOverflowScrollViewDelegate to pass along an "inUserInteration"
     13        flag to the ScrollingTree to say that we're in the middle of a user interaction
     14        (and also to send a final non-interactive update). That gets passed along
     15        to the web process, and turned into "SyncScrollingLayerPosition" update.
     16        AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll() consults
     17        this, and uses it to set a flag on the ScrollableArea to say that the scroll
     18        is a user scroll.
     19       
     20        RenderLayerBacking then makes use of this (in existing code, shared with WK1)
     21        to avoid triggering layer bounds setting. Instead, it now just calls syncBoundsOrigin(),
     22        which updates the GraphicsLayer without touching platform layers. This is necessary
     23        so that GraphicsLayer geometry is up-to-date (used for tiled layer visibility
     24        computations).
     25       
     26        Finally, a hack in GraphicsLayerCA::computeVisibleRect() is conditionalized
     27        for WebKit1 by checking the type of platform layer.
     28
     29        * WebCore.exp.in:
     30        * page/scrolling/AsyncScrollingCoordinator.cpp:
     31        (WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):
     32        * page/scrolling/ScrollingTree.cpp:
     33        (WebCore::ScrollingTree::scrollPositionChangedViaDelegatedScrolling):
     34        * page/scrolling/ScrollingTree.h:
     35        * platform/graphics/GraphicsLayer.h:
     36        (WebCore::GraphicsLayer::syncBoundsOrigin):
     37        * platform/graphics/ca/GraphicsLayerCA.cpp:
     38        (WebCore::GraphicsLayerCA::computeVisibleRect):
     39        * rendering/RenderLayerBacking.cpp:
     40        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
     41
    1422014-05-05  Alexey Proskuryakov  <ap@apple.com>
    243
  • trunk/Source/WebCore/WebCore.exp.in

    r168316 r168338  
    27612761__ZN7WebCore13ScrollingTree36viewportChangedViaDelegatedScrollingEyRKNS_9FloatRectEd
    27622762__ZN7WebCore13ScrollingTree37setScrollingPerformanceLoggingEnabledEb
    2763 __ZN7WebCore13ScrollingTree42scrollPositionChangedViaDelegatedScrollingEyRKNS_10FloatPointE
     2763__ZN7WebCore13ScrollingTree42scrollPositionChangedViaDelegatedScrollingEyRKNS_10FloatPointEb
    27642764__ZN7WebCore13ScrollingTreeC2Ev
    27652765__ZN7WebCore13ScrollingTreeD1Ev
  • trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp

    r168244 r168338  
    255255
    256256    // Overflow-scroll area.
    257     if (ScrollableArea* scrollableArea = frameView->scrollableAreaForScrollLayerID(scrollingNodeID))
     257    if (ScrollableArea* scrollableArea = frameView->scrollableAreaForScrollLayerID(scrollingNodeID)) {
     258        scrollableArea->setIsUserScroll(scrollingLayerPositionAction == SyncScrollingLayerPosition);
    258259        scrollableArea->scrollToOffsetWithoutAnimation(scrollPosition);
     260        scrollableArea->setIsUserScroll(false);
     261    }
    259262}
    260263
  • trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp

    r168325 r168338  
    111111}
    112112
    113 void ScrollingTree::scrollPositionChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const WebCore::FloatPoint& scrollPosition)
     113void ScrollingTree::scrollPositionChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const WebCore::FloatPoint& scrollPosition, bool inUserInteration)
    114114{
    115115    ScrollingTreeNode* node = nodeForID(nodeID);
     
    124124
    125125    // Update GraphicsLayers and scroll state.
    126     scrollingTreeNodeDidScroll(nodeID, scrollPosition);
     126    scrollingTreeNodeDidScroll(nodeID, scrollPosition, inUserInteration ? SyncScrollingLayerPosition : SetScrollingLayerPosition);
    127127}
    128128
  • trunk/Source/WebCore/page/scrolling/ScrollingTree.h

    r167262 r168338  
    8585    // Delegated scrolling has scrolled a node. Update layer positions on descendant tree nodes,
    8686    // and call scrollingTreeNodeDidScroll().
    87     virtual void scrollPositionChangedViaDelegatedScrolling(ScrollingNodeID, const WebCore::FloatPoint& scrollPosition);
     87    virtual void scrollPositionChangedViaDelegatedScrolling(ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool inUserInteration);
    8888
    8989    FloatPoint mainFrameScrollPosition();
  • trunk/Source/WebCore/platform/ScrollableArea.h

    r167560 r168338  
    6969    virtual void didEndScroll() { }
    7070    virtual void didUpdateScroll() { }
     71#endif
    7172    virtual void setIsUserScroll(bool) { }
    72 #endif
    7373
    7474    // Functions for controlling if you can scroll past the end of the document.
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.h

    r168219 r168338  
    290290    // For platforms that move underlying platform layers on a different thread for scrolling; just update the GraphicsLayer state.
    291291    virtual void syncPosition(const FloatPoint& p) { m_position = p; }
    292    
     292
    293293    // Anchor point: (0, 0) is top left, (1, 1) is bottom right. The anchor point
    294294    // affects the origin of the transforms.
     
    303303    const FloatPoint& boundsOrigin() const { return m_boundsOrigin; }
    304304    virtual void setBoundsOrigin(const FloatPoint& origin) { m_boundsOrigin = origin; }
     305
     306    // For platforms that move underlying platform layers on a different thread for scrolling; just update the GraphicsLayer state.
     307    virtual void syncBoundsOrigin(const FloatPoint& origin) { m_boundsOrigin = origin; }
    305308
    306309    const TransformationMatrix& transform() const { return m_transform; }
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp

    r168227 r168338  
    11481148    FloatPoint boundsOrigin = m_boundsOrigin;
    11491149#if PLATFORM(IOS)
    1150     // UIKit may be changing layer bounds behind our back in overflow-scroll layers, so use the layer's origin.
    1151     boundsOrigin = m_layer->bounds().location();
     1150    // In WK1, UIKit may be changing layer bounds behind our back in overflow-scroll layers, so use the layer's origin.
     1151    if (m_layer->isPlatformCALayerMac())
     1152        boundsOrigin = m_layer->bounds().location();
    11521153#endif
    11531154    clipRectForChildren.move(boundsOrigin.x(), boundsOrigin.y());
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r168314 r168338  
    925925
    926926        if (m_owningLayer.isInUserScroll()) {
    927             // If scrolling is happening externally, we don't want to touch the layer bounds origin here because that will cause
    928             // jitter. Set a flag to ensure that we sync up later.
     927            // If scrolling is happening externally, we don't want to touch the layer bounds origin here because that will cause jitter.
     928            m_scrollingLayer->syncBoundsOrigin(FloatPoint(scrollOffset.width(), scrollOffset.height()));
    929929            m_owningLayer.setRequiresScrollBoundsOriginUpdate(true);
    930930        } else {
  • trunk/Source/WebKit2/ChangeLog

    r168333 r168338  
     12014-05-05  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [iOS WK2] Flickery scrolling inside overflow-scrolling: touch
     4        https://bugs.webkit.org/show_bug.cgi?id=132591
     5        <rdar://problem/16760466>
     6
     7        Reviewed by Tim Horton.
     8       
     9        Avoid triggering layer tree commits that touch the layer's boundsOrigin
     10        while the user is scrolling in the UI process.
     11       
     12        Fix the WKOverflowScrollViewDelegate to pass along an "inUserInteration"
     13        flag to the ScrollingTree to say that we're in the middle of a user interaction
     14        (and also to send a final non-interactive update). That gets passed along
     15        to the web process, and turned into "SyncScrollingLayerPosition" update.
     16        AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll() consults
     17        this, and uses it to set a flag on the ScrollableArea to say that the scroll
     18        is a user scroll.
     19       
     20        RenderLayerBacking then makes use of this (in existing code, shared with WK1)
     21        to avoid triggering layer bounds setting. Instead, it now just calls syncBoundsOrigin(),
     22        which updates the GraphicsLayer without touching platform layers. This is necessary
     23        so that GraphicsLayer geometry is up-to-date (used for tiled layer visibility
     24        computations).
     25       
     26        Finally, a hack in GraphicsLayerCA::computeVisibleRect() is conditionalized
     27        for WebKit1 by checking the type of platform layer.
     28
     29        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp:
     30        (WebKit::RemoteScrollingCoordinatorProxy::rootScrollingNodeID):
     31        (WebKit::RemoteScrollingCoordinatorProxy::isPointInNonFastScrollableRegion):
     32        (WebKit::RemoteScrollingCoordinatorProxy::viewportChangedViaDelegatedScrolling):
     33        (WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll):
     34        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
     35        * UIProcess/Scrolling/RemoteScrollingTree.cpp:
     36        (WebKit::RemoteScrollingTree::scrollingTreeNodeDidScroll):
     37        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h:
     38        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
     39        (-[WKOverflowScrollViewDelegate scrollViewDidScroll:]):
     40        (-[WKOverflowScrollViewDelegate scrollViewDidEndDragging:willDecelerate:]):
     41        (-[WKOverflowScrollViewDelegate scrollViewDidEndDecelerating:]):
     42        (WebKit::ScrollingTreeOverflowScrollingNodeIOS::scrollViewDidScroll):
     43        * WebProcess/Scrolling/RemoteScrollingCoordinator.h:
     44        * WebProcess/Scrolling/RemoteScrollingCoordinator.messages.in:
     45        * WebProcess/Scrolling/RemoteScrollingCoordinator.mm:
     46        (WebKit::RemoteScrollingCoordinator::scrollPositionChangedForNode):
     47
    1482014-05-05  Alexey Proskuryakov  <ap@apple.com>
    249
  • trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp

    r167262 r168338  
    5757}
    5858
    59 WebCore::ScrollingNodeID RemoteScrollingCoordinatorProxy::rootScrollingNodeID() const
     59ScrollingNodeID RemoteScrollingCoordinatorProxy::rootScrollingNodeID() const
    6060{
    6161    if (!m_scrollingTree->rootNode())
     
    140140}
    141141
    142 bool RemoteScrollingCoordinatorProxy::isPointInNonFastScrollableRegion(const WebCore::IntPoint& p) const
     142bool RemoteScrollingCoordinatorProxy::isPointInNonFastScrollableRegion(const IntPoint& p) const
    143143{
    144144    return m_scrollingTree->isPointInNonFastScrollableRegion(p);
    145145}
    146146
    147 void RemoteScrollingCoordinatorProxy::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const WebCore::FloatRect& viewportRect, double scale)
     147void RemoteScrollingCoordinatorProxy::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const FloatRect& viewportRect, double scale)
    148148{
    149149    m_scrollingTree->viewportChangedViaDelegatedScrolling(nodeID, viewportRect, scale);
     
    151151
    152152// This comes from the scrolling tree.
    153 void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID scrolledNodeID, const WebCore::FloatPoint& newScrollPosition)
     153void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& newScrollPosition, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
    154154{
    155155    // Scroll updates for the main frame are sent via WebPageProxy::updateVisibleContentRects()
     
    158158        return;
    159159
    160     m_webPageProxy.send(Messages::RemoteScrollingCoordinator::ScrollPositionChangedForNode(scrolledNodeID, newScrollPosition));
     160    m_webPageProxy.send(Messages::RemoteScrollingCoordinator::ScrollPositionChangedForNode(scrolledNodeID, newScrollPosition, scrollingLayerPositionAction));
    161161}
    162162
  • trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h

    r167262 r168338  
    5353   
    5454    // Inform the web process that the scroll position changed (called from the scrolling tree)
    55     void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& newScrollPosition);
     55    void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& newScrollPosition, WebCore::SetOrSyncScrollingLayerPosition);
    5656    void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool representsProgrammaticScroll);
    5757
  • trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.cpp

    r167262 r168338  
    7878#endif
    7979
    80 void RemoteScrollingTree::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, SetOrSyncScrollingLayerPosition)
     80void RemoteScrollingTree::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
    8181{
    82     m_scrollingCoordinatorProxy.scrollingTreeNodeDidScroll(nodeID, scrollPosition);
     82    m_scrollingCoordinatorProxy.scrollingTreeNodeDidScroll(nodeID, scrollPosition, scrollingLayerPositionAction);
    8383}
    8484
  • trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h

    r166531 r168338  
    4242    virtual ~ScrollingTreeOverflowScrollingNodeIOS();
    4343
    44     void scrollViewDidScroll(const WebCore::FloatPoint&);
     44    void scrollViewDidScroll(const WebCore::FloatPoint&, bool inUserInteration);
    4545
    4646private:
  • trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm

    r167891 r168338  
    5959- (void)scrollViewDidScroll:(UIScrollView *)scrollView
    6060{
    61     _scrollingTreeNode->scrollViewDidScroll(scrollView.contentOffset);
     61    _scrollingTreeNode->scrollViewDidScroll(scrollView.contentOffset, _inUserInteraction);
    6262}
    6363
     
    6969- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)willDecelerate
    7070{
    71     if (!willDecelerate)
     71    if (_inUserInteraction && !willDecelerate) {
    7272        _inUserInteraction = NO;
     73        _scrollingTreeNode->scrollViewDidScroll(scrollView.contentOffset, _inUserInteraction);
     74    }
    7375}
    7476
    7577- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    7678{
    77     _inUserInteraction = NO;
     79    if (_inUserInteraction) {
     80        _inUserInteraction = NO;
     81        _scrollingTreeNode->scrollViewDidScroll(scrollView.contentOffset, _inUserInteraction);
     82    }
    7883}
    7984
     
    146151}
    147152
    148 void ScrollingTreeOverflowScrollingNodeIOS::scrollViewDidScroll(const FloatPoint& scrollPosition)
     153void ScrollingTreeOverflowScrollingNodeIOS::scrollViewDidScroll(const FloatPoint& scrollPosition, bool inUserInteration)
    149154{
    150     scrollingTree().scrollPositionChangedViaDelegatedScrolling(scrollingNodeID(), scrollPosition);
     155    scrollingTree().scrollPositionChangedViaDelegatedScrolling(scrollingNodeID(), scrollPosition, inUserInteration);
    151156}
    152157
  • trunk/Source/WebKit2/WebProcess/Scrolling/RemoteScrollingCoordinator.h

    r162139 r168338  
    7272   
    7373    // Respond to UI process changes.
    74     void scrollPositionChangedForNode(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition);
     74    void scrollPositionChangedForNode(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool syncLayerPosition);
    7575
    7676    WebPage* m_webPage;
  • trunk/Source/WebKit2/WebProcess/Scrolling/RemoteScrollingCoordinator.messages.in

    r161529 r168338  
    2424
    2525messages -> RemoteScrollingCoordinator {
    26     ScrollPositionChangedForNode(uint64_t nodeID, WebCore::FloatPoint scrollPosition);
     26    ScrollPositionChangedForNode(uint64_t nodeID, WebCore::FloatPoint scrollPosition, bool syncLayerPosition);
    2727}
    2828
  • trunk/Source/WebKit2/WebProcess/Scrolling/RemoteScrollingCoordinator.mm

    r166531 r168338  
    9292
    9393// Notification from the UI process that we scrolled.
    94 void RemoteScrollingCoordinator::scrollPositionChangedForNode(ScrollingNodeID nodeID, const FloatPoint& scrollPosition)
     94void RemoteScrollingCoordinator::scrollPositionChangedForNode(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, bool syncLayerPosition)
    9595{
    96     scheduleUpdateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, false /* FIXME */, SyncScrollingLayerPosition);
     96    scheduleUpdateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, false /* FIXME */, syncLayerPosition ? SyncScrollingLayerPosition : SetScrollingLayerPosition);
    9797}
    9898
Note: See TracChangeset for help on using the changeset viewer.