[BlackBerry] Add WebPageCompositor class to BlackBerry WebKit API
[WebKit-https.git] / Source / WebKit / blackberry / Api / WebPageCompositor.cpp
1 /*
2  * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include "config.h"
20
21 #include "WebPageCompositor.h"
22
23 #if USE(ACCELERATED_COMPOSITING)
24 #include "WebPageCompositorClient.h"
25 #include "WebPageCompositor_p.h"
26
27 #include "BackingStore_p.h"
28 #include "LayerWebKitThread.h"
29 #include "WebPage_p.h"
30
31 #include <BlackBerryPlatformDebugMacros.h>
32 #include <BlackBerryPlatformExecutableMessage.h>
33 #include <BlackBerryPlatformMessage.h>
34 #include <BlackBerryPlatformMessageClient.h>
35 #include <GenericTimerClient.h>
36 #include <ThreadTimerClient.h>
37
38 using namespace WebCore;
39
40 namespace BlackBerry {
41 namespace WebKit {
42
43 WebPageCompositorPrivate::WebPageCompositorPrivate(WebPagePrivate* page, WebPageCompositorClient* client)
44     : m_client(client)
45     , m_webPage(page)
46     , m_animationTimer(this, &WebPageCompositorPrivate::animationTimerFired)
47     , m_timerClient(new Platform::GenericTimerClient(Platform::userInterfaceThreadTimerClient()))
48     , m_pendingAnimationFrame(0.0)
49 {
50     m_animationTimer.setClient(m_timerClient);
51 }
52
53 WebPageCompositorPrivate::~WebPageCompositorPrivate()
54 {
55     m_animationTimer.stop();
56     delete m_timerClient;
57 }
58
59 void WebPageCompositorPrivate::setContext(Platform::Graphics::GLES2Context* context)
60 {
61     if (m_context == context)
62         return;
63
64     m_context = context;
65     if (!m_context) {
66         m_layerRenderer.clear();
67         return;
68     }
69
70     m_layerRenderer = LayerRenderer::create(m_context);
71 }
72
73 bool WebPageCompositorPrivate::hardwareCompositing() const
74 {
75     return m_layerRenderer && m_layerRenderer->hardwareCompositing();
76 }
77
78 void WebPageCompositorPrivate::setRootLayer(LayerCompositingThread* rootLayer)
79 {
80     m_rootLayer = rootLayer;
81
82     ASSERT(m_layerRenderer);
83     if (m_layerRenderer)
84         m_layerRenderer->setRootLayer(m_rootLayer.get());
85 }
86
87 void WebPageCompositorPrivate::commit(LayerWebKitThread* rootLayer)
88 {
89     if (!rootLayer)
90         return;
91
92     rootLayer->commitOnCompositingThread();
93 }
94
95 void WebPageCompositorPrivate::render(const IntRect& dstRect, const IntRect& transformedContents)
96 {
97     // It's not safe to call into the BackingStore if the compositor hasn't been set yet.
98     // For thread safety, we have to do it using a round-trip to the WebKit thread, so the
99     // embedder might call this before the round-trip to WebPagePrivate::setCompositor() is
100     // done.
101     if (m_webPage->compositor() != this)
102         return;
103
104     // The BackingStore is the root layer
105     if (BackingStore* backingStore = m_webPage->m_backingStore)
106         backingStore->d->blitContents(dstRect, transformedContents, true);
107     else {
108         FloatRect contents = m_webPage->mapFromTransformedFloatRect(FloatRect(transformedContents));
109         drawLayers(dstRect, contents);
110     }
111 }
112
113 bool WebPageCompositorPrivate::drawLayers(const IntRect& dstRect, const FloatRect& contents)
114 {
115     if (!m_layerRenderer)
116         return false;
117
118     m_pendingAnimationFrame = 0.0;
119
120     bool shouldClear = false;
121     if (BackingStore* backingStore = m_webPage->m_backingStore)
122         shouldClear = !backingStore->d->isOpenGLCompositing();
123     m_layerRenderer->setClearSurfaceOnDrawLayers(shouldClear);
124
125     m_layerRenderer->drawLayers(contents, m_layoutRectForCompositing, m_contentsSizeForCompositing, dstRect);
126     m_lastCompositingResults = m_layerRenderer->lastRenderingResults();
127
128     if (m_lastCompositingResults.needsAnimationFrame) {
129         // Using a timeout of 0 actually won't start a timer, it will send a message.
130         if (m_client)
131             m_pendingAnimationFrame = m_client->requestAnimationFrame();
132         else {
133             m_animationTimer.start(1.0 / 60.0);
134             m_webPage->updateDelegatedOverlays();
135         }
136     }
137
138     return true;
139 }
140
141 void WebPageCompositorPrivate::releaseLayerResources()
142 {
143     m_layerRenderer->releaseLayerResources();
144 }
145
146 void WebPageCompositorPrivate::animationTimerFired()
147 {
148     BackingStore* backingStore = m_webPage->m_backingStore;
149     if (!backingStore) {
150         drawLayers(m_webPage->client()->userInterfaceBlittedDestinationRect(),
151                    IntRect(m_webPage->client()->userInterfaceBlittedVisibleContentsRect()));
152         return;
153     }
154
155     if (backingStore->d->shouldDirectRenderingToWindow()) {
156         if (backingStore->d->isDirectRenderingAnimationMessageScheduled())
157             return; // don't send new messages as long as we haven't rerendered
158
159         using namespace BlackBerry::Platform;
160
161         backingStore->d->setDirectRenderingAnimationMessageScheduled();
162         webKitThreadMessageClient()->dispatchMessage(createMethodCallMessage(&BackingStorePrivate::renderVisibleContents, backingStore->d));
163         return;
164     }
165     m_webPage->blitVisibleContents();
166 }
167
168 void WebPageCompositorPrivate::compositorDestroyed()
169 {
170     if (m_client)
171         m_client->compositorDestroyed();
172
173     m_client = 0;
174 }
175
176 WebPageCompositor::WebPageCompositor(WebPage* page, WebPageCompositorClient* client)
177 {
178     using namespace BlackBerry::Platform;
179
180     RefPtr<WebPageCompositorPrivate> tmp = WebPageCompositorPrivate::create(page->d, client);
181
182     // Keep one ref ourselves...
183     d = tmp.get();
184     d->ref();
185
186     // ...And pass one ref to the web page.
187     // This ensures that the compositor will be around for as long as it's
188     // needed. Unfortunately RefPtr<T> is not public, so we have declare to
189     // resort to manual refcounting.
190     webKitThreadMessageClient()->dispatchMessage(createMethodCallMessage(&WebPagePrivate::setCompositor, d->page(), tmp));
191 }
192
193 WebPageCompositor::~WebPageCompositor()
194 {
195     using namespace BlackBerry::Platform;
196
197     webKitThreadMessageClient()->dispatchMessage(createMethodCallMessage(&WebPagePrivate::setCompositor, d->page(), PassRefPtr<WebPageCompositorPrivate>(0)));
198     d->compositorDestroyed();
199     d->deref();
200 }
201
202 WebPageCompositorClient* WebPageCompositor::client() const
203 {
204     return 0;
205 }
206
207 void WebPageCompositor::prepareFrame(Platform::Graphics::GLES2Context* context, double timestamp)
208 {
209     d->setContext(context);
210 }
211
212 void WebPageCompositor::render(Platform::Graphics::GLES2Context* context, const Platform::IntRect& dstRect, const Platform::IntRect& contents)
213 {
214     d->setContext(context);
215     d->render(dstRect, contents);
216 }
217
218 void WebPageCompositor::cleanup(Platform::Graphics::GLES2Context* context)
219 {
220     d->setContext(0);
221 }
222
223 void WebPageCompositor::contextLost()
224 {
225     // This method needs to delete the compositor in a way that not tries to
226     // use any OpenGL calls (the context is gone, so we can't and don't need to
227     // free any OpenGL resources.
228     notImplemented();
229 }
230
231 } // namespace WebKit
232 } // namespace BlackBerry
233
234 #else // USE(ACCELERATED_COMPOSITING)
235
236 namespace BlackBerry {
237 namespace WebKit {
238
239 WebPageCompositor::WebPageCompositor(WebPage*, WebPageCompositorClient*)
240     : d(0)
241 {
242 }
243
244 WebPageCompositor::~WebPageCompositor()
245 {
246 }
247
248 WebPageCompositorClient* WebPageCompositor::client() const
249 {
250     return 0;
251 }
252
253 void WebPageCompositor::prepareFrame(Platform::Graphics::GLES2Context*, double)
254 {
255 }
256
257 void WebPageCompositor::render(Platform::Graphics::GLES2Context*, const Platform::IntRect&, const Platform::IntRect&)
258 {
259 }
260
261 void WebPageCompositor::cleanup(Platform::Graphics::GLES2Context*)
262 {
263 }
264
265 void WebPageCompositor::contextLost()
266 {
267 }
268
269 } // namespace WebKit
270 } // namespace BlackBerry
271
272 #endif // USE(ACCELERATED_COMPOSITING)