2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * Copyright (C) 2009 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
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
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.
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.
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.
44 #if USE(ACCELERATED_COMPOSITING)
46 #include "GraphicsLayerChromium.h"
48 #include "Canvas2DLayerChromium.h"
49 #include "ContentLayerChromium.h"
50 #include "DrawingBuffer.h"
51 #include "FloatConversion.h"
52 #include "FloatRect.h"
54 #include "ImageLayerChromium.h"
55 #include "LayerChromium.h"
56 #include "PlatformString.h"
57 #include "SystemTime.h"
59 #include <wtf/CurrentTime.h>
60 #include <wtf/StringExtras.h>
61 #include <wtf/text/CString.h>
67 static void setLayerBorderColor(LayerChromium& layer, const Color& color)
69 layer.setBorderColor(color);
72 static void clearBorderColor(LayerChromium& layer)
74 layer.setBorderColor(static_cast<RGBA32>(0));
77 static void setLayerBackgroundColor(LayerChromium& layer, const Color& color)
79 layer.setBackgroundColor(color);
82 static void clearLayerBackgroundColor(LayerChromium& layer)
84 layer.setBackgroundColor(static_cast<RGBA32>(0));
87 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
89 return new GraphicsLayerChromium(client);
92 GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
93 : GraphicsLayer(client)
94 , m_contentsLayerPurpose(NoContentsLayer)
95 , m_contentsLayerHasBackgroundColor(false)
97 m_layer = ContentLayerChromium::create(this);
99 updateDebugIndicators();
102 GraphicsLayerChromium::~GraphicsLayerChromium()
105 m_layer->setOwner(0);
107 m_contentsLayer->setOwner(0);
108 if (m_transformLayer)
109 m_transformLayer->setOwner(0);
112 void GraphicsLayerChromium::setName(const String& inName)
115 String name = String::format("GraphicsLayerChromium(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName;
116 GraphicsLayer::setName(name);
120 void GraphicsLayerChromium::updateNames()
123 m_layer->setName("Layer for " + m_nameBase);
124 if (m_transformLayer)
125 m_transformLayer->setName("TransformLayer for " + m_nameBase);
127 m_contentsLayer->setName("ContentsLayer for " + m_nameBase);
130 bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children)
132 bool childrenChanged = GraphicsLayer::setChildren(children);
133 // FIXME: GraphicsLayer::setChildren calls addChild() for each sublayer, which
134 // will end up calling updateSublayerList() N times.
136 updateSublayerList();
138 return childrenChanged;
141 void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer)
143 GraphicsLayer::addChild(childLayer);
144 updateSublayerList();
147 void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index)
149 GraphicsLayer::addChildAtIndex(childLayer, index);
150 updateSublayerList();
153 void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
155 GraphicsLayer::addChildBelow(childLayer, sibling);
156 updateSublayerList();
159 void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
161 GraphicsLayer::addChildAbove(childLayer, sibling);
162 updateSublayerList();
165 bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
167 if (GraphicsLayer::replaceChild(oldChild, newChild)) {
168 updateSublayerList();
174 void GraphicsLayerChromium::removeFromParent()
176 GraphicsLayer::removeFromParent();
177 layerForSuperlayer()->removeFromSuperlayer();
180 void GraphicsLayerChromium::setPosition(const FloatPoint& point)
182 GraphicsLayer::setPosition(point);
183 updateLayerPosition();
186 void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point)
188 if (point == m_anchorPoint)
191 GraphicsLayer::setAnchorPoint(point);
195 void GraphicsLayerChromium::setSize(const FloatSize& size)
200 GraphicsLayer::setSize(size);
204 void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform)
206 if (transform == m_transform)
209 GraphicsLayer::setTransform(transform);
213 void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform)
215 if (transform == m_childrenTransform)
218 GraphicsLayer::setChildrenTransform(transform);
219 updateChildrenTransform();
222 void GraphicsLayerChromium::setPreserves3D(bool preserves3D)
224 if (preserves3D == m_preserves3D)
227 GraphicsLayer::setPreserves3D(preserves3D);
228 updateLayerPreserves3D();
231 void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds)
233 if (masksToBounds == m_masksToBounds)
236 GraphicsLayer::setMasksToBounds(masksToBounds);
237 updateMasksToBounds();
240 void GraphicsLayerChromium::setDrawsContent(bool drawsContent)
242 if (drawsContent == m_drawsContent)
245 GraphicsLayer::setDrawsContent(drawsContent);
246 updateLayerDrawsContent();
249 void GraphicsLayerChromium::setBackgroundColor(const Color& color)
251 if (m_backgroundColorSet && m_backgroundColor == color)
254 GraphicsLayer::setBackgroundColor(color);
256 m_contentsLayerHasBackgroundColor = true;
257 updateLayerBackgroundColor();
260 void GraphicsLayerChromium::clearBackgroundColor()
262 if (!m_backgroundColorSet)
265 GraphicsLayer::clearBackgroundColor();
266 clearLayerBackgroundColor(*m_contentsLayer);
269 void GraphicsLayerChromium::setContentsOpaque(bool opaque)
271 if (m_contentsOpaque == opaque)
274 GraphicsLayer::setContentsOpaque(opaque);
275 updateContentsOpaque();
278 void GraphicsLayerChromium::setMaskLayer(GraphicsLayer* maskLayer)
280 if (maskLayer == m_maskLayer)
283 GraphicsLayer::setMaskLayer(maskLayer);
285 LayerChromium* maskLayerChromium = m_maskLayer ? m_maskLayer->platformLayer() : 0;
286 m_layer->setMaskLayer(maskLayerChromium);
289 void GraphicsLayerChromium::setBackfaceVisibility(bool visible)
291 if (m_backfaceVisibility == visible)
294 GraphicsLayer::setBackfaceVisibility(visible);
295 updateBackfaceVisibility();
298 void GraphicsLayerChromium::setOpacity(float opacity)
300 float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
302 if (m_opacity == clampedOpacity)
305 GraphicsLayer::setOpacity(clampedOpacity);
306 primaryLayer()->setOpacity(opacity);
309 void GraphicsLayerChromium::setReplicatedByLayer(GraphicsLayer* layer)
311 GraphicsLayerChromium* layerChromium = static_cast<GraphicsLayerChromium*>(layer);
312 GraphicsLayer::setReplicatedByLayer(layer);
313 LayerChromium* replicaLayer = layerChromium ? layerChromium->primaryLayer() : 0;
314 primaryLayer()->setReplicaLayer(replicaLayer);
318 void GraphicsLayerChromium::setContentsNeedsDisplay()
321 m_contentsLayer->setNeedsDisplay();
324 void GraphicsLayerChromium::setNeedsDisplay()
327 m_layer->setNeedsDisplay();
330 void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect)
333 m_layer->setNeedsDisplay(rect);
336 void GraphicsLayerChromium::setContentsRect(const IntRect& rect)
338 if (rect == m_contentsRect)
341 GraphicsLayer::setContentsRect(rect);
342 updateContentsRect();
345 void GraphicsLayerChromium::setContentsToImage(Image* image)
347 bool childrenChanged = false;
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;
356 ImageLayerChromium* imageLayer = static_cast<ImageLayerChromium*>(m_contentsLayer.get());
357 imageLayer->setContents(image);
358 updateContentsRect();
360 if (m_contentsLayer) {
361 childrenChanged = true;
363 // The old contents layer will be removed via updateSublayerList.
369 updateSublayerList();
372 void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* platformLayer)
374 bool childrenChanged = false;
376 platformLayer->setOwner(this);
377 if (m_contentsLayer.get() != platformLayer) {
378 setupContentsLayer(platformLayer);
379 m_contentsLayer = platformLayer;
380 m_contentsLayerPurpose = ContentsLayerForCanvas;
381 childrenChanged = true;
383 m_contentsLayer->setNeedsDisplay();
384 updateContentsRect();
386 if (m_contentsLayer) {
387 childrenChanged = true;
389 // The old contents layer will be removed via updateSublayerList.
395 updateSublayerList();
398 void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
400 bool childrenChanged = false;
402 if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForVideo) {
403 setupContentsLayer(layer);
404 m_contentsLayer = layer;
405 m_contentsLayerPurpose = ContentsLayerForVideo;
406 childrenChanged = true;
408 layer->setOwner(this);
409 layer->setNeedsDisplay();
410 updateContentsRect();
412 if (m_contentsLayer) {
413 childrenChanged = true;
415 // The old contents layer will be removed via updateSublayerList.
421 updateSublayerList();
424 PlatformLayer* GraphicsLayerChromium::hostLayerForSublayers() const
426 return m_transformLayer ? m_transformLayer.get() : m_layer.get();
429 PlatformLayer* GraphicsLayerChromium::layerForSuperlayer() const
431 return m_transformLayer ? m_transformLayer.get() : m_layer.get();
434 PlatformLayer* GraphicsLayerChromium::platformLayer() const
436 return primaryLayer();
439 void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color)
442 setLayerBackgroundColor(*m_layer, color);
444 clearLayerBackgroundColor(*m_layer);
447 void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth)
449 if (color.isValid()) {
450 setLayerBorderColor(*m_layer, color);
451 m_layer->setBorderWidth(borderWidth);
453 clearBorderColor(*m_layer);
454 m_layer->setBorderWidth(0);
458 void GraphicsLayerChromium::updateSublayerList()
460 Vector<RefPtr<LayerChromium> > newSublayers;
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());
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]);
477 LayerChromium* childLayer = curChild->layerForSuperlayer();
478 newSublayers.append(childLayer);
481 for (size_t i = 0; i < newSublayers.size(); ++i)
482 newSublayers[i]->removeFromSuperlayer();
484 if (m_transformLayer) {
485 m_transformLayer->setSublayers(newSublayers);
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);
494 m_layer->setSublayers(newSublayers);
497 void GraphicsLayerChromium::updateLayerPosition()
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());
503 primaryLayer()->setPosition(layerPosition);
506 void GraphicsLayerChromium::updateLayerSize()
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);
516 m_layer->setBounds(layerSize);
518 // Note that we don't resize m_contentsLayer. It's up the caller to do that.
520 // If we've changed the bounds, we need to recalculate the position
521 // of the layer, taking anchor point into account.
522 updateLayerPosition();
525 void GraphicsLayerChromium::updateAnchorPoint()
527 primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
528 primaryLayer()->setAnchorPointZ(m_anchorPoint.z());
530 updateLayerPosition();
533 void GraphicsLayerChromium::updateTransform()
535 primaryLayer()->setTransform(m_transform);
538 void GraphicsLayerChromium::updateChildrenTransform()
540 primaryLayer()->setSublayerTransform(m_childrenTransform);
543 void GraphicsLayerChromium::updateMasksToBounds()
545 m_layer->setMasksToBounds(m_masksToBounds);
546 updateDebugIndicators();
549 void GraphicsLayerChromium::updateContentsOpaque()
551 m_layer->setOpaque(m_contentsOpaque);
554 void GraphicsLayerChromium::updateBackfaceVisibility()
556 m_layer->setDoubleSided(m_backfaceVisibility);
559 void GraphicsLayerChromium::updateLayerPreserves3D()
561 if (m_preserves3D && !m_transformLayer) {
562 // Create the transform layer.
563 m_transformLayer = LayerChromium::create(this);
565 // Copy the position from this layer.
566 updateLayerPosition();
570 updateChildrenTransform();
572 m_layer->setPosition(FloatPoint(m_size.width() / 2.0f, m_size.height() / 2.0f));
574 m_layer->setAnchorPoint(FloatPoint(0.5f, 0.5f));
575 TransformationMatrix identity;
576 m_layer->setTransform(identity);
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);
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());
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());
592 // Release the transform layer.
593 m_transformLayer = 0;
595 updateLayerPosition();
599 updateChildrenTransform();
601 updateSublayerList();
604 updateOpacityOnLayer();
608 void GraphicsLayerChromium::updateLayerDrawsContent()
611 m_layer->setNeedsDisplay();
613 updateDebugIndicators();
616 void GraphicsLayerChromium::updateLayerBackgroundColor()
618 if (!m_contentsLayer)
621 // We never create the contents layer just for background color yet.
622 if (m_backgroundColorSet)
623 setLayerBackgroundColor(*m_contentsLayer, m_backgroundColor);
625 clearLayerBackgroundColor(*m_contentsLayer);
628 void GraphicsLayerChromium::updateContentsVideo()
633 void GraphicsLayerChromium::updateContentsRect()
635 if (!m_contentsLayer)
638 m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
639 m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
642 void GraphicsLayerChromium::setupContentsLayer(LayerChromium* contentsLayer)
644 if (contentsLayer == m_contentsLayer)
647 if (m_contentsLayer) {
648 m_contentsLayer->removeFromSuperlayer();
653 m_contentsLayer = contentsLayer;
655 m_contentsLayer->setAnchorPoint(FloatPoint(0, 0));
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);
661 updateContentsRect();
663 if (showDebugBorders()) {
664 setLayerBorderColor(*m_contentsLayer, Color(0, 0, 128, 180));
665 m_contentsLayer->setBorderWidth(1);
668 updateDebugIndicators();
672 // This function simply mimics the operation of GraphicsLayerCA
673 void GraphicsLayerChromium::updateOpacityOnLayer()
675 primaryLayer()->setOpacity(m_opacity);
678 } // namespace WebCore
680 #endif // USE(ACCELERATED_COMPOSITING)