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