Adjust tile coverage with margin tiles, and tidy up the indicator
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 5 Jan 2016 22:09:20 +0000 (22:09 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 5 Jan 2016 22:09:20 +0000 (22:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=152742

Reviewed by Beth Dakin.

Source/WebCore:

The tile coverage rect was unfeasibly large when margin tiles are present, and
could be bigger than the layer itself, making the indicator look odd.

Fix by improving the logic in TileController::adjustTileCoverageRect(): this
now first extends the visible rect for scrolling, and then constrains it
within the bounds with margin padding. It also unites with the passed-in
coverageRect, ensuring that we don't lose information about overhang for
margin tile coverage.

Second, update the tiled scrolling indicator when the visible rect changes,
and coalesce the map updates on a timer.

* platform/graphics/TiledBacking.h:
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::adjustCoverageRect):
* platform/graphics/ca/TileController.cpp:
(WebCore::TileController::setVisibleRect):
(WebCore::TileController::setTiledScrollingIndicatorPosition):
(WebCore::expandRectWithinRect):
(WebCore::TileController::adjustTileCoverageRect):
(WebCore::TileController::updateTileCoverageMap):
(WebCore::TileController::computeTileCoverageRect): Deleted.
* platform/graphics/ca/TileController.h:
* platform/graphics/ca/TileCoverageMap.cpp:
(WebCore::TileCoverageMap::TileCoverageMap):
(WebCore::TileCoverageMap::setNeedsUpdate):
(WebCore::TileCoverageMap::updateTimerFired):
* platform/graphics/ca/TileCoverageMap.h:

LayoutTests:

New baselines. simple-document-with-margin-tiles.html needs to wait for over 0.5s
for the FrameView::enableSpeculativeTilingIfNeeded() timer to fire before
dumping coverage (ouch).

* tiled-drawing/scrolling/fast-scroll-iframe-latched-iframe-expected.txt:
* tiled-drawing/scrolling/fast-scroll-iframe-latched-iframe-with-handler-expected.txt:
* tiled-drawing/scrolling/fast-scroll-iframe-latched-mainframe-expected.txt:
* tiled-drawing/scrolling/fast-scroll-iframe-latched-mainframe-with-handler-expected.txt:
* tiled-drawing/simple-document-with-margin-tiles.html:

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

14 files changed:
LayoutTests/ChangeLog
LayoutTests/tiled-drawing/scrolling/fast-scroll-iframe-latched-iframe-expected.txt
LayoutTests/tiled-drawing/scrolling/fast-scroll-iframe-latched-iframe-with-handler-expected.txt
LayoutTests/tiled-drawing/scrolling/fast-scroll-iframe-latched-mainframe-expected.txt
LayoutTests/tiled-drawing/scrolling/fast-scroll-iframe-latched-mainframe-with-handler-expected.txt
LayoutTests/tiled-drawing/simple-document-with-margin-tiles-expected.txt
LayoutTests/tiled-drawing/simple-document-with-margin-tiles.html
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/TiledBacking.h
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
Source/WebCore/platform/graphics/ca/TileController.cpp
Source/WebCore/platform/graphics/ca/TileController.h
Source/WebCore/platform/graphics/ca/TileCoverageMap.cpp
Source/WebCore/platform/graphics/ca/TileCoverageMap.h

index 156347e..c7089b4 100644 (file)
@@ -1,3 +1,20 @@
+2016-01-05  Simon Fraser  <simon.fraser@apple.com>
+
+        Adjust tile coverage with margin tiles, and tidy up the indicator
+        https://bugs.webkit.org/show_bug.cgi?id=152742
+
+        Reviewed by Beth Dakin.
+
+        New baselines. simple-document-with-margin-tiles.html needs to wait for over 0.5s
+        for the FrameView::enableSpeculativeTilingIfNeeded() timer to fire before
+        dumping coverage (ouch).
+
+        * tiled-drawing/scrolling/fast-scroll-iframe-latched-iframe-expected.txt:
+        * tiled-drawing/scrolling/fast-scroll-iframe-latched-iframe-with-handler-expected.txt:
+        * tiled-drawing/scrolling/fast-scroll-iframe-latched-mainframe-expected.txt:
+        * tiled-drawing/scrolling/fast-scroll-iframe-latched-mainframe-with-handler-expected.txt:
+        * tiled-drawing/simple-document-with-margin-tiles.html:
+
 2016-01-05  Brady Eidson  <beidson@apple.com>
 
         IDB test gardening.
index d8e3e3d..9625c20 100644 (file)
@@ -21,7 +21,7 @@ PASS Page did not receive wheel events.
       (bounds 785.00 2266.00)
       (contentsOpaque 1)
       (visible rect 0.00, 0.00 785.00 x 600.00)
-      (coverage rect 0.00, 0.00 1570.00 x 1800.00)
+      (coverage rect 0.00, 0.00 785.00 x 1800.00)
       (intersects coverage rect 1)
       (contentsScale 1.00)
       (tile cache coverage 0, 0 785 x 2048)
index d8e3e3d..9625c20 100644 (file)
@@ -21,7 +21,7 @@ PASS Page did not receive wheel events.
       (bounds 785.00 2266.00)
       (contentsOpaque 1)
       (visible rect 0.00, 0.00 785.00 x 600.00)
-      (coverage rect 0.00, 0.00 1570.00 x 1800.00)
+      (coverage rect 0.00, 0.00 785.00 x 1800.00)
       (intersects coverage rect 1)
       (contentsScale 1.00)
       (tile cache coverage 0, 0 785 x 2048)
index b40ed20..19b94a3 100644 (file)
@@ -21,7 +21,7 @@ PASS IFrame did not receive wheel events.
       (bounds 785.00 2266.00)
       (contentsOpaque 1)
       (visible rect 0.00, 70.00 785.00 x 600.00)
-      (coverage rect 0.00, 0.00 1570.00 x 1800.00)
+      (coverage rect 0.00, 0.00 785.00 x 1800.00)
       (intersects coverage rect 1)
       (contentsScale 1.00)
       (tile cache coverage 0, 0 785 x 2048)
index b40ed20..19b94a3 100644 (file)
@@ -21,7 +21,7 @@ PASS IFrame did not receive wheel events.
       (bounds 785.00 2266.00)
       (contentsOpaque 1)
       (visible rect 0.00, 70.00 785.00 x 600.00)
-      (coverage rect 0.00, 0.00 1570.00 x 1800.00)
+      (coverage rect 0.00, 0.00 785.00 x 1800.00)
       (intersects coverage rect 1)
       (contentsScale 1.00)
       (tile cache coverage 0, 0 785 x 2048)
index f83d674..063c128 100644 (file)
@@ -10,7 +10,7 @@
       (bounds 1208.00 2021.00)
       (contentsOpaque 1)
       (visible rect 0.00, 0.00 785.00 x 585.00)
-      (coverage rect -512.00, -512.00 1809.00 x 1609.00)
+      (coverage rect -392.50, -512.00 1570.00 x 1755.00)
       (intersects coverage rect 1)
       (contentsScale 1.00)
       (tile cache coverage -512, -512 2048 x 2048)
index 912bb50..6475780 100644 (file)
         }
     </style>
     <script>
-        if (window.testRunner)
+        if (window.testRunner) {
             testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
 
         function doTest()
         {
-            if (window.internals) {
+            if (window.internals)
                 window.internals.settings.setBackgroundShouldExtendBeyondPage(true);
-                document.getElementById('layers').innerText = internals.layerTreeAsText(document,
-                    internals.LAYER_TREE_INCLUDES_VISIBLE_RECTS | internals.LAYER_TREE_INCLUDES_TILE_CACHES);
-            }
+
+            // FrameView::enableSpeculativeTilingIfNeeded() uses a 0.5s timer to enable speculative tiling.
+            window.setTimeout(function() {
+                if (window.internals) {
+                    document.getElementById('layers').innerText = internals.layerTreeAsText(document,
+                        internals.LAYER_TREE_INCLUDES_VISIBLE_RECTS | internals.LAYER_TREE_INCLUDES_TILE_CACHES);
+                }
+                
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }, 550);
         }
         window.addEventListener('load', doTest, false);
     </script>
index 2d63979..952cf21 100644 (file)
@@ -1,3 +1,39 @@
+2016-01-05  Simon Fraser  <simon.fraser@apple.com>
+
+        Adjust tile coverage with margin tiles, and tidy up the indicator
+        https://bugs.webkit.org/show_bug.cgi?id=152742
+
+        Reviewed by Beth Dakin.
+
+        The tile coverage rect was unfeasibly large when margin tiles are present, and
+        could be bigger than the layer itself, making the indicator look odd.
+
+        Fix by improving the logic in TileController::adjustTileCoverageRect(): this
+        now first extends the visible rect for scrolling, and then constrains it
+        within the bounds with margin padding. It also unites with the passed-in
+        coverageRect, ensuring that we don't lose information about overhang for
+        margin tile coverage.
+
+        Second, update the tiled scrolling indicator when the visible rect changes,
+        and coalesce the map updates on a timer.
+
+        * platform/graphics/TiledBacking.h:
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::adjustCoverageRect):
+        * platform/graphics/ca/TileController.cpp:
+        (WebCore::TileController::setVisibleRect):
+        (WebCore::TileController::setTiledScrollingIndicatorPosition):
+        (WebCore::expandRectWithinRect):
+        (WebCore::TileController::adjustTileCoverageRect):
+        (WebCore::TileController::updateTileCoverageMap):
+        (WebCore::TileController::computeTileCoverageRect): Deleted.
+        * platform/graphics/ca/TileController.h:
+        * platform/graphics/ca/TileCoverageMap.cpp:
+        (WebCore::TileCoverageMap::TileCoverageMap):
+        (WebCore::TileCoverageMap::setNeedsUpdate):
+        (WebCore::TileCoverageMap::updateTimerFired):
+        * platform/graphics/ca/TileCoverageMap.h:
+
 2016-01-05  Antti Koivisto  <antti@apple.com>
 
         Remove selector filter update calls from Element child parsing callbacks
index 6cb27bf..1add86b 100644 (file)
@@ -110,7 +110,7 @@ public:
     virtual void setTileCoverage(TileCoverage) = 0;
     virtual TileCoverage tileCoverage() const = 0;
 
-    virtual FloatRect computeTileCoverageRect(const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, float contentsScale) const = 0;
+    virtual void adjustTileCoverageRect(FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, float contentsScale) const = 0;
 
     virtual IntSize tileSize() const = 0;
 
index b272951..9dc7cd3 100644 (file)
@@ -32,6 +32,7 @@
 #include "FloatRect.h"
 #include "GraphicsLayerFactory.h"
 #include "Image.h"
+#include "Logging.h"
 #include "PlatformCAFilters.h"
 #include "PlatformCALayer.h"
 #include "RotateTransformOperation.h"
@@ -1243,7 +1244,7 @@ bool GraphicsLayerCA::adjustCoverageRect(VisibleAndCoverageRects& rects, const F
     // ways of computing coverage.
     switch (type()) {
     case Type::PageTiledBacking:
-        coverageRect = tiledBacking()->computeTileCoverageRect(size(), oldVisibleRect, rects.visibleRect, pageScaleFactor() * deviceScaleFactor());
+        tiledBacking()->adjustTileCoverageRect(coverageRect, size(), oldVisibleRect, rects.visibleRect, pageScaleFactor() * deviceScaleFactor());
         break;
     case Type::Normal:
         if (m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
index 5f57be9..ac70d9d 100644 (file)
 #include "TileController.h"
 
 #include "IntRect.h"
+#include "Logging.h"
 #include "PlatformCALayer.h"
 #include "Region.h"
+#include "TextStream.h"
 #include "TileCoverageMap.h"
 #include "TileGrid.h"
 #include <utility>
@@ -185,7 +187,11 @@ void TileController::setTilesOpaque(bool opaque)
 
 void TileController::setVisibleRect(const FloatRect& rect)
 {
+    if (rect == m_visibleRect)
+        return;
+
     m_visibleRect = rect;
+    updateTileCoverageMap();
 }
 
 void TileController::setCoverageRect(const FloatRect& rect)
@@ -225,8 +231,9 @@ void TileController::setTiledScrollingIndicatorPosition(const FloatPoint& positi
 {
     if (!m_coverageMap)
         return;
+
     m_coverageMap->setPosition(position);
-    m_coverageMap->update();
+    updateTileCoverageMap();
 }
 
 void TileController::prepopulateRect(const FloatRect& rect)
@@ -314,18 +321,48 @@ IntRect TileController::boundsAtLastRevalidateWithoutMargin() const
     return boundsWithoutMargin;
 }
 
-FloatRect TileController::computeTileCoverageRect(const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& visibleRect, float contentsScale) const
+#if !PLATFORM(IOS)
+// 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
+
+void TileController::adjustTileCoverageRect(FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& visibleRect, float contentsScale) 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;
+    if (!m_isInWindow) {
+        coverageRect = visibleRect;
+        return;
+    }
 
 #if PLATFORM(IOS)
     // FIXME: unify the iOS and Mac code.
     UNUSED_PARAM(previousVisibleRect);
     
-    if (m_tileCoverage == CoverageForVisibleArea || MemoryPressureHandler::singleton().isUnderMemoryPressure())
-        return visibleRect;
+    if (m_tileCoverage == CoverageForVisibleArea || MemoryPressureHandler::singleton().isUnderMemoryPressure()) {
+        coverageRect = visibleRect;
+        return;
+    }
 
     double horizontalMargin = tileSize().width() / contentsScale;
     double verticalMargin = tileSize().height() / contentsScale;
@@ -351,8 +388,10 @@ FloatRect TileController::computeTileCoverageRect(const FloatSize& newSize, cons
     }
 
     if (!m_velocity.horizontalVelocity && !m_velocity.verticalVelocity) {
-        if (m_velocity.scaleChangeRate > 0)
-            return visibleRect;
+        if (m_velocity.scaleChangeRate > 0) {
+            coverageRect = visibleRect;
+            return;
+        }
         futureRect.setWidth(futureRect.width() + horizontalMargin);
         futureRect.setHeight(futureRect.height() + verticalMargin);
         futureRect.setX(futureRect.x() - horizontalMargin / 2);
@@ -371,41 +410,35 @@ FloatRect TileController::computeTileCoverageRect(const FloatSize& newSize, cons
     if (futureRect.y() < 0)
         futureRect.setY(0);
 
-    return futureRect;
+    coverageRect.unite(futureRect);
+    return;
 #else
     UNUSED_PARAM(contentsScale);
 
     // FIXME: look at how far the document can scroll in each dimension.
-    float coverageHorizontalSize = visibleRect.width();
-    float coverageVerticalSize = visibleRect.height();
+    FloatSize coverageSize = visibleRect.size();
 
     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)
-        coverageHorizontalSize *= 2;
+        widthScale = 2;
 
     if (m_tileCoverage & CoverageForVerticalScrolling && !largeVisibleRectChange)
-        coverageVerticalSize *= 3;
-
-    coverageVerticalSize += topMarginHeight() + bottomMarginHeight();
-    coverageHorizontalSize += leftMarginWidth() + rightMarginWidth();
+        heightScale = 3;
+    
+    coverageSize.scale(widthScale, heightScale);
 
-    // Can't use m_tileCacheLayer->bounds() here, because the size of the underlying platform layer
-    // hasn't been updated for the current commit.
     FloatRect coverageBounds = boundsForSize(newSize);
-    float coverageLeft = visibleRect.x() - (coverageHorizontalSize - visibleRect.width()) / 2;
-    coverageLeft = std::min(coverageLeft, coverageBounds.maxX() - coverageHorizontalSize);
-    coverageLeft = std::max(coverageLeft, coverageBounds.x());
-
-    float coverageTop = visibleRect.y() - (coverageVerticalSize - visibleRect.height()) / 2;
-    coverageTop = std::min(coverageTop, coverageBounds.maxY() - coverageVerticalSize);
-    coverageTop = std::max(coverageTop, coverageBounds.y());
-
-    return FloatRect(coverageLeft, coverageTop, coverageHorizontalSize, coverageVerticalSize);
+    
+    FloatRect coverage = expandRectWithinRect(visibleRect, coverageSize, coverageBounds);
+    LOG_WITH_STREAM(Scrolling, stream << "TileController::computeTileCoverageRect newSize=" << newSize << " mode " << m_tileCoverage << " expanded to " << coverageSize << " bounds with margin " << coverageBounds << " coverage " << coverage);
+    coverageRect.unite(coverage);
 #endif
 }
 
@@ -500,7 +533,7 @@ void TileController::setNeedsRevalidateTiles()
 void TileController::updateTileCoverageMap()
 {
     if (m_coverageMap)
-        m_coverageMap->update();
+        m_coverageMap->setNeedsUpdate();
 }
 
 IntRect TileController::tileGridExtent() const
index 62d3108..99c4749 100644 (file)
@@ -106,7 +106,7 @@ public:
     virtual int leftMarginWidth() const override;
     virtual int rightMarginWidth() const override;
     virtual TileCoverage tileCoverage() const override { return m_tileCoverage; }
-    virtual FloatRect computeTileCoverageRect(const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, float contentsScale) const override;
+    virtual void adjustTileCoverageRect(FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect, float contentsScale) const override;
     virtual bool unparentsOffscreenTiles() const override { return m_unparentsOffscreenTiles; }
     virtual bool scrollingPerformanceLoggingEnabled() const override { return m_scrollingPerformanceLoggingEnabled; }
 
index ec67b89..1e00047 100644 (file)
@@ -34,6 +34,7 @@ namespace WebCore {
 
 TileCoverageMap::TileCoverageMap(const TileController& controller)
     : m_controller(controller)
+    , m_updateTimer(*this, &TileCoverageMap::updateTimerFired)
     , m_layer(*controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeSimpleLayer, this))
     , m_visibleRectIndicatorLayer(*controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
     , m_coverageRectIndicatorLayer(*controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
@@ -46,10 +47,12 @@ TileCoverageMap::TileCoverageMap(const TileController& controller)
     m_layer.get().setPosition(FloatPoint(2, 2));
     m_layer.get().setContentsScale(m_controller.deviceScaleFactor());
 
+    m_visibleRectIndicatorLayer.get().setName("visible rect indicator");
     m_visibleRectIndicatorLayer.get().setBorderWidth(2);
     m_visibleRectIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
     m_visibleRectIndicatorLayer.get().setBorderColor(Color(255, 0, 0));
     
+    m_coverageRectIndicatorLayer.get().setName("coverage indicator");
     m_coverageRectIndicatorLayer.get().setBorderWidth(2);
     m_coverageRectIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
     m_coverageRectIndicatorLayer.get().setBorderColor(Color(0, 0, 128));
@@ -65,6 +68,17 @@ TileCoverageMap::~TileCoverageMap()
     m_layer.get().setOwner(nullptr);
 }
 
+void TileCoverageMap::setNeedsUpdate()
+{
+    if (!m_updateTimer.isActive())
+        m_updateTimer.startOneShot(0);
+}
+
+void TileCoverageMap::updateTimerFired()
+{
+    update();
+}
+
 void TileCoverageMap::update()
 {
     FloatRect containerBounds = m_controller.bounds();
index 5943753..68e5bb4 100644 (file)
@@ -30,6 +30,7 @@
 #include "IntRect.h"
 #include "PlatformCALayer.h"
 #include "PlatformCALayerClient.h"
+#include "Timer.h"
 #include <wtf/Noncopyable.h>
 #include <wtf/RetainPtr.h>
 
@@ -53,6 +54,8 @@ public:
 
     void setDeviceScaleFactor(float);
 
+    void setNeedsUpdate();
+
 private:
     // PlatformCALayerClient
     virtual GraphicsLayer::CompositingCoordinatesOrientation platformCALayerContentsOrientation() const override { return GraphicsLayer::CompositingCoordinatesTopDown; }
@@ -61,7 +64,11 @@ private:
     virtual void platformCALayerPaintContents(PlatformCALayer*, GraphicsContext&, const FloatRect&) override;
     virtual float platformCALayerDeviceScaleFactor() const override;
 
+    void updateTimerFired();
+    
     const TileController& m_controller;
+    
+    Timer m_updateTimer;
 
     Ref<PlatformCALayer> m_layer;
     Ref<PlatformCALayer> m_visibleRectIndicatorLayer;