[SCM] WebKit Debian packaging branch, webkit-1.3, updated. upstream/1.3.7-4207-g178b198

aroben at apple.com aroben at apple.com
Sun Feb 20 23:34:04 UTC 2011


The following commit has been merged in the webkit-1.3 branch:
commit 77cc9c576c85e59a047ebabfccd3f6f577f8f5ba
Author: aroben at apple.com <aroben at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Jan 21 19:35:43 2011 +0000

    Separate flushing layer changes from rendering in CACFLayerTreeHost
    
    Old model:
      1) A change is made to a GraphicsLayer.
      2) CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon is called, which schedules the
         render timer.
      3) The timer fires, which calls through to CACFLayerTreeHost::render, which performs the
         flush and then renders.
    
    New model:
      1) A change is made to a GraphicsLayer.
      2) CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon is called, which tells the new
         LayerChangesFlusher singleton that this host has changes that need to be flushed.
      3) LayerChangesFlusher sets up a Windows hook that will get called on the next iteration
         of the message loop.
      4) LayerChangesFlusher's hook is called, which calls through to
         CACFLayerTreeHost::flushPendingLayerChangesNow.
      5) CACFLayerTreeHost::flushPendingLayerChangesNow schedules the render timer so the changes
         that were just flushed to the context will be rendered.
    
    When a change is made to a PlatformCALayer that doesn't have a corresponding GraphicsLayer
    (e.g., for rendering <video>), CACFLayerTreeHost::layerTreeDidChange takes care of
    scheduling the flush.
    
    This change has three advantages:
      1) Whenever we flush layer changes, we first update layout. This can cause the page to
         leave compositing mode, which in turn can cause all references to the CACFLayerTreeHost
         to be dropped. By separating flushing (and thus updating layout) from rendering, we no
         longer have to worry about this happen during rendering.
      2) The new model is much more similar to how things work on the Mac, so will hopefully
         reduce the number of platform-specific bugs.
      3) CACFLayerTreeHost::shouldRender, which was used to make sure we didn't render while a
         layout was pending, is no longer needed. It actually hasn't been needed since at least
         r75987, but removing it before now would have resulted in a crash whenever a page came
         out of compositing mode due to (1).
    
    Fixes <http://webkit.org/b/52852> Flushing layer changes and rendering are intertwined in
    CACFLayerTreeHost, but shouldn't be
    
    Reviewed by Simon Fraser.
    
    Source/WebCore:
    
    * WebCore.vcproj/WebCore.vcproj: Added LayerChangesFlusher.
    
    * platform/graphics/ca/win/CACFLayerTreeHost.cpp: Added new #include, sorted existing
     #includes.
    (WebCore::CACFLayerTreeHost::CACFLayerTreeHost): Initialize new member.
    (WebCore::CACFLayerTreeHost::layerTreeDidChange): If we aren't already flushing changes,
    schedule a flush. Removed the call to renderSoon(), which now happens when the flush is
    finished.
    (WebCore::CACFLayerTreeHost::destroyRenderer): Cancel any pending flush we had scheduled. Also
    fixed a bug where we'd fail to clear the context's layer.
    (WebCore::CACFLayerTreeHost::render): Removed code to ask the client if we should render, which
    is no longer needed. Moved code to flush layer changes from here to
    flushPendingLayerChangesNow, which is called via the above-described mechanism.
    (WebCore::CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon): Schedule a flush. Removed
    code to schedule a render, which now happens after we've flushed.
    (WebCore::CACFLayerTreeHost::flushPendingLayerChangesNow): Added. Some of this code came from
    render(). First we flush GraphicsLayer changes from GraphicsLayers to their underlying
    PlatformCALayers, then we flush changes from PlatformCALayers to the context, then we
    schedule a render so that the changes will be rendered to the screen.
    
    * platform/graphics/ca/win/CACFLayerTreeHost.h: Removed
    CACFLayerTreeHostClient::shouldRender. Added flushPendingLayerChangesNow and
    m_isFlushingLayerChanges.
    
    * platform/graphics/ca/win/LayerChangesFlusher.cpp: Added.
    (WebCore::LayerChangesFlusher::shared):
    (WebCore::LayerChangesFlusher::LayerChangesFlusher):
    (WebCore::LayerChangesFlusher::flushPendingLayerChangesSoon):
    (WebCore::LayerChangesFlusher::cancelPendingFlush):
    (WebCore::LayerChangesFlusher::hookCallback):
    (WebCore::LayerChangesFlusher::hookFired):
    (WebCore::LayerChangesFlusher::setHook):
    (WebCore::LayerChangesFlusher::removeHook):
    
    * platform/graphics/ca/win/LayerChangesFlusher.cpp: Added.
    (WebCore::LayerChangesFlusher::shared): Returns the singleton.
    (WebCore::LayerChangesFlusher::LayerChangesFlusher): Initialize our members.
    (WebCore::LayerChangesFlusher::flushPendingLayerChangesSoon): Add the host to the set of
    hosts with changes that need to be flushed, and set up our hook if we haven't already.
    (WebCore::LayerChangesFlusher::cancelPendingFlush): Remove the host from the set of hosts
    with changes that need to be flushed. If we have no more such hosts, remove our hook, unless
    we're currently in the process of calling out to our hosts, in which case we'll take care of
    the hook once we're done calling out.
    (WebCore::LayerChangesFlusher::hookCallback): This is the function that Windows calls when
    our hook fires. Just calls through to hookFired on the singleton.
    (WebCore::LayerChangesFlusher::hookFired): Tell all the hosts with changes that needed to be
    flushed that it's time to flush. If no hosts re-added themselves to our set during this
    process, remove our hook.
    (WebCore::LayerChangesFlusher::setHook): Calls through to ::SetWindowsHookExW.
    (WebCore::LayerChangesFlusher::removeHook): Calls through to ::UnhookWindowsHookEx.
    
    * platform/graphics/ca/win/LayerChangesFlusher.h: Added.
    
    Source/WebKit/win:
    
    Update for CACFLayerTreeHost changes
    
    * WebView.cpp:
    (WebView::paint): Changed to flush layer changes via CACFLayerTreeHost, which will call back
    to our own flushing function if needed.
    
    * WebView.h: Removed shouldRender, which is no longer used or needed.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@76372 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 2669043..23b413d 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,99 @@
+2011-01-21  Adam Roben  <aroben at apple.com>
+
+        Separate flushing layer changes from rendering in CACFLayerTreeHost
+
+        Old model:
+          1) A change is made to a GraphicsLayer.
+          2) CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon is called, which schedules the
+             render timer.
+          3) The timer fires, which calls through to CACFLayerTreeHost::render, which performs the
+             flush and then renders.
+
+        New model:
+          1) A change is made to a GraphicsLayer.
+          2) CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon is called, which tells the new
+             LayerChangesFlusher singleton that this host has changes that need to be flushed.
+          3) LayerChangesFlusher sets up a Windows hook that will get called on the next iteration
+             of the message loop.
+          4) LayerChangesFlusher's hook is called, which calls through to
+             CACFLayerTreeHost::flushPendingLayerChangesNow.
+          5) CACFLayerTreeHost::flushPendingLayerChangesNow schedules the render timer so the changes
+             that were just flushed to the context will be rendered.
+
+        When a change is made to a PlatformCALayer that doesn't have a corresponding GraphicsLayer
+        (e.g., for rendering <video>), CACFLayerTreeHost::layerTreeDidChange takes care of
+        scheduling the flush.
+
+        This change has three advantages:
+          1) Whenever we flush layer changes, we first update layout. This can cause the page to
+             leave compositing mode, which in turn can cause all references to the CACFLayerTreeHost
+             to be dropped. By separating flushing (and thus updating layout) from rendering, we no
+             longer have to worry about this happen during rendering.
+          2) The new model is much more similar to how things work on the Mac, so will hopefully
+             reduce the number of platform-specific bugs.
+          3) CACFLayerTreeHost::shouldRender, which was used to make sure we didn't render while a
+             layout was pending, is no longer needed. It actually hasn't been needed since at least
+             r75987, but removing it before now would have resulted in a crash whenever a page came
+             out of compositing mode due to (1).
+
+        Fixes <http://webkit.org/b/52852> Flushing layer changes and rendering are intertwined in
+        CACFLayerTreeHost, but shouldn't be
+
+        Reviewed by Simon Fraser.
+
+        * WebCore.vcproj/WebCore.vcproj: Added LayerChangesFlusher.
+
+        * platform/graphics/ca/win/CACFLayerTreeHost.cpp: Added new #include, sorted existing
+        #includes.
+        (WebCore::CACFLayerTreeHost::CACFLayerTreeHost): Initialize new member.
+        (WebCore::CACFLayerTreeHost::layerTreeDidChange): If we aren't already flushing changes,
+        schedule a flush. Removed the call to renderSoon(), which now happens when the flush is
+        finished.
+        (WebCore::CACFLayerTreeHost::destroyRenderer): Cancel any pending flush we had scheduled. Also
+        fixed a bug where we'd fail to clear the context's layer.
+        (WebCore::CACFLayerTreeHost::render): Removed code to ask the client if we should render, which
+        is no longer needed. Moved code to flush layer changes from here to
+        flushPendingLayerChangesNow, which is called via the above-described mechanism.
+        (WebCore::CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon): Schedule a flush. Removed
+        code to schedule a render, which now happens after we've flushed.
+        (WebCore::CACFLayerTreeHost::flushPendingLayerChangesNow): Added. Some of this code came from
+        render(). First we flush GraphicsLayer changes from GraphicsLayers to their underlying
+        PlatformCALayers, then we flush changes from PlatformCALayers to the context, then we
+        schedule a render so that the changes will be rendered to the screen.
+
+        * platform/graphics/ca/win/CACFLayerTreeHost.h: Removed
+        CACFLayerTreeHostClient::shouldRender. Added flushPendingLayerChangesNow and
+        m_isFlushingLayerChanges.
+
+        * platform/graphics/ca/win/LayerChangesFlusher.cpp: Added.
+        (WebCore::LayerChangesFlusher::shared):
+        (WebCore::LayerChangesFlusher::LayerChangesFlusher):
+        (WebCore::LayerChangesFlusher::flushPendingLayerChangesSoon):
+        (WebCore::LayerChangesFlusher::cancelPendingFlush):
+        (WebCore::LayerChangesFlusher::hookCallback):
+        (WebCore::LayerChangesFlusher::hookFired):
+        (WebCore::LayerChangesFlusher::setHook):
+        (WebCore::LayerChangesFlusher::removeHook):
+
+        * platform/graphics/ca/win/LayerChangesFlusher.cpp: Added.
+        (WebCore::LayerChangesFlusher::shared): Returns the singleton.
+        (WebCore::LayerChangesFlusher::LayerChangesFlusher): Initialize our members.
+        (WebCore::LayerChangesFlusher::flushPendingLayerChangesSoon): Add the host to the set of
+        hosts with changes that need to be flushed, and set up our hook if we haven't already.
+        (WebCore::LayerChangesFlusher::cancelPendingFlush): Remove the host from the set of hosts
+        with changes that need to be flushed. If we have no more such hosts, remove our hook, unless
+        we're currently in the process of calling out to our hosts, in which case we'll take care of
+        the hook once we're done calling out.
+        (WebCore::LayerChangesFlusher::hookCallback): This is the function that Windows calls when
+        our hook fires. Just calls through to hookFired on the singleton.
+        (WebCore::LayerChangesFlusher::hookFired): Tell all the hosts with changes that needed to be
+        flushed that it's time to flush. If no hosts re-added themselves to our set during this
+        process, remove our hook.
+        (WebCore::LayerChangesFlusher::setHook): Calls through to ::SetWindowsHookExW.
+        (WebCore::LayerChangesFlusher::removeHook): Calls through to ::UnhookWindowsHookEx.
+
+        * platform/graphics/ca/win/LayerChangesFlusher.h: Added.
+
 2011-01-21  Simon Fraser  <simon.fraser at apple.com>
 
         Reviewed by Sam Weinig.
diff --git a/Source/WebCore/WebCore.vcproj/WebCore.vcproj b/Source/WebCore/WebCore.vcproj/WebCore.vcproj
index 165a193..009c8ea 100755
--- a/Source/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/Source/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -28895,6 +28895,46 @@
 							</FileConfiguration>
 						</File>
 						<File
+							RelativePath="..\platform\graphics\ca\win\LayerChangesFlusher.cpp"
+							>
+							<FileConfiguration
+								Name="Debug_Cairo_CFLite|Win32"
+								ExcludedFromBuild="true"
+								>
+								<Tool
+									Name="VCCLCompilerTool"
+								/>
+							</FileConfiguration>
+							<FileConfiguration
+								Name="Release_Cairo_CFLite|Win32"
+								ExcludedFromBuild="true"
+								>
+								<Tool
+									Name="VCCLCompilerTool"
+								/>
+							</FileConfiguration>
+						</File>
+						<File
+							RelativePath="..\platform\graphics\ca\win\LayerChangesFlusher.h"
+							>
+							<FileConfiguration
+								Name="Debug_Cairo_CFLite|Win32"
+								ExcludedFromBuild="true"
+								>
+								<Tool
+									Name="VCCustomBuildTool"
+								/>
+							</FileConfiguration>
+							<FileConfiguration
+								Name="Release_Cairo_CFLite|Win32"
+								ExcludedFromBuild="true"
+								>
+								<Tool
+									Name="VCCustomBuildTool"
+								/>
+							</FileConfiguration>
+						</File>
+						<File
 							RelativePath="..\platform\graphics\ca\win\PlatformCAAnimationWin.cpp"
 							>
 						</File>
diff --git a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp
index 61d76a0..1d27608 100644
--- a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp
@@ -24,15 +24,11 @@
  */
 
 #include "config.h"
+#include "CACFLayerTreeHost.h"
 
 #if USE(ACCELERATED_COMPOSITING)
 
-#ifndef NDEBUG
-#define D3D_DEBUG_INFO
-#endif
-
-#include "CACFLayerTreeHost.h"
-
+#include "LayerChangesFlusher.h"
 #include "PlatformCALayer.h"
 #include "WebCoreInstanceHandle.h"
 #include <WebKitSystemInterface/WebKitSystemInterface.h>
@@ -43,6 +39,11 @@
 #include <wtf/OwnPtr.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/StdLibExtras.h>
+
+#ifndef NDEBUG
+#define D3D_DEBUG_INFO
+#endif
+
 #include <d3d9.h>
 #include <d3dx9.h>
 
@@ -188,6 +189,7 @@ CACFLayerTreeHost::CACFLayerTreeHost()
     , m_renderTimer(this, &CACFLayerTreeHost::renderTimerFired)
     , m_mustResetLostDeviceBeforeRendering(false)
     , m_shouldFlushPendingGraphicsLayerChanges(false)
+    , m_isFlushingLayerChanges(false)
 {
     // Point the CACFContext to this
     wkCACFContextSetUserData(m_context, this);
@@ -260,7 +262,17 @@ void CACFLayerTreeHost::setRootChildLayer(PlatformCALayer* layer)
    
 void CACFLayerTreeHost::layerTreeDidChange()
 {
-    renderSoon();
+    if (m_isFlushingLayerChanges) {
+        // The layer tree is changing as a result of flushing GraphicsLayer changes to their
+        // underlying PlatformCALayers. We'll flush those changes to the context as part of that
+        // process, so there's no need to schedule another flush here.
+        return;
+    }
+
+    // The layer tree is changing as a result of someone modifying a PlatformCALayer that doesn't
+    // have a corresponding GraphicsLayer. Schedule a flush since we won't schedule one through the
+    // normal GraphicsLayer mechanisms.
+    LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
 }
 
 bool CACFLayerTreeHost::createRenderer()
@@ -337,7 +349,9 @@ bool CACFLayerTreeHost::createRenderer()
 
 void CACFLayerTreeHost::destroyRenderer()
 {
-    wkCACFContextSetLayer(m_context, m_rootLayer->platformLayer());
+    LayerChangesFlusher::shared().cancelPendingFlush(this);
+
+    wkCACFContextSetLayer(m_context, 0);
 
     wkCACFContextSetD3DDevice(m_context, 0);
     m_d3dDevice = 0;
@@ -425,19 +439,6 @@ void CACFLayerTreeHost::render(const Vector<CGRect>& windowDirtyRects)
         return;
     }
 
-    if (m_client && !m_client->shouldRender()) {
-        renderSoon();
-        return;
-    }
-
-    if (m_shouldFlushPendingGraphicsLayerChanges) {
-        m_client->flushPendingGraphicsLayerChanges();
-        m_shouldFlushPendingGraphicsLayerChanges = false;
-    }
-
-    // Flush the root layer to the render tree.
-    wkCACFContextFlush(m_context);
-
     // All pending animations will have been started with the flush. Fire the animationStarted calls
     double currentTime = WTF::currentTime();
     double currentMediaTime = CACurrentMediaTime();
@@ -526,7 +527,29 @@ void CACFLayerTreeHost::renderSoon()
 void CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon()
 {
     m_shouldFlushPendingGraphicsLayerChanges = true;
+    LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
+}
+
+void CACFLayerTreeHost::flushPendingLayerChangesNow()
+{
+    // Calling out to the client could cause our last reference to go away.
+    RefPtr<CACFLayerTreeHost> protector(this);
+
+    m_isFlushingLayerChanges = true;
+
+    // Flush changes stored up in GraphicsLayers to their underlying PlatformCALayers, if
+    // requested.
+    if (m_client && m_shouldFlushPendingGraphicsLayerChanges) {
+        m_shouldFlushPendingGraphicsLayerChanges = false;
+        m_client->flushPendingGraphicsLayerChanges();
+    }
+
+    // Flush changes stored up in PlatformCALayers to the context so they will be rendered.
+    wkCACFContextFlush(m_context);
+
     renderSoon();
+
+    m_isFlushingLayerChanges = false;
 }
 
 CGRect CACFLayerTreeHost::bounds() const
diff --git a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h
index ffe87ef..fc61f39 100644
--- a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h
+++ b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h
@@ -52,7 +52,6 @@ class PlatformCALayer;
 class CACFLayerTreeHostClient {
 public:
     virtual ~CACFLayerTreeHostClient() { }
-    virtual bool shouldRender() const = 0;
     virtual void flushPendingGraphicsLayerChanges() { }
 };
 
@@ -76,6 +75,7 @@ public:
     void paint();
     void resize();
     void flushPendingGraphicsLayerChangesSoon();
+    void flushPendingLayerChangesNow();
 
 protected:
     PlatformCALayer* rootLayer() const;
@@ -111,6 +111,7 @@ private:
     Timer<CACFLayerTreeHost> m_renderTimer;
     bool m_mustResetLostDeviceBeforeRendering;
     bool m_shouldFlushPendingGraphicsLayerChanges;
+    bool m_isFlushingLayerChanges;
     HashSet<RefPtr<PlatformCALayer> > m_pendingAnimatedLayers;
 
 #ifndef NDEBUG
diff --git a/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp b/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp
new file mode 100644
index 0000000..3fd857b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LayerChangesFlusher.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "CACFLayerTreeHost.h"
+#include "WebCoreInstanceHandle.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+LayerChangesFlusher& LayerChangesFlusher::shared()
+{
+    DEFINE_STATIC_LOCAL(LayerChangesFlusher, flusher, ());
+    return flusher;
+}
+
+LayerChangesFlusher::LayerChangesFlusher()
+    : m_hook(0)
+    , m_isCallingHosts(false)
+{
+}
+
+void LayerChangesFlusher::flushPendingLayerChangesSoon(CACFLayerTreeHost* host)
+{
+    if (!m_hostsWithChangesToFlush.add(host).second || m_hook)
+        return;
+
+    setHook();
+}
+
+void LayerChangesFlusher::cancelPendingFlush(CACFLayerTreeHost* host)
+{
+    m_hostsWithChangesToFlush.remove(host);
+
+    if (!m_hostsWithChangesToFlush.isEmpty() || !m_hook)
+        return;
+
+    // We handle removing the hook when we finish calling out to the hosts, so we shouldn't
+    // mess with it while we're in the process of calling them.
+    if (m_isCallingHosts)
+        return;
+
+    removeHook();
+}
+
+LRESULT LayerChangesFlusher::hookCallback(int code, WPARAM wParam, LPARAM lParam)
+{
+    return shared().hookFired(code, wParam, lParam);
+}
+
+LRESULT LayerChangesFlusher::hookFired(int code, WPARAM wParam, LPARAM lParam)
+{
+    ASSERT(m_hook);
+
+    // Calling out to the hosts can cause m_hostsWithChangesToFlush to be modified, so we copy it
+    // into a Vector first. We have to hold a reference to them because otherwise they could be
+    // destroyed while we're calling out to them.
+    Vector<RefPtr<CACFLayerTreeHost> > hosts;
+    copyToVector(m_hostsWithChangesToFlush, hosts);
+    m_hostsWithChangesToFlush.clear();
+
+    m_isCallingHosts = true;
+    for (size_t i = 0; i < hosts.size(); ++i)
+        hosts[i]->flushPendingLayerChangesNow();
+    m_isCallingHosts = false;
+
+    LRESULT result = ::CallNextHookEx(m_hook, code, wParam, lParam);
+
+    if (m_hostsWithChangesToFlush.isEmpty()) {
+        // We won't have any work to do next time around, so just remove our hook.
+        removeHook();
+    }
+
+    return result;
+}
+
+void LayerChangesFlusher::setHook()
+{
+    ASSERT(!m_hook);
+    ASSERT(!m_isCallingHosts);
+
+    DWORD threadID = ::GetCurrentThreadId();
+
+    m_hook = ::SetWindowsHookExW(WH_GETMESSAGE, hookCallback, instanceHandle(), threadID);
+    ASSERT_WITH_MESSAGE(m_hook, "::SetWindowsHookExW failed with error %lu", ::GetLastError());
+
+    // Post a message to the message queue to prevent ::GetMessage from blocking, which will ensure
+    // our hook is called soon.
+    ::PostThreadMessageW(threadID, WM_NULL, 0, 0);
+}
+
+void LayerChangesFlusher::removeHook()
+{
+    ASSERT(m_hook);
+    ASSERT(!m_isCallingHosts);
+
+    if (!::UnhookWindowsHookEx(m_hook))
+        ASSERT_WITH_MESSAGE(false, "::UnhookWindowsHookEx failed with error %lu", ::GetLastError());
+
+    m_hook = 0;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.h b/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.h
new file mode 100644
index 0000000..6a98a99
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LayerChangesFlusher_h
+#define LayerChangesFlusher_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <windows.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class CACFLayerTreeHost;
+
+class LayerChangesFlusher {
+    WTF_MAKE_NONCOPYABLE(LayerChangesFlusher);
+public:
+    static LayerChangesFlusher& shared();
+
+    void flushPendingLayerChangesSoon(CACFLayerTreeHost*);
+    void cancelPendingFlush(CACFLayerTreeHost*);
+
+private:
+    LayerChangesFlusher();
+    ~LayerChangesFlusher();
+
+    static LRESULT CALLBACK hookCallback(int code, WPARAM, LPARAM);
+    LRESULT hookFired(int code, WPARAM, LPARAM);
+    void setHook();
+    void removeHook();
+
+    HashSet<CACFLayerTreeHost*> m_hostsWithChangesToFlush;
+    HHOOK m_hook;
+    bool m_isCallingHosts;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // LayerChangesFlusher_h
diff --git a/Source/WebKit/win/ChangeLog b/Source/WebKit/win/ChangeLog
index 3e3cc49..b1981da 100644
--- a/Source/WebKit/win/ChangeLog
+++ b/Source/WebKit/win/ChangeLog
@@ -1,3 +1,18 @@
+2011-01-20  Adam Roben  <aroben at apple.com>
+
+        Update for CACFLayerTreeHost changes
+
+        Fixes <http://webkit.org/b/52852> Flushing layer changes and rendering are intertwined in
+        CACFLayerTreeHost, but shouldn't be
+
+        Reviewed by Simon Fraser.
+
+        * WebView.cpp:
+        (WebView::paint): Changed to flush layer changes via CACFLayerTreeHost, which will call back
+        to our own flushing function if needed.
+
+        * WebView.h: Removed shouldRender, which is no longer used or needed.
+
 2011-01-21  Adam Roben  <aroben at apple.com>
 
         Update for WKCACFLayerRenderer -> CACFLayerTreeHost rename
diff --git a/Source/WebKit/win/WebView.cpp b/Source/WebKit/win/WebView.cpp
index 5a33d5b..6e80785 100644
--- a/Source/WebKit/win/WebView.cpp
+++ b/Source/WebKit/win/WebView.cpp
@@ -990,7 +990,7 @@ void WebView::paint(HDC dc, LPARAM options)
 
 #if USE(ACCELERATED_COMPOSITING)
     if (isAcceleratedCompositing()) {
-        flushPendingGraphicsLayerChanges();
+        m_layerTreeHost->flushPendingLayerChangesNow();
         // Flushing might have taken us out of compositing mode.
         if (isAcceleratedCompositing()) {
             // FIXME: We need to paint into dc (if provided). <http://webkit.org/b/52578>
@@ -6506,18 +6506,6 @@ bool WebView::showRepaintCounter() const
     return m_page->settings()->showRepaintCounter();
 }
 
-bool WebView::shouldRender() const
-{
-    Frame* coreFrame = core(m_mainFrame);
-    if (!coreFrame)
-        return true;
-    FrameView* frameView = coreFrame->view();
-    if (!frameView)
-        return true;
-
-    return !frameView->layoutPending();
-}
-
 void WebView::flushPendingGraphicsLayerChanges()
 {
     Frame* coreFrame = core(m_mainFrame);
diff --git a/Source/WebKit/win/WebView.h b/Source/WebKit/win/WebView.h
index c81f6d6..1a993c6 100644
--- a/Source/WebKit/win/WebView.h
+++ b/Source/WebKit/win/WebView.h
@@ -948,7 +948,6 @@ private:
     virtual bool showRepaintCounter() const;
 
     // CACFLayerTreeHostClient
-    virtual bool shouldRender() const;
     virtual void flushPendingGraphicsLayerChanges();
 #endif
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list