- Revision
- 166540
- Author
- [email protected]
- Date
- 2014-03-31 15:52:31 -0700 (Mon, 31 Mar 2014)
Log Message
Synchronize Web process remote layer tree commits with CoreAnimation commits in the UI process
https://bugs.webkit.org/show_bug.cgi?id=130984
Reviewed by Simon Fraser.
There's no reason for the Web process to paint faster than the UI process
can apply to and commit the CoreAnimation layer tree.
Also, once we get proper double-buffering and purgeable back buffers, we
will need the ability to make some assumptions about in-use surfaces.
Unfortunately, we can't actually tell when the render server commits,
as this is an asynchronous operation in a process we don't control, so
for now, this is only an approximation.
This also means that the assumptions we would like to make won't be
strong guarantees yet.
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
When we commit, install a run loop observer to fire immediately after CoreAnimation commits.
(WebKit::RemoteLayerTreeDrawingAreaProxy::showDebugIndicator):
Fix a typo ('cmponents').
(WebKit::coreAnimationDidCommitLayersCallback):
(WebKit::RemoteLayerTreeDrawingAreaProxy::scheduleCoreAnimationLayerCommitObserver):
(WebKit::RemoteLayerTreeDrawingAreaProxy::coreAnimationDidCommitLayers):
When CA commits, send a message to the Web process letting it know that we
swapped to the new backing store.
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::RemoteLayerTreeDrawingArea):
(WebKit::RemoteLayerTreeDrawingArea::flushLayers):
(WebKit::RemoteLayerTreeDrawingArea::didUpdate):
Defer remote layer tree commits until we get didUpdate() from the UI process.
Modified Paths
Diff
Modified: trunk/Source/WebKit2/ChangeLog (166539 => 166540)
--- trunk/Source/WebKit2/ChangeLog 2014-03-31 22:29:36 UTC (rev 166539)
+++ trunk/Source/WebKit2/ChangeLog 2014-03-31 22:52:31 UTC (rev 166540)
@@ -1,3 +1,44 @@
+2014-03-31 Tim Horton <[email protected]>
+
+ Synchronize Web process remote layer tree commits with CoreAnimation commits in the UI process
+ https://bugs.webkit.org/show_bug.cgi?id=130984
+
+ Reviewed by Simon Fraser.
+
+ There's no reason for the Web process to paint faster than the UI process
+ can apply to and commit the CoreAnimation layer tree.
+
+ Also, once we get proper double-buffering and purgeable back buffers, we
+ will need the ability to make some assumptions about in-use surfaces.
+
+ Unfortunately, we can't actually tell when the render server commits,
+ as this is an asynchronous operation in a process we don't control, so
+ for now, this is only an approximation.
+
+ This also means that the assumptions we would like to make won't be
+ strong guarantees yet.
+
+ * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
+ * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
+ (WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
+ When we commit, install a run loop observer to fire immediately after CoreAnimation commits.
+
+ (WebKit::RemoteLayerTreeDrawingAreaProxy::showDebugIndicator):
+ Fix a typo ('cmponents').
+
+ (WebKit::coreAnimationDidCommitLayersCallback):
+ (WebKit::RemoteLayerTreeDrawingAreaProxy::scheduleCoreAnimationLayerCommitObserver):
+ (WebKit::RemoteLayerTreeDrawingAreaProxy::coreAnimationDidCommitLayers):
+ When CA commits, send a message to the Web process letting it know that we
+ swapped to the new backing store.
+
+ * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
+ * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
+ (WebKit::RemoteLayerTreeDrawingArea::RemoteLayerTreeDrawingArea):
+ (WebKit::RemoteLayerTreeDrawingArea::flushLayers):
+ (WebKit::RemoteLayerTreeDrawingArea::didUpdate):
+ Defer remote layer tree commits until we get didUpdate() from the UI process.
+
2014-03-31 Dean Jackson <[email protected]>
Remove WEB_ANIMATIONS
Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h (166539 => 166540)
--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h 2014-03-31 22:29:36 UTC (rev 166539)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h 2014-03-31 22:52:31 UTC (rev 166540)
@@ -44,6 +44,8 @@
const RemoteLayerTreeHost& remoteLayerTreeHost() const { return m_remoteLayerTreeHost; }
+ void coreAnimationDidCommitLayers();
+
private:
virtual void sizeDidChange() override;
virtual void deviceScaleFactorDidChange() override;
@@ -71,6 +73,8 @@
void sendUpdateGeometry();
+ void scheduleCoreAnimationLayerCommitObserver();
+
RemoteLayerTreeHost m_remoteLayerTreeHost;
bool m_isWaitingForDidUpdateGeometry;
@@ -80,6 +84,8 @@
std::unique_ptr<RemoteLayerTreeHost> m_debugIndicatorLayerTreeHost;
RetainPtr<CALayer> m_tileMapHostLayer;
RetainPtr<CALayer> m_exposedRectIndicatorLayer;
+
+ RetainPtr<CFRunLoopObserverRef> m_layerCommitObserver;
};
DRAWING_AREA_PROXY_TYPE_CASTS(RemoteLayerTreeDrawingAreaProxy, type() == DrawingAreaTypeRemoteLayerTree);
Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm (166539 => 166540)
--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm 2014-03-31 22:29:36 UTC (rev 166539)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm 2014-03-31 22:52:31 UTC (rev 166540)
@@ -34,6 +34,9 @@
#import "WebProcessProxy.h"
#import <WebCore/WebCoreCALayerExtras.h>
+static const CFIndex CoreAnimationCommitRunLoopOrder = 2000000;
+static const CFIndex DidCommitLayersRunLoopOrder = CoreAnimationCommitRunLoopOrder + 1;
+
using namespace WebCore;
namespace WebKit {
@@ -49,6 +52,11 @@
RemoteLayerTreeDrawingAreaProxy::~RemoteLayerTreeDrawingAreaProxy()
{
m_webPageProxy->process().removeMessageReceiver(Messages::RemoteLayerTreeDrawingAreaProxy::messageReceiverName(), m_webPageProxy->pageID());
+
+ if (m_layerCommitObserver) {
+ CFRunLoopObserverInvalidate(m_layerCommitObserver.get());
+ m_layerCommitObserver = nullptr;
+ }
}
void RemoteLayerTreeDrawingAreaProxy::sizeDidChange()
@@ -129,6 +137,8 @@
updateDebugIndicator(layerTreeTransaction.contentsSize(), rootLayerChanged, scale);
asLayer(m_debugIndicatorLayerTreeHost->rootLayer()).name = @"Indicator host root";
}
+
+ scheduleCoreAnimationLayerCommitObserver();
}
static const float indicatorInset = 10;
@@ -253,8 +263,8 @@
RetainPtr<CGColorRef> color = adoptCF(CGColorCreate(colorSpace.get(), components));
[m_tileMapHostLayer setBackgroundColor:color.get()];
- const CGFloat borderCmponents[] = { 0, 0, 0, 1 };
- RetainPtr<CGColorRef> borderColor = adoptCF(CGColorCreate(colorSpace.get(), borderCmponents));
+ const CGFloat borderComponents[] = { 0, 0, 0, 1 };
+ RetainPtr<CGColorRef> borderColor = adoptCF(CGColorCreate(colorSpace.get(), borderComponents));
[m_tileMapHostLayer setBorderColor:borderColor.get()];
}
@@ -269,4 +279,41 @@
}
}
+static void coreAnimationDidCommitLayersCallback(CFRunLoopObserverRef, CFRunLoopActivity, void* context)
+{
+ static_cast<RemoteLayerTreeDrawingAreaProxy*>(context)->coreAnimationDidCommitLayers();
+}
+
+void RemoteLayerTreeDrawingAreaProxy::scheduleCoreAnimationLayerCommitObserver()
+{
+ if (m_layerCommitObserver)
+ return;
+
+ CFRunLoopRef runLoop = CFRunLoopGetCurrent();
+
+ // Make sure we wake up the loop or the observer could be delayed until some other source fires.
+ CFRunLoopWakeUp(runLoop);
+
+ CFRunLoopObserverContext context = { 0, this, 0, 0, 0 };
+ m_layerCommitObserver = adoptCF(CFRunLoopObserverCreate(0, kCFRunLoopBeforeWaiting | kCFRunLoopExit, true, DidCommitLayersRunLoopOrder, coreAnimationDidCommitLayersCallback, &context));
+
+ CFRunLoopAddObserver(runLoop, m_layerCommitObserver.get(), kCFRunLoopCommonModes);
+}
+
+void RemoteLayerTreeDrawingAreaProxy::coreAnimationDidCommitLayers()
+{
+ if (m_layerCommitObserver) {
+ CFRunLoopObserverInvalidate(m_layerCommitObserver.get());
+ m_layerCommitObserver = nullptr;
+ }
+
+ if (!m_webPageProxy->isValid())
+ return;
+
+ // Waiting for CA to commit is insufficient, because the render server can still be
+ // using our backing store. We can improve this by waiting for the render server to commit
+ // if we find API to do so, but for now we will make extra buffers if need be.
+ m_webPageProxy->process().send(Messages::DrawingArea::DidUpdate(), m_webPageProxy->pageID());
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h (166539 => 166540)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h 2014-03-31 22:29:36 UTC (rev 166539)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h 2014-03-31 22:52:31 UTC (rev 166540)
@@ -79,6 +79,8 @@
virtual void setExposedContentRect(const WebCore::FloatRect&) override;
#endif
+ virtual void didUpdate() override;
+
// WebCore::GraphicsLayerClient
virtual void notifyAnimationStarted(const WebCore::GraphicsLayer*, double time) override { }
virtual void notifyFlushRequired(const WebCore::GraphicsLayer*) override { }
@@ -109,6 +111,9 @@
WebCore::Timer<RemoteLayerTreeDrawingArea> m_layerFlushTimer;
bool m_isFlushingSuspended;
bool m_hasDeferredFlush;
+
+ bool m_waitingForBackingStoreSwap;
+ bool m_hadFlushDeferredWhileWaitingForBackingStoreSwap;
};
DRAWING_AREA_TYPE_CASTS(RemoteLayerTreeDrawingArea, type() == DrawingAreaTypeRemoteLayerTree);
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm (166539 => 166540)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm 2014-03-31 22:29:36 UTC (rev 166539)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm 2014-03-31 22:52:31 UTC (rev 166540)
@@ -51,6 +51,8 @@
, m_layerFlushTimer(this, &RemoteLayerTreeDrawingArea::layerFlushTimerFired)
, m_isFlushingSuspended(false)
, m_hasDeferredFlush(false)
+ , m_waitingForBackingStoreSwap(false)
+ , m_hadFlushDeferredWhileWaitingForBackingStoreSwap(false)
{
webPage->corePage()->settings().setForceCompositingMode(true);
#if PLATFORM(IOS)
@@ -312,13 +314,16 @@
return;
}
+ if (m_waitingForBackingStoreSwap) {
+ m_hadFlushDeferredWhileWaitingForBackingStoreSwap = true;
+ return;
+ }
+
m_webPage->layoutIfNeeded();
m_webPage->corePage()->mainFrame().view()->flushCompositingStateIncludingSubframes();
m_remoteLayerTreeContext->flushOutOfTreeLayers();
- ASSERT(m_rootLayer);
-
// FIXME: minize these transactions if nothing changed.
RemoteLayerTreeTransaction layerTransaction;
m_remoteLayerTreeContext->buildTransaction(layerTransaction, *m_rootLayer);
@@ -330,7 +335,21 @@
toRemoteScrollingCoordinator(m_webPage->scrollingCoordinator())->buildTransaction(scrollingTransaction);
#endif
+ m_waitingForBackingStoreSwap = true;
m_webPage->send(Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree(layerTransaction, scrollingTransaction));
}
+void RemoteLayerTreeDrawingArea::didUpdate()
+{
+ // FIXME: This should use a counted replacement for setLayerTreeStateIsFrozen, but
+ // the callers of that function are not strictly paired.
+
+ m_waitingForBackingStoreSwap = false;
+
+ if (m_hadFlushDeferredWhileWaitingForBackingStoreSwap) {
+ scheduleCompositingLayerFlush();
+ m_hadFlushDeferredWhileWaitingForBackingStoreSwap = false;
+ }
+}
+
} // namespace WebKit