2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #if USE(ACCELERATED_COMPOSITING)
30 #include "GraphicsLayerCA.h"
32 #include "Animation.h"
33 #include "FloatConversion.h"
34 #include "FloatRect.h"
35 #include "PlatformCALayer.h"
36 #include "PlatformString.h"
37 #include "RotateTransformOperation.h"
38 #include "ScaleTransformOperation.h"
39 #include "SystemTime.h"
40 #include "TranslateTransformOperation.h"
42 #include <wtf/CurrentTime.h>
43 #include <wtf/text/StringConcatenate.h>
47 #define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
51 // The threshold width or height above which a tiled layer will be used. This should be
52 // large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL
53 // texture size limit on all supported hardware.
54 static const int cMaxPixelDimension = 2000;
56 // If we send a duration of 0 to CA, then it will use the default duration
57 // of 250ms. So send a very small value instead.
58 static const float cAnimationAlmostZeroDuration = 1e-3f;
60 // CACurrentMediaTime() is a time since boot. These methods convert between that and
61 // WebCore time, which is system time (UTC).
62 static CFTimeInterval currentTimeToMediaTime(double t)
64 return CACurrentMediaTime() + t - WTF::currentTime();
67 static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType)
69 switch (transformType) {
70 case TransformOperation::SKEW_X:
71 case TransformOperation::SKEW_Y:
72 case TransformOperation::SKEW:
73 case TransformOperation::MATRIX:
74 case TransformOperation::ROTATE_3D:
75 case TransformOperation::MATRIX_3D:
76 case TransformOperation::PERSPECTIVE:
77 case TransformOperation::IDENTITY:
78 case TransformOperation::NONE:
85 static bool isTransformTypeFloatPoint3D(TransformOperation::OperationType transformType)
87 switch (transformType) {
88 case TransformOperation::SCALE:
89 case TransformOperation::SCALE_3D:
90 case TransformOperation::TRANSLATE:
91 case TransformOperation::TRANSLATE_3D:
98 static bool isTransformTypeNumber(TransformOperation::OperationType transformType)
100 return !isTransformTypeTransformationMatrix(transformType) && !isTransformTypeFloatPoint3D(transformType);
103 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, float& value)
105 switch (transformType) {
106 case TransformOperation::ROTATE:
107 case TransformOperation::ROTATE_X:
108 case TransformOperation::ROTATE_Y:
109 value = transformOp ? narrowPrecisionToFloat(deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle())) : 0;
111 case TransformOperation::SCALE_X:
112 value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1;
114 case TransformOperation::SCALE_Y:
115 value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1;
117 case TransformOperation::SCALE_Z:
118 value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1;
120 case TransformOperation::TRANSLATE_X:
121 value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0;
123 case TransformOperation::TRANSLATE_Y:
124 value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0;
126 case TransformOperation::TRANSLATE_Z:
127 value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0;
134 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, FloatPoint3D& value)
136 switch (transformType) {
137 case TransformOperation::SCALE:
138 case TransformOperation::SCALE_3D:
139 value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1);
140 value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1);
141 value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1);
143 case TransformOperation::TRANSLATE:
144 case TransformOperation::TRANSLATE_3D:
145 value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0);
146 value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0);
147 value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0);
154 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, TransformationMatrix& value)
156 switch (transformType) {
157 case TransformOperation::SKEW_X:
158 case TransformOperation::SKEW_Y:
159 case TransformOperation::SKEW:
160 case TransformOperation::MATRIX:
161 case TransformOperation::ROTATE_3D:
162 case TransformOperation::MATRIX_3D:
163 case TransformOperation::PERSPECTIVE:
164 case TransformOperation::IDENTITY:
165 case TransformOperation::NONE:
167 transformOp->apply(value, size);
169 value.makeIdentity();
176 #if HAVE_MODERN_QUARTZCORE
177 static PlatformCAAnimation::ValueFunctionType getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType)
179 // Use literal strings to avoid link-time dependency on those symbols.
180 switch (transformType) {
181 case TransformOperation::ROTATE_X:
182 return PlatformCAAnimation::RotateX;
183 case TransformOperation::ROTATE_Y:
184 return PlatformCAAnimation::RotateY;
185 case TransformOperation::ROTATE:
186 return PlatformCAAnimation::RotateZ;
187 case TransformOperation::SCALE_X:
188 return PlatformCAAnimation::ScaleX;
189 case TransformOperation::SCALE_Y:
190 return PlatformCAAnimation::ScaleY;
191 case TransformOperation::SCALE_Z:
192 return PlatformCAAnimation::ScaleZ;
193 case TransformOperation::TRANSLATE_X:
194 return PlatformCAAnimation::TranslateX;
195 case TransformOperation::TRANSLATE_Y:
196 return PlatformCAAnimation::TranslateY;
197 case TransformOperation::TRANSLATE_Z:
198 return PlatformCAAnimation::TranslateZ;
199 case TransformOperation::SCALE:
200 case TransformOperation::SCALE_3D:
201 return PlatformCAAnimation::Scale;
202 case TransformOperation::TRANSLATE:
203 case TransformOperation::TRANSLATE_3D:
204 return PlatformCAAnimation::Translate;
206 return PlatformCAAnimation::NoValueFunction;
211 static String propertyIdToString(AnimatedPropertyID property)
214 case AnimatedPropertyWebkitTransform:
216 case AnimatedPropertyOpacity:
218 case AnimatedPropertyBackgroundColor:
219 return "backgroundColor";
220 case AnimatedPropertyInvalid:
221 ASSERT_NOT_REACHED();
223 ASSERT_NOT_REACHED();
227 static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index)
229 return makeString(animationName, '_', String::number(property), '_', String::number(index));
232 static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim)
234 if (anim->timingFunction()->isStepsTimingFunction())
237 for (unsigned i = 0; i < valueList.size(); ++i) {
238 const TimingFunction* timingFunction = valueList.at(i)->timingFunction();
239 if (timingFunction && timingFunction->isStepsTimingFunction())
246 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
248 return new GraphicsLayerCA(client);
251 GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client)
252 : GraphicsLayer(client)
253 , m_contentsLayerPurpose(NoContentsLayer)
254 , m_contentsLayerHasBackgroundColor(false)
255 , m_uncommittedChanges(NoChange)
257 m_layer = PlatformCALayer::create(PlatformCALayer::LayerTypeWebLayer, this);
259 #if !HAVE_MODERN_QUARTZCORE
260 setContentsOrientation(defaultContentsOrientation());
263 updateDebugIndicators();
266 GraphicsLayerCA::~GraphicsLayerCA()
268 // We release our references to the PlatformCALayers here, but do not actively unparent them,
269 // since that will cause a commit and break our batched commit model. The layers will
270 // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers.
272 // Clean up the layer.
274 m_layer->setOwner(0);
277 m_contentsLayer->setOwner(0);
279 if (m_structuralLayer)
280 m_structuralLayer->setOwner(0);
285 void GraphicsLayerCA::setName(const String& name)
287 String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + name;
288 GraphicsLayer::setName(longName);
289 noteLayerPropertyChanged(NameChanged);
292 PlatformLayer* GraphicsLayerCA::platformLayer() const
294 return primaryLayer()->platformLayer();
297 bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children)
299 bool childrenChanged = GraphicsLayer::setChildren(children);
301 noteSublayersChanged();
303 return childrenChanged;
306 void GraphicsLayerCA::addChild(GraphicsLayer* childLayer)
308 GraphicsLayer::addChild(childLayer);
309 noteSublayersChanged();
312 void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index)
314 GraphicsLayer::addChildAtIndex(childLayer, index);
315 noteSublayersChanged();
318 void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
320 GraphicsLayer::addChildBelow(childLayer, sibling);
321 noteSublayersChanged();
324 void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
326 GraphicsLayer::addChildAbove(childLayer, sibling);
327 noteSublayersChanged();
330 bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
332 if (GraphicsLayer::replaceChild(oldChild, newChild)) {
333 noteSublayersChanged();
339 void GraphicsLayerCA::removeFromParent()
342 static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged();
343 GraphicsLayer::removeFromParent();
346 void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer)
348 if (layer == m_maskLayer)
351 GraphicsLayer::setMaskLayer(layer);
352 noteLayerPropertyChanged(MaskLayerChanged);
354 propagateLayerChangeToReplicas();
356 if (m_replicatedLayer)
357 static_cast<GraphicsLayerCA*>(m_replicatedLayer)->propagateLayerChangeToReplicas();
360 void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer)
362 if (layer == m_replicatedLayer)
365 GraphicsLayer::setReplicatedLayer(layer);
366 noteLayerPropertyChanged(ReplicatedLayerChanged);
369 void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer)
371 if (layer == m_replicaLayer)
374 GraphicsLayer::setReplicatedByLayer(layer);
375 noteSublayersChanged();
376 noteLayerPropertyChanged(ReplicatedLayerChanged);
379 void GraphicsLayerCA::setPosition(const FloatPoint& point)
381 if (point == m_position)
384 GraphicsLayer::setPosition(point);
385 noteLayerPropertyChanged(PositionChanged);
388 void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point)
390 if (point == m_anchorPoint)
393 GraphicsLayer::setAnchorPoint(point);
394 noteLayerPropertyChanged(AnchorPointChanged);
397 void GraphicsLayerCA::setSize(const FloatSize& size)
402 GraphicsLayer::setSize(size);
403 noteLayerPropertyChanged(SizeChanged);
406 void GraphicsLayerCA::setTransform(const TransformationMatrix& t)
408 if (t == m_transform)
411 GraphicsLayer::setTransform(t);
412 noteLayerPropertyChanged(TransformChanged);
415 void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t)
417 if (t == m_childrenTransform)
420 GraphicsLayer::setChildrenTransform(t);
421 noteLayerPropertyChanged(ChildrenTransformChanged);
424 void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
426 RefPtr<PlatformCAAnimation> anim = fromLayer->animationForKey(animationIdentifier);
432 fromLayer->removeAnimationForKey(animationIdentifier);
433 toLayer->addAnimationForKey(animationIdentifier, anim.get());
437 toLayer->addAnimationForKey(animationIdentifier, anim.get());
442 void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
444 // Look for running animations affecting this property.
445 AnimationsMap::const_iterator end = m_runningAnimations.end();
446 for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
447 const Vector<LayerPropertyAnimation>& propertyAnimations = it->second;
448 size_t numAnimations = propertyAnimations.size();
449 for (size_t i = 0; i < numAnimations; ++i) {
450 const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
451 if (currAnimation.m_property == property)
452 moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index), fromLayer, toLayer);
457 void GraphicsLayerCA::setPreserves3D(bool preserves3D)
459 if (preserves3D == m_preserves3D)
462 GraphicsLayer::setPreserves3D(preserves3D);
463 noteLayerPropertyChanged(Preserves3DChanged);
466 void GraphicsLayerCA::setMasksToBounds(bool masksToBounds)
468 if (masksToBounds == m_masksToBounds)
471 GraphicsLayer::setMasksToBounds(masksToBounds);
472 noteLayerPropertyChanged(MasksToBoundsChanged);
475 void GraphicsLayerCA::setDrawsContent(bool drawsContent)
477 if (drawsContent == m_drawsContent)
480 GraphicsLayer::setDrawsContent(drawsContent);
481 noteLayerPropertyChanged(DrawsContentChanged);
484 void GraphicsLayerCA::setAcceleratesDrawing(bool acceleratesDrawing)
486 if (acceleratesDrawing == m_acceleratesDrawing)
489 GraphicsLayer::setAcceleratesDrawing(acceleratesDrawing);
490 noteLayerPropertyChanged(AcceleratesDrawingChanged);
493 void GraphicsLayerCA::setBackgroundColor(const Color& color)
495 if (m_backgroundColorSet && m_backgroundColor == color)
498 GraphicsLayer::setBackgroundColor(color);
500 m_contentsLayerHasBackgroundColor = true;
501 noteLayerPropertyChanged(BackgroundColorChanged);
504 void GraphicsLayerCA::clearBackgroundColor()
506 if (!m_backgroundColorSet)
509 GraphicsLayer::clearBackgroundColor();
510 m_contentsLayerHasBackgroundColor = false;
511 noteLayerPropertyChanged(BackgroundColorChanged);
514 void GraphicsLayerCA::setContentsOpaque(bool opaque)
516 if (m_contentsOpaque == opaque)
519 GraphicsLayer::setContentsOpaque(opaque);
520 noteLayerPropertyChanged(ContentsOpaqueChanged);
523 void GraphicsLayerCA::setBackfaceVisibility(bool visible)
525 if (m_backfaceVisibility == visible)
528 GraphicsLayer::setBackfaceVisibility(visible);
529 noteLayerPropertyChanged(BackfaceVisibilityChanged);
532 void GraphicsLayerCA::setOpacity(float opacity)
534 float clampedOpacity = max(0.0f, min(opacity, 1.0f));
536 if (clampedOpacity == m_opacity)
539 GraphicsLayer::setOpacity(clampedOpacity);
540 noteLayerPropertyChanged(OpacityChanged);
543 void GraphicsLayerCA::setNeedsDisplay()
545 FloatRect hugeRect(-numeric_limits<float>::max() / 2, -numeric_limits<float>::max() / 2,
546 numeric_limits<float>::max(), numeric_limits<float>::max());
548 setNeedsDisplayInRect(hugeRect);
551 void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& rect)
556 const size_t maxDirtyRects = 32;
558 for (size_t i = 0; i < m_dirtyRects.size(); ++i) {
559 if (m_dirtyRects[i].contains(rect))
563 if (m_dirtyRects.size() < maxDirtyRects)
564 m_dirtyRects.append(rect);
566 m_dirtyRects[0].unite(rect);
568 noteLayerPropertyChanged(DirtyRectsChanged);
571 void GraphicsLayerCA::setContentsNeedsDisplay()
573 noteLayerPropertyChanged(ContentsNeedsDisplay);
576 void GraphicsLayerCA::setContentsRect(const IntRect& rect)
578 if (rect == m_contentsRect)
581 GraphicsLayer::setContentsRect(rect);
582 noteLayerPropertyChanged(ContentsRectChanged);
585 bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset)
587 ASSERT(!animationName.isEmpty());
589 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
592 #if !HAVE_MODERN_QUARTZCORE
593 // Older versions of QuartzCore do not handle opacity in transform layers properly, so we will
594 // always do software animation in that case.
595 if (valueList.property() == AnimatedPropertyOpacity)
599 // CoreAnimation does not handle the steps() timing function. Fall back
600 // to software animation in that case.
601 if (animationHasStepsTimingFunction(valueList, anim))
604 bool createdAnimations = false;
605 if (valueList.property() == AnimatedPropertyWebkitTransform)
606 createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize);
608 createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset);
610 if (createdAnimations)
611 noteLayerPropertyChanged(AnimationChanged);
613 return createdAnimations;
616 void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset)
618 if (!animationIsRunning(animationName))
621 AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName);
622 if (it != m_animationsToProcess.end()) {
623 AnimationProcessingAction& processingInfo = it->second;
624 // If an animation is scheduled to be removed, don't change the remove to a pause.
625 if (processingInfo.action != Remove)
626 processingInfo.action = Pause;
628 m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset));
630 noteLayerPropertyChanged(AnimationChanged);
633 void GraphicsLayerCA::removeAnimation(const String& animationName)
635 if (!animationIsRunning(animationName))
638 m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove));
639 noteLayerPropertyChanged(AnimationChanged);
642 void GraphicsLayerCA::platformCALayerAnimationStarted(CFTimeInterval startTime)
645 m_client->notifyAnimationStarted(this, startTime);
648 void GraphicsLayerCA::setContentsToImage(Image* image)
651 CGImageRef newImage = image->nativeImageForCurrentFrame();
655 // Check to see if the image changed; we have to do this because the call to
656 // CGImageCreateCopyWithColorSpace() below can create a new image every time.
657 if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage)
660 m_uncorrectedContentsImage = newImage;
661 m_pendingContentsImage = newImage;
664 CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get());
666 static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
667 if (colorSpace && CFEqual(colorSpace, deviceRGB)) {
668 // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such
669 // images to CA we need to tag them similarly so CA rendering matches CG rendering.
670 static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
671 m_pendingContentsImage.adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB));
674 m_contentsLayerPurpose = ContentsLayerForImage;
675 if (!m_contentsLayer)
676 noteSublayersChanged();
678 m_uncorrectedContentsImage = 0;
679 m_pendingContentsImage = 0;
680 m_contentsLayerPurpose = NoContentsLayer;
682 noteSublayersChanged();
685 noteLayerPropertyChanged(ContentsImageChanged);
688 void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer)
690 if (m_contentsLayer && mediaLayer == m_contentsLayer->platformLayer())
693 // FIXME: The passed in layer might be a raw layer or an externally created
694 // PlatformCALayer. To determine this we attempt to get the
695 // PlatformCALayer pointer. If this returns a null pointer we assume it's
696 // raw. This test might be invalid if the raw layer is, for instance, the
697 // PlatformCALayer is using a user data pointer in the raw layer, and
698 // the creator of the raw layer is using it for some other purpose.
699 // For now we don't support such a case.
700 PlatformCALayer* platformCALayer = PlatformCALayer::platformCALayer(mediaLayer);
701 m_contentsLayer = mediaLayer ? (platformCALayer ? platformCALayer : PlatformCALayer::create(mediaLayer, this)) : 0;
702 m_contentsLayerPurpose = mediaLayer ? ContentsLayerForMedia : NoContentsLayer;
704 noteSublayersChanged();
705 noteLayerPropertyChanged(ContentsMediaLayerChanged);
708 void GraphicsLayerCA::setContentsToCanvas(PlatformLayer* canvasLayer)
710 if (m_contentsLayer && canvasLayer == m_contentsLayer->platformLayer())
713 // Create the PlatformCALayer to wrap the incoming layer
714 m_contentsLayer = canvasLayer ? PlatformCALayer::create(canvasLayer, this) : 0;
716 m_contentsLayerPurpose = canvasLayer ? ContentsLayerForCanvas : NoContentsLayer;
718 noteSublayersChanged();
719 noteLayerPropertyChanged(ContentsCanvasLayerChanged);
722 void GraphicsLayerCA::layerDidDisplay(PlatformLayer* layer)
724 PlatformCALayer* currentLayer = PlatformCALayer::platformCALayer(layer);
725 PlatformCALayer* sourceLayer;
726 LayerMap* layerCloneMap;
728 if (currentLayer == m_layer) {
729 sourceLayer = m_layer.get();
730 layerCloneMap = m_layerClones.get();
731 } else if (currentLayer == m_contentsLayer) {
732 sourceLayer = m_contentsLayer.get();
733 layerCloneMap = m_contentsLayerClones.get();
738 LayerMap::const_iterator end = layerCloneMap->end();
739 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
740 PlatformCALayer* currClone = it->second.get();
744 if (currClone->contents() != sourceLayer->contents())
745 currClone->setContents(sourceLayer->contents());
747 currClone->setContentsChanged();
752 void GraphicsLayerCA::syncCompositingState()
754 recursiveCommitChanges();
757 void GraphicsLayerCA::syncCompositingStateForThisLayerOnly()
759 commitLayerChangesBeforeSublayers();
760 commitLayerChangesAfterSublayers();
763 void GraphicsLayerCA::recursiveCommitChanges()
765 commitLayerChangesBeforeSublayers();
768 static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesBeforeSublayers();
770 const Vector<GraphicsLayer*>& childLayers = children();
771 size_t numChildren = childLayers.size();
772 for (size_t i = 0; i < numChildren; ++i) {
773 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
774 curChild->recursiveCommitChanges();
778 static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveCommitChanges();
781 static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers();
783 commitLayerChangesAfterSublayers();
786 void GraphicsLayerCA::commitLayerChangesBeforeSublayers()
788 if (!m_uncommittedChanges)
791 // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to
792 if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged))
793 updateStructuralLayer();
795 if (m_uncommittedChanges & NameChanged)
798 if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged
799 updateContentsImage();
801 if (m_uncommittedChanges & ContentsMediaLayerChanged) // Needs to happen before ChildrenChanged
802 updateContentsMediaLayer();
804 if (m_uncommittedChanges & ContentsCanvasLayerChanged) // Needs to happen before ChildrenChanged
805 updateContentsCanvasLayer();
807 if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video
808 updateLayerBackgroundColor();
810 if (m_uncommittedChanges & ChildrenChanged)
811 updateSublayerList();
813 if (m_uncommittedChanges & PositionChanged)
814 updateLayerPosition();
816 if (m_uncommittedChanges & AnchorPointChanged)
819 if (m_uncommittedChanges & SizeChanged)
822 if (m_uncommittedChanges & TransformChanged)
825 if (m_uncommittedChanges & ChildrenTransformChanged)
826 updateChildrenTransform();
828 if (m_uncommittedChanges & MasksToBoundsChanged)
829 updateMasksToBounds();
831 if (m_uncommittedChanges & DrawsContentChanged)
832 updateLayerDrawsContent();
834 if (m_uncommittedChanges & ContentsOpaqueChanged)
835 updateContentsOpaque();
837 if (m_uncommittedChanges & BackfaceVisibilityChanged)
838 updateBackfaceVisibility();
840 if (m_uncommittedChanges & OpacityChanged)
841 updateOpacityOnLayer();
843 if (m_uncommittedChanges & AnimationChanged)
844 updateLayerAnimations();
846 if (m_uncommittedChanges & DirtyRectsChanged)
847 repaintLayerDirtyRects();
849 if (m_uncommittedChanges & ContentsRectChanged)
850 updateContentsRect();
852 if (m_uncommittedChanges & MaskLayerChanged)
855 if (m_uncommittedChanges & ContentsNeedsDisplay)
856 updateContentsNeedsDisplay();
858 if (m_uncommittedChanges & AcceleratesDrawingChanged)
859 updateAcceleratesDrawing();
862 void GraphicsLayerCA::commitLayerChangesAfterSublayers()
864 if (!m_uncommittedChanges)
867 if (m_uncommittedChanges & ReplicatedLayerChanged)
868 updateReplicatedLayers();
870 m_uncommittedChanges = NoChange;
873 void GraphicsLayerCA::updateLayerNames()
875 switch (structuralLayerPurpose()) {
876 case StructuralLayerForPreserves3D:
877 m_structuralLayer->setName("Transform layer " + name());
879 case StructuralLayerForReplicaFlattening:
880 m_structuralLayer->setName("Replica flattening layer " + name());
882 case NoStructuralLayer:
885 m_layer->setName(name());
888 void GraphicsLayerCA::updateSublayerList()
890 PlatformCALayerList newSublayers;
891 const Vector<GraphicsLayer*>& childLayers = children();
893 if (m_structuralLayer || m_contentsLayer || childLayers.size() > 0) {
894 if (m_structuralLayer) {
895 // Add the replica layer first.
897 newSublayers.append(static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer());
898 // Add the primary layer. Even if we have negative z-order children, the primary layer always comes behind.
899 newSublayers.append(m_layer);
900 } else if (m_contentsLayer) {
901 // FIXME: add the contents layer in the correct order with negative z-order children.
902 // This does not cause visible rendering issues because currently contents layers are only used
903 // for replaced elements that don't have children.
904 newSublayers.append(m_contentsLayer);
907 size_t numChildren = childLayers.size();
908 for (size_t i = 0; i < numChildren; ++i) {
909 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
910 PlatformCALayer* childLayer = curChild->layerForSuperlayer();
911 newSublayers.append(childLayer);
914 for (size_t i = 0; i < newSublayers.size(); --i)
915 newSublayers[i]->removeFromSuperlayer();
918 if (m_structuralLayer) {
919 m_structuralLayer->setSublayers(newSublayers);
921 if (m_contentsLayer) {
922 // If we have a transform layer, then the contents layer is parented in the
923 // primary layer (which is itself a child of the transform layer).
924 m_layer->removeAllSublayers();
925 m_layer->appendSublayer(m_contentsLayer.get());
928 m_layer->setSublayers(newSublayers);
931 void GraphicsLayerCA::updateLayerPosition()
933 FloatSize usedSize = m_usingTiledLayer ? constrainedSize() : m_size;
935 // Position is offset on the layer by the layer anchor point.
936 FloatPoint posPoint(m_position.x() + m_anchorPoint.x() * usedSize.width(),
937 m_position.y() + m_anchorPoint.y() * usedSize.height());
939 primaryLayer()->setPosition(posPoint);
941 if (LayerMap* layerCloneMap = primaryLayerClones()) {
942 LayerMap::const_iterator end = layerCloneMap->end();
943 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
944 FloatPoint clonePosition = posPoint;
945 if (m_replicaLayer && isReplicatedRootClone(it->first)) {
946 // Maintain the special-case position for the root of a clone subtree,
947 // which we set up in replicatedLayerRoot().
948 clonePosition = positionForCloneRootLayer();
950 it->second->setPosition(clonePosition);
955 void GraphicsLayerCA::updateLayerSize()
957 FloatRect rect(0, 0, m_size.width(), m_size.height());
958 if (m_structuralLayer) {
959 m_structuralLayer->setBounds(rect);
961 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
962 LayerMap::const_iterator end = layerCloneMap->end();
963 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
964 it->second->setBounds(rect);
967 // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
968 CGPoint centerPoint = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f);
969 m_layer->setPosition(centerPoint);
971 if (LayerMap* layerCloneMap = m_layerClones.get()) {
972 LayerMap::const_iterator end = layerCloneMap->end();
973 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
974 it->second->setPosition(centerPoint);
978 bool needTiledLayer = requiresTiledLayer(m_size);
979 if (needTiledLayer != m_usingTiledLayer)
980 swapFromOrToTiledLayer(needTiledLayer);
982 if (m_usingTiledLayer) {
983 FloatSize sizeToUse = constrainedSize();
984 rect = CGRectMake(0, 0, sizeToUse.width(), sizeToUse.height());
987 m_layer->setBounds(rect);
988 if (LayerMap* layerCloneMap = m_layerClones.get()) {
989 LayerMap::const_iterator end = layerCloneMap->end();
990 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
991 it->second->setBounds(rect);
994 // Contents transform may depend on height.
995 updateContentsTransform();
997 // Note that we don't resize m_contentsLayer. It's up the caller to do that.
999 // if we've changed the bounds, we need to recalculate the position
1000 // of the layer, taking anchor point into account.
1001 updateLayerPosition();
1004 void GraphicsLayerCA::updateAnchorPoint()
1006 primaryLayer()->setAnchorPoint(m_anchorPoint);
1008 if (LayerMap* layerCloneMap = primaryLayerClones()) {
1009 LayerMap::const_iterator end = layerCloneMap->end();
1010 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1011 PlatformCALayer* currLayer = it->second.get();
1012 currLayer->setAnchorPoint(m_anchorPoint);
1016 updateLayerPosition();
1019 void GraphicsLayerCA::updateTransform()
1021 primaryLayer()->setTransform(m_transform);
1023 if (LayerMap* layerCloneMap = primaryLayerClones()) {
1024 LayerMap::const_iterator end = layerCloneMap->end();
1025 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1026 PlatformCALayer* currLayer = it->second.get();
1027 if (m_replicaLayer && isReplicatedRootClone(it->first)) {
1028 // Maintain the special-case transform for the root of a clone subtree,
1029 // which we set up in replicatedLayerRoot().
1030 currLayer->setTransform(TransformationMatrix());
1032 currLayer->setTransform(m_transform);
1037 void GraphicsLayerCA::updateChildrenTransform()
1039 primaryLayer()->setSublayerTransform(m_childrenTransform);
1041 if (LayerMap* layerCloneMap = primaryLayerClones()) {
1042 LayerMap::const_iterator end = layerCloneMap->end();
1043 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1044 it->second->setSublayerTransform(m_childrenTransform);
1048 void GraphicsLayerCA::updateMasksToBounds()
1050 m_layer->setMasksToBounds(m_masksToBounds);
1052 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1053 LayerMap::const_iterator end = layerCloneMap->end();
1054 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1055 it->second->setMasksToBounds(m_masksToBounds);
1058 updateDebugIndicators();
1061 void GraphicsLayerCA::updateContentsOpaque()
1063 m_layer.get()->setOpaque(m_contentsOpaque);
1065 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1066 LayerMap::const_iterator end = layerCloneMap->end();
1067 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1068 it->second->setOpaque(m_contentsOpaque);
1072 void GraphicsLayerCA::updateBackfaceVisibility()
1074 if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) {
1075 m_structuralLayer->setDoubleSided(m_backfaceVisibility);
1077 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
1078 LayerMap::const_iterator end = layerCloneMap->end();
1079 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1080 it->second->setDoubleSided(m_backfaceVisibility);
1084 m_layer->setDoubleSided(m_backfaceVisibility);
1086 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1087 LayerMap::const_iterator end = layerCloneMap->end();
1088 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1089 it->second->setDoubleSided(m_backfaceVisibility);
1093 void GraphicsLayerCA::updateStructuralLayer()
1095 ensureStructuralLayer(structuralLayerPurpose());
1098 void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose)
1100 if (purpose == NoStructuralLayer) {
1101 if (m_structuralLayer) {
1102 // Replace the transformLayer in the parent with this layer.
1103 m_layer->removeFromSuperlayer();
1104 m_structuralLayer->superlayer()->replaceSublayer(m_structuralLayer.get(), m_layer.get());
1106 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_structuralLayer.get(), m_layer.get());
1107 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_structuralLayer.get(), m_layer.get());
1109 // Release the structural layer.
1110 m_structuralLayer = 0;
1112 // Update the properties of m_layer now that we no longer have a structural layer.
1113 updateLayerPosition();
1115 updateAnchorPoint();
1117 updateChildrenTransform();
1119 updateSublayerList();
1120 updateOpacityOnLayer();
1125 bool structuralLayerChanged = false;
1127 if (purpose == StructuralLayerForPreserves3D) {
1128 if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeTransformLayer)
1129 m_structuralLayer = 0;
1131 if (!m_structuralLayer) {
1132 m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeTransformLayer, this);
1133 structuralLayerChanged = true;
1136 if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeLayer)
1137 m_structuralLayer = 0;
1139 if (!m_structuralLayer) {
1140 m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this);
1141 structuralLayerChanged = true;
1145 if (!structuralLayerChanged)
1150 // Update the properties of the structural layer.
1151 updateLayerPosition();
1153 updateAnchorPoint();
1155 updateChildrenTransform();
1156 updateBackfaceVisibility();
1158 // Set properties of m_layer to their default values, since these are expressed on on the structural layer.
1159 FloatPoint point(m_size.width() / 2.0f, m_size.height() / 2.0f);
1160 FloatPoint3D anchorPoint(0.5f, 0.5f, 0);
1161 m_layer->setPosition(point);
1162 m_layer->setAnchorPoint(anchorPoint);
1163 m_layer->setTransform(TransformationMatrix());
1164 m_layer->setOpacity(1);
1165 if (m_layerClones) {
1166 LayerMap::const_iterator end = m_layerClones->end();
1167 for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) {
1168 PlatformCALayer* currLayer = it->second.get();
1169 currLayer->setPosition(point);
1170 currLayer->setAnchorPoint(anchorPoint);
1171 currLayer->setTransform(TransformationMatrix());
1172 currLayer->setOpacity(1);
1176 // Move this layer to be a child of the transform layer.
1177 m_layer->superlayer()->replaceSublayer(m_layer.get(), m_structuralLayer.get());
1178 m_structuralLayer->appendSublayer(m_layer.get());
1180 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_layer.get(), m_structuralLayer.get());
1181 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_layer.get(), m_structuralLayer.get());
1183 updateSublayerList();
1184 updateOpacityOnLayer();
1187 GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const
1190 return StructuralLayerForPreserves3D;
1193 return StructuralLayerForReplicaFlattening;
1195 return NoStructuralLayer;
1198 void GraphicsLayerCA::updateLayerDrawsContent()
1200 bool needTiledLayer = requiresTiledLayer(m_size);
1201 if (needTiledLayer != m_usingTiledLayer)
1202 swapFromOrToTiledLayer(needTiledLayer);
1205 m_layer->setNeedsDisplay();
1207 m_layer->setContents(0);
1209 updateDebugIndicators();
1212 void GraphicsLayerCA::updateAcceleratesDrawing()
1214 m_layer->setAcceleratesDrawing(m_acceleratesDrawing);
1217 void GraphicsLayerCA::updateLayerBackgroundColor()
1219 if (!m_contentsLayer)
1222 // We never create the contents layer just for background color yet.
1223 if (m_backgroundColorSet)
1224 m_contentsLayer->setBackgroundColor(m_backgroundColor);
1226 m_contentsLayer->setBackgroundColor(Color::transparent);
1229 void GraphicsLayerCA::updateContentsImage()
1231 if (m_pendingContentsImage) {
1232 if (!m_contentsLayer.get()) {
1233 m_contentsLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this);
1235 m_contentsLayer->setName("Image Layer");
1237 setupContentsLayer(m_contentsLayer.get());
1238 // m_contentsLayer will be parented by updateSublayerList
1241 // FIXME: maybe only do trilinear if the image is being scaled down,
1242 // but then what if the layer size changes?
1243 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
1244 m_contentsLayer->setMinificationFilter(PlatformCALayer::Trilinear);
1246 m_contentsLayer->setContents(m_pendingContentsImage.get());
1247 m_pendingContentsImage = 0;
1249 if (m_contentsLayerClones) {
1250 LayerMap::const_iterator end = m_contentsLayerClones->end();
1251 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it)
1252 it->second->setContents(m_contentsLayer->contents());
1255 updateContentsRect();
1258 // m_contentsLayer will be removed via updateSublayerList.
1259 m_contentsLayer = 0;
1263 void GraphicsLayerCA::updateContentsMediaLayer()
1265 // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList().
1266 if (m_contentsLayer) {
1267 setupContentsLayer(m_contentsLayer.get());
1268 updateContentsRect();
1272 void GraphicsLayerCA::updateContentsCanvasLayer()
1274 // CanvasLayer was set as m_contentsLayer, and will get parented in updateSublayerList().
1275 if (m_contentsLayer) {
1276 setupContentsLayer(m_contentsLayer.get());
1277 m_contentsLayer->setNeedsDisplay();
1278 updateContentsRect();
1282 void GraphicsLayerCA::updateContentsRect()
1284 if (!m_contentsLayer)
1287 FloatPoint point(m_contentsRect.x(), m_contentsRect.y());
1288 FloatRect rect(0, 0, m_contentsRect.width(), m_contentsRect.height());
1290 m_contentsLayer->setPosition(point);
1291 m_contentsLayer->setBounds(rect);
1293 if (m_contentsLayerClones) {
1294 LayerMap::const_iterator end = m_contentsLayerClones->end();
1295 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) {
1296 it->second->setPosition(point);
1297 it->second->setBounds(rect);
1302 void GraphicsLayerCA::updateMaskLayer()
1304 PlatformCALayer* maskCALayer = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayer() : 0;
1305 m_layer->setMask(maskCALayer);
1307 LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayerClones() : 0;
1309 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1310 LayerMap::const_iterator end = layerCloneMap->end();
1311 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1312 PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->first).get() : 0;
1313 it->second->setMask(maskClone);
1318 void GraphicsLayerCA::updateReplicatedLayers()
1320 // Clone the descendants of the replicated layer, and parent under us.
1321 ReplicaState replicaState(ReplicaState::ReplicaBranch);
1323 RefPtr<PlatformCALayer>replicaRoot = replicatedLayerRoot(replicaState);
1327 if (m_structuralLayer)
1328 m_structuralLayer->insertSublayer(replicaRoot.get(), 0);
1330 m_layer->insertSublayer(replicaRoot.get(), 0);
1333 // For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1.
1334 GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const
1336 size_t depth = m_replicaBranches.size();
1338 const size_t bitsPerUChar = sizeof(UChar) * 8;
1339 size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar;
1341 Vector<UChar> result(vectorSize);
1344 // Create a string from the bit sequence which we can use to identify the clone.
1345 // Note that the string may contain embedded nulls, but that's OK.
1346 for (size_t i = 0; i < depth; ++i) {
1347 UChar& currChar = result[i / bitsPerUChar];
1348 currChar = (currChar << 1) | m_replicaBranches[i];
1351 return String::adopt(result);
1354 PassRefPtr<PlatformCALayer> GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState)
1356 // Limit replica nesting, to avoid 2^N explosion of replica layers.
1357 if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth)
1360 GraphicsLayerCA* replicatedLayer = static_cast<GraphicsLayerCA*>(m_replicatedLayer);
1362 RefPtr<PlatformCALayer> clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel);
1363 FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer();
1365 // Replica root has no offset or transform
1366 clonedLayerRoot->setPosition(cloneRootPosition);
1367 clonedLayerRoot->setTransform(TransformationMatrix());
1369 return clonedLayerRoot;
1372 void GraphicsLayerCA::updateLayerAnimations()
1374 if (m_animationsToProcess.size()) {
1375 AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end();
1376 for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) {
1377 const String& currAnimationName = it->first;
1378 AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName);
1379 if (animationIt == m_runningAnimations.end())
1382 const AnimationProcessingAction& processingInfo = it->second;
1383 const Vector<LayerPropertyAnimation>& animations = animationIt->second;
1384 for (size_t i = 0; i < animations.size(); ++i) {
1385 const LayerPropertyAnimation& currAnimation = animations[i];
1386 switch (processingInfo.action) {
1388 removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index);
1391 pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, processingInfo.timeOffset);
1396 if (processingInfo.action == Remove)
1397 m_runningAnimations.remove(currAnimationName);
1400 m_animationsToProcess.clear();
1403 size_t numAnimations;
1404 if ((numAnimations = m_uncomittedAnimations.size())) {
1405 for (size_t i = 0; i < numAnimations; ++i) {
1406 const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i];
1407 setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_timeOffset);
1409 AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name);
1410 if (it == m_runningAnimations.end()) {
1411 Vector<LayerPropertyAnimation> animations;
1412 animations.append(pendingAnimation);
1413 m_runningAnimations.add(pendingAnimation.m_name, animations);
1415 Vector<LayerPropertyAnimation>& animations = it->second;
1416 animations.append(pendingAnimation);
1420 m_uncomittedAnimations.clear();
1424 void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, double timeOffset)
1426 PlatformCALayer* layer = animatedLayer(property);
1429 caAnim->setBeginTime(CACurrentMediaTime() - timeOffset);
1431 String animationID = animationIdentifier(animationName, property, index);
1433 layer->removeAnimationForKey(animationID);
1434 layer->addAnimationForKey(animationID, caAnim);
1436 if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
1437 LayerMap::const_iterator end = layerCloneMap->end();
1438 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1439 // Skip immediate replicas, since they move with the original.
1440 if (m_replicaLayer && isReplicatedRootClone(it->first))
1443 it->second->removeAnimationForKey(animationID);
1444 it->second->addAnimationForKey(animationID, caAnim);
1449 // Workaround for <rdar://problem/7311367>
1450 static void bug7311367Workaround(PlatformCALayer* transformLayer, const TransformationMatrix& transform)
1452 if (!transformLayer)
1455 TransformationMatrix caTransform = transform;
1456 caTransform.setM41(caTransform.m41() + 1);
1457 transformLayer->setTransform(caTransform);
1459 caTransform.setM41(caTransform.m41() - 1);
1460 transformLayer->setTransform(caTransform);
1463 bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index)
1465 PlatformCALayer* layer = animatedLayer(property);
1467 String animationID = animationIdentifier(animationName, property, index);
1469 if (!layer->animationForKey(animationID))
1472 layer->removeAnimationForKey(animationID);
1473 bug7311367Workaround(m_structuralLayer.get(), m_transform);
1475 if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
1476 LayerMap::const_iterator end = layerCloneMap->end();
1477 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1478 // Skip immediate replicas, since they move with the original.
1479 if (m_replicaLayer && isReplicatedRootClone(it->first))
1482 it->second ->removeAnimationForKey(animationID);
1488 void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, double timeOffset)
1490 PlatformCALayer* layer = animatedLayer(property);
1492 String animationID = animationIdentifier(animationName, property, index);
1494 RefPtr<PlatformCAAnimation> curAnim = layer->animationForKey(animationID);
1498 // Animations on the layer are immutable, so we have to clone and modify.
1499 RefPtr<PlatformCAAnimation> newAnim = PlatformCAAnimation::create(curAnim.get());
1501 newAnim->setSpeed(0);
1502 newAnim->setTimeOffset(timeOffset);
1504 layer->addAnimationForKey(animationID, newAnim.get()); // This will replace the running animation.
1506 // Pause the animations on the clones too.
1507 if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
1508 LayerMap::const_iterator end = layerCloneMap->end();
1509 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1510 // Skip immediate replicas, since they move with the original.
1511 if (m_replicaLayer && isReplicatedRootClone(it->first))
1513 it->second->addAnimationForKey(animationID, newAnim.get());
1518 void GraphicsLayerCA::repaintLayerDirtyRects()
1520 if (!m_dirtyRects.size())
1523 for (size_t i = 0; i < m_dirtyRects.size(); ++i)
1524 m_layer->setNeedsDisplay(&(m_dirtyRects[i]));
1526 m_dirtyRects.clear();
1529 void GraphicsLayerCA::updateContentsNeedsDisplay()
1531 if (m_contentsLayer)
1532 m_contentsLayer->setNeedsDisplay();
1535 bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset)
1537 ASSERT(valueList.property() != AnimatedPropertyWebkitTransform);
1539 bool isKeyframe = valueList.size() > 2;
1542 bool additive = false;
1543 int animationIndex = 0;
1545 RefPtr<PlatformCAAnimation> caAnimation;
1548 caAnimation = createKeyframeAnimation(animation, valueList.property(), additive);
1549 valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get());
1551 caAnimation = createBasicAnimation(animation, valueList.property(), additive);
1552 valuesOK = setAnimationEndpoints(valueList, animation, caAnimation.get());
1558 m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset));
1563 bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize)
1565 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
1567 TransformOperationList functionList;
1568 bool listsMatch, hasBigRotation;
1569 fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation);
1571 // We need to fall back to software animation if we don't have setValueFunction:, and
1572 // we would need to animate each incoming transform function separately. This is the
1573 // case if we have a rotation >= 180 or we have more than one transform function.
1574 if ((hasBigRotation || functionList.size() > 1) && !PlatformCAAnimation::supportsValueFunction())
1577 bool validMatrices = true;
1579 // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation.
1580 // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation
1581 // if that's not true as well.
1582 bool isMatrixAnimation = !listsMatch || !PlatformCAAnimation::supportsValueFunction();
1584 size_t numAnimations = isMatrixAnimation ? 1 : functionList.size();
1585 bool isKeyframe = valueList.size() > 2;
1587 // Iterate through the transform functions, sending an animation for each one.
1588 for (size_t animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
1589 TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : functionList[animationIndex];
1590 RefPtr<PlatformCAAnimation> caAnimation;
1592 #if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD)
1593 // CA applies animations in reverse order (<rdar://problem/7095638>) so we need the last one we add (per property)
1594 // to be non-additive.
1595 bool additive = animationIndex < (numAnimations - 1);
1597 bool additive = animationIndex > 0;
1600 caAnimation = createKeyframeAnimation(animation, valueList.property(), additive);
1601 validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
1603 caAnimation = createBasicAnimation(animation, valueList.property(), additive);
1604 validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
1610 m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset));
1613 return validMatrices;
1616 PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, AnimatedPropertyID property, bool additive)
1618 RefPtr<PlatformCAAnimation> basicAnim = PlatformCAAnimation::create(PlatformCAAnimation::Basic, propertyIdToString(property));
1619 setupAnimation(basicAnim.get(), anim, additive);
1623 PassRefPtr<PlatformCAAnimation>GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, AnimatedPropertyID property, bool additive)
1625 RefPtr<PlatformCAAnimation> keyframeAnim = PlatformCAAnimation::create(PlatformCAAnimation::Keyframe, propertyIdToString(property));
1626 setupAnimation(keyframeAnim.get(), anim, additive);
1627 return keyframeAnim;
1630 void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive)
1632 double duration = anim->duration();
1634 duration = cAnimationAlmostZeroDuration;
1636 float repeatCount = anim->iterationCount();
1637 if (repeatCount == Animation::IterationCountInfinite)
1638 repeatCount = FLT_MAX;
1639 else if (anim->direction() == Animation::AnimationDirectionAlternate)
1642 PlatformCAAnimation::FillModeType fillMode = PlatformCAAnimation::NoFillMode;
1643 switch (anim->fillMode()) {
1644 case AnimationFillModeNone:
1645 fillMode = PlatformCAAnimation::Forwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash.
1647 case AnimationFillModeBackwards:
1648 fillMode = PlatformCAAnimation::Both; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash.
1650 case AnimationFillModeForwards:
1651 fillMode = PlatformCAAnimation::Forwards;
1653 case AnimationFillModeBoth:
1654 fillMode = PlatformCAAnimation::Both;
1658 propertyAnim->setDuration(duration);
1659 propertyAnim->setRepeatCount(repeatCount);
1660 propertyAnim->setAutoreverses(anim->direction());
1661 propertyAnim->setRemovedOnCompletion(false);
1662 propertyAnim->setAdditive(additive);
1663 propertyAnim->setFillMode(fillMode);
1666 const TimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue* animValue, const Animation* anim)
1668 if (animValue->timingFunction())
1669 return animValue->timingFunction();
1670 if (anim->isTimingFunctionSet())
1671 return anim->timingFunction().get();
1676 bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim)
1678 switch (valueList.property()) {
1679 case AnimatedPropertyOpacity: {
1680 basicAnim->setFromValue(static_cast<const FloatAnimationValue*>(valueList.at(0))->value());
1681 basicAnim->setToValue(static_cast<const FloatAnimationValue*>(valueList.at(1))->value());
1685 ASSERT_NOT_REACHED(); // we don't animate color yet
1689 // This codepath is used for 2-keyframe animations, so we still need to look in the start
1690 // for a timing function.
1691 const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim);
1693 basicAnim->setTimingFunction(timingFunction);
1698 bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* keyframeAnim)
1700 Vector<float> keyTimes;
1701 Vector<float> values;
1702 Vector<const TimingFunction*> timingFunctions;
1704 for (unsigned i = 0; i < valueList.size(); ++i) {
1705 const AnimationValue* curValue = valueList.at(i);
1706 keyTimes.append(curValue->keyTime());
1708 switch (valueList.property()) {
1709 case AnimatedPropertyOpacity: {
1710 const FloatAnimationValue* floatValue = static_cast<const FloatAnimationValue*>(curValue);
1711 values.append(floatValue->value());
1715 ASSERT_NOT_REACHED(); // we don't animate color yet
1719 timingFunctions.append(timingFunctionForAnimationValue(curValue, anim));
1722 // We toss the last tfArray value because it has to one shorter than the others.
1723 timingFunctions.removeLast();
1725 keyframeAnim->setKeyTimes(keyTimes);
1726 keyframeAnim->setValues(values);
1727 keyframeAnim->setTimingFunctions(timingFunctions);
1732 bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
1734 ASSERT(valueList.size() == 2);
1735 const TransformAnimationValue* startValue = static_cast<const TransformAnimationValue*>(valueList.at(0));
1736 const TransformAnimationValue* endValue = static_cast<const TransformAnimationValue*>(valueList.at(1));
1738 if (isMatrixAnimation) {
1739 TransformationMatrix fromTransform, toTransform;
1740 startValue->value()->apply(boxSize, fromTransform);
1741 endValue->value()->apply(boxSize, toTransform);
1743 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
1744 if (!fromTransform.isInvertible() || !toTransform.isInvertible())
1747 basicAnim->setFromValue(fromTransform);
1748 basicAnim->setToValue(toTransform);
1750 if (isTransformTypeNumber(transformOpType)) {
1752 getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, value);
1753 basicAnim->setFromValue(value);
1754 getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, value);
1755 basicAnim->setToValue(value);
1756 } else if (isTransformTypeFloatPoint3D(transformOpType)) {
1758 getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, value);
1759 basicAnim->setFromValue(value);
1760 getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, value);
1761 basicAnim->setToValue(value);
1763 TransformationMatrix value;
1764 getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, value);
1765 basicAnim->setFromValue(value);
1766 getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, value);
1767 basicAnim->setToValue(value);
1771 // This codepath is used for 2-keyframe animations, so we still need to look in the start
1772 // for a timing function.
1773 const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim);
1774 basicAnim->setTimingFunction(timingFunction);
1776 #if HAVE_MODERN_QUARTZCORE
1777 PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
1778 if (valueFunction != PlatformCAAnimation::NoValueFunction)
1779 basicAnim->setValueFunction(valueFunction);
1785 bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
1787 Vector<float> keyTimes;
1788 Vector<float> floatValues;
1789 Vector<FloatPoint3D> floatPoint3DValues;
1790 Vector<TransformationMatrix> transformationMatrixValues;
1791 Vector<const TimingFunction*> timingFunctions;
1793 for (unsigned i = 0; i < valueList.size(); ++i) {
1794 const TransformAnimationValue* curValue = static_cast<const TransformAnimationValue*>(valueList.at(i));
1795 keyTimes.append(curValue->keyTime());
1797 if (isMatrixAnimation) {
1798 TransformationMatrix transform;
1799 curValue->value()->apply(boxSize, transform);
1801 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
1802 if (!transform.isInvertible())
1805 transformationMatrixValues.append(transform);
1807 const TransformOperation* transformOp = curValue->value()->at(functionIndex);
1808 if (isTransformTypeNumber(transformOpType)) {
1810 getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
1811 floatValues.append(value);
1812 } else if (isTransformTypeFloatPoint3D(transformOpType)) {
1814 getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
1815 floatPoint3DValues.append(value);
1817 TransformationMatrix value;
1818 getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
1819 transformationMatrixValues.append(value);
1823 const TimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, animation);
1824 timingFunctions.append(timingFunction);
1827 // We toss the last tfArray value because it has to one shorter than the others.
1828 timingFunctions.removeLast();
1830 keyframeAnim->setKeyTimes(keyTimes);
1832 if (isTransformTypeNumber(transformOpType))
1833 keyframeAnim->setValues(floatValues);
1834 else if (isTransformTypeFloatPoint3D(transformOpType))
1835 keyframeAnim->setValues(floatPoint3DValues);
1837 keyframeAnim->setValues(transformationMatrixValues);
1839 keyframeAnim->setTimingFunctions(timingFunctions);
1841 #if HAVE_MODERN_QUARTZCORE
1842 PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
1843 if (valueFunction != PlatformCAAnimation::NoValueFunction)
1844 keyframeAnim->setValueFunction(valueFunction);
1849 void GraphicsLayerCA::suspendAnimations(double time)
1851 double t = currentTimeToMediaTime(time ? time : currentTime());
1852 primaryLayer()->setSpeed(0);
1853 primaryLayer()->setTimeOffset(t);
1855 // Suspend the animations on the clones too.
1856 if (LayerMap* layerCloneMap = primaryLayerClones()) {
1857 LayerMap::const_iterator end = layerCloneMap->end();
1858 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1859 it->second->setSpeed(0);
1860 it->second->setTimeOffset(t);
1865 void GraphicsLayerCA::resumeAnimations()
1867 primaryLayer()->setSpeed(1);
1868 primaryLayer()->setTimeOffset(0);
1870 // Resume the animations on the clones too.
1871 if (LayerMap* layerCloneMap = primaryLayerClones()) {
1872 LayerMap::const_iterator end = layerCloneMap->end();
1873 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1874 it->second->setSpeed(1);
1875 it->second->setTimeOffset(0);
1880 PlatformCALayer* GraphicsLayerCA::hostLayerForSublayers() const
1882 return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get();
1885 PlatformCALayer* GraphicsLayerCA::layerForSuperlayer() const
1887 return m_structuralLayer ? m_structuralLayer.get() : m_layer.get();
1890 PlatformCALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const
1892 return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer();
1895 GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const
1897 return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones();
1900 void GraphicsLayerCA::setContentsScale(float scale)
1902 float newScale = clampedContentsScaleForScale(scale);
1903 if (newScale == m_contentsScale)
1906 m_contentsScale = newScale;
1907 noteLayerPropertyChanged(ContentsScaleChanged);
1910 float GraphicsLayerCA::clampedContentsScaleForScale(float scale) const
1912 // Define some limits as a sanity check for the incoming scale value
1913 // those too small to see.
1914 const float maxScale = 5.0f;
1915 const float minScale = 0.01f;
1917 // Avoid very slight scale changes that would be doing extra work for no benefit
1918 const float maxAllowableDelta = 0.05;
1921 float result = max(minScale, min(scale, maxScale));
1923 // If it hasn't changed much, don't do any work
1924 return ((fabs(result - m_contentsScale) / m_contentsScale) < maxAllowableDelta) ? m_contentsScale : result;
1927 void GraphicsLayerCA::updateContentsScale()
1929 bool needTiledLayer = requiresTiledLayer(m_size);
1930 if (needTiledLayer != m_usingTiledLayer)
1931 swapFromOrToTiledLayer(needTiledLayer);
1933 m_layer->setContentsScale(m_contentsScale);
1934 m_layer->setNeedsDisplay();
1937 void GraphicsLayerCA::setDebugBackgroundColor(const Color& color)
1939 if (color.isValid())
1940 m_layer->setBackgroundColor(color);
1942 m_layer->setBackgroundColor(Color::transparent);
1945 void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth)
1947 if (color.isValid()) {
1948 m_layer->setBorderColor(color);
1949 m_layer->setBorderWidth(borderWidth);
1951 m_layer->setBorderColor(Color::transparent);
1952 m_layer->setBorderWidth(0);
1956 FloatSize GraphicsLayerCA::constrainedSize() const
1958 float tileColumns = ceilf(m_size.width() / kTiledLayerTileSize);
1959 float tileRows = ceilf(m_size.height() / kTiledLayerTileSize);
1960 double numTiles = tileColumns * tileRows;
1962 FloatSize constrainedSize = m_size;
1963 const unsigned cMaxTileCount = 512;
1964 while (numTiles > cMaxTileCount) {
1965 // Constrain the wider dimension.
1966 if (constrainedSize.width() >= constrainedSize.height()) {
1967 tileColumns = max(floorf(cMaxTileCount / tileRows), 1.0f);
1968 constrainedSize.setWidth(tileColumns * kTiledLayerTileSize);
1970 tileRows = max(floorf(cMaxTileCount / tileColumns), 1.0f);
1971 constrainedSize.setHeight(tileRows * kTiledLayerTileSize);
1973 numTiles = tileColumns * tileRows;
1976 return constrainedSize;
1979 bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const
1981 if (!m_drawsContent)
1984 // FIXME: catch zero-size height or width here (or earlier)?
1985 return size.width() > cMaxPixelDimension || size.height() > cMaxPixelDimension;
1988 void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer)
1990 ASSERT(useTiledLayer != m_usingTiledLayer);
1991 RefPtr<PlatformCALayer> oldLayer = m_layer;
1993 m_layer = PlatformCALayer::create(useTiledLayer ? PlatformCALayer::LayerTypeWebTiledLayer : PlatformCALayer::LayerTypeWebLayer, this);
1995 m_usingTiledLayer = useTiledLayer;
1997 if (useTiledLayer) {
1998 #if !HAVE_MODERN_QUARTZCORE
1999 // Tiled layer has issues with flipped coordinates.
2000 setContentsOrientation(CompositingCoordinatesTopDown);
2003 #if !HAVE_MODERN_QUARTZCORE
2004 setContentsOrientation(GraphicsLayerCA::defaultContentsOrientation());
2008 m_layer->adoptSublayers(oldLayer.get());
2010 oldLayer->superlayer()->replaceSublayer(oldLayer.get(), m_layer.get());
2012 updateContentsTransform();
2014 updateLayerPosition();
2016 updateAnchorPoint();
2018 updateChildrenTransform();
2019 updateMasksToBounds();
2020 updateContentsOpaque();
2021 updateBackfaceVisibility();
2022 updateLayerBackgroundColor();
2024 updateOpacityOnLayer();
2027 String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + m_name;
2028 m_layer->setName(name);
2031 // move over animations
2032 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, oldLayer.get(), m_layer.get());
2033 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, oldLayer.get(), m_layer.get());
2034 moveOrCopyAnimationsForProperty(Move, AnimatedPropertyBackgroundColor, oldLayer.get(), m_layer.get());
2036 // need to tell new layer to draw itself
2039 updateDebugIndicators();
2042 GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const
2044 #if !HAVE_MODERN_QUARTZCORE
2045 // Older QuartzCore does not support -geometryFlipped, so we manually flip the root
2046 // layer geometry, and then flip the contents of each layer back so that the CTM for CG
2047 // is unflipped, allowing it to do the correct font auto-hinting.
2048 return CompositingCoordinatesBottomUp;
2050 return CompositingCoordinatesTopDown;
2054 void GraphicsLayerCA::updateContentsTransform()
2056 #if !HAVE_MODERN_QUARTZCORE
2057 if (contentsOrientation() == CompositingCoordinatesBottomUp) {
2058 CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1);
2059 contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -m_layer->bounds().size().height());
2060 m_layer->setContentsTransform(TransformationMatrix(contentsTransform));
2065 void GraphicsLayerCA::setupContentsLayer(PlatformCALayer* contentsLayer)
2067 // Turn off implicit animations on the inner layer.
2068 contentsLayer->setMasksToBounds(true);
2070 if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) {
2071 TransformationMatrix flipper(
2072 1.0f, 0.0f, 0.0f, 0.0f,
2073 0.0f, -1.0f, 0.0f, 0.0f,
2074 0.0f, 0.0f, 1.0f, 0.0f,
2075 0.0f, 0.0f, 0.0f, 1.0f);
2076 contentsLayer->setTransform(flipper);
2077 contentsLayer->setAnchorPoint(FloatPoint3D(0, 1, 0));
2079 contentsLayer->setAnchorPoint(FloatPoint3D());
2081 if (showDebugBorders()) {
2082 contentsLayer->setBorderColor(Color(0, 0, 128, 180));
2083 contentsLayer->setBorderWidth(1.0f);
2087 PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, PlatformCALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel)
2092 RefPtr<PlatformCALayer> resultLayer;
2094 // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells
2095 // us whether there's an item there. This technique avoids two hash lookups.
2096 RefPtr<PlatformCALayer> dummy;
2097 pair<LayerMap::iterator, bool> addResult = clones->add(cloneID, dummy);
2098 if (!addResult.second) {
2099 // Value was not added, so it exists already.
2100 resultLayer = addResult.first->second.get();
2102 resultLayer = cloneLayer(sourceLayer, cloneLevel);
2104 resultLayer->setName(String::format("Clone %d of layer %p", cloneID[0U], sourceLayer));
2106 addResult.first->second = resultLayer;
2112 void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer, RefPtr<PlatformCALayer>& contentsLayer, CloneLevel cloneLevel)
2114 structuralLayer = 0;
2118 m_layerClones = new LayerMap;
2120 if (!m_structuralLayerClones && m_structuralLayer)
2121 m_structuralLayerClones = new LayerMap;
2123 if (!m_contentsLayerClones && m_contentsLayer)
2124 m_contentsLayerClones = new LayerMap;
2126 primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel);
2127 structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel);
2128 contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel);
2131 void GraphicsLayerCA::removeCloneLayers()
2134 m_structuralLayerClones = 0;
2135 m_contentsLayerClones = 0;
2138 FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const
2140 // This can get called during a sync when we've just removed the m_replicaLayer.
2141 if (!m_replicaLayer)
2142 return FloatPoint();
2144 FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition();
2145 return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(),
2146 replicaPosition.y() + m_anchorPoint.y() * m_size.height());
2149 void GraphicsLayerCA::propagateLayerChangeToReplicas()
2151 for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) {
2152 GraphicsLayerCA* currLayerCA = static_cast<GraphicsLayerCA*>(currLayer);
2153 if (!currLayerCA->hasCloneLayers())
2156 if (currLayerCA->replicaLayer())
2157 static_cast<GraphicsLayerCA*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged);
2161 PassRefPtr<PlatformCALayer> GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel)
2163 RefPtr<PlatformCALayer> primaryLayer;
2164 RefPtr<PlatformCALayer> structuralLayer;
2165 RefPtr<PlatformCALayer> contentsLayer;
2166 ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, cloneLevel);
2169 RefPtr<PlatformCALayer> maskClone = static_cast<GraphicsLayerCA*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
2170 primaryLayer->setMask(maskClone.get());
2173 if (m_replicatedLayer) {
2174 // We are a replica being asked for clones of our layers.
2175 RefPtr<PlatformCALayer> replicaRoot = replicatedLayerRoot(replicaState);
2179 if (structuralLayer) {
2180 structuralLayer->insertSublayer(replicaRoot.get(), 0);
2181 return structuralLayer;
2184 primaryLayer->insertSublayer(replicaRoot.get(), 0);
2185 return primaryLayer;
2188 const Vector<GraphicsLayer*>& childLayers = children();
2189 Vector<RefPtr<PlatformCALayer> > clonalSublayers;
2191 RefPtr<PlatformCALayer> replicaLayer;
2193 if (m_replicaLayer && m_replicaLayer != replicaRoot) {
2194 // We have nested replicas. Ask the replica layer for a clone of its contents.
2195 replicaState.setBranchType(ReplicaState::ReplicaBranch);
2196 replicaLayer = static_cast<GraphicsLayerCA*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel);
2197 replicaState.setBranchType(ReplicaState::ChildBranch);
2200 if (replicaLayer || structuralLayer || contentsLayer || childLayers.size() > 0) {
2201 if (structuralLayer) {
2202 // Replicas render behind the actual layer content.
2204 clonalSublayers.append(replicaLayer);
2206 // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind.
2207 clonalSublayers.append(primaryLayer);
2208 } else if (contentsLayer) {
2209 // FIXME: add the contents layer in the correct order with negative z-order children.
2210 // This does not cause visible rendering issues because currently contents layers are only used
2211 // for replaced elements that don't have children.
2212 clonalSublayers.append(contentsLayer);
2215 replicaState.push(ReplicaState::ChildBranch);
2217 size_t numChildren = childLayers.size();
2218 for (size_t i = 0; i < numChildren; ++i) {
2219 GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
2221 RefPtr<PlatformCALayer> childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
2223 clonalSublayers.append(childLayer);
2228 for (size_t i = 0; i < clonalSublayers.size(); ++i)
2229 clonalSublayers[i]->removeFromSuperlayer();
2232 RefPtr<PlatformCALayer> result;
2233 if (structuralLayer) {
2234 structuralLayer->setSublayers(clonalSublayers);
2236 if (contentsLayer) {
2237 // If we have a transform layer, then the contents layer is parented in the
2238 // primary layer (which is itself a child of the transform layer).
2239 primaryLayer->removeAllSublayers();
2240 primaryLayer->appendSublayer(contentsLayer.get());
2243 result = structuralLayer;
2245 primaryLayer->setSublayers(clonalSublayers);
2246 result = primaryLayer;
2252 PassRefPtr<PlatformCALayer> GraphicsLayerCA::cloneLayer(PlatformCALayer *layer, CloneLevel cloneLevel)
2254 PlatformCALayer::LayerType layerType = (layer->layerType() == PlatformCALayer::LayerTypeTransformLayer) ?
2255 PlatformCALayer::LayerTypeTransformLayer : PlatformCALayer::LayerTypeLayer;
2256 RefPtr<PlatformCALayer> newLayer = PlatformCALayer::create(layerType, this);
2258 newLayer->setPosition(layer->position());
2259 newLayer->setBounds(layer->bounds());
2260 newLayer->setAnchorPoint(layer->anchorPoint());
2261 newLayer->setTransform(layer->transform());
2262 newLayer->setSublayerTransform(layer->sublayerTransform());
2263 newLayer->setContents(layer->contents());
2264 newLayer->setMasksToBounds(layer->masksToBounds());
2265 newLayer->setDoubleSided(layer->isDoubleSided());
2266 newLayer->setOpaque(layer->isOpaque());
2267 newLayer->setBackgroundColor(layer->backgroundColor());
2269 if (cloneLevel == IntermediateCloneLevel) {
2270 newLayer->setOpacity(layer->opacity());
2271 moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyWebkitTransform, layer, newLayer.get());
2272 moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyOpacity, layer, newLayer.get());
2275 if (showDebugBorders()) {
2276 newLayer->setBorderColor(Color(255, 122, 251));
2277 newLayer->setBorderWidth(2);
2283 void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity)
2285 LayerMap* layerCloneMap = 0;
2287 if (preserves3D()) {
2288 m_layer->setOpacity(accumulatedOpacity);
2289 layerCloneMap = m_layerClones.get();
2291 primaryLayer()->setOpacity(accumulatedOpacity);
2292 layerCloneMap = primaryLayerClones();
2295 if (layerCloneMap) {
2296 LayerMap::const_iterator end = layerCloneMap->end();
2297 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2298 if (m_replicaLayer && isReplicatedRootClone(it->first))
2300 it->second->setOpacity(m_opacity);
2305 void GraphicsLayerCA::updateOpacityOnLayer()
2307 #if !HAVE_MODERN_QUARTZCORE
2308 // Distribute opacity either to our own layer or to our children. We pass in the
2309 // contribution from our parent(s).
2310 distributeOpacity(parent() ? parent()->accumulatedOpacity() : 1);
2312 primaryLayer()->setOpacity(m_opacity);
2314 if (LayerMap* layerCloneMap = primaryLayerClones()) {
2315 LayerMap::const_iterator end = layerCloneMap->end();
2316 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2317 if (m_replicaLayer && isReplicatedRootClone(it->first))
2320 it->second->setOpacity(m_opacity);
2327 void GraphicsLayerCA::noteSublayersChanged()
2329 noteLayerPropertyChanged(ChildrenChanged);
2330 propagateLayerChangeToReplicas();
2333 void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags)
2335 if (!m_uncommittedChanges && m_client)
2336 m_client->notifySyncRequired(this);
2338 m_uncommittedChanges |= flags;
2341 } // namespace WebCore
2343 #endif // USE(ACCELERATED_COMPOSITING)