Flip the direction of the fence in scaleViewAndUpdateGeometryFenced
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 May 2015 20:40:32 +0000 (20:40 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 May 2015 20:40:32 +0000 (20:40 +0000)
https://bugs.webkit.org/show_bug.cgi?id=144810

Reviewed by Simon Fraser.

Send the fence from the Web process to the UI process, instead of vice versa.
This means that we won't keep the UI process CAContext blocked for the whole
time that the Web process is doing layout/painting/etc. Instead, we'll start
blocking the Web process CAContext immediately after flushing and before committing,
and send the fence to the UI process to be applied immediately. This minimizes
the amount of time in both processes spent blocked on the fence.

* Platform/mac/LayerHostingContext.h:
* Platform/mac/LayerHostingContext.mm:
(WebKit::LayerHostingContext::createFencePort):
Add createFencePort, which creates a MachSendRight wrapping a CA fence port.
Note that you must setFencePort() with this port if you want the LayerHostingContext's
CAContext to block on it!

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::scaleViewAndUpdateGeometryFenced):
(WebKit::WebPageProxy::machSendRightCallback):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
Create a callback and send it to the Web process along with scaleViewAndUpdateGeometryFenced.

* UIProcess/mac/WKViewLayoutStrategy.mm:
(-[WKViewDynamicSizeWithMinimumViewSizeLayoutStrategy updateLayout]):
When called back, install the fence port in our CAContext; when the commit goes through,
remove the transient scale as we did previously.

* WebProcess/WebPage/DrawingArea.h:
(WebKit::DrawingArea::replyWithFenceAfterNextFlush):
(WebKit::DrawingArea::updateGeometry): Deleted.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::scaleViewAndUpdateGeometryFenced):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Instead of installing a fence created in the UI process, tell the DrawingArea
to create one and reply to the UI process with it after the next flush.

* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):
(WebKit::TiledCoreAnimationDrawingArea::replyWithFenceAfterNextFlush):
After flushing, before committing, create a fence and reply to any
callbacks that requested fences, and install it in our context.

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

13 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/Platform/mac/LayerHostingContext.h
Source/WebKit2/Platform/mac/LayerHostingContext.mm
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/UIProcess/mac/WKViewLayoutStrategy.mm
Source/WebKit2/WebProcess/WebPage/DrawingArea.h
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h
Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm

index 73ce9d5..26c87d8 100644 (file)
@@ -1,3 +1,53 @@
+2015-05-08  Timothy Horton  <timothy_horton@apple.com>
+
+        Flip the direction of the fence in scaleViewAndUpdateGeometryFenced
+        https://bugs.webkit.org/show_bug.cgi?id=144810
+
+        Reviewed by Simon Fraser.
+
+        Send the fence from the Web process to the UI process, instead of vice versa.
+        This means that we won't keep the UI process CAContext blocked for the whole
+        time that the Web process is doing layout/painting/etc. Instead, we'll start
+        blocking the Web process CAContext immediately after flushing and before committing,
+        and send the fence to the UI process to be applied immediately. This minimizes
+        the amount of time in both processes spent blocked on the fence.
+
+        * Platform/mac/LayerHostingContext.h:
+        * Platform/mac/LayerHostingContext.mm:
+        (WebKit::LayerHostingContext::createFencePort):
+        Add createFencePort, which creates a MachSendRight wrapping a CA fence port.
+        Note that you must setFencePort() with this port if you want the LayerHostingContext's
+        CAContext to block on it!
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::scaleViewAndUpdateGeometryFenced):
+        (WebKit::WebPageProxy::machSendRightCallback):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        Create a callback and send it to the Web process along with scaleViewAndUpdateGeometryFenced.
+
+        * UIProcess/mac/WKViewLayoutStrategy.mm:
+        (-[WKViewDynamicSizeWithMinimumViewSizeLayoutStrategy updateLayout]):
+        When called back, install the fence port in our CAContext; when the commit goes through,
+        remove the transient scale as we did previously.
+
+        * WebProcess/WebPage/DrawingArea.h:
+        (WebKit::DrawingArea::replyWithFenceAfterNextFlush):
+        (WebKit::DrawingArea::updateGeometry): Deleted.
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::scaleViewAndUpdateGeometryFenced):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        Instead of installing a fence created in the UI process, tell the DrawingArea
+        to create one and reply to the UI process with it after the next flush.
+
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+        (WebKit::TiledCoreAnimationDrawingArea::flushLayers):
+        (WebKit::TiledCoreAnimationDrawingArea::replyWithFenceAfterNextFlush):
+        After flushing, before committing, create a fence and reply to any
+        callbacks that requested fences, and install it in our context.
+
 2015-05-08  Michael Catanzaro  <mcatanzaro@igalia.com>, Martin Robinson <mrobinson@igalia.com>
 
         [GTK] Checks for DEVELOPMENT_BUILD are all wrong
index 054b981..151dc58 100644 (file)
@@ -62,9 +62,14 @@ public:
     void setColorSpace(CGColorSpaceRef);
     CGColorSpaceRef colorSpace() const;
 
-    // This only works on iOS and OS 10.10+
+    // Fences only work on iOS and OS 10.10+.
     void setFencePort(mach_port_t);
 
+    // createFencePort does not install the fence port on the LayerHostingContext's
+    // CAContext; call setFencePort() with the newly created port if synchronization
+    // with this context is desired.
+    WebCore::MachSendRight createFencePort();
+
 private:
     LayerHostingMode m_layerHostingMode;
     RetainPtr<CAContext> m_context;
index 84f315c..8215fe0 100644 (file)
@@ -107,11 +107,21 @@ void LayerHostingContext::setFencePort(mach_port_t fencePort)
 {
     [m_context setFencePort:fencePort];
 }
+
+MachSendRight LayerHostingContext::createFencePort()
+{
+    return MachSendRight::adopt([m_context createFencePort]);
+}
 #else
 NO_RETURN_DUE_TO_ASSERT void LayerHostingContext::setFencePort(mach_port_t fencePort)
 {
     ASSERT_NOT_REACHED();
 }
+
+NO_RETURN_DUE_TO_ASSERT const MachSendRight& LayerHostingContext::createFencePort()
+{
+    ASSERT_NOT_REACHED();
+}
 #endif
 
 } // namespace WebKit
index 535576f..d823103 100644 (file)
@@ -2248,15 +2248,18 @@ void WebPageProxy::scaleView(double scale)
 }
 
 #if PLATFORM(COCOA)
-void WebPageProxy::scaleViewAndUpdateGeometryFenced(double scale, IntSize viewSize, const MachSendRight& fencePort)
+void WebPageProxy::scaleViewAndUpdateGeometryFenced(double scale, IntSize viewSize, std::function<void (const MachSendRight&, CallbackBase::Error)> callback)
 {
-    if (!isValid())
+    if (!isValid()) {
+        callback(MachSendRight(), CallbackBase::Error::OwnerWasInvalidated);
         return;
+    }
 
     m_viewScaleFactor = scale;
     if (m_drawingArea)
         m_drawingArea->willSendUpdateGeometry();
-    m_process->send(Messages::WebPage::ScaleViewAndUpdateGeometryFenced(scale, viewSize, fencePort), m_pageID);
+    uint64_t callbackID = m_callbacks.put(WTF::move(callback), m_process->throttler().backgroundActivityToken());
+    m_process->send(Messages::WebPage::ScaleViewAndUpdateGeometryFenced(scale, viewSize, callbackID), m_pageID);
 }
 #endif
 
@@ -4656,6 +4659,17 @@ void WebPageProxy::editingRangeCallback(const EditingRange& range, uint64_t call
     callback->performCallbackWithReturnValue(range);
 }
 
+#if PLATFORM(COCOA)
+void WebPageProxy::machSendRightCallback(const MachSendRight& sendRight, uint64_t callbackID)
+{
+    auto callback = m_callbacks.take<MachSendRightCallback>(callbackID);
+    if (!callback)
+        return;
+
+    callback->performCallbackWithReturnValue(sendRight);
+}
+#endif
+
 static bool shouldLogDiagnosticMessage(bool shouldSample)
 {
     if (!shouldSample)
index 589993f..d54740d 100644 (file)
@@ -242,6 +242,10 @@ typedef GenericCallback<const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t>
 typedef GenericCallback<const WebCore::IntPoint&, uint32_t> TouchesCallback;
 #endif
 
+#if PLATFORM(COCOA)
+typedef GenericCallback<const WebCore::MachSendRight&> MachSendRightCallback;
+#endif
+
 struct WebPageConfiguration {
     WebPageGroup* pageGroup = nullptr;
     WebPreferences* preferences = nullptr;
@@ -649,7 +653,7 @@ public:
     double viewScaleFactor() const { return m_viewScaleFactor; }
     void scaleView(double scale);
 #if PLATFORM(COCOA)
-    void scaleViewAndUpdateGeometryFenced(double scale, WebCore::IntSize viewSize, const WebCore::MachSendRight& fencePort);
+    void scaleViewAndUpdateGeometryFenced(double scale, WebCore::IntSize viewSize, std::function<void (const WebCore::MachSendRight&, CallbackBase::Error)>);
 #endif
 
     float deviceScaleFactor() const;
@@ -1313,6 +1317,9 @@ private:
     void validateCommandCallback(const String&, bool, int, uint64_t);
     void unsignedCallback(uint64_t, uint64_t);
     void editingRangeCallback(const EditingRange&, uint64_t);
+#if PLATFORM(COCOA)
+    void machSendRightCallback(const WebCore::MachSendRight&, uint64_t);
+#endif
     void rectForCharacterRangeCallback(const WebCore::IntRect&, const EditingRange&, uint64_t);
 #if PLATFORM(MAC)
     void attributedStringForCharacterRangeCallback(const AttributedString&, const EditingRange&, uint64_t);
index 0e16f6d..c1d2ba7 100644 (file)
@@ -194,6 +194,9 @@ messages -> WebPageProxy {
 #if PLATFORM(GTK)
     PrintFinishedCallback(WebCore::ResourceError error, uint64_t callbackID)
 #endif
+#if PLATFORM(COCOA)
+    MachSendRightCallback(WebCore::MachSendRight sendRight, uint64_t callbackID)
+#endif
 
     PageScaleFactorDidChange(double scaleFactor)
     PluginScaleFactorDidChange(double zoomFactor)
index 72ac3b4..3e3ea85 100644 (file)
@@ -293,12 +293,13 @@ using namespace WebKit;
         _wkView._rootLayer.transform = transform;
     } else if (scale != _page->viewScaleFactor()) {
 #if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
-        CAContext *context = [_wkView.layer context];
-        MachSendRight fencePort = MachSendRight::adopt([context createFencePort]);
-        _page->scaleViewAndUpdateGeometryFenced(scale, IntSize(_wkView.frame.size), fencePort);
-        [context setFencePort:fencePort.sendRight() commitHandler:^{
-            _wkView._rootLayer.transform = CATransform3DIdentity;
-        }];
+        RetainPtr<CAContext> context = [_wkView.layer context];
+        RetainPtr<WKView> retainedWKView = _wkView;
+        _page->scaleViewAndUpdateGeometryFenced(scale, IntSize(_wkView.frame.size), [retainedWKView, context] (const WebCore::MachSendRight& fencePort, CallbackBase::Error) {
+            [context setFencePort:fencePort.sendRight() commitHandler:^{
+                [retainedWKView _rootLayer].transform = CATransform3DIdentity;
+            }];
+        });
 #else
         _page->scaleView(scale);
         _wkView._rootLayer.transform = CATransform3DIdentity;
index cd4a138..726c574 100644 (file)
@@ -129,6 +129,8 @@ public:
 #if PLATFORM(COCOA)
     // Used by TiledCoreAnimationDrawingArea.
     virtual void updateGeometry(const WebCore::IntSize& viewSize, const WebCore::IntSize& layerPosition, bool flushSynchronously) { }
+
+    virtual void replyWithFenceAfterNextFlush(uint64_t callbackID) { ASSERT_NOT_REACHED(); }
 #endif
 
 protected:
index bfba85e..49dbcd9 100644 (file)
@@ -1449,11 +1449,11 @@ void WebPage::scaleView(double scale)
 
 
 #if PLATFORM(COCOA)
-void WebPage::scaleViewAndUpdateGeometryFenced(double scale, IntSize viewSize, const MachSendRight& fencePort)
+void WebPage::scaleViewAndUpdateGeometryFenced(double scale, IntSize viewSize, uint64_t callbackID)
 {
     scaleView(scale);
     m_drawingArea->updateGeometry(viewSize, IntSize(), false);
-    m_drawingArea->addFence(fencePort);
+    m_drawingArea->replyWithFenceAfterNextFlush(callbackID);
 }
 #endif
 
index 84d9395..b25fde0 100644 (file)
@@ -362,7 +362,7 @@ public:
     double viewScaleFactor() const { return m_viewScaleFactor; }
     void scaleView(double scale);
 #if PLATFORM(COCOA)
-    void scaleViewAndUpdateGeometryFenced(double scale, WebCore::IntSize viewSize, const WebCore::MachSendRight& fencePort);
+    void scaleViewAndUpdateGeometryFenced(double scale, WebCore::IntSize viewSize, uint64_t callbackID);
 #endif
 
     void setUseFixedLayout(bool);
index 344bc44..8582e83 100644 (file)
@@ -203,7 +203,7 @@ messages -> WebPage LegacyReceiver {
     ScalePageInViewCoordinates(double scale, WebCore::IntPoint centerInViewCoordinates)
     ScaleView(double scale)
 #if PLATFORM(COCOA)
-    ScaleViewAndUpdateGeometryFenced(double scale, WebCore::IntSize viewSize, WebCore::MachSendRight fencePort)
+    ScaleViewAndUpdateGeometryFenced(double scale, WebCore::IntSize viewSize, uint64_t callbackID)
 #endif
 
     SetUseFixedLayout(bool fixed)
index 019e0fe..9d51fd8 100644 (file)
@@ -86,6 +86,8 @@ private:
 
     virtual void attachViewOverlayGraphicsLayer(WebCore::Frame*, WebCore::GraphicsLayer*) override;
 
+    virtual void replyWithFenceAfterNextFlush(uint64_t callbackID) override;
+
     // WebCore::LayerFlushSchedulerClient
     virtual bool flushLayers() override;
 
@@ -146,6 +148,8 @@ private:
     bool m_wantsDidUpdateViewState;
 
     WebCore::GraphicsLayer* m_viewOverlayRootLayer;
+
+    Vector<uint64_t> m_fenceCallbacksForAfterNextFlush;
 };
 
 } // namespace WebKit
index 35e0929..2cbbc61 100644 (file)
@@ -329,6 +329,16 @@ bool TiledCoreAnimationDrawingArea::flushLayers()
         if (m_transientZoomScale != 1)
             applyTransientZoomToLayers(m_transientZoomScale, m_transientZoomOrigin);
 
+        if (!m_fenceCallbacksForAfterNextFlush.isEmpty()) {
+            MachSendRight fencePort = m_layerHostingContext->createFencePort();
+
+            for (auto callbackID : m_fenceCallbacksForAfterNextFlush)
+                m_webPage.send(Messages::WebPageProxy::MachSendRightCallback(fencePort, callbackID));
+            m_fenceCallbacksForAfterNextFlush.clear();
+
+            m_layerHostingContext->setFencePort(fencePort.sendRight());
+        }
+
         return returnValue;
     }
 }
@@ -746,6 +756,11 @@ void TiledCoreAnimationDrawingArea::addFence(const MachSendRight& fencePort)
     m_layerHostingContext->setFencePort(fencePort.sendRight());
 }
 
+void TiledCoreAnimationDrawingArea::replyWithFenceAfterNextFlush(uint64_t callbackID)
+{
+    m_fenceCallbacksForAfterNextFlush.append(callbackID);
+}
+
 } // namespace WebKit
 
 #endif // !PLATFORM(IOS)