OSDN Git Service

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