Changeset 137646 in webkit


Ignore:
Timestamp:
Dec 13, 2012 1:37:25 PM (11 years ago)
Author:
vollick@chromium.org
Message:

Source/WebCore: [chromium] Automatically use composited scrolling
https://bugs.webkit.org/show_bug.cgi?id=94743

Reviewed by Adrienne Walker.

We currently use the composited scrolling facilities provided by
wkb.ug/91117 if the overflow scroll block element is styled with
-webkit-overflow-scrolling: touch. Ideally, we could automatically
opt into composited scrolling if it is safe to do so. This can affect
antialiasing, so it is important that automatically opting in is only
enabled via a setting.

The way I determine if it is safe is by checking that z-ordering will
not be affected if the overflow scrollable element were promoted to a
stacking context (details below), and that clipping our scrolling
descendants will not affect rendering.

To check the first condition (that z-ordering will not be affected).
I ensure that the candidate element and all its descendants appear as a
continuous block in the candidate's stacking context. That is, if no
other elements are 'between' any of the candidates descendants when we
sort in paint order, then we're safe. This is overly conservative,
however. We could, in future, only consider stacking problems between
elements that actually overlap.

To ensure that clipping will not cause a rendering change, I ensure
that the layer has no out of flow positioned descendant whose
containing block is not also a descendant of ours.

Test: compositing/overflow/automatically-opt-into-compositing-scrolling.html

(WebCore):

  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::RenderLayer):
(WebCore::RenderLayer::acceleratedCompositingForOverflowScrollEnabled):
(WebCore):
(WebCore::RenderLayer::updateDescendantsAreContiguousInStackingOrder):
(WebCore::RenderLayer::updateDescendantsAreContiguousInStackingOrderRecursive):
(WebCore::RenderLayer::positionOverflowControlsAfterPromotionToCompositedScrolling):
(WebCore::RenderLayer::canSafelyEstablishAStackingContext):

Returns true if the RenderLayer could become a stacking context without
affecting the stacking order.

(WebCore::RenderLayer::updateDescendantDependentFlags):

We now need to keep track of out of flow positioned descendants.

(WebCore::RenderLayer::addChild):
(WebCore::RenderLayer::removeChild):
(WebCore::RenderLayer::usesCompositedScrolling):

Has been updated to return true if it can safely establish a stacking
context, and the setting is turned on.

(WebCore::RenderLayer::needsCompositedScrolling):

This function returns true if we would like to use composited
scrolling.

(WebCore::RenderLayer::updateNeedsCompositedScrolling):
(WebCore::RenderLayer::scrollTo):
(WebCore::RenderLayer::dirtyZOrderLists):
(WebCore::RenderLayer::dirtyNormalFlowList):

Since these could affect opting into composited scrolling, we must
request that the RenderLayerCompositor reevaluate compositing.

(WebCore::RenderLayer::updateLayerListsIfNeeded):

We call updateCanSafelyEstablishStackingContext here, if necessary.

(WebCore::RenderLayer::shouldBeNormalFlowOnly):
(WebCore::RenderLayer::shouldBeSelfPaintingLayer):

usesCompositedScrolling -> needsCompositedScrolling

(WebCore::RenderLayer::setAncestorChainHasOutOfFlowPositionedDescendant):
(WebCore::RenderLayer::dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus):
(WebCore::RenderLayer::updateOutOfFlowPositioned):

Dirties and sets the out of flow positioned descendant state.

(WebCore::RenderLayer::styleChanged):

  • rendering/RenderLayer.h:

(RenderLayer):
(WebCore::RenderLayer::hasOutOfFlowPositionedDescendant):

  • rendering/RenderLayerBacking.cpp:

(WebCore::layerOrAncestorIsTransformedOrUsingCompositedScrolling):
(WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration):
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
(WebCore::RenderLayerBacking::hasUnpositionedOverflowControlsLayers):
(WebCore):

  • rendering/RenderLayerBacking.h:

(RenderLayerBacking):

  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::computeCompositingRequirements):

We now ensure that newly created overflow scroll controls get
positioned.

(WebCore::RenderLayerCompositor::requiresCompositingForOverflowScrolling):

  • rendering/RenderLayerCompositor.h:

(WebCore::RenderLayerCompositor::setShouldReevaluateCompositingAfterLayout):

  • testing/InternalSettings.cpp:

(WebCore::InternalSettings::setEnableCompositingForOverflowScroll):

Allows enabling the setting in layout tests.

(WebCore):

  • testing/InternalSettings.h:

(InternalSettings):

  • testing/InternalSettings.idl:

LayoutTests: Automatically use composited scrolling
https://bugs.webkit.org/show_bug.cgi?id=94743

Reviewed by Adrienne Walker.

Tests various configurations of elements to ensure that we only automatically opt into
composited scrolling when it is safe to do so.

  • compositing/overflow/automatically-opt-into-composited-scrolling-expected.txt: Added.
  • compositing/overflow/automatically-opt-into-composited-scrolling.html: Added.
Location:
trunk
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r137645 r137646  
     12012-12-13  Ian Vollick  <vollick@chromium.org>
     2
     3        Automatically use composited scrolling
     4        https://bugs.webkit.org/show_bug.cgi?id=94743
     5
     6        Reviewed by Adrienne Walker.
     7
     8        Tests various configurations of elements to ensure that we only automatically opt into
     9        composited scrolling when it is safe to do so.
     10
     11        * compositing/overflow/automatically-opt-into-composited-scrolling-expected.txt: Added.
     12        * compositing/overflow/automatically-opt-into-composited-scrolling.html: Added.
     13
    1142012-12-13  Ian Vollick  <vollick@chromium.org>
    215
  • trunk/Source/WebCore/ChangeLog

    r137642 r137646  
     12012-12-13  Ian Vollick  <vollick@chromium.org>
     2
     3        [chromium] Automatically use composited scrolling
     4        https://bugs.webkit.org/show_bug.cgi?id=94743
     5
     6        Reviewed by Adrienne Walker.
     7
     8        We currently use the composited scrolling facilities provided by
     9        wkb.ug/91117 if the overflow scroll block element is styled with
     10        -webkit-overflow-scrolling: touch. Ideally, we could automatically
     11        opt into composited scrolling if it is safe to do so. This can affect
     12        antialiasing, so it is important that automatically opting in is only
     13        enabled via a setting.
     14
     15        The way I determine if it is safe is by checking that z-ordering will
     16        not be affected if the overflow scrollable element were promoted to a
     17        stacking context (details below), and that clipping our scrolling
     18        descendants will not affect rendering.
     19
     20        To check the first condition (that z-ordering will not be affected).
     21        I ensure that the candidate element and all its descendants appear as a
     22        continuous block in the candidate's stacking context. That is, if no
     23        other elements are 'between' any of the candidates descendants when we
     24        sort in paint order, then we're safe. This is overly conservative,
     25        however. We could, in future, only consider stacking problems between
     26        elements that actually overlap.
     27
     28        To ensure that clipping will not cause a rendering change, I ensure
     29        that the layer has no out of flow positioned descendant whose
     30        containing block is not also a descendant of ours.
     31
     32        Test: compositing/overflow/automatically-opt-into-compositing-scrolling.html
     33
     34        (WebCore):
     35        * rendering/RenderLayer.cpp:
     36        (WebCore::RenderLayer::RenderLayer):
     37        (WebCore::RenderLayer::acceleratedCompositingForOverflowScrollEnabled):
     38        (WebCore):
     39        (WebCore::RenderLayer::updateDescendantsAreContiguousInStackingOrder):
     40        (WebCore::RenderLayer::updateDescendantsAreContiguousInStackingOrderRecursive):
     41        (WebCore::RenderLayer::positionOverflowControlsAfterPromotionToCompositedScrolling):
     42        (WebCore::RenderLayer::canSafelyEstablishAStackingContext):
     43          Returns true if the RenderLayer could become a stacking context without
     44          affecting the stacking order.
     45        (WebCore::RenderLayer::updateDescendantDependentFlags):
     46          We now need to keep track of out of flow positioned descendants.
     47        (WebCore::RenderLayer::addChild):
     48        (WebCore::RenderLayer::removeChild):
     49        (WebCore::RenderLayer::usesCompositedScrolling):
     50          Has been updated to return true if it can safely establish a stacking
     51          context, and the setting is turned on.
     52        (WebCore::RenderLayer::needsCompositedScrolling):
     53          This function returns true if we would like to use composited
     54          scrolling.
     55        (WebCore::RenderLayer::updateNeedsCompositedScrolling):
     56        (WebCore::RenderLayer::scrollTo):
     57        (WebCore::RenderLayer::dirtyZOrderLists):
     58        (WebCore::RenderLayer::dirtyNormalFlowList):
     59          Since these could affect opting into composited scrolling, we must
     60          request that the RenderLayerCompositor reevaluate compositing.
     61        (WebCore::RenderLayer::updateLayerListsIfNeeded):
     62          We call updateCanSafelyEstablishStackingContext here, if necessary.
     63        (WebCore::RenderLayer::shouldBeNormalFlowOnly):
     64        (WebCore::RenderLayer::shouldBeSelfPaintingLayer):
     65          usesCompositedScrolling -> needsCompositedScrolling
     66        (WebCore::RenderLayer::setAncestorChainHasOutOfFlowPositionedDescendant):
     67        (WebCore::RenderLayer::dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus):
     68        (WebCore::RenderLayer::updateOutOfFlowPositioned):
     69          Dirties and sets the out of flow positioned descendant state.
     70        (WebCore::RenderLayer::styleChanged):
     71        * rendering/RenderLayer.h:
     72        (RenderLayer):
     73        (WebCore::RenderLayer::hasOutOfFlowPositionedDescendant):
     74        * rendering/RenderLayerBacking.cpp:
     75        (WebCore::layerOrAncestorIsTransformedOrUsingCompositedScrolling):
     76        (WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration):
     77        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
     78        (WebCore::RenderLayerBacking::hasUnpositionedOverflowControlsLayers):
     79        (WebCore):
     80        * rendering/RenderLayerBacking.h:
     81        (RenderLayerBacking):
     82        * rendering/RenderLayerCompositor.cpp:
     83        (WebCore::RenderLayerCompositor::computeCompositingRequirements):
     84          We now ensure that newly created overflow scroll controls get
     85          positioned.
     86        (WebCore::RenderLayerCompositor::requiresCompositingForOverflowScrolling):
     87        * rendering/RenderLayerCompositor.h:
     88        (WebCore::RenderLayerCompositor::setShouldReevaluateCompositingAfterLayout):
     89        * testing/InternalSettings.cpp:
     90        (WebCore::InternalSettings::setEnableCompositingForOverflowScroll):
     91          Allows enabling the setting in layout tests.
     92        (WebCore):
     93        * testing/InternalSettings.h:
     94        (InternalSettings):
     95        * testing/InternalSettings.idl:
     96
    1972012-12-13  Ryosuke Niwa  <rniwa@webkit.org>
    298
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r137589 r137646  
    148148    , m_hasSelfPaintingLayerDescendant(false)
    149149    , m_hasSelfPaintingLayerDescendantDirty(false)
     150    , m_hasOutOfFlowPositionedDescendant(false)
     151    , m_hasOutOfFlowPositionedDescendantDirty(false)
     152    , m_needsCompositedScrolling(false)
     153    , m_descendantsAreContiguousInStackingOrder(false)
    150154    , m_isRootLayer(renderer->isRenderView())
    151155    , m_usedTransparency(false)
     
    471475}
    472476
     477bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const
     478{
     479    return renderer()->frame()
     480        && renderer()->frame()->page()
     481        && renderer()->frame()->page()->settings()->acceleratedCompositingForOverflowScrollEnabled();
     482}
     483
     484// If we are a stacking context, then this function will determine if our
     485// descendants for a contiguous block in stacking order. This is required in
     486// order for an element to be safely promoted to a stacking context. It is safe
     487// to become a stacking context if this change would not alter the stacking
     488// order of layers on the page. That can only happen if a non-descendant appear
     489// between us and our descendants in stacking order. Here's an example:
     490//
     491//                                 this
     492//                                /  |  \.
     493//                               A   B   C
     494//                              /\   |   /\.
     495//                             0 -8  D  2  7
     496//                                   |
     497//                                   5
     498//
     499// I've labeled our normal flow descendants A, B, C, and D, our stacking
     500// context descendants with their z indices, and us with 'this' (we're a
     501// stacking context and our zIndex doesn't matter here). These nodes appear in
     502// three lists: posZOrder, negZOrder, and normal flow (keep in mind that normal
     503// flow layers don't overlap). So if we arrange these lists in order we get our
     504// stacking order:
     505//
     506//                     [-8], [A-D], [0, 2, 5, 7]--> pos z-order.
     507//                       |     |
     508//        Neg z-order. <-+     +--> Normal flow descendants.
     509//
     510// We can then assign new, 'stacking' order indices to these elements as follows:
     511//
     512//                     [-8], [A-D], [0, 2, 5, 7]
     513// 'Stacking' indices:  -1     0     1  2  3  4
     514//
     515// Note that the normal flow descendants can share an index because they don't
     516// stack/overlap. Now our problem becomes very simple: a layer can safely become
     517// a stacking context if the stacking-order indices of it and its descendants
     518// appear in a contiguous block in the list of stacking indices. This problem
     519// can be solved very efficiently by calculating the min/max stacking indices in
     520// the subtree, and the number stacking context descendants. Once we have this
     521// information, we know that the subtree's indices form a contiguous block if:
     522//
     523//           maxStackIndex - minStackIndex == numSCDescendants
     524//
     525// So for node A in the example above we would have:
     526//   maxStackIndex = 1
     527//   minStackIndex = -1
     528//   numSCDecendants = 2
     529//
     530// and so,
     531//       maxStackIndex - minStackIndex == numSCDescendants
     532//  ===>                      1 - (-1) == 2
     533//  ===>                             2 == 2
     534//
     535//  Since this is true, A can safely become a stacking context.
     536//  Now, for node C we have:
     537//
     538//   maxStackIndex = 4
     539//   minStackIndex = 0 <-- because C has stacking index 0.
     540//   numSCDecendants = 2
     541//
     542// and so,
     543//       maxStackIndex - minStackIndex == numSCDescendants
     544//  ===>                         4 - 0 == 2
     545//  ===>                             4 == 2
     546//
     547// Since this is false, C cannot be safely promoted to a stacking context. This
     548// happened because of the elements with z-index 5 and 0. Now if 5 had been a
     549// child of C rather than D, and A had no child with Z index 0, we would have had:
     550//
     551//   maxStackIndex = 3
     552//   minStackIndex = 0 <-- because C has stacking index 0.
     553//   numSCDecendants = 3
     554//
     555// and so,
     556//       maxStackIndex - minStackIndex == numSCDescendants
     557//  ===>                         3 - 0 == 3
     558//  ===>                             3 == 3
     559//
     560//  And we would conclude that C could be promoted.
     561void RenderLayer::updateDescendantsAreContiguousInStackingOrder()
     562{
     563    if (!isStackingContext() || !acceleratedCompositingForOverflowScrollEnabled())
     564        return;
     565
     566    ASSERT(!m_normalFlowListDirty);
     567    ASSERT(!m_zOrderListsDirty);
     568
     569    // Create a reverse lookup.
     570    HashMap<const RenderLayer*, int> lookup;
     571
     572    if (m_negZOrderList) {
     573        int stackingOrderIndex = -1;
     574        size_t listSize = m_negZOrderList->size();
     575        for (size_t i = 0; i < listSize; ++i) {
     576            RenderLayer* currentLayer = m_negZOrderList->at(listSize - i - 1);
     577            if (!currentLayer->isStackingContext())
     578                continue;
     579            lookup.set(currentLayer, stackingOrderIndex--);
     580        }
     581    }
     582
     583    if (m_posZOrderList) {
     584        size_t listSize = m_posZOrderList->size();
     585        int stackingOrderIndex = 1;
     586        for (size_t i = 0; i < listSize; ++i) {
     587            RenderLayer* currentLayer = m_posZOrderList->at(i);
     588            if (!currentLayer->isStackingContext())
     589                continue;
     590            lookup.set(currentLayer, stackingOrderIndex++);
     591        }
     592    }
     593
     594    int minIndex = 0;
     595    int maxIndex = 0;
     596    int count = 0;
     597    bool firstIteration = true;
     598    updateDescendantsAreContiguousInStackingOrderRecursive(lookup, minIndex, maxIndex, count, firstIteration);
     599}
     600
     601void RenderLayer::updateDescendantsAreContiguousInStackingOrderRecursive(const HashMap<const RenderLayer*, int>& lookup, int& minIndex, int& maxIndex, int& count, bool firstIteration)
     602{
     603    if (isStackingContext() && !firstIteration) {
     604        if (lookup.contains(this)) {
     605            minIndex = std::min(minIndex, lookup.get(this));
     606            maxIndex = std::max(maxIndex, lookup.get(this));
     607            count++;
     608        }
     609        return;
     610    }
     611
     612    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
     613        int childMinIndex = 0;
     614        int childMaxIndex = 0;
     615        int childCount = 0;
     616        child->updateDescendantsAreContiguousInStackingOrderRecursive(lookup, childMinIndex, childMaxIndex, childCount, false);
     617        if (childCount) {
     618            count += childCount;
     619            minIndex = std::min(minIndex, childMinIndex);
     620            maxIndex = std::max(maxIndex, childMaxIndex);
     621        }
     622    }
     623
     624    if (!isStackingContext()) {
     625        bool newValue = maxIndex - minIndex == count;
     626#if USE(ACCELERATED_COMPOSITING)
     627        bool didUpdate = newValue != m_descendantsAreContiguousInStackingOrder;
     628#endif
     629        m_descendantsAreContiguousInStackingOrder = newValue;
     630#if USE(ACCELERATED_COMPOSITING)
     631        if (didUpdate)
     632            updateNeedsCompositedScrolling();
     633#endif
     634    }
     635}
     636
    473637void RenderLayer::computeRepaintRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap)
    474638{
     
    575739        geometryMap->popMappingsToAncestor(parent());
    576740}
     741
     742#if USE(ACCELERATED_COMPOSITING)
     743void RenderLayer::positionOverflowControlsAfterPromotionToCompositedScrolling()
     744{
     745    if (!usesCompositedScrolling() || !backing()->hasUnpositionedOverflowControlsLayers())
     746        return;
     747
     748    RenderGeometryMap geometryMap(UseTransforms);
     749    RenderView* view = renderer()->view();
     750    if (this != view->layer())
     751        geometryMap.pushMappingsToAncestor(parent(), 0);
     752
     753    LayoutPoint offsetFromRoot = LayoutPoint(geometryMap.absolutePoint(FloatPoint()));
     754    positionOverflowControls(toSize(roundedIntPoint(offsetFromRoot)));
     755}
     756#endif
    577757
    578758#if ENABLE(CSS_COMPOSITING)
     
    705885            return;
    706886    }
     887}
     888
     889bool RenderLayer::canSafelyEstablishAStackingContext() const
     890{
     891    if (isStackingContext() || !stackingContext())
     892        return true;
     893
     894    return m_descendantsAreContiguousInStackingOrder;
    707895}
    708896
     
    760948}
    761949
    762 void RenderLayer::updateDescendantDependentFlags()
    763 {
    764     if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty) {
     950void RenderLayer::updateDescendantDependentFlags(HashSet<const RenderObject*>* outOfFlowDescendantContainingBlocks)
     951{
     952    if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty || m_hasOutOfFlowPositionedDescendantDirty) {
     953#if USE(ACCELERATED_COMPOSITING)
     954        bool oldHasOutOfFlowPositionedDescendant = m_hasOutOfFlowPositionedDescendant;
     955#endif
    765956        m_hasVisibleDescendant = false;
    766957        m_hasSelfPaintingLayerDescendant = false;
     958        m_hasOutOfFlowPositionedDescendant = false;
     959
     960        HashSet<const RenderObject*> childOutOfFlowDescendantContainingBlocks;
    767961        for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
    768             child->updateDescendantDependentFlags();
     962            childOutOfFlowDescendantContainingBlocks.clear();
     963            child->updateDescendantDependentFlags(&childOutOfFlowDescendantContainingBlocks);
     964
     965            bool childIsOutOfFlowPositioned = child->renderer() && child->renderer()->isOutOfFlowPositioned();
     966            if (childIsOutOfFlowPositioned)
     967                childOutOfFlowDescendantContainingBlocks.add(child->renderer()->containingBlock());
     968
     969            if (outOfFlowDescendantContainingBlocks) {
     970                HashSet<const RenderObject*>::const_iterator it = childOutOfFlowDescendantContainingBlocks.begin();
     971                for (; it != childOutOfFlowDescendantContainingBlocks.end(); ++it)
     972                    outOfFlowDescendantContainingBlocks->add(*it);
     973            }
    769974
    770975            bool hasVisibleDescendant = child->m_hasVisibleContent || child->m_hasVisibleDescendant;
    771976            bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant();
     977            bool hasOutOfFlowPositionedDescendant = !childOutOfFlowDescendantContainingBlocks.isEmpty();
    772978
    773979            m_hasVisibleDescendant |= hasVisibleDescendant;
    774980            m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant;
    775 
    776             if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant)
     981            m_hasOutOfFlowPositionedDescendant |= hasOutOfFlowPositionedDescendant;
     982
     983            if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant && m_hasOutOfFlowPositionedDescendant)
    777984                break;
    778985        }
     986
     987        if (outOfFlowDescendantContainingBlocks && renderer())
     988            outOfFlowDescendantContainingBlocks->remove(renderer());
     989
    779990        m_visibleDescendantStatusDirty = false;
    780991        m_hasSelfPaintingLayerDescendantDirty = false;
     992        m_hasOutOfFlowPositionedDescendantDirty = false;
     993
     994#if USE(ACCELERATED_COMPOSITING)
     995        if (oldHasOutOfFlowPositionedDescendant != m_hasOutOfFlowPositionedDescendant)
     996            updateNeedsCompositedScrolling();
     997#endif
    781998    }
    782999
     
    13791596        setAncestorChainHasSelfPaintingLayerDescendant();
    13801597
     1598    if ((child->renderer() && child->renderer()->isOutOfFlowPositioned()) || child->hasOutOfFlowPositionedDescendant())
     1599        setAncestorChainHasOutOfFlowPositionedDescendant(child->renderer()->containingBlock());
     1600
    13811601#if USE(ACCELERATED_COMPOSITING)
    13821602    compositor()->layerWasAdded(this, child);
     
    14101630        oldChild->dirtyStackingContextZOrderLists();
    14111631    }
     1632
     1633    if ((oldChild->renderer() && oldChild->renderer()->isOutOfFlowPositioned()) || oldChild->hasOutOfFlowPositionedDescendant())
     1634        dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
    14121635
    14131636    oldChild->setPreviousSibling(0);
     
    16231846bool RenderLayer::usesCompositedScrolling() const
    16241847{
     1848    return isComposited() && backing()->scrollingLayer();
     1849}
     1850
     1851bool RenderLayer::needsCompositedScrolling() const
     1852{
     1853    return m_needsCompositedScrolling;
     1854}
     1855
     1856void RenderLayer::updateNeedsCompositedScrolling()
     1857{
     1858    bool oldNeedsCompositedScrolling = m_needsCompositedScrolling;
     1859
    16251860    if (!scrollsOverflow() || !allowsScrolling())
    1626         return false;
     1861        m_needsCompositedScrolling = false;
     1862    else {
     1863        bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScrollEnabled()
     1864            && canSafelyEstablishAStackingContext()
     1865            && !hasOutOfFlowPositionedDescendant();
    16271866
    16281867#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
    1629     return renderer()->style()->useTouchOverflowScrolling();
     1868        m_needsCompositedScrolling = forceUseCompositedScrolling || renderer()->style()->useTouchOverflowScrolling();
    16301869#else
    1631     return false;
    1632 #endif
     1870        m_needsCompositedScrolling = forceUseCompositedScrolling;
     1871#endif
     1872    }
     1873
     1874    if (oldNeedsCompositedScrolling != m_needsCompositedScrolling)
     1875        updateSelfPaintingLayer();
    16331876}
    16341877#endif
     
    17942037    }
    17952038
     2039    bool requiresRepaint = true;
     2040
     2041#if USE(ACCELERATED_COMPOSITING)
     2042    if (compositor()->inCompositingMode() && usesCompositedScrolling())
     2043        requiresRepaint = false;
     2044#endif
     2045
    17962046    // Just schedule a full repaint of our object.
    1797     if (view && !usesCompositedScrolling())
     2047    if (view && requiresRepaint)
    17982048        renderer()->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(m_repaintRect));
    17992049
     
    48015051
    48025052#if USE(ACCELERATED_COMPOSITING)
    4803     if (!renderer()->documentBeingDestroyed())
     5053    if (!renderer()->documentBeingDestroyed()) {
    48045054        compositor()->setCompositingLayersNeedRebuild();
     5055        if (acceleratedCompositingForOverflowScrollEnabled())
     5056            compositor()->setShouldReevaluateCompositingAfterLayout();
     5057    }
    48055058#endif
    48065059}
     
    48225075
    48235076#if USE(ACCELERATED_COMPOSITING)
    4824     if (!renderer()->documentBeingDestroyed())
     5077    if (!renderer()->documentBeingDestroyed()) {
    48255078        compositor()->setCompositingLayersNeedRebuild();
     5079        if (acceleratedCompositingForOverflowScrollEnabled())
     5080            compositor()->setShouldReevaluateCompositingAfterLayout();
     5081    }
    48265082#endif
    48275083}
     
    49215177void RenderLayer::updateLayerListsIfNeeded()
    49225178{
     5179    bool shouldUpdateDescendantsAreContiguousInStackingOrder = isStackingContext() && (m_zOrderListsDirty || m_normalFlowListDirty);
     5180
    49235181    updateZOrderLists();
    49245182    updateNormalFlowList();
     
    49285186        reflectionLayer->updateNormalFlowList();
    49295187    }
     5188
     5189    if (shouldUpdateDescendantsAreContiguousInStackingOrder)
     5190        updateDescendantsAreContiguousInStackingOrder();
    49305191}
    49315192
     
    50155276#endif
    50165277            && !isTransparent()
    5017             && !usesCompositedScrolling();
     5278            && !needsCompositedScrolling();
    50185279}
    50195280
     
    50225283    return !isNormalFlowOnly()
    50235284        || hasOverlayScrollbars()
    5024         || usesCompositedScrolling()
     5285        || needsCompositedScrolling()
    50255286        || renderer()->hasReflection()
    50265287        || renderer()->hasMask()
     
    51185379}
    51195380
     5381void RenderLayer::setAncestorChainHasOutOfFlowPositionedDescendant(RenderObject* containingBlock)
     5382{
     5383    for (RenderLayer* layer = this; layer; layer = layer->parent()) {
     5384        if (!layer->m_hasOutOfFlowPositionedDescendantDirty && layer->hasOutOfFlowPositionedDescendant())
     5385            break;
     5386
     5387        layer->m_hasOutOfFlowPositionedDescendantDirty = false;
     5388        layer->m_hasOutOfFlowPositionedDescendant = true;
     5389#if USE(ACCELERATED_COMPOSITING)
     5390        layer->updateNeedsCompositedScrolling();
     5391#endif
     5392
     5393        if (layer->renderer() && layer->renderer() == containingBlock)
     5394            break;
     5395    }
     5396}
     5397
     5398void RenderLayer::dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus()
     5399{
     5400    m_hasOutOfFlowPositionedDescendantDirty = true;
     5401    if (parent())
     5402        parent()->dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
     5403}
     5404
     5405void RenderLayer::updateOutOfFlowPositioned(const RenderStyle* oldStyle)
     5406{
     5407    bool wasOutOfFlowPositioned = oldStyle && (oldStyle->position() == AbsolutePosition || oldStyle->position() == FixedPosition);
     5408    if (parent() && ((renderer() && renderer()->isOutOfFlowPositioned()) != wasOutOfFlowPositioned)) {
     5409        parent()->dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
     5410#if USE(ACCELERATED_COMPOSITING)
     5411        if (!renderer()->documentBeingDestroyed() && acceleratedCompositingForOverflowScrollEnabled())
     5412            compositor()->setShouldReevaluateCompositingAfterLayout();
     5413#endif
     5414    }
     5415}
     5416
    51205417void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
    51215418{
     
    51385435    }
    51395436
     5437    updateScrollbarsAfterStyleChange(oldStyle);
    51405438    updateStackingContextsAfterStyleChange(oldStyle);
    5141     updateScrollbarsAfterStyleChange(oldStyle);
    51425439    // Overlay scrollbars can make this layer self-painting so we need
    51435440    // to recompute the bit once scrollbars have been updated.
    51445441    updateSelfPaintingLayer();
     5442    updateOutOfFlowPositioned(oldStyle);
    51455443
    51465444    if (!hasReflection() && m_reflection)
     
    51715469
    51725470#if USE(ACCELERATED_COMPOSITING)
     5471    updateNeedsCompositedScrolling();
    51735472    if (compositor()->updateLayerCompositingState(this))
    51745473        compositor()->setCompositingLayersNeedRebuild();
  • trunk/Source/WebCore/rendering/RenderLayer.h

    r137539 r137646  
    404404    void updateLayerPositionsAfterOverflowScroll();
    405405    void updateLayerPositionsAfterDocumentScroll();
     406
     407#if USE(ACCELERATED_COMPOSITING)
     408    void positionOverflowControlsAfterPromotionToCompositedScrolling();
     409#endif
    406410   
    407411    bool isPaginated() const { return m_isPaginated; }
     
    463467    // Part of the issue is with subtree relayout: we don't check if our ancestors have some descendant flags dirty, missing some updates.
    464468    bool hasSelfPaintingLayerDescendant() const { return m_hasSelfPaintingLayerDescendant; }
     469
     470    // This returns true if we have an out of flow positioned descendant whose
     471    // containing block is not a descendant of ours. If this is true, we cannot
     472    // automatically opt into composited scrolling since this out of flow
     473    // positioned descendant would become clipped by us, possibly altering the
     474    // rendering of the page.
     475    bool hasOutOfFlowPositionedDescendant() const { return m_hasOutOfFlowPositionedDescendant; }
    465476
    466477    // Gets the nearest enclosing positioned ancestor layer (also includes
     
    656667    virtual GraphicsLayer* layerForScrollCorner() const;
    657668    virtual bool usesCompositedScrolling() const OVERRIDE;
     669    bool needsCompositedScrolling() const;
    658670#else
    659671    bool isComposited() const { return false; }
     
    725737    void dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
    726738
     739    bool acceleratedCompositingForOverflowScrollEnabled() const;
     740    void updateDescendantsAreContiguousInStackingOrder();
     741    void updateDescendantsAreContiguousInStackingOrderRecursive(const HashMap<const RenderLayer*, int>&, int& minIndex, int& maxIndex, int& count, bool firstIteration);
     742
    727743    void computeRepaintRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* = 0);
    728744    void computeRepaintRectsIncludingDescendants();
     
    740756    void updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle);
    741757    void updateScrollbarsAfterLayout();
     758
     759    void setAncestorChainHasOutOfFlowPositionedDescendant(RenderObject* containingBlock);
     760    void dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
     761    void updateOutOfFlowPositioned(const RenderStyle* oldStyle);
     762
     763    void updateNeedsCompositedScrolling();
    742764
    743765    // Returns true if the position changed.
     
    876898    void setAncestorChainHasVisibleDescendant();
    877899
    878     void updateDescendantDependentFlags();
     900    void updateDescendantDependentFlags(HashSet<const RenderObject*>* outOfFlowDescendantContainingBlocks = 0);
    879901
    880902    // This flag is computed by RenderLayerCompositor, which knows more about 3d hierarchies than we do.
     
    933955    IndirectCompositingReason indirectCompositingReason() const { return static_cast<IndirectCompositingReason>(m_indirectCompositingReason); }
    934956    bool mustCompositeForIndirectReasons() const { return m_indirectCompositingReason; }
     957
     958    // Returns true if z ordering would not change if this layer were to establish a stacking context.
     959    bool canSafelyEstablishAStackingContext() const;
    935960#endif
    936961
     
    972997    bool m_hasSelfPaintingLayerDescendant : 1;
    973998    bool m_hasSelfPaintingLayerDescendantDirty : 1;
     999
     1000    // If we have no out of flow positioned descendants and no non-descendant
     1001    // appears between our descendants in stacking order, then we may become a
     1002    // stacking context.
     1003    bool m_hasOutOfFlowPositionedDescendant : 1;
     1004    bool m_hasOutOfFlowPositionedDescendantDirty : 1;
     1005
     1006    bool m_needsCompositedScrolling : 1;
     1007
     1008    // If this is true, then no non-descendant appears between any of our
     1009    // descendants in stacking order. This is one of the requirements of being
     1010    // able to safely become a stacking context.
     1011    bool m_descendantsAreContiguousInStackingOrder : 1;
    9741012
    9751013    const bool m_isRootLayer : 1;
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r137526 r137646  
    343343{
    344344    for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
    345         if (curr->hasTransform() || curr->usesCompositedScrolling())
     345        if (curr->hasTransform() || curr->needsCompositedScrolling())
    346346            return true;
    347347    }
     
    452452
    453453    // Our scrolling layer will clip.
    454     if (m_owningLayer->usesCompositedScrolling())
     454    if (m_owningLayer->needsCompositedScrolling())
    455455        needsDescendentsClippingLayer = false;
    456456
     
    461461        layerConfigChanged = true;
    462462
    463     if (updateScrollingLayers(m_owningLayer->usesCompositedScrolling()))
     463    if (updateScrollingLayers(m_owningLayer->needsCompositedScrolling()))
    464464        layerConfigChanged = true;
    465465
     
    605605        graphicsLayerParentLocation = renderer()->view()->documentRect().location();
    606606
    607     if (compAncestor && compAncestor->usesCompositedScrolling()) {
     607    if (compAncestor && compAncestor->needsCompositedScrolling()) {
    608608        RenderBox* renderBox = toRenderBox(compAncestor->renderer());
    609609        IntSize scrollOffset = compAncestor->scrolledContentOffset();
     
    962962        layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
    963963    }
     964}
     965
     966bool RenderLayerBacking::hasUnpositionedOverflowControlsLayers() const
     967{
     968    if (GraphicsLayer* layer = layerForHorizontalScrollbar())
     969        if (!layer->drawsContent())
     970            return true;
     971
     972    if (GraphicsLayer* layer = layerForVerticalScrollbar())
     973        if (!layer->drawsContent())
     974            return true;
     975
     976    if (GraphicsLayer* layer = layerForScrollCorner())
     977        if (!layer->drawsContent())
     978            return true;
     979
     980    return false;
    964981}
    965982
  • trunk/Source/WebCore/rendering/RenderLayerBacking.h

    r137248 r137646  
    138138    void updateAfterWidgetResize();
    139139    void positionOverflowControlsLayers(const IntSize& offsetFromRoot);
     140    bool hasUnpositionedOverflowControlsLayers() const;
    140141
    141142    bool usingTileCache() const { return m_usingTiledCacheLayer; }
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r137486 r137646  
    991991    if (overlapMap)
    992992        overlapMap->geometryMap().popMappingsToAncestor(ancestorLayer);
     993
     994    if (layer->usesCompositedScrolling())
     995        layer->positionOverflowControlsAfterPromotionToCompositedScrolling();
    993996}
    994997
     
    20112014bool RenderLayerCompositor::requiresCompositingForOverflowScrolling(const RenderLayer* layer) const
    20122015{
    2013     return layer->usesCompositedScrolling();
     2016    return layer->needsCompositedScrolling();
    20142017}
    20152018
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.h

    r137409 r137646  
    230230
    231231    void reportMemoryUsage(MemoryObjectInfo*) const;
     232    void setShouldReevaluateCompositingAfterLayout() { m_reevaluateCompositingAfterLayout = true; }
    232233
    233234    enum FixedPositionLayerNotCompositedReason {
  • trunk/Source/WebCore/testing/InternalSettings.cpp

    r136055 r137646  
    212212}
    213213
     214void InternalSettings::setEnableCompositingForOverflowScroll(bool enabled, ExceptionCode& ec)
     215{
     216    InternalSettingsGuardForSettings();
     217    settings()->setAcceleratedCompositingForOverflowScrollEnabled(enabled);
     218}
     219
    214220void InternalSettings::setAcceleratedDrawingEnabled(bool enabled, ExceptionCode& ec)
    215221{
  • trunk/Source/WebCore/testing/InternalSettings.h

    r136055 r137646  
    104104    void setEnableCompositingForFixedPosition(bool enabled, ExceptionCode&);
    105105    void setEnableCompositingForScrollableFrames(bool enabled, ExceptionCode&);
     106    void setEnableCompositingForOverflowScroll(bool enabled, ExceptionCode&);
    106107    void setAcceleratedDrawingEnabled(bool enabled, ExceptionCode&);
    107108    void setAcceleratedFiltersEnabled(bool enabled, ExceptionCode&);
  • trunk/Source/WebCore/testing/InternalSettings.idl

    r136055 r137646  
    3030    void setEnableCompositingForFixedPosition(in boolean enabled) raises(DOMException);
    3131    void setEnableCompositingForScrollableFrames(in boolean enabled) raises(DOMException);
     32    void setEnableCompositingForOverflowScroll(in boolean enabled) raises(DOMException);
    3233    void setAcceleratedDrawingEnabled(in boolean enabled) raises(DOMException);
    3334    void setAcceleratedFiltersEnabled(in boolean enabled) raises(DOMException);
Note: See TracChangeset for help on using the changeset viewer.