Title: [260118] trunk
Revision
260118
Author
simon.fra...@apple.com
Date
2020-04-14 23:20:39 -0700 (Tue, 14 Apr 2020)

Log Message

[Async overflow scroll] Backgrounds missing on gmail sometimes
https://bugs.webkit.org/show_bug.cgi?id=210506
<rdar://problem/60523869>

Reviewed by Zalan Bujtas.
Source/WebCore:

When painting the scrolled contents layers of accelerated overflow:scroll, RenderBlock::paint()
needs to not short-circuit when the dirty rect is outside a clipping rect, because accelerated
overflow involves overdraw for tiles outside the visible area.

There were two code paths that made this mostly work: overflowRectForPaintRejection() tested for
usesCompositedScrolling(), and the #if PLATFORM(IOS_FAMILY) made it work on iOS.

For content involving flexbox, overflowRectForPaintRejection() gave the wrong answer because
flex layout would sometimes clear m_overflow, even on an overflow:scroll element.

So remove overflowRectForPaintRejection(), and instead revert to the simple visualOverflowRect(),
but first check a bit that's passed down from compositing code that indicates that
we're painting the contents of composited scroll

Test: compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles.html

* rendering/PaintPhase.h:
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paint):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::overflowRectForPaintRejection const): Deleted.
* rendering/RenderBox.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::paintLayerContents):
(WebCore::RenderLayer::paintForegroundForFragments):

LayoutTests:

Test with a scroller inside a flexbox; programmatically scrolls the scroller to the bottom,
then mouseWheels up to reveal new tiles.

* TestExpectations:
* compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles-expected.html: Added.
* compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles.html: Added.
* platform/mac/TestExpectations: Test is macOS-only because it uses wheel events.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (260117 => 260118)


--- trunk/LayoutTests/ChangeLog	2020-04-15 05:30:59 UTC (rev 260117)
+++ trunk/LayoutTests/ChangeLog	2020-04-15 06:20:39 UTC (rev 260118)
@@ -1,3 +1,19 @@
+2020-04-14  Simon Fraser  <simon.fra...@apple.com>
+
+        [Async overflow scroll] Backgrounds missing on gmail sometimes
+        https://bugs.webkit.org/show_bug.cgi?id=210506
+        <rdar://problem/60523869>
+
+        Reviewed by Zalan Bujtas.
+        
+        Test with a scroller inside a flexbox; programmatically scrolls the scroller to the bottom,
+        then mouseWheels up to reveal new tiles.
+
+        * TestExpectations:
+        * compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles-expected.html: Added.
+        * compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles.html: Added.
+        * platform/mac/TestExpectations: Test is macOS-only because it uses wheel events.
+
 2020-04-14  Lauro Moura  <lmo...@igalia.com>
 
         [GTK] Garden media/media-source/media-source-seek-back flaky crashes

Modified: trunk/LayoutTests/TestExpectations (260117 => 260118)


--- trunk/LayoutTests/TestExpectations	2020-04-15 05:30:59 UTC (rev 260117)
+++ trunk/LayoutTests/TestExpectations	2020-04-15 06:20:39 UTC (rev 260118)
@@ -9,6 +9,7 @@
 compositing/ios [ Skip ]
 compositing/contents-format/ipad [ Skip ]
 compositing/contents-format/iphone-7 [ Skip ]
+compositing/scrolling/async-overflow-scrolling/mac [ Skip ]
 css3/touch-action [ Skip ]
 accessibility/ios-simulator [ Skip ]
 accessibility/gtk [ Skip ]

Added: trunk/LayoutTests/compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles-expected.html (0 => 260118)


--- trunk/LayoutTests/compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles-expected.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles-expected.html	2020-04-15 06:20:39 UTC (rev 260118)
@@ -0,0 +1,42 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true ] -->
+<html>
+<head>
+    <style>
+        .scroller {
+            overflow-y: scroll;
+            width: 500px;
+            height: 500px;
+            border: 1px solid black;
+            background-color: red;
+        }
+        .contents {
+            height: 3000px;
+            width: 100%;
+            background-color: green;
+        }
+    </style>
+    <script src=""
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+        
+        window.addEventListener('load', async () => {
+            let scroller = document.querySelector('.scroller');
+            
+            await UIHelper.delayFor(0);
+            scroller.scrollTop = 3000;
+            await UIHelper.delayFor(0);
+            
+            await UIHelper.mouseWheelScrollAt(200, 200, 0, 1, 0, 100);
+            
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="scroller">
+        <div class="contents">&nbsp;</div>
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles.html (0 => 260118)


--- trunk/LayoutTests/compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles.html	2020-04-15 06:20:39 UTC (rev 260118)
@@ -0,0 +1,59 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true ] -->
+<html>
+<head>
+    <style>
+        .flex {
+            display: flex;
+            width: 500px;
+            border: 1px solid black;
+        }
+        .clipped {
+            overflow: hidden;
+            width: 100%;
+        }
+        .relative {
+            position: relative;
+        }
+        .scroller {
+            overflow-y: scroll;
+            width: 100%;
+            height: 500px;
+            background-color: red;
+        }
+        .contents {
+            height: 3000px;
+            width: 100%;
+            background-color: green;
+        }
+    </style>
+    <script src=""
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+        
+        window.addEventListener('load', async () => {
+            let scroller = document.querySelector('.scroller');
+            
+            await UIHelper.delayFor(0);
+            scroller.scrollTop = 3000;
+            await UIHelper.delayFor(0);
+            
+            await UIHelper.mouseWheelScrollAt(200, 200, 0, 1, 0, 100);
+            
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="flex">
+        <div class="clipped">
+            <div class="relative">
+                <div class="scroller">
+                    <div class="contents">&nbsp;</div>
+                </div>
+            </div>
+        </div>
+    </div>
+</body>
+</html>

Modified: trunk/LayoutTests/platform/ios-wk2/TestExpectations (260117 => 260118)


--- trunk/LayoutTests/platform/ios-wk2/TestExpectations	2020-04-15 05:30:59 UTC (rev 260117)
+++ trunk/LayoutTests/platform/ios-wk2/TestExpectations	2020-04-15 06:20:39 UTC (rev 260118)
@@ -9,6 +9,7 @@
 compositing/ios [ Pass ]
 compositing/shared-backing/overflow-scroll [ Pass ]
 compositing/scrolling/async-overflow-scrolling [ Pass ]
+compositing/scrolling/async-overflow-scrolling/mac [ Skip ]
 compositing/layer-creation/clipping-scope [ Pass ]
 fast/device-orientation [ Pass ]
 fast/history/ios [ Pass ]

Modified: trunk/LayoutTests/platform/mac/TestExpectations (260117 => 260118)


--- trunk/LayoutTests/platform/mac/TestExpectations	2020-04-15 05:30:59 UTC (rev 260117)
+++ trunk/LayoutTests/platform/mac/TestExpectations	2020-04-15 06:20:39 UTC (rev 260118)
@@ -7,12 +7,13 @@
 #//////////////////////////////////////////////////////////////////////////////////////////
 
 accessibility/mac [ Pass ]
+compositing/scrolling/async-overflow-scrolling/mac [ Pass ]
 displaylists [ Pass ]
 editing/mac [ Pass ]
+editing/pasteboard/mac [ Pass ]
+fast/dom/Range/mac [ Pass ]
 fast/scrolling/latching [ Pass ]
 media/mac [ Pass ]
-editing/pasteboard/mac [ Pass ]
-fast/dom/Range/mac [ Pass ]
 
 fast/forms/search/search-padding-cancel-results-buttons.html [ Pass ]
 fast/forms/search/search-results-hidden-crash.html [ Pass ]

Modified: trunk/Source/WebCore/ChangeLog (260117 => 260118)


--- trunk/Source/WebCore/ChangeLog	2020-04-15 05:30:59 UTC (rev 260117)
+++ trunk/Source/WebCore/ChangeLog	2020-04-15 06:20:39 UTC (rev 260118)
@@ -1,3 +1,37 @@
+2020-04-14  Simon Fraser  <simon.fra...@apple.com>
+
+        [Async overflow scroll] Backgrounds missing on gmail sometimes
+        https://bugs.webkit.org/show_bug.cgi?id=210506
+        <rdar://problem/60523869>
+
+        Reviewed by Zalan Bujtas.
+
+        When painting the scrolled contents layers of accelerated overflow:scroll, RenderBlock::paint()
+        needs to not short-circuit when the dirty rect is outside a clipping rect, because accelerated
+        overflow involves overdraw for tiles outside the visible area.
+
+        There were two code paths that made this mostly work: overflowRectForPaintRejection() tested for
+        usesCompositedScrolling(), and the #if PLATFORM(IOS_FAMILY) made it work on iOS.
+
+        For content involving flexbox, overflowRectForPaintRejection() gave the wrong answer because 
+        flex layout would sometimes clear m_overflow, even on an overflow:scroll element.
+        
+        So remove overflowRectForPaintRejection(), and instead revert to the simple visualOverflowRect(),
+        but first check a bit that's passed down from compositing code that indicates that
+        we're painting the contents of composited scroll
+
+        Test: compositing/scrolling/async-overflow-scrolling/mac/overflow-in-flex-empty-tiles.html
+
+        * rendering/PaintPhase.h:
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::paint):
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::overflowRectForPaintRejection const): Deleted.
+        * rendering/RenderBox.h:
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::paintLayerContents):
+        (WebCore::RenderLayer::paintForegroundForFragments):
+
 2020-04-14  Zalan Bujtas  <za...@apple.com>
 
         Content expanding is broken on icourse163.org

Modified: trunk/Source/WebCore/rendering/PaintPhase.h (260117 => 260118)


--- trunk/Source/WebCore/rendering/PaintPhase.h	2020-04-15 05:30:59 UTC (rev 260117)
+++ trunk/Source/WebCore/rendering/PaintPhase.h	2020-04-15 06:20:39 UTC (rev 260118)
@@ -54,20 +54,21 @@
 };
 
 enum class PaintBehavior : uint16_t {
-    Normal                      = 0,
-    SelectionOnly               = 1 << 0,
-    SkipSelectionHighlight      = 1 << 1,
-    ForceBlackText              = 1 << 2,
-    ForceWhiteText              = 1 << 3,
-    RenderingSVGMask            = 1 << 4,
-    SkipRootBackground          = 1 << 5,
-    RootBackgroundOnly          = 1 << 6,
-    SelectionAndBackgroundsOnly = 1 << 7,
-    ExcludeSelection            = 1 << 8,
-    FlattenCompositingLayers    = 1 << 9, // Paint doesn't stop at compositing layer boundaries.
-    Snapshotting                = 1 << 10,
-    TileFirstPaint              = 1 << 11,
-    AnnotateLinks               = 1 << 12, // Collect all renderers with links to annotate their URLs (e.g. PDFs)
+    Normal                              = 0,
+    SelectionOnly                       = 1 << 0,
+    SkipSelectionHighlight              = 1 << 1,
+    ForceBlackText                      = 1 << 2,
+    ForceWhiteText                      = 1 << 3,
+    RenderingSVGMask                    = 1 << 4,
+    SkipRootBackground                  = 1 << 5,
+    RootBackgroundOnly                  = 1 << 6,
+    SelectionAndBackgroundsOnly         = 1 << 7,
+    ExcludeSelection                    = 1 << 8,
+    FlattenCompositingLayers            = 1 << 9, // Paint doesn't stop at compositing layer boundaries.
+    Snapshotting                        = 1 << 10,
+    TileFirstPaint                      = 1 << 11,
+    CompositedOverflowScrollContent     = 1 << 12,
+    AnnotateLinks                       = 1 << 13, // Collect all renderers with links to annotate their URLs (e.g. PDFs)
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (260117 => 260118)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2020-04-15 05:30:59 UTC (rev 260117)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2020-04-15 06:20:39 UTC (rev 260118)
@@ -1092,16 +1092,11 @@
     // Check if we need to do anything at all.
     // FIXME: Could eliminate the isDocumentElementRenderer() check if we fix background painting so that the RenderView
     // paints the root's background.
-    if (!isDocumentElementRenderer()) {
-        LayoutRect overflowBox = overflowRectForPaintRejection();
+    if (!isDocumentElementRenderer() && !paintInfo.paintBehavior.contains(PaintBehavior::CompositedOverflowScrollContent)) {
+        LayoutRect overflowBox = visualOverflowRect();
         flipForWritingMode(overflowBox);
         overflowBox.moveBy(adjustedPaintOffset);
-        if (!overflowBox.intersects(paintInfo.rect)
-#if PLATFORM(IOS_FAMILY)
-            // FIXME: This may be applicable to non-iOS ports.
-            && (!hasLayer() || !layer()->isComposited())
-#endif
-        )
+        if (!overflowBox.intersects(paintInfo.rect))
             return;
     }
 

Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (260117 => 260118)


--- trunk/Source/WebCore/rendering/RenderBox.cpp	2020-04-15 05:30:59 UTC (rev 260117)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp	2020-04-15 06:20:39 UTC (rev 260118)
@@ -4848,18 +4848,6 @@
     return rect;
 }
 
-LayoutRect RenderBox::overflowRectForPaintRejection() const
-{
-    LayoutRect overflowRect = visualOverflowRect();
-    
-    if (!m_overflow || !usesCompositedScrolling())
-        return overflowRect;
-
-    overflowRect.unite(layoutOverflowRect());
-    overflowRect.moveBy(-scrollPosition());
-    return overflowRect;
-}
-
 LayoutUnit RenderBox::offsetLeft() const
 {
     return adjustedPositionRelativeToOffsetParent(topLeftLocation()).x();

Modified: trunk/Source/WebCore/rendering/RenderBox.h (260117 => 260118)


--- trunk/Source/WebCore/rendering/RenderBox.h	2020-04-15 05:30:59 UTC (rev 260117)
+++ trunk/Source/WebCore/rendering/RenderBox.h	2020-04-15 06:20:39 UTC (rev 260118)
@@ -195,8 +195,6 @@
     LayoutUnit logicalLeftVisualOverflow() const { return style().isHorizontalWritingMode() ? visualOverflowRect().x() : visualOverflowRect().y(); }
     LayoutUnit logicalRightVisualOverflow() const { return style().isHorizontalWritingMode() ? visualOverflowRect().maxX() : visualOverflowRect().maxY(); }
 
-    LayoutRect overflowRectForPaintRejection() const;
-    
     void addLayoutOverflow(const LayoutRect&);
     void addVisualOverflow(const LayoutRect&);
     void clearOverflow();

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (260117 => 260118)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2020-04-15 05:30:59 UTC (rev 260117)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2020-04-15 06:20:39 UTC (rev 260118)
@@ -4684,6 +4684,9 @@
         if (paintingInfo.paintBehavior & PaintBehavior::ExcludeSelection)
             paintBehavior.add(PaintBehavior::ExcludeSelection);
 
+        if (isPaintingScrollingContent && isPaintingOverflowContents)
+            paintBehavior.add(PaintBehavior::CompositedOverflowScrollContent);
+
         LayoutRect paintDirtyRect = localPaintingInfo.paintDirtyRect;
         if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars || isCollectingEventRegion) {
             // Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment, as well as whether or not the content of each
@@ -4761,6 +4764,9 @@
         if (paintingInfo.paintBehavior & PaintBehavior::TileFirstPaint)
             paintBehavior.add(PaintBehavior::TileFirstPaint);
 
+        if (isPaintingScrollingContent && isPaintingOverflowContents)
+            paintBehavior.add(PaintBehavior::CompositedOverflowScrollContent);
+
         if (shouldPaintMask(paintingInfo.paintBehavior, localPaintFlags)) {
             // Paint the mask for the fragments.
             paintMaskForFragments(layerFragments, context, paintingInfo, paintBehavior, subtreePaintRootForRenderer);
@@ -5092,6 +5098,7 @@
     else
         localPaintBehavior = paintBehavior;
 
+    // FIXME: It's unclear if this flag copying is necessary.
     if (localPaintingInfo.paintBehavior & PaintBehavior::ExcludeSelection)
         localPaintBehavior.add(PaintBehavior::ExcludeSelection);
     
@@ -5101,6 +5108,9 @@
     if (localPaintingInfo.paintBehavior & PaintBehavior::TileFirstPaint)
         localPaintBehavior.add(PaintBehavior::TileFirstPaint);
 
+    if (localPaintingInfo.paintBehavior & PaintBehavior::CompositedOverflowScrollContent)
+        localPaintBehavior.add(PaintBehavior::CompositedOverflowScrollContent);
+
     // Optimize clipping for the single fragment case.
     bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty();
     ClipRect clippedRect;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to