Render accelerated content into a web process-owned child HWND
authoraroben@apple.com <aroben@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Jun 2011 18:39:19 +0000 (18:39 +0000)
committeraroben@apple.com <aroben@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Jun 2011 18:39:19 +0000 (18:39 +0000)
This allows us to use WKCACFView's far more efficient kWKCACFViewDrawingDestinationWindow
mode, which gives us asynchronous rendering on a background thread and doesn't require us to
read bits off the GPU back into system memory.

A new class, WKCACFViewWindow, represents the child HWND. The child HWND is placed at the
bottom of the z-order so it won't obscure any other child HWNDs (i.e., windowed plugins).
The child HWND is made transparent to mouse events so that WKView will continue to receive
mouse events even though it is obscured by the child HWND.

There is now a bunch of dead code in DrawingAreaImpl to handle our old rendering model. I'll
remove that in a future patch.

Fixes <http://webkit.org/b/58054> <rdar://problem/9249839> REGRESSION (WebKit2): Accelerated
CSS animations have a lower framerate than in WebKit1

Reviewed by Anders Carlsson.

* Shared/LayerTreeContext.h: Added HWND member on Windows.

* Shared/win/CoalescedWindowGeometriesUpdater.cpp:
(WebKit::CoalescedWindowGeometriesUpdater::updateGeometries):
* Shared/win/CoalescedWindowGeometriesUpdater.h:
Added new BringToTopOrNot argument. Allows the caller to specify that all windows being
updated should also be brought to the top of the z-order.

* Shared/win/LayerTreeContextWin.cpp:
(WebKit::LayerTreeContext::LayerTreeContext):
(WebKit::LayerTreeContext::~LayerTreeContext):
(WebKit::LayerTreeContext::encode):
(WebKit::LayerTreeContext::decode):
(WebKit::LayerTreeContext::isEmpty):
(WebKit::operator==):
Implemented based on new window member.

* UIProcess/win/WebView.cpp:
(WebKit::WebView::WebView): Initialize new member.
(WebKit::WebView::onSizeEvent): Resize the layer host window to cover our entire view, if we
have one.
(WebKit::WebView::enterAcceleratedCompositingMode): Store, position, and show the layer host
window.
(WebKit::WebView::exitAcceleratedCompositingMode): Destroy the layer host window.
(WebKit::WebView::updateChildWindowGeometries): Updated for change to
CoalescedWindowGeometriesUpdater.

* UIProcess/win/WebView.h: Added m_layerHostWindow member.

* WebProcess/WebPage/LayerTreeHost.h: Added scheduleChildWindowGeometryUpdate.

* WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp:
(WebKit::LayerTreeHostCAWin::supportsAcceleratedCompositing): Simplified by using
WKCACFViewWindow.

(WebKit::LayerTreeHostCAWin::LayerTreeHostCAWin): Removed initialization of a removed
member.
(WebKit::LayerTreeHostCAWin::platformInitialize): Changed to use WKCACFViewWindow,
kWKCACFViewDrawingDestinationWindow, and to initialize the LayerTreeContext.
(WebKit::LayerTreeHostCAWin::invalidate): Leak our window and tell it to clean up after
itself. The UI process will take care of destroying the window when it finishes switching
out of accelerated compositing mode. Removed a WKCACFViewUpdate call that is now handled by
WKCACFViewWindow.
(WebKit::LayerTreeHostCAWin::scheduleChildWindowGeometryUpdate): Added. Calls through to
m_geometriesUpdater.
(WebKit::LayerTreeHostCAWin::sizeDidChange): Updated to use WKCACFViewWindow.
(WebKit::LayerTreeHostCAWin::contextDidChange): Update child window geometries now to keep
them (almost) in sync with the accelerated content. <http://webkit.org/b/61867> covers the
slight asynchrony that still exists.
(WebKit::LayerTreeHostCAWin::setRootCompositingLayer): Don't flush any changes when we don't
have a root layer. This prevents a flash of white when switching out of compositing mode.

* WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h: Added m_window and m_geometriesUpdater.
Removed code related to the old, synchronous display model.

* WebProcess/WebPage/ca/win/WKCACFViewWindow.cpp: Added.
(WebKit::WKCACFViewWindow::WKCACFViewWindow): Initialize members and create our window.
(WebKit::WKCACFViewWindow::~WKCACFViewWindow): Destroy our window if needed.
(WebKit::WKCACFViewWindow::onCustomDestroy): Just call ::DestroyWindow.
(WebKit::WKCACFViewWindow::onDestroy): Tell our view not to render into our window anymore.
(WebKit::WKCACFViewWindow::onEraseBackground): Tell Windows not to erase us.
(WebKit::WKCACFViewWindow::onNCDestroy): Clear out m_window since it's now pointing to a
destroy window, and destroy ourselves if requested.
(WebKit::WKCACFViewWindow::onPaint): Tell the view to draw, then clear our invalid region.
(WebKit::WKCACFViewWindow::onPrintClient): Tell our view to draw into the given HDC.
(WebKit::WKCACFViewWindow::registerClass): Register our class (duh).
(WebKit::WKCACFViewWindow::staticWndProc): Get the WKCACFViewWindow pointer, or store the
pointer if needed, then call through to wndProc.
(WebKit::WKCACFViewWindow::wndProc): Call out to the appropriate handler function.

* WebProcess/WebPage/ca/win/WKCACFViewWindow.h: Added.
(WebKit::WKCACFViewWindow::setDeletesSelfWhenWindowDestroyed): Simple setter.
(WebKit::WKCACFViewWindow::window): Simple getter.

* WebProcess/WebPage/win/DrawingAreaImplWin.cpp:
(WebKit::DrawingAreaImpl::scheduleChildWindowGeometryUpdate): Let the LayerTreeHost handle
the geometry update, if we have one.

* win/WebKit2.vcproj: Added WKCACFViewWindow files.

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

14 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/LayerTreeContext.h
Source/WebKit2/Shared/win/CoalescedWindowGeometriesUpdater.cpp
Source/WebKit2/Shared/win/CoalescedWindowGeometriesUpdater.h
Source/WebKit2/Shared/win/LayerTreeContextWin.cpp
Source/WebKit2/UIProcess/win/WebView.cpp
Source/WebKit2/UIProcess/win/WebView.h
Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h
Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp
Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h
Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.cpp [new file with mode: 0644]
Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.h [new file with mode: 0644]
Source/WebKit2/WebProcess/WebPage/win/DrawingAreaImplWin.cpp
Source/WebKit2/win/WebKit2.vcproj

index 6832577..13f9d75 100644 (file)
@@ -1,5 +1,106 @@
 2011-06-01  Adam Roben  <aroben@apple.com>
 
+        Render accelerated content into a web process-owned child HWND
+
+        This allows us to use WKCACFView's far more efficient kWKCACFViewDrawingDestinationWindow
+        mode, which gives us asynchronous rendering on a background thread and doesn't require us to
+        read bits off the GPU back into system memory.
+
+        A new class, WKCACFViewWindow, represents the child HWND. The child HWND is placed at the
+        bottom of the z-order so it won't obscure any other child HWNDs (i.e., windowed plugins).
+        The child HWND is made transparent to mouse events so that WKView will continue to receive
+        mouse events even though it is obscured by the child HWND.
+
+        There is now a bunch of dead code in DrawingAreaImpl to handle our old rendering model. I'll
+        remove that in a future patch.
+
+        Fixes <http://webkit.org/b/58054> <rdar://problem/9249839> REGRESSION (WebKit2): Accelerated
+        CSS animations have a lower framerate than in WebKit1
+
+        Reviewed by Anders Carlsson.
+
+        * Shared/LayerTreeContext.h: Added HWND member on Windows.
+
+        * Shared/win/CoalescedWindowGeometriesUpdater.cpp:
+        (WebKit::CoalescedWindowGeometriesUpdater::updateGeometries):
+        * Shared/win/CoalescedWindowGeometriesUpdater.h:
+        Added new BringToTopOrNot argument. Allows the caller to specify that all windows being
+        updated should also be brought to the top of the z-order.
+
+        * Shared/win/LayerTreeContextWin.cpp:
+        (WebKit::LayerTreeContext::LayerTreeContext):
+        (WebKit::LayerTreeContext::~LayerTreeContext):
+        (WebKit::LayerTreeContext::encode):
+        (WebKit::LayerTreeContext::decode):
+        (WebKit::LayerTreeContext::isEmpty):
+        (WebKit::operator==):
+        Implemented based on new window member.
+
+        * UIProcess/win/WebView.cpp:
+        (WebKit::WebView::WebView): Initialize new member.
+        (WebKit::WebView::onSizeEvent): Resize the layer host window to cover our entire view, if we
+        have one.
+        (WebKit::WebView::enterAcceleratedCompositingMode): Store, position, and show the layer host
+        window.
+        (WebKit::WebView::exitAcceleratedCompositingMode): Destroy the layer host window.
+        (WebKit::WebView::updateChildWindowGeometries): Updated for change to
+        CoalescedWindowGeometriesUpdater.
+
+        * UIProcess/win/WebView.h: Added m_layerHostWindow member.
+
+        * WebProcess/WebPage/LayerTreeHost.h: Added scheduleChildWindowGeometryUpdate.
+
+        * WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp:
+        (WebKit::LayerTreeHostCAWin::supportsAcceleratedCompositing): Simplified by using
+        WKCACFViewWindow.
+
+        (WebKit::LayerTreeHostCAWin::LayerTreeHostCAWin): Removed initialization of a removed
+        member.
+        (WebKit::LayerTreeHostCAWin::platformInitialize): Changed to use WKCACFViewWindow,
+        kWKCACFViewDrawingDestinationWindow, and to initialize the LayerTreeContext.
+        (WebKit::LayerTreeHostCAWin::invalidate): Leak our window and tell it to clean up after
+        itself. The UI process will take care of destroying the window when it finishes switching
+        out of accelerated compositing mode. Removed a WKCACFViewUpdate call that is now handled by
+        WKCACFViewWindow.
+        (WebKit::LayerTreeHostCAWin::scheduleChildWindowGeometryUpdate): Added. Calls through to
+        m_geometriesUpdater.
+        (WebKit::LayerTreeHostCAWin::sizeDidChange): Updated to use WKCACFViewWindow.
+        (WebKit::LayerTreeHostCAWin::contextDidChange): Update child window geometries now to keep
+        them (almost) in sync with the accelerated content. <http://webkit.org/b/61867> covers the
+        slight asynchrony that still exists.
+        (WebKit::LayerTreeHostCAWin::setRootCompositingLayer): Don't flush any changes when we don't
+        have a root layer. This prevents a flash of white when switching out of compositing mode.
+
+        * WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h: Added m_window and m_geometriesUpdater.
+        Removed code related to the old, synchronous display model.
+
+        * WebProcess/WebPage/ca/win/WKCACFViewWindow.cpp: Added.
+        (WebKit::WKCACFViewWindow::WKCACFViewWindow): Initialize members and create our window.
+        (WebKit::WKCACFViewWindow::~WKCACFViewWindow): Destroy our window if needed.
+        (WebKit::WKCACFViewWindow::onCustomDestroy): Just call ::DestroyWindow.
+        (WebKit::WKCACFViewWindow::onDestroy): Tell our view not to render into our window anymore.
+        (WebKit::WKCACFViewWindow::onEraseBackground): Tell Windows not to erase us.
+        (WebKit::WKCACFViewWindow::onNCDestroy): Clear out m_window since it's now pointing to a
+        destroy window, and destroy ourselves if requested.
+        (WebKit::WKCACFViewWindow::onPaint): Tell the view to draw, then clear our invalid region.
+        (WebKit::WKCACFViewWindow::onPrintClient): Tell our view to draw into the given HDC.
+        (WebKit::WKCACFViewWindow::registerClass): Register our class (duh).
+        (WebKit::WKCACFViewWindow::staticWndProc): Get the WKCACFViewWindow pointer, or store the
+        pointer if needed, then call through to wndProc.
+        (WebKit::WKCACFViewWindow::wndProc): Call out to the appropriate handler function.
+
+        * WebProcess/WebPage/ca/win/WKCACFViewWindow.h: Added.
+        (WebKit::WKCACFViewWindow::setDeletesSelfWhenWindowDestroyed): Simple setter.
+        (WebKit::WKCACFViewWindow::window): Simple getter.
+
+        * WebProcess/WebPage/win/DrawingAreaImplWin.cpp:
+        (WebKit::DrawingAreaImpl::scheduleChildWindowGeometryUpdate): Let the LayerTreeHost handle
+        the geometry update, if we have one.
+
+        * win/WebKit2.vcproj: Added WKCACFViewWindow files.
+
+2011-06-01  Adam Roben  <aroben@apple.com>
+
         Route plugin window geometry updates through the DrawingArea
 
         This will allow the geometry updates to be handled by the LayerTreeHost in compositing mode
index 0fb552a..8667c98 100644 (file)
@@ -45,6 +45,8 @@ public:
 
 #if PLATFORM(MAC)
     uint32_t contextID;
+#elif PLATFORM(WIN)
+    HWND window;
 #endif
 };
 
index 32c60f9..eed2d6e 100644 (file)
@@ -55,7 +55,7 @@ static void setWindowRegion(HWND window, PassOwnPtr<HRGN> popRegion)
     region.leakPtr();
 }
 
-void CoalescedWindowGeometriesUpdater::updateGeometries()
+void CoalescedWindowGeometriesUpdater::updateGeometries(BringToTopOrNot bringToTopOrNot)
 {
     HashMap<HWND, WindowGeometry> geometries;
     geometries.swap(m_geometries);
@@ -68,13 +68,21 @@ void CoalescedWindowGeometriesUpdater::updateGeometries()
         if (!::IsWindow(geometry.window))
             continue;
 
-        UINT flags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER;
+        UINT flags = SWP_NOACTIVATE;
         if (geometry.visible)
             flags |= SWP_SHOWWINDOW;
         else
             flags |= SWP_HIDEWINDOW;
 
-        deferWindowPos = ::DeferWindowPos(deferWindowPos, geometry.window, 0, geometry.frame.x(), geometry.frame.y(), geometry.frame.width(), geometry.frame.height(), flags);
+        HWND hwndInsertAfter;
+        if (bringToTopOrNot == BringToTop)
+            hwndInsertAfter = HWND_TOP;
+        else {
+            hwndInsertAfter = 0;
+            flags |= SWP_NOOWNERZORDER | SWP_NOZORDER;
+        }
+
+        deferWindowPos = ::DeferWindowPos(deferWindowPos, geometry.window, hwndInsertAfter, geometry.frame.x(), geometry.frame.y(), geometry.frame.width(), geometry.frame.height(), flags);
 
         setWindowRegion(geometry.window, adoptPtr(::CreateRectRgn(geometry.clipRect.x(), geometry.clipRect.y(), geometry.clipRect.maxX(), geometry.clipRect.maxY())));
     }
index a9644bc..5fc9445 100644 (file)
@@ -33,6 +33,8 @@ namespace WebKit {
 
 struct WindowGeometry;
 
+enum BringToTopOrNot { BringToTop, DoNotBringToTop };
+
 class CoalescedWindowGeometriesUpdater {
     WTF_MAKE_NONCOPYABLE(CoalescedWindowGeometriesUpdater);
 public:
@@ -40,7 +42,7 @@ public:
     ~CoalescedWindowGeometriesUpdater();
 
     void addPendingUpdate(const WindowGeometry&);
-    void updateGeometries();
+    void updateGeometries(BringToTopOrNot);
 
 private:
     HashMap<HWND, WindowGeometry> m_geometries;
index 9159976..2cdf2b3 100644 (file)
 #include "config.h"
 #include "LayerTreeContext.h"
 
-#include <WebCore/NotImplemented.h>
+#include "ArgumentCoders.h"
 
 namespace WebKit {
 
 LayerTreeContext::LayerTreeContext()
+    : window(0)
 {
-    notImplemented();
 }
 
 LayerTreeContext::~LayerTreeContext()
 {
-    notImplemented();
 }
 
-void LayerTreeContext::encode(CoreIPC::ArgumentEncoder*) const
+void LayerTreeContext::encode(CoreIPC::ArgumentEncoder* encoder) const
 {
-    notImplemented();
+    encoder->encodeUInt64(reinterpret_cast<uint64_t>(window));
 }
 
-bool LayerTreeContext::decode(CoreIPC::ArgumentDecoder*, LayerTreeContext&)
+bool LayerTreeContext::decode(CoreIPC::ArgumentDecoder* decoder, LayerTreeContext& context)
 {
-    notImplemented();
+    uint64_t window;
+    if (!decoder->decode(window))
+        return false;
+
+    context.window = reinterpret_cast<HWND>(window);
     return true;
 }
 
 bool LayerTreeContext::isEmpty() const
 {
-    notImplemented();
-    return true;
+    return !window;
 }
 
-bool operator==(const LayerTreeContext&, const LayerTreeContext&)
+bool operator==(const LayerTreeContext& a, const LayerTreeContext& b)
 {
-    notImplemented();
-    return true;
+    return a.window == b.window;
 }
 
 } // namespace WebKit
index 6367d58..6446ca4 100644 (file)
@@ -35,6 +35,7 @@
 #include "Region.h"
 #include "RunLoop.h"
 #include "WKAPICast.h"
+#include "WKCACFViewWindow.h"
 #include "WebContext.h"
 #include "WebContextMenuProxyWin.h"
 #include "WebEditCommandProxy.h"
@@ -276,6 +277,9 @@ WebView::WebView(RECT rect, WebContext* context, WebPageGroup* pageGroup, HWND p
     , m_lastPanY(0)
     , m_overPanY(0)
     , m_gestureReachedScrollingLimit(false)
+#if USE(ACCELERATED_COMPOSITING)
+    , m_layerHostWindow(0)
+#endif
 {
     registerWebViewWindowClass();
 
@@ -729,6 +733,11 @@ LRESULT WebView::onSizeEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
         m_nextResizeScrollOffset = IntSize();
     }
 
+#if USE(ACCELERATED_COMPOSITING)
+    if (m_layerHostWindow)
+        ::MoveWindow(m_layerHostWindow, 0, 0, width, height, FALSE);
+#endif
+
     handled = true;
     return 0;
 }
@@ -1509,16 +1518,25 @@ void WebView::setIsVisible(bool isVisible)
 
 #if USE(ACCELERATED_COMPOSITING)
 
-void WebView::enterAcceleratedCompositingMode(const LayerTreeContext&)
+void WebView::enterAcceleratedCompositingMode(const LayerTreeContext& context)
 {
-    // FIXME: Implement.
-    ASSERT_NOT_REACHED();
+    ASSERT(!context.isEmpty());
+
+    m_layerHostWindow = context.window;
+
+    IntSize size = viewSize();
+    // Ensure the layer host window is behind all other child windows (since otherwise it would obscure them).
+    ::SetWindowPos(m_layerHostWindow, HWND_BOTTOM, 0, 0, size.width(), size.height(), SWP_SHOWWINDOW | SWP_NOACTIVATE);
 }
 
 void WebView::exitAcceleratedCompositingMode()
 {
-    // FIXME: Implement.
-    ASSERT_NOT_REACHED();
+    ASSERT(m_layerHostWindow);
+
+    // Tell the WKCACFViewWindow to destroy itself. We can't call ::DestroyWindow directly because
+    // the window is owned by another thread.
+    ::PostMessageW(m_layerHostWindow, WKCACFViewWindow::customDestroyMessage, 0, 0);
+    m_layerHostWindow = 0;
 }
 
 #endif // USE(ACCELERATED_COMPOSITING)
@@ -1535,7 +1553,7 @@ void WebView::scheduleChildWindowGeometryUpdate(const WindowGeometry& geometry)
 
 void WebView::updateChildWindowGeometries()
 {
-    m_geometriesUpdater.updateGeometries();
+    m_geometriesUpdater.updateGeometries(DoNotBringToTop);
 }
 
 // WebCore::WindowMessageListener
index b5f76c0..48b53e7 100644 (file)
@@ -280,6 +280,10 @@ private:
 #if ENABLE(FULLSCREEN_API)
     OwnPtr<WebCore::FullScreenController> m_fullScreenController;
 #endif
+
+#if USE(ACCELERATED_COMPOSITING)
+    HWND m_layerHostWindow;
+#endif
 };
 
 } // namespace WebKit
index 97325ab..6d274ef 100644 (file)
@@ -41,6 +41,10 @@ class LayerTreeContext;
 class UpdateInfo;
 class WebPage;
 
+#if PLATFORM(WIN)
+struct WindowGeometry;
+#endif
+
 class LayerTreeHost : public RefCounted<LayerTreeHost> {
 public:
     static PassRefPtr<LayerTreeHost> create(WebPage*);
@@ -74,6 +78,10 @@ public:
     virtual double timeUntilNextDisplay() { ASSERT_NOT_REACHED(); return 0; }
     virtual void display(UpdateInfo&) { ASSERT_NOT_REACHED(); }
 
+#if PLATFORM(WIN)
+    virtual void scheduleChildWindowGeometryUpdate(const WindowGeometry&) = 0;
+#endif
+
 protected:
     explicit LayerTreeHost(WebPage*);
 
index a4677e1..467d38d 100644 (file)
@@ -31,8 +31,8 @@
 #include "DrawingAreaImpl.h"
 #include "ShareableBitmap.h"
 #include "UpdateInfo.h"
+#include "WKCACFViewWindow.h"
 #include "WebPage.h"
-#include <WebCore/DefWndProcWindowClass.h>
 #include <WebCore/GraphicsLayerCA.h>
 #include <WebCore/LayerChangesFlusher.h>
 #include <WebCore/PlatformCALayer.h>
@@ -52,15 +52,6 @@ using namespace WebCore;
 
 namespace WebKit {
 
-static HWND dummyWindow;
-static size_t validLayerTreeHostCount;
-
-// This window is never shown. It is only needed so that D3D can determine the display mode, etc.
-static HWND createDummyWindow()
-{
-    return ::CreateWindowW(defWndProcWindowClassName(), 0, WS_POPUP, 0, 0, 10, 10, 0, 0, instanceHandle(), 0);
-}
-
 bool LayerTreeHostCAWin::supportsAcceleratedCompositing()
 {
     static bool initialized;
@@ -69,17 +60,14 @@ bool LayerTreeHostCAWin::supportsAcceleratedCompositing()
         return supportsAcceleratedCompositing;
     initialized = true;
 
-    ASSERT(!dummyWindow);
-    dummyWindow = createDummyWindow();
-    RetainPtr<WKCACFViewRef> view(AdoptCF, WKCACFViewCreate(kWKCACFViewDrawingDestinationImage));
+    RetainPtr<WKCACFViewRef> view(AdoptCF, WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow));
+    WKCACFViewWindow dummyWindow(view.get(), 0, 0);
     CGRect fakeBounds = CGRectMake(0, 0, 10, 10);
-    WKCACFViewUpdate(view.get(), dummyWindow, &fakeBounds);
+    WKCACFViewUpdate(view.get(), dummyWindow.window(), &fakeBounds);
 
     supportsAcceleratedCompositing = WKCACFViewCanDraw(view.get());
 
     WKCACFViewUpdate(view.get(), 0, 0);
-    ::DestroyWindow(dummyWindow);
-    dummyWindow = 0;
 
     return supportsAcceleratedCompositing;
 }
@@ -94,7 +82,6 @@ PassRefPtr<LayerTreeHostCAWin> LayerTreeHostCAWin::create(WebPage* webPage)
 LayerTreeHostCAWin::LayerTreeHostCAWin(WebPage* webPage)
     : LayerTreeHostCA(webPage)
     , m_isFlushingLayerChanges(false)
-    , m_nextDisplayTime(0)
 {
 }
 
@@ -102,36 +89,43 @@ LayerTreeHostCAWin::~LayerTreeHostCAWin()
 {
 }
 
-void LayerTreeHostCAWin::platformInitialize(LayerTreeContext&)
+void LayerTreeHostCAWin::platformInitialize(LayerTreeContext& context)
 {
-    ++validLayerTreeHostCount;
-    if (!dummyWindow)
-        dummyWindow = createDummyWindow();
-
-    m_view.adoptCF(WKCACFViewCreate(kWKCACFViewDrawingDestinationImage));
+    m_view.adoptCF(WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow));
     WKCACFViewSetContextUserData(m_view.get(), static_cast<AbstractCACFLayerTreeHost*>(this));
     WKCACFViewSetLayer(m_view.get(), rootLayer()->platformLayer());
     WKCACFViewSetContextDidChangeCallback(m_view.get(), contextDidChangeCallback, this);
 
+    // Passing WS_DISABLED makes the window invisible to mouse events, which lets WKView's normal
+    // event handling mechanism work even when this window is obscuring the entire WKView HWND.
+    // Note that m_webPage->nativeWindow() is owned by the UI process, so this creates a cross-
+    // process window hierarchy (and thus implicitly attaches the input queues of the UI and web
+    // processes' main threads).
+    m_window = adoptPtr(new WKCACFViewWindow(m_view.get(), m_webPage->nativeWindow(), WS_DISABLED));
+
     CGRect bounds = m_webPage->bounds();
-    WKCACFViewUpdate(m_view.get(), dummyWindow, &bounds);
+    WKCACFViewUpdate(m_view.get(), m_window->window(), &bounds);
+
+    context.window = m_window->window();
 }
 
 void LayerTreeHostCAWin::invalidate()
 {
     LayerChangesFlusher::shared().cancelPendingFlush(this);
 
-    WKCACFViewUpdate(m_view.get(), 0, 0);
     WKCACFViewSetContextUserData(m_view.get(), 0);
     WKCACFViewSetLayer(m_view.get(), 0);
     WKCACFViewSetContextDidChangeCallback(m_view.get(), 0, 0);
 
-    LayerTreeHostCA::invalidate();
+    // The UI process will destroy m_window's HWND when it gets the message to switch out of
+    // accelerated compositing mode. We don't want to destroy the HWND before then or we will get a
+    // flash of white before the UI process has a chance to display the non-composited content.
+    // Since the HWND needs to outlive us, we leak m_window here and tell it to clean itself up
+    // when its HWND is destroyed.
+    WKCACFViewWindow* window = m_window.leakPtr();
+    window->setDeletesSelfWhenWindowDestroyed(true);
 
-    if (--validLayerTreeHostCount)
-        return;
-    ::DestroyWindow(dummyWindow);
-    dummyWindow = 0;
+    LayerTreeHostCA::invalidate();
 }
 
 void LayerTreeHostCAWin::scheduleLayerFlush()
@@ -155,65 +149,16 @@ void LayerTreeHostCAWin::setLayerFlushSchedulingEnabled(bool layerFlushingEnable
     LayerChangesFlusher::shared().cancelPendingFlush(this);
 }
 
-bool LayerTreeHostCAWin::participatesInDisplay()
-{
-    return true;
-}
-
-bool LayerTreeHostCAWin::needsDisplay()
-{
-    return timeUntilNextDisplay() <= 0;
-}
-
-double LayerTreeHostCAWin::timeUntilNextDisplay()
+void LayerTreeHostCAWin::scheduleChildWindowGeometryUpdate(const WindowGeometry& geometry)
 {
-    return m_nextDisplayTime - currentTime();
-}
-
-static IntSize size(WKCACFImageRef image)
-{
-    return IntSize(WKCACFImageGetWidth(image), WKCACFImageGetHeight(image));
-}
-
-static PassRefPtr<ShareableBitmap> toShareableBitmap(WKCACFImageRef image)
-{
-    size_t fileMappingSize;
-    HANDLE mapping = WKCACFImageCopyFileMapping(image, &fileMappingSize);
-    if (!mapping)
-        return 0;
-
-    RefPtr<SharedMemory> sharedMemory = SharedMemory::adopt(mapping, fileMappingSize, SharedMemory::ReadWrite);
-    if (!sharedMemory) {
-        ::CloseHandle(mapping);
-        return 0;
-    }
-
-    // WKCACFImage never has an alpha channel.
-    return ShareableBitmap::create(size(image), 0, sharedMemory.release());
-}
-
-void LayerTreeHostCAWin::display(UpdateInfo& updateInfo)
-{
-    CGPoint imageOrigin;
-    CFTimeInterval nextDrawTime;
-    RetainPtr<WKCACFImageRef> image(AdoptCF, WKCACFViewCopyDrawnImage(m_view.get(), &imageOrigin, &nextDrawTime));
-    m_nextDisplayTime = nextDrawTime - CACurrentMediaTime() + currentTime();
-    if (!image)
-        return;
-    RefPtr<ShareableBitmap> bitmap = toShareableBitmap(image.get());
-    if (!bitmap)
-        return;
-    if (!bitmap->createHandle(updateInfo.bitmapHandle))
-        return;
-    updateInfo.updateRectBounds = IntRect(IntPoint(imageOrigin.x, m_webPage->size().height() - imageOrigin.y - bitmap->size().height()), bitmap->size());
-    updateInfo.updateRects.append(updateInfo.updateRectBounds);
+    m_geometriesUpdater.addPendingUpdate(geometry);
 }
 
 void LayerTreeHostCAWin::sizeDidChange(const IntSize& newSize)
 {
     LayerTreeHostCA::sizeDidChange(newSize);
     CGRect bounds = CGRectMake(0, 0, newSize.width(), newSize.height());
-    WKCACFViewUpdate(m_view.get(), dummyWindow, &bounds);
+    WKCACFViewUpdate(m_view.get(), m_window->window(), &bounds);
     WKCACFViewFlushContext(m_view.get());
 }
 
@@ -249,8 +194,11 @@ void LayerTreeHostCAWin::contextDidChange()
 
     m_pendingAnimatedLayers.clear();
 
-    m_nextDisplayTime = 0;
-    static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->setLayerHostNeedsDisplay();
+    // Update child window geometries now so that they stay mostly in sync with the accelerated content.
+    // FIXME: We should really be doing this when the changes we just flushed appear on screen. <http://webkit.org/b/61867>
+    // We also bring the child windows (i.e., plugins) to the top of the z-order to ensure they are above m_window.
+    // FIXME: We could do this just once per window when it is first shown. Maybe that would be more efficient?
+    m_geometriesUpdater.updateGeometries(BringToTop);
 }
 
 PlatformCALayer* LayerTreeHostCAWin::rootLayer() const
@@ -295,7 +243,11 @@ void LayerTreeHostCAWin::flushPendingLayerChangesNow()
 }
 
 void LayerTreeHostCAWin::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
-{    
+{
+    // Don't flush any changes when we don't have a root layer. This will prevent flashes of white
+    // when switching out of compositing mode.
+    setLayerFlushSchedulingEnabled(graphicsLayer);
+
     // Resubmit all existing animations. CACF does not remember running animations
     // When the layer tree is removed and then added back to the hierarchy
     if (graphicsLayer)
index 655f103..d9d5967 100644 (file)
@@ -30,6 +30,7 @@
 
 #if HAVE(WKQCA)
 
+#include "CoalescedWindowGeometriesUpdater.h"
 #include "LayerTreeHostCA.h"
 #include <WebCore/AbstractCACFLayerTreeHost.h>
 #include <wtf/HashSet.h>
@@ -39,6 +40,8 @@ typedef struct _WKCACFView* WKCACFViewRef;
 
 namespace WebKit {
 
+class WKCACFViewWindow;
+
 class LayerTreeHostCAWin : public LayerTreeHostCA, private WebCore::AbstractCACFLayerTreeHost {
 public:
     static bool supportsAcceleratedCompositing();
@@ -58,10 +61,7 @@ private:
     virtual void sizeDidChange(const WebCore::IntSize& newSize);
     virtual void scheduleLayerFlush();
     virtual void setLayerFlushSchedulingEnabled(bool);
-    virtual bool participatesInDisplay();
-    virtual bool needsDisplay();
-    virtual double timeUntilNextDisplay();
-    virtual void display(UpdateInfo&);
+    virtual void scheduleChildWindowGeometryUpdate(const WindowGeometry&);
 
     // LayerTreeHostCA
     virtual void platformInitialize(LayerTreeContext&);
@@ -73,10 +73,11 @@ private:
     virtual void layerTreeDidChange();
     virtual void flushPendingLayerChangesNow();
 
+    OwnPtr<WKCACFViewWindow> m_window;
     RetainPtr<WKCACFViewRef> m_view;
     HashSet<RefPtr<WebCore::PlatformCALayer> > m_pendingAnimatedLayers;
     bool m_isFlushingLayerChanges;
-    double m_nextDisplayTime;
+    CoalescedWindowGeometriesUpdater m_geometriesUpdater;
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.cpp b/Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.cpp
new file mode 100644 (file)
index 0000000..0ce37c4
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * 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. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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 "WKCACFViewWindow.h"
+
+#if HAVE(WKQCA)
+
+#include <WebCore/WebCoreInstanceHandle.h>
+#include <WebKitQuartzCoreAdditions/WKCACFView.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+static LPCWSTR windowClassName = L"WKCACFViewWindowClass";
+
+WKCACFViewWindow::WKCACFViewWindow(WKCACFViewRef view, HWND parentWindow, DWORD additionalStyles)
+    : m_window(0)
+    , m_view(view)
+    , m_deletesSelfWhenWindowDestroyed(false)
+{
+    ASSERT_ARG(view, view);
+
+    registerClass();
+
+    UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | additionalStyles;
+    if (parentWindow)
+        style |= WS_CHILD;
+    else
+        style |= WS_POPUP;
+
+    m_window = ::CreateWindowExW(0, windowClassName, L"WKCACFViewWindow", style, 0, 0, 0, 0, parentWindow, 0, instanceHandle(), this);
+    ASSERT_WITH_MESSAGE(m_window, "::CreateWindowExW failed with error %lu", ::GetLastError());
+}
+
+WKCACFViewWindow::~WKCACFViewWindow()
+{
+    if (!m_window)
+        return;
+
+    ASSERT(!m_deletesSelfWhenWindowDestroyed);
+    ::DestroyWindow(m_window);
+}
+
+LRESULT WKCACFViewWindow::onCustomDestroy(WPARAM, LPARAM)
+{
+    ::DestroyWindow(m_window);
+    return 0;
+}
+
+LRESULT WKCACFViewWindow::onDestroy(WPARAM, LPARAM)
+{
+    WKCACFViewUpdate(m_view.get(), 0, 0);
+    return 0;
+}
+
+LRESULT WKCACFViewWindow::onEraseBackground(WPARAM, LPARAM)
+{
+    // Tell Windows not to erase us.
+    return 1;
+}
+
+LRESULT WKCACFViewWindow::onNCDestroy(WPARAM, LPARAM)
+{
+    m_window = 0;
+
+    if (!m_deletesSelfWhenWindowDestroyed)
+        return 0;
+
+    delete this;
+    return 0;
+}
+
+LRESULT WKCACFViewWindow::onPaint(WPARAM, LPARAM)
+{
+    WKCACFViewDraw(m_view.get());
+    ::ValidateRect(m_window, 0);
+    return 0;
+}
+
+LRESULT WKCACFViewWindow::onPrintClient(WPARAM wParam, LPARAM lParam)
+{
+    if (!(lParam & PRF_CLIENT))
+        return 0;
+
+    WKCACFViewDrawIntoDC(m_view.get(), reinterpret_cast<HDC>(wParam));
+    return 0;
+}
+
+void WKCACFViewWindow::registerClass()
+{
+    static bool didRegister;
+    if (didRegister)
+        return;
+    didRegister = true;
+
+    WNDCLASSW wndClass = {0};
+    wndClass.lpfnWndProc = staticWndProc;
+    wndClass.hInstance = instanceHandle();
+    wndClass.lpszClassName = windowClassName;
+
+    ::RegisterClassW(&wndClass);
+}
+
+LRESULT WKCACFViewWindow::staticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    WKCACFViewWindow* window = reinterpret_cast<WKCACFViewWindow*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
+    if (!window) {
+        if (message != WM_CREATE)
+            return ::DefWindowProcW(hWnd, message, wParam, lParam);
+        CREATESTRUCT* createStruct = reinterpret_cast<CREATESTRUCT*>(lParam);
+        window = static_cast<WKCACFViewWindow*>(createStruct->lpCreateParams);
+        ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(window));
+    }
+
+    return window->wndProc(message, wParam, lParam);
+}
+
+LRESULT WKCACFViewWindow::wndProc(UINT message, WPARAM wParam, LPARAM lParam)
+{
+    switch (message) {
+    case customDestroyMessage:
+        return onCustomDestroy(wParam, lParam);
+    case WM_DESTROY:
+        return onDestroy(wParam, lParam);
+    case WM_ERASEBKGND:
+        return onEraseBackground(wParam, lParam);
+    case WM_NCDESTROY:
+        return onNCDestroy(wParam, lParam);
+    case WM_PAINT:
+        return onPaint(wParam, lParam);
+    case WM_PRINTCLIENT:
+        return onPrintClient(wParam, lParam);
+    default:
+        return ::DefWindowProcW(m_window, message, wParam, lParam);
+    }
+}
+
+} // namespace WebKit
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.h b/Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.h
new file mode 100644 (file)
index 0000000..391146a
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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 WKCACFViewWindow_h
+#define WKCACFViewWindow_h
+
+#include "HeaderDetection.h"
+
+#if HAVE(WKQCA)
+
+#include <wtf/Noncopyable.h>
+#include <wtf/RetainPtr.h>
+
+typedef struct _WKCACFView* WKCACFViewRef;
+
+namespace WebKit {
+
+// FIXME: Move this class down to WebCore. (Maybe it can even replace some of WKCACFViewLayerTreeHost.)
+class WKCACFViewWindow {
+    WTF_MAKE_NONCOPYABLE(WKCACFViewWindow);
+public:
+    // WKCACFViewWindow will destroy its HWND when this message is received.
+    static const UINT customDestroyMessage = WM_USER + 1;
+
+    WKCACFViewWindow(WKCACFViewRef, HWND parentWindow, DWORD additionalStyles);
+    ~WKCACFViewWindow();
+
+    void setDeletesSelfWhenWindowDestroyed(bool deletes) { m_deletesSelfWhenWindowDestroyed = deletes; }
+
+    HWND window() const { return m_window; }
+
+private:
+    LRESULT onCustomDestroy(WPARAM, LPARAM);
+    LRESULT onDestroy(WPARAM, LPARAM);
+    LRESULT onEraseBackground(WPARAM, LPARAM);
+    LRESULT onNCDestroy(WPARAM, LPARAM);
+    LRESULT onPaint(WPARAM, LPARAM);
+    LRESULT onPrintClient(WPARAM, LPARAM);
+    static void registerClass();
+    static LRESULT CALLBACK staticWndProc(HWND, UINT, WPARAM, LPARAM);
+    LRESULT wndProc(UINT, WPARAM, LPARAM);
+
+    HWND m_window;
+    RetainPtr<WKCACFViewRef> m_view;
+    bool m_deletesSelfWhenWindowDestroyed;
+};
+
+} // namespace WebKit
+
+#endif // HAVE(WKQCA)
+
+#endif // WKCACFViewWindow_h
index 02af9fd..6d527c4 100644 (file)
@@ -34,9 +34,16 @@ namespace WebKit {
 
 void DrawingAreaImpl::scheduleChildWindowGeometryUpdate(const WindowGeometry& geometry)
 {
+#if USE(ACCELERATED_COMPOSITING)
+    if (m_layerTreeHost) {
+        m_layerTreeHost->scheduleChildWindowGeometryUpdate(geometry);
+        return;
+    }
+#endif
+
     // FIXME: This should be a Messages::DrawingAreaProxy, and DrawingAreaProxy should pass the
     // data off to the WebPageProxy.
     m_webPage->send(Messages::WebPageProxy::ScheduleChildWindowGeometryUpdate(geometry));
 }
 
-} // namespace WebKit
\ No newline at end of file
+} // namespace WebKit
index 887f6aa..1a5b064 100755 (executable)
                                                        RelativePath="..\WebProcess\WebPage\ca\win\LayerTreeHostCAWin.h"
                                                        >
                                                </File>
+                                               <File
+                                                       RelativePath="..\WebProcess\WebPage\ca\win\WKCACFViewWindow.cpp"
+                                                       >
+                                               </File>
+                                               <File
+                                                       RelativePath="..\WebProcess\WebPage\ca\win\WKCACFViewWindow.h"
+                                                       >
+                                               </File>
                                        </Filter>
                                </Filter>
                        </Filter>