Changeset 114651 in webkit


Ignore:
Timestamp:
Apr 19, 2012 11:03:46 AM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Source/WebCore: [chromium] Allow scrolling non-root layers in the compositor thread
https://bugs.webkit.org/show_bug.cgi?id=73350

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

This patch enables scrolling child layers in the compositor thread.
Scroll deltas are accumulated for each scrolled CCLayerImpl and
synchronized to the main thread.

If a layer has no room to scroll in a given direction, one of its
ancestor layers is scrolled instead if possible.

Added new webkit_unit_tests to verify scrolling behavior.

  • platform/graphics/chromium/ContentLayerChromium.cpp:

(WebCore::ContentLayerChromium::scrollBy):
(WebCore):

  • platform/graphics/chromium/ContentLayerChromium.h:

(ContentLayerDelegate):
(ContentLayerChromium):

  • platform/graphics/chromium/GraphicsLayerChromium.h:

(WebCore::GraphicsLayerChromium::didScroll):

  • platform/graphics/chromium/LayerChromium.cpp:

(WebCore::LayerChromium::setMaxScrollPosition):
(WebCore):
(WebCore::LayerChromium::pushPropertiesTo):

  • platform/graphics/chromium/LayerChromium.h:

(LayerChromium):
(WebCore::LayerChromium::maxScrollPosition):
(WebCore::LayerChromium::scrollable):
(WebCore::LayerChromium::scrollBy):

  • platform/graphics/chromium/cc/CCLayerImpl.cpp:

(WebCore::CCLayerImpl::findLayerInSubtree):
(WebCore):
(WebCore::CCLayerImpl::tryScroll):

  • platform/graphics/chromium/cc/CCLayerImpl.h:

(CCLayerImpl):

  • platform/graphics/chromium/cc/CCLayerTreeHost.cpp:

(WebCore::findLayerById):
(WebCore):
(WebCore::findFirstScrollableLayer):
(WebCore::CCLayerTreeHost::applyScrollAndScale):

  • platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:

(WebCore::CCLayerTreeHostImpl::CCLayerTreeHostImpl):
(WebCore::CCLayerTreeHostImpl::startPageScaleAnimation):
(WebCore::CCLayerTreeHostImpl::contentSize):
(WebCore):
(WebCore::CCLayerTreeHostImpl::calculateVisibleLayers):
(WebCore::CCLayerTreeHostImpl::prepareToDraw):
(WebCore::findRootScrollLayer):
(WebCore::findScrollLayerForContentLayer):
(WebCore::CCLayerTreeHostImpl::setRootLayer):
(WebCore::adjustScrollsForPageScaleChange):
(WebCore::applyPageScaleDeltaToScrollLayers):
(WebCore::CCLayerTreeHostImpl::setPageScaleFactorAndLimits):
(WebCore::CCLayerTreeHostImpl::setPageScaleDelta):
(WebCore::CCLayerTreeHostImpl::updateMaxScrollPosition):
(WebCore::CCLayerTreeHostImpl::scrollBegin):
(WebCore::CCLayerTreeHostImpl::scrollBy):
(WebCore::CCLayerTreeHostImpl::scrollEnd):
(WebCore::CCLayerTreeHostImpl::pinchGestureUpdate):
(WebCore::CCLayerTreeHostImpl::computePinchZoomDeltas):
(WebCore::CCLayerTreeHostImpl::makeScrollAndScaleSet):
(WebCore::collectScrollDeltas):
(WebCore::CCLayerTreeHostImpl::processScrollDeltas):
(WebCore::CCLayerTreeHostImpl::animatePageScale):

  • platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:

(WebCore::CCLayerTreeHostImpl::rootScrollLayer):
(CCLayerTreeHostImpl):
(LayerGeometry):

Source/WebKit/chromium: [chromium] Add tests for scrolling non-root layers in the compositor thread
https://bugs.webkit.org/show_bug.cgi?id=73350

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

  • src/WebContentLayerImpl.cpp:

(WebKit::WebContentLayerImpl::didScroll):
(WebKit):

  • src/WebContentLayerImpl.h:

(WebContentLayerImpl):

  • tests/CCLayerImplTest.cpp:

(WebCore::TEST):
(WebCore):

  • tests/CCLayerTreeHostImplTest.cpp:

(WebKitTests::CCLayerTreeHostImplTest::createScrollableLayer):
(CCLayerTreeHostImplTest):
(WebKitTests::CCLayerTreeHostImplTest::initializeLayerRendererAndDrawFrame):
(WebKitTests::TEST_F):
(WebKitTests):

  • tests/CCLayerTreeHostTest.cpp:

(WTF::TestOpacityChangeLayerDelegate::didScroll):
(WTF::MockContentLayerDelegate::paintContents):
(WTF::MockContentLayerDelegate::didScroll):
(CCLayerTreeHostTestScrollChildLayer):
(WTF::CCLayerTreeHostTestScrollChildLayer::CCLayerTreeHostTestScrollChildLayer):
(WTF::CCLayerTreeHostTestScrollChildLayer::beginTest):
(WTF::CCLayerTreeHostTestScrollChildLayer::applyScrollAndScale):
(WTF::CCLayerTreeHostTestScrollChildLayer::beginCommitOnCCThread):
(WTF::CCLayerTreeHostTestScrollChildLayer::drawLayersOnCCThread):
(WTF::CCLayerTreeHostTestScrollChildLayer::afterTest):
(WTF):
(WTF::TEST_F):

Location:
trunk/Source
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r114649 r114651  
     12012-04-19  Sami Kyostila  <skyostil@chromium.org>
     2
     3        [chromium] Allow scrolling non-root layers in the compositor thread
     4        https://bugs.webkit.org/show_bug.cgi?id=73350
     5
     6        Reviewed by James Robinson.
     7
     8        This patch enables scrolling child layers in the compositor thread.
     9        Scroll deltas are accumulated for each scrolled CCLayerImpl and
     10        synchronized to the main thread.
     11
     12        If a layer has no room to scroll in a given direction, one of its
     13        ancestor layers is scrolled instead if possible.
     14
     15        Added new webkit_unit_tests to verify scrolling behavior.
     16
     17        * platform/graphics/chromium/ContentLayerChromium.cpp:
     18        (WebCore::ContentLayerChromium::scrollBy):
     19        (WebCore):
     20        * platform/graphics/chromium/ContentLayerChromium.h:
     21        (ContentLayerDelegate):
     22        (ContentLayerChromium):
     23        * platform/graphics/chromium/GraphicsLayerChromium.h:
     24        (WebCore::GraphicsLayerChromium::didScroll):
     25        * platform/graphics/chromium/LayerChromium.cpp:
     26        (WebCore::LayerChromium::setMaxScrollPosition):
     27        (WebCore):
     28        (WebCore::LayerChromium::pushPropertiesTo):
     29        * platform/graphics/chromium/LayerChromium.h:
     30        (LayerChromium):
     31        (WebCore::LayerChromium::maxScrollPosition):
     32        (WebCore::LayerChromium::scrollable):
     33        (WebCore::LayerChromium::scrollBy):
     34        * platform/graphics/chromium/cc/CCLayerImpl.cpp:
     35        (WebCore::CCLayerImpl::findLayerInSubtree):
     36        (WebCore):
     37        (WebCore::CCLayerImpl::tryScroll):
     38        * platform/graphics/chromium/cc/CCLayerImpl.h:
     39        (CCLayerImpl):
     40        * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
     41        (WebCore::findLayerById):
     42        (WebCore):
     43        (WebCore::findFirstScrollableLayer):
     44        (WebCore::CCLayerTreeHost::applyScrollAndScale):
     45        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
     46        (WebCore::CCLayerTreeHostImpl::CCLayerTreeHostImpl):
     47        (WebCore::CCLayerTreeHostImpl::startPageScaleAnimation):
     48        (WebCore::CCLayerTreeHostImpl::contentSize):
     49        (WebCore):
     50        (WebCore::CCLayerTreeHostImpl::calculateVisibleLayers):
     51        (WebCore::CCLayerTreeHostImpl::prepareToDraw):
     52        (WebCore::findRootScrollLayer):
     53        (WebCore::findScrollLayerForContentLayer):
     54        (WebCore::CCLayerTreeHostImpl::setRootLayer):
     55        (WebCore::adjustScrollsForPageScaleChange):
     56        (WebCore::applyPageScaleDeltaToScrollLayers):
     57        (WebCore::CCLayerTreeHostImpl::setPageScaleFactorAndLimits):
     58        (WebCore::CCLayerTreeHostImpl::setPageScaleDelta):
     59        (WebCore::CCLayerTreeHostImpl::updateMaxScrollPosition):
     60        (WebCore::CCLayerTreeHostImpl::scrollBegin):
     61        (WebCore::CCLayerTreeHostImpl::scrollBy):
     62        (WebCore::CCLayerTreeHostImpl::scrollEnd):
     63        (WebCore::CCLayerTreeHostImpl::pinchGestureUpdate):
     64        (WebCore::CCLayerTreeHostImpl::computePinchZoomDeltas):
     65        (WebCore::CCLayerTreeHostImpl::makeScrollAndScaleSet):
     66        (WebCore::collectScrollDeltas):
     67        (WebCore::CCLayerTreeHostImpl::processScrollDeltas):
     68        (WebCore::CCLayerTreeHostImpl::animatePageScale):
     69        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
     70        (WebCore::CCLayerTreeHostImpl::rootScrollLayer):
     71        (CCLayerTreeHostImpl):
     72        (LayerGeometry):
     73
    1742012-04-19  Yury Semikhatsky  <yurys@chromium.org>
    275
  • trunk/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp

    r113809 r114651  
    146146}
    147147
     148void ContentLayerChromium::scrollBy(const IntSize& scrollDelta)
     149{
     150    setScrollPosition(scrollPosition() + scrollDelta);
     151    if (m_delegate)
     152        m_delegate->didScroll(scrollDelta);
     153}
     154
    148155}
    149156#endif // USE(ACCELERATED_COMPOSITING)
  • trunk/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h

    r113902 r114651  
    4747    virtual ~ContentLayerDelegate() { }
    4848    virtual void paintContents(GraphicsContext&, const IntRect& clip) = 0;
     49    virtual void didScroll(const IntSize&) = 0;
    4950};
    5051
     
    6465    virtual void setOpaque(bool) OVERRIDE;
    6566
     67    virtual void scrollBy(const IntSize&) OVERRIDE;
     68
    6669protected:
    6770    explicit ContentLayerChromium(ContentLayerDelegate*);
  • trunk/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h

    r113090 r114651  
    114114    // ContentLayerDelegate implementation.
    115115    virtual void paintContents(GraphicsContext&, const IntRect& clip);
     116    virtual void didScroll(const IntSize&) OVERRIDE { }
    116117
    117118    // CCLayerAnimationDelegate implementation.
  • trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp

    r114081 r114651  
    382382}
    383383
     384void LayerChromium::setMaxScrollPosition(const IntSize& maxScrollPosition)
     385{
     386    if (m_maxScrollPosition == maxScrollPosition)
     387        return;
     388    m_maxScrollPosition = maxScrollPosition;
     389    setNeedsCommit();
     390}
     391
    384392void LayerChromium::setScrollable(bool scrollable)
    385393{
     
    502510    layer->setPreserves3D(preserves3D());
    503511    layer->setScrollPosition(m_scrollPosition);
     512    layer->setMaxScrollPosition(m_maxScrollPosition);
    504513    layer->setSublayerTransform(m_sublayerTransform);
    505514    if (!transformIsAnimating())
  • trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.h

    r114284 r114651  
    142142    const IntPoint& scrollPosition() const { return m_scrollPosition; }
    143143
     144    void setMaxScrollPosition(const IntSize&);
     145    const IntSize& maxScrollPosition() const { return m_maxScrollPosition; }
     146
    144147    void setScrollable(bool);
     148    bool scrollable() const { return m_scrollable; }
    145149    void setShouldScrollOnMainThread(bool);
    146150    void setHaveWheelEventHandlers(bool);
     
    148152    void setNonFastScrollableRegion(const Region&);
    149153    void setNonFastScrollableRegionChanged() { m_nonFastScrollableRegionChanged = true; }
     154    virtual void scrollBy(const IntSize&) { }
    150155
    151156    void setDrawCheckerboardForMissingTiles(bool);
     
    304309    IntRect m_visibleLayerRect;
    305310    IntPoint m_scrollPosition;
     311    IntSize m_maxScrollPosition;
    306312    bool m_scrollable;
    307313    bool m_shouldScrollOnMainThread;
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp

    r114081 r114651  
    161161}
    162162
     163CCInputHandlerClient::ScrollStatus CCLayerImpl::tryScroll(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type) const
     164{
     165    if (shouldScrollOnMainThread()) {
     166        TRACE_EVENT("tryScroll Failed shouldScrollOnMainThread", this, 0);
     167        return CCInputHandlerClient::ScrollFailed;
     168    }
     169
     170    if (!screenSpaceTransform().isInvertible()) {
     171        TRACE_EVENT("tryScroll Failed nonInvertibleTransform", this, 0);
     172        return CCInputHandlerClient::ScrollIgnored;
     173    }
     174
     175    IntPoint contentPoint(screenSpaceTransform().inverse().mapPoint(viewportPoint));
     176    if (nonFastScrollableRegion().contains(contentPoint)) {
     177        TRACE_EVENT("tryScroll Failed nonFastScrollableRegion", this, 0);
     178        return CCInputHandlerClient::ScrollFailed;
     179    }
     180
     181    if (type == CCInputHandlerClient::Wheel && haveWheelEventHandlers()) {
     182        TRACE_EVENT("tryScroll Failed wheelEventHandlers", this, 0);
     183        return CCInputHandlerClient::ScrollFailed;
     184    }
     185
     186    if (!scrollable()) {
     187        TRACE_EVENT("tryScroll Ignored not scrollable", this, 0);
     188        return CCInputHandlerClient::ScrollIgnored;
     189    }
     190
     191    return CCInputHandlerClient::ScrollStarted;
     192}
     193
    163194const IntRect CCLayerImpl::getDrawRect() const
    164195{
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h

    r114284 r114651  
    3434#include "TextStream.h"
    3535#include "TransformationMatrix.h"
     36#include "cc/CCInputHandler.h"
    3637#include "cc/CCLayerAnimationController.h"
    3738#include "cc/CCRenderSurface.h"
     
    200201    void setDrawCheckerboardForMissingTiles(bool checkerboard) { m_drawCheckerboardForMissingTiles = checkerboard; }
    201202    bool drawCheckerboardForMissingTiles() const { return m_drawCheckerboardForMissingTiles; }
     203
     204    CCInputHandlerClient::ScrollStatus tryScroll(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType) const;
    202205
    203206    const IntRect& visibleLayerRect() const { return m_visibleLayerRect; }
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp

    r114601 r114651  
    572572}
    573573
     574static LayerChromium* findFirstScrollableLayer(LayerChromium* layer)
     575{
     576    if (!layer)
     577        return 0;
     578
     579    if (layer->scrollable())
     580        return layer;
     581
     582    for (size_t i = 0; i < layer->children().size(); ++i) {
     583        LayerChromium* found = findFirstScrollableLayer(layer->children()[i].get());
     584        if (found)
     585            return found;
     586    }
     587
     588    return 0;
     589}
     590
    574591void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info)
    575592{
    576     // FIXME: pushing scroll offsets to non-root layers not implemented
    577     if (!info.scrolls.size())
    578         return;
    579 
    580     ASSERT(info.scrolls.size() == 1);
    581     IntSize scrollDelta = info.scrolls[0].scrollDelta;
    582     m_client->applyScrollAndScale(scrollDelta, info.pageScaleDelta);
     593    if (!m_rootLayer)
     594        return;
     595
     596    LayerChromium* rootScrollLayer = findFirstScrollableLayer(m_rootLayer.get());
     597    IntSize rootScrollDelta;
     598
     599    for (size_t i = 0; i < info.scrolls.size(); ++i) {
     600        LayerChromium* layer = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayer.get(), info.scrolls[i].layerId);
     601        if (!layer)
     602            continue;
     603        if (layer == rootScrollLayer)
     604            rootScrollDelta += info.scrolls[i].scrollDelta;
     605        else
     606            layer->scrollBy(info.scrolls[i].scrollDelta);
     607    }
     608    if (!rootScrollDelta.isZero() || info.pageScaleDelta != 1)
     609        m_client->applyScrollAndScale(rootScrollDelta, info.pageScaleDelta);
    583610}
    584611
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h

    r113602 r114651  
    4747    template<typename LayerType> static bool renderSurfaceContributesToTarget(LayerType*, int targetSurfaceLayerID);
    4848
     49    // Returns a layer with the given id if one exists in the subtree starting
     50    // from the given root layer (including mask and replica layers).
     51    template<typename LayerType> static LayerType* findLayerInSubtree(LayerType* rootLayer, int layerId);
     52
    4953    struct ScrollUpdateInfo {
    5054        int layerId;
     
    7276}
    7377
     78template<typename LayerType>
     79LayerType* CCLayerTreeHostCommon::findLayerInSubtree(LayerType* rootLayer, int layerId)
     80{
     81    if (rootLayer->id() == layerId)
     82        return rootLayer;
     83
     84    if (rootLayer->maskLayer() && rootLayer->maskLayer()->id() == layerId)
     85        return rootLayer->maskLayer();
     86
     87    if (rootLayer->replicaLayer() && rootLayer->replicaLayer()->id() == layerId)
     88        return rootLayer->replicaLayer();
     89
     90    for (size_t i = 0; i < rootLayer->children().size(); ++i) {
     91        if (LayerType* found = findLayerInSubtree(rootLayer->children()[i].get(), layerId))
     92            return found;
     93    }
     94    return 0;
     95}
     96
    7497} // namespace WebCore
    7598
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp

    r114601 r114651  
    105105    , m_sourceFrameNumber(-1)
    106106    , m_frameNumber(0)
    107     , m_scrollLayerImpl(0)
     107    , m_rootScrollLayerImpl(0)
     108    , m_currentlyScrollingLayerImpl(0)
    108109    , m_settings(settings)
    109110    , m_visible(true)
     
    165166void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration)
    166167{
    167     if (!m_scrollLayerImpl)
    168         return;
    169 
    170     IntSize scrollTotal = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
     168    if (!m_rootScrollLayerImpl)
     169        return;
     170
     171    IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
    171172    scrollTotal.scale(m_pageScaleDelta);
    172173    float scaleTotal = m_pageScale * m_pageScaleDelta;
     
    358359    // TODO(aelias): Hardcoding the first child here is weird. Think of
    359360    // a cleaner way to get the contentBounds on the Impl side.
    360     if (!m_scrollLayerImpl || m_scrollLayerImpl->children().isEmpty())
     361    if (!m_rootScrollLayerImpl || m_rootScrollLayerImpl->children().isEmpty())
    361362        return IntSize();
    362     return m_scrollLayerImpl->children()[0]->contentBounds();
     363    return m_rootScrollLayerImpl->children()[0]->contentBounds();
    363364}
    364365
     
    369370    frame.renderPasses.clear();
    370371    frame.renderSurfaceLayerList.clear();
     372    m_mostRecentRenderSurfaceLayerList.clear();
    371373
    372374    if (!m_rootLayerImpl)
     
    375377    if (!calculateRenderPasses(frame.renderPasses, frame.renderSurfaceLayerList))
    376378        return false;
     379
     380    m_mostRecentRenderSurfaceLayerList = frame.renderSurfaceLayerList;
    377381
    378382    // If we return true, then we expect drawLayers() to be called before this function is called again.
     
    460464}
    461465
    462 static CCLayerImpl* findScrollLayer(CCLayerImpl* layer)
     466static CCLayerImpl* findRootScrollLayer(CCLayerImpl* layer)
    463467{
    464468    if (!layer)
     
    469473
    470474    for (size_t i = 0; i < layer->children().size(); ++i) {
    471         CCLayerImpl* found = findScrollLayer(layer->children()[i].get());
     475        CCLayerImpl* found = findRootScrollLayer(layer->children()[i].get());
    472476        if (found)
    473477            return found;
     
    477481}
    478482
     483// Content layers can be either directly scrollable or contained in an outer
     484// scrolling layer which applies the scroll transform. Given a content layer,
     485// this function returns the associated scroll layer if any.
     486static CCLayerImpl* findScrollLayerForContentLayer(CCLayerImpl* layerImpl)
     487{
     488    if (!layerImpl)
     489        return 0;
     490
     491    if (layerImpl->scrollable())
     492        return layerImpl;
     493
     494    if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable())
     495        return layerImpl->parent();
     496
     497    return 0;
     498}
     499
    479500void CCLayerTreeHostImpl::setRootLayer(PassOwnPtr<CCLayerImpl> layer)
    480501{
    481502    m_rootLayerImpl = layer;
    482 
    483     // FIXME: Currently, this only finds the first scrollable layer.
    484     m_scrollLayerImpl = findScrollLayer(m_rootLayerImpl.get());
     503    m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get());
     504
     505    if (!m_currentlyScrollingLayerImpl)
     506        return;
     507
     508    if (m_rootLayerImpl && CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_currentlyScrollingLayerImpl->id()))
     509        return;
     510
     511    m_currentlyScrollingLayerImpl = 0;
     512}
     513
     514PassOwnPtr<CCLayerImpl> CCLayerTreeHostImpl::releaseRootLayer()
     515{
     516    m_mostRecentRenderSurfaceLayerList.clear();
     517    return m_rootLayerImpl.release();
    485518}
    486519
     
    533566}
    534567
     568static void adjustScrollsForPageScaleChange(CCLayerImpl* layerImpl, float pageScaleChange)
     569{
     570    if (!layerImpl)
     571        return;
     572
     573    if (layerImpl->scrollable()) {
     574        // We need to convert impl-side scroll deltas to pageScale space.
     575        FloatSize scrollDelta = layerImpl->scrollDelta();
     576        scrollDelta.scale(pageScaleChange);
     577        layerImpl->setScrollDelta(scrollDelta);
     578    }
     579
     580    for (size_t i = 0; i < layerImpl->children().size(); ++i)
     581        adjustScrollsForPageScaleChange(layerImpl->children()[i].get(), pageScaleChange);
     582}
     583
     584static void applyPageScaleDeltaToScrollLayers(CCLayerImpl* layerImpl, float pageScaleDelta)
     585{
     586    if (!layerImpl)
     587        return;
     588
     589    if (layerImpl->scrollable())
     590        layerImpl->setPageScaleDelta(pageScaleDelta);
     591
     592    for (size_t i = 0; i < layerImpl->children().size(); ++i)
     593        applyPageScaleDeltaToScrollLayers(layerImpl->children()[i].get(), pageScaleDelta);
     594}
     595
    535596void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale)
    536597{
     
    547608    m_pageScale = pageScale;
    548609
    549     adjustScrollsForPageScaleChange(pageScaleChange);
     610    if (pageScaleChange != 1)
     611        adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
    550612
    551613    // Clamp delta to limits and refresh display matrix.
    552614    setPageScaleDelta(m_pageScaleDelta / m_sentPageScaleDelta);
    553615    m_sentPageScaleDelta = 1;
    554     applyPageScaleDeltaToScrollLayer();
    555 }
    556 
    557 void CCLayerTreeHostImpl::adjustScrollsForPageScaleChange(float pageScaleChange)
    558 {
    559     if (pageScaleChange == 1)
    560         return;
    561 
    562     // We also need to convert impl-side scroll deltas to pageScale space.
    563     if (m_scrollLayerImpl) {
    564         FloatSize scrollDelta = m_scrollLayerImpl->scrollDelta();
    565         scrollDelta.scale(pageScaleChange);
    566         m_scrollLayerImpl->setScrollDelta(scrollDelta);
    567     }
     616    applyPageScaleDeltaToScrollLayers(m_rootScrollLayerImpl, m_pageScaleDelta);
    568617}
    569618
     
    583632
    584633    updateMaxScrollPosition();
    585     applyPageScaleDeltaToScrollLayer();
    586 }
    587 
    588 void CCLayerTreeHostImpl::applyPageScaleDeltaToScrollLayer()
    589 {
    590     if (m_scrollLayerImpl)
    591         m_scrollLayerImpl->setPageScaleDelta(m_pageScaleDelta);
     634    applyPageScaleDeltaToScrollLayers(m_rootScrollLayerImpl, m_pageScaleDelta);
    592635}
    593636
    594637void CCLayerTreeHostImpl::updateMaxScrollPosition()
    595638{
    596     if (!m_scrollLayerImpl || !m_scrollLayerImpl->children().size())
     639    if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size())
    597640        return;
    598641
    599642    FloatSize viewBounds = m_viewportSize;
    600     if (CCLayerImpl* clipLayer = m_scrollLayerImpl->parent()) {
     643    if (CCLayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) {
    601644        if (clipLayer->masksToBounds())
    602645            viewBounds = clipLayer->bounds();
     
    609652    maxScroll.clampNegativeToZero();
    610653
    611     m_scrollLayerImpl->setMaxScrollPosition(maxScroll);
    612 
    613     // TODO(aelias): Also update sublayers.
     654    m_rootScrollLayerImpl->setMaxScrollPosition(maxScroll);
    614655}
    615656
     
    619660}
    620661
     662bool CCLayerTreeHostImpl::ensureMostRecentRenderSurfaceLayerList()
     663{
     664    if (m_mostRecentRenderSurfaceLayerList.size())
     665        return true;
     666
     667    // If we are called after setRootLayer() but before prepareToDraw(), we need to recalculate
     668    // the visible layers. The return value is ignored because we don't care about checkerboarding.
     669    CCRenderPassList passes;
     670    calculateRenderPasses(passes, m_mostRecentRenderSurfaceLayerList);
     671
     672    return m_mostRecentRenderSurfaceLayerList.size();
     673}
     674
    621675CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type)
    622676{
    623     // TODO: Check for scrollable sublayers.
    624     if (!m_scrollLayerImpl || !m_scrollLayerImpl->scrollable()) {
    625         TRACE_EVENT("scrollBegin Ignored no scrollable", this, 0);
     677    TRACE_EVENT("CCLayerTreeHostImpl::scrollBegin", this, 0);
     678
     679    m_currentlyScrollingLayerImpl = 0;
     680
     681    if (!ensureMostRecentRenderSurfaceLayerList())
    626682        return ScrollIgnored;
    627     }
    628 
    629     if (m_scrollLayerImpl->shouldScrollOnMainThread()) {
    630         TRACE_EVENT("scrollBegin Failed shouldScrollOnMainThread", this, 0);
    631         return ScrollFailed;
    632     }
    633 
    634     IntPoint scrollLayerContentPoint(m_scrollLayerImpl->screenSpaceTransform().inverse().mapPoint(viewportPoint));
    635     if (m_scrollLayerImpl->nonFastScrollableRegion().contains(scrollLayerContentPoint)) {
    636         TRACE_EVENT("scrollBegin Failed nonFastScrollableRegion", this, 0);
    637         return ScrollFailed;
    638     }
    639 
    640     if (type == CCInputHandlerClient::Wheel && m_scrollLayerImpl->haveWheelEventHandlers()) {
    641         TRACE_EVENT("scrollBegin Failed wheelEventHandlers", this, 0);
    642         return ScrollFailed;
    643     }
    644 
    645     return ScrollStarted;
     683
     684    // First find out which layer was hit by walking the saved list of visible layers from the most recent frame.
     685    CCLayerImpl* layerImpl = 0;
     686    typedef CCLayerIterator<CCLayerImpl, CCLayerList, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
     687    CCLayerIteratorType end = CCLayerIteratorType::end(&m_mostRecentRenderSurfaceLayerList);
     688    for (CCLayerIteratorType it = CCLayerIteratorType::begin(&m_mostRecentRenderSurfaceLayerList); it != end; ++it) {
     689        CCLayerImpl* renderSurfaceLayerImpl = (*it);
     690        if (!renderSurfaceLayerImpl->screenSpaceTransform().isInvertible())
     691            continue;
     692        IntPoint contentPoint(renderSurfaceLayerImpl->screenSpaceTransform().inverse().mapPoint(viewportPoint));
     693        if (!renderSurfaceLayerImpl->visibleLayerRect().contains(contentPoint))
     694            continue;
     695        layerImpl = renderSurfaceLayerImpl;
     696        break;
     697    }
     698
     699    // Walk up the hierarchy and look for a scrollable layer.
     700    CCLayerImpl* potentiallyScrollingLayerImpl = 0;
     701    for (; layerImpl; layerImpl = layerImpl->parent()) {
     702        // The content layer can also block attempts to scroll outside the main thread.
     703        if (layerImpl->tryScroll(viewportPoint, type) == ScrollFailed)
     704            return ScrollFailed;
     705
     706        CCLayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
     707        if (!scrollLayerImpl)
     708            continue;
     709
     710        ScrollStatus status = scrollLayerImpl->tryScroll(viewportPoint, type);
     711
     712        // If any layer wants to divert the scroll event to the main thread, abort.
     713        if (status == ScrollFailed)
     714            return ScrollFailed;
     715
     716        if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
     717            potentiallyScrollingLayerImpl = scrollLayerImpl;
     718    }
     719
     720    if (potentiallyScrollingLayerImpl) {
     721        m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl;
     722        return ScrollStarted;
     723    }
     724    return ScrollIgnored;
    646725}
    647726
     
    649728{
    650729    TRACE_EVENT("CCLayerTreeHostImpl::scrollBy", this, 0);
    651     if (!m_scrollLayerImpl)
    652         return;
    653 
    654     m_scrollLayerImpl->scrollBy(scrollDelta);
    655     m_client->setNeedsCommitOnImplThread();
    656     m_client->setNeedsRedrawOnImplThread();
     730    if (!m_currentlyScrollingLayerImpl)
     731        return;
     732
     733    FloatSize pendingDelta(scrollDelta);
     734    pendingDelta.scale(1 / m_pageScaleDelta);
     735
     736    for (CCLayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl && !pendingDelta.isZero(); layerImpl = layerImpl->parent()) {
     737        if (!layerImpl->scrollable())
     738            continue;
     739        FloatSize previousDelta(layerImpl->scrollDelta());
     740        layerImpl->scrollBy(pendingDelta);
     741        // Reset the pending scroll delta to zero if the layer was able to move along the requested
     742        // axis. This is to ensure it is possible to scroll exactly to the beginning or end of a
     743        // scroll area regardless of the scroll step. For diagonal scrolls this also avoids applying
     744        // the scroll on one axis to multiple layers.
     745        if (previousDelta.width() != layerImpl->scrollDelta().width())
     746            pendingDelta.setWidth(0);
     747        if (previousDelta.height() != layerImpl->scrollDelta().height())
     748            pendingDelta.setHeight(0);
     749    }
     750
     751    if (pendingDelta != scrollDelta) {
     752        m_client->setNeedsCommitOnImplThread();
     753        m_client->setNeedsRedrawOnImplThread();
     754    }
    657755}
    658756
    659757void CCLayerTreeHostImpl::scrollEnd()
    660758{
     759    m_currentlyScrollingLayerImpl = 0;
    661760}
    662761
     
    672771    TRACE_EVENT("CCLayerTreeHostImpl::pinchGestureUpdate", this, 0);
    673772
    674     if (!m_scrollLayerImpl)
     773    if (!m_rootScrollLayerImpl)
    675774        return;
    676775
     
    687786    m_previousPinchAnchor = anchor;
    688787
    689     m_scrollLayerImpl->scrollBy(roundedIntSize(move));
     788    m_rootScrollLayerImpl->scrollBy(roundedIntSize(move));
    690789    m_client->setNeedsCommitOnImplThread();
    691790    m_client->setNeedsRedrawOnImplThread();
     
    709808void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo)
    710809{
    711     if (!m_scrollLayerImpl)
     810    if (!m_rootScrollLayerImpl)
    712811        return;
    713812
     
    721820    // Compute where the scroll offset/page scale would be if fully pinch-zoomed
    722821    // out from the anchor point.
    723     IntSize scrollBegin = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
     822    IntSize scrollBegin = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
    724823    scrollBegin.scale(m_pageScaleDelta);
    725824    float scaleBegin = m_pageScale * m_pageScaleDelta;
     
    740839void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
    741840{
    742     if (!m_scrollLayerImpl)
     841    if (!m_rootScrollLayerImpl)
    743842        return;
    744843
    745844    CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
    746     scroll.layerId = m_scrollLayerImpl->id();
    747     scroll.scrollDelta = scrollOffset - toSize(m_scrollLayerImpl->scrollPosition());
     845    scroll.layerId = m_rootScrollLayerImpl->id();
     846    scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition());
    748847    scrollInfo->scrolls.append(scroll);
    749     m_scrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
     848    m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
    750849    m_sentPageScaleDelta = scrollInfo->pageScaleDelta = pageScale / m_pageScale;
    751850}
    752851
     852static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* layerImpl)
     853{
     854    if (!layerImpl)
     855        return;
     856
     857    if (!layerImpl->scrollDelta().isZero()) {
     858        IntSize scrollDelta = flooredIntSize(layerImpl->scrollDelta());
     859        CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
     860        scroll.layerId = layerImpl->id();
     861        scroll.scrollDelta = scrollDelta;
     862        scrollInfo->scrolls.append(scroll);
     863        layerImpl->setSentScrollDelta(scrollDelta);
     864    }
     865
     866    for (size_t i = 0; i < layerImpl->children().size(); ++i)
     867        collectScrollDeltas(scrollInfo, layerImpl->children()[i].get());
     868}
     869
    753870PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
    754871{
    755872    OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet());
    756     bool didMove = m_scrollLayerImpl && (!m_scrollLayerImpl->scrollDelta().isZero() || m_pageScaleDelta != 1.0f);
     873    collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get());
     874
     875    bool didMove = scrollInfo->scrolls.size() || m_pageScaleDelta != 1;
    757876    if (!didMove || m_pinchGestureActive || m_pageScaleAnimation) {
    758877        m_sentPageScaleDelta = scrollInfo->pageScaleDelta = 1;
     
    766885    m_sentPageScaleDelta = scrollInfo->pageScaleDelta = m_pageScaleDelta;
    767886
    768     // FIXME: track scrolls from layers other than the root
    769     CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
    770     scroll.layerId = m_scrollLayerImpl->id();
    771     scroll.scrollDelta = flooredIntSize(m_scrollLayerImpl->scrollDelta());
    772     scrollInfo->scrolls.append(scroll);
    773 
    774     m_scrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
    775 
    776887    return scrollInfo.release();
    777888}
     
    788899void CCLayerTreeHostImpl::animatePageScale(double monotonicTime)
    789900{
    790     if (!m_pageScaleAnimation || !m_scrollLayerImpl)
    791         return;
    792 
    793     IntSize scrollTotal = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
     901    if (!m_pageScaleAnimation || !m_rootScrollLayerImpl)
     902        return;
     903
     904    IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
    794905
    795906    setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScale);
    796907    IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
    797908    nextScroll.scale(1 / m_pageScaleDelta);
    798     m_scrollLayerImpl->scrollBy(nextScroll - scrollTotal);
     909    m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal);
    799910    m_client->setNeedsRedrawOnImplThread();
    800911
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h

    r114218 r114651  
    123123
    124124    void setRootLayer(PassOwnPtr<CCLayerImpl>);
    125     PassOwnPtr<CCLayerImpl> releaseRootLayer() { return m_rootLayerImpl.release(); }
     125    PassOwnPtr<CCLayerImpl> releaseRootLayer();
    126126    CCLayerImpl* rootLayer() { return m_rootLayerImpl.get(); }
    127127
    128     CCLayerImpl* scrollLayer() const { return m_scrollLayerImpl; }
     128    CCLayerImpl* rootScrollLayer() const { return m_rootScrollLayerImpl; }
    129129
    130130    bool visible() const { return m_visible; }
     
    170170
    171171    void setPageScaleDelta(float);
    172     void applyPageScaleDeltaToScrollLayer();
    173     void adjustScrollsForPageScaleChange(float);
    174172    void updateMaxScrollPosition();
    175173    void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList);
     
    180178    void sendDidLoseContextRecursive(CCLayerImpl*);
    181179    void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl*);
     180    bool ensureMostRecentRenderSurfaceLayerList();
    182181
    183182    void dumpRenderSurfaces(TextStream&, int indent, const CCLayerImpl*) const;
     
    185184    OwnPtr<LayerRendererChromium> m_layerRenderer;
    186185    OwnPtr<CCLayerImpl> m_rootLayerImpl;
    187     CCLayerImpl* m_scrollLayerImpl;
     186    CCLayerImpl* m_rootScrollLayerImpl;
     187    CCLayerImpl* m_currentlyScrollingLayerImpl;
    188188    CCSettings m_settings;
    189189    IntSize m_viewportSize;
     
    212212    CCLayerSorter m_layerSorter;
    213213
     214    // List of visible layers in the most recent frame. Used for input event hit testing.
     215    CCLayerList m_mostRecentRenderSurfaceLayerList;
     216
    214217    FloatRect m_rootDamageRect;
    215218};
  • trunk/Source/WebKit/chromium/ChangeLog

    r114647 r114651  
     12012-04-19  Sami Kyostila  <skyostil@chromium.org>
     2
     3        [chromium] Add tests for scrolling non-root layers in the compositor thread
     4        https://bugs.webkit.org/show_bug.cgi?id=73350
     5
     6        Reviewed by James Robinson.
     7
     8        * src/WebContentLayerImpl.cpp:
     9        (WebKit::WebContentLayerImpl::didScroll):
     10        (WebKit):
     11        * src/WebContentLayerImpl.h:
     12        (WebContentLayerImpl):
     13        * tests/CCLayerImplTest.cpp:
     14        (WebCore::TEST):
     15        (WebCore):
     16        * tests/CCLayerTreeHostImplTest.cpp:
     17        (WebKitTests::CCLayerTreeHostImplTest::createScrollableLayer):
     18        (CCLayerTreeHostImplTest):
     19        (WebKitTests::CCLayerTreeHostImplTest::initializeLayerRendererAndDrawFrame):
     20        (WebKitTests::TEST_F):
     21        (WebKitTests):
     22        * tests/CCLayerTreeHostTest.cpp:
     23        (WTF::TestOpacityChangeLayerDelegate::didScroll):
     24        (WTF::MockContentLayerDelegate::paintContents):
     25        (WTF::MockContentLayerDelegate::didScroll):
     26        (CCLayerTreeHostTestScrollChildLayer):
     27        (WTF::CCLayerTreeHostTestScrollChildLayer::CCLayerTreeHostTestScrollChildLayer):
     28        (WTF::CCLayerTreeHostTestScrollChildLayer::beginTest):
     29        (WTF::CCLayerTreeHostTestScrollChildLayer::applyScrollAndScale):
     30        (WTF::CCLayerTreeHostTestScrollChildLayer::beginCommitOnCCThread):
     31        (WTF::CCLayerTreeHostTestScrollChildLayer::drawLayersOnCCThread):
     32        (WTF::CCLayerTreeHostTestScrollChildLayer::afterTest):
     33        (WTF):
     34        (WTF::TEST_F):
     35
    1362012-04-19  Alec Flett  <alecflett@chromium.org>
    237
  • trunk/Source/WebKit/chromium/src/WebContentLayerImpl.cpp

    r105460 r114651  
    7373}
    7474
     75void WebContentLayerImpl::didScroll(const WebCore::IntSize&)
     76{
     77}
     78
    7579} // namespace WebKit
  • trunk/Source/WebKit/chromium/src/WebContentLayerImpl.h

    r105460 r114651  
    4545    // ContentLayerDelegate implementation.
    4646    virtual void paintContents(WebCore::GraphicsContext&, const WebCore::IntRect& clip);
     47    virtual void didScroll(const WebCore::IntSize&);
    4748
    4849    WebContentLayerClient* m_contentClient;
  • trunk/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp

    r113947 r114651  
    13261326}
    13271327
     1328TEST(CCLayerTreeHostCommonTest, verifySubtreeSearch)
     1329{
     1330    RefPtr<LayerChromium> root = LayerChromium::create();
     1331    RefPtr<LayerChromium> child = LayerChromium::create();
     1332    RefPtr<LayerChromium> grandChild = LayerChromium::create();
     1333    RefPtr<LayerChromium> maskLayer = LayerChromium::create();
     1334    RefPtr<LayerChromium> replicaLayer = LayerChromium::create();
     1335
     1336    grandChild->setReplicaLayer(replicaLayer.get());
     1337    child->addChild(grandChild.get());
     1338    child->setMaskLayer(maskLayer.get());
     1339    root->addChild(child.get());
     1340
     1341    int nonexistentId = -1;
     1342    EXPECT_EQ(root, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), root->id()));
     1343    EXPECT_EQ(child, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), child->id()));
     1344    EXPECT_EQ(grandChild, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), grandChild->id()));
     1345    EXPECT_EQ(maskLayer, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), maskLayer->id()));
     1346    EXPECT_EQ(replicaLayer, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), replicaLayer->id()));
     1347    EXPECT_EQ(0, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), nonexistentId));
     1348}
     1349
    13281350// FIXME:
    13291351// continue working on https://bugs.webkit.org/show_bug.cgi?id=68942
  • trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp

    r114473 r114651  
    9898    }
    9999
     100    static PassOwnPtr<CCLayerImpl> createScrollableLayer(int id, const FloatPoint& position, const IntSize& size)
     101    {
     102        OwnPtr<CCLayerImpl> layer = CCLayerImpl::create(id);
     103        layer->setScrollable(true);
     104        layer->setDrawsContent(true);
     105        layer->setPosition(position);
     106        layer->setBounds(size);
     107        layer->setMaxScrollPosition(IntSize(size.width() * 2, size.height() * 2));
     108        return layer.release();
     109    }
     110
     111    void initializeLayerRendererAndDrawFrame()
     112    {
     113        m_hostImpl->initializeLayerRenderer(createContext());
     114        CCLayerTreeHostImpl::FrameData frame;
     115        EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
     116        m_hostImpl->drawLayers(frame);
     117    }
     118
    100119protected:
    101120    PassRefPtr<GraphicsContext3D> createContext()
     
    181200    {
    182201        OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
     202        root->setVisibleLayerRect(IntRect(0, 0, 100, 100));
    183203        root->setScrollable(true);
    184204        root->setScrollPosition(IntPoint(0, 0));
    185205        root->setMaxScrollPosition(IntSize(100, 100));
    186206        m_hostImpl->setRootLayer(root.release());
     207        initializeLayerRendererAndDrawFrame();
    187208    }
    188209
     
    198219    {
    199220        OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
     221        root->setVisibleLayerRect(IntRect(0, 0, 100, 100));
    200222        root->setScrollable(true);
    201223        root->setScrollPosition(IntPoint(0, 0));
    202224        root->setMaxScrollPosition(IntSize(100, 100));
    203225        m_hostImpl->setRootLayer(root.release());
     226        initializeLayerRendererAndDrawFrame();
    204227    }
    205228    CCLayerImpl* root = m_hostImpl->rootLayer();
     
    216239{
    217240    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
     241    root->setVisibleLayerRect(IntRect(0, 0, 100, 100));
    218242    root->setScrollable(true);
    219243    root->setScrollPosition(IntPoint(0, 0));
     
    221245    root->setShouldScrollOnMainThread(true);
    222246    m_hostImpl->setRootLayer(root.release());
     247    initializeLayerRendererAndDrawFrame();
     248
    223249    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
    224250    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollFailed);
     
    228254{
    229255    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
     256    root->setVisibleLayerRect(IntRect(0, 0, 100, 100));
    230257    root->setScrollable(true);
    231258    root->setScrollPosition(IntPoint(0, 0));
     
    233260    root->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
    234261    m_hostImpl->setRootLayer(root.release());
     262    initializeLayerRendererAndDrawFrame();
     263
    235264    // All scroll types inside the non-fast scrollable region should fail.
    236265    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
     
    248277TEST_F(CCLayerTreeHostImplTest, nonFastScrollableRegionWithOffset)
    249278{
    250     m_hostImpl->initializeLayerRenderer(createContext());
    251 
    252279    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
     280    root->setBounds(IntSize(1, 1));
     281    root->setVisibleLayerRect(IntRect(0, 0, 100, 100));
    253282    root->setScrollable(true);
    254283    root->setScrollPosition(IntPoint(0, 0));
     
    257286    root->setPosition(FloatPoint(-25, 0));
    258287    m_hostImpl->setRootLayer(root.release());
    259     CCLayerTreeHostImpl::FrameData frame;
    260     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
    261     m_hostImpl->drawLayers(frame); // Update draw transforms so we can correctly map points into layer space.
     288    initializeLayerRendererAndDrawFrame();
    262289
    263290    // This point would fall into the non-fast scrollable region except that we've moved the layer down by 25 pixels.
     
    274301    setupScrollAndContentsLayers(IntSize(100, 100));
    275302    m_hostImpl->setViewportSize(IntSize(50, 50));
    276 
    277     CCLayerImpl* scrollLayer = m_hostImpl->scrollLayer();
     303    initializeLayerRendererAndDrawFrame();
     304
     305    CCLayerImpl* scrollLayer = m_hostImpl->rootScrollLayer();
    278306    ASSERT(scrollLayer);
    279307
     
    354382    setupScrollAndContentsLayers(IntSize(100, 100));
    355383    m_hostImpl->setViewportSize(IntSize(50, 50));
    356 
    357     CCLayerImpl* scrollLayer = m_hostImpl->scrollLayer();
     384    initializeLayerRendererAndDrawFrame();
     385
     386    CCLayerImpl* scrollLayer = m_hostImpl->rootScrollLayer();
    358387    ASSERT(scrollLayer);
    359388
     
    560589    EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
    561590    m_hostImpl->drawLayers(frame);
     591}
     592
     593TEST_F(CCLayerTreeHostImplTest, scrollRootIgnored)
     594{
     595    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
     596    root->setScrollable(false);
     597    m_hostImpl->setRootLayer(root.release());
     598    initializeLayerRendererAndDrawFrame();
     599
     600    // Scroll event is ignored because layer is not scrollable.
     601    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollIgnored);
     602    EXPECT_FALSE(m_didRequestRedraw);
     603    EXPECT_FALSE(m_didRequestCommit);
     604}
     605
     606TEST_F(CCLayerTreeHostImplTest, scrollNonCompositedRoot)
     607{
     608    // Test the configuration where a non-composited root layer is embedded in a
     609    // scrollable outer layer.
     610    IntSize surfaceSize(10, 10);
     611
     612    OwnPtr<CCLayerImpl> contentLayer = CCLayerImpl::create(1);
     613    contentLayer->setIsNonCompositedContent(true);
     614    contentLayer->setDrawsContent(true);
     615    contentLayer->setPosition(IntPoint(5, 5));
     616    contentLayer->setBounds(surfaceSize);
     617    contentLayer->setContentBounds(IntSize(surfaceSize.width() * 2, surfaceSize.height() * 2));
     618
     619    OwnPtr<CCLayerImpl> scrollLayer = CCLayerImpl::create(0);
     620    scrollLayer->setScrollable(true);
     621    scrollLayer->addChild(contentLayer.release());
     622
     623    m_hostImpl->setRootLayer(scrollLayer.release());
     624    m_hostImpl->setViewportSize(surfaceSize);
     625    initializeLayerRendererAndDrawFrame();
     626
     627    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
     628    m_hostImpl->scrollBy(IntSize(0, 10));
     629    m_hostImpl->scrollEnd();
     630    EXPECT_TRUE(m_didRequestRedraw);
     631    EXPECT_TRUE(m_didRequestCommit);
     632}
     633
     634TEST_F(CCLayerTreeHostImplTest, scrollChildCallsCommitAndRedraw)
     635{
     636    IntSize surfaceSize(10, 10);
     637    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
     638    root->addChild(createScrollableLayer(1, FloatPoint(5, 5), surfaceSize));
     639    m_hostImpl->setRootLayer(root.release());
     640    m_hostImpl->setViewportSize(surfaceSize);
     641    initializeLayerRendererAndDrawFrame();
     642
     643    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
     644    m_hostImpl->scrollBy(IntSize(0, 10));
     645    m_hostImpl->scrollEnd();
     646    EXPECT_TRUE(m_didRequestRedraw);
     647    EXPECT_TRUE(m_didRequestCommit);
     648}
     649
     650TEST_F(CCLayerTreeHostImplTest, scrollMissesChild)
     651{
     652    IntSize surfaceSize(10, 10);
     653    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
     654    root->addChild(createScrollableLayer(1, FloatPoint(5, 5), surfaceSize));
     655    m_hostImpl->setRootLayer(root.release());
     656    m_hostImpl->setViewportSize(surfaceSize);
     657    initializeLayerRendererAndDrawFrame();
     658
     659    // Scroll event is ignored because the input coordinate is outside the layer boundaries.
     660    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(15, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollIgnored);
     661    EXPECT_FALSE(m_didRequestRedraw);
     662    EXPECT_FALSE(m_didRequestCommit);
     663}
     664
     665TEST_F(CCLayerTreeHostImplTest, scrollMissesBackfacingChild)
     666{
     667    IntSize surfaceSize(10, 10);
     668    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
     669    OwnPtr<CCLayerImpl> child = createScrollableLayer(1, FloatPoint(5, 5), surfaceSize);
     670    m_hostImpl->setViewportSize(surfaceSize);
     671
     672    TransformationMatrix matrix;
     673    matrix.rotate3d(180, 0, 0);
     674    child->setTransform(matrix);
     675    child->setDoubleSided(false);
     676
     677    root->addChild(child.release());
     678    m_hostImpl->setRootLayer(root.release());
     679    initializeLayerRendererAndDrawFrame();
     680
     681    // Scroll event is ignored because the scrollable layer is not facing the viewer and there is
     682    // nothing scrollable behind it.
     683    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollIgnored);
     684    EXPECT_FALSE(m_didRequestRedraw);
     685    EXPECT_FALSE(m_didRequestCommit);
     686}
     687
     688TEST_F(CCLayerTreeHostImplTest, scrollBlockedByContentLayer)
     689{
     690    IntSize surfaceSize(10, 10);
     691    OwnPtr<CCLayerImpl> contentLayer = createScrollableLayer(0, FloatPoint(5, 5), surfaceSize);
     692    contentLayer->setShouldScrollOnMainThread(true);
     693    contentLayer->setScrollable(false);
     694
     695    OwnPtr<CCLayerImpl> scrollLayer = createScrollableLayer(1, FloatPoint(5, 5), surfaceSize);
     696    scrollLayer->addChild(contentLayer.release());
     697
     698    m_hostImpl->setRootLayer(scrollLayer.release());
     699    m_hostImpl->setViewportSize(surfaceSize);
     700    initializeLayerRendererAndDrawFrame();
     701
     702    // Scrolling fails because the content layer is asking to be scrolled on the main thread.
     703    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
     704}
     705
     706TEST_F(CCLayerTreeHostImplTest, scrollRootAndChangePageScaleOnMainThread)
     707{
     708    IntSize surfaceSize(10, 10);
     709    float pageScale = 2;
     710    OwnPtr<CCLayerImpl> root = createScrollableLayer(0, FloatPoint(5, 5), surfaceSize);
     711    m_hostImpl->setRootLayer(root.release());
     712    m_hostImpl->setViewportSize(surfaceSize);
     713    initializeLayerRendererAndDrawFrame();
     714
     715    IntSize scrollDelta(0, 10);
     716    IntSize expectedScrollDelta(scrollDelta);
     717    IntSize expectedMaxScroll(m_hostImpl->rootLayer()->maxScrollPosition());
     718    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
     719    m_hostImpl->scrollBy(scrollDelta);
     720    m_hostImpl->scrollEnd();
     721
     722    // Set new page scale from main thread.
     723    m_hostImpl->setPageScaleFactorAndLimits(pageScale, pageScale, pageScale);
     724
     725    // The scale should apply to the scroll delta.
     726    expectedScrollDelta.scale(pageScale);
     727    OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
     728    expectContains(*scrollInfo.get(), 0, expectedScrollDelta);
     729
     730    // The scroll range should also have been updated.
     731    EXPECT_EQ(m_hostImpl->rootLayer()->maxScrollPosition(), expectedMaxScroll);
     732
     733    // The page scale delta remains constant because the impl thread did not scale.
     734    EXPECT_EQ(m_hostImpl->rootLayer()->pageScaleDelta(), 1);
     735}
     736
     737TEST_F(CCLayerTreeHostImplTest, scrollRootAndChangePageScaleOnImplThread)
     738{
     739    IntSize surfaceSize(10, 10);
     740    float pageScale = 2;
     741    OwnPtr<CCLayerImpl> root = createScrollableLayer(0, FloatPoint(5, 5), surfaceSize);
     742    m_hostImpl->setRootLayer(root.release());
     743    m_hostImpl->setViewportSize(surfaceSize);
     744    m_hostImpl->setPageScaleFactorAndLimits(1, 1, pageScale);
     745    initializeLayerRendererAndDrawFrame();
     746
     747    IntSize scrollDelta(0, 10);
     748    IntSize expectedScrollDelta(scrollDelta);
     749    IntSize expectedMaxScroll(m_hostImpl->rootLayer()->maxScrollPosition());
     750    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
     751    m_hostImpl->scrollBy(scrollDelta);
     752    m_hostImpl->scrollEnd();
     753
     754    // Set new page scale on impl thread by pinching.
     755    m_hostImpl->pinchGestureBegin();
     756    m_hostImpl->pinchGestureUpdate(pageScale, IntPoint());
     757    m_hostImpl->pinchGestureEnd();
     758
     759    // The scroll delta is not scaled because the main thread did not scale.
     760    OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
     761    expectContains(*scrollInfo.get(), 0, expectedScrollDelta);
     762
     763    // The scroll range should also have been updated.
     764    EXPECT_EQ(m_hostImpl->rootLayer()->maxScrollPosition(), expectedMaxScroll);
     765
     766    // The page scale delta should match the new scale on the impl side.
     767    EXPECT_EQ(m_hostImpl->rootLayer()->pageScaleDelta(), pageScale);
     768}
     769
     770TEST_F(CCLayerTreeHostImplTest, scrollChildAndChangePageScaleOnMainThread)
     771{
     772    IntSize surfaceSize(10, 10);
     773    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
     774    // Also mark the root scrollable so it becomes the root scroll layer.
     775    root->setScrollable(true);
     776    root->addChild(createScrollableLayer(1, FloatPoint(5, 5), surfaceSize));
     777    m_hostImpl->setRootLayer(root.release());
     778    m_hostImpl->setViewportSize(surfaceSize);
     779    initializeLayerRendererAndDrawFrame();
     780
     781    CCLayerImpl* child = m_hostImpl->rootLayer()->children()[0].get();
     782
     783    IntSize scrollDelta(0, 10);
     784    IntSize expectedScrollDelta(scrollDelta);
     785    IntSize expectedMaxScroll(child->maxScrollPosition());
     786    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
     787    m_hostImpl->scrollBy(scrollDelta);
     788    m_hostImpl->scrollEnd();
     789
     790    float pageScale = 2;
     791    m_hostImpl->setPageScaleFactorAndLimits(pageScale, 1, pageScale);
     792
     793    // The scale should apply to the scroll delta.
     794    expectedScrollDelta.scale(pageScale);
     795    OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
     796    expectContains(*scrollInfo.get(), 1, expectedScrollDelta);
     797
     798    // The scroll range should not have changed.
     799    EXPECT_EQ(child->maxScrollPosition(), expectedMaxScroll);
     800
     801    // The page scale delta remains constant because the impl thread did not scale.
     802    EXPECT_EQ(child->pageScaleDelta(), 1);
     803}
     804
     805TEST_F(CCLayerTreeHostImplTest, scrollChildBeyondLimit)
     806{
     807    // Scroll a child layer beyond its maximum scroll range and make sure the
     808    // parent layer is scrolled on the axis on which the child was unable to
     809    // scroll.
     810    IntSize surfaceSize(10, 10);
     811    OwnPtr<CCLayerImpl> root = createScrollableLayer(0, FloatPoint(5, 5), surfaceSize);
     812
     813    OwnPtr<CCLayerImpl> grandChild = createScrollableLayer(2, FloatPoint(5, 5), surfaceSize);
     814    grandChild->setScrollPosition(IntPoint(0, 5));
     815
     816    OwnPtr<CCLayerImpl> child = createScrollableLayer(1, FloatPoint(5, 5), surfaceSize);
     817    child->setScrollPosition(IntPoint(3, 0));
     818    child->addChild(grandChild.release());
     819
     820    root->addChild(child.release());
     821    m_hostImpl->setRootLayer(root.release());
     822    m_hostImpl->setViewportSize(surfaceSize);
     823    initializeLayerRendererAndDrawFrame();
     824    {
     825        IntSize scrollDelta(-3, -7);
     826        EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
     827        m_hostImpl->scrollBy(scrollDelta);
     828        m_hostImpl->scrollEnd();
     829
     830        OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
     831
     832        // The grand child should have scrolled up to its limit.
     833        CCLayerImpl* child = m_hostImpl->rootLayer()->children()[0].get();
     834        CCLayerImpl* grandChild = child->children()[0].get();
     835        expectContains(*scrollInfo.get(), grandChild->id(), IntSize(0, -5));
     836
     837        // The child should have only scrolled on the other axis.
     838        expectContains(*scrollInfo.get(), child->id(), IntSize(-3, 0));
     839    }
     840}
     841
     842TEST_F(CCLayerTreeHostImplTest, scrollBeforeRedraw)
     843{
     844    IntSize surfaceSize(10, 10);
     845    m_hostImpl->setRootLayer(createScrollableLayer(0, FloatPoint(5, 5), surfaceSize));
     846    m_hostImpl->setViewportSize(surfaceSize);
     847
     848    // Draw one frame and then immediately rebuild the layer tree to mimic a tree synchronization.
     849    initializeLayerRendererAndDrawFrame();
     850    m_hostImpl->releaseRootLayer();
     851    m_hostImpl->setRootLayer(createScrollableLayer(0, FloatPoint(5, 5), surfaceSize));
     852
     853    // Scrolling should still work even though we did not draw yet.
     854    EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
    562855}
    563856
  • trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp

    r114203 r114651  
    14181418
    14191419    virtual bool preserves3D() { return false; }
     1420    virtual void didScroll(const IntSize&) { }
    14201421
    14211422private:
     
    15521553    bool drawsContent() const { return true; }
    15531554    MOCK_CONST_METHOD0(preserves3D, bool());
    1554     void paintContents(GraphicsContext&, const IntRect&) { }
     1555    virtual void paintContents(GraphicsContext&, const IntRect&) { }
     1556    virtual void didScroll(const IntSize&) { }
    15551557    void notifySyncRequired() { }
    15561558};
     
    23142316}
    23152317
     2318class CCLayerTreeHostTestScrollChildLayer : public CCLayerTreeHostTest {
     2319public:
     2320    CCLayerTreeHostTestScrollChildLayer()
     2321        : m_scrollAmount(2, 1)
     2322    {
     2323    }
     2324
     2325    virtual void beginTest()
     2326    {
     2327        m_layerTreeHost->setViewportSize(IntSize(10, 10));
     2328        m_rootScrollLayer = ContentLayerChromium::create(&m_mockDelegate);
     2329        m_rootScrollLayer->setBounds(IntSize(10, 10));
     2330        m_rootScrollLayer->setIsDrawable(true);
     2331        m_rootScrollLayer->setScrollable(true);
     2332        m_rootScrollLayer->setMaxScrollPosition(IntSize(100, 100));
     2333        m_layerTreeHost->rootLayer()->addChild(m_rootScrollLayer);
     2334        m_childLayer = ContentLayerChromium::create(&m_mockDelegate);
     2335        m_childLayer->setBounds(IntSize(50, 50));
     2336        m_childLayer->setIsDrawable(true);
     2337        m_childLayer->setScrollable(true);
     2338        m_childLayer->setMaxScrollPosition(IntSize(100, 100));
     2339        m_rootScrollLayer->addChild(m_childLayer);
     2340        postSetNeedsCommitToMainThread();
     2341    }
     2342
     2343    virtual void applyScrollAndScale(const IntSize& scrollDelta, float)
     2344    {
     2345        IntPoint position = m_rootScrollLayer->scrollPosition();
     2346        m_rootScrollLayer->setScrollPosition(position + scrollDelta);
     2347    }
     2348
     2349    virtual void beginCommitOnCCThread(CCLayerTreeHostImpl* impl)
     2350    {
     2351        EXPECT_EQ(m_rootScrollLayer->scrollPosition(), IntPoint());
     2352        if (!m_layerTreeHost->frameNumber())
     2353            EXPECT_EQ(m_childLayer->scrollPosition(), IntPoint());
     2354        else
     2355            EXPECT_EQ(m_childLayer->scrollPosition(), IntPoint() + m_scrollAmount);
     2356    }
     2357
     2358    virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
     2359    {
     2360        if (impl->frameNumber() == 1) {
     2361            EXPECT_EQ(impl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
     2362            impl->scrollBy(m_scrollAmount);
     2363            impl->scrollEnd();
     2364        } else if (impl->frameNumber() == 2)
     2365            endTest();
     2366    }
     2367
     2368    virtual void afterTest()
     2369    {
     2370    }
     2371
     2372private:
     2373    const IntSize m_scrollAmount;
     2374    MockContentLayerDelegate m_mockDelegate;
     2375    RefPtr<LayerChromium> m_childLayer;
     2376    RefPtr<LayerChromium> m_rootScrollLayer;
     2377};
     2378
     2379TEST_F(CCLayerTreeHostTestScrollChildLayer, runMultiThread)
     2380{
     2381    runTest(true);
     2382}
     2383
    23162384} // namespace
Note: See TracChangeset for help on using the changeset viewer.