Title: [171068] trunk/Source/WebKit2
Revision
171068
Author
[email protected]
Date
2014-07-14 11:11:46 -0700 (Mon, 14 Jul 2014)

Log Message

[iOS] Throttle painting using a UI-process-side CADisplayLink
https://bugs.webkit.org/show_bug.cgi?id=134879
<rdar://problem/17641699>

Reviewed by Simon Fraser.

Just waiting for CA to commit is insufficient to actually throttle to 60fps,
because nothing will block the main runloop from spinning.

Instead, listen to a CADisplayLink, and send didUpdate to the WebProcess
the first time it fires after we commit. This is not a guarantee that
our content is on the screen, but we don't have any way to make that guarantee yet.

This will throttle painting, rAF, etc. to the display refresh rate.

* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[OneShotDisplayLinkHandler initWithDrawingAreaProxy:]):
(-[OneShotDisplayLinkHandler dealloc]):
(-[OneShotDisplayLinkHandler displayLinkFired:]):
(-[OneShotDisplayLinkHandler invalidate]):
(-[OneShotDisplayLinkHandler schedule]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy):
(WebKit::RemoteLayerTreeDrawingAreaProxy::~RemoteLayerTreeDrawingAreaProxy):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::coreAnimationDidCommitLayers): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (171067 => 171068)


--- trunk/Source/WebKit2/ChangeLog	2014-07-14 17:16:57 UTC (rev 171067)
+++ trunk/Source/WebKit2/ChangeLog	2014-07-14 18:11:46 UTC (rev 171068)
@@ -1,3 +1,33 @@
+2014-07-14  Tim Horton  <[email protected]>
+
+        [iOS] Throttle painting using a UI-process-side CADisplayLink
+        https://bugs.webkit.org/show_bug.cgi?id=134879
+        <rdar://problem/17641699>
+
+        Reviewed by Simon Fraser.
+
+        Just waiting for CA to commit is insufficient to actually throttle to 60fps,
+        because nothing will block the main runloop from spinning.
+
+        Instead, listen to a CADisplayLink, and send didUpdate to the WebProcess
+        the first time it fires after we commit. This is not a guarantee that
+        our content is on the screen, but we don't have any way to make that guarantee yet.
+
+        This will throttle painting, rAF, etc. to the display refresh rate.
+
+        * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
+        * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
+        (-[OneShotDisplayLinkHandler initWithDrawingAreaProxy:]):
+        (-[OneShotDisplayLinkHandler dealloc]):
+        (-[OneShotDisplayLinkHandler displayLinkFired:]):
+        (-[OneShotDisplayLinkHandler invalidate]):
+        (-[OneShotDisplayLinkHandler schedule]):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::~RemoteLayerTreeDrawingAreaProxy):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::coreAnimationDidCommitLayers): Deleted.
+
 2014-07-14  Dan Bernstein  <[email protected]>
 
         <rdar://problem/17657391> [iOS] Networking process writes persistent credentials to the keychain

Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h (171067 => 171068)


--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h	2014-07-14 17:16:57 UTC (rev 171067)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h	2014-07-14 18:11:46 UTC (rev 171068)
@@ -31,8 +31,9 @@
 #include <WebCore/FloatPoint.h>
 #include <WebCore/IntPoint.h>
 #include <WebCore/IntSize.h>
-#include <WebCore/RunLoopObserver.h>
 
+OBJC_CLASS OneShotDisplayLinkHandler;
+
 namespace WebKit {
 
 class RemoteLayerTreeTransaction;
@@ -47,11 +48,11 @@
 
     void acceleratedAnimationDidStart(uint64_t layerID, const String& key, double startTime);
 
-    void coreAnimationDidCommitLayers();
-
     uint64_t nextLayerTreeTransactionID() const { return m_pendingLayerTreeTransactionID + 1; }
     uint64_t lastCommittedLayerTreeTransactionID() const { return m_transactionIDForPendingCACommit; }
 
+    void didRefreshDisplay(double timestamp);
+
 private:
     virtual void sizeDidChange() override;
     virtual void deviceScaleFactorDidChange() override;
@@ -96,13 +97,13 @@
     RetainPtr<CALayer> m_tileMapHostLayer;
     RetainPtr<CALayer> m_exposedRectIndicatorLayer;
 
-    std::unique_ptr<WebCore::RunLoopObserver> m_layerCommitObserver;
-
     uint64_t m_pendingLayerTreeTransactionID;
     uint64_t m_lastVisibleTransactionID;
     uint64_t m_transactionIDForPendingCACommit;
 
     CallbackMap m_callbacks;
+
+    RetainPtr<OneShotDisplayLinkHandler> m_displayLinkHandler;
 };
 
 DRAWING_AREA_PROXY_TYPE_CASTS(RemoteLayerTreeDrawingAreaProxy, type() == DrawingAreaTypeRemoteLayerTree);

Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm (171067 => 171068)


--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm	2014-07-14 17:16:57 UTC (rev 171067)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm	2014-07-14 18:11:46 UTC (rev 171068)
@@ -40,8 +40,62 @@
 using namespace IPC;
 using namespace WebCore;
 
-static const CFIndex didCommitLayersRunLoopOrder = (CFIndex)RunLoopObserver::WellKnownRunLoopOrders::CoreAnimationCommit + 1;
+// FIXME: Mac will need something similar; we should figure out how to share this with DisplayRefreshMonitor without
+// breaking WebKit1 behavior or WebKit2-WebKit1 coexistence.
+#if PLATFORM(IOS)
+@interface OneShotDisplayLinkHandler : NSObject {
+    WebKit::RemoteLayerTreeDrawingAreaProxy* _drawingAreaProxy;
+    CADisplayLink *_displayLink;
+}
 
+- (id)initWithDrawingAreaProxy:(WebKit::RemoteLayerTreeDrawingAreaProxy*)drawingAreaProxy;
+- (void)displayLinkFired:(CADisplayLink *)sender;
+- (void)invalidate;
+- (void)schedule;
+
+@end
+
+@implementation OneShotDisplayLinkHandler
+
+- (id)initWithDrawingAreaProxy:(WebKit::RemoteLayerTreeDrawingAreaProxy*)drawingAreaProxy
+{
+    if (self = [super init]) {
+        _drawingAreaProxy = drawingAreaProxy;
+        // Note that CADisplayLink retains its target (self), so a call to -invalidate is needed on teardown.
+        _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkFired:)];
+        [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
+        _displayLink.paused = YES;
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    ASSERT(!_displayLink);
+    [super dealloc];
+}
+
+- (void)displayLinkFired:(CADisplayLink *)sender
+{
+    ASSERT(isMainThread());
+    _drawingAreaProxy->didRefreshDisplay(sender.timestamp);
+    _displayLink.paused = YES;
+}
+
+- (void)invalidate
+{
+    [_displayLink invalidate];
+    _displayLink = nullptr;
+}
+
+- (void)schedule
+{
+    _displayLink.paused = NO;
+}
+
+@end
+#endif
+
 namespace WebKit {
 
 RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy(WebPageProxy* webPageProxy)
@@ -51,6 +105,9 @@
     , m_pendingLayerTreeTransactionID(0)
     , m_lastVisibleTransactionID(0)
     , m_transactionIDForPendingCACommit(0)
+#if PLATFORM(IOS)
+    , m_displayLinkHandler(adoptNS([[OneShotDisplayLinkHandler alloc] initWithDrawingAreaProxy:this]))
+#endif
 {
 #if USE(IOSURFACE)
     // We don't want to pool surfaces in the UI process.
@@ -62,16 +119,16 @@
 
     if (m_webPageProxy->preferences().tiledScrollingIndicatorVisible())
         initializeDebugIndicator();
-
-    m_layerCommitObserver = RunLoopObserver::create(didCommitLayersRunLoopOrder, [this]() {
-        this->coreAnimationDidCommitLayers();
-    });
 }
 
 RemoteLayerTreeDrawingAreaProxy::~RemoteLayerTreeDrawingAreaProxy()
 {
     m_callbacks.invalidate(CallbackBase::Error::OwnerWasInvalidated);
     m_webPageProxy->process().removeMessageReceiver(Messages::RemoteLayerTreeDrawingAreaProxy::messageReceiverName(), m_webPageProxy->pageID());
+
+#if PLATFORM(IOS)
+    [m_displayLinkHandler invalidate];
+#endif
 }
 
 void RemoteLayerTreeDrawingAreaProxy::sizeDidChange()
@@ -167,7 +224,11 @@
         asLayer(m_debugIndicatorLayerTreeHost->rootLayer()).name = @"Indicator host root";
     }
 
-    m_layerCommitObserver->schedule();
+#if PLATFORM(IOS)
+    [m_displayLinkHandler schedule];
+#else
+    didRefreshDisplay(monotonicallyIncreasingTime());
+#endif
 }
 
 void RemoteLayerTreeDrawingAreaProxy::acceleratedAnimationDidStart(uint64_t layerID, const String& key, double startTime)
@@ -302,10 +363,8 @@
     }
 }
 
-void RemoteLayerTreeDrawingAreaProxy::coreAnimationDidCommitLayers()
+void RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay(double)
 {
-    m_layerCommitObserver->invalidate();
-
     if (!m_webPageProxy->isValid())
         return;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to