2011-02-12 Chris Marrin <cmarrin@apple.com>
authorcmarrin@apple.com <cmarrin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Feb 2011 00:18:02 +0000 (00:18 +0000)
committercmarrin@apple.com <cmarrin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Feb 2011 00:18:02 +0000 (00:18 +0000)
        Reviewed by Dan Bernstein.

        Crash in RenderLayerCompositor::updateCompositingLayers when loading some sites
        https://bugs.webkit.org/show_bug.cgi?id=54345

        Some sites flip between composited and non-comosited state while loading. When the timing is
        right, when we flip out of compositing we will need to do a display while tossing all the
        compositing layers. This causes us to reenter RenderLayerCompositor::computeCompositingRequirements()
        while we are in the middle of tossing layers, which leads to a crash.

        The solution is to defer the logic of exiting compositing mode until the DrawingArea is finished
        doing its display, using a timer.

        * WebProcess/WebPage/DrawingAreaImpl.cpp:
        (WebKit::DrawingAreaImpl::DrawingAreaImpl):
        (WebKit::DrawingAreaImpl::setRootCompositingLayer):
        (WebKit::DrawingAreaImpl::enterAcceleratedCompositingMode):
        (WebKit::DrawingAreaImpl::exitAcceleratedCompositingMode):
        (WebKit::DrawingAreaImpl::exitAcceleratedCompositingModeSoon):
        * WebProcess/WebPage/DrawingAreaImpl.h:

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

Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h

index 45b6ff8..482f97e 100644 (file)
@@ -1,3 +1,26 @@
+2011-02-12  Chris Marrin  <cmarrin@apple.com>
+
+        Reviewed by Dan Bernstein.
+
+        Crash in RenderLayerCompositor::updateCompositingLayers when loading some sites
+        https://bugs.webkit.org/show_bug.cgi?id=54345
+
+        Some sites flip between composited and non-comosited state while loading. When the timing is
+        right, when we flip out of compositing we will need to do a display while tossing all the
+        compositing layers. This causes us to reenter RenderLayerCompositor::computeCompositingRequirements()
+        while we are in the middle of tossing layers, which leads to a crash.
+
+        The solution is to defer the logic of exiting compositing mode until the DrawingArea is finished
+        doing its display, using a timer.
+
+        * WebProcess/WebPage/DrawingAreaImpl.cpp:
+        (WebKit::DrawingAreaImpl::DrawingAreaImpl):
+        (WebKit::DrawingAreaImpl::setRootCompositingLayer):
+        (WebKit::DrawingAreaImpl::enterAcceleratedCompositingMode):
+        (WebKit::DrawingAreaImpl::exitAcceleratedCompositingMode):
+        (WebKit::DrawingAreaImpl::exitAcceleratedCompositingModeSoon):
+        * WebProcess/WebPage/DrawingAreaImpl.h:
+
 2011-02-12  Kevin Decker  <kdecker@apple.com>
 
         Reviewed by Dan Bernstein.
index 6fb93a0..c0c91fa 100644 (file)
@@ -64,6 +64,7 @@ DrawingAreaImpl::DrawingAreaImpl(WebPage* webPage, const WebPageCreationParamete
     , m_isWaitingForDidUpdate(false)
     , m_isPaintingSuspended(!parameters.isVisible)
     , m_displayTimer(WebProcess::shared().runLoop(), this, &DrawingAreaImpl::display)
+    , m_exitCompositingTimer(WebProcess::shared().runLoop(), this, &DrawingAreaImpl::exitAcceleratedCompositingMode)
 {
 }
 
@@ -182,14 +183,15 @@ void DrawingAreaImpl::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
             // We're actually entering accelerated compositing mode.
             enterAcceleratedCompositingMode(graphicsLayer);
         } else {
+            m_exitCompositingTimer.stop();
             // We're already in accelerated compositing mode, but the root compositing layer changed.
             m_layerTreeHost->setRootCompositingLayer(graphicsLayer);
         }
     } else {
         if (m_layerTreeHost) {
-            // We're exiting accelerated compositing mode.
-            exitAcceleratedCompositingMode();
-            ASSERT(!m_layerTreeHost);
+            // We'll exit accelerated compositing mode on a timer, to avoid re-entering
+            // compositing code via display() and layout.
+            exitAcceleratedCompositingModeSoon();
         }
     }
 }
@@ -277,6 +279,8 @@ void DrawingAreaImpl::resumePainting()
 
 void DrawingAreaImpl::enterAcceleratedCompositingMode(GraphicsLayer* graphicsLayer)
 {
+    m_exitCompositingTimer.stop();
+
     ASSERT(!m_layerTreeHost);
 
     m_layerTreeHost = LayerTreeHost::create(m_webPage);
@@ -295,6 +299,8 @@ void DrawingAreaImpl::enterAcceleratedCompositingMode(GraphicsLayer* graphicsLay
 
 void DrawingAreaImpl::exitAcceleratedCompositingMode()
 {
+    m_exitCompositingTimer.stop();
+
     ASSERT(m_layerTreeHost);
 
     m_layerTreeHost->invalidate();
@@ -317,6 +323,14 @@ void DrawingAreaImpl::exitAcceleratedCompositingMode()
         m_webPage->send(Messages::DrawingAreaProxy::ExitAcceleratedCompositingMode(generateSequenceNumber(), updateInfo));
 }
 
+void DrawingAreaImpl::exitAcceleratedCompositingModeSoon()
+{
+    if (m_exitCompositingTimer.isActive())
+        return;
+
+    m_exitCompositingTimer.startOneShot(0);
+}
+
 void DrawingAreaImpl::scheduleDisplay()
 {
     if (m_isWaitingForDidUpdate)
index eeeeab0..cbb94c2 100644 (file)
@@ -66,6 +66,7 @@ private:
     virtual void resumePainting();
 
     void enterAcceleratedCompositingMode(WebCore::GraphicsLayer*);
+    void exitAcceleratedCompositingModeSoon();
     void exitAcceleratedCompositingMode();
 
     void scheduleDisplay();
@@ -88,6 +89,7 @@ private:
     bool m_isPaintingSuspended;
 
     RunLoop::Timer<DrawingAreaImpl> m_displayTimer;
+    RunLoop::Timer<DrawingAreaImpl> m_exitCompositingTimer;
 
     // The layer tree host that handles accelerated compositing.
     RefPtr<LayerTreeHost> m_layerTreeHost;