initial import
[vuplus_webkit] / Source / WebKit2 / WebProcess / WebPage / ca / win / LayerTreeHostCAWin.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #include "config.h"
27 #include "LayerTreeHostCAWin.h"
28
29 #if HAVE(WKQCA)
30
31 #include "DrawingAreaImpl.h"
32 #include "ShareableBitmap.h"
33 #include "UpdateInfo.h"
34 #include "WKCACFViewWindow.h"
35 #include "WebPage.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>
44
45 #ifdef DEBUG_ALL
46 #pragma comment(lib, "WebKitQuartzCoreAdditions_debug")
47 #else
48 #pragma comment(lib, "WebKitQuartzCoreAdditions")
49 #endif
50
51 using namespace WebCore;
52
53 namespace WebKit {
54
55 bool LayerTreeHostCAWin::supportsAcceleratedCompositing()
56 {
57     static bool initialized;
58     static bool supportsAcceleratedCompositing;
59     if (initialized)
60         return supportsAcceleratedCompositing;
61     initialized = true;
62
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);
67
68     supportsAcceleratedCompositing = WKCACFViewCanDraw(view.get());
69
70     WKCACFViewUpdate(view.get(), 0, 0);
71
72     return supportsAcceleratedCompositing;
73 }
74
75 PassRefPtr<LayerTreeHostCAWin> LayerTreeHostCAWin::create(WebPage* webPage)
76 {
77     RefPtr<LayerTreeHostCAWin> host = adoptRef(new LayerTreeHostCAWin(webPage));
78     host->initialize();
79     return host.release();
80 }
81
82 LayerTreeHostCAWin::LayerTreeHostCAWin(WebPage* webPage)
83     : LayerTreeHostCA(webPage)
84     , m_isFlushingLayerChanges(false)
85 {
86 }
87
88 LayerTreeHostCAWin::~LayerTreeHostCAWin()
89 {
90 }
91
92 void LayerTreeHostCAWin::platformInitialize(LayerTreeContext& context)
93 {
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);
98
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));
105
106     CGRect bounds = m_webPage->bounds();
107     WKCACFViewUpdate(m_view.get(), m_window->window(), &bounds);
108
109     context.window = m_window->window();
110 }
111
112 void LayerTreeHostCAWin::invalidate()
113 {
114     LayerChangesFlusher::shared().cancelPendingFlush(this);
115
116     WKCACFViewSetContextUserData(m_view.get(), 0);
117     WKCACFViewSetLayer(m_view.get(), 0);
118     WKCACFViewSetContextDidChangeCallback(m_view.get(), 0, 0);
119
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);
127
128     LayerTreeHostCA::invalidate();
129 }
130
131 void LayerTreeHostCAWin::scheduleLayerFlush()
132 {
133     if (!m_layerFlushSchedulingEnabled)
134         return;
135
136     LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
137 }
138
139 void LayerTreeHostCAWin::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled)
140 {
141     if (m_layerFlushSchedulingEnabled == layerFlushingEnabled)
142         return;
143
144     m_layerFlushSchedulingEnabled = layerFlushingEnabled;
145
146     if (m_layerFlushSchedulingEnabled) {
147         scheduleLayerFlush();
148         return;
149     }
150
151     LayerChangesFlusher::shared().cancelPendingFlush(this);
152 }
153
154 void LayerTreeHostCAWin::scheduleChildWindowGeometryUpdate(const WindowGeometry& geometry)
155 {
156     m_geometriesUpdater.addPendingUpdate(geometry);
157 }
158
159 void LayerTreeHostCAWin::sizeDidChange(const IntSize& newSize)
160 {
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());
165 }
166
167 void LayerTreeHostCAWin::forceRepaint()
168 {
169     LayerTreeHostCA::forceRepaint();
170     WKCACFViewFlushContext(m_view.get());
171 }
172
173 void LayerTreeHostCAWin::contextDidChangeCallback(WKCACFViewRef view, void* info)
174 {
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.
178     if (!isMainThread())
179         return;
180     
181     LayerTreeHostCAWin* host = static_cast<LayerTreeHostCAWin*>(info);
182     ASSERT_ARG(view, view == host->m_view);
183     host->contextDidChange();
184 }
185
186 void LayerTreeHostCAWin::contextDidChange()
187 {
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();
192
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);
196
197     m_pendingAnimatedLayers.clear();
198
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);
204 }
205
206 PlatformCALayer* LayerTreeHostCAWin::rootLayer() const
207 {
208     return static_cast<GraphicsLayerCA*>(LayerTreeHostCA::rootLayer())->platformCALayer();
209 }
210
211 void LayerTreeHostCAWin::addPendingAnimatedLayer(PassRefPtr<PlatformCALayer> layer)
212 {
213     m_pendingAnimatedLayers.add(layer);
214 }
215
216 void LayerTreeHostCAWin::layerTreeDidChange()
217 {
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.
222         return;
223     }
224
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);
229 }
230
231 void LayerTreeHostCAWin::flushPendingLayerChangesNow()
232 {
233     RefPtr<LayerTreeHostCA> protector(this);
234
235     m_isFlushingLayerChanges = true;
236
237     // Flush changes stored up in GraphicsLayers to their underlying PlatformCALayers, if
238     // requested.
239     performScheduledLayerFlush();
240
241     // Flush changes stored up in PlatformCALayers to the context so they will be rendered.
242     WKCACFViewFlushContext(m_view.get());
243
244     m_isFlushingLayerChanges = false;
245 }
246
247 void LayerTreeHostCAWin::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
248 {
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);
252
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
255     if (graphicsLayer)
256         static_cast<GraphicsLayerCA*>(graphicsLayer)->platformCALayer()->ensureAnimationsSubmitted();
257
258     LayerTreeHostCA::setRootCompositingLayer(graphicsLayer);
259 }
260
261 } // namespace WebKit
262
263 #endif // HAVE(WKQCA)