1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26#include "config.h"
27
28#if USE(ACCELERATED_COMPOSITING)
29
30#include "GraphicsLayerCA.h"
31
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"
41#include <QuartzCore/CATransform3D.h>
42#include <limits.h>
43#include <wtf/CurrentTime.h>
44#include <wtf/text/StringConcatenate.h>
45
46using namespace std;
47
48#define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
49
50namespace WebCore {
51
52// The threshold width or height above which a tiled layer will be used. This should be
53// large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL
54// texture size limit on all supported hardware.
55static const int cMaxPixelDimension = 2000;
56
57// If we send a duration of 0 to CA, then it will use the default duration
58// of 250ms. So send a very small value instead.
59static const float cAnimationAlmostZeroDuration = 1e-3f;
60
61// CACurrentMediaTime() is a time since boot. These methods convert between that and
62// WebCore time, which is system time (UTC).
63static CFTimeInterval currentTimeToMediaTime(double t)
64{
65    return CACurrentMediaTime() + t - WTF::currentTime();
66}
67
68static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType)
69{
70    switch (transformType) {
71    case TransformOperation::SKEW_X:
72    case TransformOperation::SKEW_Y:
73    case TransformOperation::SKEW:
74    case TransformOperation::MATRIX:
75    case TransformOperation::ROTATE_3D:
76    case TransformOperation::MATRIX_3D:
77    case TransformOperation::PERSPECTIVE:
78    case TransformOperation::IDENTITY:
79    case TransformOperation::NONE:
80        return true;
81    default:
82        return false;
83    }
84}
85
86static bool isTransformTypeFloatPoint3D(TransformOperation::OperationType transformType)
87{
88    switch (transformType) {
89    case TransformOperation::SCALE:
90    case TransformOperation::SCALE_3D:
91    case TransformOperation::TRANSLATE:
92    case TransformOperation::TRANSLATE_3D:
93        return true;
94    default:
95        return false;
96    }
97}
98
99static bool isTransformTypeNumber(TransformOperation::OperationType transformType)
100{
101    return !isTransformTypeTransformationMatrix(transformType) && !isTransformTypeFloatPoint3D(transformType);
102}
103
104static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, float& value)
105{
106    switch (transformType) {
107    case TransformOperation::ROTATE:
108    case TransformOperation::ROTATE_X:
109    case TransformOperation::ROTATE_Y:
110        value = transformOp ? narrowPrecisionToFloat(deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle())) : 0;
111        break;
112    case TransformOperation::SCALE_X:
113        value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1;
114        break;
115    case TransformOperation::SCALE_Y:
116        value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1;
117        break;
118    case TransformOperation::SCALE_Z:
119        value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1;
120        break;
121    case TransformOperation::TRANSLATE_X:
122        value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0;
123        break;
124    case TransformOperation::TRANSLATE_Y:
125        value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0;
126        break;
127    case TransformOperation::TRANSLATE_Z:
128        value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0;
129        break;
130    default:
131        break;
132    }
133}
134
135static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, FloatPoint3D& value)
136{
137    switch (transformType) {
138    case TransformOperation::SCALE:
139    case TransformOperation::SCALE_3D:
140        value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1);
141        value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1);
142        value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1);
143        break;
144    case TransformOperation::TRANSLATE:
145    case TransformOperation::TRANSLATE_3D:
146        value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0);
147        value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0);
148        value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0);
149        break;
150    default:
151        break;
152    }
153}
154
155static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, TransformationMatrix& value)
156{
157    switch (transformType) {
158    case TransformOperation::SKEW_X:
159    case TransformOperation::SKEW_Y:
160    case TransformOperation::SKEW:
161    case TransformOperation::MATRIX:
162    case TransformOperation::ROTATE_3D:
163    case TransformOperation::MATRIX_3D:
164    case TransformOperation::PERSPECTIVE:
165    case TransformOperation::IDENTITY:
166    case TransformOperation::NONE:
167        if (transformOp)
168            transformOp->apply(value, size);
169        else
170            value.makeIdentity();
171        break;
172    default:
173        break;
174    }
175}
176
177#if HAVE_MODERN_QUARTZCORE
178static PlatformCAAnimation::ValueFunctionType getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType)
179{
180    // Use literal strings to avoid link-time dependency on those symbols.
181    switch (transformType) {
182    case TransformOperation::ROTATE_X:
183        return PlatformCAAnimation::RotateX;
184    case TransformOperation::ROTATE_Y:
185        return PlatformCAAnimation::RotateY;
186    case TransformOperation::ROTATE:
187        return PlatformCAAnimation::RotateZ;
188    case TransformOperation::SCALE_X:
189        return PlatformCAAnimation::ScaleX;
190    case TransformOperation::SCALE_Y:
191        return PlatformCAAnimation::ScaleY;
192    case TransformOperation::SCALE_Z:
193        return PlatformCAAnimation::ScaleZ;
194    case TransformOperation::TRANSLATE_X:
195        return PlatformCAAnimation::TranslateX;
196    case TransformOperation::TRANSLATE_Y:
197        return PlatformCAAnimation::TranslateY;
198    case TransformOperation::TRANSLATE_Z:
199        return PlatformCAAnimation::TranslateZ;
200    case TransformOperation::SCALE:
201    case TransformOperation::SCALE_3D:
202        return PlatformCAAnimation::Scale;
203    case TransformOperation::TRANSLATE:
204    case TransformOperation::TRANSLATE_3D:
205        return PlatformCAAnimation::Translate;
206    default:
207        return PlatformCAAnimation::NoValueFunction;
208    }
209}
210#endif
211
212static String propertyIdToString(AnimatedPropertyID property)
213{
214    switch (property) {
215    case AnimatedPropertyWebkitTransform:
216        return "transform";
217    case AnimatedPropertyOpacity:
218        return "opacity";
219    case AnimatedPropertyBackgroundColor:
220        return "backgroundColor";
221    case AnimatedPropertyInvalid:
222        ASSERT_NOT_REACHED();
223    }
224    ASSERT_NOT_REACHED();
225    return "";
226}
227
228static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index)
229{
230    return makeString(animationName, '_', String::number(property), '_', String::number(index));
231}
232
233static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim)
234{
235    if (anim->timingFunction()->isStepsTimingFunction())
236        return true;
237
238    for (unsigned i = 0; i < valueList.size(); ++i) {
239        const TimingFunction* timingFunction = valueList.at(i)->timingFunction();
240        if (timingFunction && timingFunction->isStepsTimingFunction())
241            return true;
242    }
243
244    return false;
245}
246
247PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
248{
249    return new GraphicsLayerCA(client);
250}
251
252GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client)
253    : GraphicsLayer(client)
254    , m_contentsLayerPurpose(NoContentsLayer)
255    , m_contentsLayerHasBackgroundColor(false)
256    , m_uncommittedChanges(NoChange)
257    , m_contentsScale(1)
258    , m_allowTiledLayer(true)
259{
260    m_layer = PlatformCALayer::create(PlatformCALayer::LayerTypeWebLayer, this);
261
262#if !HAVE_MODERN_QUARTZCORE
263    setContentsOrientation(defaultContentsOrientation());
264#endif
265
266    updateDebugIndicators();
267}
268
269GraphicsLayerCA::~GraphicsLayerCA()
270{
271    // We release our references to the PlatformCALayers here, but do not actively unparent them,
272    // since that will cause a commit and break our batched commit model. The layers will
273    // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers.
274
275    // Clean up the layer.
276    if (m_layer)
277        m_layer->setOwner(0);
278
279    if (m_contentsLayer)
280        m_contentsLayer->setOwner(0);
281
282    if (m_structuralLayer)
283        m_structuralLayer->setOwner(0);
284
285    removeCloneLayers();
286}
287
288void GraphicsLayerCA::setName(const String& name)
289{
290    String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + name;
291    GraphicsLayer::setName(longName);
292    noteLayerPropertyChanged(NameChanged);
293}
294
295PlatformLayer* GraphicsLayerCA::platformLayer() const
296{
297    return primaryLayer()->platformLayer();
298}
299
300bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children)
301{
302    bool childrenChanged = GraphicsLayer::setChildren(children);
303    if (childrenChanged)
304        noteSublayersChanged();
305
306    return childrenChanged;
307}
308
309void GraphicsLayerCA::addChild(GraphicsLayer* childLayer)
310{
311    GraphicsLayer::addChild(childLayer);
312    noteSublayersChanged();
313}
314
315void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index)
316{
317    GraphicsLayer::addChildAtIndex(childLayer, index);
318    noteSublayersChanged();
319}
320
321void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
322{
323    GraphicsLayer::addChildBelow(childLayer, sibling);
324    noteSublayersChanged();
325}
326
327void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
328{
329    GraphicsLayer::addChildAbove(childLayer, sibling);
330    noteSublayersChanged();
331}
332
333bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
334{
335    if (GraphicsLayer::replaceChild(oldChild, newChild)) {
336        noteSublayersChanged();
337        return true;
338    }
339    return false;
340}
341
342void GraphicsLayerCA::removeFromParent()
343{
344    if (m_parent)
345        static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged();
346    GraphicsLayer::removeFromParent();
347}
348
349void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer)
350{
351    if (layer == m_maskLayer)
352        return;
353
354    GraphicsLayer::setMaskLayer(layer);
355    noteLayerPropertyChanged(MaskLayerChanged);
356
357    propagateLayerChangeToReplicas();
358
359    if (m_replicatedLayer)
360        static_cast<GraphicsLayerCA*>(m_replicatedLayer)->propagateLayerChangeToReplicas();
361}
362
363void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer)
364{
365    if (layer == m_replicatedLayer)
366        return;
367
368    GraphicsLayer::setReplicatedLayer(layer);
369    noteLayerPropertyChanged(ReplicatedLayerChanged);
370}
371
372void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer)
373{
374    if (layer == m_replicaLayer)
375        return;
376
377    GraphicsLayer::setReplicatedByLayer(layer);
378    noteSublayersChanged();
379    noteLayerPropertyChanged(ReplicatedLayerChanged);
380}
381
382void GraphicsLayerCA::setPosition(const FloatPoint& point)
383{
384    if (point == m_position)
385        return;
386
387    GraphicsLayer::setPosition(point);
388    noteLayerPropertyChanged(PositionChanged);
389}
390
391void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point)
392{
393    if (point == m_anchorPoint)
394        return;
395
396    GraphicsLayer::setAnchorPoint(point);
397    noteLayerPropertyChanged(AnchorPointChanged);
398}
399
400void GraphicsLayerCA::setSize(const FloatSize& size)
401{
402    if (size == m_size)
403        return;
404
405    GraphicsLayer::setSize(size);
406    noteLayerPropertyChanged(SizeChanged);
407}
408
409void GraphicsLayerCA::setTransform(const TransformationMatrix& t)
410{
411    if (t == m_transform)
412        return;
413
414    GraphicsLayer::setTransform(t);
415    noteLayerPropertyChanged(TransformChanged);
416}
417
418void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t)
419{
420    if (t == m_childrenTransform)
421        return;
422
423    GraphicsLayer::setChildrenTransform(t);
424    noteLayerPropertyChanged(ChildrenTransformChanged);
425}
426
427void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
428{
429    RefPtr<PlatformCAAnimation> anim = fromLayer->animationForKey(animationIdentifier);
430    if (!anim)
431        return;
432
433    switch (operation) {
434    case Move:
435        fromLayer->removeAnimationForKey(animationIdentifier);
436        toLayer->addAnimationForKey(animationIdentifier, anim.get());
437        break;
438
439    case Copy:
440        toLayer->addAnimationForKey(animationIdentifier, anim.get());
441        break;
442    }
443}
444
445void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
446{
447    // Look for running animations affecting this property.
448    AnimationsMap::const_iterator end = m_runningAnimations.end();
449    for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
450        const Vector<LayerPropertyAnimation>& propertyAnimations = it->second;
451        size_t numAnimations = propertyAnimations.size();
452        for (size_t i = 0; i < numAnimations; ++i) {
453            const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
454            if (currAnimation.m_property == property)
455                moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index), fromLayer, toLayer);
456        }
457    }
458}
459
460void GraphicsLayerCA::setPreserves3D(bool preserves3D)
461{
462    if (preserves3D == m_preserves3D)
463        return;
464
465    GraphicsLayer::setPreserves3D(preserves3D);
466    noteLayerPropertyChanged(Preserves3DChanged);
467}
468
469void GraphicsLayerCA::setMasksToBounds(bool masksToBounds)
470{
471    if (masksToBounds == m_masksToBounds)
472        return;
473
474    GraphicsLayer::setMasksToBounds(masksToBounds);
475    noteLayerPropertyChanged(MasksToBoundsChanged);
476}
477
478void GraphicsLayerCA::setDrawsContent(bool drawsContent)
479{
480    if (drawsContent == m_drawsContent)
481        return;
482
483    GraphicsLayer::setDrawsContent(drawsContent);
484    noteLayerPropertyChanged(DrawsContentChanged);
485}
486
487void GraphicsLayerCA::setAcceleratesDrawing(bool acceleratesDrawing)
488{
489    if (acceleratesDrawing == m_acceleratesDrawing)
490        return;
491
492    GraphicsLayer::setAcceleratesDrawing(acceleratesDrawing);
493    noteLayerPropertyChanged(AcceleratesDrawingChanged);
494}
495
496void GraphicsLayerCA::setAllowTiledLayer(bool allowTiledLayer)
497{
498    if (allowTiledLayer == m_allowTiledLayer)
499        return;
500
501    m_allowTiledLayer = allowTiledLayer;
502
503    // Handling this as a SizeChanged will cause use to switch in or out of tiled layer as needed
504    noteLayerPropertyChanged(SizeChanged);
505}
506
507void GraphicsLayerCA::setBackgroundColor(const Color& color)
508{
509    if (m_backgroundColorSet && m_backgroundColor == color)
510        return;
511
512    GraphicsLayer::setBackgroundColor(color);
513
514    m_contentsLayerHasBackgroundColor = true;
515    noteLayerPropertyChanged(BackgroundColorChanged);
516}
517
518void GraphicsLayerCA::clearBackgroundColor()
519{
520    if (!m_backgroundColorSet)
521        return;
522
523    GraphicsLayer::clearBackgroundColor();
524    m_contentsLayerHasBackgroundColor = false;
525    noteLayerPropertyChanged(BackgroundColorChanged);
526}
527
528void GraphicsLayerCA::setContentsOpaque(bool opaque)
529{
530    if (m_contentsOpaque == opaque)
531        return;
532
533    GraphicsLayer::setContentsOpaque(opaque);
534    noteLayerPropertyChanged(ContentsOpaqueChanged);
535}
536
537void GraphicsLayerCA::setBackfaceVisibility(bool visible)
538{
539    if (m_backfaceVisibility == visible)
540        return;
541
542    GraphicsLayer::setBackfaceVisibility(visible);
543    noteLayerPropertyChanged(BackfaceVisibilityChanged);
544}
545
546void GraphicsLayerCA::setOpacity(float opacity)
547{
548    float clampedOpacity = max(0.0f, min(opacity, 1.0f));
549
550    if (clampedOpacity == m_opacity)
551        return;
552
553    GraphicsLayer::setOpacity(clampedOpacity);
554    noteLayerPropertyChanged(OpacityChanged);
555}
556
557void GraphicsLayerCA::setNeedsDisplay()
558{
559    FloatRect hugeRect(-numeric_limits<float>::max() / 2, -numeric_limits<float>::max() / 2,
560                       numeric_limits<float>::max(), numeric_limits<float>::max());
561
562    setNeedsDisplayInRect(hugeRect);
563}
564
565void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& r)
566{
567    if (!drawsContent())
568        return;
569
570    FloatRect rect(r);
571    FloatRect layerBounds(FloatPoint(), m_size);
572    rect.intersect(layerBounds);
573    if (rect.isEmpty())
574        return;
575
576    const size_t maxDirtyRects = 32;
577
578    for (size_t i = 0; i < m_dirtyRects.size(); ++i) {
579        if (m_dirtyRects[i].contains(rect))
580            return;
581    }
582
583    if (m_dirtyRects.size() < maxDirtyRects)
584        m_dirtyRects.append(rect);
585    else
586        m_dirtyRects[0].unite(rect);
587
588    noteLayerPropertyChanged(DirtyRectsChanged);
589}
590
591void GraphicsLayerCA::setContentsNeedsDisplay()
592{
593    noteLayerPropertyChanged(ContentsNeedsDisplay);
594}
595
596void GraphicsLayerCA::setContentsRect(const IntRect& rect)
597{
598    if (rect == m_contentsRect)
599        return;
600
601    GraphicsLayer::setContentsRect(rect);
602    noteLayerPropertyChanged(ContentsRectChanged);
603}
604
605bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset)
606{
607    ASSERT(!animationName.isEmpty());
608
609    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
610        return false;
611
612#if !HAVE_MODERN_QUARTZCORE
613    // Older versions of QuartzCore do not handle opacity in transform layers properly, so we will
614    // always do software animation in that case.
615    if (valueList.property() == AnimatedPropertyOpacity)
616        return false;
617#endif
618
619    // CoreAnimation does not handle the steps() timing function. Fall back
620    // to software animation in that case.
621    if (animationHasStepsTimingFunction(valueList, anim))
622        return false;
623
624    bool createdAnimations = false;
625    if (valueList.property() == AnimatedPropertyWebkitTransform)
626        createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize);
627    else
628        createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset);
629
630    if (createdAnimations)
631        noteLayerPropertyChanged(AnimationChanged);
632
633    return createdAnimations;
634}
635
636void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset)
637{
638    if (!animationIsRunning(animationName))
639        return;
640
641    AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName);
642    if (it != m_animationsToProcess.end()) {
643        AnimationProcessingAction& processingInfo = it->second;
644        // If an animation is scheduled to be removed, don't change the remove to a pause.
645        if (processingInfo.action != Remove)
646            processingInfo.action = Pause;
647    } else
648        m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset));
649
650    noteLayerPropertyChanged(AnimationChanged);
651}
652
653void GraphicsLayerCA::removeAnimation(const String& animationName)
654{
655    if (!animationIsRunning(animationName))
656        return;
657
658    m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove));
659    noteLayerPropertyChanged(AnimationChanged);
660}
661
662void GraphicsLayerCA::platformCALayerAnimationStarted(CFTimeInterval startTime)
663{
664    if (m_client)
665        m_client->notifyAnimationStarted(this, startTime);
666}
667
668void GraphicsLayerCA::setContentsToImage(Image* image)
669{
670    if (image) {
671        CGImageRef newImage = image->nativeImageForCurrentFrame();
672        if (!newImage)
673            return;
674
675        // Check to see if the image changed; we have to do this because the call to
676        // CGImageCreateCopyWithColorSpace() below can create a new image every time.
677        if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage)
678            return;
679
680        m_uncorrectedContentsImage = newImage;
681        m_pendingContentsImage = newImage;
682
683#if !PLATFORM(WIN)
684        CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get());
685
686        static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
687        if (colorSpace && CFEqual(colorSpace, deviceRGB)) {
688            // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such
689            // images to CA we need to tag them similarly so CA rendering matches CG rendering.
690            static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
691            m_pendingContentsImage.adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB));
692        }
693#endif
694        m_contentsLayerPurpose = ContentsLayerForImage;
695        if (!m_contentsLayer)
696            noteSublayersChanged();
697    } else {
698        m_uncorrectedContentsImage = 0;
699        m_pendingContentsImage = 0;
700        m_contentsLayerPurpose = NoContentsLayer;
701        if (m_contentsLayer)
702            noteSublayersChanged();
703    }
704
705    noteLayerPropertyChanged(ContentsImageChanged);
706}
707
708void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer)
709{
710    if (m_contentsLayer && mediaLayer == m_contentsLayer->platformLayer())
711        return;
712
713    // FIXME: The passed in layer might be a raw layer or an externally created
714    // PlatformCALayer. To determine this we attempt to get the
715    // PlatformCALayer pointer. If this returns a null pointer we assume it's
716    // raw. This test might be invalid if the raw layer is, for instance, the
717    // PlatformCALayer is using a user data pointer in the raw layer, and
718    // the creator of the raw layer is using it for some other purpose.
719    // For now we don't support such a case.
720    PlatformCALayer* platformCALayer = PlatformCALayer::platformCALayer(mediaLayer);
721    m_contentsLayer = mediaLayer ? (platformCALayer ? platformCALayer : PlatformCALayer::create(mediaLayer, this)) : 0;
722    m_contentsLayerPurpose = mediaLayer ? ContentsLayerForMedia : NoContentsLayer;
723
724    noteSublayersChanged();
725    noteLayerPropertyChanged(ContentsMediaLayerChanged);
726}
727
728void GraphicsLayerCA::setContentsToCanvas(PlatformLayer* canvasLayer)
729{
730    if (m_contentsLayer && canvasLayer == m_contentsLayer->platformLayer())
731        return;
732
733    // Create the PlatformCALayer to wrap the incoming layer
734    m_contentsLayer = canvasLayer ? PlatformCALayer::create(canvasLayer, this) : 0;
735
736    m_contentsLayerPurpose = canvasLayer ? ContentsLayerForCanvas : NoContentsLayer;
737
738    noteSublayersChanged();
739    noteLayerPropertyChanged(ContentsCanvasLayerChanged);
740}
741
742void GraphicsLayerCA::layerDidDisplay(PlatformLayer* layer)
743{
744    PlatformCALayer* currentLayer = PlatformCALayer::platformCALayer(layer);
745    PlatformCALayer* sourceLayer;
746    LayerMap* layerCloneMap;
747
748    if (currentLayer == m_layer) {
749        sourceLayer = m_layer.get();
750        layerCloneMap = m_layerClones.get();
751    } else if (currentLayer == m_contentsLayer) {
752        sourceLayer = m_contentsLayer.get();
753        layerCloneMap = m_contentsLayerClones.get();
754    } else
755        return;
756
757    if (layerCloneMap) {
758        LayerMap::const_iterator end = layerCloneMap->end();
759        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
760            PlatformCALayer* currClone = it->second.get();
761            if (!currClone)
762                continue;
763
764            if (currClone->contents() != sourceLayer->contents())
765                currClone->setContents(sourceLayer->contents());
766            else
767                currClone->setContentsChanged();
768        }
769    }
770}
771
772void GraphicsLayerCA::syncCompositingState()
773{
774    recursiveCommitChanges();
775}
776
777void GraphicsLayerCA::syncCompositingStateForThisLayerOnly()
778{
779    commitLayerChangesBeforeSublayers();
780    commitLayerChangesAfterSublayers();
781}
782
783void GraphicsLayerCA::recursiveCommitChanges()
784{
785    commitLayerChangesBeforeSublayers();
786
787    if (m_maskLayer)
788        static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesBeforeSublayers();
789
790    const Vector<GraphicsLayer*>& childLayers = children();
791    size_t numChildren = childLayers.size();
792    for (size_t i = 0; i < numChildren; ++i) {
793        GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
794        curChild->recursiveCommitChanges();
795    }
796
797    if (m_replicaLayer)
798        static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveCommitChanges();
799
800    if (m_maskLayer)
801        static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers();
802
803    commitLayerChangesAfterSublayers();
804}
805
806void GraphicsLayerCA::commitLayerChangesBeforeSublayers()
807{
808    if (!m_uncommittedChanges)
809        return;
810
811    // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to
812    if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged))
813        updateStructuralLayer();
814
815    if (m_uncommittedChanges & NameChanged)
816        updateLayerNames();
817
818    if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged
819        updateContentsImage();
820
821    if (m_uncommittedChanges & ContentsMediaLayerChanged) // Needs to happen before ChildrenChanged
822        updateContentsMediaLayer();
823
824    if (m_uncommittedChanges & ContentsCanvasLayerChanged) // Needs to happen before ChildrenChanged
825        updateContentsCanvasLayer();
826
827    if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video
828        updateLayerBackgroundColor();
829
830    if (m_uncommittedChanges & ChildrenChanged)
831        updateSublayerList();
832
833    if (m_uncommittedChanges & PositionChanged)
834        updateLayerPosition();
835
836    if (m_uncommittedChanges & AnchorPointChanged)
837        updateAnchorPoint();
838
839    if (m_uncommittedChanges & SizeChanged)
840        updateLayerSize();
841
842    if (m_uncommittedChanges & TransformChanged)
843        updateTransform();
844
845    if (m_uncommittedChanges & ChildrenTransformChanged)
846        updateChildrenTransform();
847
848    if (m_uncommittedChanges & MasksToBoundsChanged)
849        updateMasksToBounds();
850
851    if (m_uncommittedChanges & DrawsContentChanged)
852        updateLayerDrawsContent();
853
854    if (m_uncommittedChanges & ContentsOpaqueChanged)
855        updateContentsOpaque();
856
857    if (m_uncommittedChanges & BackfaceVisibilityChanged)
858        updateBackfaceVisibility();
859
860    if (m_uncommittedChanges & OpacityChanged)
861        updateOpacityOnLayer();
862
863    if (m_uncommittedChanges & AnimationChanged)
864        updateLayerAnimations();
865
866    if (m_uncommittedChanges & DirtyRectsChanged)
867        repaintLayerDirtyRects();
868
869    if (m_uncommittedChanges & ContentsRectChanged)
870        updateContentsRect();
871
872    if (m_uncommittedChanges & MaskLayerChanged)
873        updateMaskLayer();
874
875    if (m_uncommittedChanges & ContentsNeedsDisplay)
876        updateContentsNeedsDisplay();
877
878    if (m_uncommittedChanges & AcceleratesDrawingChanged)
879        updateAcceleratesDrawing();
880
881    if (m_uncommittedChanges & ContentsScaleChanged)
882        updateContentsScale();
883}
884
885void GraphicsLayerCA::commitLayerChangesAfterSublayers()
886{
887    if (!m_uncommittedChanges)
888        return;
889
890    if (m_uncommittedChanges & ReplicatedLayerChanged)
891        updateReplicatedLayers();
892
893    m_uncommittedChanges = NoChange;
894}
895
896void GraphicsLayerCA::updateLayerNames()
897{
898    switch (structuralLayerPurpose()) {
899    case StructuralLayerForPreserves3D:
900        m_structuralLayer->setName("Transform layer " + name());
901        break;
902    case StructuralLayerForReplicaFlattening:
903        m_structuralLayer->setName("Replica flattening layer " + name());
904        break;
905    case NoStructuralLayer:
906        break;
907    }
908    m_layer->setName(name());
909}
910
911void GraphicsLayerCA::updateSublayerList()
912{
913    PlatformCALayerList newSublayers;
914    const Vector<GraphicsLayer*>& childLayers = children();
915
916    if (m_structuralLayer || m_contentsLayer || childLayers.size() > 0) {
917        if (m_structuralLayer) {
918            // Add the replica layer first.
919            if (m_replicaLayer)
920                newSublayers.append(static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer());
921            // Add the primary layer. Even if we have negative z-order children, the primary layer always comes behind.
922            newSublayers.append(m_layer);
923        } else if (m_contentsLayer) {
924            // FIXME: add the contents layer in the correct order with negative z-order children.
925            // This does not cause visible rendering issues because currently contents layers are only used
926            // for replaced elements that don't have children.
927            newSublayers.append(m_contentsLayer);
928        }
929
930        size_t numChildren = childLayers.size();
931        for (size_t i = 0; i < numChildren; ++i) {
932            GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
933            PlatformCALayer* childLayer = curChild->layerForSuperlayer();
934            newSublayers.append(childLayer);
935        }
936
937        for (size_t i = 0; i < newSublayers.size(); --i)
938            newSublayers[i]->removeFromSuperlayer();
939    }
940
941    if (m_structuralLayer) {
942        m_structuralLayer->setSublayers(newSublayers);
943
944        if (m_contentsLayer) {
945            // If we have a transform layer, then the contents layer is parented in the
946            // primary layer (which is itself a child of the transform layer).
947            m_layer->removeAllSublayers();
948            m_layer->appendSublayer(m_contentsLayer.get());
949        }
950    } else
951        m_layer->setSublayers(newSublayers);
952}
953
954void GraphicsLayerCA::updateLayerPosition()
955{
956    FloatSize usedSize = m_usingTiledLayer ? constrainedSize() : m_size;
957
958    // Position is offset on the layer by the layer anchor point.
959    FloatPoint posPoint(m_position.x() + m_anchorPoint.x() * usedSize.width(),
960                          m_position.y() + m_anchorPoint.y() * usedSize.height());
961
962    primaryLayer()->setPosition(posPoint);
963
964    if (LayerMap* layerCloneMap = primaryLayerClones()) {
965        LayerMap::const_iterator end = layerCloneMap->end();
966        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
967            FloatPoint clonePosition = posPoint;
968            if (m_replicaLayer && isReplicatedRootClone(it->first)) {
969                // Maintain the special-case position for the root of a clone subtree,
970                // which we set up in replicatedLayerRoot().
971                clonePosition = positionForCloneRootLayer();
972            }
973            it->second->setPosition(clonePosition);
974        }
975    }
976}
977
978void GraphicsLayerCA::updateLayerSize()
979{
980    FloatRect rect(0, 0, m_size.width(), m_size.height());
981    if (m_structuralLayer) {
982        m_structuralLayer->setBounds(rect);
983
984        if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
985            LayerMap::const_iterator end = layerCloneMap->end();
986            for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
987                it->second->setBounds(rect);
988        }
989
990        // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
991        CGPoint centerPoint = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f);
992        m_layer->setPosition(centerPoint);
993
994        if (LayerMap* layerCloneMap = m_layerClones.get()) {
995            LayerMap::const_iterator end = layerCloneMap->end();
996            for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
997                it->second->setPosition(centerPoint);
998        }
999    }
1000
1001    bool needTiledLayer = requiresTiledLayer(m_size);
1002    if (needTiledLayer != m_usingTiledLayer)
1003        swapFromOrToTiledLayer(needTiledLayer);
1004
1005    if (m_usingTiledLayer) {
1006        FloatSize sizeToUse = constrainedSize();
1007        rect = CGRectMake(0, 0, sizeToUse.width(), sizeToUse.height());
1008    }
1009
1010    m_layer->setBounds(rect);
1011    if (LayerMap* layerCloneMap = m_layerClones.get()) {
1012        LayerMap::const_iterator end = layerCloneMap->end();
1013        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1014            it->second->setBounds(rect);
1015    }
1016
1017    // Contents transform may depend on height.
1018    updateContentsTransform();
1019
1020    // Note that we don't resize m_contentsLayer. It's up the caller to do that.
1021
1022    // if we've changed the bounds, we need to recalculate the position
1023    // of the layer, taking anchor point into account.
1024    updateLayerPosition();
1025}
1026
1027void GraphicsLayerCA::updateAnchorPoint()
1028{
1029    primaryLayer()->setAnchorPoint(m_anchorPoint);
1030
1031    if (LayerMap* layerCloneMap = primaryLayerClones()) {
1032        LayerMap::const_iterator end = layerCloneMap->end();
1033        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1034            PlatformCALayer* currLayer = it->second.get();
1035            currLayer->setAnchorPoint(m_anchorPoint);
1036        }
1037    }
1038
1039    updateLayerPosition();
1040}
1041
1042void GraphicsLayerCA::updateTransform()
1043{
1044    primaryLayer()->setTransform(m_transform);
1045
1046    if (LayerMap* layerCloneMap = primaryLayerClones()) {
1047        LayerMap::const_iterator end = layerCloneMap->end();
1048        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1049            PlatformCALayer* currLayer = it->second.get();
1050            if (m_replicaLayer && isReplicatedRootClone(it->first)) {
1051                // Maintain the special-case transform for the root of a clone subtree,
1052                // which we set up in replicatedLayerRoot().
1053                currLayer->setTransform(TransformationMatrix());
1054            } else
1055                currLayer->setTransform(m_transform);
1056        }
1057    }
1058}
1059
1060void GraphicsLayerCA::updateChildrenTransform()
1061{
1062    primaryLayer()->setSublayerTransform(m_childrenTransform);
1063
1064    if (LayerMap* layerCloneMap = primaryLayerClones()) {
1065        LayerMap::const_iterator end = layerCloneMap->end();
1066        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1067            it->second->setSublayerTransform(m_childrenTransform);
1068    }
1069}
1070
1071void GraphicsLayerCA::updateMasksToBounds()
1072{
1073    m_layer->setMasksToBounds(m_masksToBounds);
1074
1075    if (LayerMap* layerCloneMap = m_layerClones.get()) {
1076        LayerMap::const_iterator end = layerCloneMap->end();
1077        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1078            it->second->setMasksToBounds(m_masksToBounds);
1079    }
1080
1081    updateDebugIndicators();
1082}
1083
1084void GraphicsLayerCA::updateContentsOpaque()
1085{
1086    m_layer.get()->setOpaque(m_contentsOpaque);
1087
1088    if (LayerMap* layerCloneMap = m_layerClones.get()) {
1089        LayerMap::const_iterator end = layerCloneMap->end();
1090        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1091            it->second->setOpaque(m_contentsOpaque);
1092    }
1093}
1094
1095void GraphicsLayerCA::updateBackfaceVisibility()
1096{
1097    if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) {
1098        m_structuralLayer->setDoubleSided(m_backfaceVisibility);
1099
1100        if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
1101            LayerMap::const_iterator end = layerCloneMap->end();
1102            for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1103                it->second->setDoubleSided(m_backfaceVisibility);
1104        }
1105    }
1106
1107    m_layer->setDoubleSided(m_backfaceVisibility);
1108
1109    if (LayerMap* layerCloneMap = m_layerClones.get()) {
1110        LayerMap::const_iterator end = layerCloneMap->end();
1111        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1112            it->second->setDoubleSided(m_backfaceVisibility);
1113    }
1114}
1115
1116void GraphicsLayerCA::updateStructuralLayer()
1117{
1118    ensureStructuralLayer(structuralLayerPurpose());
1119}
1120
1121void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose)
1122{
1123    if (purpose == NoStructuralLayer) {
1124        if (m_structuralLayer) {
1125            // Replace the transformLayer in the parent with this layer.
1126            m_layer->removeFromSuperlayer();
1127
1128            // If m_layer doesn't have a parent, it means it's the root layer and
1129            // is likely hosted by something that is not expecting to be changed
1130            ASSERT(m_structuralLayer->superlayer());
1131            m_structuralLayer->superlayer()->replaceSublayer(m_structuralLayer.get(), m_layer.get());
1132
1133            moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_structuralLayer.get(), m_layer.get());
1134            moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_structuralLayer.get(), m_layer.get());
1135
1136            // Release the structural layer.
1137            m_structuralLayer = 0;
1138
1139            // Update the properties of m_layer now that we no longer have a structural layer.
1140            updateLayerPosition();
1141            updateLayerSize();
1142            updateAnchorPoint();
1143            updateTransform();
1144            updateChildrenTransform();
1145
1146            updateSublayerList();
1147            updateOpacityOnLayer();
1148        }
1149        return;
1150    }
1151
1152    bool structuralLayerChanged = false;
1153
1154    if (purpose == StructuralLayerForPreserves3D) {
1155        if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeTransformLayer)
1156            m_structuralLayer = 0;
1157
1158        if (!m_structuralLayer) {
1159            m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeTransformLayer, this);
1160            structuralLayerChanged = true;
1161        }
1162    } else {
1163        if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeLayer)
1164            m_structuralLayer = 0;
1165
1166        if (!m_structuralLayer) {
1167            m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this);
1168            structuralLayerChanged = true;
1169        }
1170    }
1171
1172    if (!structuralLayerChanged)
1173        return;
1174
1175    updateLayerNames();
1176
1177    // Update the properties of the structural layer.
1178    updateLayerPosition();
1179    updateLayerSize();
1180    updateAnchorPoint();
1181    updateTransform();
1182    updateChildrenTransform();
1183    updateBackfaceVisibility();
1184
1185    // Set properties of m_layer to their default values, since these are expressed on on the structural layer.
1186    FloatPoint point(m_size.width() / 2.0f, m_size.height() / 2.0f);
1187    FloatPoint3D anchorPoint(0.5f, 0.5f, 0);
1188    m_layer->setPosition(point);
1189    m_layer->setAnchorPoint(anchorPoint);
1190    m_layer->setTransform(TransformationMatrix());
1191    m_layer->setOpacity(1);
1192    if (m_layerClones) {
1193        LayerMap::const_iterator end = m_layerClones->end();
1194        for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) {
1195            PlatformCALayer* currLayer = it->second.get();
1196            currLayer->setPosition(point);
1197            currLayer->setAnchorPoint(anchorPoint);
1198            currLayer->setTransform(TransformationMatrix());
1199            currLayer->setOpacity(1);
1200        }
1201    }
1202
1203    // Move this layer to be a child of the transform layer.
1204    // If m_layer doesn't have a parent, it means it's the root layer and
1205    // is likely hosted by something that is not expecting to be changed
1206    ASSERT(m_layer->superlayer());
1207    m_layer->superlayer()->replaceSublayer(m_layer.get(), m_structuralLayer.get());
1208    m_structuralLayer->appendSublayer(m_layer.get());
1209
1210    moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_layer.get(), m_structuralLayer.get());
1211    moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_layer.get(), m_structuralLayer.get());
1212
1213    updateSublayerList();
1214    updateOpacityOnLayer();
1215}
1216
1217GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const
1218{
1219    if (preserves3D())
1220        return StructuralLayerForPreserves3D;
1221
1222    if (isReplicated())
1223        return StructuralLayerForReplicaFlattening;
1224
1225    return NoStructuralLayer;
1226}
1227
1228void GraphicsLayerCA::updateLayerDrawsContent()
1229{
1230    bool needTiledLayer = requiresTiledLayer(m_size);
1231    if (needTiledLayer != m_usingTiledLayer)
1232        swapFromOrToTiledLayer(needTiledLayer);
1233
1234    if (m_drawsContent)
1235        m_layer->setNeedsDisplay();
1236    else
1237        m_layer->setContents(0);
1238
1239    updateDebugIndicators();
1240}
1241
1242void GraphicsLayerCA::updateAcceleratesDrawing()
1243{
1244    m_layer->setAcceleratesDrawing(m_acceleratesDrawing);
1245}
1246
1247void GraphicsLayerCA::updateLayerBackgroundColor()
1248{
1249    if (!m_contentsLayer)
1250        return;
1251
1252    // We never create the contents layer just for background color yet.
1253    if (m_backgroundColorSet)
1254        m_contentsLayer->setBackgroundColor(m_backgroundColor);
1255    else
1256        m_contentsLayer->setBackgroundColor(Color::transparent);
1257}
1258
1259void GraphicsLayerCA::updateContentsImage()
1260{
1261    if (m_pendingContentsImage) {
1262        if (!m_contentsLayer.get()) {
1263            m_contentsLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this);
1264#ifndef NDEBUG
1265            m_contentsLayer->setName("Image Layer");
1266#endif
1267            setupContentsLayer(m_contentsLayer.get());
1268            // m_contentsLayer will be parented by updateSublayerList
1269        }
1270
1271        // FIXME: maybe only do trilinear if the image is being scaled down,
1272        // but then what if the layer size changes?
1273#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
1274        m_contentsLayer->setMinificationFilter(PlatformCALayer::Trilinear);
1275#endif
1276        m_contentsLayer->setContents(m_pendingContentsImage.get());
1277        m_pendingContentsImage = 0;
1278
1279        if (m_contentsLayerClones) {
1280            LayerMap::const_iterator end = m_contentsLayerClones->end();
1281            for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it)
1282                it->second->setContents(m_contentsLayer->contents());
1283        }
1284
1285        updateContentsRect();
1286    } else {
1287        // No image.
1288        // m_contentsLayer will be removed via updateSublayerList.
1289        m_contentsLayer = 0;
1290    }
1291}
1292
1293void GraphicsLayerCA::updateContentsMediaLayer()
1294{
1295    // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList().
1296    if (m_contentsLayer) {
1297        setupContentsLayer(m_contentsLayer.get());
1298        updateContentsRect();
1299    }
1300}
1301
1302void GraphicsLayerCA::updateContentsCanvasLayer()
1303{
1304    // CanvasLayer was set as m_contentsLayer, and will get parented in updateSublayerList().
1305    if (m_contentsLayer) {
1306        setupContentsLayer(m_contentsLayer.get());
1307        m_contentsLayer->setNeedsDisplay();
1308        updateContentsRect();
1309    }
1310}
1311
1312void GraphicsLayerCA::updateContentsRect()
1313{
1314    if (!m_contentsLayer)
1315        return;
1316
1317    FloatPoint point(m_contentsRect.x(), m_contentsRect.y());
1318    FloatRect rect(0, 0, m_contentsRect.width(), m_contentsRect.height());
1319
1320    m_contentsLayer->setPosition(point);
1321    m_contentsLayer->setBounds(rect);
1322
1323    if (m_contentsLayerClones) {
1324        LayerMap::const_iterator end = m_contentsLayerClones->end();
1325        for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) {
1326            it->second->setPosition(point);
1327            it->second->setBounds(rect);
1328        }
1329    }
1330}
1331
1332void GraphicsLayerCA::updateMaskLayer()
1333{
1334    PlatformCALayer* maskCALayer = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayer() : 0;
1335    m_layer->setMask(maskCALayer);
1336
1337    LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayerClones() : 0;
1338
1339    if (LayerMap* layerCloneMap = m_layerClones.get()) {
1340        LayerMap::const_iterator end = layerCloneMap->end();
1341        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1342            PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->first).get() : 0;
1343            it->second->setMask(maskClone);
1344        }
1345    }
1346}
1347
1348void GraphicsLayerCA::updateReplicatedLayers()
1349{
1350    // Clone the descendants of the replicated layer, and parent under us.
1351    ReplicaState replicaState(ReplicaState::ReplicaBranch);
1352
1353    RefPtr<PlatformCALayer>replicaRoot = replicatedLayerRoot(replicaState);
1354    if (!replicaRoot)
1355        return;
1356
1357    if (m_structuralLayer)
1358        m_structuralLayer->insertSublayer(replicaRoot.get(), 0);
1359    else
1360        m_layer->insertSublayer(replicaRoot.get(), 0);
1361}
1362
1363// For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1.
1364GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const
1365{
1366    size_t depth = m_replicaBranches.size();
1367
1368    const size_t bitsPerUChar = sizeof(UChar) * 8;
1369    size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar;
1370
1371    Vector<UChar> result(vectorSize);
1372    result.fill(0);
1373
1374    // Create a string from the bit sequence which we can use to identify the clone.
1375    // Note that the string may contain embedded nulls, but that's OK.
1376    for (size_t i = 0; i < depth; ++i) {
1377        UChar& currChar = result[i / bitsPerUChar];
1378        currChar = (currChar << 1) | m_replicaBranches[i];
1379    }
1380
1381    return String::adopt(result);
1382}
1383
1384PassRefPtr<PlatformCALayer> GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState)
1385{
1386    // Limit replica nesting, to avoid 2^N explosion of replica layers.
1387    if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth)
1388        return 0;
1389
1390    GraphicsLayerCA* replicatedLayer = static_cast<GraphicsLayerCA*>(m_replicatedLayer);
1391
1392    RefPtr<PlatformCALayer> clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel);
1393    FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer();
1394
1395    // Replica root has no offset or transform
1396    clonedLayerRoot->setPosition(cloneRootPosition);
1397    clonedLayerRoot->setTransform(TransformationMatrix());
1398
1399    return clonedLayerRoot;
1400}
1401
1402void GraphicsLayerCA::updateLayerAnimations()
1403{
1404    if (m_animationsToProcess.size()) {
1405        AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end();
1406        for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) {
1407            const String& currAnimationName = it->first;
1408            AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName);
1409            if (animationIt == m_runningAnimations.end())
1410                continue;
1411
1412            const AnimationProcessingAction& processingInfo = it->second;
1413            const Vector<LayerPropertyAnimation>& animations = animationIt->second;
1414            for (size_t i = 0; i < animations.size(); ++i) {
1415                const LayerPropertyAnimation& currAnimation = animations[i];
1416                switch (processingInfo.action) {
1417                case Remove:
1418                    removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index);
1419                    break;
1420                case Pause:
1421                    pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, processingInfo.timeOffset);
1422                    break;
1423                }
1424            }
1425
1426            if (processingInfo.action == Remove)
1427                m_runningAnimations.remove(currAnimationName);
1428        }
1429
1430        m_animationsToProcess.clear();
1431    }
1432
1433    size_t numAnimations;
1434    if ((numAnimations = m_uncomittedAnimations.size())) {
1435        for (size_t i = 0; i < numAnimations; ++i) {
1436            const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i];
1437            setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_timeOffset);
1438
1439            AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name);
1440            if (it == m_runningAnimations.end()) {
1441                Vector<LayerPropertyAnimation> animations;
1442                animations.append(pendingAnimation);
1443                m_runningAnimations.add(pendingAnimation.m_name, animations);
1444            } else {
1445                Vector<LayerPropertyAnimation>& animations = it->second;
1446                animations.append(pendingAnimation);
1447            }
1448        }
1449
1450        m_uncomittedAnimations.clear();
1451    }
1452}
1453
1454void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, double timeOffset)
1455{
1456    PlatformCALayer* layer = animatedLayer(property);
1457
1458    if (timeOffset)
1459        caAnim->setBeginTime(CACurrentMediaTime() - timeOffset);
1460
1461    String animationID = animationIdentifier(animationName, property, index);
1462
1463    layer->removeAnimationForKey(animationID);
1464    layer->addAnimationForKey(animationID, caAnim);
1465
1466    if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
1467        LayerMap::const_iterator end = layerCloneMap->end();
1468        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1469            // Skip immediate replicas, since they move with the original.
1470            if (m_replicaLayer && isReplicatedRootClone(it->first))
1471                continue;
1472
1473            it->second->removeAnimationForKey(animationID);
1474            it->second->addAnimationForKey(animationID, caAnim);
1475        }
1476    }
1477}
1478
1479// Workaround for <rdar://problem/7311367>
1480static void bug7311367Workaround(PlatformCALayer* transformLayer, const TransformationMatrix& transform)
1481{
1482    if (!transformLayer)
1483        return;
1484
1485    TransformationMatrix caTransform = transform;
1486    caTransform.setM41(caTransform.m41() + 1);
1487    transformLayer->setTransform(caTransform);
1488
1489    caTransform.setM41(caTransform.m41() - 1);
1490    transformLayer->setTransform(caTransform);
1491}
1492
1493bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index)
1494{
1495    PlatformCALayer* layer = animatedLayer(property);
1496
1497    String animationID = animationIdentifier(animationName, property, index);
1498
1499    if (!layer->animationForKey(animationID))
1500        return false;
1501
1502    layer->removeAnimationForKey(animationID);
1503    bug7311367Workaround(m_structuralLayer.get(), m_transform);
1504
1505    if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
1506        LayerMap::const_iterator end = layerCloneMap->end();
1507        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1508            // Skip immediate replicas, since they move with the original.
1509            if (m_replicaLayer && isReplicatedRootClone(it->first))
1510                continue;
1511
1512            it->second ->removeAnimationForKey(animationID);
1513        }
1514    }
1515    return true;
1516}
1517
1518void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, double timeOffset)
1519{
1520    PlatformCALayer* layer = animatedLayer(property);
1521
1522    String animationID = animationIdentifier(animationName, property, index);
1523
1524    RefPtr<PlatformCAAnimation> curAnim = layer->animationForKey(animationID);
1525    if (!curAnim)
1526        return;
1527
1528    // Animations on the layer are immutable, so we have to clone and modify.
1529    RefPtr<PlatformCAAnimation> newAnim = curAnim->copy();
1530
1531    newAnim->setSpeed(0);
1532    newAnim->setTimeOffset(timeOffset);
1533
1534    layer->addAnimationForKey(animationID, newAnim.get()); // This will replace the running animation.
1535
1536    // Pause the animations on the clones too.
1537    if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
1538        LayerMap::const_iterator end = layerCloneMap->end();
1539        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1540            // Skip immediate replicas, since they move with the original.
1541            if (m_replicaLayer && isReplicatedRootClone(it->first))
1542                continue;
1543            it->second->addAnimationForKey(animationID, newAnim.get());
1544        }
1545    }
1546}
1547
1548void GraphicsLayerCA::repaintLayerDirtyRects()
1549{
1550    if (!m_dirtyRects.size())
1551        return;
1552
1553    for (size_t i = 0; i < m_dirtyRects.size(); ++i)
1554        m_layer->setNeedsDisplay(&(m_dirtyRects[i]));
1555
1556    m_dirtyRects.clear();
1557}
1558
1559void GraphicsLayerCA::updateContentsNeedsDisplay()
1560{
1561    if (m_contentsLayer)
1562        m_contentsLayer->setNeedsDisplay();
1563}
1564
1565bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset)
1566{
1567    ASSERT(valueList.property() != AnimatedPropertyWebkitTransform);
1568
1569    bool isKeyframe = valueList.size() > 2;
1570    bool valuesOK;
1571
1572    bool additive = false;
1573    int animationIndex = 0;
1574
1575    RefPtr<PlatformCAAnimation> caAnimation;
1576
1577    if (isKeyframe) {
1578        caAnimation = createKeyframeAnimation(animation, valueList.property(), additive);
1579        valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get());
1580    } else {
1581        caAnimation = createBasicAnimation(animation, valueList.property(), additive);
1582        valuesOK = setAnimationEndpoints(valueList, animation, caAnimation.get());
1583    }
1584
1585    if (!valuesOK)
1586        return false;
1587
1588    m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset));
1589
1590    return true;
1591}
1592
1593bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize)
1594{
1595    ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
1596
1597    TransformOperationList functionList;
1598    bool listsMatch, hasBigRotation;
1599    fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation);
1600
1601    // We need to fall back to software animation if we don't have setValueFunction:, and
1602    // we would need to animate each incoming transform function separately. This is the
1603    // case if we have a rotation >= 180 or we have more than one transform function.
1604    if ((hasBigRotation || functionList.size() > 1) && !PlatformCAAnimation::supportsValueFunction())
1605        return false;
1606
1607    bool validMatrices = true;
1608
1609    // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation.
1610    // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation
1611    // if that's not true as well.
1612    bool isMatrixAnimation = !listsMatch || !PlatformCAAnimation::supportsValueFunction();
1613
1614    size_t numAnimations = isMatrixAnimation ? 1 : functionList.size();
1615    bool isKeyframe = valueList.size() > 2;
1616
1617    // Iterate through the transform functions, sending an animation for each one.
1618    for (size_t animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
1619        TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : functionList[animationIndex];
1620        RefPtr<PlatformCAAnimation> caAnimation;
1621
1622#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) || PLATFORM(WIN)
1623        // CA applies animations in reverse order (<rdar://problem/7095638>) so we need the last one we add (per property)
1624        // to be non-additive.
1625        // FIXME: This fix has not been added to QuartzCore on Windows yet (<rdar://problem/9112233>) so we expect the
1626        // reversed animation behavior
1627        bool additive = animationIndex < (numAnimations - 1);
1628#else
1629        bool additive = animationIndex > 0;
1630#endif
1631        if (isKeyframe) {
1632            caAnimation = createKeyframeAnimation(animation, valueList.property(), additive);
1633            validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
1634        } else {
1635            caAnimation = createBasicAnimation(animation, valueList.property(), additive);
1636            validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
1637        }
1638
1639        if (!validMatrices)
1640            break;
1641
1642        m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset));
1643    }
1644
1645    return validMatrices;
1646}
1647
1648PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, AnimatedPropertyID property, bool additive)
1649{
1650    RefPtr<PlatformCAAnimation> basicAnim = PlatformCAAnimation::create(PlatformCAAnimation::Basic, propertyIdToString(property));
1651    setupAnimation(basicAnim.get(), anim, additive);
1652    return basicAnim;
1653}
1654
1655PassRefPtr<PlatformCAAnimation>GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, AnimatedPropertyID property, bool additive)
1656{
1657    RefPtr<PlatformCAAnimation> keyframeAnim = PlatformCAAnimation::create(PlatformCAAnimation::Keyframe, propertyIdToString(property));
1658    setupAnimation(keyframeAnim.get(), anim, additive);
1659    return keyframeAnim;
1660}
1661
1662void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive)
1663{
1664    double duration = anim->duration();
1665    if (duration <= 0)
1666        duration = cAnimationAlmostZeroDuration;
1667
1668    float repeatCount = anim->iterationCount();
1669    if (repeatCount == Animation::IterationCountInfinite)
1670        repeatCount = numeric_limits<float>::max();
1671    else if (anim->direction() == Animation::AnimationDirectionAlternate)
1672        repeatCount /= 2;
1673
1674    PlatformCAAnimation::FillModeType fillMode = PlatformCAAnimation::NoFillMode;
1675    switch (anim->fillMode()) {
1676    case AnimationFillModeNone:
1677        fillMode = PlatformCAAnimation::Forwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash.
1678        break;
1679    case AnimationFillModeBackwards:
1680        fillMode = PlatformCAAnimation::Both; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash.
1681        break;
1682    case AnimationFillModeForwards:
1683        fillMode = PlatformCAAnimation::Forwards;
1684        break;
1685    case AnimationFillModeBoth:
1686        fillMode = PlatformCAAnimation::Both;
1687        break;
1688    }
1689
1690    propertyAnim->setDuration(duration);
1691    propertyAnim->setRepeatCount(repeatCount);
1692    propertyAnim->setAutoreverses(anim->direction());
1693    propertyAnim->setRemovedOnCompletion(false);
1694    propertyAnim->setAdditive(additive);
1695    propertyAnim->setFillMode(fillMode);
1696}
1697
1698const TimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue* animValue, const Animation* anim)
1699{
1700    if (animValue->timingFunction())
1701        return animValue->timingFunction();
1702    if (anim->isTimingFunctionSet())
1703        return anim->timingFunction().get();
1704
1705    return CubicBezierTimingFunction::defaultTimingFunction();
1706}
1707
1708bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim)
1709{
1710    switch (valueList.property()) {
1711    case AnimatedPropertyOpacity: {
1712        basicAnim->setFromValue(static_cast<const FloatAnimationValue*>(valueList.at(0))->value());
1713        basicAnim->setToValue(static_cast<const FloatAnimationValue*>(valueList.at(1))->value());
1714        break;
1715    }
1716    default:
1717        ASSERT_NOT_REACHED(); // we don't animate color yet
1718        break;
1719    }
1720
1721    // This codepath is used for 2-keyframe animations, so we still need to look in the start
1722    // for a timing function.
1723    const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim);
1724    if (timingFunction)
1725        basicAnim->setTimingFunction(timingFunction);
1726
1727    return true;
1728}
1729
1730bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* keyframeAnim)
1731{
1732    Vector<float> keyTimes;
1733    Vector<float> values;
1734    Vector<const TimingFunction*> timingFunctions;
1735
1736    for (unsigned i = 0; i < valueList.size(); ++i) {
1737        const AnimationValue* curValue = valueList.at(i);
1738        keyTimes.append(curValue->keyTime());
1739
1740        switch (valueList.property()) {
1741        case AnimatedPropertyOpacity: {
1742            const FloatAnimationValue* floatValue = static_cast<const FloatAnimationValue*>(curValue);
1743            values.append(floatValue->value());
1744            break;
1745        }
1746        default:
1747            ASSERT_NOT_REACHED(); // we don't animate color yet
1748            break;
1749        }
1750
1751        timingFunctions.append(timingFunctionForAnimationValue(curValue, anim));
1752    }
1753
1754    // We toss the last tfArray value because it has to one shorter than the others.
1755    timingFunctions.removeLast();
1756
1757    keyframeAnim->setKeyTimes(keyTimes);
1758    keyframeAnim->setValues(values);
1759    keyframeAnim->setTimingFunctions(timingFunctions);
1760
1761    return true;
1762}
1763
1764bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
1765{
1766    ASSERT(valueList.size() == 2);
1767    const TransformAnimationValue* startValue = static_cast<const TransformAnimationValue*>(valueList.at(0));
1768    const TransformAnimationValue* endValue = static_cast<const TransformAnimationValue*>(valueList.at(1));
1769
1770    if (isMatrixAnimation) {
1771        TransformationMatrix fromTransform, toTransform;
1772        startValue->value()->apply(boxSize, fromTransform);
1773        endValue->value()->apply(boxSize, toTransform);
1774
1775        // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
1776        if (!fromTransform.isInvertible() || !toTransform.isInvertible())
1777            return false;
1778
1779        basicAnim->setFromValue(fromTransform);
1780        basicAnim->setToValue(toTransform);
1781    } else {
1782        if (isTransformTypeNumber(transformOpType)) {
1783            float fromValue;
1784            getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, fromValue);
1785            basicAnim->setFromValue(fromValue);
1786
1787            float toValue;
1788            getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, toValue);
1789            basicAnim->setToValue(toValue);
1790        } else if (isTransformTypeFloatPoint3D(transformOpType)) {
1791            FloatPoint3D fromValue;
1792            getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, fromValue);
1793            basicAnim->setFromValue(fromValue);
1794
1795            FloatPoint3D toValue;
1796            getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, toValue);
1797            basicAnim->setToValue(toValue);
1798        } else {
1799            TransformationMatrix fromValue;
1800            getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, fromValue);
1801            basicAnim->setFromValue(fromValue);
1802
1803            TransformationMatrix toValue;
1804            getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, toValue);
1805            basicAnim->setToValue(toValue);
1806        }
1807    }
1808
1809    // This codepath is used for 2-keyframe animations, so we still need to look in the start
1810    // for a timing function.
1811    const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim);
1812    basicAnim->setTimingFunction(timingFunction);
1813
1814#if HAVE_MODERN_QUARTZCORE
1815    PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
1816    if (valueFunction != PlatformCAAnimation::NoValueFunction)
1817        basicAnim->setValueFunction(valueFunction);
1818#endif
1819
1820    return true;
1821}
1822
1823bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
1824{
1825    Vector<float> keyTimes;
1826    Vector<float> floatValues;
1827    Vector<FloatPoint3D> floatPoint3DValues;
1828    Vector<TransformationMatrix> transformationMatrixValues;
1829    Vector<const TimingFunction*> timingFunctions;
1830
1831    for (unsigned i = 0; i < valueList.size(); ++i) {
1832        const TransformAnimationValue* curValue = static_cast<const TransformAnimationValue*>(valueList.at(i));
1833        keyTimes.append(curValue->keyTime());
1834
1835        if (isMatrixAnimation) {
1836            TransformationMatrix transform;
1837            curValue->value()->apply(boxSize, transform);
1838
1839            // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
1840            if (!transform.isInvertible())
1841                return false;
1842
1843            transformationMatrixValues.append(transform);
1844        } else {
1845            const TransformOperation* transformOp = curValue->value()->at(functionIndex);
1846            if (isTransformTypeNumber(transformOpType)) {
1847                float value;
1848                getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
1849                floatValues.append(value);
1850            } else if (isTransformTypeFloatPoint3D(transformOpType)) {
1851                FloatPoint3D value;
1852                getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
1853                floatPoint3DValues.append(value);
1854            } else {
1855                TransformationMatrix value;
1856                getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
1857                transformationMatrixValues.append(value);
1858            }
1859        }
1860
1861        const TimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, animation);
1862        timingFunctions.append(timingFunction);
1863    }
1864
1865    // We toss the last tfArray value because it has to one shorter than the others.
1866    timingFunctions.removeLast();
1867
1868    keyframeAnim->setKeyTimes(keyTimes);
1869
1870    if (isTransformTypeNumber(transformOpType))
1871        keyframeAnim->setValues(floatValues);
1872    else if (isTransformTypeFloatPoint3D(transformOpType))
1873        keyframeAnim->setValues(floatPoint3DValues);
1874    else
1875        keyframeAnim->setValues(transformationMatrixValues);
1876
1877    keyframeAnim->setTimingFunctions(timingFunctions);
1878
1879#if HAVE_MODERN_QUARTZCORE
1880    PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
1881    if (valueFunction != PlatformCAAnimation::NoValueFunction)
1882        keyframeAnim->setValueFunction(valueFunction);
1883#endif
1884    return true;
1885}
1886
1887void GraphicsLayerCA::suspendAnimations(double time)
1888{
1889    double t = currentTimeToMediaTime(time ? time : currentTime());
1890    primaryLayer()->setSpeed(0);
1891    primaryLayer()->setTimeOffset(t);
1892
1893    // Suspend the animations on the clones too.
1894    if (LayerMap* layerCloneMap = primaryLayerClones()) {
1895        LayerMap::const_iterator end = layerCloneMap->end();
1896        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1897            it->second->setSpeed(0);
1898            it->second->setTimeOffset(t);
1899        }
1900    }
1901}
1902
1903void GraphicsLayerCA::resumeAnimations()
1904{
1905    primaryLayer()->setSpeed(1);
1906    primaryLayer()->setTimeOffset(0);
1907
1908    // Resume the animations on the clones too.
1909    if (LayerMap* layerCloneMap = primaryLayerClones()) {
1910        LayerMap::const_iterator end = layerCloneMap->end();
1911        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1912            it->second->setSpeed(1);
1913            it->second->setTimeOffset(0);
1914        }
1915    }
1916}
1917
1918PlatformCALayer* GraphicsLayerCA::hostLayerForSublayers() const
1919{
1920    return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get();
1921}
1922
1923PlatformCALayer* GraphicsLayerCA::layerForSuperlayer() const
1924{
1925    return m_structuralLayer ? m_structuralLayer.get() : m_layer.get();
1926}
1927
1928PlatformCALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const
1929{
1930    return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer();
1931}
1932
1933GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const
1934{
1935    return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones();
1936}
1937
1938void GraphicsLayerCA::setContentsScale(float scale)
1939{
1940    float newScale = clampedContentsScaleForScale(scale);
1941    if (newScale == m_contentsScale)
1942        return;
1943
1944    m_contentsScale = newScale;
1945    noteLayerPropertyChanged(ContentsScaleChanged);
1946}
1947
1948float GraphicsLayerCA::clampedContentsScaleForScale(float scale) const
1949{
1950    // Define some limits as a sanity check for the incoming scale value
1951    // those too small to see.
1952    const float maxScale = 5.0f;
1953    const float minScale = 0.01f;
1954
1955    // Avoid very slight scale changes that would be doing extra work for no benefit
1956    const float maxAllowableDelta = 0.05f;
1957
1958    // Clamp
1959    float result = max(minScale, min(scale, maxScale));
1960
1961    // If it hasn't changed much, don't do any work
1962    return ((fabs(result - m_contentsScale) / m_contentsScale) < maxAllowableDelta) ? m_contentsScale : result;
1963}
1964
1965void GraphicsLayerCA::updateContentsScale()
1966{
1967    bool needTiledLayer = requiresTiledLayer(m_size);
1968    if (needTiledLayer != m_usingTiledLayer)
1969        swapFromOrToTiledLayer(needTiledLayer);
1970
1971    m_layer->setContentsScale(m_contentsScale);
1972    if (drawsContent())
1973        m_layer->setNeedsDisplay();
1974}
1975
1976void GraphicsLayerCA::setDebugBackgroundColor(const Color& color)
1977{
1978    if (color.isValid())
1979        m_layer->setBackgroundColor(color);
1980    else
1981        m_layer->setBackgroundColor(Color::transparent);
1982}
1983
1984void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth)
1985{
1986    if (color.isValid()) {
1987        m_layer->setBorderColor(color);
1988        m_layer->setBorderWidth(borderWidth);
1989    } else {
1990        m_layer->setBorderColor(Color::transparent);
1991        m_layer->setBorderWidth(0);
1992    }
1993}
1994
1995FloatSize GraphicsLayerCA::constrainedSize() const
1996{
1997    float tileColumns = ceilf(m_size.width() / kTiledLayerTileSize);
1998    float tileRows = ceilf(m_size.height() / kTiledLayerTileSize);
1999    double numTiles = tileColumns * tileRows;
2000
2001    FloatSize constrainedSize = m_size;
2002    const unsigned cMaxTileCount = 512;
2003    while (numTiles > cMaxTileCount) {
2004        // Constrain the wider dimension.
2005        if (constrainedSize.width() >= constrainedSize.height()) {
2006            tileColumns = max(floorf(cMaxTileCount / tileRows), 1.0f);
2007            constrainedSize.setWidth(tileColumns * kTiledLayerTileSize);
2008        } else {
2009            tileRows = max(floorf(cMaxTileCount / tileColumns), 1.0f);
2010            constrainedSize.setHeight(tileRows * kTiledLayerTileSize);
2011        }
2012        numTiles = tileColumns * tileRows;
2013    }
2014
2015    return constrainedSize;
2016}
2017
2018bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const
2019{
2020    if (!m_drawsContent || !m_allowTiledLayer)
2021        return false;
2022
2023    // FIXME: catch zero-size height or width here (or earlier)?
2024    return size.width() > cMaxPixelDimension || size.height() > cMaxPixelDimension;
2025}
2026
2027void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer)
2028{
2029    ASSERT(useTiledLayer != m_usingTiledLayer);
2030    RefPtr<PlatformCALayer> oldLayer = m_layer;
2031
2032    m_layer = PlatformCALayer::create(useTiledLayer ? PlatformCALayer::LayerTypeWebTiledLayer : PlatformCALayer::LayerTypeWebLayer, this);
2033    m_layer->setContentsScale(m_contentsScale);
2034
2035    m_usingTiledLayer = useTiledLayer;
2036
2037    if (useTiledLayer) {
2038#if !HAVE_MODERN_QUARTZCORE
2039        // Tiled layer has issues with flipped coordinates.
2040        setContentsOrientation(CompositingCoordinatesTopDown);
2041#endif
2042    } else {
2043#if !HAVE_MODERN_QUARTZCORE
2044        setContentsOrientation(GraphicsLayerCA::defaultContentsOrientation());
2045#endif
2046    }
2047
2048    m_layer->adoptSublayers(oldLayer.get());
2049
2050    // If m_layer doesn't have a parent, it means it's the root layer and
2051    // is likely hosted by something that is not expecting to be changed
2052    ASSERT(oldLayer->superlayer());
2053    oldLayer->superlayer()->replaceSublayer(oldLayer.get(), m_layer.get());
2054
2055    updateContentsTransform();
2056
2057    updateLayerPosition();
2058    updateLayerSize();
2059    updateAnchorPoint();
2060    updateTransform();
2061    updateChildrenTransform();
2062    updateMasksToBounds();
2063    updateContentsOpaque();
2064    updateBackfaceVisibility();
2065    updateLayerBackgroundColor();
2066
2067    updateOpacityOnLayer();
2068
2069#ifndef NDEBUG
2070    String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + m_name;
2071    m_layer->setName(name);
2072#endif
2073
2074    // move over animations
2075    moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, oldLayer.get(), m_layer.get());
2076    moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, oldLayer.get(), m_layer.get());
2077    moveOrCopyAnimationsForProperty(Move, AnimatedPropertyBackgroundColor, oldLayer.get(), m_layer.get());
2078
2079    // need to tell new layer to draw itself
2080    setNeedsDisplay();
2081
2082    updateDebugIndicators();
2083}
2084
2085GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const
2086{
2087#if !HAVE_MODERN_QUARTZCORE
2088    // Older QuartzCore does not support -geometryFlipped, so we manually flip the root
2089    // layer geometry, and then flip the contents of each layer back so that the CTM for CG
2090    // is unflipped, allowing it to do the correct font auto-hinting.
2091    return CompositingCoordinatesBottomUp;
2092#else
2093    return CompositingCoordinatesTopDown;
2094#endif
2095}
2096
2097void GraphicsLayerCA::updateContentsTransform()
2098{
2099#if !HAVE_MODERN_QUARTZCORE
2100    if (contentsOrientation() == CompositingCoordinatesBottomUp) {
2101        CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1);
2102        contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -m_layer->bounds().size().height());
2103        m_layer->setContentsTransform(TransformationMatrix(contentsTransform));
2104    }
2105#endif
2106}
2107
2108void GraphicsLayerCA::setupContentsLayer(PlatformCALayer* contentsLayer)
2109{
2110    // Turn off implicit animations on the inner layer.
2111    contentsLayer->setMasksToBounds(true);
2112
2113    if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) {
2114        TransformationMatrix flipper(
2115            1.0f, 0.0f, 0.0f, 0.0f,
2116            0.0f, -1.0f, 0.0f, 0.0f,
2117            0.0f, 0.0f, 1.0f, 0.0f,
2118            0.0f, 0.0f, 0.0f, 1.0f);
2119        contentsLayer->setTransform(flipper);
2120        contentsLayer->setAnchorPoint(FloatPoint3D(0, 1, 0));
2121    } else
2122        contentsLayer->setAnchorPoint(FloatPoint3D());
2123
2124    if (showDebugBorders()) {
2125        contentsLayer->setBorderColor(Color(0, 0, 128, 180));
2126        contentsLayer->setBorderWidth(1.0f);
2127    }
2128}
2129
2130PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, PlatformCALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel)
2131{
2132    if (!sourceLayer)
2133        return 0;
2134
2135    RefPtr<PlatformCALayer> resultLayer;
2136
2137    // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells
2138    // us whether there's an item there. This technique avoids two hash lookups.
2139    RefPtr<PlatformCALayer> dummy;
2140    pair<LayerMap::iterator, bool> addResult = clones->add(cloneID, dummy);
2141    if (!addResult.second) {
2142        // Value was not added, so it exists already.
2143        resultLayer = addResult.first->second.get();
2144    } else {
2145        resultLayer = cloneLayer(sourceLayer, cloneLevel);
2146#ifndef NDEBUG
2147        resultLayer->setName(String::format("Clone %d of layer %p", cloneID[0U], sourceLayer));
2148#endif
2149        addResult.first->second = resultLayer;
2150    }
2151
2152    return resultLayer;
2153}
2154
2155void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer, RefPtr<PlatformCALayer>& contentsLayer, CloneLevel cloneLevel)
2156{
2157    structuralLayer = 0;
2158    contentsLayer = 0;
2159
2160    if (!m_layerClones)
2161        m_layerClones = new LayerMap;
2162
2163    if (!m_structuralLayerClones && m_structuralLayer)
2164        m_structuralLayerClones = new LayerMap;
2165
2166    if (!m_contentsLayerClones && m_contentsLayer)
2167        m_contentsLayerClones = new LayerMap;
2168
2169    primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel);
2170    structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel);
2171    contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel);
2172}
2173
2174void GraphicsLayerCA::removeCloneLayers()
2175{
2176    m_layerClones = 0;
2177    m_structuralLayerClones = 0;
2178    m_contentsLayerClones = 0;
2179}
2180
2181FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const
2182{
2183    // This can get called during a sync when we've just removed the m_replicaLayer.
2184    if (!m_replicaLayer)
2185        return FloatPoint();
2186
2187    FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition();
2188    return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(),
2189                      replicaPosition.y() + m_anchorPoint.y() * m_size.height());
2190}
2191
2192void GraphicsLayerCA::propagateLayerChangeToReplicas()
2193{
2194    for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) {
2195        GraphicsLayerCA* currLayerCA = static_cast<GraphicsLayerCA*>(currLayer);
2196        if (!currLayerCA->hasCloneLayers())
2197            break;
2198
2199        if (currLayerCA->replicaLayer())
2200            static_cast<GraphicsLayerCA*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged);
2201    }
2202}
2203
2204PassRefPtr<PlatformCALayer> GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel)
2205{
2206    RefPtr<PlatformCALayer> primaryLayer;
2207    RefPtr<PlatformCALayer> structuralLayer;
2208    RefPtr<PlatformCALayer> contentsLayer;
2209    ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, cloneLevel);
2210
2211    if (m_maskLayer) {
2212        RefPtr<PlatformCALayer> maskClone = static_cast<GraphicsLayerCA*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
2213        primaryLayer->setMask(maskClone.get());
2214    }
2215
2216    if (m_replicatedLayer) {
2217        // We are a replica being asked for clones of our layers.
2218        RefPtr<PlatformCALayer> replicaRoot = replicatedLayerRoot(replicaState);
2219        if (!replicaRoot)
2220            return 0;
2221
2222        if (structuralLayer) {
2223            structuralLayer->insertSublayer(replicaRoot.get(), 0);
2224            return structuralLayer;
2225        }
2226
2227        primaryLayer->insertSublayer(replicaRoot.get(), 0);
2228        return primaryLayer;
2229    }
2230
2231    const Vector<GraphicsLayer*>& childLayers = children();
2232    Vector<RefPtr<PlatformCALayer> > clonalSublayers;
2233
2234    RefPtr<PlatformCALayer> replicaLayer;
2235
2236    if (m_replicaLayer && m_replicaLayer != replicaRoot) {
2237        // We have nested replicas. Ask the replica layer for a clone of its contents.
2238        replicaState.setBranchType(ReplicaState::ReplicaBranch);
2239        replicaLayer = static_cast<GraphicsLayerCA*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel);
2240        replicaState.setBranchType(ReplicaState::ChildBranch);
2241    }
2242
2243    if (replicaLayer || structuralLayer || contentsLayer || childLayers.size() > 0) {
2244        if (structuralLayer) {
2245            // Replicas render behind the actual layer content.
2246            if (replicaLayer)
2247                clonalSublayers.append(replicaLayer);
2248
2249            // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind.
2250            clonalSublayers.append(primaryLayer);
2251        } else if (contentsLayer) {
2252            // FIXME: add the contents layer in the correct order with negative z-order children.
2253            // This does not cause visible rendering issues because currently contents layers are only used
2254            // for replaced elements that don't have children.
2255            clonalSublayers.append(contentsLayer);
2256        }
2257
2258        replicaState.push(ReplicaState::ChildBranch);
2259
2260        size_t numChildren = childLayers.size();
2261        for (size_t i = 0; i < numChildren; ++i) {
2262            GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
2263
2264            RefPtr<PlatformCALayer> childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
2265            if (childLayer)
2266                clonalSublayers.append(childLayer);
2267        }
2268
2269        replicaState.pop();
2270
2271        for (size_t i = 0; i < clonalSublayers.size(); ++i)
2272            clonalSublayers[i]->removeFromSuperlayer();
2273    }
2274
2275    RefPtr<PlatformCALayer> result;
2276    if (structuralLayer) {
2277        structuralLayer->setSublayers(clonalSublayers);
2278
2279        if (contentsLayer) {
2280            // If we have a transform layer, then the contents layer is parented in the
2281            // primary layer (which is itself a child of the transform layer).
2282            primaryLayer->removeAllSublayers();
2283            primaryLayer->appendSublayer(contentsLayer.get());
2284        }
2285
2286        result = structuralLayer;
2287    } else {
2288        primaryLayer->setSublayers(clonalSublayers);
2289        result = primaryLayer;
2290    }
2291
2292    return result;
2293}
2294
2295PassRefPtr<PlatformCALayer> GraphicsLayerCA::cloneLayer(PlatformCALayer *layer, CloneLevel cloneLevel)
2296{
2297    PlatformCALayer::LayerType layerType = (layer->layerType() == PlatformCALayer::LayerTypeTransformLayer) ?
2298                                                PlatformCALayer::LayerTypeTransformLayer : PlatformCALayer::LayerTypeLayer;
2299    RefPtr<PlatformCALayer> newLayer = PlatformCALayer::create(layerType, this);
2300
2301    newLayer->setPosition(layer->position());
2302    newLayer->setBounds(layer->bounds());
2303    newLayer->setAnchorPoint(layer->anchorPoint());
2304    newLayer->setTransform(layer->transform());
2305    newLayer->setSublayerTransform(layer->sublayerTransform());
2306    newLayer->setContents(layer->contents());
2307    newLayer->setMasksToBounds(layer->masksToBounds());
2308    newLayer->setDoubleSided(layer->isDoubleSided());
2309    newLayer->setOpaque(layer->isOpaque());
2310    newLayer->setBackgroundColor(layer->backgroundColor());
2311    newLayer->setContentsScale(layer->contentsScale());
2312
2313    if (cloneLevel == IntermediateCloneLevel) {
2314        newLayer->setOpacity(layer->opacity());
2315        moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyWebkitTransform, layer, newLayer.get());
2316        moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyOpacity, layer, newLayer.get());
2317    }
2318
2319    if (showDebugBorders()) {
2320        newLayer->setBorderColor(Color(255, 122, 251));
2321        newLayer->setBorderWidth(2);
2322    }
2323
2324    return newLayer;
2325}
2326
2327void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity)
2328{
2329    LayerMap* layerCloneMap = 0;
2330
2331    if (preserves3D()) {
2332        m_layer->setOpacity(accumulatedOpacity);
2333        layerCloneMap = m_layerClones.get();
2334    } else {
2335        primaryLayer()->setOpacity(accumulatedOpacity);
2336        layerCloneMap = primaryLayerClones();
2337    }
2338
2339    if (layerCloneMap) {
2340        LayerMap::const_iterator end = layerCloneMap->end();
2341        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2342            if (m_replicaLayer && isReplicatedRootClone(it->first))
2343                continue;
2344            it->second->setOpacity(m_opacity);
2345        }
2346    }
2347}
2348
2349void GraphicsLayerCA::updateOpacityOnLayer()
2350{
2351#if !HAVE_MODERN_QUARTZCORE
2352    // Distribute opacity either to our own layer or to our children. We pass in the
2353    // contribution from our parent(s).
2354    distributeOpacity(parent() ? parent()->accumulatedOpacity() : 1);
2355#else
2356    primaryLayer()->setOpacity(m_opacity);
2357
2358    if (LayerMap* layerCloneMap = primaryLayerClones()) {
2359        LayerMap::const_iterator end = layerCloneMap->end();
2360        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2361            if (m_replicaLayer && isReplicatedRootClone(it->first))
2362                continue;
2363
2364            it->second->setOpacity(m_opacity);
2365        }
2366
2367    }
2368#endif
2369}
2370
2371void GraphicsLayerCA::noteSublayersChanged()
2372{
2373    noteLayerPropertyChanged(ChildrenChanged);
2374    propagateLayerChangeToReplicas();
2375}
2376
2377void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags)
2378{
2379    if (!m_uncommittedChanges && m_client)
2380        m_client->notifySyncRequired(this);
2381
2382    m_uncommittedChanges |= flags;
2383}
2384
2385} // namespace WebCore
2386
2387#endif // USE(ACCELERATED_COMPOSITING)
2388