2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #include "LayerTreeHostCAWin.h"
31 #include "DrawingAreaImpl.h"
32 #include "ShareableBitmap.h"
33 #include "UpdateInfo.h"
34 #include "WKCACFViewWindow.h"
36 #include <WebCore/GraphicsLayerCA.h>
37 #include <WebCore/LayerChangesFlusher.h>
38 #include <WebCore/PlatformCALayer.h>
39 #include <WebCore/WebCoreInstanceHandle.h>
40 #include <WebKitQuartzCoreAdditions/WKCACFImage.h>
41 #include <WebKitQuartzCoreAdditions/WKCACFView.h>
42 #include <wtf/CurrentTime.h>
43 #include <wtf/MainThread.h>
46 #pragma comment(lib, "WebKitQuartzCoreAdditions_debug")
48 #pragma comment(lib, "WebKitQuartzCoreAdditions")
51 using namespace WebCore;
55 bool LayerTreeHostCAWin::supportsAcceleratedCompositing()
57 static bool initialized;
58 static bool supportsAcceleratedCompositing;
60 return supportsAcceleratedCompositing;
63 RetainPtr<WKCACFViewRef> view(AdoptCF, WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow));
64 WKCACFViewWindow dummyWindow(view.get(), 0, 0);
65 CGRect fakeBounds = CGRectMake(0, 0, 10, 10);
66 WKCACFViewUpdate(view.get(), dummyWindow.window(), &fakeBounds);
68 supportsAcceleratedCompositing = WKCACFViewCanDraw(view.get());
70 WKCACFViewUpdate(view.get(), 0, 0);
72 return supportsAcceleratedCompositing;
75 PassRefPtr<LayerTreeHostCAWin> LayerTreeHostCAWin::create(WebPage* webPage)
77 RefPtr<LayerTreeHostCAWin> host = adoptRef(new LayerTreeHostCAWin(webPage));
79 return host.release();
82 LayerTreeHostCAWin::LayerTreeHostCAWin(WebPage* webPage)
83 : LayerTreeHostCA(webPage)
84 , m_isFlushingLayerChanges(false)
88 LayerTreeHostCAWin::~LayerTreeHostCAWin()
92 void LayerTreeHostCAWin::platformInitialize(LayerTreeContext& context)
94 m_view.adoptCF(WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow));
95 WKCACFViewSetContextUserData(m_view.get(), static_cast<AbstractCACFLayerTreeHost*>(this));
96 WKCACFViewSetLayer(m_view.get(), rootLayer()->platformLayer());
97 WKCACFViewSetContextDidChangeCallback(m_view.get(), contextDidChangeCallback, this);
99 // Passing WS_DISABLED makes the window invisible to mouse events, which lets WKView's normal
100 // event handling mechanism work even when this window is obscuring the entire WKView HWND.
101 // Note that m_webPage->nativeWindow() is owned by the UI process, so this creates a cross-
102 // process window hierarchy (and thus implicitly attaches the input queues of the UI and web
103 // processes' main threads).
104 m_window = adoptPtr(new WKCACFViewWindow(m_view.get(), m_webPage->nativeWindow(), WS_DISABLED));
106 CGRect bounds = m_webPage->bounds();
107 WKCACFViewUpdate(m_view.get(), m_window->window(), &bounds);
109 context.window = m_window->window();
112 void LayerTreeHostCAWin::invalidate()
114 LayerChangesFlusher::shared().cancelPendingFlush(this);
116 WKCACFViewSetContextUserData(m_view.get(), 0);
117 WKCACFViewSetLayer(m_view.get(), 0);
118 WKCACFViewSetContextDidChangeCallback(m_view.get(), 0, 0);
120 // The UI process will destroy m_window's HWND when it gets the message to switch out of
121 // accelerated compositing mode. We don't want to destroy the HWND before then or we will get a
122 // flash of white before the UI process has a chance to display the non-composited content.
123 // Since the HWND needs to outlive us, we leak m_window here and tell it to clean itself up
124 // when its HWND is destroyed.
125 WKCACFViewWindow* window = m_window.leakPtr();
126 window->setDeletesSelfWhenWindowDestroyed(true);
128 LayerTreeHostCA::invalidate();
131 void LayerTreeHostCAWin::scheduleLayerFlush()
133 if (!m_layerFlushSchedulingEnabled)
136 LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
139 void LayerTreeHostCAWin::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled)
141 if (m_layerFlushSchedulingEnabled == layerFlushingEnabled)
144 m_layerFlushSchedulingEnabled = layerFlushingEnabled;
146 if (m_layerFlushSchedulingEnabled) {
147 scheduleLayerFlush();
151 LayerChangesFlusher::shared().cancelPendingFlush(this);
154 void LayerTreeHostCAWin::scheduleChildWindowGeometryUpdate(const WindowGeometry& geometry)
156 m_geometriesUpdater.addPendingUpdate(geometry);
159 void LayerTreeHostCAWin::sizeDidChange(const IntSize& newSize)
161 LayerTreeHostCA::sizeDidChange(newSize);
162 CGRect bounds = CGRectMake(0, 0, newSize.width(), newSize.height());
163 WKCACFViewUpdate(m_view.get(), m_window->window(), &bounds);
164 WKCACFViewFlushContext(m_view.get());
167 void LayerTreeHostCAWin::forceRepaint()
169 LayerTreeHostCA::forceRepaint();
170 WKCACFViewFlushContext(m_view.get());
173 void LayerTreeHostCAWin::contextDidChangeCallback(WKCACFViewRef view, void* info)
175 // This should only be called on a background thread when no changes have actually
176 // been committed to the context, eg. when a video frame has been added to an image
177 // queue, so return without triggering animations etc.
181 LayerTreeHostCAWin* host = static_cast<LayerTreeHostCAWin*>(info);
182 ASSERT_ARG(view, view == host->m_view);
183 host->contextDidChange();
186 void LayerTreeHostCAWin::contextDidChange()
188 // Send currentTime to the pending animations. This function is called by CACF in a callback
189 // which occurs after the drawInContext calls. So currentTime is very close to the time
190 // the animations actually start
191 double currentTime = WTF::currentTime();
193 HashSet<RefPtr<PlatformCALayer> >::iterator end = m_pendingAnimatedLayers.end();
194 for (HashSet<RefPtr<PlatformCALayer> >::iterator it = m_pendingAnimatedLayers.begin(); it != end; ++it)
195 (*it)->animationStarted(currentTime);
197 m_pendingAnimatedLayers.clear();
199 // Update child window geometries now so that they stay mostly in sync with the accelerated content.
200 // FIXME: We should really be doing this when the changes we just flushed appear on screen. <http://webkit.org/b/61867>
201 // We also bring the child windows (i.e., plugins) to the top of the z-order to ensure they are above m_window.
202 // FIXME: We could do this just once per window when it is first shown. Maybe that would be more efficient?
203 m_geometriesUpdater.updateGeometries(BringToTop);
206 PlatformCALayer* LayerTreeHostCAWin::rootLayer() const
208 return static_cast<GraphicsLayerCA*>(LayerTreeHostCA::rootLayer())->platformCALayer();
211 void LayerTreeHostCAWin::addPendingAnimatedLayer(PassRefPtr<PlatformCALayer> layer)
213 m_pendingAnimatedLayers.add(layer);
216 void LayerTreeHostCAWin::layerTreeDidChange()
218 if (m_isFlushingLayerChanges) {
219 // The layer tree is changing as a result of flushing GraphicsLayer changes to their
220 // underlying PlatformCALayers. We'll flush those changes to the context as part of that
221 // process, so there's no need to schedule another flush here.
225 // The layer tree is changing as a result of someone modifying a PlatformCALayer that doesn't
226 // have a corresponding GraphicsLayer. Schedule a flush since we won't schedule one through the
227 // normal GraphicsLayer mechanisms.
228 LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
231 void LayerTreeHostCAWin::flushPendingLayerChangesNow()
233 RefPtr<LayerTreeHostCA> protector(this);
235 m_isFlushingLayerChanges = true;
237 // Flush changes stored up in GraphicsLayers to their underlying PlatformCALayers, if
239 performScheduledLayerFlush();
241 // Flush changes stored up in PlatformCALayers to the context so they will be rendered.
242 WKCACFViewFlushContext(m_view.get());
244 m_isFlushingLayerChanges = false;
247 void LayerTreeHostCAWin::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
249 // Don't flush any changes when we don't have a root layer. This will prevent flashes of white
250 // when switching out of compositing mode.
251 setLayerFlushSchedulingEnabled(graphicsLayer);
253 // Resubmit all existing animations. CACF does not remember running animations
254 // When the layer tree is removed and then added back to the hierarchy
256 static_cast<GraphicsLayerCA*>(graphicsLayer)->platformCALayer()->ensureAnimationsSubmitted();
258 LayerTreeHostCA::setRootCompositingLayer(graphicsLayer);
261 } // namespace WebKit
263 #endif // HAVE(WKQCA)