Changeset 126663 in webkit


Ignore:
Timestamp:
Aug 24, 2012 5:35:34 PM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Add support for compositing the contents of overflow:scroll areas
https://bugs.webkit.org/show_bug.cgi?id=91117

Patch by Sami Kyostila <skyostil@chromium.org> on 2012-08-24
Reviewed by Simon Fraser.

Patch by Simon Fraser with modifications by Sami Kyostila and Ian Vollick.

Allow a RenderLayer which exists for overflow scrolling
to use a composited layer for the scrolled contents, which
allows for compositing-accelerated overflow scrolling.

Tests:

compositing/overflow/clipping-ancestor-with-accelerated-scrolling-ancestor.html
compositing/overflow/iframe-inside-overflow-clipping.html
compositing/overflow/nested-scrolling.html
compositing/overflow/overflow-auto-with-touch-no-overflow.html
compositing/overflow/overflow-auto-with-touch.html
compositing/overflow/overflow-clip-with-accelerated-scrolling-ancestor.html
compositing/overflow/overflow-hidden-with-touch.html
compositing/overflow/overflow-overlay-with-touch-no-overflow.html
compositing/overflow/overflow-overlay-with-touch.html
compositing/overflow/overflow-scroll-with-touch-no-overflow.html
compositing/overflow/overflow-visible-with-touch.html
compositing/overflow/remove-overflow-crash.html
compositing/overflow/remove-overflow-crash2.html
compositing/overflow/scrolling-content-clip-to-viewport.html
compositing/overflow/textarea-scroll-touch.html

  • platform/graphics/GraphicsLayerClient.h: New paint phase flag

used for scrolled contents. Provide a typedef for the flags
so that they can be ORed together.

  • rendering/RenderLayer.h:

(WebCore::ClipRectsCache::ClipRectsCache):
(ClipRectsCache): In debug builds, store a m_respectingOverflowClip
flag so we can ASSERT later that we're fetching clip rects with the
same setting the rects were generated with.
Add new PaintLayerPaintingOverflowContents painting flag.

  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::usesCompositedScrolling): New method returns
true if this layer is using composited overflow scrolling.
(WebCore::RenderLayer::scrollTo): Don't repaint if we're doing
a composited scroll.
(WebCore::RenderLayer::paintLayer): Pass the right flags to backgroundClipRect();
if we're painting scrolled contents, we don't want to take the overflow clip rect
into account.
(WebCore::RenderLayer::paintLayerContents): Ditto. Also don't do the intersectsDamageRect()
check if we're painting scrolled contents.
(WebCore::RenderLayer::updateClipRects): New parameter to tell whether to respect overflow clipping.
Assert if we're fetching cached rects with a different 'respect clip' flag to the one they were generated
with.
(WebCore::RenderLayer::calculateClipRects): Take the 'respectOverflowClip' flag into account
when computing clip rects.
(WebCore::RenderLayer::parentClipRects): Ditto
(WebCore::RenderLayer::backgroundClipRect): Ditto
(WebCore::RenderLayer::calculateRects): Ditto
(WebCore::RenderLayer::childrenClipRect): This function is called from widget code, so may use a different
'respect clip rects' setting than that used for painting, so it has to compute clip rects on the fly.
(WebCore::RenderLayer::shouldBeNormalFlowOnly): Composited scrolling makes a layer not normal-flow only.

  • rendering/RenderLayerBacking.h:

(RenderLayerBacking): New member variables for the layers for scrolled contents, and the scrolling
layer which handles the scroll offset.
(WebCore::RenderLayerBacking::hasScrollingLayer):
(WebCore::RenderLayerBacking::scrollingLayer):
(WebCore::RenderLayerBacking::scrollingContentsLayer):

  • rendering/RenderLayerBacking.cpp:

(WebCore::RenderLayerBacking::~RenderLayerBacking):
(WebCore::RenderLayerBacking::destroyGraphicsLayers): Tear down the scrolling layers, if any.
(WebCore::layerOrAncestorIsTransformedOrUsingCompositedScrolling): Renamed from layerOrAncestorIsTransformed,
since it has to look for composited scrolling layers too.
(WebCore::RenderLayerBacking::shouldClipCompositedBounds): We don't want the contents of scrolling layers
to get clipped to the viewport.
(WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): Create scrolling layers if necessary.
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry): Set scrolling layer geometry.
(WebCore::RenderLayerBacking::updateInternalHierarchy): Hook up scrolling layers.
(WebCore::RenderLayerBacking::updateDrawsContent): Scrolling layers affect whether the main graphics layer
needs to draw content.
(WebCore::RenderLayerBacking::updateScrollingLayers): Create or destroy scrolling layers.
(WebCore::RenderLayerBacking::paintingPhaseForPrimaryLayer): If we have a scrolled contents layer,
the main layer should not paint the foreground.
(WebCore::RenderLayerBacking::parentForSublayers): Sublayers are parented in the scrolling contents
layer if one exists.
(WebCore::RenderLayerBacking::setContentsNeedDisplay): Need to dirty the scrolling contents layer.
(WebCore::RenderLayerBacking::setContentsNeedDisplayInRect): Ditto.
(WebCore::RenderLayerBacking::paintIntoLayer): Set the right painting flags.
(WebCore::RenderLayerBacking::paintContents): Only clip to the bounds if we're not painting overflow contents.

Location:
trunk
Files:
34 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/platform/chromium/TestExpectations

    r126655 r126663  
    34403440BUGWK94261 DEBUG : http/tests/inspector/indexeddb/resources-panel.html = PASS CRASH TIMEOUT
    34413441
     3442// ENABLE_OVERFLOW_SCROLLING is not currently enabled in Chromium.
     3443BUGWK94353 : compositing/overflow/overflow-clip-with-accelerated-scrolling-ancestor.html = TEXT
     3444BUGWK94353 : compositing/overflow/scrolling-content-clip-to-viewport.html = TEXT
     3445BUGWK94353 : compositing/overflow/textarea-scroll-touch.html = TEXT
     3446BUGWK94353 : compositing/overflow/nested-scrolling.html = IMAGE+TEXT
     3447BUGWK94353 : compositing/overflow/overflow-auto-with-touch.html = TEXT
     3448BUGWK94353 : compositing/overflow/overflow-overlay-with-touch.html = TEXT
     3449
    34423450// Needs a rebaseline.
    34433451BUGWK40272 : svg/css/circle-in-mask-with-shadow.svg = IMAGE
  • trunk/Source/WebCore/ChangeLog

    r126657 r126663  
     12012-08-24  Sami Kyostila  <skyostil@chromium.org>
     2
     3        Add support for compositing the contents of overflow:scroll areas
     4        https://bugs.webkit.org/show_bug.cgi?id=91117
     5
     6        Reviewed by Simon Fraser.
     7
     8        Patch by Simon Fraser with modifications by Sami Kyostila and Ian Vollick.
     9
     10        Allow a RenderLayer which exists for overflow scrolling
     11        to use a composited layer for the scrolled contents, which
     12        allows for compositing-accelerated overflow scrolling.
     13
     14        Tests:
     15            compositing/overflow/clipping-ancestor-with-accelerated-scrolling-ancestor.html
     16            compositing/overflow/iframe-inside-overflow-clipping.html
     17            compositing/overflow/nested-scrolling.html
     18            compositing/overflow/overflow-auto-with-touch-no-overflow.html
     19            compositing/overflow/overflow-auto-with-touch.html
     20            compositing/overflow/overflow-clip-with-accelerated-scrolling-ancestor.html
     21            compositing/overflow/overflow-hidden-with-touch.html
     22            compositing/overflow/overflow-overlay-with-touch-no-overflow.html
     23            compositing/overflow/overflow-overlay-with-touch.html
     24            compositing/overflow/overflow-scroll-with-touch-no-overflow.html
     25            compositing/overflow/overflow-visible-with-touch.html
     26            compositing/overflow/remove-overflow-crash.html
     27            compositing/overflow/remove-overflow-crash2.html
     28            compositing/overflow/scrolling-content-clip-to-viewport.html
     29            compositing/overflow/textarea-scroll-touch.html
     30
     31        * platform/graphics/GraphicsLayerClient.h: New paint phase flag
     32        used for scrolled contents. Provide a typedef for the flags
     33        so that they can be ORed together.
     34
     35        * rendering/RenderLayer.h:
     36        (WebCore::ClipRectsCache::ClipRectsCache):
     37        (ClipRectsCache): In debug builds, store a m_respectingOverflowClip
     38        flag so we can ASSERT later that we're fetching clip rects with the
     39        same setting the rects were generated with.
     40        Add new PaintLayerPaintingOverflowContents painting flag.
     41
     42        * rendering/RenderLayer.cpp:
     43        (WebCore::RenderLayer::usesCompositedScrolling): New method returns
     44        true if this layer is using composited overflow scrolling.
     45        (WebCore::RenderLayer::scrollTo): Don't repaint if we're doing
     46        a composited scroll.
     47        (WebCore::RenderLayer::paintLayer): Pass the right flags to backgroundClipRect();
     48        if we're painting scrolled contents, we don't want to take the overflow clip rect
     49        into account.
     50        (WebCore::RenderLayer::paintLayerContents): Ditto. Also don't do the intersectsDamageRect()
     51        check if we're painting scrolled contents.
     52        (WebCore::RenderLayer::updateClipRects): New parameter to tell whether to respect overflow clipping.
     53        Assert if we're fetching cached rects with a different 'respect clip' flag to the one they were generated
     54        with.
     55        (WebCore::RenderLayer::calculateClipRects): Take the 'respectOverflowClip' flag into account
     56        when computing clip rects.
     57        (WebCore::RenderLayer::parentClipRects): Ditto
     58        (WebCore::RenderLayer::backgroundClipRect): Ditto
     59        (WebCore::RenderLayer::calculateRects): Ditto
     60        (WebCore::RenderLayer::childrenClipRect): This function is called from widget code, so may use a different
     61        'respect clip rects' setting than that used for painting, so it has to compute clip rects on the fly.
     62        (WebCore::RenderLayer::shouldBeNormalFlowOnly): Composited scrolling makes a layer not normal-flow only.
     63
     64        * rendering/RenderLayerBacking.h:
     65        (RenderLayerBacking): New member variables for the layers for scrolled contents, and the scrolling
     66        layer which handles the scroll offset.
     67        (WebCore::RenderLayerBacking::hasScrollingLayer):
     68        (WebCore::RenderLayerBacking::scrollingLayer):
     69        (WebCore::RenderLayerBacking::scrollingContentsLayer):
     70
     71        * rendering/RenderLayerBacking.cpp:
     72        (WebCore::RenderLayerBacking::~RenderLayerBacking):
     73        (WebCore::RenderLayerBacking::destroyGraphicsLayers): Tear down the scrolling layers, if any.
     74        (WebCore::layerOrAncestorIsTransformedOrUsingCompositedScrolling): Renamed from layerOrAncestorIsTransformed,
     75        since it has to look for composited scrolling layers too.
     76        (WebCore::RenderLayerBacking::shouldClipCompositedBounds): We don't want the contents of scrolling layers
     77        to get clipped to the viewport.
     78        (WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): Create scrolling layers if necessary.
     79        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry): Set scrolling layer geometry.
     80        (WebCore::RenderLayerBacking::updateInternalHierarchy): Hook up scrolling layers.
     81        (WebCore::RenderLayerBacking::updateDrawsContent): Scrolling layers affect whether the main graphics layer
     82        needs to draw content.
     83        (WebCore::RenderLayerBacking::updateScrollingLayers): Create or destroy scrolling layers.
     84        (WebCore::RenderLayerBacking::paintingPhaseForPrimaryLayer): If we have a scrolled contents layer,
     85        the main layer should not paint the foreground.
     86        (WebCore::RenderLayerBacking::parentForSublayers): Sublayers are parented in the scrolling contents
     87        layer if one exists.
     88        (WebCore::RenderLayerBacking::setContentsNeedDisplay): Need to dirty the scrolling contents layer.
     89        (WebCore::RenderLayerBacking::setContentsNeedDisplayInRect): Ditto.
     90        (WebCore::RenderLayerBacking::paintIntoLayer): Set the right painting flags.
     91        (WebCore::RenderLayerBacking::paintContents): Only clip to the bounds if we're not painting overflow contents.
     92
    1932012-08-24  Florin Malita  <fmalita@chromium.org>
    294
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp

    r123999 r126663  
    8181    , m_appliesPageScale(false)
    8282    , m_usingTileCache(false)
    83     , m_paintingPhase(GraphicsLayerPaintAll)
     83    , m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip)
    8484    , m_contentsOrientation(CompositingCoordinatesTopDown)
    8585    , m_parent(0)
  • trunk/Source/WebCore/platform/graphics/GraphicsLayerClient.h

    r124550 r126663  
    3737class FloatPoint;
    3838
    39 enum GraphicsLayerPaintingPhase {
     39enum GraphicsLayerPaintingPhaseFlags {
    4040    GraphicsLayerPaintBackground = (1 << 0),
    4141    GraphicsLayerPaintForeground = (1 << 1),
    4242    GraphicsLayerPaintMask = (1 << 2),
    43     GraphicsLayerPaintAll = (GraphicsLayerPaintBackground | GraphicsLayerPaintForeground | GraphicsLayerPaintMask)
     43    GraphicsLayerPaintOverflowContents = (1 << 3),
     44    GraphicsLayerPaintAllWithOverflowClip = (GraphicsLayerPaintBackground | GraphicsLayerPaintForeground | GraphicsLayerPaintMask)
    4445};
     46typedef unsigned GraphicsLayerPaintingPhase;
    4547
    4648enum AnimatedPropertyID {
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r126520 r126663  
    15531553}
    15541554
     1555bool RenderLayer::usesCompositedScrolling() const
     1556{
     1557#if USE(ACCELERATED_COMPOSITING)
     1558    if (!scrollsOverflow() || !allowsScrolling())
     1559        return false;
     1560
     1561#if ENABLE(OVERFLOW_SCROLLING)
     1562    return renderer()->style()->useTouchOverflowScrolling();
     1563#else
     1564    return false;
     1565#endif
     1566#else
     1567    return false;
     1568#endif
     1569}
     1570
    15551571static inline int adjustedScrollDelta(int beginningDelta) {
    15561572    // This implemention matches Firefox's.
     
    17041720
    17051721    // Just schedule a full repaint of our object.
    1706     if (view)
     1722    if (view && !usesCompositedScrolling())
    17071723        renderer()->repaintUsingContainer(repaintContainer, m_repaintRect);
    17081724
     
    30103026        ClipRect clipRect = paintDirtyRect;
    30113027        if (parent()) {
    3012             clipRect = backgroundClipRect(rootLayer, region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects);
     3028            clipRect = backgroundClipRect(rootLayer, region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
     3029                IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
    30133030            clipRect.intersect(paintDirtyRect);
    30143031       
     
    31263143   
    31273144    if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
    3128         calculateRects(rootLayer, region, (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
     3145        calculateRects(rootLayer, region, (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect,
     3146            IgnoreOverlayScrollbarSize, localPaintFlags & PaintLayerPaintingOverflowContents ? IgnoreOverflowClip : RespectOverflowClip);
    31293147        paintOffset = toPoint(layerBounds.location() - renderBoxLocation() + subPixelAccumulation);
    31303148    }
     
    31453163
    31463164    // We want to paint our layer, but only if we intersect the damage rect.
    3147     shouldPaintContent &= intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);
     3165    if (this != rootLayer || !(localPaintFlags & PaintLayerPaintingOverflowContents))
     3166        shouldPaintContent &= intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);
    31483167   
    31493168    if (localPaintFlags & PaintLayerPaintingCompositingBackgroundPhase) {
     
    38923911}
    38933912
    3894 void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy)
     3913void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip)
    38953914{
    38963915    ASSERT(clipRectsType < NumCachedClipRectsTypes);
    38973916    if (m_clipRectsCache && m_clipRectsCache->m_clipRects[clipRectsType]) {
    38983917        ASSERT(rootLayer == m_clipRectsCache->m_clipRectsRoot[clipRectsType]);
     3918        ASSERT(m_clipRectsCache->m_respectingOverflowClip[clipRectsType] == (respectOverflowClip == RespectOverflowClip));
    38993919        return; // We have the correct cached value.
    39003920    }
     
    39043924    RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
    39053925    if (parentLayer)
    3906         parentLayer->updateClipRects(rootLayer, region, clipRectsType, relevancy);
     3926        parentLayer->updateClipRects(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
    39073927
    39083928    ClipRects clipRects;
    3909     calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy);
     3929    calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy, respectOverflowClip);
    39103930
    39113931    if (!m_clipRectsCache)
     
    39193939#ifndef NDEBUG
    39203940    m_clipRectsCache->m_clipRectsRoot[clipRectsType] = rootLayer;
    3921 #endif
    3922 }
    3923 
    3924 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy) const
     3941    m_clipRectsCache->m_respectingOverflowClip[clipRectsType] = respectOverflowClip == RespectOverflowClip;
     3942#endif
     3943}
     3944
     3945void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
    39253946{
    39263947    if (!parent()) {
     
    39413962            clipRects = *parentLayer->clipRects(clipRectsType);
    39423963        else
    3943             parentLayer->calculateClipRects(rootLayer, region, clipRectsType, clipRects);
     3964            parentLayer->calculateClipRects(rootLayer, region, clipRectsType, clipRects, IgnoreOverlayScrollbarSize, respectOverflowClip);
    39443965    } else
    39453966        clipRects.reset(PaintInfo::infiniteRect());
     
    39573978   
    39583979    // Update the clip rects that will be passed to child layers.
    3959     if (renderer()->hasClipOrOverflowClip()) {
     3980    if ((renderer()->hasOverflowClip() && (respectOverflowClip == RespectOverflowClip || this != rootLayer)) || renderer()->hasClip()) {
    39603981        // This layer establishes a clip of some kind.
    39613982
     
    39884009}
    39894010
    3990 void RenderLayer::parentClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy) const
     4011void RenderLayer::parentClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
    39914012{
    39924013    ASSERT(parent());
    39934014    if (clipRectsType == TemporaryClipRects) {
    3994         parent()->calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy);
    3995         return;
    3996     }
    3997 
    3998     parent()->updateClipRects(rootLayer, region, clipRectsType, relevancy);
     4015        parent()->calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy, respectOverflowClip);
     4016        return;
     4017    }
     4018
     4019    parent()->updateClipRects(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
    39994020    clipRects = *parent()->clipRects(clipRectsType);
    40004021}
     
    40114032}
    40124033
    4013 ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy) const
     4034ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
    40144035{
    40154036    ASSERT(parent());
    40164037    ClipRects parentRects;
    4017     parentClipRects(rootLayer, region, clipRectsType, parentRects, relevancy);
     4038    parentClipRects(rootLayer, region, clipRectsType, parentRects, relevancy, respectOverflowClip);
    40184039    ClipRect backgroundClipRect = backgroundClipRectForPosition(parentRects, renderer()->style()->position());
    40194040    RenderView* view = renderer()->view();
     
    40284049
    40294050void RenderLayer::calculateRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
    4030                                  ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, OverlayScrollbarSizeRelevancy relevancy) const
     4051                                 ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
    40314052{
    40324053    if (rootLayer != this && parent()) {
    4033         backgroundRect = backgroundClipRect(rootLayer, region, clipRectsType, relevancy);
     4054        backgroundRect = backgroundClipRect(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
    40344055        backgroundRect.intersect(paintDirtyRect);
    40354056    } else
     
    40464067    if (renderer()->hasClipOrOverflowClip()) {
    40474068        // This layer establishes a clip of some kind.
    4048         if (renderer()->hasOverflowClip()) {
     4069        if (renderer()->hasOverflowClip() && (this != rootLayer || respectOverflowClip == RespectOverflowClip)) {
    40494070            foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(offset, region, relevancy));
    40504071            if (renderer()->style()->hasBorderRadius())
     
    40694090            renderBox()->flipForWritingMode(layerBoundsWithVisualOverflow); // Layers are in physical coordinates, so the overflow has to be flipped.
    40704091            layerBoundsWithVisualOverflow.moveBy(offset);
    4071             backgroundRect.intersect(layerBoundsWithVisualOverflow);
     4092            if (this != rootLayer || respectOverflowClip == RespectOverflowClip)
     4093                backgroundRect.intersect(layerBoundsWithVisualOverflow);
    40724094        } else {
    40734095            // Shift the bounds to be for our region only.
    40744096            LayoutRect bounds = renderBox()->borderBoxRectInRegion(region);
    40754097            bounds.moveBy(offset);
    4076             backgroundRect.intersect(bounds);
     4098            if (this != rootLayer || respectOverflowClip == RespectOverflowClip)
     4099                backgroundRect.intersect(bounds);
    40774100        }
    40784101    }
     
    40874110    LayoutRect layerBounds;
    40884111    ClipRect backgroundRect, foregroundRect, outlineRect;
    4089     calculateRects(clippingRootLayer, 0, PaintingClipRects, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
     4112    // Need to use temporary clip rects, because the value of 'dontClipToOverflow' may be different from the painting path (<rdar://problem/11844909>).
     4113    calculateRects(clippingRootLayer, 0, TemporaryClipRects, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
    40904114    return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect())).enclosingBoundingBox();
    40914115}
     
    47844808            && !renderer()->hasFilter()
    47854809#endif
    4786             && !isTransparent();
     4810            && !isTransparent()
     4811            && !usesCompositedScrolling();
    47874812}
    47884813
  • trunk/Source/WebCore/rendering/RenderLayer.h

    r126520 r126663  
    231231    {
    232232#ifndef NDEBUG
    233         for (int i = 0; i < NumCachedClipRectsTypes; ++i)
     233        for (int i = 0; i < NumCachedClipRectsTypes; ++i) {
    234234            m_clipRectsRoot[i] = 0;
     235            m_respectingOverflowClip[i] = false;
     236        }
    235237#endif
    236238    }
     
    239241#ifndef NDEBUG
    240242    const RenderLayer* m_clipRectsRoot[NumCachedClipRectsTypes];
     243    bool m_respectingOverflowClip[NumCachedClipRectsTypes];
    241244#endif
    242245};
     
    361364
    362365    void updateScrollInfoAfterLayout();
     366    bool usesCompositedScrolling() const;
    363367
    364368    bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1);
     
    505509        PaintLayerPaintingCompositingForegroundPhase = 1 << 6,
    506510        PaintLayerPaintingCompositingMaskPhase = 1 << 7,
     511        PaintLayerPaintingOverflowContents = 1 << 8,
    507512        PaintLayerPaintingCompositingAllPhases = (PaintLayerPaintingCompositingBackgroundPhase | PaintLayerPaintingCompositingForegroundPhase | PaintLayerPaintingCompositingMaskPhase)
    508513    };
     
    520525    void paintOverlayScrollbars(GraphicsContext*, const LayoutRect& damageRect, PaintBehavior, RenderObject* paintingRoot);
    521526
     527    enum ShouldRespectOverflowClip { IgnoreOverflowClip, RespectOverflowClip };
     528
    522529    // This method figures out our layerBounds in coordinates relative to
    523530    // |rootLayer}.  It also computes our background and foreground clip rects
     
    525532    void calculateRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
    526533                        ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect,
    527                         OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
     534                        OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip) const;
    528535
    529536    // Compute and cache clip rects computed with the given layer as the root
    530     void updateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
     537    void updateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip);
    531538    // Compute and return the clip rects. If useCached is true, will used previously computed clip rects on ancestors
    532539    // (rather than computing them all from scratch up the parent chain).
    533     void calculateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, ClipRects&, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
     540    void calculateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, ClipRects&, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip) const;
    534541
    535542    ClipRects* clipRects(ClipRectsType type) const { ASSERT(type < NumCachedClipRectsTypes); return m_clipRectsCache ? m_clipRectsCache->m_clipRects[type].get() : 0; }
     
    830837#endif
    831838
    832     void parentClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, ClipRects&, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
    833     ClipRect backgroundClipRect(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
     839    void parentClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, ClipRects&, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip) const;
     840    ClipRect backgroundClipRect(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip) const;
    834841    LayoutRect paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior);
    835842
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r126105 r126663  
    139139    updateForegroundLayer(false);
    140140    updateMaskLayer(false);
     141    updateScrollingLayers(false);
    141142    destroyGraphicsLayers();
    142143}
     
    219220    m_containmentLayer = nullptr;
    220221    m_maskLayer = nullptr;
     222
     223    m_scrollingLayer = nullptr;
     224    m_scrollingContentsLayer = nullptr;
    221225}
    222226
     
    259263}
    260264
    261 static bool layerOrAncestorIsTransformed(RenderLayer* layer)
     265static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer* layer)
    262266{
    263267    for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
    264         if (curr->hasTransform())
     268        if (curr->hasTransform() || curr->usesCompositedScrolling())
    265269            return true;
    266270    }
     
    281285        return false;
    282286
    283     if (layerOrAncestorIsTransformed(m_owningLayer))
     287    if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
    284288        return false;
    285289
     
    367371        layerConfigChanged = true;
    368372   
    369     if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer)))
     373    bool needsDescendentsClippingLayer = compositor->clipsCompositingDescendants(m_owningLayer);
     374
     375    // Our scrolling layer will clip.
     376    if (m_owningLayer->usesCompositedScrolling())
     377        needsDescendentsClippingLayer = false;
     378
     379    if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), needsDescendentsClippingLayer))
    370380        layerConfigChanged = true;
    371381
    372382    if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
     383        layerConfigChanged = true;
     384
     385    if (updateScrollingLayers(m_owningLayer->usesCompositedScrolling()))
    373386        layerConfigChanged = true;
    374387
     
    521534    else
    522535        graphicsLayerParentLocation = renderer()->view()->documentRect().location();
     536
     537    if (compAncestor && compAncestor->usesCompositedScrolling()) {
     538        RenderBox* renderBox = toRenderBox(compAncestor->renderer());
     539        IntSize scrollOffset = compAncestor->scrolledContentOffset();
     540        IntPoint scrollOrigin(renderBox->borderLeft(), renderBox->borderTop());
     541        graphicsLayerParentLocation = scrollOrigin - scrollOffset;
     542    }
    523543   
    524544    if (compAncestor && m_ancestorClippingLayer) {
     
    526546        // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
    527547        // for a compositing layer, rootLayer is the layer itself.
    528         IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(compAncestor, 0, TemporaryClipRects).rect()); // FIXME: Incorrect for CSS regions.
     548        IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, RenderLayer::IgnoreOverflowClip).rect()); // FIXME: Incorrect for CSS regions.
    529549        ASSERT(parentClipRect != PaintInfo::infiniteRect());
    530550        m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
     
    634654    }
    635655
     656    if (m_scrollingLayer) {
     657        ASSERT(m_scrollingContentsLayer);
     658        RenderBox* renderBox = toRenderBox(renderer());
     659        IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(), renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(), renderBox->height() - renderBox->borderTop() - renderBox->borderBottom());
     660        IntSize scrollOffset = m_owningLayer->scrolledContentOffset();
     661
     662        m_scrollingLayer->setPosition(FloatPoint() + (paddingBox.location() - localCompositingBounds.location()));
     663        m_scrollingLayer->setSize(paddingBox.size());
     664        m_scrollingContentsLayer->setPosition(FloatPoint(-scrollOffset.width(), -scrollOffset.height()));
     665
     666        IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
     667        m_scrollingLayer->setOffsetFromRenderer(IntPoint() - paddingBox.location());
     668        bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
     669
     670        IntSize scrollSize(m_owningLayer->scrollWidth(), m_owningLayer->scrollHeight());
     671        if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
     672            m_scrollingContentsLayer->setNeedsDisplay();
     673
     674        m_scrollingContentsLayer->setSize(scrollSize);
     675        // FIXME: Scrolling the content layer does not need to trigger a repaint. The offset will be compensated away during painting.
     676        // FIXME: The paint offset and the scroll offset should really be separate concepts.
     677        m_scrollingContentsLayer->setOffsetFromRenderer(paddingBox.location() - IntPoint() - scrollOffset);
     678    }
     679
    636680    m_graphicsLayer->setContentsRect(contentsBox());
    637681
     
    658702    }
    659703
     704    if (m_scrollingLayer) {
     705        GraphicsLayer* superlayer = m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get();
     706        m_scrollingLayer->removeFromParent();
     707        superlayer->addChild(m_scrollingLayer.get());
     708    }
     709
    660710    // The clip for child layers does not include space for overflow controls, so they exist as
    661711    // siblings of the clipping layer if we have one. Normal children of this layer are set as
     
    677727void RenderLayerBacking::updateDrawsContent()
    678728{
     729    if (m_scrollingLayer) {
     730        // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
     731        // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
     732        // m_scrollingLayer never has backing store.
     733        // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
     734        bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && hasBoxDecorationsOrBackground(renderer());
     735        m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
     736
     737        bool hasScrollingPaintedContent = m_owningLayer->hasVisibleContent() && (renderer()->hasBackground() || paintsChildren());
     738        m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent);
     739        return;
     740    }
     741
    679742    bool hasPaintedContent = containsPaintedContent();
    680743
     
    827890}
    828891
     892bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
     893{
     894    bool layerChanged = false;
     895    if (needsScrollingLayers) {
     896        if (!m_scrollingLayer) {
     897            // Outer layer which corresponds with the scroll view.
     898            m_scrollingLayer = createGraphicsLayer("Scrolling container");
     899            m_scrollingLayer->setDrawsContent(false);
     900            m_scrollingLayer->setMasksToBounds(true);
     901
     902            // Inner layer which renders the content that scrolls.
     903            m_scrollingContentsLayer = createGraphicsLayer("Scrolled Contents");
     904            m_scrollingContentsLayer->setDrawsContent(true);
     905            m_scrollingContentsLayer->setPaintingPhase(GraphicsLayerPaintForeground | GraphicsLayerPaintOverflowContents);
     906            m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
     907
     908            layerChanged = true;
     909        }
     910    } else if (m_scrollingLayer) {
     911        m_scrollingLayer = nullptr;
     912        m_scrollingContentsLayer = nullptr;
     913        layerChanged = true;
     914    }
     915
     916    if (layerChanged) {
     917        updateInternalHierarchy();
     918        m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
     919        m_graphicsLayer->setNeedsDisplay();
     920    }
     921
     922    return layerChanged;
     923}
     924
    829925GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
    830926{
     
    834930    if (!m_maskLayer)
    835931        phase |= GraphicsLayerPaintMask;
     932
     933    if (m_scrollingContentsLayer)
     934        phase &= ~GraphicsLayerPaintForeground;
    836935
    837936    return static_cast<GraphicsLayerPaintingPhase>(phase);
     
    11671266}
    11681267
     1268GraphicsLayer* RenderLayerBacking::parentForSublayers() const
     1269{
     1270    if (m_scrollingContentsLayer)
     1271        return m_scrollingContentsLayer.get();
     1272
     1273    return m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get();
     1274}
     1275
    11691276bool RenderLayerBacking::paintsIntoWindow() const
    11701277{
     
    12151322    if (m_maskLayer && m_maskLayer->drawsContent())
    12161323        m_maskLayer->setNeedsDisplay();
     1324
     1325    if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
     1326        m_scrollingContentsLayer->setNeedsDisplay();
    12171327}
    12181328
     
    12381348        layerDirtyRect.move(-m_maskLayer->offsetFromRenderer());
    12391349        m_maskLayer->setNeedsDisplayInRect(layerDirtyRect);
     1350    }
     1351
     1352    if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
     1353        IntRect layerDirtyRect = r;
     1354        layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer());
     1355        m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect);
    12401356    }
    12411357}
     
    12601376    if (paintingPhase & GraphicsLayerPaintMask)
    12611377        paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase;
    1262        
     1378    if (paintingPhase & GraphicsLayerPaintOverflowContents)
     1379        paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
     1380   
    12631381    // FIXME: GraphicsLayers need a way to split for RenderRegions.
    12641382    m_owningLayer->paintLayerContents(rootLayer, context, paintDirtyRect, LayoutSize(), paintBehavior, paintingRoot, 0, 0, paintFlags);
     
    12911409        page->setIsPainting(true);
    12921410#endif
    1293     if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get()) {
     1411
     1412    if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get() || graphicsLayer == m_scrollingContentsLayer.get()) {
    12941413        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), &context, clip);
    12951414
    12961415        // The dirtyRect is in the coords of the painting root.
    1297         IntRect dirtyRect = compositedBounds();
    1298         dirtyRect.intersect(clip);
     1416        IntRect dirtyRect = clip;
     1417        if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
     1418            dirtyRect.intersect(compositedBounds());
    12991419
    13001420        // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
     
    16381758        backingMemory += m_maskLayer->backingStoreMemoryEstimate();
    16391759
     1760    if (m_scrollingContentsLayer)
     1761        backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate();
     1762
    16401763    if (m_layerForHorizontalScrollbar)
    16411764        backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
  • trunk/Source/WebCore/rendering/RenderLayerBacking.h

    r126105 r126663  
    8484    bool hasContentsLayer() const { return m_foregroundLayer != 0; }
    8585    GraphicsLayer* foregroundLayer() const { return m_foregroundLayer.get(); }
     86
     87    bool hasScrollingLayer() const { return m_scrollingLayer; }
     88    GraphicsLayer* scrollingLayer() const { return m_scrollingLayer.get(); }
     89    GraphicsLayer* scrollingContentsLayer() const { return m_scrollingContentsLayer.get(); }
    8690   
    8791    bool hasMaskLayer() const { return m_maskLayer != 0; }
    8892
    89     GraphicsLayer* parentForSublayers() const { return m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get(); }
     93    GraphicsLayer* parentForSublayers() const;
    9094    GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer.get() : m_graphicsLayer.get(); }
    9195
     
    187191    bool requiresVerticalScrollbarLayer() const;
    188192    bool requiresScrollCornerLayer() const;
     193    bool updateScrollingLayers(bool scrollingLayers);
    189194
    190195    GraphicsLayerPaintingPhase paintingPhaseForPrimaryLayer() const;
     
    248253    OwnPtr<GraphicsLayer> m_layerForScrollCorner;
    249254
     255    OwnPtr<GraphicsLayer> m_scrollingLayer; // only used if the layer is using composited scrolling.
     256    OwnPtr<GraphicsLayer> m_scrollingContentsLayer; // only used if the layer is using composited scrolling.
     257
    250258    IntRect m_compositedBounds;
    251259
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r125597 r126663  
    10261026        // If the layer has a clipping layer the overflow controls layers will be siblings of the clipping layer.
    10271027        // Otherwise, the overflow control layers are normal children.
    1028         if (!layerBacking->hasClippingLayer()) {
     1028        if (!layerBacking->hasClippingLayer() && !layerBacking->hasScrollingLayer()) {
    10291029            if (GraphicsLayer* overflowControlLayer = layerBacking->layerForHorizontalScrollbar()) {
    10301030                overflowControlLayer->removeFromParent();
     
    14451445        || requiresCompositingForAnimation(renderer)
    14461446        || requiresCompositingForFilters(renderer)
    1447         || requiresCompositingForPosition(renderer, layer);
     1447        || requiresCompositingForPosition(renderer, layer)
     1448        || requiresCompositingForOverflowScrolling(layer);
    14481449}
    14491450
     
    14741475        || requiresCompositingForFilters(renderer)
    14751476        || requiresCompositingForPosition(renderer, layer)
     1477        || requiresCompositingForOverflowScrolling(layer)
    14761478        || renderer->isTransparent()
    14771479        || renderer->hasMask()
     
    15301532    if (requiresCompositingForPosition(renderer, layer))
    15311533        return "position: fixed";
     1534
     1535    if (requiresCompositingForOverflowScrolling(layer))
     1536        return "-webkit-overflow-scrolling: touch";
    15321537
    15331538    if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForStacking)
     
    18331838
    18341839    return true;
     1840}
     1841
     1842bool RenderLayerCompositor::requiresCompositingForOverflowScrolling(const RenderLayer* layer) const
     1843{
     1844    return layer->usesCompositedScrolling();
    18351845}
    18361846
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.h

    r121461 r126663  
    293293    bool requiresCompositingForScrollableFrame() const;
    294294    bool requiresCompositingForPosition(RenderObject*, const RenderLayer*) const;
     295    bool requiresCompositingForOverflowScrolling(const RenderLayer*) const;
    295296    bool requiresCompositingForIndirectReason(RenderObject*, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const;
    296297
Note: See TracChangeset for help on using the changeset viewer.