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 "FloatConversion.h"
51 #include "FloatRect.h"
53 #include "ImageLayerChromium.h"
54 #include "LayerChromium.h"
55 #include "PlatformString.h"
56 #include "SystemTime.h"
58 #include <wtf/CurrentTime.h>
59 #include <wtf/StringExtras.h>
60 #include <wtf/text/CString.h>
66 static void setLayerBorderColor(LayerChromium& layer, const Color& color)
68 layer.setBorderColor(color);
71 static void clearBorderColor(LayerChromium& layer)
73 layer.setBorderColor(static_cast<RGBA32>(0));
76 static void setLayerBackgroundColor(LayerChromium& layer, const Color& color)
78 layer.setBackgroundColor(color);
81 static void clearLayerBackgroundColor(LayerChromium& layer)
83 layer.setBackgroundColor(static_cast<RGBA32>(0));
86 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
88 return adoptPtr(new GraphicsLayerChromium(client));
91 GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
92 : GraphicsLayer(client)
93 , m_contentsLayerPurpose(NoContentsLayer)
94 , m_contentsLayerHasBackgroundColor(false)
95 , m_inSetChildren(false)
97 m_layer = ContentLayerChromium::create(this);
99 updateDebugIndicators();
102 GraphicsLayerChromium::~GraphicsLayerChromium()
105 m_layer->setDelegate(0);
106 m_layer->clearRenderSurface();
108 if (m_contentsLayer) {
109 m_contentsLayer->setDelegate(0);
110 m_contentsLayer->clearRenderSurface();
112 if (m_transformLayer) {
113 m_transformLayer->setDelegate(0);
114 m_transformLayer->clearRenderSurface();
118 void GraphicsLayerChromium::setName(const String& inName)
121 String name = String::format("GraphicsLayerChromium(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName;
122 GraphicsLayer::setName(name);
126 void GraphicsLayerChromium::updateNames()
129 m_layer->setName("Layer for " + m_nameBase);
130 if (m_transformLayer)
131 m_transformLayer->setName("TransformLayer for " + m_nameBase);
133 m_contentsLayer->setName("ContentsLayer for " + m_nameBase);
136 bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children)
138 m_inSetChildren = true;
139 bool childrenChanged = GraphicsLayer::setChildren(children);
143 m_inSetChildren = false;
145 return childrenChanged;
148 void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer)
150 GraphicsLayer::addChild(childLayer);
151 if (!m_inSetChildren)
155 void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index)
157 GraphicsLayer::addChildAtIndex(childLayer, index);
161 void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
163 GraphicsLayer::addChildBelow(childLayer, sibling);
167 void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
169 GraphicsLayer::addChildAbove(childLayer, sibling);
173 bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
175 if (GraphicsLayer::replaceChild(oldChild, newChild)) {
182 void GraphicsLayerChromium::removeFromParent()
184 GraphicsLayer::removeFromParent();
185 layerForParent()->removeFromParent();
188 void GraphicsLayerChromium::setPosition(const FloatPoint& point)
190 GraphicsLayer::setPosition(point);
191 updateLayerPosition();
194 void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point)
196 if (point == m_anchorPoint)
199 GraphicsLayer::setAnchorPoint(point);
203 void GraphicsLayerChromium::setSize(const FloatSize& size)
208 GraphicsLayer::setSize(size);
212 void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform)
214 if (transform == m_transform)
217 GraphicsLayer::setTransform(transform);
221 void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform)
223 if (transform == m_childrenTransform)
226 GraphicsLayer::setChildrenTransform(transform);
227 updateChildrenTransform();
230 void GraphicsLayerChromium::setPreserves3D(bool preserves3D)
232 if (preserves3D == m_preserves3D)
235 GraphicsLayer::setPreserves3D(preserves3D);
236 updateLayerPreserves3D();
239 void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds)
241 if (masksToBounds == m_masksToBounds)
244 GraphicsLayer::setMasksToBounds(masksToBounds);
245 updateMasksToBounds();
248 void GraphicsLayerChromium::setDrawsContent(bool drawsContent)
250 if (drawsContent == m_drawsContent)
253 GraphicsLayer::setDrawsContent(drawsContent);
254 updateLayerDrawsContent();
257 void GraphicsLayerChromium::setBackgroundColor(const Color& color)
259 if (m_backgroundColorSet && m_backgroundColor == color)
262 GraphicsLayer::setBackgroundColor(color);
264 m_contentsLayerHasBackgroundColor = true;
265 updateLayerBackgroundColor();
268 void GraphicsLayerChromium::clearBackgroundColor()
270 if (!m_backgroundColorSet)
273 GraphicsLayer::clearBackgroundColor();
274 clearLayerBackgroundColor(*m_contentsLayer);
277 void GraphicsLayerChromium::setContentsOpaque(bool opaque)
279 if (m_contentsOpaque == opaque)
282 GraphicsLayer::setContentsOpaque(opaque);
283 updateContentsOpaque();
286 void GraphicsLayerChromium::setMaskLayer(GraphicsLayer* maskLayer)
288 if (maskLayer == m_maskLayer)
291 GraphicsLayer::setMaskLayer(maskLayer);
293 LayerChromium* maskLayerChromium = m_maskLayer ? m_maskLayer->platformLayer() : 0;
294 if (maskLayerChromium)
295 maskLayerChromium->setIsMask(true);
296 m_layer->setMaskLayer(maskLayerChromium);
299 void GraphicsLayerChromium::setBackfaceVisibility(bool visible)
301 if (m_backfaceVisibility == visible)
304 GraphicsLayer::setBackfaceVisibility(visible);
305 updateBackfaceVisibility();
308 void GraphicsLayerChromium::setOpacity(float opacity)
310 float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
312 if (m_opacity == clampedOpacity)
315 GraphicsLayer::setOpacity(clampedOpacity);
316 primaryLayer()->setOpacity(opacity);
319 void GraphicsLayerChromium::setReplicatedByLayer(GraphicsLayer* layer)
321 GraphicsLayerChromium* layerChromium = static_cast<GraphicsLayerChromium*>(layer);
322 GraphicsLayer::setReplicatedByLayer(layer);
323 LayerChromium* replicaLayer = layerChromium ? layerChromium->primaryLayer() : 0;
324 primaryLayer()->setReplicaLayer(replicaLayer);
328 void GraphicsLayerChromium::setContentsNeedsDisplay()
331 m_contentsLayer->setNeedsDisplay();
334 void GraphicsLayerChromium::setNeedsDisplay()
337 m_layer->setNeedsDisplay();
340 void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect)
343 m_layer->setNeedsDisplay(rect);
346 void GraphicsLayerChromium::setContentsRect(const IntRect& rect)
348 if (rect == m_contentsRect)
351 GraphicsLayer::setContentsRect(rect);
352 updateContentsRect();
355 void GraphicsLayerChromium::setContentsToImage(Image* image)
357 bool childrenChanged = false;
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;
366 ImageLayerChromium* imageLayer = static_cast<ImageLayerChromium*>(m_contentsLayer.get());
367 imageLayer->setContents(image);
368 updateContentsRect();
370 if (m_contentsLayer) {
371 childrenChanged = true;
373 // The old contents layer will be removed via updateChildList.
382 void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* platformLayer)
384 bool childrenChanged = false;
386 platformLayer->setDelegate(this);
387 if (m_contentsLayer.get() != platformLayer) {
388 setupContentsLayer(platformLayer);
389 m_contentsLayer = platformLayer;
390 m_contentsLayerPurpose = ContentsLayerForCanvas;
391 childrenChanged = true;
393 m_contentsLayer->setNeedsDisplay();
394 updateContentsRect();
396 if (m_contentsLayer) {
397 childrenChanged = true;
399 // The old contents layer will be removed via updateChildList.
408 void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
410 bool childrenChanged = false;
412 if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForVideo) {
413 setupContentsLayer(layer);
414 m_contentsLayer = layer;
415 m_contentsLayerPurpose = ContentsLayerForVideo;
416 childrenChanged = true;
418 layer->setDelegate(this);
419 layer->setNeedsDisplay();
420 updateContentsRect();
422 if (m_contentsLayer) {
423 childrenChanged = true;
425 // The old contents layer will be removed via updateChildList.
434 PlatformLayer* GraphicsLayerChromium::hostLayerForChildren() const
436 return m_transformLayer ? m_transformLayer.get() : m_layer.get();
439 PlatformLayer* GraphicsLayerChromium::layerForParent() const
441 return m_transformLayer ? m_transformLayer.get() : m_layer.get();
444 PlatformLayer* GraphicsLayerChromium::platformLayer() const
446 return primaryLayer();
449 void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color)
452 setLayerBackgroundColor(*m_layer, color);
454 clearLayerBackgroundColor(*m_layer);
457 void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth)
459 if (color.isValid()) {
460 setLayerBorderColor(*m_layer, color);
461 m_layer->setBorderWidth(borderWidth);
463 clearBorderColor(*m_layer);
464 m_layer->setBorderWidth(0);
468 void GraphicsLayerChromium::updateChildList()
470 Vector<RefPtr<LayerChromium> > newChildren;
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());
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]);
487 LayerChromium* childLayer = curChild->layerForParent();
488 newChildren.append(childLayer);
491 for (size_t i = 0; i < newChildren.size(); ++i)
492 newChildren[i]->removeFromParent();
494 if (m_transformLayer) {
495 m_transformLayer->setChildren(newChildren);
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);
504 m_layer->setChildren(newChildren);
507 void GraphicsLayerChromium::updateLayerPosition()
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());
513 primaryLayer()->setPosition(layerPosition);
516 void GraphicsLayerChromium::updateLayerSize()
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);
526 m_layer->setBounds(layerSize);
528 // Note that we don't resize m_contentsLayer. It's up the caller to do that.
530 // If we've changed the bounds, we need to recalculate the position
531 // of the layer, taking anchor point into account.
532 updateLayerPosition();
535 void GraphicsLayerChromium::updateAnchorPoint()
537 primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
538 primaryLayer()->setAnchorPointZ(m_anchorPoint.z());
540 updateLayerPosition();
543 void GraphicsLayerChromium::updateTransform()
545 primaryLayer()->setTransform(m_transform);
548 void GraphicsLayerChromium::updateChildrenTransform()
550 primaryLayer()->setSublayerTransform(m_childrenTransform);
553 void GraphicsLayerChromium::updateMasksToBounds()
555 m_layer->setMasksToBounds(m_masksToBounds);
556 updateDebugIndicators();
559 void GraphicsLayerChromium::updateContentsOpaque()
561 m_layer->setOpaque(m_contentsOpaque);
564 void GraphicsLayerChromium::updateBackfaceVisibility()
566 m_layer->setDoubleSided(m_backfaceVisibility);
569 void GraphicsLayerChromium::updateLayerPreserves3D()
571 if (m_preserves3D && !m_transformLayer) {
572 // Create the transform layer.
573 m_transformLayer = LayerChromium::create(this);
575 // Copy the position from this layer.
576 updateLayerPosition();
580 updateChildrenTransform();
582 m_layer->setPosition(FloatPoint(m_size.width() / 2.0f, m_size.height() / 2.0f));
584 m_layer->setAnchorPoint(FloatPoint(0.5f, 0.5f));
585 TransformationMatrix identity;
586 m_layer->setTransform(identity);
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);
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());
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());
603 // Release the transform layer.
604 m_transformLayer = 0;
606 updateLayerPosition();
610 updateChildrenTransform();
615 updateOpacityOnLayer();
619 void GraphicsLayerChromium::updateLayerDrawsContent()
622 m_layer->setNeedsDisplay();
624 updateDebugIndicators();
627 void GraphicsLayerChromium::updateLayerBackgroundColor()
629 if (!m_contentsLayer)
632 // We never create the contents layer just for background color yet.
633 if (m_backgroundColorSet)
634 setLayerBackgroundColor(*m_contentsLayer, m_backgroundColor);
636 clearLayerBackgroundColor(*m_contentsLayer);
639 void GraphicsLayerChromium::updateContentsVideo()
644 void GraphicsLayerChromium::updateContentsRect()
646 if (!m_contentsLayer)
649 m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
650 m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
653 void GraphicsLayerChromium::setupContentsLayer(LayerChromium* contentsLayer)
655 if (contentsLayer == m_contentsLayer)
658 if (m_contentsLayer) {
659 m_contentsLayer->removeFromParent();
664 m_contentsLayer = contentsLayer;
666 m_contentsLayer->setAnchorPoint(FloatPoint(0, 0));
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);
672 updateContentsRect();
674 if (showDebugBorders()) {
675 setLayerBorderColor(*m_contentsLayer, Color(0, 0, 128, 180));
676 m_contentsLayer->setBorderWidth(1);
679 updateDebugIndicators();
683 // This function simply mimics the operation of GraphicsLayerCA
684 void GraphicsLayerChromium::updateOpacityOnLayer()
686 primaryLayer()->setOpacity(m_opacity);
689 bool GraphicsLayerChromium::drawsContent() const
691 return GraphicsLayer::drawsContent();
694 bool GraphicsLayerChromium::preserves3D() const
696 return GraphicsLayer::preserves3D();
699 void GraphicsLayerChromium::paintContents(GraphicsContext& context, const IntRect& clip)
701 paintGraphicsLayerContents(context, clip);
704 void GraphicsLayerChromium::notifySyncRequired()
707 m_client->notifySyncRequired(this);
710 } // namespace WebCore
712 #endif // USE(ACCELERATED_COMPOSITING)