initial import
[vuplus_webkit] / Source / WebCore / platform / graphics / chromium / GraphicsLayerChromium.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2009 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32
33 /** FIXME
34  * This file borrows code heavily from platform/graphics/win/GraphicsLayerCACF.cpp
35  * (and hence it includes both copyrights)
36  * Ideally the common code (mostly the code that keeps track of the layer hierarchy)
37  * should be kept separate and shared between platforms. It would be a well worthwhile
38  * effort once the Windows implementation (binaries and headers) of CoreAnimation is
39  * checked in to the WebKit repository. Until then only Apple can make this happen.
40  */
41
42 #include "config.h"
43
44 #if USE(ACCELERATED_COMPOSITING)
45
46 #include "GraphicsLayerChromium.h"
47
48 #include "Canvas2DLayerChromium.h"
49 #include "ContentLayerChromium.h"
50 #include "FloatConversion.h"
51 #include "FloatRect.h"
52 #include "Image.h"
53 #include "ImageLayerChromium.h"
54 #include "LayerChromium.h"
55 #include "PlatformString.h"
56 #include "SystemTime.h"
57
58 #include <wtf/CurrentTime.h>
59 #include <wtf/StringExtras.h>
60 #include <wtf/text/CString.h>
61
62 using namespace std;
63
64 namespace WebCore {
65
66 static void setLayerBorderColor(LayerChromium& layer, const Color& color)
67 {
68     layer.setBorderColor(color);
69 }
70
71 static void clearBorderColor(LayerChromium& layer)
72 {
73     layer.setBorderColor(static_cast<RGBA32>(0));
74 }
75
76 static void setLayerBackgroundColor(LayerChromium& layer, const Color& color)
77 {
78     layer.setBackgroundColor(color);
79 }
80
81 static void clearLayerBackgroundColor(LayerChromium& layer)
82 {
83     layer.setBackgroundColor(static_cast<RGBA32>(0));
84 }
85
86 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
87 {
88     return adoptPtr(new GraphicsLayerChromium(client));
89 }
90
91 GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
92     : GraphicsLayer(client)
93     , m_contentsLayerPurpose(NoContentsLayer)
94     , m_contentsLayerHasBackgroundColor(false)
95     , m_inSetChildren(false)
96 {
97     m_layer = ContentLayerChromium::create(this);
98
99     updateDebugIndicators();
100 }
101
102 GraphicsLayerChromium::~GraphicsLayerChromium()
103 {
104     if (m_layer) {
105         m_layer->setDelegate(0);
106         m_layer->clearRenderSurface();
107     }
108     if (m_contentsLayer) {
109         m_contentsLayer->setDelegate(0);
110         m_contentsLayer->clearRenderSurface();
111     }
112     if (m_transformLayer) {
113         m_transformLayer->setDelegate(0);
114         m_transformLayer->clearRenderSurface();
115     }
116 }
117
118 void GraphicsLayerChromium::setName(const String& inName)
119 {
120     m_nameBase = inName;
121     String name = String::format("GraphicsLayerChromium(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName;
122     GraphicsLayer::setName(name);
123     updateNames();
124 }
125
126 void GraphicsLayerChromium::updateNames()
127 {
128     if (m_layer)
129         m_layer->setName("Layer for " + m_nameBase);
130     if (m_transformLayer)
131         m_transformLayer->setName("TransformLayer for " + m_nameBase);
132     if (m_contentsLayer)
133         m_contentsLayer->setName("ContentsLayer for " + m_nameBase);
134 }
135
136 bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children)
137 {
138     m_inSetChildren = true;
139     bool childrenChanged = GraphicsLayer::setChildren(children);
140
141     if (childrenChanged)
142         updateChildList();
143     m_inSetChildren = false;
144
145     return childrenChanged;
146 }
147
148 void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer)
149 {
150     GraphicsLayer::addChild(childLayer);
151     if (!m_inSetChildren) 
152         updateChildList();
153 }
154
155 void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index)
156 {
157     GraphicsLayer::addChildAtIndex(childLayer, index);
158     updateChildList();
159 }
160
161 void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
162 {
163     GraphicsLayer::addChildBelow(childLayer, sibling);
164     updateChildList();
165 }
166
167 void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
168 {
169     GraphicsLayer::addChildAbove(childLayer, sibling);
170     updateChildList();
171 }
172
173 bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
174 {
175     if (GraphicsLayer::replaceChild(oldChild, newChild)) {
176         updateChildList();
177         return true;
178     }
179     return false;
180 }
181
182 void GraphicsLayerChromium::removeFromParent()
183 {
184     GraphicsLayer::removeFromParent();
185     layerForParent()->removeFromParent();
186 }
187
188 void GraphicsLayerChromium::setPosition(const FloatPoint& point)
189 {
190     GraphicsLayer::setPosition(point);
191     updateLayerPosition();
192 }
193
194 void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point)
195 {
196     if (point == m_anchorPoint)
197         return;
198
199     GraphicsLayer::setAnchorPoint(point);
200     updateAnchorPoint();
201 }
202
203 void GraphicsLayerChromium::setSize(const FloatSize& size)
204 {
205     if (size == m_size)
206         return;
207
208     GraphicsLayer::setSize(size);
209     updateLayerSize();
210 }
211
212 void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform)
213 {
214     if (transform == m_transform)
215         return;
216
217     GraphicsLayer::setTransform(transform);
218     updateTransform();
219 }
220
221 void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform)
222 {
223     if (transform == m_childrenTransform)
224         return;
225
226     GraphicsLayer::setChildrenTransform(transform);
227     updateChildrenTransform();
228 }
229
230 void GraphicsLayerChromium::setPreserves3D(bool preserves3D)
231 {
232     if (preserves3D == m_preserves3D)
233         return;
234
235     GraphicsLayer::setPreserves3D(preserves3D);
236     updateLayerPreserves3D();
237 }
238
239 void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds)
240 {
241     if (masksToBounds == m_masksToBounds)
242         return;
243
244     GraphicsLayer::setMasksToBounds(masksToBounds);
245     updateMasksToBounds();
246 }
247
248 void GraphicsLayerChromium::setDrawsContent(bool drawsContent)
249 {
250     if (drawsContent == m_drawsContent)
251         return;
252
253     GraphicsLayer::setDrawsContent(drawsContent);
254     updateLayerDrawsContent();
255 }
256
257 void GraphicsLayerChromium::setBackgroundColor(const Color& color)
258 {
259     if (m_backgroundColorSet && m_backgroundColor == color)
260         return;
261
262     GraphicsLayer::setBackgroundColor(color);
263
264     m_contentsLayerHasBackgroundColor = true;
265     updateLayerBackgroundColor();
266 }
267
268 void GraphicsLayerChromium::clearBackgroundColor()
269 {
270     if (!m_backgroundColorSet)
271         return;
272
273     GraphicsLayer::clearBackgroundColor();
274     clearLayerBackgroundColor(*m_contentsLayer);
275 }
276
277 void GraphicsLayerChromium::setContentsOpaque(bool opaque)
278 {
279     if (m_contentsOpaque == opaque)
280         return;
281
282     GraphicsLayer::setContentsOpaque(opaque);
283     updateContentsOpaque();
284 }
285
286 void GraphicsLayerChromium::setMaskLayer(GraphicsLayer* maskLayer)
287 {
288     if (maskLayer == m_maskLayer)
289         return;
290
291     GraphicsLayer::setMaskLayer(maskLayer);
292
293     LayerChromium* maskLayerChromium = m_maskLayer ? m_maskLayer->platformLayer() : 0;
294     if (maskLayerChromium)
295         maskLayerChromium->setIsMask(true);
296     m_layer->setMaskLayer(maskLayerChromium);
297 }
298
299 void GraphicsLayerChromium::setBackfaceVisibility(bool visible)
300 {
301     if (m_backfaceVisibility == visible)
302         return;
303
304     GraphicsLayer::setBackfaceVisibility(visible);
305     updateBackfaceVisibility();
306 }
307
308 void GraphicsLayerChromium::setOpacity(float opacity)
309 {
310     float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
311
312     if (m_opacity == clampedOpacity)
313         return;
314
315     GraphicsLayer::setOpacity(clampedOpacity);
316     primaryLayer()->setOpacity(opacity);
317 }
318
319 void GraphicsLayerChromium::setReplicatedByLayer(GraphicsLayer* layer)
320 {
321     GraphicsLayerChromium* layerChromium = static_cast<GraphicsLayerChromium*>(layer);
322     GraphicsLayer::setReplicatedByLayer(layer);
323     LayerChromium* replicaLayer = layerChromium ? layerChromium->primaryLayer() : 0;
324     primaryLayer()->setReplicaLayer(replicaLayer);
325 }
326
327
328 void GraphicsLayerChromium::setContentsNeedsDisplay()
329 {
330     if (m_contentsLayer)
331         m_contentsLayer->setNeedsDisplay();
332 }
333
334 void GraphicsLayerChromium::setNeedsDisplay()
335 {
336     if (drawsContent())
337         m_layer->setNeedsDisplay();
338 }
339
340 void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect)
341 {
342     if (drawsContent())
343         m_layer->setNeedsDisplay(rect);
344 }
345
346 void GraphicsLayerChromium::setContentsRect(const IntRect& rect)
347 {
348     if (rect == m_contentsRect)
349         return;
350
351     GraphicsLayer::setContentsRect(rect);
352     updateContentsRect();
353 }
354
355 void GraphicsLayerChromium::setContentsToImage(Image* image)
356 {
357     bool childrenChanged = false;
358     if (image) {
359         if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForImage) {
360             RefPtr<ImageLayerChromium> imageLayer = ImageLayerChromium::create(this);
361             setupContentsLayer(imageLayer.get());
362             m_contentsLayer = imageLayer;
363             m_contentsLayerPurpose = ContentsLayerForImage;
364             childrenChanged = true;
365         }
366         ImageLayerChromium* imageLayer = static_cast<ImageLayerChromium*>(m_contentsLayer.get());
367         imageLayer->setContents(image);
368         updateContentsRect();
369     } else {
370         if (m_contentsLayer) {
371             childrenChanged = true;
372
373             // The old contents layer will be removed via updateChildList.
374             m_contentsLayer = 0;
375         }
376     }
377
378     if (childrenChanged)
379         updateChildList();
380 }
381
382 void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* platformLayer)
383 {
384     bool childrenChanged = false;
385     if (platformLayer) {
386         platformLayer->setDelegate(this);
387         if (m_contentsLayer.get() != platformLayer) {
388             setupContentsLayer(platformLayer);
389             m_contentsLayer = platformLayer;
390             m_contentsLayerPurpose = ContentsLayerForCanvas;
391             childrenChanged = true;
392         }
393         m_contentsLayer->setNeedsDisplay();
394         updateContentsRect();
395     } else {
396         if (m_contentsLayer) {
397             childrenChanged = true;
398
399             // The old contents layer will be removed via updateChildList.
400             m_contentsLayer = 0;
401         }
402     }
403
404     if (childrenChanged)
405         updateChildList();
406 }
407
408 void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
409 {
410     bool childrenChanged = false;
411     if (layer) {
412         if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForVideo) {
413             setupContentsLayer(layer);
414             m_contentsLayer = layer;
415             m_contentsLayerPurpose = ContentsLayerForVideo;
416             childrenChanged = true;
417         }
418         layer->setDelegate(this);
419         layer->setNeedsDisplay();
420         updateContentsRect();
421     } else {
422         if (m_contentsLayer) {
423             childrenChanged = true;
424   
425             // The old contents layer will be removed via updateChildList.
426             m_contentsLayer = 0;
427         }
428     }
429   
430     if (childrenChanged)
431         updateChildList();
432 }
433
434 PlatformLayer* GraphicsLayerChromium::hostLayerForChildren() const
435 {
436     return m_transformLayer ? m_transformLayer.get() : m_layer.get();
437 }
438
439 PlatformLayer* GraphicsLayerChromium::layerForParent() const
440 {
441     return m_transformLayer ? m_transformLayer.get() : m_layer.get();
442 }
443
444 PlatformLayer* GraphicsLayerChromium::platformLayer() const
445 {
446     return primaryLayer();
447 }
448
449 void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color)
450 {
451     if (color.isValid())
452         setLayerBackgroundColor(*m_layer, color);
453     else
454         clearLayerBackgroundColor(*m_layer);
455 }
456
457 void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth)
458 {
459     if (color.isValid()) {
460         setLayerBorderColor(*m_layer, color);
461         m_layer->setBorderWidth(borderWidth);
462     } else {
463         clearBorderColor(*m_layer);
464         m_layer->setBorderWidth(0);
465     }
466 }
467
468 void GraphicsLayerChromium::updateChildList()
469 {
470     Vector<RefPtr<LayerChromium> > newChildren;
471
472     if (m_transformLayer) {
473         // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
474         newChildren.append(m_layer.get());
475     } else if (m_contentsLayer) {
476         // FIXME: add the contents layer in the correct order with negative z-order children.
477         // This does not cause visible rendering issues because currently contents layers are only used
478         // for replaced elements that don't have children.
479         newChildren.append(m_contentsLayer.get());
480     }
481
482     const Vector<GraphicsLayer*>& childLayers = children();
483     size_t numChildren = childLayers.size();
484     for (size_t i = 0; i < numChildren; ++i) {
485         GraphicsLayerChromium* curChild = static_cast<GraphicsLayerChromium*>(childLayers[i]);
486
487         LayerChromium* childLayer = curChild->layerForParent();
488         newChildren.append(childLayer);
489     }
490
491     for (size_t i = 0; i < newChildren.size(); ++i)
492         newChildren[i]->removeFromParent();
493
494     if (m_transformLayer) {
495         m_transformLayer->setChildren(newChildren);
496
497         if (m_contentsLayer) {
498             // If we have a transform layer, then the contents layer is parented in the
499             // primary layer (which is itself a child of the transform layer).
500             m_layer->removeAllChildren();
501             m_layer->addChild(m_contentsLayer);
502         }
503     } else
504         m_layer->setChildren(newChildren);
505 }
506
507 void GraphicsLayerChromium::updateLayerPosition()
508 {
509     // Position is offset on the layer by the layer anchor point.
510     FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(),
511                              m_position.y() + m_anchorPoint.y() * m_size.height());
512
513     primaryLayer()->setPosition(layerPosition);
514 }
515
516 void GraphicsLayerChromium::updateLayerSize()
517 {
518     IntSize layerSize(m_size.width(), m_size.height());
519     if (m_transformLayer) {
520         m_transformLayer->setBounds(layerSize);
521         // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
522         FloatPoint centerPoint(m_size.width() / 2, m_size.height() / 2);
523         m_layer->setPosition(centerPoint);
524     }
525
526     m_layer->setBounds(layerSize);
527
528     // Note that we don't resize m_contentsLayer. It's up the caller to do that.
529
530     // If we've changed the bounds, we need to recalculate the position
531     // of the layer, taking anchor point into account.
532     updateLayerPosition();
533 }
534
535 void GraphicsLayerChromium::updateAnchorPoint()
536 {
537     primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
538     primaryLayer()->setAnchorPointZ(m_anchorPoint.z());
539
540     updateLayerPosition();
541 }
542
543 void GraphicsLayerChromium::updateTransform()
544 {
545     primaryLayer()->setTransform(m_transform);
546 }
547
548 void GraphicsLayerChromium::updateChildrenTransform()
549 {
550     primaryLayer()->setSublayerTransform(m_childrenTransform);
551 }
552
553 void GraphicsLayerChromium::updateMasksToBounds()
554 {
555     m_layer->setMasksToBounds(m_masksToBounds);
556     updateDebugIndicators();
557 }
558
559 void GraphicsLayerChromium::updateContentsOpaque()
560 {
561     m_layer->setOpaque(m_contentsOpaque);
562 }
563
564 void GraphicsLayerChromium::updateBackfaceVisibility()
565 {
566     m_layer->setDoubleSided(m_backfaceVisibility);
567 }
568
569 void GraphicsLayerChromium::updateLayerPreserves3D()
570 {
571     if (m_preserves3D && !m_transformLayer) {
572         // Create the transform layer.
573         m_transformLayer = LayerChromium::create(this);
574
575         // Copy the position from this layer.
576         updateLayerPosition();
577         updateLayerSize();
578         updateAnchorPoint();
579         updateTransform();
580         updateChildrenTransform();
581
582         m_layer->setPosition(FloatPoint(m_size.width() / 2.0f, m_size.height() / 2.0f));
583
584         m_layer->setAnchorPoint(FloatPoint(0.5f, 0.5f));
585         TransformationMatrix identity;
586         m_layer->setTransform(identity);
587         
588         // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer.
589         m_layer->setOpacity(1);
590
591         // Move this layer to be a child of the transform layer.
592         if (m_layer->parent())
593             m_layer->parent()->replaceChild(m_layer.get(), m_transformLayer.get());
594         m_transformLayer->addChild(m_layer.get());
595
596         updateChildList();
597     } else if (!m_preserves3D && m_transformLayer) {
598         // Relace the transformLayer in the parent with this layer.
599         m_layer->removeFromParent();
600         if (m_transformLayer->parent())
601             m_transformLayer->parent()->replaceChild(m_transformLayer.get(), m_layer.get());
602
603         // Release the transform layer.
604         m_transformLayer = 0;
605
606         updateLayerPosition();
607         updateLayerSize();
608         updateAnchorPoint();
609         updateTransform();
610         updateChildrenTransform();
611
612         updateChildList();
613     }
614
615     updateOpacityOnLayer();
616     updateNames();
617 }
618
619 void GraphicsLayerChromium::updateLayerDrawsContent()
620 {
621     if (m_drawsContent)
622         m_layer->setNeedsDisplay();
623
624     updateDebugIndicators();
625 }
626
627 void GraphicsLayerChromium::updateLayerBackgroundColor()
628 {
629     if (!m_contentsLayer)
630         return;
631
632     // We never create the contents layer just for background color yet.
633     if (m_backgroundColorSet)
634         setLayerBackgroundColor(*m_contentsLayer, m_backgroundColor);
635     else
636         clearLayerBackgroundColor(*m_contentsLayer);
637 }
638
639 void GraphicsLayerChromium::updateContentsVideo()
640 {
641     // FIXME: Implement
642 }
643
644 void GraphicsLayerChromium::updateContentsRect()
645 {
646     if (!m_contentsLayer)
647         return;
648
649     m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
650     m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
651 }
652
653 void GraphicsLayerChromium::setupContentsLayer(LayerChromium* contentsLayer)
654 {
655     if (contentsLayer == m_contentsLayer)
656         return;
657
658     if (m_contentsLayer) {
659         m_contentsLayer->removeFromParent();
660         m_contentsLayer = 0;
661     }
662
663     if (contentsLayer) {
664         m_contentsLayer = contentsLayer;
665
666         m_contentsLayer->setAnchorPoint(FloatPoint(0, 0));
667
668         // Insert the content layer first. Video elements require this, because they have
669         // shadow content that must display in front of the video.
670         m_layer->insertChild(m_contentsLayer.get(), 0);
671
672         updateContentsRect();
673
674         if (showDebugBorders()) {
675             setLayerBorderColor(*m_contentsLayer, Color(0, 0, 128, 180));
676             m_contentsLayer->setBorderWidth(1);
677         }
678     }
679     updateDebugIndicators();
680     updateNames();
681 }
682
683 // This function simply mimics the operation of GraphicsLayerCA
684 void GraphicsLayerChromium::updateOpacityOnLayer()
685 {
686     primaryLayer()->setOpacity(m_opacity);
687 }
688
689 bool GraphicsLayerChromium::drawsContent() const
690 {
691     return GraphicsLayer::drawsContent();
692 }
693
694 bool GraphicsLayerChromium::preserves3D() const
695 {
696     return GraphicsLayer::preserves3D();
697 }
698
699 void GraphicsLayerChromium::paintContents(GraphicsContext& context, const IntRect& clip)
700 {
701     paintGraphicsLayerContents(context, clip);
702 }
703
704 void GraphicsLayerChromium::notifySyncRequired()
705 {
706     if (m_client)
707         m_client->notifySyncRequired(this);
708 }
709
710 } // namespace WebCore
711
712 #endif // USE(ACCELERATED_COMPOSITING)