- Revision
- 161296
- Author
- [email protected]
- Date
- 2014-01-03 16:35:59 -0800 (Fri, 03 Jan 2014)
Log Message
[iOS] [WK2] TileController creates all tiles on first paint, making it slow and consuming lots of memory
https://bugs.webkit.org/show_bug.cgi?id=126457
Reviewed by Simon Fraser.
Instead of making all of the tiles all of the time, we should use the
view-exposed-rect mechanism to inform TileController about what portion
of the WKContentView is currently exposed by the WKScrollView.
* UIProcess/API/ios/WKContentView.h:
* UIProcess/API/ios/WKContentView.mm:
(-[WKContentView setViewportSize:]):
(-[WKContentView didFinishScrollTo:]):
(-[WKContentView didScrollTo:]):
Inform the WebPageProxy that our exposed rect changed.
* UIProcess/API/ios/WKView.mm:
(-[WKView scrollViewDidScroll:]):
Inform the WKContentView that we've scrolled at all.
Rename the existing WKContentView didScrollTo: to didFinishScrollTo:,
because it is expected to only fire when a scroll lands. Add didScrollTo:,
which fires continually as scrolling progresses.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::WebPageProxy):
(WebKit::WebPageProxy::viewExposedRectChanged):
(WebKit::WebPageProxy::exposedRectChangedTimerFired):
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::viewExposedRect):
* UIProcess/mac/WebPageProxyMac.mm:
Move view-exposed-rect stuff to WebPageProxy so it can be built on both
Mac and iOS, and un-!PLATFORM(IOS) some of the related members.
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::RemoteLayerTreeDrawingArea):
(WebKit::RemoteLayerTreeDrawingArea::setExposedRect):
(WebKit::RemoteLayerTreeDrawingArea::setClipsToExposedRect):
(WebKit::RemoteLayerTreeDrawingArea::updateScrolledExposedRect):
(WebKit::RemoteLayerTreeDrawingArea::updateMainFrameClipsToExposedRect):
(WebKit::RemoteLayerTreeDrawingArea::mainFrameTiledBacking):
Steal TiledCoreAnimationDrawingArea's exposed-rect code.
Note that on iOS, we don't need to manually offset the exposed rect by
the scroll position, because the scroll position is already baked into
the exposed rect, and WebCore's notion of the scroll position will be
inaccurate until the scroll lands.
Modified Paths
Diff
Modified: trunk/Source/WebKit2/ChangeLog (161295 => 161296)
--- trunk/Source/WebKit2/ChangeLog 2014-01-04 00:24:08 UTC (rev 161295)
+++ trunk/Source/WebKit2/ChangeLog 2014-01-04 00:35:59 UTC (rev 161296)
@@ -1,3 +1,52 @@
+2014-01-03 Tim Horton <[email protected]>
+
+ [iOS] [WK2] TileController creates all tiles on first paint, making it slow and consuming lots of memory
+ https://bugs.webkit.org/show_bug.cgi?id=126457
+
+ Reviewed by Simon Fraser.
+
+ Instead of making all of the tiles all of the time, we should use the
+ view-exposed-rect mechanism to inform TileController about what portion
+ of the WKContentView is currently exposed by the WKScrollView.
+
+ * UIProcess/API/ios/WKContentView.h:
+ * UIProcess/API/ios/WKContentView.mm:
+ (-[WKContentView setViewportSize:]):
+ (-[WKContentView didFinishScrollTo:]):
+ (-[WKContentView didScrollTo:]):
+ Inform the WebPageProxy that our exposed rect changed.
+
+ * UIProcess/API/ios/WKView.mm:
+ (-[WKView scrollViewDidScroll:]):
+ Inform the WKContentView that we've scrolled at all.
+ Rename the existing WKContentView didScrollTo: to didFinishScrollTo:,
+ because it is expected to only fire when a scroll lands. Add didScrollTo:,
+ which fires continually as scrolling progresses.
+
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::WebPageProxy):
+ (WebKit::WebPageProxy::viewExposedRectChanged):
+ (WebKit::WebPageProxy::exposedRectChangedTimerFired):
+ * UIProcess/WebPageProxy.h:
+ (WebKit::WebPageProxy::viewExposedRect):
+ * UIProcess/mac/WebPageProxyMac.mm:
+ Move view-exposed-rect stuff to WebPageProxy so it can be built on both
+ Mac and iOS, and un-!PLATFORM(IOS) some of the related members.
+
+ * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
+ * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
+ (WebKit::RemoteLayerTreeDrawingArea::RemoteLayerTreeDrawingArea):
+ (WebKit::RemoteLayerTreeDrawingArea::setExposedRect):
+ (WebKit::RemoteLayerTreeDrawingArea::setClipsToExposedRect):
+ (WebKit::RemoteLayerTreeDrawingArea::updateScrolledExposedRect):
+ (WebKit::RemoteLayerTreeDrawingArea::updateMainFrameClipsToExposedRect):
+ (WebKit::RemoteLayerTreeDrawingArea::mainFrameTiledBacking):
+ Steal TiledCoreAnimationDrawingArea's exposed-rect code.
+ Note that on iOS, we don't need to manually offset the exposed rect by
+ the scroll position, because the scroll position is already baked into
+ the exposed rect, and WebCore's notion of the scroll position will be
+ inaccurate until the scroll lands.
+
2014-01-03 Simon Fraser <[email protected]>
Give all PlatformCALayers a PlatformLayerID, not just remote ones
Modified: trunk/Source/WebKit2/UIProcess/API/ios/WKContentView.h (161295 => 161296)
--- trunk/Source/WebKit2/UIProcess/API/ios/WKContentView.h 2014-01-04 00:24:08 UTC (rev 161295)
+++ trunk/Source/WebKit2/UIProcess/API/ios/WKContentView.h 2014-01-04 00:35:59 UTC (rev 161296)
@@ -64,6 +64,7 @@
- (void)setMinimumSize:(CGSize)size;
- (void)setViewportSize:(CGSize)size;
+- (void)didFinishScrollTo:(CGPoint)contentOffset;
- (void)didScrollTo:(CGPoint)contentOffset;
- (void)didZoomToScale:(CGFloat)scale;
Modified: trunk/Source/WebKit2/UIProcess/API/ios/WKContentView.mm (161295 => 161296)
--- trunk/Source/WebKit2/UIProcess/API/ios/WKContentView.mm 2014-01-04 00:24:08 UTC (rev 161295)
+++ trunk/Source/WebKit2/UIProcess/API/ios/WKContentView.mm 2014-01-04 00:35:59 UTC (rev 161296)
@@ -138,13 +138,20 @@
- (void)setViewportSize:(CGSize)size
{
_page->setFixedLayoutSize(IntSize(size));
+ _page->viewExposedRectChanged(FloatRect(_page->viewExposedRect().location(), FloatSize(size)), WebPageProxy::ClipsToExposedRect::Clip);
}
-- (void)didScrollTo:(CGPoint)contentOffset
+- (void)didFinishScrollTo:(CGPoint)contentOffset
{
_page->didFinishScrolling(contentOffset);
+ _page->viewExposedRectChanged(FloatRect(FloatPoint(contentOffset), _page->fixedLayoutSize()), WebPageProxy::ClipsToExposedRect::Clip);
}
+- (void)didScrollTo:(CGPoint)contentOffset
+{
+ _page->viewExposedRectChanged(FloatRect(FloatPoint(contentOffset), _page->fixedLayoutSize()), WebPageProxy::ClipsToExposedRect::Clip);
+}
+
- (void)didZoomToScale:(CGFloat)scale
{
_page->didFinishZooming(scale);
Modified: trunk/Source/WebKit2/UIProcess/API/ios/WKView.mm (161295 => 161296)
--- trunk/Source/WebKit2/UIProcess/API/ios/WKView.mm 2014-01-04 00:24:08 UTC (rev 161295)
+++ trunk/Source/WebKit2/UIProcess/API/ios/WKView.mm 2014-01-04 00:35:59 UTC (rev 161296)
@@ -187,29 +187,35 @@
_userHasChangedPageScale = YES;
}
-- (void)_didScroll
+- (void)_didFinishScroll
{
CGPoint position = [_scrollView convertPoint:[_scrollView contentOffset] toView:_contentView.get()];
- [_contentView didScrollTo:position];
+ [_contentView didFinishScrollTo:position];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
// If we're decelerating, scroll offset will be updated when scrollViewDidFinishDecelerating: is called.
if (!decelerate)
- [self _didScroll];
+ [self _didFinishScroll];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
- [self _didScroll];
+ [self _didFinishScroll];
}
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
{
- [self _didScroll];
+ [self _didFinishScroll];
}
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView
+{
+ CGPoint position = [_scrollView convertPoint:[_scrollView contentOffset] toView:_contentView.get()];
+ [_contentView didScrollTo:position];
+}
+
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
{
ASSERT(scrollView == _scrollView);
Modified: trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm (161295 => 161296)
--- trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm 2014-01-04 00:24:08 UTC (rev 161295)
+++ trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm 2014-01-04 00:35:59 UTC (rev 161296)
@@ -390,7 +390,7 @@
if (_data->_useContentPreparationRectForVisibleRect)
exposedRect = NSUnionRect(_data->_contentPreparationRect, exposedRect);
- _data->_page->viewExposedRectChanged(exposedRect, _data->_clipsToVisibleRect);
+ _data->_page->viewExposedRectChanged(exposedRect, _data->_clipsToVisibleRect ? WebPageProxy::ClipsToExposedRect::Clip : WebPageProxy::ClipsToExposedRect::DoNotClip);
}
- (void)setFrameSize:(NSSize)size
Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (161295 => 161296)
--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp 2014-01-04 00:24:08 UTC (rev 161295)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp 2014-01-04 00:35:59 UTC (rev 161296)
@@ -302,10 +302,10 @@
, m_mediaVolume(1)
, m_mayStartMediaWhenInWindow(true)
, m_waitingForDidUpdateViewState(false)
-#if PLATFORM(MAC) && !PLATFORM(IOS)
+#if PLATFORM(MAC)
, m_exposedRectChangedTimer(this, &WebPageProxy::exposedRectChangedTimerFired)
- , m_clipsToExposedRect(false)
- , m_lastSentClipsToExposedRect(false)
+ , m_clipsToExposedRect(ClipsToExposedRect::DoNotClip)
+ , m_lastSentClipsToExposedRect(ClipsToExposedRect::DoNotClip)
#endif
, m_scrollPinningBehavior(DoNotPin)
{
@@ -4394,4 +4394,31 @@
m_process->send(Messages::WebPage::SetScrollPinningBehavior(pinning), m_pageID);
}
+#if PLATFORM(MAC) || PLATFORM(IOS)
+void WebPageProxy::viewExposedRectChanged(const FloatRect& exposedRect, ClipsToExposedRect clipsToExposedRect)
+{
+ if (!isValid())
+ return;
+
+ m_exposedRect = exposedRect;
+ m_clipsToExposedRect = clipsToExposedRect;
+
+ if (!m_exposedRectChangedTimer.isActive())
+ m_exposedRectChangedTimer.startOneShot(0);
+}
+
+void WebPageProxy::exposedRectChangedTimerFired(Timer<WebPageProxy>*)
+{
+ if (!isValid())
+ return;
+
+ if (m_exposedRect == m_lastSentExposedRect && m_clipsToExposedRect == m_lastSentClipsToExposedRect)
+ return;
+
+ process().send(Messages::WebPage::ViewExposedRectChanged(m_exposedRect, m_clipsToExposedRect == ClipsToExposedRect::Clip), m_pageID);
+ m_lastSentExposedRect = m_exposedRect;
+ m_lastSentClipsToExposedRect = m_clipsToExposedRect;
+}
+#endif
+
} // namespace WebKit
Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (161295 => 161296)
--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h 2014-01-04 00:24:08 UTC (rev 161295)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h 2014-01-04 00:35:59 UTC (rev 161296)
@@ -463,7 +463,9 @@
#if PLATFORM(MAC)
void windowAndViewFramesChanged(const WebCore::FloatRect& viewFrameInWindowCoordinates, const WebCore::FloatPoint& accessibilityViewCoordinates);
- void viewExposedRectChanged(const WebCore::FloatRect& exposedRect, bool);
+ enum class ClipsToExposedRect { DoNotClip, Clip };
+ void viewExposedRectChanged(const WebCore::FloatRect& exposedRect, ClipsToExposedRect);
+ WebCore::FloatRect viewExposedRect() const { return m_exposedRect; }
void exposedRectChangedTimerFired(WebCore::Timer<WebPageProxy>*);
void setMainFrameIsScrollable(bool);
@@ -1355,13 +1357,11 @@
bool m_waitingForDidUpdateViewState;
#if PLATFORM(MAC)
-#if !PLATFORM(IOS)
WebCore::Timer<WebPageProxy> m_exposedRectChangedTimer;
-#endif // PLATFORM(IOS)
WebCore::FloatRect m_exposedRect;
WebCore::FloatRect m_lastSentExposedRect;
- bool m_clipsToExposedRect;
- bool m_lastSentClipsToExposedRect;
+ ClipsToExposedRect m_clipsToExposedRect;
+ ClipsToExposedRect m_lastSentClipsToExposedRect;
#endif
#if PLATFORM(MAC)
Modified: trunk/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm (161295 => 161296)
--- trunk/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm 2014-01-04 00:24:08 UTC (rev 161295)
+++ trunk/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm 2014-01-04 00:35:59 UTC (rev 161296)
@@ -155,31 +155,6 @@
process().send(Messages::WebPage::WindowAndViewFramesChanged(windowFrameInScreenCoordinates, windowFrameInUnflippedScreenCoordinates, viewFrameInWindowCoordinates, accessibilityViewCoordinates), m_pageID);
}
-void WebPageProxy::viewExposedRectChanged(const FloatRect& exposedRect, bool clipsToExposedRect)
-{
- if (!isValid())
- return;
-
- m_exposedRect = exposedRect;
- m_clipsToExposedRect = clipsToExposedRect;
-
- if (!m_exposedRectChangedTimer.isActive())
- m_exposedRectChangedTimer.startOneShot(0);
-}
-
-void WebPageProxy::exposedRectChangedTimerFired(Timer<WebPageProxy>*)
-{
- if (!isValid())
- return;
-
- if (m_exposedRect == m_lastSentExposedRect && m_clipsToExposedRect == m_lastSentClipsToExposedRect)
- return;
-
- process().send(Messages::WebPage::ViewExposedRectChanged(m_exposedRect, m_clipsToExposedRect), m_pageID);
- m_lastSentExposedRect = m_exposedRect;
- m_lastSentClipsToExposedRect = m_clipsToExposedRect;
-}
-
void WebPageProxy::setMainFrameIsScrollable(bool isScrollable)
{
if (!isValid())
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h (161295 => 161296)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h 2014-01-04 00:24:08 UTC (rev 161295)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h 2014-01-04 00:35:59 UTC (rev 161296)
@@ -69,6 +69,9 @@
virtual void forceRepaint() OVERRIDE;
virtual bool forceRepaintAsync(uint64_t) OVERRIDE { return false; }
+ virtual void setExposedRect(const WebCore::FloatRect&) OVERRIDE;
+ virtual void setClipsToExposedRect(bool) OVERRIDE;
+
// WebCore::GraphicsLayerClient
virtual void notifyAnimationStarted(const WebCore::GraphicsLayer*, double time) OVERRIDE { }
virtual void notifyFlushRequired(const WebCore::GraphicsLayer*) OVERRIDE { }
@@ -80,12 +83,21 @@
virtual bool allowCompositingLayerVisualDegradation() const OVERRIDE { return false; }
#endif
+ void updateMainFrameClipsToExposedRect();
+ void updateScrolledExposedRect();
+
+ WebCore::TiledBacking* mainFrameTiledBacking() const;
+
std::unique_ptr<RemoteLayerTreeContext> m_remoteLayerTreeContext;
RefPtr<WebCore::PlatformCALayer> m_rootLayer;
HashMap<PageOverlay*, std::unique_ptr<GraphicsLayerCARemote>> m_pageOverlayLayers;
WebCore::IntSize m_viewSize;
+
+ WebCore::FloatRect m_exposedRect;
+ WebCore::FloatRect m_scrolledExposedRect;
+ bool m_clipsToExposedRect;
};
} // namespace WebKit
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm (161295 => 161296)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm 2014-01-04 00:24:08 UTC (rev 161295)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm 2014-01-04 00:35:59 UTC (rev 161296)
@@ -34,6 +34,7 @@
#import <WebCore/FrameView.h>
#import <WebCore/MainFrame.h>
#import <WebCore/Settings.h>
+#import <WebCore/TiledBacking.h>
using namespace WebCore;
@@ -42,10 +43,12 @@
RemoteLayerTreeDrawingArea::RemoteLayerTreeDrawingArea(WebPage* webPage, const WebPageCreationParameters&)
: DrawingArea(DrawingAreaTypeRemoteLayerTree, webPage)
, m_remoteLayerTreeContext(std::make_unique<RemoteLayerTreeContext>(webPage))
+ , m_clipsToExposedRect(false)
{
webPage->corePage()->settings().setForceCompositingMode(true);
#if PLATFORM(IOS)
webPage->corePage()->settings().setDelegatesPageScaling(true);
+ setClipsToExposedRect(true);
#endif
}
@@ -207,4 +210,63 @@
m_remoteLayerTreeContext->forceRepaint();
}
+void RemoteLayerTreeDrawingArea::setExposedRect(const FloatRect& exposedRect)
+{
+ m_exposedRect = exposedRect;
+ updateScrolledExposedRect();
+}
+
+void RemoteLayerTreeDrawingArea::setClipsToExposedRect(bool clipsToExposedRect)
+{
+ m_clipsToExposedRect = clipsToExposedRect;
+ updateScrolledExposedRect();
+ updateMainFrameClipsToExposedRect();
+}
+
+void RemoteLayerTreeDrawingArea::updateScrolledExposedRect()
+{
+ if (!m_clipsToExposedRect)
+ return;
+
+ FrameView* frameView = m_webPage->corePage()->mainFrame().view();
+ if (!frameView)
+ return;
+
+ m_scrolledExposedRect = m_exposedRect;
+
+#if !PLATFORM(IOS)
+ IntPoint scrollPositionWithOrigin = frameView->scrollPosition() + toIntSize(frameView->scrollOrigin());
+ m_scrolledExposedRect.moveBy(scrollPositionWithOrigin);
+#endif
+
+ mainFrameTiledBacking()->setExposedRect(m_scrolledExposedRect);
+
+ for (auto it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it) {
+ if (TiledBacking* tiledBacking = it->value->tiledBacking())
+ tiledBacking->setExposedRect(m_scrolledExposedRect);
+ }
+}
+
+void RemoteLayerTreeDrawingArea::updateMainFrameClipsToExposedRect()
+{
+ if (TiledBacking* tiledBacking = mainFrameTiledBacking())
+ tiledBacking->setClipsToExposedRect(m_clipsToExposedRect);
+
+ for (auto it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it)
+ if (TiledBacking* tiledBacking = it->value->tiledBacking())
+ tiledBacking->setClipsToExposedRect(m_clipsToExposedRect);
+
+ FrameView* frameView = m_webPage->corePage()->mainFrame().view();
+ if (!frameView)
+ return;
+
+ frameView->adjustTiledBackingCoverage();
+}
+
+TiledBacking* RemoteLayerTreeDrawingArea::mainFrameTiledBacking() const
+{
+ FrameView* frameView = m_webPage->corePage()->mainFrame().view();
+ return frameView ? frameView->tiledBacking() : 0;
+}
+
} // namespace WebKit