Use scroll-velocity-based tile coverage for overflow:scroll
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 May 2019 01:07:03 +0000 (01:07 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 May 2019 01:07:03 +0000 (01:07 +0000)
https://bugs.webkit.org/show_bug.cgi?id=198294
rdar://problem/48942184

Reviewed by Tim Horton.

Source/WebCore:

Start using a velocity-based tile coverage computation on layers with Type::ScrolledContents,
which is the content layers for overflow:scroll when they get big enough to get tiled.

Move legacy macOS coverage code into adjustTileCoverageForDesktopPageScrolling() because
I don't want to change its behavior in this patch. Use TileController::adjustTileCoverageRectForScrolling()
for iOS and macOS overflow scrolling. Since only iOS page scrolling gets velocity data from the UI
process, compute velocity in TileController using the visible rect top-left.

For overflow scroll, we have to plumb horizontal and vertical coverage in from
RenderLayerBacking.

Tests: tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage.html
       tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage.html
       tiled-drawing/scrolling/overflow/overflow-tile-coverage.html

* platform/graphics/TiledBacking.h:
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::adjustCoverageRect const):
* platform/graphics/ca/PlatformCALayer.h:
* platform/graphics/ca/TileController.cpp:
(WebCore::TileController::setVelocity):
(WebCore::TileController::adjustTileCoverageRect):
(WebCore::TileController::adjustTileCoverageForDesktopPageScrolling const):
(WebCore::TileController::adjustTileCoverageWithScrollingVelocity const):
(WebCore::TileController::adjustTileCoverageRectForScrolling):
(WebCore::expandRectWithinRect): Deleted.
(WebCore::TileController::adjustTileCoverageRect const): Deleted.
(WebCore::TileController::adjustTileCoverageRectForScrolling const): Deleted.
* platform/graphics/ca/TileController.h:
* rendering/RenderLayer.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::computePageTiledBackingCoverage):
(WebCore::computeOverflowTiledBackingCoverage):
(WebCore::RenderLayerBacking::adjustTiledBackingCoverage):
(WebCore::RenderLayerBacking::updateGeometry):

LayoutTests:

* tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage-expected.txt: Added.
* tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage.html: Added.
* tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage-expected.txt: Added.
* tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage.html: Added.
* tiled-drawing/scrolling/overflow/overflow-tile-coverage-expected.txt: Added.
* tiled-drawing/scrolling/overflow/overflow-tile-coverage.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@245837 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
LayoutTests/ChangeLog
LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage-expected.txt [new file with mode: 0644]
LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage.html [new file with mode: 0644]
LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage-expected.txt [new file with mode: 0644]
LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage.html [new file with mode: 0644]
LayoutTests/tiled-drawing/scrolling/overflow/overflow-tile-coverage-expected.txt [new file with mode: 0644]
LayoutTests/tiled-drawing/scrolling/overflow/overflow-tile-coverage.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/TiledBacking.h
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
Source/WebCore/platform/graphics/ca/PlatformCALayer.h
Source/WebCore/platform/graphics/ca/TileController.cpp
Source/WebCore/platform/graphics/ca/TileController.h
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerBacking.cpp

index 144fd27..90ae311 100644 (file)
@@ -1,3 +1,18 @@
+2019-05-28  Simon Fraser  <simon.fraser@apple.com>
+
+        Use scroll-velocity-based tile coverage for overflow:scroll
+        https://bugs.webkit.org/show_bug.cgi?id=198294
+        rdar://problem/48942184
+
+        Reviewed by Tim Horton.
+
+        * tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage-expected.txt: Added.
+        * tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage.html: Added.
+        * tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage-expected.txt: Added.
+        * tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage.html: Added.
+        * tiled-drawing/scrolling/overflow/overflow-tile-coverage-expected.txt: Added.
+        * tiled-drawing/scrolling/overflow/overflow-tile-coverage.html: Added.
+
 2019-05-28  Youenn Fablet  <youenn@apple.com>
 
         createAnswer() SDP Rejected by setLocalDescription()
diff --git a/LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage-expected.txt b/LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage-expected.txt
new file mode 100644 (file)
index 0000000..d7f26ac
--- /dev/null
@@ -0,0 +1,63 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 785.00 700.00)
+  (visible rect 0.00, 0.00 785.00 x 600.00)
+  (coverage rect 0.00, 0.00 785.00 x 600.00)
+  (intersects coverage rect 1)
+  (contentsScale 1.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 700.00)
+      (contentsOpaque 1)
+      (visible rect 0.00, 0.00 785.00 x 600.00)
+      (coverage rect 0.00, 0.00 785.00 x 600.00)
+      (intersects coverage rect 1)
+      (contentsScale 1.00)
+      (tile cache coverage 0, 0 785 x 700)
+      (tile size 785 x 512)
+      (top left tile 0, 0 tiles grid 1 x 2)
+      (in window 1)
+      (children 1
+        (GraphicsLayer
+          (position 58.00 50.00)
+          (bounds 402.00 514.00)
+          (drawsContent 1)
+          (visible rect 0.00, 0.00 402.00 x 514.00)
+          (coverage rect -58.00, -50.00 785.00 x 600.00)
+          (intersects coverage rect 1)
+          (contentsScale 1.00)
+          (children 1
+            (GraphicsLayer
+              (offsetFromRenderer width=1 height=1)
+              (position 1.00 1.00)
+              (bounds 385.00 512.00)
+              (visible rect 0.00, 0.00 385.00 x 512.00)
+              (coverage rect 0.00, 0.00 385.00 x 512.00)
+              (intersects coverage rect 1)
+              (contentsScale 1.00)
+              (children 1
+                (GraphicsLayer
+                  (offsetFromRenderer width=1 height=1)
+                  (scrollOffset (0,1800))
+                  (position 0.00 -1800.00)
+                  (anchor 0.00 0.00)
+                  (bounds 385.00 3000.00)
+                  (drawsContent 1)
+                  (visible rect 0.00, 1800.00 385.00 x 512.00)
+                  (coverage rect 0.00, 1544.00 897.00 x 1024.00)
+                  (intersects coverage rect 1)
+                  (contentsScale 1.00)
+                  (tile cache coverage 0, 1536 385 x 1464)
+                  (tile size 512 x 512)
+                  (top left tile 0, 3 tiles grid 1 x 3)
+                  (in window 1)
+                )
+              )
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage.html b/LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage.html
new file mode 100644 (file)
index 0000000..71c90d5
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true ] -->
+<html>
+<head>
+    <style>
+        #scroller {
+            margin: 50px;
+            height: 512px;
+            width: 400px;
+            overflow-y: scroll;
+            border: 1px solid black;
+        }
+        
+        .contents {
+                       height: 3000px;
+            background-image: repeating-linear-gradient(white, silver 400px);
+        }
+
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+               
+               function startTest()
+               {
+                       requestAnimationFrame(() => {
+                               scroller.scrollTop = 2000;
+
+                               requestAnimationFrame(() => {
+                                       scroller.scrollTop = 1800;
+
+                           document.getElementById('layers').innerText = internals.layerTreeAsText(document,
+                               internals.LAYER_TREE_INCLUDES_VISIBLE_RECTS | internals.LAYER_TREE_INCLUDES_TILE_CACHES);
+                                       
+                                       if (window.testRunner)
+                                               testRunner.notifyDone();
+                               });
+                       });
+               }
+
+        window.addEventListener('load', startTest, false);
+    </script>
+</head>
+<body>
+
+    <div id="scroller">
+        <div class="contents">
+        </div>
+    </div>
+
+<pre id="layers">Layer tree goes here</p>
+</body>
+</html>
diff --git a/LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage-expected.txt b/LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage-expected.txt
new file mode 100644 (file)
index 0000000..292b085
--- /dev/null
@@ -0,0 +1,63 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 785.00 700.00)
+  (visible rect 0.00, 0.00 785.00 x 600.00)
+  (coverage rect 0.00, 0.00 785.00 x 600.00)
+  (intersects coverage rect 1)
+  (contentsScale 1.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 700.00)
+      (contentsOpaque 1)
+      (visible rect 0.00, 0.00 785.00 x 600.00)
+      (coverage rect 0.00, 0.00 785.00 x 600.00)
+      (intersects coverage rect 1)
+      (contentsScale 1.00)
+      (tile cache coverage 0, 0 785 x 700)
+      (tile size 785 x 512)
+      (top left tile 0, 0 tiles grid 1 x 2)
+      (in window 1)
+      (children 1
+        (GraphicsLayer
+          (position 58.00 50.00)
+          (bounds 402.00 514.00)
+          (drawsContent 1)
+          (visible rect 0.00, 0.00 402.00 x 514.00)
+          (coverage rect -58.00, -50.00 785.00 x 600.00)
+          (intersects coverage rect 1)
+          (contentsScale 1.00)
+          (children 1
+            (GraphicsLayer
+              (offsetFromRenderer width=1 height=1)
+              (position 1.00 1.00)
+              (bounds 385.00 512.00)
+              (visible rect 0.00, 0.00 385.00 x 512.00)
+              (coverage rect 0.00, 0.00 385.00 x 512.00)
+              (intersects coverage rect 1)
+              (contentsScale 1.00)
+              (children 1
+                (GraphicsLayer
+                  (offsetFromRenderer width=1 height=1)
+                  (scrollOffset (0,200))
+                  (position 0.00 -200.00)
+                  (anchor 0.00 0.00)
+                  (bounds 385.00 3000.00)
+                  (drawsContent 1)
+                  (visible rect 0.00, 200.00 385.00 x 512.00)
+                  (coverage rect 0.00, 0.00 897.00 x 1024.00)
+                  (intersects coverage rect 1)
+                  (contentsScale 1.00)
+                  (tile cache coverage 0, 0 385 x 1024)
+                  (tile size 512 x 512)
+                  (top left tile 0, 0 tiles grid 1 x 2)
+                  (in window 1)
+                )
+              )
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage.html b/LayoutTests/tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage.html
new file mode 100644 (file)
index 0000000..924b110
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true ] -->
+<html>
+<head>
+    <style>
+        #scroller {
+            margin: 50px;
+            height: 512px;
+            width: 400px;
+            overflow-y: scroll;
+            border: 1px solid black;
+        }
+        
+        .contents {
+                       height: 3000px;
+            background-image: repeating-linear-gradient(white, silver 400px);
+        }
+
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+               
+               function startTest()
+               {
+                       requestAnimationFrame(() => {
+                               scroller.scrollTop = 20;
+
+                               requestAnimationFrame(() => {
+                                       scroller.scrollTop = 200;
+
+                           document.getElementById('layers').innerText = internals.layerTreeAsText(document,
+                               internals.LAYER_TREE_INCLUDES_VISIBLE_RECTS | internals.LAYER_TREE_INCLUDES_TILE_CACHES);
+                                       
+                                       if (window.testRunner)
+                                               testRunner.notifyDone();
+                               });
+                       });
+               }
+
+        window.addEventListener('load', startTest, false);
+    </script>
+</head>
+<body>
+
+    <div id="scroller">
+        <div class="contents">
+        </div>
+    </div>
+
+<pre id="layers">Layer tree goes here</p>
+</body>
+</html>
diff --git a/LayoutTests/tiled-drawing/scrolling/overflow/overflow-tile-coverage-expected.txt b/LayoutTests/tiled-drawing/scrolling/overflow/overflow-tile-coverage-expected.txt
new file mode 100644 (file)
index 0000000..c459546
--- /dev/null
@@ -0,0 +1,61 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 785.00 700.00)
+  (visible rect 0.00, 0.00 785.00 x 600.00)
+  (coverage rect 0.00, 0.00 785.00 x 600.00)
+  (intersects coverage rect 1)
+  (contentsScale 1.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 700.00)
+      (contentsOpaque 1)
+      (visible rect 0.00, 0.00 785.00 x 600.00)
+      (coverage rect 0.00, 0.00 785.00 x 600.00)
+      (intersects coverage rect 1)
+      (contentsScale 1.00)
+      (tile cache coverage 0, 0 785 x 700)
+      (tile size 785 x 512)
+      (top left tile 0, 0 tiles grid 1 x 2)
+      (in window 1)
+      (children 1
+        (GraphicsLayer
+          (position 58.00 50.00)
+          (bounds 402.00 514.00)
+          (drawsContent 1)
+          (visible rect 0.00, 0.00 402.00 x 514.00)
+          (coverage rect -58.00, -50.00 785.00 x 600.00)
+          (intersects coverage rect 1)
+          (contentsScale 1.00)
+          (children 1
+            (GraphicsLayer
+              (offsetFromRenderer width=1 height=1)
+              (position 1.00 1.00)
+              (bounds 385.00 512.00)
+              (visible rect 0.00, 0.00 385.00 x 512.00)
+              (coverage rect 0.00, 0.00 385.00 x 512.00)
+              (intersects coverage rect 1)
+              (contentsScale 1.00)
+              (children 1
+                (GraphicsLayer
+                  (offsetFromRenderer width=1 height=1)
+                  (anchor 0.00 0.00)
+                  (bounds 385.00 3000.00)
+                  (drawsContent 1)
+                  (visible rect 0.00, 0.00 385.00 x 512.00)
+                  (coverage rect 0.00, 0.00 385.00 x 512.00)
+                  (intersects coverage rect 1)
+                  (contentsScale 1.00)
+                  (tile cache coverage 0, 0 385 x 512)
+                  (tile size 512 x 512)
+                  (top left tile 0, 0 tiles grid 1 x 1)
+                  (in window 1)
+                )
+              )
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/tiled-drawing/scrolling/overflow/overflow-tile-coverage.html b/LayoutTests/tiled-drawing/scrolling/overflow/overflow-tile-coverage.html
new file mode 100644 (file)
index 0000000..36cffa9
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true ] -->
+<html>
+<head>
+    <style>
+        .scroller {
+            margin: 50px;
+            height: 512px;
+            width: 400px;
+            overflow-y: scroll;
+            border: 1px solid black;
+        }
+        
+        .contents {
+                       height: 3000px;
+            background-image: repeating-linear-gradient(white, silver 400px);
+        }
+
+    </style>
+    <script>
+        if (window.testRunner)
+            testRunner.dumpAsText();
+
+        window.addEventListener('load', () => {
+            document.getElementById('layers').innerText = internals.layerTreeAsText(document,
+                internals.LAYER_TREE_INCLUDES_VISIBLE_RECTS | internals.LAYER_TREE_INCLUDES_TILE_CACHES);
+        }, false);
+    </script>
+</head>
+<body>
+
+    <div class="scroller">
+        <div class="contents">
+        </div>
+    </div>
+
+<pre id="layers">Layer tree goes here</p>
+</body>
+</html>
index 8bd54d5..98153c3 100644 (file)
@@ -1,3 +1,47 @@
+2019-05-28  Simon Fraser  <simon.fraser@apple.com>
+
+        Use scroll-velocity-based tile coverage for overflow:scroll
+        https://bugs.webkit.org/show_bug.cgi?id=198294
+        rdar://problem/48942184
+
+        Reviewed by Tim Horton.
+
+        Start using a velocity-based tile coverage computation on layers with Type::ScrolledContents,
+        which is the content layers for overflow:scroll when they get big enough to get tiled.
+
+        Move legacy macOS coverage code into adjustTileCoverageForDesktopPageScrolling() because
+        I don't want to change its behavior in this patch. Use TileController::adjustTileCoverageRectForScrolling()
+        for iOS and macOS overflow scrolling. Since only iOS page scrolling gets velocity data from the UI
+        process, compute velocity in TileController using the visible rect top-left.
+        
+        For overflow scroll, we have to plumb horizontal and vertical coverage in from
+        RenderLayerBacking.
+
+        Tests: tiled-drawing/scrolling/overflow/overflow-scrolled-down-tile-coverage.html
+               tiled-drawing/scrolling/overflow/overflow-scrolled-up-tile-coverage.html
+               tiled-drawing/scrolling/overflow/overflow-tile-coverage.html
+
+        * platform/graphics/TiledBacking.h:
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::adjustCoverageRect const):
+        * platform/graphics/ca/PlatformCALayer.h:
+        * platform/graphics/ca/TileController.cpp:
+        (WebCore::TileController::setVelocity):
+        (WebCore::TileController::adjustTileCoverageRect):
+        (WebCore::TileController::adjustTileCoverageForDesktopPageScrolling const):
+        (WebCore::TileController::adjustTileCoverageWithScrollingVelocity const):
+        (WebCore::TileController::adjustTileCoverageRectForScrolling):
+        (WebCore::expandRectWithinRect): Deleted.
+        (WebCore::TileController::adjustTileCoverageRect const): Deleted.
+        (WebCore::TileController::adjustTileCoverageRectForScrolling const): Deleted.
+        * platform/graphics/ca/TileController.h:
+        * rendering/RenderLayer.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::computePageTiledBackingCoverage):
+        (WebCore::computeOverflowTiledBackingCoverage):
+        (WebCore::RenderLayerBacking::adjustTiledBackingCoverage):
+        (WebCore::RenderLayerBacking::updateGeometry):
+
 2019-05-28  Shawn Roberts  <sroberts@apple.com>
 
         Unreviewed, rolling out r245475.
index f22a6fc..6087985 100644 (file)
@@ -95,8 +95,8 @@ public:
     virtual void setTileCoverage(TileCoverage) = 0;
     virtual TileCoverage tileCoverage() const = 0;
 
-    virtual FloatRect adjustTileCoverageRect(const FloatRect& coverageRect, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, bool sizeChanged) const = 0;
-    virtual FloatRect adjustTileCoverageRectForScrolling(const FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, float contentsScale) const = 0;
+    virtual FloatRect adjustTileCoverageRect(const FloatRect& coverageRect, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, bool sizeChanged) = 0;
+    virtual FloatRect adjustTileCoverageRectForScrolling(const FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, float contentsScale) = 0;
 
     virtual void willStartLiveResize() = 0;
     virtual void didEndLiveResize() = 0;
index 18ed2e7..a81ff69 100644 (file)
@@ -1447,9 +1447,12 @@ bool GraphicsLayerCA::adjustCoverageRect(VisibleAndCoverageRects& rects, const F
     case Type::PageTiledBacking:
         coverageRect = tiledBacking()->adjustTileCoverageRectForScrolling(coverageRect, size(), oldVisibleRect, rects.visibleRect, pageScaleFactor() * deviceScaleFactor());
         break;
-    case Type::Normal:
     case Type::ScrolledContents:
-        if (m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
+        if (m_layer->usesTiledBackingLayer())
+            coverageRect = tiledBacking()->adjustTileCoverageRectForScrolling(coverageRect, size(), oldVisibleRect, rects.visibleRect, pageScaleFactor() * deviceScaleFactor());
+        break;
+    case Type::Normal:
+        if (m_layer->usesTiledBackingLayer())
             coverageRect = tiledBacking()->adjustTileCoverageRect(coverageRect, oldVisibleRect, rects.visibleRect, size() != m_sizeAtLastCoverageRectUpdate);
         break;
     default:
index 39b9294..f19768a 100644 (file)
@@ -99,6 +99,8 @@ public:
 
     bool usesTiledBackingLayer() const { return layerType() == LayerTypePageTiledBackingLayer || layerType() == LayerTypeTiledBackingLayer; }
 
+    bool isPageTiledBackingLayer() const { return layerType() == LayerTypePageTiledBackingLayer; }
+
     PlatformCALayerClient* owner() const { return m_owner; }
     virtual void setOwner(PlatformCALayerClient* owner) { m_owner = owner; }
 
index 4aff101..7ffef81 100644 (file)
@@ -240,8 +240,10 @@ bool TileController::tilesWouldChangeForCoverageRect(const FloatRect& rect) cons
 void TileController::setVelocity(const VelocityData& velocity)
 {
     bool changeAffectsTileCoverage = m_velocity.velocityOrScaleIsChanging() || velocity.velocityOrScaleIsChanging();
+
     m_velocity = velocity;
-    
+    m_haveExternalVelocityData = true;
+
     if (changeAffectsTileCoverage)
         setNeedsRevalidateTiles();
 }
@@ -360,33 +362,7 @@ IntRect TileController::boundsAtLastRevalidateWithoutMargin() const
     return boundsWithoutMargin;
 }
 
-#if !PLATFORM(IOS_FAMILY)
-// Return 'rect' padded evenly on all sides to achieve 'newSize', but make the padding uneven to contain within constrainingRect.
-static FloatRect expandRectWithinRect(const FloatRect& rect, const FloatSize& newSize, const FloatRect& constrainingRect)
-{
-    ASSERT(newSize.width() >= rect.width() && newSize.height() >= rect.height());
-
-    FloatSize extraSize = newSize - rect.size();
-    
-    FloatRect expandedRect = rect;
-    expandedRect.inflateX(extraSize.width() / 2);
-    expandedRect.inflateY(extraSize.height() / 2);
-
-    if (expandedRect.x() < constrainingRect.x())
-        expandedRect.setX(constrainingRect.x());
-    else if (expandedRect.maxX() > constrainingRect.maxX())
-        expandedRect.setX(constrainingRect.maxX() - expandedRect.width());
-    
-    if (expandedRect.y() < constrainingRect.y())
-        expandedRect.setY(constrainingRect.y());
-    else if (expandedRect.maxY() > constrainingRect.maxY())
-        expandedRect.setY(constrainingRect.maxY() - expandedRect.height());
-    
-    return intersection(expandedRect, constrainingRect);
-}
-#endif
-
-FloatRect TileController::adjustTileCoverageRect(const FloatRect& coverageRect, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, bool sizeChanged) const
+FloatRect TileController::adjustTileCoverageRect(const FloatRect& coverageRect, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, bool sizeChanged)
 {
     // If the old visible rect is empty, we have no information about how the visible area is changing
     // (maybe the layer was just created), so don't attempt to expand. Also don't attempt to expand
@@ -449,16 +425,63 @@ FloatRect TileController::adjustTileCoverageRect(const FloatRect& coverageRect,
     return unionRect(coverageRect, expandedRect);
 }
 
-FloatRect TileController::adjustTileCoverageRectForScrolling(const FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& visibleRect, float contentsScale) const
+#if !PLATFORM(IOS_FAMILY)
+// Coverage expansion for less memory-constrained devices.
+// Kept separate to preserve historical behavior; should be merged with adjustTileCoverageWithScrollingVelocity eventually.
+FloatRect TileController::adjustTileCoverageForDesktopPageScrolling(const FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& visibleRect) const
 {
-    // If the page is not in a window (for example if it's in a background tab), we limit the tile coverage rect to the visible rect.
-    if (!m_isInWindow)
-        return visibleRect;
+    // FIXME: look at how far the document can scroll in each dimension.
+    FloatSize coverageSize = visibleRect.size();
 
-#if PLATFORM(IOS_FAMILY)
-    // FIXME: unify the iOS and Mac code.
-    UNUSED_PARAM(previousVisibleRect);
-    
+    bool largeVisibleRectChange = !previousVisibleRect.isEmpty() && !visibleRect.intersects(previousVisibleRect);
+
+    // Inflate the coverage rect so that it covers 2x of the visible width and 3x of the visible height.
+    // These values were chosen because it's more common to have tall pages and to scroll vertically,
+    // so we keep more tiles above and below the current area.
+    float widthScale = 1;
+    float heightScale = 1;
+
+    if (m_tileCoverage & CoverageForHorizontalScrolling && !largeVisibleRectChange)
+        widthScale = 2;
+
+    if (m_tileCoverage & CoverageForVerticalScrolling && !largeVisibleRectChange)
+        heightScale = 3;
+
+    coverageSize.scale(widthScale, heightScale);
+
+    FloatRect coverageBounds = boundsForSize(newSize);
+
+    // Return 'rect' padded evenly on all sides to achieve 'newSize', but make the padding uneven to contain within constrainingRect.
+    auto expandRectWithinRect = [](const FloatRect& rect, const FloatSize& newSize, const FloatRect& constrainingRect) {
+        ASSERT(newSize.width() >= rect.width() && newSize.height() >= rect.height());
+
+        FloatSize extraSize = newSize - rect.size();
+        
+        FloatRect expandedRect = rect;
+        expandedRect.inflateX(extraSize.width() / 2);
+        expandedRect.inflateY(extraSize.height() / 2);
+
+        if (expandedRect.x() < constrainingRect.x())
+            expandedRect.setX(constrainingRect.x());
+        else if (expandedRect.maxX() > constrainingRect.maxX())
+            expandedRect.setX(constrainingRect.maxX() - expandedRect.width());
+        
+        if (expandedRect.y() < constrainingRect.y())
+            expandedRect.setY(constrainingRect.y());
+        else if (expandedRect.maxY() > constrainingRect.maxY())
+            expandedRect.setY(constrainingRect.maxY() - expandedRect.height());
+        
+        return intersection(expandedRect, constrainingRect);
+    };
+
+    FloatRect coverage = expandRectWithinRect(visibleRect, coverageSize, coverageBounds);
+    LOG_WITH_STREAM(Tiling, stream << "TileController::adjustTileCoverageForDesktopPageScrolling newSize=" << newSize << " mode " << m_tileCoverage << " expanded to " << coverageSize << " bounds with margin " << coverageBounds << " coverage " << coverage);
+    return unionRect(coverageRect, coverage);
+}
+#endif
+
+FloatRect TileController::adjustTileCoverageWithScrollingVelocity(const FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& visibleRect, float contentsScale) const
+{
     if (m_tileCoverage == CoverageForVisibleArea || MemoryPressureHandler::singleton().isUnderMemoryPressure())
         return visibleRect;
 
@@ -508,37 +531,37 @@ FloatRect TileController::adjustTileCoverageRectForScrolling(const FloatRect& co
     if (futureRect.y() < 0)
         futureRect.setY(0);
 
-    LOG_WITH_STREAM(Tiling, stream << "TileController " << this << " computeTileCoverageRect - coverage " << coverageRect << " expanded to " << unionRect(coverageRect, futureRect) << " velocity " << m_velocity);
+    LOG_WITH_STREAM(Tiling, stream << "TileController " << this << " adjustTileCoverageForScrolling - coverage " << coverageRect << " expanded to " << unionRect(coverageRect, futureRect) << " velocity " << m_velocity);
 
     return unionRect(coverageRect, futureRect);
-#else
-    UNUSED_PARAM(contentsScale);
+}
 
-    // FIXME: look at how far the document can scroll in each dimension.
-    FloatSize coverageSize = visibleRect.size();
+FloatRect TileController::adjustTileCoverageRectForScrolling(const FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& visibleRect, float contentsScale)
+{
+    // If the page is not in a window (for example if it's in a background tab), we limit the tile coverage rect to the visible rect.
+    if (!m_isInWindow)
+        return visibleRect;
 
-    bool largeVisibleRectChange = !previousVisibleRect.isEmpty() && !visibleRect.intersects(previousVisibleRect);
+#if !PLATFORM(IOS_FAMILY)
+    if (m_tileCacheLayer->isPageTiledBackingLayer())
+        return adjustTileCoverageForDesktopPageScrolling(coverageRect, newSize, previousVisibleRect, visibleRect);
+#else
+    UNUSED_PARAM(previousVisibleRect);
+#endif
 
-    // Inflate the coverage rect so that it covers 2x of the visible width and 3x of the visible height.
-    // These values were chosen because it's more common to have tall pages and to scroll vertically,
-    // so we keep more tiles above and below the current area.
-    float widthScale = 1;
-    float heightScale = 1;
+    auto computeVelocityIfNecessary = [&](FloatPoint scrollOffset) {
+        if (m_haveExternalVelocityData)
+            return;
 
-    if (m_tileCoverage & CoverageForHorizontalScrolling && !largeVisibleRectChange)
-        widthScale = 2;
+        if (!m_historicalVelocityData)
+            m_historicalVelocityData = std::make_unique<HistoricalVelocityData>();
 
-    if (m_tileCoverage & CoverageForVerticalScrolling && !largeVisibleRectChange)
-        heightScale = 3;
+        m_velocity = m_historicalVelocityData->velocityForNewData(scrollOffset, contentsScale, MonotonicTime::now());
+    };
     
-    coverageSize.scale(widthScale, heightScale);
+    computeVelocityIfNecessary(visibleRect.location());
 
-    FloatRect coverageBounds = boundsForSize(newSize);
-    
-    FloatRect coverage = expandRectWithinRect(visibleRect, coverageSize, coverageBounds);
-    LOG_WITH_STREAM(Tiling, stream << "TileController::computeTileCoverageRect newSize=" << newSize << " mode " << m_tileCoverage << " expanded to " << coverageSize << " bounds with margin " << coverageBounds << " coverage " << coverage);
-    return unionRect(coverageRect, coverage);
-#endif
+    return adjustTileCoverageWithScrollingVelocity(coverageRect, newSize, visibleRect, contentsScale);
 }
 
 void TileController::scheduleTileRevalidation(Seconds interval)
index 8dfc432..496c483 100644 (file)
@@ -122,8 +122,8 @@ public:
     int rightMarginWidth() const final;
     TileCoverage tileCoverage() const final { return m_tileCoverage; }
 
-    FloatRect adjustTileCoverageRect(const FloatRect& coverageRect, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, bool sizeChanged) const final;
-    FloatRect adjustTileCoverageRectForScrolling(const FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, float contentsScale) const final;
+    FloatRect adjustTileCoverageRect(const FloatRect& coverageRect, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, bool sizeChanged) final;
+    FloatRect adjustTileCoverageRectForScrolling(const FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, float contentsScale) final;
 
     bool scrollingPerformanceLoggingEnabled() const final { return m_scrollingPerformanceLoggingEnabled; }
 
@@ -190,7 +190,13 @@ private:
 
     void notePendingTileSizeChange();
     void tileSizeChangeTimerFired();
-    
+
+#if !PLATFORM(IOS_FAMILY)
+    FloatRect adjustTileCoverageForDesktopPageScrolling(const FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& visibleRect) const;
+#endif
+
+    FloatRect adjustTileCoverageWithScrollingVelocity(const FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& visibleRect, float contentsScale) const;
+
     IntRect boundsForSize(const FloatSize&) const;
 
     PlatformCALayerClient* owningGraphicsLayer() const { return m_tileCacheLayer->owner(); }
@@ -205,6 +211,8 @@ private:
     std::unique_ptr<TileGrid> m_tileGrid;
     std::unique_ptr<TileGrid> m_zoomedOutTileGrid;
 
+    std::unique_ptr<HistoricalVelocityData> m_historicalVelocityData; // Used when we track velocity internally.
+
     FloatRect m_visibleRect; // Only used for scroll performance logging.
     Optional<FloatRect> m_layoutViewportRect; // Only used by the tiled scrolling indicator.
     FloatRect m_coverageRect;
@@ -214,7 +222,7 @@ private:
     DeferrableOneShotTimer m_tileSizeChangeTimer;
 
     TileCoverage m_tileCoverage { CoverageForVisibleArea };
-    
+
     VelocityData m_velocity;
 
     int m_marginSize { kDefaultTileSize };
@@ -236,6 +244,7 @@ private:
     bool m_hasTilesWithTemporaryScaleFactor { false }; // Used to make low-res tiles when zooming.
     bool m_inLiveResize { false };
     bool m_tileSizeLocked { false };
+    bool m_haveExternalVelocityData { false };
     bool m_isTileSizeUpdateDelayDisabledForTesting { false };
 
     Color m_tileDebugBorderColor;
index 6ddc70d..5e07bc7 100644 (file)
@@ -450,6 +450,8 @@ public:
     void scrollRectToVisible(const LayoutRect& absoluteRect, bool insideFixed, const ScrollRectToVisibleOptions&);
 
     bool scrollsOverflow() const;
+    bool hasScrollableHorizontalOverflow() const;
+    bool hasScrollableVerticalOverflow() const;
     bool hasScrollbars() const { return m_hBar || m_vBar; }
     void setHasHorizontalScrollbar(bool);
     void setHasVerticalScrollbar(bool);
@@ -1066,8 +1068,6 @@ private:
     void computeScrollDimensions();
     bool hasHorizontalOverflow() const;
     bool hasVerticalOverflow() const;
-    bool hasScrollableHorizontalOverflow() const;
-    bool hasScrollableVerticalOverflow() const;
 
     bool showsOverflowControls() const;
 
index 4b46e8c..048bee1 100644 (file)
@@ -355,15 +355,14 @@ TiledBacking* RenderLayerBacking::tiledBacking() const
     return m_graphicsLayer->tiledBacking();
 }
 
-static TiledBacking::TileCoverage computePageTiledBackingCoverage(RenderLayerBacking* backing)
+static TiledBacking::TileCoverage computePageTiledBackingCoverage(const RenderLayer& layer)
 {
-    // FIXME: When we use TiledBacking for overflow, this should look at RenderView scrollability.
-    auto& frameView = backing->owningLayer().renderer().view().frameView();
-
     // If the page is non-visible, don't incur the cost of keeping extra tiles for scrolling.
-    if (!backing->owningLayer().page().isVisible())
+    if (!layer.page().isVisible())
         return TiledBacking::CoverageForVisibleArea;
 
+    auto& frameView = layer.renderer().view().frameView();
+
     TiledBacking::TileCoverage tileCoverage = TiledBacking::CoverageForVisibleArea;
     bool useMinimalTilesDuringLiveResize = frameView.inLiveResize();
     if (frameView.speculativeTilingEnabled() && !useMinimalTilesDuringLiveResize) {
@@ -377,13 +376,39 @@ static TiledBacking::TileCoverage computePageTiledBackingCoverage(RenderLayerBac
     return tileCoverage;
 }
 
+static TiledBacking::TileCoverage computeOverflowTiledBackingCoverage(const RenderLayer& layer)
+{
+    // If the page is non-visible, don't incur the cost of keeping extra tiles for scrolling.
+    if (!layer.page().isVisible())
+        return TiledBacking::CoverageForVisibleArea;
+    
+    auto& frameView = layer.renderer().view().frameView();
+
+    TiledBacking::TileCoverage tileCoverage = TiledBacking::CoverageForVisibleArea;
+    bool useMinimalTilesDuringLiveResize = frameView.inLiveResize();
+    if (!useMinimalTilesDuringLiveResize) {
+        if (layer.hasScrollableHorizontalOverflow())
+            tileCoverage |= TiledBacking::CoverageForHorizontalScrolling;
+
+        if (layer.hasScrollableVerticalOverflow())
+            tileCoverage |= TiledBacking::CoverageForVerticalScrolling;
+    }
+    return tileCoverage;
+}
+
 void RenderLayerBacking::adjustTiledBackingCoverage()
 {
-    if (!m_isFrameLayerWithTiledBacking)
-        return;
+    if (m_isFrameLayerWithTiledBacking) {
+        auto tileCoverage = computePageTiledBackingCoverage(m_owningLayer);
+        tiledBacking()->setTileCoverage(tileCoverage);
+    }
 
-    TiledBacking::TileCoverage tileCoverage = computePageTiledBackingCoverage(this);
-    tiledBacking()->setTileCoverage(tileCoverage);
+    if (m_owningLayer.hasCompositedScrollableOverflow() && m_scrolledContentsLayer) {
+        if (auto* tiledBacking = m_scrolledContentsLayer->tiledBacking()) {
+            auto tileCoverage = computeOverflowTiledBackingCoverage(m_owningLayer);
+            tiledBacking->setTileCoverage(tileCoverage);
+        }
+    }
 }
 
 void RenderLayerBacking::setTiledBackingHasMargins(bool hasExtendedBackgroundOnLeftAndRight, bool hasExtendedBackgroundOnTopAndBottom)
@@ -1258,6 +1283,8 @@ void RenderLayerBacking::updateGeometry()
             m_foregroundLayer->setSize(m_scrolledContentsLayer->size());
             m_foregroundLayer->setOffsetFromRenderer(m_scrolledContentsLayer->offsetFromRenderer() - toLayoutSize(m_scrolledContentsLayer->scrollOffset()));
         }
+        
+        adjustTiledBackingCoverage();
     }
 
     // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.