2 Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library 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.
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 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
22 #if USE(UI_SIDE_COMPOSITING)
24 #include "WebLayerTreeRenderer.h"
26 #include "GraphicsLayerTextureMapper.h"
27 #include "LayerBackingStore.h"
28 #include "LayerTreeHostProxy.h"
29 #include "MessageID.h"
30 #include "ShareableBitmap.h"
31 #include "TextureMapper.h"
32 #include "TextureMapperBackingStore.h"
33 #include "TextureMapperLayer.h"
34 #include "UpdateInfo.h"
35 #if !ENABLE(TIZEN_WEBKIT2_TILED_AC)
36 #include <OpenGLShims.h>
38 #include <WebCore/Logging.h>
39 #include <wtf/Atomics.h>
40 #include <wtf/MainThread.h>
42 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
43 #include "LayerTreeHostMessages.h"
44 #include "TextureMapperGL.h"
45 #include "WebPageProxy.h"
46 #include "WebProcessProxy.h"
51 using namespace WebCore;
53 template<class T> class MainThreadGuardedInvoker {
55 static void call(PassRefPtr<T> objectToGuard, const Function<void()>& function)
57 MainThreadGuardedInvoker<T>* invoker = new MainThreadGuardedInvoker<T>(objectToGuard, function);
58 callOnMainThread(invoke, invoker);
62 MainThreadGuardedInvoker(PassRefPtr<T> object, const Function<void()>& newFunction)
63 : objectToGuard(object)
64 , function(newFunction)
68 RefPtr<T> objectToGuard;
69 Function<void()> function;
70 static void invoke(void* data)
72 MainThreadGuardedInvoker<T>* invoker = static_cast<MainThreadGuardedInvoker<T>*>(data);
78 #if ENABLE(TIZEN_WEB_LAYER_TREE_RENDERER_FUNCTION_NAME_BUG_FIX)
79 void WebLayerTreeRenderer::callOnMainThread(const Function<void()>& function)
81 void WebLayerTreeRenderer::callOnMainTread(const Function<void()>& function)
87 MainThreadGuardedInvoker<WebLayerTreeRenderer>::call(this, function);
90 static IntPoint boundedScrollPosition(const IntPoint& scrollPosition, const IntRect& visibleContentRect, const FloatSize& contentSize)
92 IntSize size(contentSize.width(), contentSize.height());
93 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
94 // Prevent negative scroll position.
95 int scrollPositionX = std::min(scrollPosition.x(), size.width() - visibleContentRect.width());
96 scrollPositionX = std::max(scrollPositionX, 0);
98 int scrollPositionY = std::min(scrollPosition.y(), size.height() - visibleContentRect.height());
99 scrollPositionY = std::max(scrollPositionY, 0);
101 int scrollPositionX = std::max(scrollPosition.x(), 0);
102 scrollPositionX = std::min(scrollPositionX, size.width() - visibleContentRect.width());
104 int scrollPositionY = std::max(scrollPosition.y(), 0);
105 scrollPositionY = std::min(scrollPositionY, size.height() - visibleContentRect.height());
108 return IntPoint(scrollPositionX, scrollPositionY);
111 WebLayerTreeRenderer::WebLayerTreeRenderer(LayerTreeHostProxy* layerTreeHostProxy)
112 : m_layerTreeHostProxy(layerTreeHostProxy)
113 , m_rootLayerID(InvalidWebLayerID)
115 #if ENABLE(TIZEN_WEBKIT2_DIRECT_RENDERING)
121 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
122 WebLayerTreeRenderer::WebLayerTreeRenderer(LayerTreeHostProxy* layerTreeHostProxy, DrawingAreaProxy* drawingAreaProxy)
123 : m_layerTreeHostProxy(layerTreeHostProxy)
125 , m_drawingAreaProxy(drawingAreaProxy)
126 #if ENABLE(TIZEN_ONESHOT_DRAWING_SYNCHRONIZATION)
127 , m_needsOneShotDrawingSynchronization(false)
133 WebLayerTreeRenderer::~WebLayerTreeRenderer()
137 PassOwnPtr<GraphicsLayer> WebLayerTreeRenderer::createLayer(WebLayerID layerID)
139 GraphicsLayer* newLayer = new GraphicsLayerTextureMapper(this);
140 TextureMapperLayer* layer = toTextureMapperLayer(newLayer);
141 layer->setShouldUpdateBackingStoreFromLayer(false);
142 LOG(AcceleratedCompositing, "[UI ] create layer %u @WebLayerTreeRenderer::createLayer \n", layerID);
143 return adoptPtr(newLayer);
146 void WebLayerTreeRenderer::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect, TextureMapper::PaintFlags PaintFlags)
148 if (!m_textureMapper)
149 m_textureMapper = TextureMapper::create(TextureMapper::OpenGLMode);
150 ASSERT(m_textureMapper->accelerationMode() == TextureMapper::OpenGLMode);
152 // We need to compensate for the rounding error that happens due to m_visibleContentsRect being
153 // int and not float. We do that by moving the TransformationMatrix by the delta between the
154 // position of m_visibleContentsRect and the position it would have if it wasn't rounded.
156 TransformationMatrix newMatrix = matrix;
157 newMatrix.translate(m_accurateVisibleContentsPosition.x() / m_contentsScale - m_visibleContentsRect.x(), m_accurateVisibleContentsPosition.y() / m_contentsScale - m_visibleContentsRect.y());
158 adjustPositionForFixedLayers();
159 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
160 adjustPositionForOverflowLayers();
162 GraphicsLayer* currentRootLayer = rootLayer();
163 if (!currentRootLayer)
166 TextureMapperLayer* layer = toTextureMapperLayer(currentRootLayer);
171 #if ENABLE(TIZEN_WEBKIT2_DIRECT_RENDERING)
172 static_cast<TextureMapperGL*>(m_textureMapper.get())->setAngle(m_angle);
175 layer->setTextureMapper(m_textureMapper.get());
176 m_textureMapper->beginPainting(PaintFlags);
177 m_textureMapper->beginClip(TransformationMatrix(), clipRect);
179 if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != newMatrix) {
180 currentRootLayer->setOpacity(opacity);
181 currentRootLayer->setTransform(newMatrix);
182 currentRootLayer->syncCompositingStateForThisLayerOnly();
186 m_textureMapper->endClip();
187 m_textureMapper->endPainting();
191 void WebLayerTreeRenderer::paintToGraphicsContext(QPainter* painter)
193 if (!m_textureMapper)
194 m_textureMapper = TextureMapper::create();
195 ASSERT(m_textureMapper->accelerationMode() == TextureMapper::SoftwareMode);
197 TextureMapperLayer* layer = toTextureMapperLayer(rootLayer());
202 GraphicsContext graphicsContext(painter);
203 m_textureMapper->setGraphicsContext(&graphicsContext);
204 m_textureMapper->beginPainting();
206 m_textureMapper->endPainting();
207 m_textureMapper->setGraphicsContext(0);
210 void WebLayerTreeRenderer::paintToGraphicsContext(BackingStore::PlatformGraphicsContext)
215 void WebLayerTreeRenderer::setContentsSize(const WebCore::FloatSize& contentsSize)
217 m_contentsSize = contentsSize;
220 void WebLayerTreeRenderer::setVisibleContentsRect(const IntRect& rect, float scale, const WebCore::FloatPoint& accurateVisibleContentsPosition)
222 m_visibleContentsRect = rect;
223 m_contentsScale = scale;
224 m_accurateVisibleContentsPosition = accurateVisibleContentsPosition;
227 void WebLayerTreeRenderer::updateViewport()
229 if (m_layerTreeHostProxy)
230 m_layerTreeHostProxy->updateViewport();
233 void WebLayerTreeRenderer::adjustPositionForFixedLayers()
235 if (m_fixedLayers.isEmpty())
238 IntPoint scrollPosition = boundedScrollPosition(m_visibleContentsRect.location(), m_visibleContentsRect, m_contentsSize);
240 LayerMap::iterator end = m_fixedLayers.end();
241 for (LayerMap::iterator it = m_fixedLayers.begin(); it != end; ++it)
242 toTextureMapperLayer(it->second)->setScrollPositionDeltaIfNeeded(IntPoint(scrollPosition.x() - m_renderedContentsScrollPosition.x(), scrollPosition.y() - m_renderedContentsScrollPosition.y()));
245 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
246 void WebLayerTreeRenderer::adjustPositionForOverflowLayers()
248 LayerMap::iterator end = m_scrollingContentsLayers.end();
249 for (LayerMap::iterator it = m_scrollingContentsLayers.begin(); it != end; ++it) {
250 GraphicsLayer* contentsLayer = it->second;
251 TextureMapperLayer* textureMapperLayer = contentsLayer ? toTextureMapperLayer(contentsLayer) : 0;
252 if (!textureMapperLayer)
255 textureMapperLayer->setScrollPositionDeltaIfNeeded(-flooredIntPoint(contentsLayer->boundsOrigin()));
259 bool WebLayerTreeRenderer::setOffset(const WebLayerID id, const FloatPoint& offset)
261 LayerMap::iterator it = m_scrollingContentsLayers.find(id);
262 if (it == m_scrollingContentsLayers.end())
265 GraphicsLayer* contentsLayer = it->second;
266 GraphicsLayer* scrollingLayer = contentsLayer ? contentsLayer->parent() : 0;
270 const IntSize contentLayerSize(contentsLayer->size().width(), contentsLayer->size().height());
271 const IntRect boundaryRect(FloatRect(scrollingLayer->position(), scrollingLayer->size()));
272 const IntRect visibleRect(FloatRect(contentsLayer->boundsOrigin(), scrollingLayer->size()));
274 IntRect newVisibleRect = visibleRect;
275 newVisibleRect.moveBy(flooredIntPoint(offset));
277 if (newVisibleRect.x() < boundaryRect.x())
278 newVisibleRect.setX(boundaryRect.x());
279 if (contentLayerSize.width() - newVisibleRect.x() < boundaryRect.maxX())
280 newVisibleRect.setX(contentLayerSize.width() - boundaryRect.width());
281 if (newVisibleRect.y() < boundaryRect.y())
282 newVisibleRect.setY(boundaryRect.y());
283 if (contentLayerSize.height() - newVisibleRect.y() < boundaryRect.maxY())
284 newVisibleRect.setY(contentLayerSize.height() - boundaryRect.height());
286 if (visibleRect == newVisibleRect)
289 contentsLayer->setBoundsOrigin(newVisibleRect.location());
291 m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeHost::SetVisibleContentsRectAndTrajectoryVectorForLayer(id, visibleRect, offset), m_drawingAreaProxy->page()->pageID());
296 void WebLayerTreeRenderer::setVisibleContentsRectForScrollingContentsLayers(const WebCore::IntRect& visibleRect)
298 LayerMap::iterator end = m_scrollingContentsLayers.end();
299 for (LayerMap::iterator it = m_scrollingContentsLayers.begin(); it != end; ++it) {
300 GraphicsLayer* contentsLayer = it->second;
301 GraphicsLayer* scrollingLayer = contentsLayer ? contentsLayer->parent() : 0;
305 // FIXME: We might need to check if the each content layer is in viewport.
306 // Simply, we should find out a intersected rect between visibleRect and each scrollingLayer here.
307 const IntRect newVisibleRect(FloatRect(contentsLayer->boundsOrigin(), scrollingLayer->size()));
309 m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeHost::SetVisibleContentsRectAndTrajectoryVectorForLayer(it->first, newVisibleRect, WebCore::FloatPoint()), m_drawingAreaProxy->page()->pageID());
314 void WebLayerTreeRenderer::didChangeScrollPosition(const IntPoint& position)
316 m_pendingRenderedContentsScrollPosition = boundedScrollPosition(position, m_visibleContentsRect, m_contentsSize);
319 void WebLayerTreeRenderer::setLayerChildren(WebLayerID id, const Vector<WebLayerID>& childIDs)
322 LayerMap::iterator it = m_layers.find(id);
323 GraphicsLayer* layer = it->second;
324 Vector<GraphicsLayer*> children;
326 for (size_t i = 0; i < childIDs.size(); ++i) {
327 WebLayerID childID = childIDs[i];
328 GraphicsLayer* child = layerByID(childID);
330 child = createLayer(childID).leakPtr();
331 m_layers.add(childID, child);
333 children.append(child);
335 layer->setChildren(children);
338 #if ENABLE(CSS_FILTERS)
339 void WebLayerTreeRenderer::setLayerFilters(WebLayerID id, const FilterOperations& filters)
342 LayerMap::iterator it = m_layers.find(id);
343 ASSERT(it != m_layers.end());
345 GraphicsLayer* layer = it->second;
346 layer->setFilters(filters);
350 void WebLayerTreeRenderer::setLayerState(WebLayerID id, const WebLayerInfo& layerInfo)
353 LayerMap::iterator it = m_layers.find(id);
354 ASSERT(it != m_layers.end());
356 GraphicsLayer* layer = it->second;
358 layer->setReplicatedByLayer(layerByID(layerInfo.replica));
359 layer->setMaskLayer(layerByID(layerInfo.mask));
361 layer->setPosition(layerInfo.pos);
362 layer->setSize(layerInfo.size);
363 layer->setTransform(layerInfo.transform);
364 layer->setAnchorPoint(layerInfo.anchorPoint);
365 layer->setChildrenTransform(layerInfo.childrenTransform);
366 layer->setBackfaceVisibility(layerInfo.backfaceVisible);
367 layer->setContentsOpaque(layerInfo.contentsOpaque);
368 layer->setContentsRect(layerInfo.contentsRect);
369 layer->setDrawsContent(layerInfo.drawsContent);
370 toGraphicsLayerTextureMapper(layer)->setFixedToViewport(layerInfo.fixedToViewport);
372 if (layerInfo.fixedToViewport)
373 m_fixedLayers.add(id, layer);
375 m_fixedLayers.remove(id);
377 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
378 if (layerInfo.isScrollingContentsLayer)
379 m_scrollingContentsLayers.add(id, layer);
381 m_scrollingContentsLayers.remove(id);
384 assignImageToLayer(layer, layerInfo.imageBackingStoreID);
386 // Never make the root layer clip.
387 layer->setMasksToBounds(layerInfo.isRootLayer ? false : layerInfo.masksToBounds);
388 layer->setOpacity(layerInfo.opacity);
389 layer->setPreserves3D(layerInfo.preserves3D);
390 if (layerInfo.isRootLayer && m_rootLayerID != id)
394 void WebLayerTreeRenderer::deleteLayer(WebLayerID layerID)
396 GraphicsLayer* layer = layerByID(layerID);
400 LOG(AcceleratedCompositing, "[UI ] delete layer %u @WebLayerTreeRenderer::deleteLayer \n", layerID);
401 layer->removeFromParent();
402 m_layers.remove(layerID);
403 m_fixedLayers.remove(layerID);
404 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
405 m_scrollingContentsLayers.remove(layerID);
411 void WebLayerTreeRenderer::ensureLayer(WebLayerID id)
413 // We have to leak the new layer's pointer and manage it ourselves,
414 // because OwnPtr is not copyable.
415 if (m_layers.find(id) == m_layers.end())
416 m_layers.add(id, createLayer(id).leakPtr());
419 void WebLayerTreeRenderer::setRootLayerID(WebLayerID layerID)
421 if (layerID == m_rootLayerID)
424 m_rootLayerID = layerID;
426 m_rootLayer->removeAllChildren();
431 GraphicsLayer* layer = layerByID(layerID);
435 m_rootLayer->addChild(layer);
438 PassRefPtr<LayerBackingStore> WebLayerTreeRenderer::getBackingStore(WebLayerID id)
440 TextureMapperLayer* layer = toTextureMapperLayer(layerByID(id));
442 RefPtr<LayerBackingStore> backingStore = static_cast<LayerBackingStore*>(layer->backingStore().get());
444 backingStore = LayerBackingStore::create();
445 layer->setBackingStore(backingStore.get());
447 ASSERT(backingStore);
451 void WebLayerTreeRenderer::createTile(WebLayerID layerID, int tileID, float scale)
453 getBackingStore(layerID)->createTile(tileID, scale);
456 void WebLayerTreeRenderer::removeTile(WebLayerID layerID, int tileID)
459 // Check whether composited graphics layer already been detached
460 GraphicsLayer* pGraphicsLayer = layerByID(layerID);
465 getBackingStore(layerID)->removeTile(tileID);
468 void WebLayerTreeRenderer::updateTile(WebLayerID layerID, int tileID, const TileUpdate& update)
470 RefPtr<LayerBackingStore> backingStore = getBackingStore(layerID);
471 backingStore->updateTile(tileID, update.sourceRect, update.targetRect, update.surface, update.offset);
472 m_backingStoresWithPendingBuffers.add(backingStore);
475 void WebLayerTreeRenderer::createImage(int64_t imageID, PassRefPtr<ShareableBitmap> weakBitmap)
477 RefPtr<ShareableBitmap> bitmap = weakBitmap;
478 RefPtr<TextureMapperTiledBackingStore> backingStore = TextureMapperTiledBackingStore::create();
479 m_directlyCompositedImages.set(imageID, backingStore);
480 backingStore->updateContents(m_textureMapper.get(), bitmap->createImage().get());
483 void WebLayerTreeRenderer::destroyImage(int64_t imageID)
485 m_directlyCompositedImages.remove(imageID);
488 void WebLayerTreeRenderer::assignImageToLayer(GraphicsLayer* layer, int64_t imageID)
491 layer->setContentsToMedia(0);
495 HashMap<int64_t, RefPtr<TextureMapperBackingStore> >::iterator it = m_directlyCompositedImages.find(imageID);
496 ASSERT(it != m_directlyCompositedImages.end());
497 layer->setContentsToMedia(it->second.get());
500 void WebLayerTreeRenderer::commitTileOperations()
502 HashSet<RefPtr<LayerBackingStore> >::iterator end = m_backingStoresWithPendingBuffers.end();
503 for (HashSet<RefPtr<LayerBackingStore> >::iterator it = m_backingStoresWithPendingBuffers.begin(); it != end; ++it)
504 (*it)->commitTileOperations(m_textureMapper.get());
506 m_backingStoresWithPendingBuffers.clear();
509 void WebLayerTreeRenderer::flushLayerChanges()
511 m_renderedContentsScrollPosition = m_pendingRenderedContentsScrollPosition;
513 m_rootLayer->syncCompositingState(FloatRect());
515 commitTileOperations();
517 // The pending tiles state is on its way for the screen, tell the web process to render the next one.
518 callOnMainThread(bind(&WebLayerTreeRenderer::renderNextFrame, this));
521 void WebLayerTreeRenderer::renderNextFrame()
523 if (m_layerTreeHostProxy)
524 m_layerTreeHostProxy->renderNextFrame();
527 void WebLayerTreeRenderer::ensureRootLayer()
531 if (!m_textureMapper)
532 m_textureMapper = TextureMapper::create(TextureMapper::OpenGLMode);
534 m_rootLayer = createLayer(InvalidWebLayerID);
535 m_rootLayer->setMasksToBounds(false);
536 m_rootLayer->setDrawsContent(false);
537 m_rootLayer->setAnchorPoint(FloatPoint3D(0, 0, 0));
539 // The root layer should not have zero size, or it would be optimized out.
540 m_rootLayer->setSize(FloatSize(1.0, 1.0));
541 toTextureMapperLayer(m_rootLayer.get())->setTextureMapper(m_textureMapper.get());
544 void WebLayerTreeRenderer::syncRemoteContent()
546 #if ENABLE(TIZEN_ONESHOT_DRAWING_SYNCHRONIZATION)
547 if (m_needsOneShotDrawingSynchronization)
551 // We enqueue messages and execute them during paint, as they require an active GL context.
554 for (size_t i = 0; i < m_renderQueue.size(); ++i)
557 m_renderQueue.clear();
560 void WebLayerTreeRenderer::purgeGLResources()
562 TextureMapperLayer* layer = toTextureMapperLayer(rootLayer());
565 layer->clearBackingStoresRecursive();
567 m_directlyCompositedImages.clear();
568 m_rootLayer->removeAllChildren();
570 m_rootLayerID = InvalidWebLayerID;
572 m_fixedLayers.clear();
573 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
574 m_scrollingContentsLayers.clear();
576 m_textureMapper.clear();
577 m_backingStoresWithPendingBuffers.clear();
579 callOnMainThread(bind(&WebLayerTreeRenderer::purgeBackingStores, this));
582 void WebLayerTreeRenderer::purgeBackingStores()
584 if (m_layerTreeHostProxy)
585 m_layerTreeHostProxy->purgeBackingStores();
588 void WebLayerTreeRenderer::detach()
590 m_layerTreeHostProxy = 0;
593 void WebLayerTreeRenderer::appendUpdate(const Function<void()>& function)
597 m_renderQueue.append(function);
600 void WebLayerTreeRenderer::setActive(bool active)
602 if (m_isActive == active)
605 // Have to clear render queue in both cases.
606 // If there are some updates in queue during activation then those updates are from previous instance of paint node
607 // and cannot be applied to the newly created instance.
608 m_renderQueue.clear();
610 #if ENABLE(TIZEN_ONESHOT_DRAWING_SYNCHRONIZATION)
611 m_needsOneShotDrawingSynchronization = false;
615 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
616 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
617 void WebLayerTreeRenderer::platformLayerChanged(WebCore::GraphicsLayer*, WebCore::PlatformLayer* oldPlatformLayer, WebCore::PlatformLayer* newPlatformLayer)
624 void WebLayerTreeRenderer::clearBackingStores()
626 TextureMapperLayer* layer = toTextureMapperLayer(rootLayer());
629 layer->clearBackingStoresRecursive();
631 m_directlyCompositedImages.clear();
632 m_backingStoresWithPendingBuffers.clear();
634 #endif // ENABLE(TIZEN_WEBKIT2_TILED_AC)
636 #if ENABLE(TIZEN_ONESHOT_DRAWING_SYNCHRONIZATION)
637 void WebLayerTreeRenderer::setNeedsOneShotDrawingSynchronization()
639 if (!m_needsOneShotDrawingSynchronization)
640 m_needsOneShotDrawingSynchronization = true;
643 void WebLayerTreeRenderer::doOneShotDrawingSynchronization()
645 if (m_needsOneShotDrawingSynchronization)
646 m_needsOneShotDrawingSynchronization = false;
650 } // namespace WebKit
652 #endif // USE(UI_SIDE_COMPOSITING)