initial import
[vuplus_webkit] / Source / WebKit2 / WebProcess / WebCoreSupport / WebGraphicsLayer.cpp
1 /*
2  Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3
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.
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  Library General Public License for more details.
13
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.
18  */
19
20 #include "config.h"
21
22 #if USE(ACCELERATED_COMPOSITING)
23
24 #include "WebGraphicsLayer.h"
25
26 #include "Animation.h"
27 #include "BackingStore.h"
28 #include "DrawingAreaMessages.h"
29 #include "DrawingAreaProxyMessages.h"
30 #include "Frame.h"
31 #include "FrameView.h"
32 #include "GraphicsContext.h"
33 #include "GraphicsLayer.h"
34 #include "Page.h"
35 #include "WebPage.h"
36 #include "text/CString.h"
37 #include <HashMap.h>
38 #include <wtf/CurrentTime.h>
39
40 using namespace WebKit;
41
42 namespace WebCore {
43
44 static const float gTileDimension = 1024.0;
45
46 static HashMap<WebLayerID, WebGraphicsLayer*>& layerByIDMap()
47 {
48     static HashMap<WebLayerID, WebGraphicsLayer*> globalMap;
49     return globalMap;
50 }
51
52 WebGraphicsLayer* WebGraphicsLayer::layerByID(WebKit::WebLayerID id)
53 {
54     HashMap<WebLayerID, WebGraphicsLayer*>& table = layerByIDMap();
55     HashMap<WebLayerID, WebGraphicsLayer*>::iterator it = table.find(id);
56     if (it == table.end())
57         return 0;
58     return it->second;
59 }
60
61 static Vector<WebLayerID>& deletedLayerIDs()
62 {
63     static Vector<WebLayerID> layers;
64     return layers;
65 }
66
67 static WebLayerID toWebLayerID(GraphicsLayer* layer)
68 {
69     return layer ? toWebGraphicsLayer(layer)->id() : 0;
70 }
71
72 void WebGraphicsLayer::notifyChange()
73 {
74     m_modified = true;
75     if (client())
76         client()->notifySyncRequired(this);
77 }
78
79 WebGraphicsLayer::WebGraphicsLayer(GraphicsLayerClient* client)
80     : GraphicsLayer(client)
81     , m_needsDisplay(false)
82     , m_modified(false)
83     , m_contentNeedsDisplay(false)
84     , m_hasPendingAnimations(false)
85     , m_contentScale(1.f)
86 {
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);
91 }
92
93 WebGraphicsLayer::~WebGraphicsLayer()
94 {
95     layerByIDMap().remove(id());
96     deletedLayerIDs().append(id());
97 }
98
99 bool WebGraphicsLayer::setChildren(const Vector<GraphicsLayer*>& children)
100 {
101     bool ok = GraphicsLayer::setChildren(children);
102     if (ok)
103         notifyChange();
104     return ok;
105 }
106
107 void WebGraphicsLayer::addChild(GraphicsLayer* layer)
108 {
109     GraphicsLayer::addChild(layer);
110     notifyChange();
111 }
112
113 void WebGraphicsLayer::addChildAtIndex(GraphicsLayer* layer, int index)
114 {
115     GraphicsLayer::addChildAtIndex(layer, index);
116     notifyChange();
117 }
118
119 void WebGraphicsLayer::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
120 {
121     GraphicsLayer::addChildAbove(layer, sibling);
122     notifyChange();
123 }
124
125 void WebGraphicsLayer::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
126 {
127     GraphicsLayer::addChildBelow(layer, sibling);
128     notifyChange();
129 }
130
131 bool WebGraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
132 {
133     bool ok = GraphicsLayer::replaceChild(oldChild, newChild);
134
135     if (ok)
136         notifyChange();
137     return ok;
138 }
139
140 void WebGraphicsLayer::removeFromParent()
141 {
142     GraphicsLayer::removeFromParent();
143     notifyChange();
144 }
145
146 void WebGraphicsLayer::setPosition(const FloatPoint& p)
147 {
148     if (position() == p)
149         return;
150
151     GraphicsLayer::setPosition(p);
152     notifyChange();
153 }
154
155 void WebGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
156 {
157     if (anchorPoint() == p)
158         return;
159
160     GraphicsLayer::setAnchorPoint(p);
161     notifyChange();
162 }
163
164 void WebGraphicsLayer::setSize(const FloatSize& size)
165 {
166     if (this->size() == size)
167         return;
168
169     GraphicsLayer::setSize(size);
170     setNeedsDisplay();
171     notifyChange();
172 }
173
174 void WebGraphicsLayer::setTransform(const TransformationMatrix& t)
175 {
176     if (transform() == t)
177         return;
178
179     GraphicsLayer::setTransform(t);
180     notifyChange();
181 }
182
183 void WebGraphicsLayer::setChildrenTransform(const TransformationMatrix& t)
184 {
185     if (childrenTransform() == t)
186         return;
187
188     GraphicsLayer::setChildrenTransform(t);
189     notifyChange();
190 }
191
192 void WebGraphicsLayer::setPreserves3D(bool b)
193 {
194     if (preserves3D() == b)
195         return;
196
197     GraphicsLayer::setPreserves3D(b);
198     notifyChange();
199 }
200
201 void WebGraphicsLayer::setMasksToBounds(bool b)
202 {
203     if (masksToBounds() == b)
204         return;
205     GraphicsLayer::setMasksToBounds(b);
206     notifyChange();
207 }
208
209 void WebGraphicsLayer::setDrawsContent(bool b)
210 {
211     if (drawsContent() == b)
212         return;
213     GraphicsLayer::setDrawsContent(b);
214
215     if (b)
216         setNeedsDisplay();
217     notifyChange();
218 }
219
220 void WebGraphicsLayer::setContentsOpaque(bool b)
221 {
222     if (contentsOpaque() == b)
223         return;
224     GraphicsLayer::setContentsOpaque(b);
225     notifyChange();
226 }
227
228 void WebGraphicsLayer::setBackfaceVisibility(bool b)
229 {
230     if (backfaceVisibility() == b)
231         return;
232
233     GraphicsLayer::setBackfaceVisibility(b);
234     notifyChange();
235 }
236
237 void WebGraphicsLayer::setOpacity(float opacity)
238 {
239     if (this->opacity() == opacity)
240         return;
241
242     GraphicsLayer::setOpacity(opacity);
243     notifyChange();
244 }
245
246 void WebGraphicsLayer::setContentsRect(const IntRect& r)
247 {
248     if (contentsRect() == r)
249         return;
250     if (m_image)
251         setNeedsDisplay();
252
253     GraphicsLayer::setContentsRect(r);
254     notifyChange();
255 }
256
257 void WebGraphicsLayer::notifyAnimationStarted(double time)
258 {
259     if (client())
260         client()->notifyAnimationStarted(this, time);
261 }
262
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)
265 {
266     return false;
267 }
268
269 void WebGraphicsLayer::pauseAnimation(const String& animationName, double timeOffset)
270 {
271 }
272
273 void WebGraphicsLayer::removeAnimation(const String& animationName)
274 {
275 }
276
277 void WebGraphicsLayer::setContentsToImage(Image* image)
278 {
279     if (image == m_image.get())
280         return;
281
282     m_image = image;
283     setNeedsDisplay();
284     GraphicsLayer::setContentsToImage(image);
285     notifyChange();
286 }
287
288 void WebGraphicsLayer::setMaskLayer(GraphicsLayer* layer)
289 {
290     GraphicsLayer::setMaskLayer(layer);
291     notifyChange();
292 }
293
294 void WebGraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
295 {
296     if (layer == replicaLayer())
297         return;
298     GraphicsLayer::setReplicatedByLayer(layer);
299     notifyChange();
300 }
301
302 void WebGraphicsLayer::setNeedsDisplay()
303 {
304     m_needsDisplay = true;
305     notifyChange();
306 }
307
308 void WebGraphicsLayer::setNeedsDisplayInRect(const FloatRect& rect)
309 {
310     m_needsDisplayRect.unite(rect);
311     notifyChange();
312 }
313
314 void WebGraphicsLayer::setContentsNeedsDisplay()
315 {
316     setNeedsDisplay();
317 }
318
319 WebLayerID WebGraphicsLayer::id() const
320 {
321     return m_layerInfo.id;
322 }
323
324 void WebGraphicsLayer::didSynchronize()
325 {
326     m_needsDisplay = false;
327     m_modified = false;
328     m_needsDisplayRect = FloatRect();
329     if (m_hasPendingAnimations)
330         notifyAnimationStarted(WTF::currentTime());
331     m_hasPendingAnimations = false;
332 }
333
334 const WebLayerInfo& WebGraphicsLayer::layerInfo() const
335 {
336     return m_layerInfo;
337 }
338
339 void WebGraphicsLayer::syncCompositingState()
340 {
341     syncCompositingStateForThisLayerOnly();
342     for (size_t i = 0; i < children().size(); ++i)
343         children()[i]->syncCompositingState();
344     if (replicaLayer())
345         replicaLayer()->syncCompositingState();
346     if (maskLayer())
347         maskLayer()->syncCompositingState();
348 }
349
350 WebGraphicsLayer* toWebGraphicsLayer(GraphicsLayer* layer)
351 {
352     return static_cast<WebGraphicsLayer*>(layer);
353 }
354
355 FloatRect WebGraphicsLayer::needsDisplayRect() const
356 {
357     FloatRect rect = FloatRect(0, 0, size().width(), size().height());
358     if (!m_needsDisplay)
359         rect.intersect(m_needsDisplayRect);
360     return rect;
361 }
362
363 Vector<WebKit::WebLayerID> WebGraphicsLayer::takeLayersToDelete()
364 {
365     Vector<WebKit::WebLayerID> layers = deletedLayerIDs();
366     deletedLayerIDs().clear();
367     return layers;
368 }
369
370 void WebGraphicsLayer::syncCompositingStateForThisLayerOnly()
371 {
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();
390
391     for (size_t i = 0; i < children().size(); ++i)
392         m_layerInfo.children.append(toWebLayerID(children()[i]));
393 }
394
395 static Vector<FloatRect> divideIntoTiles(const FloatRect& rect)
396 {
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);
402             tiles.append(tile);
403         }
404     }
405     return tiles;
406 }
407
408 static void collectCompositingInfoForThisLayer(GraphicsLayer* layer, WebLayerTreeInfo& outInfo, Vector<WebGraphicsLayer*>& outLayers)
409 {
410     WebGraphicsLayer* layer = toWebGraphicsLayer(layer);
411     if (!layer)
412         return;
413     if (!layer->isModified())
414         return;
415
416     outLayers.append(layer);
417     outInfo.layers.append(layer->layerInfo());
418
419     WebLayerInfo& layerInfo = outInfo.layers[outInfo.layers.size() - 1];
420     if (layer->image())
421         layerInfo.drawsContent = true;
422 }
423
424 static void collectCompositingInfoRecursively(GraphicsLayer* rootLayer, WebLayerTreeInfo& outInfo, Vector<WebGraphicsLayer*>& outLayers)
425 {
426     if (!rootLayer)
427         return;
428
429     collectCompositingInfoForThisLayer(rootLayer, outInfo, outLayers);
430     collectCompositingInfoForThisLayer(rootLayer->maskLayer(), outInfo, outLayers);
431     collectCompositingInfoRecursively(rootLayer->replicaLayer(), outInfo, outLayers);
432
433     for (size_t i = 0; i < rootLayer->children().size(); ++i)
434         collectCompositingInfoRecursively(rootLayer->children()[i], outInfo, outLayers);
435 }
436
437 void WebGraphicsLayer::sendLayersToUIProcess(WebCore::GraphicsLayer* rootLayer, WebPage* webPage)
438 {
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;
446     if (rootLayer)
447         collectCompositingInfoRecursively(rootLayer, compositingInfo, layers);
448
449     if (compositingInfo.deletedLayerIDs.isEmpty() && compositingInfo.layers.isEmpty())
450         return;
451
452     webPage->send(Messages::DrawingAreaProxy::SyncCompositingLayers(compositingInfo));
453
454     for (size_t i = 0; i < layers.size(); ++i) {
455         WebGraphicsLayer* layer = layers[i];
456         FloatRect updateRect = layer->needsDisplayRect();
457
458         layer->didSynchronize();
459
460         if (updateRect.isEmpty())
461             continue;
462
463         RefPtr<Image> directImage = layer->image();
464         if (directImage)
465             updateRect = layer->contentsRect();
466         else if (!layer->drawsContent())
467             continue;
468
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);
473
474             WebLayerUpdateInfo chunk(enclosingUpdateRect);
475             chunk.layerID = uint32_t(layer->id());
476             RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(chunk.rect.size(), ShareableBitmap::SupportsAlpha);
477             if (!bitmap)
478                 return;
479
480             if (!bitmap->createHandle(chunk.bitmapHandle))
481                 return;
482
483 #if PLATFORM(QT)
484             QImage tileImage = bitmap->createQImage();
485             tileImage.fill(0);
486             {
487                 QPainter painter(&tileImage);
488                 painter.translate(-tileRect.x(), -tileRect.y());
489                 GraphicsContext context(&painter);
490                 if (directImage)
491                     context.drawImage(directImage.get(), ColorSpaceDeviceRGB, layer->contentsRect(), FloatRect(0, 0, directImage->width(), directImage->height()));
492                 else
493                     layer->paintGraphicsLayerContents(context, enclosingUpdateRect);
494             }
495 #endif
496
497             webPage->send(Messages::DrawingAreaProxy::UpdateCompositingLayerContent(chunk));
498         }
499     }
500 }
501
502 static PassOwnPtr<GraphicsLayer> createWebGraphicsLayer(GraphicsLayerClient* client)
503 {
504     return adoptPtr(new WebGraphicsLayer(client));
505 }
506
507 void WebGraphicsLayer::initFactory()
508 {
509     GraphicsLayer::setGraphicsLayerFactory(createWebGraphicsLayer);
510 }
511
512 }
513 #endif