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
+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
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;
{
[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
}
#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
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)
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;
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;
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);
#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)
_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;
#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:
#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
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);
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)
virtual void attachViewOverlayGraphicsLayer(WebCore::Frame*, WebCore::GraphicsLayer*) override;
+ virtual void replyWithFenceAfterNextFlush(uint64_t callbackID) override;
+
// WebCore::LayerFlushSchedulerClient
virtual bool flushLayers() override;
bool m_wantsDidUpdateViewState;
WebCore::GraphicsLayer* m_viewOverlayRootLayer;
+
+ Vector<uint64_t> m_fenceCallbacksForAfterNextFlush;
};
} // namespace WebKit
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;
}
}
m_layerHostingContext->setFencePort(fencePort.sendRight());
}
+void TiledCoreAnimationDrawingArea::replyWithFenceAfterNextFlush(uint64_t callbackID)
+{
+ m_fenceCallbacksForAfterNextFlush.append(callbackID);
+}
+
} // namespace WebKit
#endif // !PLATFORM(IOS)