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