2011-02-18 Anders Carlsson <andersca@apple.com>
authorandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Feb 2011 20:55:25 +0000 (20:55 +0000)
committerandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Feb 2011 20:55:25 +0000 (20:55 +0000)
        Reviewed by Simon Fraser.

        WKView flashes when entering/exiting compositing mode
        https://bugs.webkit.org/show_bug.cgi?id=54695
        <rdar://problem/9011554>

        * UIProcess/API/mac/WKView.mm:
        (-[WKView _exitAcceleratedCompositingMode]):
        Remove the layer hosting view before clearing out its layer, otherwise we can get
        white flashes when exiting accelerated compositing mode.

        * WebProcess/WebPage/DrawingAreaImpl.cpp:
        When entering accelerated compositing mode, we want to defer sending the message
        until we've actually committed the layer tree and pushed all changes over to the
        UI process.

        (WebKit::DrawingAreaImpl::layerHostDidFlushLayers):
        Tell the layer tree host to force a repaint. This will ensure that all layer tree
        changes are pushed over to the UI process. When that is done, send the new layer tree
        context over to the UI process.

        (WebKit::DrawingAreaImpl::setRootCompositingLayer):
        When exiting compositing mode in response to a didSetSize, we want to exit accelerated
        compositing mode right away to avoid flashes. This is safe since we've laid out the page
        already so we won't end up reentering setRootCompositingLayer.

        (WebKit::DrawingAreaImpl::enterAcceleratedCompositingMode):
        Tell the layer tree host to notify us when the next layer tree flush happened, so we can
        let the UI process know. If we're entering accelerated compositing mode in response to a
        SetSize message, the new layer tree context will be passed in the DidSetSize message.

        * WebProcess/WebPage/DrawingAreaImpl.h:
        Add layerHostDidFlushLayers.

        * WebProcess/WebPage/LayerTreeHost.h:
        Add setShouldNotifyAfterNextScheduledLayerFlush.

        * WebProcess/WebPage/mac/LayerTreeHostMac.h:
        Add a m_notifyAfterScheduledLayerFlush flag.

        * WebProcess/WebPage/mac/LayerTreeHostMac.mm:
        (WebKit::LayerTreeHostMac::LayerTreeHostMac):
        Initialize m_notifyAfterScheduledLayerFlush to false.

        (WebKit::LayerTreeHostMac::setShouldNotifyAfterNextScheduledLayerFlush):
        Set m_notifyAfterScheduledLayerFlush to true.

        (WebKit::LayerTreeHostMac::flushPendingLayerChangesRunLoopObserverCallback):
        If m_notifyAfterScheduledLayerFlush is true, call DrawingAreaImpl::layerHostDidFlushLayers.

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

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/mac/WKView.mm
Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h
Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h
Source/WebKit2/WebProcess/WebPage/mac/LayerTreeHostMac.h
Source/WebKit2/WebProcess/WebPage/mac/LayerTreeHostMac.mm

index b91ecf0..d14d691 100644 (file)
@@ -1,3 +1,55 @@
+2011-02-18  Anders Carlsson  <andersca@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        WKView flashes when entering/exiting compositing mode
+        https://bugs.webkit.org/show_bug.cgi?id=54695
+        <rdar://problem/9011554>
+
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView _exitAcceleratedCompositingMode]):
+        Remove the layer hosting view before clearing out its layer, otherwise we can get
+        white flashes when exiting accelerated compositing mode.
+
+        * WebProcess/WebPage/DrawingAreaImpl.cpp:
+        When entering accelerated compositing mode, we want to defer sending the message
+        until we've actually committed the layer tree and pushed all changes over to the
+        UI process.
+
+        (WebKit::DrawingAreaImpl::layerHostDidFlushLayers):
+        Tell the layer tree host to force a repaint. This will ensure that all layer tree
+        changes are pushed over to the UI process. When that is done, send the new layer tree
+        context over to the UI process.
+
+        (WebKit::DrawingAreaImpl::setRootCompositingLayer):
+        When exiting compositing mode in response to a didSetSize, we want to exit accelerated 
+        compositing mode right away to avoid flashes. This is safe since we've laid out the page
+        already so we won't end up reentering setRootCompositingLayer.
+
+        (WebKit::DrawingAreaImpl::enterAcceleratedCompositingMode):
+        Tell the layer tree host to notify us when the next layer tree flush happened, so we can
+        let the UI process know. If we're entering accelerated compositing mode in response to a
+        SetSize message, the new layer tree context will be passed in the DidSetSize message.
+
+        * WebProcess/WebPage/DrawingAreaImpl.h:
+        Add layerHostDidFlushLayers.
+
+        * WebProcess/WebPage/LayerTreeHost.h:
+        Add setShouldNotifyAfterNextScheduledLayerFlush.
+
+        * WebProcess/WebPage/mac/LayerTreeHostMac.h:
+        Add a m_notifyAfterScheduledLayerFlush flag.
+
+        * WebProcess/WebPage/mac/LayerTreeHostMac.mm:
+        (WebKit::LayerTreeHostMac::LayerTreeHostMac):
+        Initialize m_notifyAfterScheduledLayerFlush to false.
+
+        (WebKit::LayerTreeHostMac::setShouldNotifyAfterNextScheduledLayerFlush):
+        Set m_notifyAfterScheduledLayerFlush to true.
+
+        (WebKit::LayerTreeHostMac::flushPendingLayerChangesRunLoopObserverCallback):
+        If m_notifyAfterScheduledLayerFlush is true, call DrawingAreaImpl::layerHostDidFlushLayers.
+
 2011-02-18  Alexey Proskuryakov  <ap@apple.com>
 
         Reviewed by Adele Peterson.
index fd4b8df..2e1b81c 100644 (file)
@@ -1918,9 +1918,9 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I
 {
     ASSERT(_data->_layerHostingView);
 
+    [_data->_layerHostingView.get() removeFromSuperview];
     [_data->_layerHostingView.get() setLayer:nil];
     [_data->_layerHostingView.get() setWantsLayer:NO];
-    [_data->_layerHostingView.get() removeFromSuperview];
     
     _data->_layerHostingView = nullptr;
 }
index 0b41a94..f2f1c00 100644 (file)
@@ -185,6 +185,18 @@ void DrawingAreaImpl::setPageOverlayNeedsDisplay(const IntRect& rect)
     setNeedsDisplay(rect);
 }
 
+void DrawingAreaImpl::layerHostDidFlushLayers()
+{
+    ASSERT(m_layerTreeHost);
+
+    m_layerTreeHost->forceRepaint();
+
+    if (!m_layerTreeHost)
+        return;
+
+    m_webPage->send(Messages::DrawingAreaProxy::EnterAcceleratedCompositingMode(generateSequenceNumber(), m_layerTreeHost->layerTreeContext()));
+}
+
 void DrawingAreaImpl::attachCompositingContext()
 {
 }
@@ -210,7 +222,12 @@ void DrawingAreaImpl::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
             if (!m_alwaysUseCompositing) {
                 // We'll exit accelerated compositing mode on a timer, to avoid re-entering
                 // compositing code via display() and layout.
-                exitAcceleratedCompositingModeSoon();
+                // If we're leaving compositing mode because of a setSize, it is safe to
+                // exit accelerated compositing mode right away.
+                if (m_inSetSize)
+                    exitAcceleratedCompositingMode();
+                else
+                    exitAcceleratedCompositingModeSoon();
             }
         }
     }
@@ -304,6 +321,9 @@ void DrawingAreaImpl::enterAcceleratedCompositingMode(GraphicsLayer* graphicsLay
     ASSERT(!m_layerTreeHost);
 
     m_layerTreeHost = LayerTreeHost::create(m_webPage);
+    if (!m_inSetSize)
+        m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush();
+
     m_layerTreeHost->setRootCompositingLayer(graphicsLayer);
     
     // Non-composited content will now be handled exclusively by the layer tree host.
@@ -312,9 +332,6 @@ void DrawingAreaImpl::enterAcceleratedCompositingMode(GraphicsLayer* graphicsLay
     m_scrollOffset = IntSize();
     m_displayTimer.stop();
     m_isWaitingForDidUpdate = false;
-
-    if (!m_inSetSize)
-        m_webPage->send(Messages::DrawingAreaProxy::EnterAcceleratedCompositingMode(generateSequenceNumber(), m_layerTreeHost->layerTreeContext()));
 }
 
 void DrawingAreaImpl::exitAcceleratedCompositingMode()
index 03f118b..c7eb763 100644 (file)
@@ -40,6 +40,8 @@ public:
     static PassRefPtr<DrawingAreaImpl> create(WebPage*, const WebPageCreationParameters&);
     virtual ~DrawingAreaImpl();
 
+    void layerHostDidFlushLayers();
+
 private:
     DrawingAreaImpl(WebPage*, const WebPageCreationParameters&);
 
index 311e9ff..86c6cfc 100644 (file)
@@ -47,6 +47,7 @@ public:
 
     virtual const LayerTreeContext& layerTreeContext() = 0;
     virtual void scheduleLayerFlush() = 0;
+    virtual void setShouldNotifyAfterNextScheduledLayerFlush() = 0;
     virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) = 0;
     virtual void invalidate() = 0;
 
index 8468a8d..7cf619a 100644 (file)
@@ -47,6 +47,7 @@ private:
     // LayerTreeHost.
     virtual const LayerTreeContext& layerTreeContext();
     virtual void scheduleLayerFlush();
+    virtual void setShouldNotifyAfterNextScheduledLayerFlush();
     virtual void setRootCompositingLayer(WebCore::GraphicsLayer*);
     virtual void invalidate();
 
@@ -79,6 +80,10 @@ private:
     // Whether the layer tree host is valid or not.
     bool m_isValid;    
 
+    // Whether we should let the drawing area know the next time we've flushed
+    // layer tree changes.
+    bool m_notifyAfterScheduledLayerFlush;
+    
     // The root layer.
     OwnPtr<WebCore::GraphicsLayer> m_rootLayer;
 
index f913a34..3bf3202 100644 (file)
@@ -26,6 +26,7 @@
 #import "config.h"
 #import "LayerTreeHostMac.h"
 
+#import "DrawingAreaImpl.h"
 #import "WebPage.h"
 #import "WebProcess.h"
 #import <QuartzCore/CATransaction.h>
@@ -51,6 +52,7 @@ PassRefPtr<LayerTreeHostMac> LayerTreeHostMac::create(WebPage* webPage)
 LayerTreeHostMac::LayerTreeHostMac(WebPage* webPage)
     : LayerTreeHost(webPage)
     , m_isValid(true)
+    , m_notifyAfterScheduledLayerFlush(false)
 {
     mach_port_t serverPort = WebProcess::shared().compositingRenderServerPort();
     m_remoteLayerClient = WKCARemoteLayerClientMakeWithServerPort(serverPort);
@@ -116,6 +118,11 @@ void LayerTreeHostMac::scheduleLayerFlush()
     CFRunLoopAddObserver(currentRunLoop, m_flushPendingLayerChangesRunLoopObserver.get(), kCFRunLoopCommonModes);
 }
 
+void LayerTreeHostMac::setShouldNotifyAfterNextScheduledLayerFlush()
+{
+    m_notifyAfterScheduledLayerFlush = true;
+}
+
 void LayerTreeHostMac::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
 {
     m_nonCompositedContentLayer->removeAllChildren();
@@ -250,6 +257,12 @@ void LayerTreeHostMac::flushPendingLayerChangesRunLoopObserverCallback()
     ASSERT(m_flushPendingLayerChangesRunLoopObserver);
     CFRunLoopObserverInvalidate(m_flushPendingLayerChangesRunLoopObserver.get());
     m_flushPendingLayerChangesRunLoopObserver = 0;
+
+    if (m_notifyAfterScheduledLayerFlush) {
+        // Let the drawing area know that we've done a flush of the layer changes.
+        static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->layerHostDidFlushLayers();
+        m_notifyAfterScheduledLayerFlush = false;
+    }
 }
 
 bool LayerTreeHostMac::flushPendingLayerChanges()