[Qt] Decide when to apply a scrolled position to the viewport based on the rect cover...
authorjocelyn.turcotte@digia.com <jocelyn.turcotte@digia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 1 Oct 2012 11:19:01 +0000 (11:19 +0000)
committerjocelyn.turcotte@digia.com <jocelyn.turcotte@digia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 1 Oct 2012 11:19:01 +0000 (11:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=97777

Reviewed by Kenneth Rohde Christiansen.

Source/WebCore:

* platform/graphics/TiledBackingStore.cpp:
(WebCore::TiledBackingStore::createTiles):
* platform/graphics/TiledBackingStore.h:
(WebCore::TiledBackingStore::coverRect):
(WebCore::TiledBackingStore::setCoverRect):
(TiledBackingStore):

Source/WebKit2:

This patch achieves two things:
- Apply a short scroll position request directly if we already have rendered tiles
  at this position.
- Since our visible rect request is asynchronous, the next frame might not always
  be the one covering this position. This will wait for a frame that does to apply it.

* UIProcess/API/qt/raw/qrawwebview_p_p.h:
(QRawWebViewPrivate::didRenderFrame):
* UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp:
(WebKit::LayerTreeCoordinatorProxy::didRenderFrame):
* UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h:
(LayerTreeCoordinatorProxy):
* UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.messages.in:
* UIProcess/PageClient.h:
(PageClient):
* UIProcess/PageViewportController.cpp:
(WebKit::PageViewportController::didCommitLoad):
(WebKit::PageViewportController::didRenderFrame):
(WebKit::PageViewportController::pageDidRequestScroll):
* UIProcess/PageViewportController.h:
(PageViewportController):
* UIProcess/WebPageProxy.h:
(WebPageProxy):
* UIProcess/qt/QtPageClient.cpp:
(WebKit::QtPageClient::didRenderFrame):
* UIProcess/qt/QtPageClient.h:
(QtPageClient):
* UIProcess/qt/WebPageProxyQt.cpp:
(WebKit::WebPageProxy::didRenderFrame):
* WebProcess/WebPage/CoordinatedGraphics/CoordinatedGraphicsLayer.h:
(WebCore::CoordinatedGraphicsLayer::coverRect):
* WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.cpp:
(WebKit::LayerTreeCoordinator::flushPendingLayerChanges):

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

17 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/TiledBackingStore.cpp
Source/WebCore/platform/graphics/TiledBackingStore.h
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/qt/raw/qrawwebview_p_p.h
Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp
Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h
Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.messages.in
Source/WebKit2/UIProcess/PageClient.h
Source/WebKit2/UIProcess/PageViewportController.cpp
Source/WebKit2/UIProcess/PageViewportController.h
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/qt/QtPageClient.cpp
Source/WebKit2/UIProcess/qt/QtPageClient.h
Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp
Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/CoordinatedGraphicsLayer.h
Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.cpp

index d1f8a06..e546fcf 100644 (file)
@@ -1,3 +1,17 @@
+2012-09-27  Jocelyn Turcotte  <jocelyn.turcotte@digia.com>
+
+        [Qt] Decide when to apply a scrolled position to the viewport based on the rect covered by the tiles
+        https://bugs.webkit.org/show_bug.cgi?id=97777
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        * platform/graphics/TiledBackingStore.cpp:
+        (WebCore::TiledBackingStore::createTiles):
+        * platform/graphics/TiledBackingStore.h:
+        (WebCore::TiledBackingStore::coverRect):
+        (WebCore::TiledBackingStore::setCoverRect):
+        (TiledBackingStore):
+
 2012-10-01  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         Unreviewed. Fix make distcheck.
index a19f6a6..a793030 100644 (file)
@@ -255,10 +255,11 @@ void TiledBackingStore::createTiles()
     if (visibleRect.isEmpty())
         return;
 
-    IntRect keepRect;
     IntRect coverRect;
+    IntRect keepRect;
     computeCoverAndKeepRect(visibleRect, coverRect, keepRect);
 
+    setCoverRect(coverRect);
     setKeepRect(keepRect);
 
     // Resize tiles at the edge in case the contents size has changed, but only do so
index 8d662e4..b3c365c 100644 (file)
@@ -72,6 +72,7 @@ public:
     Tile::Coordinate tileCoordinateForPoint(const IntPoint&) const;
     double tileDistance(const IntRect& viewport, const Tile::Coordinate&) const;
 
+    IntRect coverRect() const { return m_coverRect; }
     bool visibleAreaIsCovered() const;
     void removeAllNonVisibleTiles();
 
@@ -94,6 +95,7 @@ private:
     void commitScaleChange();
 
     bool resizeEdgeTiles();
+    void setCoverRect(const IntRect& rect) { m_coverRect = rect; }
     void setKeepRect(const IntRect&);
 
     PassRefPtr<Tile> tileAt(const Tile::Coordinate&) const;
@@ -125,6 +127,7 @@ private:
     FloatPoint m_trajectoryVector;
     IntRect m_visibleRect;
 
+    IntRect m_coverRect;
     IntRect m_keepRect;
     IntRect m_rect;
 
index f171af1..f9e9627 100644 (file)
@@ -1,5 +1,46 @@
 2012-09-27  Jocelyn Turcotte  <jocelyn.turcotte@digia.com>
 
+        [Qt] Decide when to apply a scrolled position to the viewport based on the rect covered by the tiles
+        https://bugs.webkit.org/show_bug.cgi?id=97777
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        This patch achieves two things:
+        - Apply a short scroll position request directly if we already have rendered tiles
+          at this position.
+        - Since our visible rect request is asynchronous, the next frame might not always
+          be the one covering this position. This will wait for a frame that does to apply it.
+
+        * UIProcess/API/qt/raw/qrawwebview_p_p.h:
+        (QRawWebViewPrivate::didRenderFrame):
+        * UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp:
+        (WebKit::LayerTreeCoordinatorProxy::didRenderFrame):
+        * UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h:
+        (LayerTreeCoordinatorProxy):
+        * UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.messages.in:
+        * UIProcess/PageClient.h:
+        (PageClient):
+        * UIProcess/PageViewportController.cpp:
+        (WebKit::PageViewportController::didCommitLoad):
+        (WebKit::PageViewportController::didRenderFrame):
+        (WebKit::PageViewportController::pageDidRequestScroll):
+        * UIProcess/PageViewportController.h:
+        (PageViewportController):
+        * UIProcess/WebPageProxy.h:
+        (WebPageProxy):
+        * UIProcess/qt/QtPageClient.cpp:
+        (WebKit::QtPageClient::didRenderFrame):
+        * UIProcess/qt/QtPageClient.h:
+        (QtPageClient):
+        * UIProcess/qt/WebPageProxyQt.cpp:
+        (WebKit::WebPageProxy::didRenderFrame):
+        * WebProcess/WebPage/CoordinatedGraphics/CoordinatedGraphicsLayer.h:
+        (WebCore::CoordinatedGraphicsLayer::coverRect):
+        * WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.cpp:
+        (WebKit::LayerTreeCoordinator::flushPendingLayerChanges):
+
+2012-09-27  Jocelyn Turcotte  <jocelyn.turcotte@digia.com>
+
         [Qt] Delay viewport position, scale and contents size updates until tiles are rendered
         https://bugs.webkit.org/show_bug.cgi?id=97775
 
index 890f808..545096d 100644 (file)
@@ -105,7 +105,7 @@ public:
     virtual void didRelaunchProcess();
     virtual void setViewNeedsDisplay(const WebCore::IntRect& rect);
     virtual void didChangeContentsSize(const WebCore::IntSize& newSize);
-    virtual void didRenderFrame(const WebCore::IntSize& contentsSize) { }
+    virtual void didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect) { }
     virtual void setCursor(const WebCore::Cursor&);
 
     virtual bool isViewFocused() { return m_focused; }
index 031a4f8..623b0a9 100644 (file)
@@ -116,14 +116,15 @@ void LayerTreeCoordinatorProxy::setCompositingLayerFilters(WebLayerID id, const
 }
 #endif
 
-void LayerTreeCoordinatorProxy::didRenderFrame(const WebCore::IntSize& contentsSize)
+void LayerTreeCoordinatorProxy::didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect)
 {
     dispatchUpdate(bind(&LayerTreeRenderer::flushLayerChanges, m_renderer.get()));
     updateViewport();
 #if PLATFORM(QT)
-    m_drawingAreaProxy->page()->didRenderFrame(contentsSize);
+    m_drawingAreaProxy->page()->didRenderFrame(contentsSize, coveredRect);
 #else
     UNUSED_PARAM(contentsSize);
+    UNUSED_PARAM(coveredRect);
 #endif
 }
 
index 92c610b..943330c 100644 (file)
@@ -63,7 +63,7 @@ public:
     void purgeGLResources();
     void setContentsSize(const WebCore::FloatSize&);
     void setVisibleContentsRect(const WebCore::FloatRect&, float scale, const WebCore::FloatPoint& trajectoryVector);
-    void didRenderFrame(const WebCore::IntSize& contentsSize);
+    void didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect);
     void createTileForLayer(int layerID, int tileID, const WebCore::IntRect&, const SurfaceUpdateInfo&);
     void updateTileForLayer(int layerID, int tileID, const WebCore::IntRect&, const SurfaceUpdateInfo&);
     void removeTileForLayer(int layerID, int tileID);
index 52d61af..e095746 100644 (file)
@@ -31,7 +31,7 @@ messages -> LayerTreeCoordinatorProxy {
     RemoveTileForLayer(uint32_t layerID, int tileID)
     CreateDirectlyCompositedImage(int64_t key, WebKit::ShareableBitmap::Handle handle)
     DestroyDirectlyCompositedImage(int64_t key)
-    DidRenderFrame(WebCore::IntSize contentsSize)
+    DidRenderFrame(WebCore::IntSize contentsSize, WebCore::IntRect coveredRect)
     DidChangeScrollPosition(WebCore::IntPoint position)
     SyncCanvas(uint32_t id, WebCore::IntSize canvasSize, uint64_t graphicsSurfaceToken, uint32_t frontBuffer)
     SetLayerAnimatedOpacity(uint32_t id, float opacity)
index d52f5d2..c6fb918 100644 (file)
@@ -118,7 +118,7 @@ public:
     virtual void pageDidRequestScroll(const WebCore::IntPoint&) = 0;
 #endif
 #if PLATFORM(QT)
-    virtual void didRenderFrame(const WebCore::IntSize& contentsSize) = 0;
+    virtual void didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect) = 0;
     virtual void pageTransitionViewportReady() = 0;
     virtual void didFindZoomableArea(const WebCore::IntPoint&, const WebCore::IntRect&) = 0;
     virtual void didReceiveMessageFromNavigatorQtObject(const String&) = 0;
index 345b4b1..c4cfc52 100644 (file)
@@ -111,6 +111,9 @@ FloatPoint PageViewportController::clampViewportToContents(const WebCore::FloatP
 
 void PageViewportController::didCommitLoad()
 {
+    // Do not count the previous committed page contents as covered.
+    m_lastFrameCoveredRect = FloatRect();
+
     // Reset the position to the top, page/history scroll requests may override this before we re-enable rendering.
     applyPositionAfterRenderingContents(FloatPoint());
 }
@@ -121,11 +124,13 @@ void PageViewportController::didChangeContentsSize(const IntSize& newSize)
     updateMinimumScaleToFit();
 }
 
-void PageViewportController::didRenderFrame(const IntSize& contentsSize)
+void PageViewportController::didRenderFrame(const IntSize& contentsSize, const IntRect& coveredRect)
 {
     // Only update the viewport's contents dimensions along with its render.
     m_client->didChangeContentsSize(contentsSize);
 
+    m_lastFrameCoveredRect = coveredRect;
+
     // Apply any scale or scroll position we locked to be set on the viewport
     // only when there is something to display there. The scale goes first to
     // avoid offsetting our deferred position by scaling at the viewport center.
@@ -138,8 +143,12 @@ void PageViewportController::didRenderFrame(const IntSize& contentsSize)
         m_effectiveScaleIsLocked = false;
     }
     if (m_viewportPosIsLocked) {
-        m_client->setViewportPosition(clampViewportToContents(m_viewportPos, m_effectiveScale));
-        m_viewportPosIsLocked = false;
+        FloatPoint clampedPos = clampViewportToContents(m_viewportPos, m_effectiveScale);
+        // There might be rendered frames not covering our requested position yet, wait for it.
+        if (FloatRect(clampedPos, m_viewportSize / m_effectiveScale).intersects(coveredRect)) {
+            m_client->setViewportPosition(clampedPos);
+            m_viewportPosIsLocked = false;
+        }
     }
 }
 
@@ -163,8 +172,12 @@ void PageViewportController::pageDidRequestScroll(const IntPoint& cssPosition)
     if (m_activeDeferrerCount)
         return;
 
-    // Keep the unclamped position in case the contents size is changed later on.
-    applyPositionAfterRenderingContents(cssPosition);
+    FloatRect endVisibleContentRect(clampViewportToContents(cssPosition, m_effectiveScale), m_viewportSize / m_effectiveScale);
+    if (m_lastFrameCoveredRect.intersects(endVisibleContentRect))
+        m_client->setViewportPosition(endVisibleContentRect.location());
+    else
+        // Keep the unclamped position in case the contents size is changed later on.
+        applyPositionAfterRenderingContents(cssPosition);
 }
 
 void PageViewportController::didChangeViewportSize(const FloatSize& newSize)
index 2b94cea..79953d7 100644 (file)
@@ -98,7 +98,7 @@ public:
     void didCommitLoad();
     void didChangeContentsSize(const WebCore::IntSize& newSize);
     void didChangeViewportAttributes(const WebCore::ViewportAttributes&);
-    void didRenderFrame(const WebCore::IntSize& contentsSize);
+    void didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect);
     void pageTransitionViewportReady();
     void pageDidRequestScroll(const WebCore::IntPoint& cssPosition);
 
@@ -129,6 +129,7 @@ private:
 
     bool m_viewportPosIsLocked;
     bool m_effectiveScaleIsLocked;
+    WebCore::FloatRect m_lastFrameCoveredRect;
 
     friend class ViewportUpdateDeferrer;
 };
index 79c51dc..6e3226a 100644 (file)
@@ -356,7 +356,7 @@ public:
     bool maintainsInactiveSelection() const { return m_maintainsInactiveSelection; }
     void setMaintainsInactiveSelection(bool);
 #if PLATFORM(QT)
-    void didRenderFrame(const WebCore::IntSize& contentsSize);
+    void didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect);
     void registerApplicationScheme(const String& scheme);
     void resolveApplicationSchemeRequest(QtNetworkRequestData);
     void sendApplicationSchemeReply(const QQuickNetworkReply*);
index e7573d8..bea8a2c 100644 (file)
@@ -73,9 +73,9 @@ void QtPageClient::setViewNeedsDisplay(const WebCore::IntRect& rect)
     QQuickWebViewPrivate::get(m_webView)->setNeedsDisplay();
 }
 
-void QtPageClient::didRenderFrame(const WebCore::IntSize& contentsSize)
+void QtPageClient::didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect)
 {
-    QQuickWebViewPrivate::get(m_webView)->viewportController()->didRenderFrame(contentsSize);
+    QQuickWebViewPrivate::get(m_webView)->viewportController()->didRenderFrame(contentsSize, coveredRect);
 }
 
 void QtPageClient::pageDidRequestScroll(const IntPoint& pos)
index 173c2d7..e493ce8 100644 (file)
@@ -43,7 +43,7 @@ public:
 
     // QQuickWebView.
     virtual void setViewNeedsDisplay(const WebCore::IntRect&);
-    virtual void didRenderFrame(const WebCore::IntSize& contentsSize);
+    virtual void didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect);
     virtual WebCore::IntSize viewSize();
     virtual bool isViewFocused();
     virtual bool isViewVisible();
index 8389640..40e27af 100644 (file)
@@ -93,9 +93,9 @@ void WebPageProxy::cancelComposition()
     process()->send(Messages::WebPage::CancelComposition(), m_pageID);
 }
 
-void WebPageProxy::didRenderFrame(const WebCore::IntSize& contentsSize)
+void WebPageProxy::didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect)
 {
-    m_pageClient->didRenderFrame(contentsSize);
+    m_pageClient->didRenderFrame(contentsSize, coveredRect);
 }
 
 void WebPageProxy::registerApplicationScheme(const String& scheme)
index f4ea2fb..3eba79b 100644 (file)
@@ -133,6 +133,7 @@ public:
 
     GraphicsLayer* maskTarget() const { return m_maskTarget; }
     void setMaskTarget(GraphicsLayer* layer) { m_maskTarget = layer; }
+    IntRect coverRect() const { return m_mainBackingStore ? m_mainBackingStore->coverRect() : IntRect(); }
 
     static void initFactory();
 
index ce35bfe..292c1b6 100644 (file)
@@ -274,7 +274,8 @@ bool LayerTreeCoordinator::flushPendingLayerChanges()
         didSync = true;
 
         IntSize contentsSize = roundedIntSize(m_nonCompositedContentLayer->size());
-        m_webPage->send(Messages::LayerTreeCoordinatorProxy::DidRenderFrame(contentsSize));
+        IntRect coveredRect = toCoordinatedGraphicsLayer(m_nonCompositedContentLayer.get())->coverRect();
+        m_webPage->send(Messages::LayerTreeCoordinatorProxy::DidRenderFrame(contentsSize, coveredRect));
         m_waitingForUIProcess = true;
         m_shouldSyncFrame = false;
     }