WebPageCompositor.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*
  2. * Copyright (C) 2010, 2011, 2012, 2013 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. #include "config.h"
  19. #include "WebPageCompositor.h"
  20. #if USE(ACCELERATED_COMPOSITING)
  21. #include "BackingStore_p.h"
  22. #include "LayerWebKitThread.h"
  23. #include "WebOverlay_p.h"
  24. #include "WebPageCompositorClient.h"
  25. #include "WebPageCompositor_p.h"
  26. #include "WebPage_p.h"
  27. #include <BlackBerryPlatformDebugMacros.h>
  28. #include <BlackBerryPlatformExecutableMessage.h>
  29. #include <BlackBerryPlatformMessage.h>
  30. #include <BlackBerryPlatformMessageClient.h>
  31. #include <BlackBerryPlatformViewportAccessor.h>
  32. #include <GenericTimerClient.h>
  33. #include <ThreadTimerClient.h>
  34. #include <wtf/CurrentTime.h>
  35. using namespace WebCore;
  36. namespace BlackBerry {
  37. namespace WebKit {
  38. WebPageCompositorPrivate::WebPageCompositorPrivate(WebPagePrivate* page, WebPageCompositorClient* client)
  39. : m_client(client)
  40. , m_webPage(page)
  41. , m_context(0)
  42. , m_drawsRootLayer(false)
  43. , m_childWindowPlacement(WebPageCompositor::DocumentCoordinates)
  44. {
  45. ASSERT(m_webPage);
  46. setOneShot(true); // one-shot animation client
  47. }
  48. WebPageCompositorPrivate::~WebPageCompositorPrivate()
  49. {
  50. detach();
  51. }
  52. void WebPageCompositorPrivate::detach()
  53. {
  54. if (m_webPage)
  55. Platform::AnimationFrameRateController::instance()->removeClient(this);
  56. m_webPage = 0;
  57. detachOverlays();
  58. }
  59. void WebPageCompositorPrivate::setPage(WebPagePrivate *p)
  60. {
  61. if (p == m_webPage)
  62. return;
  63. ASSERT(p);
  64. ASSERT(m_webPage); // if this is null, we have a bug and we need to re-add.
  65. m_webPage = p;
  66. attachOverlays();
  67. }
  68. void WebPageCompositorPrivate::attachOverlays(LayerCompositingThread* overlayRoot, WebPagePrivate* page)
  69. {
  70. if (!overlayRoot)
  71. return;
  72. const Vector<RefPtr<LayerCompositingThread> >& overlays = overlayRoot->sublayers();
  73. for (size_t i = 0; i < overlays.size(); ++i) {
  74. LayerCompositingThread* overlay = overlays[i].get();
  75. if (LayerCompositingThreadClient* client = overlay->client()) {
  76. if (WebOverlayPrivate* webOverlay = static_cast<WebOverlayLayerCompositingThreadClient*>(client)->overlay())
  77. webOverlay->setPage(page);
  78. }
  79. }
  80. }
  81. void WebPageCompositorPrivate::setContext(Platform::Graphics::GLES2Context* context)
  82. {
  83. if (m_context == context)
  84. return;
  85. // LayerRenderer needs to clean up using the previous context.
  86. if (!context)
  87. m_layerRenderer.clear();
  88. m_context = context;
  89. }
  90. void WebPageCompositorPrivate::setRootLayer(LayerCompositingThread* rootLayer)
  91. {
  92. m_rootLayer = rootLayer;
  93. }
  94. void WebPageCompositorPrivate::setOverlayLayer(LayerCompositingThread* overlayLayer)
  95. {
  96. m_overlayLayer = overlayLayer;
  97. }
  98. void WebPageCompositorPrivate::prepareFrame(double animationTime)
  99. {
  100. if (!m_context)
  101. return;
  102. // The LayerRenderer is involved in rendering the BackingStore when
  103. // WebPageCompositor is used to render the web page. The presence of a
  104. // WebPageCompositorClient (m_client) indicates this is the case, so
  105. // create a LayerRenderer if there are layers or if there's a client.
  106. if (!m_rootLayer && !m_overlayLayer && !m_compositingThreadOverlayLayer && !m_client)
  107. return;
  108. if (!m_layerRenderer) {
  109. m_layerRenderer = LayerRenderer::create(this);
  110. if (!m_layerRenderer->hardwareCompositing()) {
  111. m_layerRenderer.clear();
  112. return;
  113. }
  114. }
  115. // Unfortunately, we have to use currentTime() because the animations are
  116. // started in that time coordinate system.
  117. animationTime = currentTime();
  118. if (m_rootLayer)
  119. m_layerRenderer->prepareFrame(animationTime, m_rootLayer.get());
  120. if (m_overlayLayer)
  121. m_layerRenderer->prepareFrame(animationTime, m_overlayLayer.get());
  122. if (m_compositingThreadOverlayLayer)
  123. m_layerRenderer->prepareFrame(animationTime, m_compositingThreadOverlayLayer.get());
  124. }
  125. void WebPageCompositorPrivate::render(const IntRect& targetRect, const IntRect& clipRect, const TransformationMatrix& transformIn, const FloatRect& documentSrcRect)
  126. {
  127. // m_layerRenderer should have been created in prepareFrame
  128. if (!m_layerRenderer)
  129. return;
  130. // It's not safe to call into the BackingStore if the compositor hasn't been set yet.
  131. // For thread safety, we have to do it using a round-trip to the WebKit thread, so the
  132. // embedder might call this before the round-trip to WebPagePrivate::setCompositor() is
  133. // done.
  134. if (!m_webPage || m_webPage->compositor() != this)
  135. return;
  136. m_layerRenderer->setViewport(targetRect, clipRect, documentSrcRect, m_layoutRect, m_documentRect.size());
  137. TransformationMatrix transform(transformIn);
  138. transform.translate(-m_documentRect.x(), -m_documentRect.y());
  139. if (!drawsRootLayer())
  140. m_webPage->m_backingStore->d->compositeContents(m_layerRenderer.get(), transform, documentSrcRect, !m_backgroundColor.hasAlpha());
  141. compositeLayers(transform);
  142. }
  143. void WebPageCompositorPrivate::compositeLayers(const TransformationMatrix& transform)
  144. {
  145. if (m_rootLayer)
  146. m_layerRenderer->compositeLayers(transform, m_rootLayer.get());
  147. if (m_overlayLayer)
  148. m_layerRenderer->compositeLayers(transform, m_overlayLayer.get());
  149. if (m_compositingThreadOverlayLayer)
  150. m_layerRenderer->compositeLayers(transform, m_compositingThreadOverlayLayer.get());
  151. m_lastCompositingResults = m_layerRenderer->lastRenderingResults();
  152. if (m_lastCompositingResults.needsAnimationFrame) {
  153. Platform::AnimationFrameRateController::instance()->addClient(this);
  154. m_webPage->updateDelegatedOverlays();
  155. }
  156. }
  157. bool WebPageCompositorPrivate::drawsRootLayer() const
  158. {
  159. return m_rootLayer && m_drawsRootLayer;
  160. }
  161. bool WebPageCompositorPrivate::drawLayers(const IntRect& dstRect, const FloatRect& contents)
  162. {
  163. // Is there anything to draw?
  164. if (!m_rootLayer && !m_overlayLayer && !m_compositingThreadOverlayLayer)
  165. return false;
  166. // prepareFrame creates the LayerRenderer if needed
  167. prepareFrame(currentTime());
  168. if (!m_layerRenderer)
  169. return false;
  170. // OpenGL window coordinates origin is at the lower left corner of the surface while
  171. // WebKit uses upper left as the origin of the window coordinate system. The passed in 'dstRect'
  172. // is in WebKit window coordinate system. Here we setup the viewport to the corresponding value
  173. // in OpenGL window coordinates.
  174. int viewportY = std::max(0, m_context->surfaceSize().height() - dstRect.maxY());
  175. IntRect viewport = IntRect(dstRect.x(), viewportY, dstRect.width(), dstRect.height());
  176. m_layerRenderer->setViewport(viewport, viewport, contents, m_layoutRect, m_documentRect.size());
  177. // WebKit uses row vectors which are multiplied by the matrix on the left (i.e. v*M)
  178. // Transformations are composed on the left so that M1.xform(M2) means M2*M1
  179. // We therefore start with our (othogonal) projection matrix, which will be applied
  180. // as the last transformation.
  181. TransformationMatrix transform = LayerRenderer::orthoMatrix(0, contents.width(), contents.height(), 0, -1000, 1000);
  182. transform.translate3d(-contents.x() - m_documentRect.x(), -contents.y() - m_documentRect.y(), 0);
  183. compositeLayers(transform);
  184. return true;
  185. }
  186. void WebPageCompositorPrivate::setBackgroundColor(const Color& color)
  187. {
  188. m_backgroundColor = color;
  189. }
  190. void WebPageCompositorPrivate::releaseLayerResources()
  191. {
  192. if (m_layerRenderer)
  193. m_layerRenderer->releaseLayerResources();
  194. }
  195. bool WebPageCompositorPrivate::shouldChildWindowsUseDocumentCoordinates()
  196. {
  197. return m_childWindowPlacement == WebPageCompositor::DocumentCoordinates;
  198. }
  199. void WebPageCompositorPrivate::animationFrameChanged()
  200. {
  201. BackingStore* backingStore = m_webPage->m_backingStore;
  202. if (!backingStore) {
  203. Platform::ViewportAccessor* viewportAccessor = m_webPage->client()->userInterfaceViewportAccessor();
  204. const Platform::IntRect dstRect = viewportAccessor->destinationSurfaceRect();
  205. const Platform::FloatRect srcRect = viewportAccessor->documentViewportRect();
  206. drawLayers(dstRect, srcRect);
  207. return;
  208. }
  209. if (!m_webPage->needsOneShotDrawingSynchronization())
  210. backingStore->blitVisibleContents();
  211. }
  212. void WebPageCompositorPrivate::compositorDestroyed()
  213. {
  214. if (m_client)
  215. m_client->compositorDestroyed();
  216. m_client = 0;
  217. }
  218. void WebPageCompositorPrivate::addOverlay(LayerCompositingThread* layer)
  219. {
  220. if (!m_compositingThreadOverlayLayer)
  221. m_compositingThreadOverlayLayer = LayerCompositingThread::create(LayerData::CustomLayer, 0);
  222. m_compositingThreadOverlayLayer->addSublayer(layer);
  223. }
  224. void WebPageCompositorPrivate::removeOverlay(LayerCompositingThread* layer)
  225. {
  226. if (layer->superlayer() != m_compositingThreadOverlayLayer)
  227. return;
  228. layer->removeFromSuperlayer();
  229. if (m_compositingThreadOverlayLayer && m_compositingThreadOverlayLayer->sublayers().isEmpty())
  230. m_compositingThreadOverlayLayer.clear();
  231. }
  232. void WebPageCompositorPrivate::findFixedElementRect(LayerCompositingThread* layer, WebCore::IntRect& fixedElementRect)
  233. {
  234. if ((layer->hasFixedContainer() || layer->isFixedPosition() || layer->hasFixedAncestorInDOMTree()) && layer->layerRenderer()) {
  235. IntRect fixedRect = layer->layerRenderer()->toPixelViewportCoordinates(layer->boundingBox());
  236. // FIXME: It's possible that the rects don't intersect now, but will be connected by a fixed rect found later.
  237. // We need to handle it as well.
  238. if (fixedElementRect.isEmpty() || fixedElementRect.intersects(fixedRect)) // Unite rects if they intersect each other.
  239. fixedElementRect.unite(fixedRect);
  240. else if (fixedRect.y() < fixedElementRect.y()) // Replace the fixedElementRect with fixedRect if fixedRect is above it (closer to top).
  241. fixedElementRect = fixedRect;
  242. }
  243. const Vector<RefPtr<LayerCompositingThread> >& sublayers = layer->sublayers();
  244. for (size_t i = 0; i < sublayers.size(); i++)
  245. findFixedElementRect(sublayers[i].get(), fixedElementRect);
  246. }
  247. WebPageCompositor::WebPageCompositor(WebPage* page, WebPageCompositorClient* client)
  248. {
  249. using namespace BlackBerry::Platform;
  250. RefPtr<WebPageCompositorPrivate> tmp = WebPageCompositorPrivate::create(page->d, client);
  251. // FIXME: For legacy reasons, the internal default is to use document coordinates.
  252. // Use window coordinates for new clients.
  253. tmp->setChildWindowPlacement(WindowCoordinates);
  254. // Keep one ref ourselves...
  255. d = tmp.get();
  256. d->ref();
  257. // ...And pass one ref to the web page.
  258. // This ensures that the compositor will be around for as long as it's
  259. // needed. Unfortunately RefPtr<T> is not public, so we have declare to
  260. // resort to manual refcounting.
  261. webKitThreadMessageClient()->dispatchMessage(createMethodCallMessage(&WebPagePrivate::setCompositor, d->page(), tmp));
  262. }
  263. WebPageCompositor::~WebPageCompositor()
  264. {
  265. using namespace BlackBerry::Platform;
  266. // If we're being destroyed before the page, send a message to disconnect us
  267. if (d->page())
  268. webKitThreadMessageClient()->dispatchMessage(createMethodCallMessage(&WebPagePrivate::setCompositor, d->page(), PassRefPtr<WebPageCompositorPrivate>(0)));
  269. d->compositorDestroyed();
  270. d->deref();
  271. }
  272. WebPageCompositorClient* WebPageCompositor::client() const
  273. {
  274. return d->client();
  275. }
  276. void WebPageCompositor::setChildWindowPlacement(ChildWindowPlacement placement)
  277. {
  278. d->setChildWindowPlacement(placement);
  279. }
  280. void WebPageCompositor::prepareFrame(Platform::Graphics::GLES2Context* context, double animationTime)
  281. {
  282. d->setContext(context);
  283. d->prepareFrame(animationTime);
  284. }
  285. void WebPageCompositor::render(Platform::Graphics::GLES2Context* context, const Platform::IntRect& targetRect, const Platform::IntRect& clipRect, const Platform::TransformationMatrix& transform, const Platform::FloatRect& documentSrcRect)
  286. {
  287. d->setContext(context);
  288. d->render(targetRect, clipRect, TransformationMatrix(reinterpret_cast<const TransformationMatrix&>(transform)), documentSrcRect);
  289. }
  290. void WebPageCompositor::cleanup(Platform::Graphics::GLES2Context*)
  291. {
  292. d->setContext(0);
  293. }
  294. void WebPageCompositor::contextLost()
  295. {
  296. // This method needs to delete the compositor in a way that not tries to
  297. // use any OpenGL calls (the context is gone, so we can't and don't need to
  298. // free any OpenGL resources.
  299. notImplemented();
  300. }
  301. } // namespace WebKit
  302. } // namespace BlackBerry
  303. #else // USE(ACCELERATED_COMPOSITING)
  304. namespace BlackBerry {
  305. namespace WebKit {
  306. WebPageCompositor::WebPageCompositor(WebPage*, WebPageCompositorClient*)
  307. : d(0)
  308. {
  309. }
  310. WebPageCompositor::~WebPageCompositor()
  311. {
  312. }
  313. WebPageCompositorClient* WebPageCompositor::client() const
  314. {
  315. return 0;
  316. }
  317. void WebPageCompositor::setChildWindowPlacement(ChildWindowPlacement)
  318. {
  319. }
  320. void WebPageCompositor::prepareFrame(Platform::Graphics::GLES2Context*, double)
  321. {
  322. }
  323. void WebPageCompositor::render(Platform::Graphics::GLES2Context*,
  324. const Platform::IntRect&,
  325. const Platform::IntRect&,
  326. const Platform::TransformationMatrix&,
  327. const Platform::FloatRect&)
  328. {
  329. }
  330. void WebPageCompositor::cleanup(Platform::Graphics::GLES2Context*)
  331. {
  332. }
  333. void WebPageCompositor::contextLost()
  334. {
  335. }
  336. } // namespace WebKit
  337. } // namespace BlackBerry
  338. #endif // USE(ACCELERATED_COMPOSITING)