<rdar://problem/9523192> REGRESSION (5.0.5-ToT, WebKit2): Flash to white when navigat...
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 31 May 2011 22:11:28 +0000 (22:11 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 31 May 2011 22:11:28 +0000 (22:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=61808

Reviewed by Simon Fraser.

WebKit1 has a mechanism to prevent the stale bits from the outgoing page from being erased
until the incoming page has layout. Adapt this in WebKit2 to prevent the composited layer tree
of the outgoing page from being torn down or updated until the incoming page has layout.

* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDidFirstLayout): Unfreeze the layer tree state.
(WebKit::WebFrameLoaderClient::frameLoadCompleted): Ditto.
(WebKit::WebFrameLoaderClient::provisionalLoadStarted): Freeze the layer tree state.

* WebProcess/WebPage/DrawingArea.h:
(WebKit::DrawingArea::setLayerTreeStateIsFrozen): Added.

* WebProcess/WebPage/DrawingAreaImpl.cpp:
(WebKit::DrawingAreaImpl::DrawingAreaImpl): Initialize new member variables.
(WebKit::DrawingAreaImpl::setLayerTreeStateIsFrozen): Added. When freezing, sets the flag and
disables layer flush scheduling and exiting accelerated compositing mode. When unfreezing,
clears the flag and exits compositing mode if needed.
(WebKit::DrawingAreaImpl::setRootCompositingLayer): Reset m_wantsToExitAcceleratedCompositingMode.
(WebKit::DrawingAreaImpl::enterAcceleratedCompositingMode): Ditto.
(WebKit::DrawingAreaImpl::exitAcceleratedCompositingMode): Ditto.
(WebKit::DrawingAreaImpl::exitAcceleratedCompositingModeSoon): If the layer tree state is frozen,
bail out but set m_wantsToExitAcceleratedCompositingMode.

* WebProcess/WebPage/DrawingAreaImpl.h:
* WebProcess/WebPage/LayerTreeHost.h:

* WebProcess/WebPage/ca/LayerTreeHostCA.cpp:
(WebKit::LayerTreeHostCA::LayerTreeHostCA): Initialize m_layerFlushSchedulingEnabled.

* WebProcess/WebPage/ca/LayerTreeHostCA.h:
* WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.h:

* WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm:
(WebKit::LayerTreeHostCAMac::scheduleLayerFlush): Bail out if scheduling is not enabled.
(WebKit::LayerTreeHostCAMac::setLayerFlushSchedulingEnabled): Added. Sets the flag. If disabling
flushing, cancels the pending flush.
(WebKit::LayerTreeHostCAMac::flushPendingLayerChangesRunLoopObserverCallback): Added an assertion.

* WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp:
(WebKit::LayerTreeHostCAWin::scheduleLayerFlush): Bail out if scheduling is not enabled.
(WebKit::LayerTreeHostCAWin::setLayerFlushSchedulingEnabled): Added. Sets the flag. If disabling
flushing, cancels the pending flush.

* WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h:

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

12 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
Source/WebKit2/WebProcess/WebPage/DrawingArea.h
Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h
Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h
Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.cpp
Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.h
Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.h
Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm
Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp
Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h

index b7934b494df1b15fbbb9ea419ca8cd5efc4640c7..d1ba7a20d99628e08bcbbe6bcc6aac71b64b5484 100644 (file)
@@ -1,3 +1,55 @@
+2011-05-31  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        <rdar://problem/9523192> REGRESSION (5.0.5-ToT, WebKit2): Flash to white when navigating between pages on wsj.com, other sites (when navigating away from composited page)
+        https://bugs.webkit.org/show_bug.cgi?id=61808
+
+        WebKit1 has a mechanism to prevent the stale bits from the outgoing page from being erased
+        until the incoming page has layout. Adapt this in WebKit2 to prevent the composited layer tree
+        of the outgoing page from being torn down or updated until the incoming page has layout.
+
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::dispatchDidFirstLayout): Unfreeze the layer tree state.
+        (WebKit::WebFrameLoaderClient::frameLoadCompleted): Ditto.
+        (WebKit::WebFrameLoaderClient::provisionalLoadStarted): Freeze the layer tree state.
+
+        * WebProcess/WebPage/DrawingArea.h:
+        (WebKit::DrawingArea::setLayerTreeStateIsFrozen): Added.
+
+        * WebProcess/WebPage/DrawingAreaImpl.cpp:
+        (WebKit::DrawingAreaImpl::DrawingAreaImpl): Initialize new member variables.
+        (WebKit::DrawingAreaImpl::setLayerTreeStateIsFrozen): Added. When freezing, sets the flag and
+        disables layer flush scheduling and exiting accelerated compositing mode. When unfreezing,
+        clears the flag and exits compositing mode if needed.
+        (WebKit::DrawingAreaImpl::setRootCompositingLayer): Reset m_wantsToExitAcceleratedCompositingMode.
+        (WebKit::DrawingAreaImpl::enterAcceleratedCompositingMode): Ditto.
+        (WebKit::DrawingAreaImpl::exitAcceleratedCompositingMode): Ditto.
+        (WebKit::DrawingAreaImpl::exitAcceleratedCompositingModeSoon): If the layer tree state is frozen,
+        bail out but set m_wantsToExitAcceleratedCompositingMode.
+
+        * WebProcess/WebPage/DrawingAreaImpl.h:
+        * WebProcess/WebPage/LayerTreeHost.h:
+
+        * WebProcess/WebPage/ca/LayerTreeHostCA.cpp:
+        (WebKit::LayerTreeHostCA::LayerTreeHostCA): Initialize m_layerFlushSchedulingEnabled.
+
+        * WebProcess/WebPage/ca/LayerTreeHostCA.h:
+        * WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.h:
+
+        * WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm:
+        (WebKit::LayerTreeHostCAMac::scheduleLayerFlush): Bail out if scheduling is not enabled.
+        (WebKit::LayerTreeHostCAMac::setLayerFlushSchedulingEnabled): Added. Sets the flag. If disabling
+        flushing, cancels the pending flush.
+        (WebKit::LayerTreeHostCAMac::flushPendingLayerChangesRunLoopObserverCallback): Added an assertion.
+
+        * WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp:
+        (WebKit::LayerTreeHostCAWin::scheduleLayerFlush): Bail out if scheduling is not enabled.
+        (WebKit::LayerTreeHostCAWin::setLayerFlushSchedulingEnabled): Added. Sets the flag. If disabling
+        flushing, cancels the pending flush.
+
+        * WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h:
+
 2011-05-31  ChangeLog  <james.cooley@nokia.com>
 
         Reviewed by Andreas Kling.
index 1781afa5f7c20a7a88837c782bab46a1598d59f3..5b4e582ed40711560d26ba0e33595fe723bf776f 100644 (file)
@@ -535,6 +535,9 @@ void WebFrameLoaderClient::dispatchDidFirstLayout()
 
     // Notify the UIProcess.
     webPage->send(Messages::WebPageProxy::DidFirstLayoutForFrame(m_frame->frameID(), InjectedBundleUserMessageEncoder(userData.get())));
+
+    if (m_frame == m_frame->page()->mainFrame())
+        webPage->drawingArea()->setLayerTreeStateIsFrozen(false);
 }
 
 void WebFrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
@@ -1020,7 +1023,12 @@ String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLSche
 
 void WebFrameLoaderClient::frameLoadCompleted()
 {
-    notImplemented();
+    WebPage* webPage = m_frame->page();
+    if (!webPage)
+        return;
+
+    if (m_frame == m_frame->page()->mainFrame())
+        webPage->drawingArea()->setLayerTreeStateIsFrozen(false);
 }
 
 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem*)
@@ -1042,7 +1050,12 @@ void WebFrameLoaderClient::restoreViewState()
 
 void WebFrameLoaderClient::provisionalLoadStarted()
 {
-    notImplemented();
+    WebPage* webPage = m_frame->page();
+    if (!webPage)
+        return;
+
+    if (m_frame == m_frame->page()->mainFrame())
+        webPage->drawingArea()->setLayerTreeStateIsFrozen(true);
 }
 
 void WebFrameLoaderClient::didFinishLoad()
index 075bcca1fdf28d56b2be92aceda8a9e0a4be5300..6fe73b2a6f4acdb0226f02bc739b481e8a7b11f8 100644 (file)
@@ -61,6 +61,7 @@ public:
     // FIXME: These should be pure virtual.
     virtual void pageBackgroundTransparencyChanged() { }
     virtual void forceRepaint() { }
+    virtual void setLayerTreeStateIsFrozen(bool) { }
 
     virtual void didInstallPageOverlay() { }
     virtual void didUninstallPageOverlay() { }
index 7e2987330b5966acc247cb339c606d92ad6018fb..1aa02e2792fcb22936d07c2e0f1b11d9d45f912d 100644 (file)
@@ -60,6 +60,8 @@ DrawingAreaImpl::DrawingAreaImpl(WebPage* webPage, const WebPageCreationParamete
     , m_shouldSendDidUpdateBackingStoreState(false)
     , m_isWaitingForDidUpdate(false)
     , m_compositingAccordingToProxyMessages(false)
+    , m_layerTreeStateIsFrozen(false)
+    , m_wantsToExitAcceleratedCompositingMode(false)
     , m_isPaintingSuspended(!parameters.isVisible)
     , m_alwaysUseCompositing(false)
     , m_lastDisplayTime(0)
@@ -149,6 +151,22 @@ void DrawingAreaImpl::scroll(const IntRect& scrollRect, const IntSize& scrollOff
     m_scrollOffset += scrollOffset;
 }
 
+void DrawingAreaImpl::setLayerTreeStateIsFrozen(bool isFrozen)
+{
+    if (m_layerTreeStateIsFrozen == isFrozen)
+        return;
+
+    m_layerTreeStateIsFrozen = isFrozen;
+
+    if (m_layerTreeHost)
+        m_layerTreeHost->setLayerFlushSchedulingEnabled(!isFrozen);
+
+    if (isFrozen)
+        m_exitCompositingTimer.stop();
+    else if (m_wantsToExitAcceleratedCompositingMode)
+        exitAcceleratedCompositingModeSoon();
+}
+
 void DrawingAreaImpl::forceRepaint()
 {
     setNeedsDisplay(m_webPage->bounds());
@@ -247,6 +265,7 @@ void DrawingAreaImpl::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
             // We're already in accelerated compositing mode, but the root compositing layer changed.
 
             m_exitCompositingTimer.stop();
+            m_wantsToExitAcceleratedCompositingMode = false;
 
             // If we haven't sent the EnterAcceleratedCompositingMode message, make sure that the
             // layer tree host calls us back after the next layer flush so we can send it then.
@@ -404,6 +423,7 @@ void DrawingAreaImpl::resumePainting()
 void DrawingAreaImpl::enterAcceleratedCompositingMode(GraphicsLayer* graphicsLayer)
 {
     m_exitCompositingTimer.stop();
+    m_wantsToExitAcceleratedCompositingMode = false;
 
     ASSERT(!m_layerTreeHost);
 
@@ -429,7 +449,10 @@ void DrawingAreaImpl::exitAcceleratedCompositingMode()
     if (m_alwaysUseCompositing)
         return;
 
+    ASSERT(!m_layerTreeStateIsFrozen);
+
     m_exitCompositingTimer.stop();
+    m_wantsToExitAcceleratedCompositingMode = false;
 
     ASSERT(m_layerTreeHost);
 
@@ -476,6 +499,11 @@ void DrawingAreaImpl::exitAcceleratedCompositingMode()
 
 void DrawingAreaImpl::exitAcceleratedCompositingModeSoon()
 {
+    if (m_layerTreeStateIsFrozen) {
+        m_wantsToExitAcceleratedCompositingMode = true;
+        return;
+    }
+
     if (exitAcceleratedCompositingModePending())
         return;
 
index 80b2828b09ebe50c248286f8530b990b4ed61e65..ca68b26be11c6cf243b307f44a8868e62b512c80 100644 (file)
@@ -49,6 +49,7 @@ private:
     // DrawingArea
     virtual void setNeedsDisplay(const WebCore::IntRect&);
     virtual void scroll(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset);
+    virtual void setLayerTreeStateIsFrozen(bool);
     virtual void forceRepaint();
 
     virtual void didInstallPageOverlay();
@@ -98,6 +99,14 @@ private:
     // True between sending the 'enter compositing' messages, and the 'exit compositing' message.
     bool m_compositingAccordingToProxyMessages;
 
+    // When true, we maintain the layer tree in its current state by not leaving accelerated compositing mode
+    // and not scheduling layer flushes.
+    bool m_layerTreeStateIsFrozen;
+
+    // True when we were asked to exit accelerated compositing mode but couldn't because layer tree
+    // state was frozen.
+    bool m_wantsToExitAcceleratedCompositingMode;
+
     // Whether painting is suspended. We'll still keep track of the dirty region but we 
     // won't paint until painting has resumed again.
     bool m_isPaintingSuspended;
index 9f78f58eb1691cac9c9cfbafc8a9df5b733313d6..97325aba58ed7c7fdb92da13c505197d54be1a77 100644 (file)
@@ -50,6 +50,7 @@ public:
 
     virtual const LayerTreeContext& layerTreeContext() = 0;
     virtual void scheduleLayerFlush() = 0;
+    virtual void setLayerFlushSchedulingEnabled(bool) = 0;
     virtual void setShouldNotifyAfterNextScheduledLayerFlush(bool) = 0;
     virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) = 0;
     virtual void invalidate() = 0;
index 201e4ec630ff6e9dd2852eacf41f6bf93385771d..f23111cff9b217923c8779dc2116bb40a36dca0c 100644 (file)
@@ -42,6 +42,7 @@ namespace WebKit {
 
 LayerTreeHostCA::LayerTreeHostCA(WebPage* webPage)
     : LayerTreeHost(webPage)
+    , m_layerFlushSchedulingEnabled(true)
     , m_isValid(true)
     , m_notifyAfterScheduledLayerFlush(false)
 {
index af685bb9bf629bb7c126dad49f352a63a0bf0343..c9131e1b7007bc8724f958c8f875dbc0ce8f24ac 100644 (file)
@@ -54,6 +54,8 @@ protected:
     // LayerTreeHostCA
     virtual void didPerformScheduledLayerFlush();
 
+    bool m_layerFlushSchedulingEnabled;
+
 private:
     // LayerTreeHost.
     virtual const LayerTreeContext& layerTreeContext();
index e3a0160b85aadef676b5e4bf0eb53ee192cd33a4..56b270253a1f604122c393885bbdff4fbcc9c7ca 100644 (file)
@@ -43,6 +43,7 @@ private:
 
     // LayerTreeHost.
     virtual void scheduleLayerFlush();
+    virtual void setLayerFlushSchedulingEnabled(bool);
     virtual void invalidate();
     virtual void sizeDidChange(const WebCore::IntSize& newSize);
     virtual void forceRepaint();
index 69cfa443d8eef170114683283c207579f796fea0..bf09bfb1bd91596d274a87bd9a2c931d91b7818e 100644 (file)
@@ -69,6 +69,9 @@ void LayerTreeHostCAMac::platformInitialize(LayerTreeContext& layerTreeContext)
 
 void LayerTreeHostCAMac::scheduleLayerFlush()
 {
+    if (!m_layerFlushSchedulingEnabled)
+        return;
+
     CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
     
     // Make sure we wake up the loop or the observer could be delayed until some other source fires.
@@ -85,6 +88,23 @@ void LayerTreeHostCAMac::scheduleLayerFlush()
     CFRunLoopAddObserver(currentRunLoop, m_flushPendingLayerChangesRunLoopObserver.get(), kCFRunLoopCommonModes);
 }
 
+void LayerTreeHostCAMac::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled)
+{
+    if (m_layerFlushSchedulingEnabled == layerFlushingEnabled)
+        return;
+
+    m_layerFlushSchedulingEnabled = layerFlushingEnabled;
+
+    if (m_layerFlushSchedulingEnabled)
+        return;
+
+    if (!m_flushPendingLayerChangesRunLoopObserver)
+        return;
+
+    CFRunLoopObserverInvalidate(m_flushPendingLayerChangesRunLoopObserver.get());
+    m_flushPendingLayerChangesRunLoopObserver = nullptr;
+}
+
 void LayerTreeHostCAMac::invalidate()
 {
     if (m_flushPendingLayerChangesRunLoopObserver) {
@@ -128,9 +148,13 @@ void LayerTreeHostCAMac::resumeRendering()
 
 void LayerTreeHostCAMac::flushPendingLayerChangesRunLoopObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity, void* context)
 {
+    LayerTreeHostCAMac* layerTreeHost = static_cast<LayerTreeHostCAMac*>(context);
+
+    ASSERT(layerTreeHost->m_layerFlushSchedulingEnabled);
+
     // This gets called outside of the normal event loop so wrap in an autorelease pool
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    static_cast<LayerTreeHostCAMac*>(context)->performScheduledLayerFlush();
+    layerTreeHost->performScheduledLayerFlush();
     [pool drain];
 }
 
index 9c192626c897296d1a289c61939972f317ed5593..50dc20c70696664b7b45c59b727fc469249e1aaf 100644 (file)
@@ -136,9 +136,25 @@ void LayerTreeHostCAWin::invalidate()
 
 void LayerTreeHostCAWin::scheduleLayerFlush()
 {
+    if (!m_layerFlushSchedulingEnabled)
+        return;
+
     LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
 }
 
+void LayerTreeHostCAWin::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled)
+{
+    if (m_layerFlushSchedulingEnabled == layerFlushingEnabled)
+        return;
+
+    m_layerFlushSchedulingEnabled = layerFlushingEnabled;
+
+    if (m_layerFlushSchedulingEnabled)
+        return;
+
+    LayerChangesFlusher::shared().cancelPendingFlush(thus);
+}
+
 bool LayerTreeHostCAWin::participatesInDisplay()
 {
     return true;
index 2d8fdd6d3c8c34920d461f75f9add8df4fca6562..655f10335454ec60c3a1dc566e3377d43518f413 100644 (file)
@@ -57,6 +57,7 @@ private:
     virtual void forceRepaint();
     virtual void sizeDidChange(const WebCore::IntSize& newSize);
     virtual void scheduleLayerFlush();
+    virtual void setLayerFlushSchedulingEnabled(bool);
     virtual bool participatesInDisplay();
     virtual bool needsDisplay();
     virtual double timeUntilNextDisplay();