2 Copyright (C) 2010 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(ACCELERATED_COMPOSITING)
24 #include "WebGraphicsLayer.h"
26 #include "Animation.h"
27 #include "BackingStore.h"
28 #include "DrawingAreaMessages.h"
29 #include "DrawingAreaProxyMessages.h"
31 #include "FrameView.h"
32 #include "GraphicsContext.h"
33 #include "GraphicsLayer.h"
36 #include "text/CString.h"
38 #include <wtf/CurrentTime.h>
40 using namespace WebKit;
44 static const float gTileDimension = 1024.0;
46 static HashMap<WebLayerID, WebGraphicsLayer*>& layerByIDMap()
48 static HashMap<WebLayerID, WebGraphicsLayer*> globalMap;
52 WebGraphicsLayer* WebGraphicsLayer::layerByID(WebKit::WebLayerID id)
54 HashMap<WebLayerID, WebGraphicsLayer*>& table = layerByIDMap();
55 HashMap<WebLayerID, WebGraphicsLayer*>::iterator it = table.find(id);
56 if (it == table.end())
61 static Vector<WebLayerID>& deletedLayerIDs()
63 static Vector<WebLayerID> layers;
67 static WebLayerID toWebLayerID(GraphicsLayer* layer)
69 return layer ? toWebGraphicsLayer(layer)->id() : 0;
72 void WebGraphicsLayer::notifyChange()
76 client()->notifySyncRequired(this);
79 WebGraphicsLayer::WebGraphicsLayer(GraphicsLayerClient* client)
80 : GraphicsLayer(client)
81 , m_needsDisplay(false)
83 , m_contentNeedsDisplay(false)
84 , m_hasPendingAnimations(false)
87 // Starting layer IDs from 1000, to help detect faulty IDs easily.
88 static WebLayerID sID = 1000;
89 m_layerInfo.id = ++sID;
90 layerByIDMap().add(id(), this);
93 WebGraphicsLayer::~WebGraphicsLayer()
95 layerByIDMap().remove(id());
96 deletedLayerIDs().append(id());
99 bool WebGraphicsLayer::setChildren(const Vector<GraphicsLayer*>& children)
101 bool ok = GraphicsLayer::setChildren(children);
107 void WebGraphicsLayer::addChild(GraphicsLayer* layer)
109 GraphicsLayer::addChild(layer);
113 void WebGraphicsLayer::addChildAtIndex(GraphicsLayer* layer, int index)
115 GraphicsLayer::addChildAtIndex(layer, index);
119 void WebGraphicsLayer::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
121 GraphicsLayer::addChildAbove(layer, sibling);
125 void WebGraphicsLayer::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
127 GraphicsLayer::addChildBelow(layer, sibling);
131 bool WebGraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
133 bool ok = GraphicsLayer::replaceChild(oldChild, newChild);
140 void WebGraphicsLayer::removeFromParent()
142 GraphicsLayer::removeFromParent();
146 void WebGraphicsLayer::setPosition(const FloatPoint& p)
151 GraphicsLayer::setPosition(p);
155 void WebGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
157 if (anchorPoint() == p)
160 GraphicsLayer::setAnchorPoint(p);
164 void WebGraphicsLayer::setSize(const FloatSize& size)
166 if (this->size() == size)
169 GraphicsLayer::setSize(size);
174 void WebGraphicsLayer::setTransform(const TransformationMatrix& t)
176 if (transform() == t)
179 GraphicsLayer::setTransform(t);
183 void WebGraphicsLayer::setChildrenTransform(const TransformationMatrix& t)
185 if (childrenTransform() == t)
188 GraphicsLayer::setChildrenTransform(t);
192 void WebGraphicsLayer::setPreserves3D(bool b)
194 if (preserves3D() == b)
197 GraphicsLayer::setPreserves3D(b);
201 void WebGraphicsLayer::setMasksToBounds(bool b)
203 if (masksToBounds() == b)
205 GraphicsLayer::setMasksToBounds(b);
209 void WebGraphicsLayer::setDrawsContent(bool b)
211 if (drawsContent() == b)
213 GraphicsLayer::setDrawsContent(b);
220 void WebGraphicsLayer::setContentsOpaque(bool b)
222 if (contentsOpaque() == b)
224 GraphicsLayer::setContentsOpaque(b);
228 void WebGraphicsLayer::setBackfaceVisibility(bool b)
230 if (backfaceVisibility() == b)
233 GraphicsLayer::setBackfaceVisibility(b);
237 void WebGraphicsLayer::setOpacity(float opacity)
239 if (this->opacity() == opacity)
242 GraphicsLayer::setOpacity(opacity);
246 void WebGraphicsLayer::setContentsRect(const IntRect& r)
248 if (contentsRect() == r)
253 GraphicsLayer::setContentsRect(r);
257 void WebGraphicsLayer::notifyAnimationStarted(double time)
260 client()->notifyAnimationStarted(this, time);
263 // We put these stub implementations here for when we implement accelerated cross-process animations.
264 bool WebGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
269 void WebGraphicsLayer::pauseAnimation(const String& animationName, double timeOffset)
273 void WebGraphicsLayer::removeAnimation(const String& animationName)
277 void WebGraphicsLayer::setContentsToImage(Image* image)
279 if (image == m_image.get())
284 GraphicsLayer::setContentsToImage(image);
288 void WebGraphicsLayer::setMaskLayer(GraphicsLayer* layer)
290 GraphicsLayer::setMaskLayer(layer);
294 void WebGraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
296 if (layer == replicaLayer())
298 GraphicsLayer::setReplicatedByLayer(layer);
302 void WebGraphicsLayer::setNeedsDisplay()
304 m_needsDisplay = true;
308 void WebGraphicsLayer::setNeedsDisplayInRect(const FloatRect& rect)
310 m_needsDisplayRect.unite(rect);
314 void WebGraphicsLayer::setContentsNeedsDisplay()
319 WebLayerID WebGraphicsLayer::id() const
321 return m_layerInfo.id;
324 void WebGraphicsLayer::didSynchronize()
326 m_needsDisplay = false;
328 m_needsDisplayRect = FloatRect();
329 if (m_hasPendingAnimations)
330 notifyAnimationStarted(WTF::currentTime());
331 m_hasPendingAnimations = false;
334 const WebLayerInfo& WebGraphicsLayer::layerInfo() const
339 void WebGraphicsLayer::syncCompositingState()
341 syncCompositingStateForThisLayerOnly();
342 for (size_t i = 0; i < children().size(); ++i)
343 children()[i]->syncCompositingState();
345 replicaLayer()->syncCompositingState();
347 maskLayer()->syncCompositingState();
350 WebGraphicsLayer* toWebGraphicsLayer(GraphicsLayer* layer)
352 return static_cast<WebGraphicsLayer*>(layer);
355 FloatRect WebGraphicsLayer::needsDisplayRect() const
357 FloatRect rect = FloatRect(0, 0, size().width(), size().height());
359 rect.intersect(m_needsDisplayRect);
363 Vector<WebKit::WebLayerID> WebGraphicsLayer::takeLayersToDelete()
365 Vector<WebKit::WebLayerID> layers = deletedLayerIDs();
366 deletedLayerIDs().clear();
370 void WebGraphicsLayer::syncCompositingStateForThisLayerOnly()
372 m_layerInfo.name = name();
373 m_layerInfo.anchorPoint = anchorPoint();
374 m_layerInfo.backfaceVisible = backfaceVisibility();
375 m_layerInfo.childrenTransform = childrenTransform();
376 m_layerInfo.contentsOpaque = contentsOpaque();
377 m_layerInfo.contentsRect = contentsRect();
378 m_layerInfo.drawsContent = drawsContent();
379 m_layerInfo.mask = toWebLayerID(maskLayer());
380 m_layerInfo.masksToBounds = masksToBounds();
381 m_layerInfo.opacity = opacity();
382 m_layerInfo.parent = toWebLayerID(parent());
383 m_layerInfo.pos = position();
384 m_layerInfo.preserves3D = preserves3D();
385 m_layerInfo.replica = toWebLayerID(replicaLayer());
386 m_layerInfo.size = FloatSize(size().width() * m_contentScale, size().height() * m_contentScale);
387 m_layerInfo.transform = transform();
388 m_contentNeedsDisplay = false;
389 m_layerInfo.children.clear();
391 for (size_t i = 0; i < children().size(); ++i)
392 m_layerInfo.children.append(toWebLayerID(children()[i]));
395 static Vector<FloatRect> divideIntoTiles(const FloatRect& rect)
397 Vector<FloatRect> tiles;
398 for (float y = rect.y(); y < rect.maxY(); y += gTileDimension) {
399 for (float x = rect.x(); x < rect.maxX(); x += gTileDimension) {
400 FloatRect tile(x, y, gTileDimension, gTileDimension);
401 tile.intersect(rect);
408 static void collectCompositingInfoForThisLayer(GraphicsLayer* layer, WebLayerTreeInfo& outInfo, Vector<WebGraphicsLayer*>& outLayers)
410 WebGraphicsLayer* layer = toWebGraphicsLayer(layer);
413 if (!layer->isModified())
416 outLayers.append(layer);
417 outInfo.layers.append(layer->layerInfo());
419 WebLayerInfo& layerInfo = outInfo.layers[outInfo.layers.size() - 1];
421 layerInfo.drawsContent = true;
424 static void collectCompositingInfoRecursively(GraphicsLayer* rootLayer, WebLayerTreeInfo& outInfo, Vector<WebGraphicsLayer*>& outLayers)
429 collectCompositingInfoForThisLayer(rootLayer, outInfo, outLayers);
430 collectCompositingInfoForThisLayer(rootLayer->maskLayer(), outInfo, outLayers);
431 collectCompositingInfoRecursively(rootLayer->replicaLayer(), outInfo, outLayers);
433 for (size_t i = 0; i < rootLayer->children().size(); ++i)
434 collectCompositingInfoRecursively(rootLayer->children()[i], outInfo, outLayers);
437 void WebGraphicsLayer::sendLayersToUIProcess(WebCore::GraphicsLayer* rootLayer, WebPage* webPage)
439 webPage->layoutIfNeeded();
440 webPage->corePage()->mainFrame()->view()->syncCompositingStateIncludingSubframes();
441 WebLayerTreeInfo compositingInfo;
442 compositingInfo.rootLayerID = rootLayer ? toWebGraphicsLayer(rootLayer)->id() : 0;
443 compositingInfo.contentScale = 1.0;
444 compositingInfo.deletedLayerIDs = WebGraphicsLayer::takeLayersToDelete();
445 Vector<WebGraphicsLayer*> layers;
447 collectCompositingInfoRecursively(rootLayer, compositingInfo, layers);
449 if (compositingInfo.deletedLayerIDs.isEmpty() && compositingInfo.layers.isEmpty())
452 webPage->send(Messages::DrawingAreaProxy::SyncCompositingLayers(compositingInfo));
454 for (size_t i = 0; i < layers.size(); ++i) {
455 WebGraphicsLayer* layer = layers[i];
456 FloatRect updateRect = layer->needsDisplayRect();
458 layer->didSynchronize();
460 if (updateRect.isEmpty())
463 RefPtr<Image> directImage = layer->image();
465 updateRect = layer->contentsRect();
466 else if (!layer->drawsContent())
469 Vector<FloatRect> tileRects = divideIntoTiles(updateRect);
470 for (size_t tileIndex = 0; tileIndex < tileRects.size(); ++tileIndex) {
471 const FloatRect& tileRect = tileRects[tileIndex];
472 IntRect enclosingUpdateRect = enclosingIntRect(tileRect);
474 WebLayerUpdateInfo chunk(enclosingUpdateRect);
475 chunk.layerID = uint32_t(layer->id());
476 RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(chunk.rect.size(), ShareableBitmap::SupportsAlpha);
480 if (!bitmap->createHandle(chunk.bitmapHandle))
484 QImage tileImage = bitmap->createQImage();
487 QPainter painter(&tileImage);
488 painter.translate(-tileRect.x(), -tileRect.y());
489 GraphicsContext context(&painter);
491 context.drawImage(directImage.get(), ColorSpaceDeviceRGB, layer->contentsRect(), FloatRect(0, 0, directImage->width(), directImage->height()));
493 layer->paintGraphicsLayerContents(context, enclosingUpdateRect);
497 webPage->send(Messages::DrawingAreaProxy::UpdateCompositingLayerContent(chunk));
502 static PassOwnPtr<GraphicsLayer> createWebGraphicsLayer(GraphicsLayerClient* client)
504 return adoptPtr(new WebGraphicsLayer(client));
507 void WebGraphicsLayer::initFactory()
509 GraphicsLayer::setGraphicsLayerFactory(createWebGraphicsLayer);