OSDN Git Service

Merge WebKit at r78450: Initial merge by git.
[android-x86/external-webkit.git] / 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 "DrawingBuffer.h"
51 #include "FloatConversion.h"
52 #include "FloatRect.h"
53 #include "Image.h"
54 #include "ImageLayerChromium.h"
55 #include "LayerChromium.h"
56 #include "PlatformString.h"
57 #include "SystemTime.h"
58
59 #include <wtf/CurrentTime.h>
60 #include <wtf/StringExtras.h>
61 #include <wtf/text/CString.h>
62
63 using namespace std;
64
65 namespace WebCore {
66
67 static void setLayerBorderColor(LayerChromium& layer, const Color& color)
68 {
69     layer.setBorderColor(color);
70 }
71
72 static void clearBorderColor(LayerChromium& layer)
73 {
74     layer.setBorderColor(static_cast<RGBA32>(0));
75 }
76
77 static void setLayerBackgroundColor(LayerChromium& layer, const Color& color)
78 {
79     layer.setBackgroundColor(color);
80 }
81
82 static void clearLayerBackgroundColor(LayerChromium& layer)
83 {
84     layer.setBackgroundColor(static_cast<RGBA32>(0));
85 }
86
87 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
88 {
89     return new GraphicsLayerChromium(client);
90 }
91
92 GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
93     : GraphicsLayer(client)
94     , m_contentsLayerPurpose(NoContentsLayer)
95     , m_contentsLayerHasBackgroundColor(false)
96 {
97     m_layer = ContentLayerChromium::create(this);
98
99     updateDebugIndicators();
100 }
101
102 GraphicsLayerChromium::~GraphicsLayerChromium()
103 {
104     if (m_layer)
105         m_layer->setOwner(0);
106     if (m_contentsLayer)
107         m_contentsLayer->setOwner(0);
108     if (m_transformLayer)
109         m_transformLayer->setOwner(0);
110 }
111
112 void GraphicsLayerChromium::setName(const String& inName)
113 {
114     String name = String::format("GraphicsLayerChromium(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName;
115     GraphicsLayer::setName(name);
116 }
117
118 bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children)
119 {
120     bool childrenChanged = GraphicsLayer::setChildren(children);
121     // FIXME: GraphicsLayer::setChildren calls addChild() for each sublayer, which
122     // will end up calling updateSublayerList() N times.
123     if (childrenChanged)
124         updateSublayerList();
125
126     return childrenChanged;
127 }
128
129 void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer)
130 {
131     GraphicsLayer::addChild(childLayer);
132     updateSublayerList();
133 }
134
135 void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index)
136 {
137     GraphicsLayer::addChildAtIndex(childLayer, index);
138     updateSublayerList();
139 }
140
141 void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
142 {
143     GraphicsLayer::addChildBelow(childLayer, sibling);
144     updateSublayerList();
145 }
146
147 void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
148 {
149     GraphicsLayer::addChildAbove(childLayer, sibling);
150     updateSublayerList();
151 }
152
153 bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
154 {
155     if (GraphicsLayer::replaceChild(oldChild, newChild)) {
156         updateSublayerList();
157         return true;
158     }
159     return false;
160 }
161
162 void GraphicsLayerChromium::removeFromParent()
163 {
164     GraphicsLayer::removeFromParent();
165     layerForSuperlayer()->removeFromSuperlayer();
166 }
167
168 void GraphicsLayerChromium::setPosition(const FloatPoint& point)
169 {
170     GraphicsLayer::setPosition(point);
171     updateLayerPosition();
172 }
173
174 void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point)
175 {
176     if (point == m_anchorPoint)
177         return;
178
179     GraphicsLayer::setAnchorPoint(point);
180     updateAnchorPoint();
181 }
182
183 void GraphicsLayerChromium::setSize(const FloatSize& size)
184 {
185     if (size == m_size)
186         return;
187
188     GraphicsLayer::setSize(size);
189     updateLayerSize();
190 }
191
192 void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform)
193 {
194     if (transform == m_transform)
195         return;
196
197     GraphicsLayer::setTransform(transform);
198     updateTransform();
199 }
200
201 void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform)
202 {
203     if (transform == m_childrenTransform)
204         return;
205
206     GraphicsLayer::setChildrenTransform(transform);
207     updateChildrenTransform();
208 }
209
210 void GraphicsLayerChromium::setPreserves3D(bool preserves3D)
211 {
212     if (preserves3D == m_preserves3D)
213         return;
214
215     GraphicsLayer::setPreserves3D(preserves3D);
216     updateLayerPreserves3D();
217 }
218
219 void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds)
220 {
221     if (masksToBounds == m_masksToBounds)
222         return;
223
224     GraphicsLayer::setMasksToBounds(masksToBounds);
225     updateMasksToBounds();
226 }
227
228 void GraphicsLayerChromium::setDrawsContent(bool drawsContent)
229 {
230     if (drawsContent == m_drawsContent)
231         return;
232
233     GraphicsLayer::setDrawsContent(drawsContent);
234     updateLayerDrawsContent();
235 }
236
237 void GraphicsLayerChromium::setBackgroundColor(const Color& color)
238 {
239     if (m_backgroundColorSet && m_backgroundColor == color)
240         return;
241
242     GraphicsLayer::setBackgroundColor(color);
243
244     m_contentsLayerHasBackgroundColor = true;
245     updateLayerBackgroundColor();
246 }
247
248 void GraphicsLayerChromium::clearBackgroundColor()
249 {
250     if (!m_backgroundColorSet)
251         return;
252
253     GraphicsLayer::clearBackgroundColor();
254     clearLayerBackgroundColor(*m_contentsLayer);
255 }
256
257 void GraphicsLayerChromium::setContentsOpaque(bool opaque)
258 {
259     if (m_contentsOpaque == opaque)
260         return;
261
262     GraphicsLayer::setContentsOpaque(opaque);
263     updateContentsOpaque();
264 }
265
266 void GraphicsLayerChromium::setMaskLayer(GraphicsLayer* maskLayer)
267 {
268     if (maskLayer == m_maskLayer)
269         return;
270
271     GraphicsLayer::setMaskLayer(maskLayer);
272
273     LayerChromium* maskLayerChromium = m_maskLayer ? m_maskLayer->platformLayer() : 0;
274     m_layer->setMaskLayer(maskLayerChromium);
275 }
276
277 void GraphicsLayerChromium::setBackfaceVisibility(bool visible)
278 {
279     if (m_backfaceVisibility == visible)
280         return;
281
282     GraphicsLayer::setBackfaceVisibility(visible);
283     updateBackfaceVisibility();
284 }
285
286 void GraphicsLayerChromium::setOpacity(float opacity)
287 {
288     float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
289
290     if (m_opacity == clampedOpacity)
291         return;
292
293     GraphicsLayer::setOpacity(clampedOpacity);
294     primaryLayer()->setOpacity(opacity);
295 }
296
297 void GraphicsLayerChromium::setReplicatedByLayer(GraphicsLayer* layer)
298 {
299     GraphicsLayerChromium* layerChromium = static_cast<GraphicsLayerChromium*>(layer);
300     GraphicsLayer::setReplicatedByLayer(layer);
301     LayerChromium* replicaLayer = layerChromium ? layerChromium->primaryLayer() : 0;
302     primaryLayer()->setReplicaLayer(replicaLayer);
303 }
304
305
306 void GraphicsLayerChromium::setContentsNeedsDisplay()
307 {
308     if (m_contentsLayer)
309         m_contentsLayer->setNeedsDisplay();
310 }
311
312 void GraphicsLayerChromium::setNeedsDisplay()
313 {
314     if (drawsContent())
315         m_layer->setNeedsDisplay();
316 }
317
318 void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect)
319 {
320     if (drawsContent())
321         m_layer->setNeedsDisplay(rect);
322 }
323
324 void GraphicsLayerChromium::setContentsRect(const IntRect& rect)
325 {
326     if (rect == m_contentsRect)
327         return;
328
329     GraphicsLayer::setContentsRect(rect);
330     updateContentsRect();
331 }
332
333 void GraphicsLayerChromium::setContentsToImage(Image* image)
334 {
335     bool childrenChanged = false;
336     if (image) {
337         if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForImage) {
338             RefPtr<ImageLayerChromium> imageLayer = ImageLayerChromium::create(this);
339             setupContentsLayer(imageLayer.get());
340             m_contentsLayer = imageLayer;
341             m_contentsLayerPurpose = ContentsLayerForImage;
342             childrenChanged = true;
343         }
344         ImageLayerChromium* imageLayer = static_cast<ImageLayerChromium*>(m_contentsLayer.get());
345         imageLayer->setContents(image);
346         updateContentsRect();
347     } else {
348         if (m_contentsLayer) {
349             childrenChanged = true;
350
351             // The old contents layer will be removed via updateSublayerList.
352             m_contentsLayer = 0;
353         }
354     }
355
356     if (childrenChanged)
357         updateSublayerList();
358 }
359
360 void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* platformLayer)
361 {
362     bool childrenChanged = false;
363     if (platformLayer) {
364         platformLayer->setOwner(this);
365         if (m_contentsLayer.get() != platformLayer) {
366             setupContentsLayer(platformLayer);
367             m_contentsLayer = platformLayer;
368             m_contentsLayerPurpose = ContentsLayerForCanvas;
369             childrenChanged = true;
370         }
371         m_contentsLayer->setNeedsDisplay();
372         updateContentsRect();
373     } else {
374         if (m_contentsLayer) {
375             childrenChanged = true;
376
377             // The old contents layer will be removed via updateSublayerList.
378             m_contentsLayer = 0;
379         }
380     }
381
382     if (childrenChanged)
383         updateSublayerList();
384 }
385
386 void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
387 {
388     bool childrenChanged = false;
389     if (layer) {
390         if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForVideo) {
391             setupContentsLayer(layer);
392             m_contentsLayer = layer;
393             m_contentsLayerPurpose = ContentsLayerForVideo;
394             childrenChanged = true;
395         }
396         layer->setOwner(this);
397         layer->setNeedsDisplay();
398         updateContentsRect();
399     } else {
400         if (m_contentsLayer) {
401             childrenChanged = true;
402   
403             // The old contents layer will be removed via updateSublayerList.
404             m_contentsLayer = 0;
405         }
406     }
407   
408     if (childrenChanged)
409         updateSublayerList();
410 }
411
412 PlatformLayer* GraphicsLayerChromium::hostLayerForSublayers() const
413 {
414     return m_transformLayer ? m_transformLayer.get() : m_layer.get();
415 }
416
417 PlatformLayer* GraphicsLayerChromium::layerForSuperlayer() const
418 {
419     return m_transformLayer ? m_transformLayer.get() : m_layer.get();
420 }
421
422 PlatformLayer* GraphicsLayerChromium::platformLayer() const
423 {
424     return primaryLayer();
425 }
426
427 void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color)
428 {
429     if (color.isValid())
430         setLayerBackgroundColor(*m_layer, color);
431     else
432         clearLayerBackgroundColor(*m_layer);
433 }
434
435 void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth)
436 {
437     if (color.isValid()) {
438         setLayerBorderColor(*m_layer, color);
439         m_layer->setBorderWidth(borderWidth);
440     } else {
441         clearBorderColor(*m_layer);
442         m_layer->setBorderWidth(0);
443     }
444 }
445
446 void GraphicsLayerChromium::updateSublayerList()
447 {
448     Vector<RefPtr<LayerChromium> > newSublayers;
449
450     if (m_transformLayer) {
451         // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
452         newSublayers.append(m_layer.get());
453     } else if (m_contentsLayer) {
454         // FIXME: add the contents layer in the correct order with negative z-order children.
455         // This does not cause visible rendering issues because currently contents layers are only used
456         // for replaced elements that don't have children.
457         newSublayers.append(m_contentsLayer.get());
458     }
459
460     const Vector<GraphicsLayer*>& childLayers = children();
461     size_t numChildren = childLayers.size();
462     for (size_t i = 0; i < numChildren; ++i) {
463         GraphicsLayerChromium* curChild = static_cast<GraphicsLayerChromium*>(childLayers[i]);
464
465         LayerChromium* childLayer = curChild->layerForSuperlayer();
466         newSublayers.append(childLayer);
467     }
468
469     for (size_t i = 0; i < newSublayers.size(); ++i)
470         newSublayers[i]->removeFromSuperlayer();
471
472     if (m_transformLayer) {
473         m_transformLayer->setSublayers(newSublayers);
474
475         if (m_contentsLayer) {
476             // If we have a transform layer, then the contents layer is parented in the
477             // primary layer (which is itself a child of the transform layer).
478             m_layer->removeAllSublayers();
479             m_layer->addSublayer(m_contentsLayer);
480         }
481     } else
482         m_layer->setSublayers(newSublayers);
483 }
484
485 void GraphicsLayerChromium::updateLayerPosition()
486 {
487     // Position is offset on the layer by the layer anchor point.
488     FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(),
489                              m_position.y() + m_anchorPoint.y() * m_size.height());
490
491     primaryLayer()->setPosition(layerPosition);
492 }
493
494 void GraphicsLayerChromium::updateLayerSize()
495 {
496     IntSize layerSize(m_size.width(), m_size.height());
497     if (m_transformLayer) {
498         m_transformLayer->setBounds(layerSize);
499         // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
500         FloatPoint centerPoint(m_size.width() / 2, m_size.height() / 2);
501         m_layer->setPosition(centerPoint);
502     }
503
504     m_layer->setBounds(layerSize);
505
506     // Note that we don't resize m_contentsLayer. It's up the caller to do that.
507
508     // If we've changed the bounds, we need to recalculate the position
509     // of the layer, taking anchor point into account.
510     updateLayerPosition();
511 }
512
513 void GraphicsLayerChromium::updateAnchorPoint()
514 {
515     primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
516     primaryLayer()->setAnchorPointZ(m_anchorPoint.z());
517
518     updateLayerPosition();
519 }
520
521 void GraphicsLayerChromium::updateTransform()
522 {
523     primaryLayer()->setTransform(m_transform);
524 }
525
526 void GraphicsLayerChromium::updateChildrenTransform()
527 {
528     primaryLayer()->setSublayerTransform(m_childrenTransform);
529 }
530
531 void GraphicsLayerChromium::updateMasksToBounds()
532 {
533     m_layer->setMasksToBounds(m_masksToBounds);
534     updateDebugIndicators();
535 }
536
537 void GraphicsLayerChromium::updateContentsOpaque()
538 {
539     m_layer->setOpaque(m_contentsOpaque);
540 }
541
542 void GraphicsLayerChromium::updateBackfaceVisibility()
543 {
544     m_layer->setDoubleSided(m_backfaceVisibility);
545 }
546
547 void GraphicsLayerChromium::updateLayerPreserves3D()
548 {
549     if (m_preserves3D && !m_transformLayer) {
550         // Create the transform layer.
551         m_transformLayer = LayerChromium::create(this);
552
553         // Copy the position from this layer.
554         updateLayerPosition();
555         updateLayerSize();
556         updateAnchorPoint();
557         updateTransform();
558         updateChildrenTransform();
559
560         m_layer->setPosition(FloatPoint(m_size.width() / 2.0f, m_size.height() / 2.0f));
561
562         m_layer->setAnchorPoint(FloatPoint(0.5f, 0.5f));
563         TransformationMatrix identity;
564         m_layer->setTransform(identity);
565         
566         // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer.
567         m_layer->setOpacity(1);
568
569         // Move this layer to be a child of the transform layer.
570         if (m_layer->superlayer())
571             m_layer->superlayer()->replaceSublayer(m_layer.get(), m_transformLayer.get());
572         m_transformLayer->addSublayer(m_layer.get());
573
574         updateSublayerList();
575     } else if (!m_preserves3D && m_transformLayer) {
576         // Relace the transformLayer in the parent with this layer.
577         m_layer->removeFromSuperlayer();
578         m_transformLayer->superlayer()->replaceSublayer(m_transformLayer.get(), m_layer.get());
579
580         // Release the transform layer.
581         m_transformLayer = 0;
582
583         updateLayerPosition();
584         updateLayerSize();
585         updateAnchorPoint();
586         updateTransform();
587         updateChildrenTransform();
588
589         updateSublayerList();
590     }
591
592     updateOpacityOnLayer();
593 }
594
595 void GraphicsLayerChromium::updateLayerDrawsContent()
596 {
597     if (m_drawsContent)
598         m_layer->setNeedsDisplay();
599
600     updateDebugIndicators();
601 }
602
603 void GraphicsLayerChromium::updateLayerBackgroundColor()
604 {
605     if (!m_contentsLayer)
606         return;
607
608     // We never create the contents layer just for background color yet.
609     if (m_backgroundColorSet)
610         setLayerBackgroundColor(*m_contentsLayer, m_backgroundColor);
611     else
612         clearLayerBackgroundColor(*m_contentsLayer);
613 }
614
615 void GraphicsLayerChromium::updateContentsVideo()
616 {
617     // FIXME: Implement
618 }
619
620 void GraphicsLayerChromium::updateContentsRect()
621 {
622     if (!m_contentsLayer)
623         return;
624
625     m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
626     m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
627 }
628
629 void GraphicsLayerChromium::setupContentsLayer(LayerChromium* contentsLayer)
630 {
631     if (contentsLayer == m_contentsLayer)
632         return;
633
634     if (m_contentsLayer) {
635         m_contentsLayer->removeFromSuperlayer();
636         m_contentsLayer = 0;
637     }
638
639     if (contentsLayer) {
640         m_contentsLayer = contentsLayer;
641
642         m_contentsLayer->setAnchorPoint(FloatPoint(0, 0));
643
644         // Insert the content layer first. Video elements require this, because they have
645         // shadow content that must display in front of the video.
646         m_layer->insertSublayer(m_contentsLayer.get(), 0);
647
648         updateContentsRect();
649
650         if (showDebugBorders()) {
651             setLayerBorderColor(*m_contentsLayer, Color(0, 0, 128, 180));
652             m_contentsLayer->setBorderWidth(1);
653         }
654     }
655     updateDebugIndicators();
656 }
657
658 // This function simply mimics the operation of GraphicsLayerCA
659 void GraphicsLayerChromium::updateOpacityOnLayer()
660 {
661     primaryLayer()->setOpacity(m_opacity);
662 }
663
664 } // namespace WebCore
665
666 #endif // USE(ACCELERATED_COMPOSITING)