d05dcc560a5624cdd18e94acac239063f1c03f88
[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 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 #include "GraphicsLayerCA.h"
29
30 #include "Animation.h"
31 #include "FloatConversion.h"
32 #include "FloatRect.h"
33 #include "GraphicsLayerFactory.h"
34 #include "Image.h"
35 #include "PlatformCAFilters.h"
36 #include "PlatformCALayer.h"
37 #include "RotateTransformOperation.h"
38 #include "ScaleTransformOperation.h"
39 #include "TextStream.h"
40 #include "TiledBacking.h"
41 #include "TransformState.h"
42 #include "TranslateTransformOperation.h"
43 #include <QuartzCore/CATransform3D.h>
44 #include <limits.h>
45 #include <wtf/CurrentTime.h>
46 #include <wtf/TemporaryChange.h>
47 #include <wtf/text/WTFString.h>
48
49 #if PLATFORM(IOS)
50 #include "SystemMemory.h"
51 #include "WebCoreThread.h"
52 #endif
53
54 #if PLATFORM(COCOA)
55 #include "PlatformCAAnimationMac.h"
56 #include "PlatformCALayerMac.h"
57 #include "WebCoreSystemInterface.h"
58 #endif
59
60 #if PLATFORM(WIN)
61 #include "PlatformCAAnimationWin.h"
62 #include "PlatformCALayerWin.h"
63 #endif
64
65 namespace WebCore {
66
67 // The threshold width or height above which a tiled layer will be used. This should be
68 // large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL
69 // texture size limit on all supported hardware.
70 #if PLATFORM(IOS)
71 static const int cMaxPixelDimension = 1280;
72 static const int cMaxPixelDimensionLowMemory = 1024;
73 static const int cMemoryLevelToUseSmallerPixelDimension = 35;
74 #else
75 static const int cMaxPixelDimension = 2000;
76 #endif
77
78 // Derived empirically: <rdar://problem/13401861>
79 static const int cMaxLayerTreeDepth = 250;
80
81 // If we send a duration of 0 to CA, then it will use the default duration
82 // of 250ms. So send a very small value instead.
83 static const float cAnimationAlmostZeroDuration = 1e-3f;
84
85 static inline bool isIntegral(float value)
86 {
87     return static_cast<int>(value) == value;
88 }
89
90 static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType)
91 {
92     switch (transformType) {
93     case TransformOperation::SKEW_X:
94     case TransformOperation::SKEW_Y:
95     case TransformOperation::SKEW:
96     case TransformOperation::MATRIX:
97     case TransformOperation::ROTATE_3D:
98     case TransformOperation::MATRIX_3D:
99     case TransformOperation::PERSPECTIVE:
100     case TransformOperation::IDENTITY:
101     case TransformOperation::NONE:
102         return true;
103     default:
104         return false;
105     }
106 }
107
108 static bool isTransformTypeFloatPoint3D(TransformOperation::OperationType transformType)
109 {
110     switch (transformType) {
111     case TransformOperation::SCALE:
112     case TransformOperation::SCALE_3D:
113     case TransformOperation::TRANSLATE:
114     case TransformOperation::TRANSLATE_3D:
115         return true;
116     default:
117         return false;
118     }
119 }
120
121 static bool isTransformTypeNumber(TransformOperation::OperationType transformType)
122 {
123     return !isTransformTypeTransformationMatrix(transformType) && !isTransformTypeFloatPoint3D(transformType);
124 }
125
126 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const FloatSize& size, float& value)
127 {
128     switch (transformType) {
129     case TransformOperation::ROTATE:
130     case TransformOperation::ROTATE_X:
131     case TransformOperation::ROTATE_Y:
132         value = transformOp ? narrowPrecisionToFloat(deg2rad(toRotateTransformOperation(transformOp)->angle())) : 0;
133         break;
134     case TransformOperation::SCALE_X:
135         value = transformOp ? narrowPrecisionToFloat(toScaleTransformOperation(transformOp)->x()) : 1;
136         break;
137     case TransformOperation::SCALE_Y:
138         value = transformOp ? narrowPrecisionToFloat(toScaleTransformOperation(transformOp)->y()) : 1;
139         break;
140     case TransformOperation::SCALE_Z:
141         value = transformOp ? narrowPrecisionToFloat(toScaleTransformOperation(transformOp)->z()) : 1;
142         break;
143     case TransformOperation::TRANSLATE_X:
144         value = transformOp ? narrowPrecisionToFloat(toTranslateTransformOperation(transformOp)->x(size)) : 0;
145         break;
146     case TransformOperation::TRANSLATE_Y:
147         value = transformOp ? narrowPrecisionToFloat(toTranslateTransformOperation(transformOp)->y(size)) : 0;
148         break;
149     case TransformOperation::TRANSLATE_Z:
150         value = transformOp ? narrowPrecisionToFloat(toTranslateTransformOperation(transformOp)->z(size)) : 0;
151         break;
152     default:
153         break;
154     }
155 }
156
157 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const FloatSize& size, FloatPoint3D& value)
158 {
159     switch (transformType) {
160     case TransformOperation::SCALE:
161     case TransformOperation::SCALE_3D: {
162         const ScaleTransformOperation* scaleTransformOp = toScaleTransformOperation(transformOp);
163         value.setX(scaleTransformOp ? narrowPrecisionToFloat(scaleTransformOp->x()) : 1);
164         value.setY(scaleTransformOp ? narrowPrecisionToFloat(scaleTransformOp->y()) : 1);
165         value.setZ(scaleTransformOp ? narrowPrecisionToFloat(scaleTransformOp->z()) : 1);
166         break;
167     }
168     case TransformOperation::TRANSLATE:
169     case TransformOperation::TRANSLATE_3D: {
170         const TranslateTransformOperation* translateTransformOp = toTranslateTransformOperation(transformOp);
171         value.setX(translateTransformOp ? narrowPrecisionToFloat(translateTransformOp->x(size)) : 0);
172         value.setY(translateTransformOp ? narrowPrecisionToFloat(translateTransformOp->y(size)) : 0);
173         value.setZ(translateTransformOp ? narrowPrecisionToFloat(translateTransformOp->z(size)) : 0);
174         break;
175     }
176     default:
177         break;
178     }
179 }
180
181 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const FloatSize& size, TransformationMatrix& value)
182 {
183     switch (transformType) {
184     case TransformOperation::SKEW_X:
185     case TransformOperation::SKEW_Y:
186     case TransformOperation::SKEW:
187     case TransformOperation::MATRIX:
188     case TransformOperation::ROTATE_3D:
189     case TransformOperation::MATRIX_3D:
190     case TransformOperation::PERSPECTIVE:
191     case TransformOperation::IDENTITY:
192     case TransformOperation::NONE:
193         if (transformOp)
194             transformOp->apply(value, size);
195         else
196             value.makeIdentity();
197         break;
198     default:
199         break;
200     }
201 }
202
203 static PlatformCAAnimation::ValueFunctionType getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType)
204 {
205     // Use literal strings to avoid link-time dependency on those symbols.
206     switch (transformType) {
207     case TransformOperation::ROTATE_X:
208         return PlatformCAAnimation::RotateX;
209     case TransformOperation::ROTATE_Y:
210         return PlatformCAAnimation::RotateY;
211     case TransformOperation::ROTATE:
212         return PlatformCAAnimation::RotateZ;
213     case TransformOperation::SCALE_X:
214         return PlatformCAAnimation::ScaleX;
215     case TransformOperation::SCALE_Y:
216         return PlatformCAAnimation::ScaleY;
217     case TransformOperation::SCALE_Z:
218         return PlatformCAAnimation::ScaleZ;
219     case TransformOperation::TRANSLATE_X:
220         return PlatformCAAnimation::TranslateX;
221     case TransformOperation::TRANSLATE_Y:
222         return PlatformCAAnimation::TranslateY;
223     case TransformOperation::TRANSLATE_Z:
224         return PlatformCAAnimation::TranslateZ;
225     case TransformOperation::SCALE:
226     case TransformOperation::SCALE_3D:
227         return PlatformCAAnimation::Scale;
228     case TransformOperation::TRANSLATE:
229     case TransformOperation::TRANSLATE_3D:
230         return PlatformCAAnimation::Translate;
231     default:
232         return PlatformCAAnimation::NoValueFunction;
233     }
234 }
235
236 static String propertyIdToString(AnimatedPropertyID property)
237 {
238     switch (property) {
239     case AnimatedPropertyWebkitTransform:
240         return "transform";
241     case AnimatedPropertyOpacity:
242         return "opacity";
243     case AnimatedPropertyBackgroundColor:
244         return "backgroundColor";
245     case AnimatedPropertyWebkitFilter:
246 #if ENABLE(CSS_FILTERS)
247         return "filters";
248 #else
249         ASSERT_NOT_REACHED();
250 #endif
251     case AnimatedPropertyInvalid:
252         ASSERT_NOT_REACHED();
253     }
254     ASSERT_NOT_REACHED();
255     return "";
256 }
257
258 static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index, int subIndex)
259 {
260     return animationName + '_' + String::number(property) + '_' + String::number(index) + '_' + String::number(subIndex);
261 }
262
263 static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim)
264 {
265     if (anim->timingFunction()->isStepsTimingFunction())
266         return true;
267     
268     for (unsigned i = 0; i < valueList.size(); ++i) {
269         if (const TimingFunction* timingFunction = valueList.at(i).timingFunction()) {
270             if (timingFunction->isStepsTimingFunction())
271                 return true;
272         }
273     }
274
275     return false;
276 }
277
278 #if ENABLE(CSS_FILTERS) || !ASSERT_DISABLED
279 static inline bool supportsAcceleratedFilterAnimations()
280 {
281 // <rdar://problem/10907251> - WebKit2 doesn't support CA animations of CI filters on Lion and below
282 #if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
283     return true;
284 #else
285     return false;
286 #endif
287 }
288 #endif
289
290 std::unique_ptr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client)
291 {
292     std::unique_ptr<GraphicsLayer> graphicsLayer;
293     if (!factory)
294         graphicsLayer = std::make_unique<GraphicsLayerCA>(client);
295     else
296         graphicsLayer = factory->createGraphicsLayer(client);
297
298     graphicsLayer->initialize();
299
300     return graphicsLayer;
301 }
302
303 #if ENABLE(CSS_FILTERS)
304 bool GraphicsLayerCA::filtersCanBeComposited(const FilterOperations& filters)
305 {
306 #if PLATFORM(COCOA)
307     return PlatformCALayerMac::filtersCanBeComposited(filters);
308 #elif PLATFORM(WIN)
309     return PlatformCALayerWin::filtersCanBeComposited(filters);
310 #endif
311 }
312 #endif
313     
314 PassRefPtr<PlatformCALayer> GraphicsLayerCA::createPlatformCALayer(PlatformCALayer::LayerType layerType, PlatformCALayerClient* owner)
315 {
316 #if PLATFORM(COCOA)
317     return PlatformCALayerMac::create(layerType, owner);
318 #elif PLATFORM(WIN)
319     return PlatformCALayerWin::create(layerType, owner);
320 #endif
321 }
322     
323 PassRefPtr<PlatformCALayer> GraphicsLayerCA::createPlatformCALayer(PlatformLayer* platformLayer, PlatformCALayerClient* owner)
324 {
325 #if PLATFORM(COCOA)
326     return PlatformCALayerMac::create(platformLayer, owner);
327 #elif PLATFORM(WIN)
328     return PlatformCALayerWin::create(platformLayer, owner);
329 #endif
330 }
331
332 PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createPlatformCAAnimation(PlatformCAAnimation::AnimationType type, const String& keyPath)
333 {
334 #if PLATFORM(COCOA)
335     return PlatformCAAnimationMac::create(type, keyPath);
336 #elif PLATFORM(WIN)
337     return PlatformCAAnimationWin::create(type, keyPath);
338 #endif
339 }
340
341 GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient& client)
342     : GraphicsLayer(client)
343     , m_contentsLayerPurpose(NoContentsLayer)
344     , m_isPageTiledBackingLayer(false)
345     , m_needsFullRepaint(false)
346     , m_uncommittedChanges(0)
347     , m_isCommittingChanges(false)
348 {
349 }
350
351 void GraphicsLayerCA::initialize()
352 {
353     PlatformCALayer::LayerType layerType = PlatformCALayer::LayerTypeWebLayer;
354     if (client().shouldUseTiledBacking(this)) {
355         layerType = PlatformCALayer::LayerTypePageTiledBackingLayer;
356         m_isPageTiledBackingLayer = true;
357     }
358
359     m_layer = createPlatformCALayer(layerType, this);
360     noteLayerPropertyChanged(ContentsScaleChanged);
361 }
362
363 GraphicsLayerCA::~GraphicsLayerCA()
364 {
365     // Do cleanup while we can still safely call methods on the derived class.
366     willBeDestroyed();
367 }
368
369 void GraphicsLayerCA::willBeDestroyed()
370 {
371     // We release our references to the PlatformCALayers here, but do not actively unparent them,
372     // since that will cause a commit and break our batched commit model. The layers will
373     // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers.
374
375     // Clean up the layer.
376     if (m_layer)
377         m_layer->setOwner(nullptr);
378     
379     if (m_contentsLayer)
380         m_contentsLayer->setOwner(nullptr);
381
382     if (m_contentsClippingLayer)
383         m_contentsClippingLayer->setOwner(nullptr);
384         
385     if (m_structuralLayer)
386         m_structuralLayer->setOwner(nullptr);
387     
388     removeCloneLayers();
389
390     GraphicsLayer::willBeDestroyed();
391 }
392
393 void GraphicsLayerCA::setName(const String& name)
394 {
395     String caLayerDescription;
396
397     if (!m_layer->isPlatformCALayerRemote())
398         caLayerDescription = String::format("CALayer(%p) ", m_layer->platformLayer());
399
400     String longName = caLayerDescription + String::format("GraphicsLayer(%p) ", this) + name;
401     GraphicsLayer::setName(longName);
402     noteLayerPropertyChanged(NameChanged);
403 }
404
405 GraphicsLayer::PlatformLayerID GraphicsLayerCA::primaryLayerID() const
406 {
407     return primaryLayer()->layerID();
408 }
409
410 PlatformLayer* GraphicsLayerCA::platformLayer() const
411 {
412     return primaryLayer()->platformLayer();
413 }
414
415 bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children)
416 {
417     bool childrenChanged = GraphicsLayer::setChildren(children);
418     if (childrenChanged)
419         noteSublayersChanged();
420     
421     return childrenChanged;
422 }
423
424 void GraphicsLayerCA::addChild(GraphicsLayer* childLayer)
425 {
426     GraphicsLayer::addChild(childLayer);
427     noteSublayersChanged();
428 }
429
430 void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index)
431 {
432     GraphicsLayer::addChildAtIndex(childLayer, index);
433     noteSublayersChanged();
434 }
435
436 void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
437 {
438     GraphicsLayer::addChildBelow(childLayer, sibling);
439     noteSublayersChanged();
440 }
441
442 void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
443 {
444     GraphicsLayer::addChildAbove(childLayer, sibling);
445     noteSublayersChanged();
446 }
447
448 bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
449 {
450     if (GraphicsLayer::replaceChild(oldChild, newChild)) {
451         noteSublayersChanged();
452         return true;
453     }
454     return false;
455 }
456
457 void GraphicsLayerCA::removeFromParent()
458 {
459     if (m_parent)
460         toGraphicsLayerCA(m_parent)->noteSublayersChanged();
461     GraphicsLayer::removeFromParent();
462 }
463
464 void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer)
465 {
466     if (layer == m_maskLayer)
467         return;
468
469     GraphicsLayer::setMaskLayer(layer);
470     noteLayerPropertyChanged(MaskLayerChanged);
471
472     propagateLayerChangeToReplicas();
473     
474     if (m_replicatedLayer)
475         toGraphicsLayerCA(m_replicatedLayer)->propagateLayerChangeToReplicas();
476 }
477
478 void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer)
479 {
480     if (layer == m_replicatedLayer)
481         return;
482
483     GraphicsLayer::setReplicatedLayer(layer);
484     noteLayerPropertyChanged(ReplicatedLayerChanged);
485 }
486
487 void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer)
488 {
489     if (layer == m_replicaLayer)
490         return;
491
492     GraphicsLayer::setReplicatedByLayer(layer);
493     noteSublayersChanged();
494     noteLayerPropertyChanged(ReplicatedLayerChanged);
495 }
496
497 void GraphicsLayerCA::setPosition(const FloatPoint& point)
498 {
499     if (point == m_position)
500         return;
501
502     GraphicsLayer::setPosition(point);
503     noteLayerPropertyChanged(GeometryChanged);
504 }
505
506 void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point)
507 {
508     if (point == m_anchorPoint)
509         return;
510
511     GraphicsLayer::setAnchorPoint(point);
512     noteLayerPropertyChanged(GeometryChanged);
513 }
514
515 void GraphicsLayerCA::setSize(const FloatSize& size)
516 {
517     if (size == m_size)
518         return;
519
520     GraphicsLayer::setSize(size);
521     noteLayerPropertyChanged(GeometryChanged);
522 }
523
524 void GraphicsLayerCA::setBoundsOrigin(const FloatPoint& origin)
525 {
526     if (origin == m_boundsOrigin)
527         return;
528
529     GraphicsLayer::setBoundsOrigin(origin);
530     noteLayerPropertyChanged(GeometryChanged);
531 }
532
533 void GraphicsLayerCA::setTransform(const TransformationMatrix& t)
534 {
535     if (t == m_transform)
536         return;
537
538     GraphicsLayer::setTransform(t);
539     noteLayerPropertyChanged(TransformChanged);
540 }
541
542 void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t)
543 {
544     if (t == m_childrenTransform)
545         return;
546
547     GraphicsLayer::setChildrenTransform(t);
548     noteLayerPropertyChanged(ChildrenTransformChanged);
549 }
550
551 void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
552 {
553     RefPtr<PlatformCAAnimation> anim = fromLayer->animationForKey(animationIdentifier);
554     if (!anim)
555         return;
556
557     switch (operation) {
558     case Move:
559         fromLayer->removeAnimationForKey(animationIdentifier);
560         toLayer->addAnimationForKey(animationIdentifier, anim.get());
561         break;
562
563     case Copy:
564         toLayer->addAnimationForKey(animationIdentifier, anim.get());
565         break;
566     }
567 }
568
569 void GraphicsLayerCA::moveOrCopyAnimations(MoveOrCopy operation, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
570 {
571     // Look for running animations affecting this property.
572     AnimationsMap::const_iterator end = m_runningAnimations.end();
573     for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
574         const Vector<LayerPropertyAnimation>& propertyAnimations = it->value;
575         size_t numAnimations = propertyAnimations.size();
576         for (size_t i = 0; i < numAnimations; ++i) {
577             const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
578             
579             if (currAnimation.m_property == AnimatedPropertyWebkitTransform || currAnimation.m_property == AnimatedPropertyOpacity
580                     || currAnimation.m_property == AnimatedPropertyBackgroundColor
581 #if ENABLE(CSS_FILTERS)
582                     || currAnimation.m_property == AnimatedPropertyWebkitFilter
583 #endif
584                 )
585                 moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index, currAnimation.m_subIndex), fromLayer, toLayer);
586         }
587     }
588 }
589
590 void GraphicsLayerCA::setPreserves3D(bool preserves3D)
591 {
592     if (preserves3D == m_preserves3D)
593         return;
594
595     GraphicsLayer::setPreserves3D(preserves3D);
596     noteLayerPropertyChanged(Preserves3DChanged);
597 }
598
599 void GraphicsLayerCA::setMasksToBounds(bool masksToBounds)
600 {
601     if (masksToBounds == m_masksToBounds)
602         return;
603
604     GraphicsLayer::setMasksToBounds(masksToBounds);
605     noteLayerPropertyChanged(MasksToBoundsChanged | DebugIndicatorsChanged);
606 }
607
608 void GraphicsLayerCA::setDrawsContent(bool drawsContent)
609 {
610     if (drawsContent == m_drawsContent)
611         return;
612
613     GraphicsLayer::setDrawsContent(drawsContent);
614     noteLayerPropertyChanged(DrawsContentChanged | DebugIndicatorsChanged);
615 }
616
617 void GraphicsLayerCA::setContentsVisible(bool contentsVisible)
618 {
619     if (contentsVisible == m_contentsVisible)
620         return;
621
622     GraphicsLayer::setContentsVisible(contentsVisible);
623     noteLayerPropertyChanged(ContentsVisibilityChanged);
624     // Visibility affects whether the contentsLayer is parented.
625     if (m_contentsLayer)
626         noteSublayersChanged();
627 }
628
629 void GraphicsLayerCA::setAcceleratesDrawing(bool acceleratesDrawing)
630 {
631     if (acceleratesDrawing == m_acceleratesDrawing)
632         return;
633
634     GraphicsLayer::setAcceleratesDrawing(acceleratesDrawing);
635     noteLayerPropertyChanged(AcceleratesDrawingChanged);
636 }
637
638 void GraphicsLayerCA::setBackgroundColor(const Color& color)
639 {
640     if (m_backgroundColor == color)
641         return;
642
643     GraphicsLayer::setBackgroundColor(color);
644     noteLayerPropertyChanged(BackgroundColorChanged);
645 }
646
647 void GraphicsLayerCA::setContentsOpaque(bool opaque)
648 {
649     if (m_contentsOpaque == opaque)
650         return;
651
652     GraphicsLayer::setContentsOpaque(opaque);
653     noteLayerPropertyChanged(ContentsOpaqueChanged);
654 }
655
656 void GraphicsLayerCA::setBackfaceVisibility(bool visible)
657 {
658     if (m_backfaceVisibility == visible)
659         return;
660     
661     GraphicsLayer::setBackfaceVisibility(visible);
662     noteLayerPropertyChanged(BackfaceVisibilityChanged);
663 }
664
665 void GraphicsLayerCA::setOpacity(float opacity)
666 {
667     float clampedOpacity = std::max(0.0f, std::min(opacity, 1.0f));
668
669     if (clampedOpacity == m_opacity)
670         return;
671
672     GraphicsLayer::setOpacity(clampedOpacity);
673     noteLayerPropertyChanged(OpacityChanged);
674 }
675
676 #if ENABLE(CSS_FILTERS)
677 bool GraphicsLayerCA::setFilters(const FilterOperations& filterOperations)
678 {
679     bool canCompositeFilters = filtersCanBeComposited(filterOperations);
680
681     if (m_filters == filterOperations)
682         return canCompositeFilters;
683
684     // Filters cause flattening, so we should never have filters on a layer with preserves3D().
685     ASSERT(!filterOperations.size() || !preserves3D());
686
687     if (canCompositeFilters) {
688         GraphicsLayer::setFilters(filterOperations);
689         noteLayerPropertyChanged(FiltersChanged);
690     } else if (filters().size()) {
691         // In this case filters are rendered in software, so we need to remove any 
692         // previously attached hardware filters.
693         clearFilters();
694         noteLayerPropertyChanged(FiltersChanged);
695     }
696     return canCompositeFilters;
697 }
698 #endif
699
700 #if ENABLE(CSS_COMPOSITING)
701 void GraphicsLayerCA::setBlendMode(BlendMode blendMode)
702 {
703     if (GraphicsLayer::blendMode() == blendMode)
704         return;
705
706     GraphicsLayer::setBlendMode(blendMode);
707     noteLayerPropertyChanged(BlendModeChanged);
708 }
709 #endif
710
711 void GraphicsLayerCA::setNeedsDisplay()
712 {
713     if (!drawsContent())
714         return;
715
716     m_needsFullRepaint = true;
717     m_dirtyRects.clear();
718     noteLayerPropertyChanged(DirtyRectsChanged);
719     addRepaintRect(FloatRect(FloatPoint(), m_size));
720 }
721
722 void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& r, ShouldClipToLayer shouldClip)
723 {
724     if (!drawsContent())
725         return;
726
727     if (m_needsFullRepaint)
728         return;
729
730     FloatRect rect(r);
731     if (shouldClip == ClipToLayer) {
732         FloatRect layerBounds(FloatPoint(), m_size);
733         rect.intersect(layerBounds);
734     }
735
736     if (rect.isEmpty())
737         return;
738     
739     const size_t maxDirtyRects = 32;
740     
741     for (size_t i = 0; i < m_dirtyRects.size(); ++i) {
742         if (m_dirtyRects[i].contains(rect))
743             return;
744     }
745     
746     if (m_dirtyRects.size() < maxDirtyRects)
747         m_dirtyRects.append(rect);
748     else
749         m_dirtyRects[0].unite(rect);
750
751     noteLayerPropertyChanged(DirtyRectsChanged);
752
753     addRepaintRect(rect);
754 }
755
756 void GraphicsLayerCA::setContentsNeedsDisplay()
757 {
758     noteLayerPropertyChanged(ContentsNeedsDisplay);
759 }
760
761 void GraphicsLayerCA::setContentsRect(const FloatRect& rect)
762 {
763     if (rect == m_contentsRect)
764         return;
765
766     GraphicsLayer::setContentsRect(rect);
767     noteLayerPropertyChanged(ContentsRectsChanged);
768 }
769
770 void GraphicsLayerCA::setContentsClippingRect(const FloatRect& rect)
771 {
772     if (rect == m_contentsClippingRect)
773         return;
774
775     GraphicsLayer::setContentsClippingRect(rect);
776     noteLayerPropertyChanged(ContentsRectsChanged);
777 }
778
779 bool GraphicsLayerCA::shouldRepaintOnSizeChange() const
780 {
781     return drawsContent() && !tiledBacking();
782 }
783
784 bool GraphicsLayerCA::animationCanBeAccelerated(const KeyframeValueList& valueList, const Animation* anim) const
785 {
786     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
787         return false;
788
789     if (animationHasStepsTimingFunction(valueList, anim))
790         return false;
791
792     return true;
793 }
794
795 bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& animationName, double timeOffset)
796 {
797     ASSERT(!animationName.isEmpty());
798
799     if (!animationCanBeAccelerated(valueList, anim))
800         return false;
801
802     bool createdAnimations = false;
803     if (valueList.property() == AnimatedPropertyWebkitTransform)
804         createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize);
805 #if ENABLE(CSS_FILTERS)
806     else if (valueList.property() == AnimatedPropertyWebkitFilter) {
807         if (supportsAcceleratedFilterAnimations())
808             createdAnimations = createFilterAnimationsFromKeyframes(valueList, anim, animationName, timeOffset);
809     }
810 #endif
811     else
812         createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset);
813
814     if (createdAnimations)
815         noteLayerPropertyChanged(AnimationChanged);
816         
817     return createdAnimations;
818 }
819
820 void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset)
821 {
822     if (!animationIsRunning(animationName))
823         return;
824
825     AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName);
826     if (it != m_animationsToProcess.end()) {
827         AnimationProcessingAction& processingInfo = it->value;
828         // If an animation is scheduled to be removed, don't change the remove to a pause.
829         if (processingInfo.action != Remove)
830             processingInfo.action = Pause;
831     } else
832         m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset));
833
834     noteLayerPropertyChanged(AnimationChanged);
835 }
836
837 void GraphicsLayerCA::removeAnimation(const String& animationName)
838 {
839     if (!animationIsRunning(animationName))
840         return;
841
842     m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove));
843     noteLayerPropertyChanged(AnimationChanged);
844 }
845
846 void GraphicsLayerCA::platformCALayerAnimationStarted(const String& animationKey, CFTimeInterval startTime)
847 {
848     client().notifyAnimationStarted(this, animationKey, startTime);
849 }
850
851 void GraphicsLayerCA::platformCALayerAnimationEnded(const String& animationKey)
852 {
853     client().notifyAnimationEnded(this, animationKey);
854 }
855
856 void GraphicsLayerCA::setContentsToSolidColor(const Color& color)
857 {
858     if (color == m_contentsSolidColor)
859         return;
860
861     m_contentsSolidColor = color;
862     
863     bool contentsLayerChanged = false;
864
865     if (m_contentsSolidColor.isValid() && m_contentsSolidColor.alpha()) {
866         if (!m_contentsLayer || m_contentsLayerPurpose != ContentsLayerForBackgroundColor) {
867             m_contentsLayerPurpose = ContentsLayerForBackgroundColor;
868             m_contentsLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
869 #ifndef NDEBUG
870             m_contentsLayer->setName("Background Color Layer");
871 #endif
872             contentsLayerChanged = true;
873         }
874     } else {
875         contentsLayerChanged = m_contentsLayer;
876         m_contentsLayerPurpose = NoContentsLayer;
877         m_contentsLayer = 0;
878     }
879
880     if (contentsLayerChanged)
881         noteSublayersChanged();
882
883     noteLayerPropertyChanged(ContentsColorLayerChanged);
884 }
885
886 void GraphicsLayerCA::setContentsToImage(Image* image)
887 {
888     if (image) {
889         CGImageRef newImage = image->nativeImageForCurrentFrame();
890         if (!newImage)
891             return;
892
893         // Check to see if the image changed; we have to do this because the call to
894         // CGImageCreateCopyWithColorSpace() below can create a new image every time.
895         if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage)
896             return;
897         
898         m_uncorrectedContentsImage = newImage;
899         m_pendingContentsImage = newImage;
900
901 #if !PLATFORM(WIN) && !PLATFORM(IOS)
902         CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get());
903
904         static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
905         if (colorSpace && CFEqual(colorSpace, deviceRGB)) {
906             // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such
907             // images to CA we need to tag them similarly so CA rendering matches CG rendering.
908             static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
909             m_pendingContentsImage = adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB));
910         }
911 #endif
912         m_contentsLayerPurpose = ContentsLayerForImage;
913         if (!m_contentsLayer)
914             noteSublayersChanged();
915     } else {
916         m_uncorrectedContentsImage = 0;
917         m_pendingContentsImage = 0;
918         m_contentsLayerPurpose = NoContentsLayer;
919         if (m_contentsLayer)
920             noteSublayersChanged();
921     }
922
923     noteLayerPropertyChanged(ContentsImageChanged);
924 }
925
926 void GraphicsLayerCA::setContentsToPlatformLayer(PlatformLayer* platformLayer, ContentsLayerPurpose purpose)
927 {
928     if (m_contentsLayer && platformLayer == m_contentsLayer->platformLayer())
929         return;
930
931     // FIXME: The passed in layer might be a raw layer or an externally created
932     // PlatformCALayer. To determine this we attempt to get the
933     // PlatformCALayer pointer. If this returns a null pointer we assume it's
934     // raw. This test might be invalid if the raw layer is, for instance, the
935     // PlatformCALayer is using a user data pointer in the raw layer, and
936     // the creator of the raw layer is using it for some other purpose.
937     // For now we don't support such a case.
938     PlatformCALayer* platformCALayer = PlatformCALayer::platformCALayer(platformLayer);
939     m_contentsLayer = platformLayer ? (platformCALayer ? platformCALayer : createPlatformCALayer(platformLayer, this)) : 0;
940     m_contentsLayerPurpose = platformLayer ? purpose : NoContentsLayer;
941
942     noteSublayersChanged();
943     noteLayerPropertyChanged(ContentsPlatformLayerChanged);
944 }
945
946 #if PLATFORM(IOS)
947 PlatformLayer* GraphicsLayerCA::contentsLayerForMedia() const
948 {
949     return m_contentsLayerPurpose == ContentsLayerForMedia ? m_contentsLayer->platformLayer() : nullptr;
950 }
951 #endif
952
953 void GraphicsLayerCA::layerDidDisplay(PlatformCALayer* layer)
954 {
955     LayerMap* layerCloneMap;
956
957     if (layer == m_layer)
958         layerCloneMap = m_layerClones.get();
959     else if (layer == m_contentsLayer)
960         layerCloneMap = m_contentsLayerClones.get();
961     else
962         return;
963
964     if (layerCloneMap) {
965         LayerMap::const_iterator end = layerCloneMap->end();
966         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
967             PlatformCALayer* currClone = it->value.get();
968             if (!currClone)
969                 continue;
970
971             currClone->copyContentsFromLayer(layer);
972         }
973     }
974 }
975
976 FloatPoint GraphicsLayerCA::computePositionRelativeToBase(float& pageScale) const
977 {
978     pageScale = 1;
979
980     FloatPoint offset;
981     for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) {
982         if (currLayer->appliesPageScale()) {
983             pageScale = currLayer->pageScaleFactor();
984             return offset;
985         }
986
987         offset += currLayer->position();
988     }
989
990     return FloatPoint();
991 }
992
993 void GraphicsLayerCA::flushCompositingState(const FloatRect& clipRect)
994 {
995     TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(clipRect));
996     recursiveCommitChanges(CommitState(), state);
997 }
998
999 void GraphicsLayerCA::flushCompositingStateForThisLayerOnly()
1000 {
1001     float pageScaleFactor;
1002     bool hadChanges = m_uncommittedChanges;
1003     
1004     CommitState commitState;
1005
1006     FloatPoint offset = computePositionRelativeToBase(pageScaleFactor);
1007     commitLayerChangesBeforeSublayers(commitState, pageScaleFactor, offset, m_visibleRect);
1008     commitLayerChangesAfterSublayers(commitState);
1009
1010     if (hadChanges)
1011         client().didCommitChangesForLayer(this);
1012 }
1013
1014 bool GraphicsLayerCA::recursiveVisibleRectChangeRequiresFlush(const TransformState& state) const
1015 {
1016     TransformState localState = state;
1017     
1018     // This may be called at times when layout has not been updated, so we want to avoid calling out to the client
1019     // for animating transforms.
1020     FloatRect newVisibleRect = computeVisibleRect(localState, 0);
1021     if (m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
1022         newVisibleRect = adjustTiledLayerVisibleRect(tiledBacking(), m_visibleRect, newVisibleRect, m_sizeAtLastVisibleRectUpdate, m_size);
1023
1024     if (newVisibleRect != m_visibleRect) {
1025         if (TiledBacking* tiledBacking = this->tiledBacking()) {
1026             if (tiledBacking->tilesWouldChangeForVisibleRect(newVisibleRect))
1027                 return true;
1028         }
1029     }
1030
1031     if (m_maskLayer) {
1032         GraphicsLayerCA* maskLayerCA = toGraphicsLayerCA(m_maskLayer);
1033         if (maskLayerCA->recursiveVisibleRectChangeRequiresFlush(localState))
1034             return true;
1035     }
1036
1037     const Vector<GraphicsLayer*>& childLayers = children();
1038     size_t numChildren = childLayers.size();
1039     
1040     for (size_t i = 0; i < numChildren; ++i) {
1041         GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
1042         if (curChild->recursiveVisibleRectChangeRequiresFlush(localState))
1043             return true;
1044     }
1045
1046     if (m_replicaLayer)
1047         if (toGraphicsLayerCA(m_replicaLayer)->recursiveVisibleRectChangeRequiresFlush(localState))
1048             return true;
1049     
1050     return false;
1051 }
1052
1053 bool GraphicsLayerCA::visibleRectChangeRequiresFlush(const FloatRect& clipRect) const
1054 {
1055     TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(clipRect));
1056     return recursiveVisibleRectChangeRequiresFlush(state);
1057 }
1058
1059 TiledBacking* GraphicsLayerCA::tiledBacking() const
1060 {
1061     return m_layer->tiledBacking();
1062 }
1063
1064 TransformationMatrix GraphicsLayerCA::layerTransform(const FloatPoint& position, const TransformationMatrix* customTransform) const
1065 {
1066     TransformationMatrix transform;
1067     transform.translate(position.x(), position.y());
1068
1069     TransformationMatrix currentTransform = customTransform ? *customTransform : m_transform;
1070     
1071     if (!currentTransform.isIdentity()) {
1072         FloatPoint3D absoluteAnchorPoint(anchorPoint());
1073         absoluteAnchorPoint.scale(size().width(), size().height(), 1);
1074         transform.translate3d(absoluteAnchorPoint.x(), absoluteAnchorPoint.y(), absoluteAnchorPoint.z());
1075         transform.multiply(currentTransform);
1076         transform.translate3d(-absoluteAnchorPoint.x(), -absoluteAnchorPoint.y(), -absoluteAnchorPoint.z());
1077     }
1078
1079     if (GraphicsLayer* parentLayer = parent()) {
1080         if (!parentLayer->childrenTransform().isIdentity()) {
1081             FloatPoint3D parentAnchorPoint(parentLayer->anchorPoint());
1082             parentAnchorPoint.scale(parentLayer->size().width(), parentLayer->size().height(), 1);
1083
1084             transform.translateRight3d(-parentAnchorPoint.x(), -parentAnchorPoint.y(), -parentAnchorPoint.z());
1085             transform = parentLayer->childrenTransform() * transform;
1086             transform.translateRight3d(parentAnchorPoint.x(), parentAnchorPoint.y(), parentAnchorPoint.z());
1087         }
1088     }
1089     
1090     return transform;
1091 }
1092
1093 FloatRect GraphicsLayerCA::computeVisibleRect(TransformState& state, ComputeVisibleRectFlags flags) const
1094 {
1095     bool preserve3D = preserves3D() || (parent() ? parent()->preserves3D() : false);
1096     TransformState::TransformAccumulation accumulation = preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform;
1097
1098     FloatPoint position = m_position;
1099     client().customPositionForVisibleRectComputation(this, position);
1100
1101     TransformationMatrix layerTransform;
1102     TransformationMatrix currentTransform;
1103     if ((flags & RespectAnimatingTransforms) && client().getCurrentTransform(this, currentTransform))
1104         layerTransform = this->layerTransform(position, &currentTransform);
1105     else
1106         layerTransform = this->layerTransform(position);
1107
1108     bool applyWasClamped;
1109     state.applyTransform(layerTransform, accumulation, &applyWasClamped);
1110
1111     bool mapWasClamped;
1112     FloatRect clipRectForChildren = state.mappedQuad(&mapWasClamped).boundingBox();
1113     FloatPoint boundsOrigin = m_boundsOrigin;
1114 #if PLATFORM(IOS)
1115     // In WK1, UIKit may be changing layer bounds behind our back in overflow-scroll layers, so use the layer's origin.
1116     if (m_layer->isPlatformCALayerMac())
1117         boundsOrigin = m_layer->bounds().location();
1118 #endif
1119     clipRectForChildren.move(boundsOrigin.x(), boundsOrigin.y());
1120     
1121     FloatRect clipRectForSelf(boundsOrigin, m_size);
1122     if (!applyWasClamped && !mapWasClamped)
1123         clipRectForSelf.intersect(clipRectForChildren);
1124     
1125     if (masksToBounds()) {
1126         ASSERT(accumulation == TransformState::FlattenTransform);
1127         // Replace the quad in the TransformState with one that is clipped to this layer's bounds
1128         state.setQuad(clipRectForSelf);
1129     }
1130
1131     return clipRectForSelf;
1132 }
1133
1134 // rootRelativeTransformForScaling is a transform from the root, but for layers with transform animations, it cherry-picked the state of the
1135 // animation that contributes maximally to the scale (on every layer with animations down the hierarchy).
1136 void GraphicsLayerCA::recursiveCommitChanges(const CommitState& commitState, const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale)
1137 {
1138     TransformState localState = state;
1139     CommitState childCommitState = commitState;
1140     bool affectedByTransformAnimation = commitState.ancestorHasTransformAnimation;
1141     
1142     FloatRect visibleRect = computeVisibleRect(localState);
1143     FloatRect oldVisibleRect = m_visibleRect;
1144     if (visibleRect != m_visibleRect) {
1145         m_uncommittedChanges |= VisibleRectChanged;
1146         m_visibleRect = visibleRect;
1147         
1148         if (GraphicsLayerCA* maskLayer = toGraphicsLayerCA(m_maskLayer)) {
1149             // FIXME: this assumes that the mask layer has the same geometry as this layer (which is currently always true).
1150             maskLayer->m_uncommittedChanges |= VisibleRectChanged;
1151             maskLayer->m_visibleRect = visibleRect;
1152         }
1153     }
1154
1155 #ifdef VISIBLE_TILE_WASH
1156     // Use having a transform as a key to making the tile wash layer. If every layer gets a wash,
1157     // they start to obscure useful information.
1158     if ((!m_transform.isIdentity() || m_usingTiledBacking) && !m_visibleTileWashLayer) {
1159         static Color washFillColor(255, 0, 0, 50);
1160         static Color washBorderColor(255, 0, 0, 100);
1161         
1162         m_visibleTileWashLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
1163         String name = String::format("Visible Tile Wash Layer %p", m_visibleTileWashLayer->platformLayer());
1164         m_visibleTileWashLayer->setName(name);
1165         m_visibleTileWashLayer->setAnchorPoint(FloatPoint3D(0, 0, 0));
1166         m_visibleTileWashLayer->setBorderColor(washBorderColor);
1167         m_visibleTileWashLayer->setBorderWidth(8);
1168         m_visibleTileWashLayer->setBackgroundColor(washFillColor);
1169         noteSublayersChanged(DontScheduleFlush);
1170     }
1171
1172     if (m_visibleTileWashLayer) {
1173         m_visibleTileWashLayer->setPosition(m_visibleRect.location());
1174         m_visibleTileWashLayer->setBounds(FloatRect(FloatPoint(), m_visibleRect.size()));
1175     }
1176 #endif
1177
1178     bool hadChanges = m_uncommittedChanges;
1179     
1180     if (appliesPageScale()) {
1181         pageScaleFactor = this->pageScaleFactor();
1182         affectedByPageScale = true;
1183     }
1184
1185     // Accumulate an offset from the ancestral pixel-aligned layer.
1186     FloatPoint baseRelativePosition = positionRelativeToBase;
1187     if (affectedByPageScale)
1188         baseRelativePosition += m_position;
1189     
1190     commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, oldVisibleRect);
1191
1192     if (isRunningTransformAnimation()) {
1193         childCommitState.ancestorHasTransformAnimation = true;
1194         affectedByTransformAnimation = true;
1195     }
1196
1197     if (GraphicsLayerCA* maskLayer = toGraphicsLayerCA(m_maskLayer))
1198         maskLayer->commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, oldVisibleRect);
1199
1200     const Vector<GraphicsLayer*>& childLayers = children();
1201     size_t numChildren = childLayers.size();
1202     
1203     for (size_t i = 0; i < numChildren; ++i) {
1204         GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
1205         curChild->recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
1206     }
1207
1208     if (GraphicsLayerCA* replicaLayer = toGraphicsLayerCA(m_replicaLayer))
1209         replicaLayer->recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
1210
1211     if (GraphicsLayerCA* maskLayer = toGraphicsLayerCA(m_maskLayer))
1212         maskLayer->commitLayerChangesAfterSublayers(childCommitState);
1213
1214     commitLayerChangesAfterSublayers(childCommitState);
1215
1216     if (affectedByTransformAnimation && m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
1217         client().notifyFlushBeforeDisplayRefresh(this);
1218
1219     if (hadChanges)
1220         client().didCommitChangesForLayer(this);
1221 }
1222
1223 bool GraphicsLayerCA::platformCALayerShowRepaintCounter(PlatformCALayer* platformLayer) const
1224 {
1225     // The repaint counters are painted into the TileController tiles (which have no corresponding platform layer),
1226     // so we don't want to overpaint the repaint counter when called with the TileController's own layer.
1227     if (m_isPageTiledBackingLayer && platformLayer)
1228         return false;
1229
1230     return isShowingRepaintCounter();
1231 }
1232
1233 void GraphicsLayerCA::platformCALayerPaintContents(PlatformCALayer*, GraphicsContext& context, const FloatRect& clip)
1234 {
1235     paintGraphicsLayerContents(context, clip);
1236 }
1237
1238 void GraphicsLayerCA::platformCALayerSetNeedsToRevalidateTiles()
1239 {
1240     noteLayerPropertyChanged(TilingAreaChanged, m_isCommittingChanges ? DontScheduleFlush : ScheduleFlush);
1241 }
1242
1243 float GraphicsLayerCA::platformCALayerDeviceScaleFactor() const
1244 {
1245     return deviceScaleFactor();
1246 }
1247
1248 float GraphicsLayerCA::platformCALayerContentsScaleMultiplierForNewTiles(PlatformCALayer*) const
1249 {
1250     return client().contentsScaleMultiplierForNewTiles(this);
1251 }
1252
1253 bool GraphicsLayerCA::platformCALayerShouldAggressivelyRetainTiles(PlatformCALayer*) const
1254 {
1255     return client().shouldAggressivelyRetainTiles(this);
1256 }
1257
1258 bool GraphicsLayerCA::platformCALayerShouldTemporarilyRetainTileCohorts(PlatformCALayer*) const
1259 {
1260     return client().shouldTemporarilyRetainTileCohorts(this);
1261 }
1262
1263 void GraphicsLayerCA::commitLayerChangesBeforeSublayers(CommitState& commitState, float pageScaleFactor, const FloatPoint& positionRelativeToBase, const FloatRect& oldVisibleRect)
1264 {
1265     TemporaryChange<bool> committingChangesChange(m_isCommittingChanges, true);
1266
1267     ++commitState.treeDepth;
1268     if (m_structuralLayer)
1269         ++commitState.treeDepth;
1270
1271     if (!m_uncommittedChanges) {
1272         // Ensure that we cap layer depth in commitLayerChangesAfterSublayers().
1273         if (commitState.treeDepth > cMaxLayerTreeDepth)
1274             m_uncommittedChanges |= ChildrenChanged;
1275     }
1276
1277     bool needTiledLayer = requiresTiledLayer(pageScaleFactor);
1278     if (needTiledLayer != m_usingTiledBacking)
1279         swapFromOrToTiledLayer(needTiledLayer);
1280
1281     // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to
1282     if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged))
1283         updateStructuralLayer();
1284
1285     if (m_uncommittedChanges & GeometryChanged)
1286         updateGeometry(pageScaleFactor, positionRelativeToBase);
1287
1288     if (m_uncommittedChanges & DrawsContentChanged)
1289         updateLayerDrawsContent();
1290
1291     if (m_uncommittedChanges & NameChanged)
1292         updateLayerNames();
1293
1294     if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged
1295         updateContentsImage();
1296         
1297     if (m_uncommittedChanges & ContentsPlatformLayerChanged) // Needs to happen before ChildrenChanged
1298         updateContentsPlatformLayer();
1299
1300     if (m_uncommittedChanges & ContentsColorLayerChanged) // Needs to happen before ChildrenChanged
1301         updateContentsColorLayer();
1302     
1303     if (m_uncommittedChanges & BackgroundColorChanged)
1304         updateBackgroundColor();
1305
1306     if (m_uncommittedChanges & TransformChanged)
1307         updateTransform();
1308
1309     if (m_uncommittedChanges & ChildrenTransformChanged)
1310         updateChildrenTransform();
1311     
1312     if (m_uncommittedChanges & MasksToBoundsChanged)
1313         updateMasksToBounds();
1314     
1315     if (m_uncommittedChanges & ContentsVisibilityChanged)
1316         updateContentsVisibility();
1317
1318     // Note that contentsScale can affect whether the layer can be opaque.
1319     if (m_uncommittedChanges & ContentsOpaqueChanged)
1320         updateContentsOpaque(pageScaleFactor);
1321
1322     if (m_uncommittedChanges & BackfaceVisibilityChanged)
1323         updateBackfaceVisibility();
1324
1325     if (m_uncommittedChanges & OpacityChanged)
1326         updateOpacityOnLayer();
1327     
1328 #if ENABLE(CSS_FILTERS)
1329     if (m_uncommittedChanges & FiltersChanged)
1330         updateFilters();
1331 #endif
1332
1333 #if ENABLE(CSS_COMPOSITING)
1334     if (m_uncommittedChanges & BlendModeChanged)
1335         updateBlendMode();
1336 #endif
1337
1338     if (m_uncommittedChanges & AnimationChanged)
1339         updateAnimations();
1340
1341     // Updating the contents scale can cause parts of the layer to be invalidated,
1342     // so make sure to update the contents scale before updating the dirty rects.
1343     if (m_uncommittedChanges & ContentsScaleChanged)
1344         updateContentsScale(pageScaleFactor);
1345
1346     if (m_uncommittedChanges & VisibleRectChanged)
1347         updateVisibleRect(oldVisibleRect);
1348     
1349     if (m_uncommittedChanges & TilingAreaChanged) // Needs to happen after VisibleRectChanged, ContentsScaleChanged
1350         updateTiles();
1351
1352     if (m_uncommittedChanges & DirtyRectsChanged)
1353         repaintLayerDirtyRects();
1354     
1355     if (m_uncommittedChanges & ContentsRectsChanged) // Needs to happen before ChildrenChanged
1356         updateContentsRects();
1357
1358     if (m_uncommittedChanges & MaskLayerChanged) {
1359         updateMaskLayer();
1360         // If the mask layer becomes tiled it can set this flag again. Clear the flag so that
1361         // commitLayerChangesAfterSublayers doesn't update the mask again in the normal case.
1362         m_uncommittedChanges &= ~MaskLayerChanged;
1363     }
1364
1365     if (m_uncommittedChanges & ContentsNeedsDisplay)
1366         updateContentsNeedsDisplay();
1367     
1368     if (m_uncommittedChanges & AcceleratesDrawingChanged)
1369         updateAcceleratesDrawing();
1370
1371     if (m_uncommittedChanges & DebugIndicatorsChanged)
1372         updateDebugBorder();
1373
1374     if (m_uncommittedChanges & CustomAppearanceChanged)
1375         updateCustomAppearance();
1376
1377     if (m_uncommittedChanges & CustomBehaviorChanged)
1378         updateCustomBehavior();
1379
1380     if (m_uncommittedChanges & ChildrenChanged) {
1381         updateSublayerList();
1382         // Sublayers may set this flag again, so clear it to avoid always updating sublayers in commitLayerChangesAfterSublayers().
1383         m_uncommittedChanges &= ~ChildrenChanged;
1384     }
1385
1386     // Ensure that we cap layer depth in commitLayerChangesAfterSublayers().
1387     if (commitState.treeDepth > cMaxLayerTreeDepth)
1388         m_uncommittedChanges |= ChildrenChanged;
1389 }
1390
1391 void GraphicsLayerCA::commitLayerChangesAfterSublayers(CommitState& commitState)
1392 {
1393     if (!m_uncommittedChanges)
1394         return;
1395
1396     TemporaryChange<bool> committingChangesChange(m_isCommittingChanges, true);
1397
1398     if (m_uncommittedChanges & MaskLayerChanged)
1399         updateMaskLayer();
1400
1401     if (m_uncommittedChanges & ChildrenChanged)
1402         updateSublayerList(commitState.treeDepth > cMaxLayerTreeDepth);
1403
1404     if (m_uncommittedChanges & ReplicatedLayerChanged)
1405         updateReplicatedLayers();
1406
1407     m_uncommittedChanges = NoChange;
1408 }
1409
1410 void GraphicsLayerCA::updateLayerNames()
1411 {
1412     switch (structuralLayerPurpose()) {
1413     case StructuralLayerForPreserves3D:
1414         m_structuralLayer->setName("Transform layer " + name());
1415         break;
1416     case StructuralLayerForReplicaFlattening:
1417         m_structuralLayer->setName("Replica flattening layer " + name());
1418         break;
1419     case NoStructuralLayer:
1420         break;
1421     }
1422     m_layer->setName(name());
1423 }
1424
1425 void GraphicsLayerCA::updateSublayerList(bool maxLayerDepthReached)
1426 {
1427     if (maxLayerDepthReached) {
1428         m_layer->setSublayers(PlatformCALayerList());
1429         return;
1430     }
1431     
1432     const PlatformCALayerList* customSublayers = m_layer->customSublayers();
1433
1434     PlatformCALayerList structuralLayerChildren;
1435     PlatformCALayerList primaryLayerChildren;
1436
1437     PlatformCALayerList& childListForSublayers = m_structuralLayer ? structuralLayerChildren : primaryLayerChildren;
1438
1439     if (customSublayers)
1440         primaryLayerChildren.appendVector(*customSublayers);
1441
1442     if (m_structuralLayer) {
1443         if (m_replicaLayer)
1444             structuralLayerChildren.append(toGraphicsLayerCA(m_replicaLayer)->primaryLayer());
1445     
1446         structuralLayerChildren.append(m_layer);
1447     }
1448
1449     if (m_contentsLayer && m_contentsVisible) {
1450         // FIXME: add the contents layer in the correct order with negative z-order children.
1451         // This does not cause visible rendering issues because currently contents layers are only used
1452         // for replaced elements that don't have children.
1453         primaryLayerChildren.append(m_contentsClippingLayer ? m_contentsClippingLayer : m_contentsLayer);
1454     }
1455     
1456     const Vector<GraphicsLayer*>& childLayers = children();
1457     size_t numChildren = childLayers.size();
1458     for (size_t i = 0; i < numChildren; ++i) {
1459         GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
1460         PlatformCALayer* childLayer = curChild->layerForSuperlayer();
1461         childListForSublayers.append(childLayer);
1462     }
1463
1464 #ifdef VISIBLE_TILE_WASH
1465     if (m_visibleTileWashLayer)
1466         childListForSublayers.append(m_visibleTileWashLayer);
1467 #endif
1468
1469     if (m_structuralLayer)
1470         m_structuralLayer->setSublayers(structuralLayerChildren);
1471     
1472     m_layer->setSublayers(primaryLayerChildren);
1473 }
1474
1475 void GraphicsLayerCA::updateGeometry(float pageScaleFactor, const FloatPoint& positionRelativeToBase)
1476 {
1477     FloatPoint scaledPosition = m_position;
1478     FloatPoint3D scaledAnchorPoint = m_anchorPoint;
1479     FloatSize scaledSize = m_size;
1480     FloatSize pixelAlignmentOffset;
1481
1482     // FIXME: figure out if we really need to pixel align the graphics layer here.
1483     if (m_client.needsPixelAligment() && !isIntegral(pageScaleFactor) && m_drawsContent && !m_masksToBounds)
1484         computePixelAlignment(pageScaleFactor, positionRelativeToBase, scaledPosition, scaledAnchorPoint, pixelAlignmentOffset);
1485
1486     // Update position.
1487     // Position is offset on the layer by the layer anchor point.
1488     FloatPoint adjustedPosition(scaledPosition.x() + scaledAnchorPoint.x() * scaledSize.width(), scaledPosition.y() + scaledAnchorPoint.y() * scaledSize.height());
1489
1490     if (m_structuralLayer) {
1491         FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(), m_position.y() + m_anchorPoint.y() * m_size.height());
1492         FloatRect layerBounds(m_boundsOrigin, m_size);
1493
1494         m_structuralLayer->setPosition(layerPosition);
1495         m_structuralLayer->setBounds(layerBounds);
1496         m_structuralLayer->setAnchorPoint(m_anchorPoint);
1497
1498         if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
1499             LayerMap::const_iterator end = layerCloneMap->end();
1500             for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1501                 PlatformCALayer* clone = it->value.get();
1502                 FloatPoint clonePosition = layerPosition;
1503
1504                 if (m_replicaLayer && isReplicatedRootClone(it->key)) {
1505                     // Maintain the special-case position for the root of a clone subtree,
1506                     // which we set up in replicatedLayerRoot().
1507                     clonePosition = positionForCloneRootLayer();
1508                 }
1509
1510                 clone->setPosition(clonePosition);
1511                 clone->setBounds(layerBounds);
1512                 clone->setAnchorPoint(m_anchorPoint);
1513             }
1514         }
1515
1516         // If we have a structural layer, we just use 0.5, 0.5 for the anchor point of the main layer.
1517         scaledAnchorPoint = FloatPoint(0.5f, 0.5f);
1518         adjustedPosition = FloatPoint(scaledAnchorPoint.x() * scaledSize.width() - pixelAlignmentOffset.width(), scaledAnchorPoint.y() * scaledSize.height() - pixelAlignmentOffset.height());
1519     }
1520
1521     m_pixelAlignmentOffset = pixelAlignmentOffset;
1522
1523     // Push the layer to device pixel boundary (setPosition()), but move the content back to its original position (setBounds())
1524     m_layer->setPosition(adjustedPosition);
1525     FloatRect adjustedBounds = FloatRect(FloatPoint(m_boundsOrigin - pixelAlignmentOffset), m_size);
1526     m_layer->setBounds(adjustedBounds);
1527     m_layer->setAnchorPoint(scaledAnchorPoint);
1528
1529     if (LayerMap* layerCloneMap = m_layerClones.get()) {
1530         LayerMap::const_iterator end = layerCloneMap->end();
1531         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1532             PlatformCALayer* clone = it->value.get();
1533             FloatPoint clonePosition = adjustedPosition;
1534
1535             if (!m_structuralLayer && m_replicaLayer && isReplicatedRootClone(it->key)) {
1536                 // Maintain the special-case position for the root of a clone subtree,
1537                 // which we set up in replicatedLayerRoot().
1538                 clonePosition = positionForCloneRootLayer();
1539             }
1540
1541             clone->setPosition(clonePosition);
1542             clone->setBounds(adjustedBounds);
1543             clone->setAnchorPoint(scaledAnchorPoint);
1544         }
1545     }
1546 }
1547
1548 void GraphicsLayerCA::updateTransform()
1549 {
1550     primaryLayer()->setTransform(m_transform);
1551
1552     if (LayerMap* layerCloneMap = primaryLayerClones()) {
1553         LayerMap::const_iterator end = layerCloneMap->end();
1554         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1555             PlatformCALayer* currLayer = it->value.get();
1556             if (m_replicaLayer && isReplicatedRootClone(it->key)) {
1557                 // Maintain the special-case transform for the root of a clone subtree,
1558                 // which we set up in replicatedLayerRoot().
1559                 currLayer->setTransform(TransformationMatrix());
1560             } else
1561                 currLayer->setTransform(m_transform);
1562         }
1563     }
1564 }
1565
1566 void GraphicsLayerCA::updateChildrenTransform()
1567 {
1568     primaryLayer()->setSublayerTransform(m_childrenTransform);
1569
1570     if (LayerMap* layerCloneMap = primaryLayerClones()) {
1571         LayerMap::const_iterator end = layerCloneMap->end();
1572         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1573             it->value->setSublayerTransform(m_childrenTransform);
1574     }
1575 }
1576
1577 void GraphicsLayerCA::updateMasksToBounds()
1578 {
1579     m_layer->setMasksToBounds(m_masksToBounds);
1580
1581     if (LayerMap* layerCloneMap = m_layerClones.get()) {
1582         LayerMap::const_iterator end = layerCloneMap->end();
1583         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1584             it->value->setMasksToBounds(m_masksToBounds);
1585     }
1586 }
1587
1588 void GraphicsLayerCA::updateContentsVisibility()
1589 {
1590     // Note that m_contentsVisible also affects whether m_contentsLayer is parented.
1591     if (m_contentsVisible) {
1592         if (m_drawsContent)
1593             m_layer->setNeedsDisplay();
1594     } else {
1595         m_layer->setContents(0);
1596
1597         if (LayerMap* layerCloneMap = m_layerClones.get()) {
1598             LayerMap::const_iterator end = layerCloneMap->end();
1599             for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1600                 it->value->setContents(0);
1601         }
1602     }
1603 }
1604
1605 void GraphicsLayerCA::updateContentsOpaque(float pageScaleFactor)
1606 {
1607     bool contentsOpaque = m_contentsOpaque;
1608     if (contentsOpaque) {
1609         float contentsScale = pageScaleFactor * deviceScaleFactor();
1610         if (!isIntegral(contentsScale) && !m_client.paintsOpaquelyAtNonIntegralScales(this))
1611             contentsOpaque = false;
1612     }
1613     
1614     m_layer->setOpaque(contentsOpaque);
1615
1616     if (LayerMap* layerCloneMap = m_layerClones.get()) {
1617         LayerMap::const_iterator end = layerCloneMap->end();
1618         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1619             it->value->setOpaque(contentsOpaque);
1620     }
1621 }
1622
1623 void GraphicsLayerCA::updateBackfaceVisibility()
1624 {
1625     if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) {
1626         m_structuralLayer->setDoubleSided(m_backfaceVisibility);
1627
1628         if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
1629             LayerMap::const_iterator end = layerCloneMap->end();
1630             for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1631                 it->value->setDoubleSided(m_backfaceVisibility);
1632         }
1633     }
1634
1635     m_layer->setDoubleSided(m_backfaceVisibility);
1636
1637     if (LayerMap* layerCloneMap = m_layerClones.get()) {
1638         LayerMap::const_iterator end = layerCloneMap->end();
1639         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1640             it->value->setDoubleSided(m_backfaceVisibility);
1641     }
1642 }
1643
1644 #if ENABLE(CSS_FILTERS)
1645 void GraphicsLayerCA::updateFilters()
1646 {
1647     m_layer->setFilters(m_filters);
1648
1649     if (LayerMap* layerCloneMap = m_layerClones.get()) {
1650         LayerMap::const_iterator end = layerCloneMap->end();
1651         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1652             if (m_replicaLayer && isReplicatedRootClone(it->key))
1653                 continue;
1654
1655             it->value->setFilters(m_filters);
1656         }
1657     }
1658 }
1659 #endif
1660
1661 #if ENABLE(CSS_COMPOSITING)
1662 void GraphicsLayerCA::updateBlendMode()
1663 {
1664     primaryLayer()->setBlendMode(m_blendMode);
1665
1666     if (LayerMap* layerCloneMap = primaryLayerClones()) {
1667         LayerMap::const_iterator end = layerCloneMap->end();
1668         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1669             if (m_replicaLayer && isReplicatedRootClone(it->key))
1670                 continue;
1671             it->value->setBlendMode(m_blendMode);
1672         }
1673     }
1674 }
1675 #endif
1676
1677 void GraphicsLayerCA::updateStructuralLayer()
1678 {
1679     ensureStructuralLayer(structuralLayerPurpose());
1680 }
1681
1682 void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose)
1683 {
1684     const LayerChangeFlags structuralLayerChangeFlags = NameChanged
1685         | GeometryChanged
1686         | TransformChanged
1687         | ChildrenTransformChanged
1688         | ChildrenChanged
1689         | BackfaceVisibilityChanged
1690 #if ENABLE(CSS_FILTERS)
1691         | FiltersChanged
1692 #endif
1693         | OpacityChanged;
1694
1695     if (purpose == NoStructuralLayer) {
1696         if (m_structuralLayer) {
1697             // Replace the transformLayer in the parent with this layer.
1698             m_layer->removeFromSuperlayer();
1699  
1700             // If m_layer doesn't have a parent, it means it's the root layer and
1701             // is likely hosted by something that is not expecting to be changed
1702             ASSERT(m_structuralLayer->superlayer());
1703             m_structuralLayer->superlayer()->replaceSublayer(m_structuralLayer.get(), m_layer.get());
1704
1705             moveOrCopyAnimations(Move, m_structuralLayer.get(), m_layer.get());
1706
1707             // Release the structural layer.
1708             m_structuralLayer = 0;
1709
1710             m_uncommittedChanges |= structuralLayerChangeFlags;
1711         }
1712         return;
1713     }
1714
1715 #if PLATFORM(IOS)
1716     RefPtr<PlatformCALayer> oldPrimaryLayer = m_structuralLayer ? m_structuralLayer.get() : m_layer.get();
1717 #endif
1718
1719     bool structuralLayerChanged = false;
1720     
1721     if (purpose == StructuralLayerForPreserves3D) {
1722         if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeTransformLayer)
1723             m_structuralLayer = 0;
1724         
1725         if (!m_structuralLayer) {
1726             m_structuralLayer = createPlatformCALayer(PlatformCALayer::LayerTypeTransformLayer, this);
1727             structuralLayerChanged = true;
1728         }
1729     } else {
1730         if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeLayer)
1731             m_structuralLayer = 0;
1732
1733         if (!m_structuralLayer) {
1734             m_structuralLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
1735             structuralLayerChanged = true;
1736         }
1737     }
1738     
1739     if (!structuralLayerChanged)
1740         return;
1741     
1742     m_uncommittedChanges |= structuralLayerChangeFlags;
1743
1744     // We've changed the layer that our parent added to its sublayer list, so tell it to update
1745     // sublayers again in its commitLayerChangesAfterSublayers().
1746     toGraphicsLayerCA(parent())->noteSublayersChanged(DontScheduleFlush);
1747
1748     // Set properties of m_layer to their default values, since these are expressed on on the structural layer.
1749     FloatPoint point(m_size.width() / 2.0f, m_size.height() / 2.0f);
1750     FloatPoint3D anchorPoint(0.5f, 0.5f, 0);
1751     m_layer->setPosition(point);
1752     m_layer->setAnchorPoint(anchorPoint);
1753     m_layer->setTransform(TransformationMatrix());
1754     m_layer->setOpacity(1);
1755     if (m_layerClones) {
1756         LayerMap::const_iterator end = m_layerClones->end();
1757         for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) {
1758             PlatformCALayer* currLayer = it->value.get();
1759             currLayer->setPosition(point);
1760             currLayer->setAnchorPoint(anchorPoint);
1761             currLayer->setTransform(TransformationMatrix());
1762             currLayer->setOpacity(1);
1763         }
1764     }
1765
1766     moveOrCopyAnimations(Move, m_layer.get(), m_structuralLayer.get());
1767 }
1768
1769 GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const
1770 {
1771     if (preserves3D())
1772         return StructuralLayerForPreserves3D;
1773     
1774     if (isReplicated())
1775         return StructuralLayerForReplicaFlattening;
1776     
1777     return NoStructuralLayer;
1778 }
1779
1780 void GraphicsLayerCA::updateLayerDrawsContent()
1781 {
1782     if (m_drawsContent)
1783         m_layer->setNeedsDisplay();
1784     else {
1785         m_layer->setContents(0);
1786         if (m_layerClones) {
1787             LayerMap::const_iterator end = m_layerClones->end();
1788             for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it)
1789                 it->value->setContents(0);
1790         }
1791     }
1792 }
1793
1794 void GraphicsLayerCA::updateAcceleratesDrawing()
1795 {
1796     m_layer->setAcceleratesDrawing(m_acceleratesDrawing);
1797 }
1798
1799 void GraphicsLayerCA::updateDebugBorder()
1800 {
1801     if (isShowingDebugBorder())
1802         updateDebugIndicators();
1803     else
1804         m_layer->setBorderWidth(0);
1805 }
1806
1807 FloatRect GraphicsLayerCA::adjustTiledLayerVisibleRect(TiledBacking* tiledBacking, const FloatRect& oldVisibleRect, const FloatRect& newVisibleRect, const FloatSize& oldSize, const FloatSize& newSize)
1808 {
1809     // If the old visible rect is empty, we have no information about how the visible area is changing
1810     // (maybe the layer was just created), so don't attempt to expand. Also don't attempt to expand
1811     // if the size changed or the rects don't overlap.
1812     if (oldVisibleRect.isEmpty() || newSize != oldSize || !newVisibleRect.intersects(oldVisibleRect))
1813         return newVisibleRect;
1814
1815     const float paddingMultiplier = 2;
1816
1817     float leftEdgeDelta = paddingMultiplier * (newVisibleRect.x() - oldVisibleRect.x());
1818     float rightEdgeDelta = paddingMultiplier * (newVisibleRect.maxX() - oldVisibleRect.maxX());
1819
1820     float topEdgeDelta = paddingMultiplier * (newVisibleRect.y() - oldVisibleRect.y());
1821     float bottomEdgeDelta = paddingMultiplier * (newVisibleRect.maxY() - oldVisibleRect.maxY());
1822     
1823     FloatRect existingTileBackingRect = tiledBacking->visibleRect();
1824     FloatRect expandedRect = newVisibleRect;
1825
1826     // More exposed on left side.
1827     if (leftEdgeDelta < 0) {
1828         float newLeft = expandedRect.x() + leftEdgeDelta;
1829         // Pad to the left, but don't reduce padding that's already in the backing store (since we're still exposing to the left).
1830         if (newLeft < existingTileBackingRect.x())
1831             expandedRect.shiftXEdgeTo(newLeft);
1832         else
1833             expandedRect.shiftXEdgeTo(existingTileBackingRect.x());
1834     }
1835
1836     // More exposed on right.
1837     if (rightEdgeDelta > 0) {
1838         float newRight = expandedRect.maxX() + rightEdgeDelta;
1839         // Pad to the right, but don't reduce padding that's already in the backing store (since we're still exposing to the right).
1840         if (newRight > existingTileBackingRect.maxX())
1841             expandedRect.setWidth(newRight - expandedRect.x());
1842         else
1843             expandedRect.setWidth(existingTileBackingRect.maxX() - expandedRect.x());
1844     }
1845
1846     // More exposed at top.
1847     if (topEdgeDelta < 0) {
1848         float newTop = expandedRect.y() + topEdgeDelta;
1849         if (newTop < existingTileBackingRect.y())
1850             expandedRect.shiftYEdgeTo(newTop);
1851         else
1852             expandedRect.shiftYEdgeTo(existingTileBackingRect.y());
1853     }
1854
1855     // More exposed on bottom.
1856     if (bottomEdgeDelta > 0) {
1857         float newBottom = expandedRect.maxY() + bottomEdgeDelta;
1858         if (newBottom > existingTileBackingRect.maxY())
1859             expandedRect.setHeight(newBottom - expandedRect.y());
1860         else
1861             expandedRect.setHeight(existingTileBackingRect.maxY() - expandedRect.y());
1862     }
1863     
1864     expandedRect.intersect(tiledBacking->boundsWithoutMargin());
1865     return expandedRect;
1866 }
1867
1868 void GraphicsLayerCA::updateVisibleRect(const FloatRect& oldVisibleRect)
1869 {
1870     if (!m_layer->usesTiledBackingLayer())
1871         return;
1872
1873     FloatRect tileArea = m_visibleRect;
1874     if (m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
1875         tileArea = adjustTiledLayerVisibleRect(tiledBacking(), oldVisibleRect, tileArea, m_sizeAtLastVisibleRectUpdate, m_size);
1876
1877     tiledBacking()->setVisibleRect(tileArea);
1878
1879     m_sizeAtLastVisibleRectUpdate = m_size;
1880 }
1881
1882 void GraphicsLayerCA::updateTiles()
1883 {
1884     if (!m_layer->usesTiledBackingLayer())
1885         return;
1886
1887     tiledBacking()->revalidateTiles();
1888 }
1889
1890 void GraphicsLayerCA::updateBackgroundColor()
1891 {
1892     m_layer->setBackgroundColor(m_backgroundColor);
1893 }
1894
1895 void GraphicsLayerCA::updateContentsImage()
1896 {
1897     if (m_pendingContentsImage) {
1898         if (!m_contentsLayer.get()) {
1899             m_contentsLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
1900 #ifndef NDEBUG
1901             m_contentsLayer->setName("Image Layer");
1902 #endif
1903             setupContentsLayer(m_contentsLayer.get());
1904             // m_contentsLayer will be parented by updateSublayerList
1905         }
1906
1907         // FIXME: maybe only do trilinear if the image is being scaled down,
1908         // but then what if the layer size changes?
1909         m_contentsLayer->setMinificationFilter(PlatformCALayer::Trilinear);
1910         m_contentsLayer->setContents(m_pendingContentsImage.get());
1911         m_pendingContentsImage = 0;
1912
1913         if (m_contentsLayerClones) {
1914             LayerMap::const_iterator end = m_contentsLayerClones->end();
1915             for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it)
1916                 it->value->setContents(m_contentsLayer->contents());
1917         }
1918         
1919         updateContentsRects();
1920     } else {
1921         // No image.
1922         // m_contentsLayer will be removed via updateSublayerList.
1923         m_contentsLayer = 0;
1924     }
1925 }
1926
1927 void GraphicsLayerCA::updateContentsPlatformLayer()
1928 {
1929     if (!m_contentsLayer)
1930         return;
1931
1932     // Platform layer was set as m_contentsLayer, and will get parented in updateSublayerList().
1933     setupContentsLayer(m_contentsLayer.get());
1934
1935     if (m_contentsLayerPurpose == ContentsLayerForCanvas)
1936         m_contentsLayer->setNeedsDisplay();
1937
1938     updateContentsRects();
1939 }
1940
1941 void GraphicsLayerCA::updateContentsColorLayer()
1942 {
1943     // Color layer was set as m_contentsLayer, and will get parented in updateSublayerList().
1944     if (!m_contentsLayer || m_contentsLayerPurpose != ContentsLayerForBackgroundColor)
1945         return;
1946
1947     setupContentsLayer(m_contentsLayer.get());
1948     updateContentsRects();
1949     ASSERT(m_contentsSolidColor.isValid());
1950     m_contentsLayer->setBackgroundColor(m_contentsSolidColor);
1951
1952     if (m_contentsLayerClones) {
1953         LayerMap::const_iterator end = m_contentsLayerClones->end();
1954         for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it)
1955             it->value->setBackgroundColor(m_contentsSolidColor);
1956     }
1957 }
1958
1959 void GraphicsLayerCA::updateContentsRects()
1960 {
1961     if (!m_contentsLayer)
1962         return;
1963
1964     FloatPoint contentOrigin;
1965     FloatRect contentBounds(0, 0, m_contentsRect.width(), m_contentsRect.height());
1966
1967     FloatPoint clippingOrigin;
1968     FloatRect clippingBounds;
1969     
1970     bool gainedOrLostClippingLayer = false;
1971     if (!m_contentsClippingRect.contains(m_contentsRect)) {
1972         if (!m_contentsClippingLayer) {
1973             m_contentsClippingLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
1974             m_contentsClippingLayer->setMasksToBounds(true);
1975             m_contentsClippingLayer->setAnchorPoint(FloatPoint());
1976 #ifndef NDEBUG
1977             m_contentsClippingLayer->setName("Contents Clipping");
1978 #endif
1979             m_contentsLayer->removeFromSuperlayer();
1980             m_contentsClippingLayer->appendSublayer(m_contentsLayer.get());
1981             gainedOrLostClippingLayer = true;
1982         }
1983     
1984         clippingOrigin = m_contentsClippingRect.location();
1985         clippingBounds.setSize(m_contentsClippingRect.size());
1986
1987         contentOrigin = FloatPoint(m_contentsRect.location() - m_contentsClippingRect.location());
1988
1989         m_contentsClippingLayer->setPosition(clippingOrigin);
1990         m_contentsClippingLayer->setBounds(clippingBounds);
1991
1992         m_contentsLayer->setPosition(contentOrigin);
1993         m_contentsLayer->setBounds(contentBounds);
1994     
1995     } else {
1996         if (m_contentsClippingLayer) {
1997             m_contentsLayer->removeFromSuperlayer();
1998
1999             m_contentsClippingLayer->removeFromSuperlayer();
2000             m_contentsClippingLayer->setOwner(0);
2001             m_contentsClippingLayer = nullptr;
2002             gainedOrLostClippingLayer = true;
2003         }
2004
2005         contentOrigin = m_contentsRect.location();
2006     }
2007     
2008     if (gainedOrLostClippingLayer)
2009         noteSublayersChanged(DontScheduleFlush);
2010
2011     m_contentsLayer->setPosition(contentOrigin);
2012     m_contentsLayer->setBounds(contentBounds);
2013
2014     if (m_contentsLayerClones) {
2015         LayerMap::const_iterator end = m_contentsLayerClones->end();
2016         for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) {
2017             it->value->setPosition(contentOrigin);
2018             it->value->setBounds(contentBounds);
2019         }
2020     }
2021
2022     if (m_contentsClippingLayerClones) {
2023         LayerMap::const_iterator end = m_contentsClippingLayerClones->end();
2024         for (LayerMap::const_iterator it = m_contentsClippingLayerClones->begin(); it != end; ++it) {
2025             it->value->setPosition(clippingOrigin);
2026             it->value->setBounds(clippingBounds);
2027         }
2028     }
2029 }
2030
2031 void GraphicsLayerCA::updateMaskLayer()
2032 {
2033     PlatformCALayer* maskCALayer = m_maskLayer ? toGraphicsLayerCA(m_maskLayer)->primaryLayer() : 0;
2034     m_layer->setMask(maskCALayer);
2035
2036     LayerMap* maskLayerCloneMap = m_maskLayer ? toGraphicsLayerCA(m_maskLayer)->primaryLayerClones() : 0;
2037     
2038     if (LayerMap* layerCloneMap = m_layerClones.get()) {
2039         LayerMap::const_iterator end = layerCloneMap->end();
2040         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {            
2041             PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->key) : 0;
2042             it->value->setMask(maskClone);
2043         }
2044     }
2045 }
2046
2047 void GraphicsLayerCA::updateReplicatedLayers()
2048 {
2049     // Clone the descendants of the replicated layer, and parent under us.
2050     ReplicaState replicaState(ReplicaState::ReplicaBranch);
2051
2052     RefPtr<PlatformCALayer>replicaRoot = replicatedLayerRoot(replicaState);
2053     if (!replicaRoot)
2054         return;
2055
2056     if (m_structuralLayer)
2057         m_structuralLayer->insertSublayer(replicaRoot.get(), 0);
2058     else
2059         m_layer->insertSublayer(replicaRoot.get(), 0);
2060 }
2061
2062 // For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1.
2063 GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const
2064 {
2065     size_t depth = m_replicaBranches.size();
2066
2067     const size_t bitsPerUChar = sizeof(UChar) * 8;
2068     size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar;
2069     
2070     Vector<UChar> result(vectorSize);
2071     result.fill(0);
2072
2073     // Create a string from the bit sequence which we can use to identify the clone.
2074     // Note that the string may contain embedded nulls, but that's OK.
2075     for (size_t i = 0; i < depth; ++i) {
2076         UChar& currChar = result[i / bitsPerUChar];
2077         currChar = (currChar << 1) | m_replicaBranches[i];
2078     }
2079     
2080     return String::adopt(result);
2081 }
2082
2083 PassRefPtr<PlatformCALayer> GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState)
2084 {
2085     // Limit replica nesting, to avoid 2^N explosion of replica layers.
2086     if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth)
2087         return 0;
2088
2089     GraphicsLayerCA* replicatedLayer = toGraphicsLayerCA(m_replicatedLayer);
2090     
2091     RefPtr<PlatformCALayer> clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel);
2092     FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer();
2093
2094     // Replica root has no offset or transform
2095     clonedLayerRoot->setPosition(cloneRootPosition);
2096     clonedLayerRoot->setTransform(TransformationMatrix());
2097
2098     return clonedLayerRoot;
2099 }
2100
2101 void GraphicsLayerCA::updateAnimations()
2102 {
2103     if (m_animationsToProcess.size()) {
2104         AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end();
2105         for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) {
2106             const String& currAnimationName = it->key;
2107             AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName);
2108             if (animationIt == m_runningAnimations.end())
2109                 continue;
2110
2111             const AnimationProcessingAction& processingInfo = it->value;
2112             const Vector<LayerPropertyAnimation>& animations = animationIt->value;
2113             for (size_t i = 0; i < animations.size(); ++i) {
2114                 const LayerPropertyAnimation& currAnimation = animations[i];
2115                 switch (processingInfo.action) {
2116                 case Remove:
2117                     removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, currAnimation.m_subIndex);
2118                     break;
2119                 case Pause:
2120                     pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, currAnimation.m_subIndex, processingInfo.timeOffset);
2121                     break;
2122                 }
2123             }
2124
2125             if (processingInfo.action == Remove)
2126                 m_runningAnimations.remove(currAnimationName);
2127         }
2128     
2129         m_animationsToProcess.clear();
2130     }
2131     
2132     size_t numAnimations;
2133     if ((numAnimations = m_uncomittedAnimations.size())) {
2134         for (size_t i = 0; i < numAnimations; ++i) {
2135             const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i];
2136             setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_subIndex, pendingAnimation.m_timeOffset);
2137             
2138             AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name);
2139             if (it == m_runningAnimations.end()) {
2140                 Vector<LayerPropertyAnimation> animations;
2141                 animations.append(pendingAnimation);
2142                 m_runningAnimations.add(pendingAnimation.m_name, animations);
2143
2144             } else {
2145                 Vector<LayerPropertyAnimation>& animations = it->value;
2146                 animations.append(pendingAnimation);
2147             }
2148         }
2149         m_uncomittedAnimations.clear();
2150     }
2151 }
2152
2153 bool GraphicsLayerCA::isRunningTransformAnimation() const
2154 {
2155     AnimationsMap::const_iterator end = m_runningAnimations.end();
2156     for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
2157         const Vector<LayerPropertyAnimation>& propertyAnimations = it->value;
2158         size_t numAnimations = propertyAnimations.size();
2159         for (size_t i = 0; i < numAnimations; ++i) {
2160             const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
2161             if (currAnimation.m_property == AnimatedPropertyWebkitTransform)
2162                 return true;
2163         }
2164     }
2165     return false;
2166 }
2167
2168 void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, int subIndex, double timeOffset)
2169 {
2170     PlatformCALayer* layer = animatedLayer(property);
2171
2172     if (timeOffset)
2173         caAnim->setBeginTime(CACurrentMediaTime() - timeOffset);
2174
2175     String animationID = animationIdentifier(animationName, property, index, subIndex);
2176
2177     layer->removeAnimationForKey(animationID);
2178     layer->addAnimationForKey(animationID, caAnim);
2179
2180     if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
2181         LayerMap::const_iterator end = layerCloneMap->end();
2182         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2183             // Skip immediate replicas, since they move with the original.
2184             if (m_replicaLayer && isReplicatedRootClone(it->key))
2185                 continue;
2186
2187             it->value->removeAnimationForKey(animationID);
2188             it->value->addAnimationForKey(animationID, caAnim);
2189         }
2190     }
2191 }
2192
2193 // Workaround for <rdar://problem/7311367>
2194 static void bug7311367Workaround(PlatformCALayer* transformLayer, const TransformationMatrix& transform)
2195 {
2196     if (!transformLayer)
2197         return;
2198
2199     TransformationMatrix caTransform = transform;
2200     caTransform.setM41(caTransform.m41() + 1);
2201     transformLayer->setTransform(caTransform);
2202
2203     caTransform.setM41(caTransform.m41() - 1);
2204     transformLayer->setTransform(caTransform);
2205 }
2206
2207 bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index, int subIndex)
2208 {
2209     PlatformCALayer* layer = animatedLayer(property);
2210
2211     String animationID = animationIdentifier(animationName, property, index, subIndex);
2212
2213     if (!layer->animationForKey(animationID))
2214         return false;
2215     
2216     layer->removeAnimationForKey(animationID);
2217     bug7311367Workaround(m_structuralLayer.get(), m_transform);
2218
2219     if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
2220         LayerMap::const_iterator end = layerCloneMap->end();
2221         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2222             // Skip immediate replicas, since they move with the original.
2223             if (m_replicaLayer && isReplicatedRootClone(it->key))
2224                 continue;
2225
2226             it->value->removeAnimationForKey(animationID);
2227         }
2228     }
2229     return true;
2230 }
2231
2232 void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, int subIndex, double timeOffset)
2233 {
2234     PlatformCALayer* layer = animatedLayer(property);
2235
2236     String animationID = animationIdentifier(animationName, property, index, subIndex);
2237
2238     RefPtr<PlatformCAAnimation> curAnim = layer->animationForKey(animationID);
2239     if (!curAnim)
2240         return;
2241
2242     // Animations on the layer are immutable, so we have to clone and modify.
2243     RefPtr<PlatformCAAnimation> newAnim = curAnim->copy();
2244
2245     newAnim->setSpeed(0);
2246     newAnim->setTimeOffset(timeOffset);
2247     
2248     layer->addAnimationForKey(animationID, newAnim.get()); // This will replace the running animation.
2249
2250     // Pause the animations on the clones too.
2251     if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
2252         LayerMap::const_iterator end = layerCloneMap->end();
2253         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2254             // Skip immediate replicas, since they move with the original.
2255             if (m_replicaLayer && isReplicatedRootClone(it->key))
2256                 continue;
2257             it->value->addAnimationForKey(animationID, newAnim.get());
2258         }
2259     }
2260 }
2261
2262 void GraphicsLayerCA::repaintLayerDirtyRects()
2263 {
2264     if (m_needsFullRepaint) {
2265         ASSERT(!m_dirtyRects.size());
2266         m_layer->setNeedsDisplay();
2267         m_needsFullRepaint = false;
2268         return;
2269     }
2270
2271     if (!m_dirtyRects.size())
2272         return;
2273
2274     for (size_t i = 0; i < m_dirtyRects.size(); ++i)
2275         m_layer->setNeedsDisplayInRect(m_dirtyRects[i]);
2276     
2277     m_dirtyRects.clear();
2278 }
2279
2280 void GraphicsLayerCA::updateContentsNeedsDisplay()
2281 {
2282     if (m_contentsLayer)
2283         m_contentsLayer->setNeedsDisplay();
2284 }
2285
2286 bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset)
2287 {
2288     ASSERT(valueList.property() != AnimatedPropertyWebkitTransform && (!supportsAcceleratedFilterAnimations() || valueList.property() != AnimatedPropertyWebkitFilter));
2289     
2290     bool isKeyframe = valueList.size() > 2;
2291     bool valuesOK;
2292     
2293     bool additive = false;
2294     int animationIndex = 0;
2295     
2296     RefPtr<PlatformCAAnimation> caAnimation;
2297     
2298     if (isKeyframe) {
2299         caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive);
2300         valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get());
2301     } else {
2302         caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive);
2303         valuesOK = setAnimationEndpoints(valueList, animation, caAnimation.get());
2304     }
2305     
2306     if (!valuesOK)
2307         return false;
2308
2309     m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, 0, timeOffset));
2310
2311     return true;
2312 }
2313
2314 bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const TransformOperations* operations, const Animation* animation, const String& animationName, const FloatSize& boxSize, int animationIndex, double timeOffset, bool isMatrixAnimation)
2315 {
2316     TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : operations->operations().at(animationIndex)->type();
2317     bool additive = animationIndex > 0;
2318     bool isKeyframe = valueList.size() > 2;
2319
2320     RefPtr<PlatformCAAnimation> caAnimation;
2321     bool validMatrices = true;
2322     if (isKeyframe) {
2323         caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive);
2324         validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
2325     } else {
2326         caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive);
2327         validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
2328     }
2329     
2330     if (!validMatrices)
2331         return false;
2332
2333     m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, 0, timeOffset));
2334     return true;
2335 }
2336
2337 bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const FloatSize& boxSize)
2338 {
2339     ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
2340
2341     bool hasBigRotation;
2342     int listIndex = validateTransformOperations(valueList, hasBigRotation);
2343     const TransformOperations* operations = (listIndex >= 0) ? &static_cast<const TransformAnimationValue&>(valueList.at(listIndex)).value() : 0;
2344
2345     bool validMatrices = true;
2346
2347     // If function lists don't match we do a matrix animation, otherwise we do a component hardware animation.
2348     bool isMatrixAnimation = listIndex < 0;
2349     int numAnimations = isMatrixAnimation ? 1 : operations->size();
2350
2351 #if PLATFORM(IOS)
2352     bool reverseAnimationList = false;
2353 #else
2354     bool reverseAnimationList = true;
2355 #if !PLATFORM(WIN)
2356         // Old versions of Core Animation apply animations in reverse order (<rdar://problem/7095638>) so we need to flip the list.
2357         // to be non-additive. For binary compatibility, the current version of Core Animation preserves this behavior for applications linked
2358         // on or before Snow Leopard.
2359         // FIXME: This fix has not been added to QuartzCore on Windows yet (<rdar://problem/9112233>) so we expect the
2360         // reversed animation behavior
2361         static bool executableWasLinkedOnOrBeforeSnowLeopard = wkExecutableWasLinkedOnOrBeforeSnowLeopard();
2362         if (!executableWasLinkedOnOrBeforeSnowLeopard)
2363             reverseAnimationList = false;
2364 #endif
2365 #endif // PLATFORM(IOS)
2366     if (reverseAnimationList) {
2367         for (int animationIndex = numAnimations - 1; animationIndex >= 0; --animationIndex) {
2368             if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
2369                 validMatrices = false;
2370                 break;
2371             }
2372         }
2373     } else {
2374         for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
2375             if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
2376                 validMatrices = false;
2377                 break;
2378             }
2379         }
2380     }
2381
2382     return validMatrices;
2383 }
2384
2385 #if ENABLE(CSS_FILTERS)
2386 bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const FilterOperation* operation, const Animation* animation, const String& animationName, int animationIndex, double timeOffset)
2387 {
2388     bool isKeyframe = valueList.size() > 2;
2389     
2390     FilterOperation::OperationType filterOp = operation->type();
2391     int numAnimatedProperties = PlatformCAFilters::numAnimatedFilterProperties(filterOp);
2392     
2393     // Each filter might need to animate multiple properties, each with their own keyPath. The keyPath is always of the form:
2394     //
2395     //      filter.filter_<animationIndex>.<filterPropertyName>
2396     //
2397     // PlatformCAAnimation tells us how many properties each filter has and we iterate that many times and create an animation
2398     // for each. This internalFilterPropertyIndex gets passed to PlatformCAAnimation so it can properly create the property animation
2399     // values.
2400     for (int internalFilterPropertyIndex = 0; internalFilterPropertyIndex < numAnimatedProperties; ++internalFilterPropertyIndex) {
2401         bool valuesOK;
2402         RefPtr<PlatformCAAnimation> caAnimation;
2403         String keyPath = String::format("filters.filter_%d.%s", animationIndex, PlatformCAFilters::animatedFilterPropertyName(filterOp, internalFilterPropertyIndex));
2404         
2405         if (isKeyframe) {
2406             caAnimation = createKeyframeAnimation(animation, keyPath, false);
2407             valuesOK = setFilterAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex, filterOp);
2408         } else {
2409             caAnimation = createBasicAnimation(animation, keyPath, false);
2410             valuesOK = setFilterAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex);
2411         }
2412         
2413         ASSERT(valuesOK);
2414
2415         m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, internalFilterPropertyIndex, timeOffset));
2416     }
2417
2418     return true;
2419 }
2420
2421 bool GraphicsLayerCA::createFilterAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset)
2422 {
2423     ASSERT(valueList.property() == AnimatedPropertyWebkitFilter);
2424
2425     int listIndex = validateFilterOperations(valueList);
2426     if (listIndex < 0)
2427         return false;
2428
2429     const FilterOperations& operations = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
2430     // Make sure the platform layer didn't fallback to using software filter compositing instead.
2431     if (!filtersCanBeComposited(operations))
2432         return false;
2433
2434     int numAnimations = operations.size();
2435
2436     // FIXME: We can't currently hardware animate shadows.
2437     for (int i = 0; i < numAnimations; ++i) {
2438         if (operations.at(i)->type() == FilterOperation::DROP_SHADOW)
2439             return false;
2440     }
2441
2442     for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
2443         if (!appendToUncommittedAnimations(valueList, operations.operations().at(animationIndex).get(), animation, animationName, animationIndex, timeOffset))
2444             return false;
2445     }
2446
2447     return true;
2448 }
2449 #endif
2450
2451 PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, const String& keyPath, bool additive)
2452 {
2453     RefPtr<PlatformCAAnimation> basicAnim = createPlatformCAAnimation(PlatformCAAnimation::Basic, keyPath);
2454     setupAnimation(basicAnim.get(), anim, additive);
2455     return basicAnim;
2456 }
2457
2458 PassRefPtr<PlatformCAAnimation>GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, const String& keyPath, bool additive)
2459 {
2460     RefPtr<PlatformCAAnimation> keyframeAnim = createPlatformCAAnimation(PlatformCAAnimation::Keyframe, keyPath);
2461     setupAnimation(keyframeAnim.get(), anim, additive);
2462     return keyframeAnim;
2463 }
2464
2465 void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive)
2466 {
2467     double duration = anim->duration();
2468     if (duration <= 0)
2469         duration = cAnimationAlmostZeroDuration;
2470
2471     float repeatCount = anim->iterationCount();
2472     if (repeatCount == Animation::IterationCountInfinite)
2473         repeatCount = std::numeric_limits<float>::max();
2474     else if (anim->direction() == Animation::AnimationDirectionAlternate || anim->direction() == Animation::AnimationDirectionAlternateReverse)
2475         repeatCount /= 2;
2476
2477     PlatformCAAnimation::FillModeType fillMode = PlatformCAAnimation::NoFillMode;
2478     switch (anim->fillMode()) {
2479     case AnimationFillModeNone:
2480         fillMode = PlatformCAAnimation::Forwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash.
2481         break;
2482     case AnimationFillModeBackwards:
2483         fillMode = PlatformCAAnimation::Both; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash.
2484         break;
2485     case AnimationFillModeForwards:
2486         fillMode = PlatformCAAnimation::Forwards;
2487         break;
2488     case AnimationFillModeBoth:
2489         fillMode = PlatformCAAnimation::Both;
2490         break;
2491     }
2492
2493     propertyAnim->setDuration(duration);
2494     propertyAnim->setRepeatCount(repeatCount);
2495     propertyAnim->setAutoreverses(anim->direction() == Animation::AnimationDirectionAlternate || anim->direction() == Animation::AnimationDirectionAlternateReverse);
2496     propertyAnim->setRemovedOnCompletion(false);
2497     propertyAnim->setAdditive(additive);
2498     propertyAnim->setFillMode(fillMode);
2499 }
2500
2501 const TimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue& animValue, const Animation& anim)
2502 {
2503     if (animValue.timingFunction())
2504         return animValue.timingFunction();
2505     if (anim.isTimingFunctionSet())
2506         return anim.timingFunction().get();
2507     
2508     return CubicBezierTimingFunction::defaultTimingFunction();
2509 }
2510
2511 bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim)
2512 {
2513     bool forwards = animation->directionIsForwards();
2514
2515     unsigned fromIndex = !forwards;
2516     unsigned toIndex = forwards;
2517     
2518     switch (valueList.property()) {
2519     case AnimatedPropertyOpacity: {
2520         basicAnim->setFromValue(static_cast<const FloatAnimationValue&>(valueList.at(fromIndex)).value());
2521         basicAnim->setToValue(static_cast<const FloatAnimationValue&>(valueList.at(toIndex)).value());
2522         break;
2523     }
2524     default:
2525         ASSERT_NOT_REACHED(); // we don't animate color yet
2526         break;
2527     }
2528
2529     // This codepath is used for 2-keyframe animations, so we still need to look in the start
2530     // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
2531     const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), *animation);
2532     if (timingFunction)
2533         basicAnim->setTimingFunction(timingFunction, !forwards);
2534
2535     return true;
2536 }
2537
2538 bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim)
2539 {
2540     Vector<float> keyTimes;
2541     Vector<float> values;
2542     Vector<const TimingFunction*> timingFunctions;
2543
2544     bool forwards = animation->directionIsForwards();
2545     
2546     for (unsigned i = 0; i < valueList.size(); ++i) {
2547         unsigned index = forwards ? i : (valueList.size() - i - 1);
2548         const AnimationValue& curValue = valueList.at(index);
2549         keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime()));
2550
2551         switch (valueList.property()) {
2552         case AnimatedPropertyOpacity: {
2553             const FloatAnimationValue& floatValue = static_cast<const FloatAnimationValue&>(curValue);
2554             values.append(floatValue.value());
2555             break;
2556         }
2557         default:
2558             ASSERT_NOT_REACHED(); // we don't animate color yet
2559             break;
2560         }
2561
2562         if (i < (valueList.size() - 1))
2563             timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation));
2564     }
2565     
2566     keyframeAnim->setKeyTimes(keyTimes);
2567     keyframeAnim->setValues(values);
2568     keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
2569     
2570     return true;
2571 }
2572
2573 bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const FloatSize& boxSize)
2574 {
2575     ASSERT(valueList.size() == 2);
2576
2577     bool forwards = animation->directionIsForwards();
2578     
2579     unsigned fromIndex = !forwards;
2580     unsigned toIndex = forwards;
2581     
2582     const TransformAnimationValue& startValue = static_cast<const TransformAnimationValue&>(valueList.at(fromIndex));
2583     const TransformAnimationValue& endValue = static_cast<const TransformAnimationValue&>(valueList.at(toIndex));
2584
2585     if (isMatrixAnimation) {
2586         TransformationMatrix fromTransform, toTransform;
2587         startValue.value().apply(boxSize, fromTransform);
2588         endValue.value().apply(boxSize, toTransform);
2589
2590         // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
2591         if (!fromTransform.isInvertible() || !toTransform.isInvertible())
2592             return false;
2593
2594         basicAnim->setFromValue(fromTransform);
2595         basicAnim->setToValue(toTransform);
2596     } else {
2597         if (isTransformTypeNumber(transformOpType)) {
2598             float fromValue;
2599             getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue);
2600             basicAnim->setFromValue(fromValue);
2601             
2602             float toValue;
2603             getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue);
2604             basicAnim->setToValue(toValue);
2605         } else if (isTransformTypeFloatPoint3D(transformOpType)) {
2606             FloatPoint3D fromValue;
2607             getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue);
2608             basicAnim->setFromValue(fromValue);
2609             
2610             FloatPoint3D toValue;
2611             getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue);
2612             basicAnim->setToValue(toValue);
2613         } else {
2614             TransformationMatrix fromValue;
2615             getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue);
2616             basicAnim->setFromValue(fromValue);
2617
2618             TransformationMatrix toValue;
2619             getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue);
2620             basicAnim->setToValue(toValue);
2621         }
2622     }
2623
2624     // This codepath is used for 2-keyframe animations, so we still need to look in the start
2625     // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
2626     const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), *animation);
2627     basicAnim->setTimingFunction(timingFunction, !forwards);
2628
2629     PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
2630     if (valueFunction != PlatformCAAnimation::NoValueFunction)
2631         basicAnim->setValueFunction(valueFunction);
2632
2633     return true;
2634 }
2635
2636 bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const FloatSize& boxSize)
2637 {
2638     Vector<float> keyTimes;
2639     Vector<float> floatValues;
2640     Vector<FloatPoint3D> floatPoint3DValues;
2641     Vector<TransformationMatrix> transformationMatrixValues;
2642     Vector<const TimingFunction*> timingFunctions;
2643
2644     bool forwards = animation->directionIsForwards();
2645
2646     for (unsigned i = 0; i < valueList.size(); ++i) {
2647         unsigned index = forwards ? i : (valueList.size() - i - 1);
2648         const TransformAnimationValue& curValue = static_cast<const TransformAnimationValue&>(valueList.at(index));
2649         keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime()));
2650
2651         TransformationMatrix transform;
2652
2653         if (isMatrixAnimation) {
2654             curValue.value().apply(boxSize, transform);
2655
2656             // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
2657             if (!transform.isInvertible())
2658                 return false;
2659
2660             transformationMatrixValues.append(transform);
2661         } else {
2662             const TransformOperation* transformOp = curValue.value().at(functionIndex);
2663             if (isTransformTypeNumber(transformOpType)) {
2664                 float value;
2665                 getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
2666                 floatValues.append(value);
2667             } else if (isTransformTypeFloatPoint3D(transformOpType)) {
2668                 FloatPoint3D value;
2669                 getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
2670                 floatPoint3DValues.append(value);
2671             } else {
2672                 TransformationMatrix value;
2673                 getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
2674                 transformationMatrixValues.append(value);
2675             }
2676
2677             curValue.value().apply(boxSize, transform);
2678         }
2679
2680         if (i < (valueList.size() - 1))
2681             timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation));
2682     }
2683     
2684     keyframeAnim->setKeyTimes(keyTimes);
2685     
2686     if (isTransformTypeNumber(transformOpType))
2687         keyframeAnim->setValues(floatValues);
2688     else if (isTransformTypeFloatPoint3D(transformOpType))
2689         keyframeAnim->setValues(floatPoint3DValues);
2690     else
2691         keyframeAnim->setValues(transformationMatrixValues);
2692         
2693     keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
2694
2695     PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
2696     if (valueFunction != PlatformCAAnimation::NoValueFunction)
2697         keyframeAnim->setValueFunction(valueFunction);
2698
2699     return true;
2700 }
2701
2702 #if ENABLE(CSS_FILTERS)
2703 bool GraphicsLayerCA::setFilterAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim, int functionIndex, int internalFilterPropertyIndex)
2704 {
2705     ASSERT(valueList.size() == 2);
2706
2707     bool forwards = animation->directionIsForwards();
2708
2709     unsigned fromIndex = !forwards;
2710     unsigned toIndex = forwards;
2711
2712     const FilterAnimationValue& fromValue = static_cast<const FilterAnimationValue&>(valueList.at(fromIndex));
2713     const FilterAnimationValue& toValue = static_cast<const FilterAnimationValue&>(valueList.at(toIndex));
2714
2715     const FilterOperation* fromOperation = fromValue.value().at(functionIndex);
2716     const FilterOperation* toOperation = toValue.value().at(functionIndex);
2717
2718     RefPtr<DefaultFilterOperation> defaultFromOperation;
2719     RefPtr<DefaultFilterOperation> defaultToOperation;
2720
2721     ASSERT(fromOperation || toOperation);
2722
2723     if (!fromOperation) {
2724         defaultFromOperation = DefaultFilterOperation::create(toOperation->type());
2725         fromOperation = defaultFromOperation.get();
2726     }
2727
2728     if (!toOperation) {
2729         defaultToOperation = DefaultFilterOperation::create(fromOperation->type());
2730         toOperation = defaultToOperation.get();
2731     }
2732
2733     basicAnim->setFromValue(fromOperation, internalFilterPropertyIndex);
2734     basicAnim->setToValue(toOperation, internalFilterPropertyIndex);
2735
2736     // This codepath is used for 2-keyframe animations, so we still need to look in the start
2737     // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
2738     basicAnim->setTimingFunction(timingFunctionForAnimationValue(valueList.at(0), *animation), !forwards);
2739
2740     return true;
2741 }
2742
2743 bool GraphicsLayerCA::setFilterAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, int internalFilterPropertyIndex, FilterOperation::OperationType filterOp)
2744 {
2745     Vector<float> keyTimes;
2746     Vector<RefPtr<FilterOperation>> values;
2747     Vector<const TimingFunction*> timingFunctions;
2748     RefPtr<DefaultFilterOperation> defaultOperation;
2749
2750     bool forwards = animation->directionIsForwards();
2751
2752     for (unsigned i = 0; i < valueList.size(); ++i) {
2753         unsigned index = forwards ? i : (valueList.size() - i - 1);
2754         const FilterAnimationValue& curValue = static_cast<const FilterAnimationValue&>(valueList.at(index));
2755         keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime()));
2756
2757         if (curValue.value().operations().size() > static_cast<size_t>(functionIndex))
2758             values.append(curValue.value().operations()[functionIndex]);
2759         else {
2760             if (!defaultOperation)
2761                 defaultOperation = DefaultFilterOperation::create(filterOp);
2762             values.append(defaultOperation);
2763         }
2764
2765         if (i < (valueList.size() - 1))
2766             timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation));
2767     }
2768     
2769     keyframeAnim->setKeyTimes(keyTimes);
2770     keyframeAnim->setValues(values, internalFilterPropertyIndex);
2771     keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
2772
2773     return true;
2774 }
2775 #endif
2776
2777 void GraphicsLayerCA::suspendAnimations(double time)
2778 {
2779     double t = PlatformCALayer::currentTimeToMediaTime(time ? time : monotonicallyIncreasingTime());
2780     primaryLayer()->setSpeed(0);
2781     primaryLayer()->setTimeOffset(t);
2782
2783     // Suspend the animations on the clones too.
2784     if (LayerMap* layerCloneMap = primaryLayerClones()) {
2785         LayerMap::const_iterator end = layerCloneMap->end();
2786         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2787             it->value->setSpeed(0);
2788             it->value->setTimeOffset(t);
2789         }
2790     }
2791 }
2792
2793 void GraphicsLayerCA::resumeAnimations()
2794 {
2795     primaryLayer()->setSpeed(1);
2796     primaryLayer()->setTimeOffset(0);
2797
2798     // Resume the animations on the clones too.
2799     if (LayerMap* layerCloneMap = primaryLayerClones()) {
2800         LayerMap::const_iterator end = layerCloneMap->end();
2801         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2802             it->value->setSpeed(1);
2803             it->value->setTimeOffset(0);
2804         }
2805     }
2806 }
2807
2808 PlatformCALayer* GraphicsLayerCA::hostLayerForSublayers() const
2809 {
2810     return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); 
2811 }
2812
2813 PlatformCALayer* GraphicsLayerCA::layerForSuperlayer() const
2814 {
2815     return m_structuralLayer ? m_structuralLayer.get() : m_layer.get();
2816 }
2817
2818 PlatformCALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const
2819 {
2820     return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer();
2821 }
2822
2823 GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const
2824 {
2825     return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones();
2826 }
2827
2828 void GraphicsLayerCA::updateContentsScale(float pageScaleFactor)
2829 {
2830     float contentsScale = pageScaleFactor * deviceScaleFactor();
2831
2832     if (m_isPageTiledBackingLayer && tiledBacking()) {
2833         float zoomedOutScale = m_client.zoomedOutPageScaleFactor() * deviceScaleFactor();
2834         tiledBacking()->setZoomedOutContentsScale(zoomedOutScale);
2835     }
2836
2837     if (contentsScale == m_layer->contentsScale())
2838         return;
2839
2840     m_layer->setContentsScale(contentsScale);
2841
2842     if (tiledBacking()) {
2843         // Scale change may swap in a different set of tiles changing the custom child layers.
2844         if (m_isPageTiledBackingLayer)
2845             m_uncommittedChanges |= ChildrenChanged;
2846         // Tiled backing repaints automatically on scale change.
2847         return;
2848     }
2849
2850     if (drawsContent())
2851         m_layer->setNeedsDisplay();
2852 }
2853
2854 void GraphicsLayerCA::updateCustomAppearance()
2855 {
2856     m_layer->updateCustomAppearance(m_customAppearance);
2857 }
2858
2859 void GraphicsLayerCA::updateCustomBehavior()
2860 {
2861     m_layer->updateCustomBehavior(m_customBehavior);
2862 }
2863
2864 void GraphicsLayerCA::setShowDebugBorder(bool showBorder)
2865 {
2866     if (showBorder == m_showDebugBorder)
2867         return;
2868
2869     GraphicsLayer::setShowDebugBorder(showBorder);
2870     noteLayerPropertyChanged(DebugIndicatorsChanged);
2871 }
2872
2873 void GraphicsLayerCA::setShowRepaintCounter(bool showCounter)
2874 {
2875     if (showCounter == m_showRepaintCounter)
2876         return;
2877
2878     GraphicsLayer::setShowRepaintCounter(showCounter);
2879     noteLayerPropertyChanged(DebugIndicatorsChanged);
2880 }
2881
2882 void GraphicsLayerCA::setDebugBackgroundColor(const Color& color)
2883 {    
2884     if (color.isValid())
2885         m_layer->setBackgroundColor(color);
2886     else
2887         m_layer->setBackgroundColor(Color::transparent);
2888 }
2889
2890 void GraphicsLayerCA::getDebugBorderInfo(Color& color, float& width) const
2891 {
2892     if (m_isPageTiledBackingLayer) {
2893         color = Color(0, 0, 128, 128); // tile cache layer: dark blue
2894         width = 0.5;
2895         return;
2896     }
2897
2898     GraphicsLayer::getDebugBorderInfo(color, width);
2899 }
2900
2901 void GraphicsLayerCA::dumpAdditionalProperties(TextStream& textStream, int indent, LayerTreeAsTextBehavior behavior) const
2902 {
2903     if (behavior & LayerTreeAsTextIncludeVisibleRects) {
2904         writeIndent(textStream, indent + 1);
2905         textStream << "(visible rect " << m_visibleRect.x() << ", " << m_visibleRect.y() << " " << m_visibleRect.width() << " x " << m_visibleRect.height() << ")\n";
2906
2907         writeIndent(textStream, indent + 1);
2908         textStream << "(contentsScale " << m_layer->contentsScale() << ")\n";
2909     }
2910
2911     if (tiledBacking() && (behavior & LayerTreeAsTextIncludeTileCaches)) {
2912         if (behavior & LayerTreeAsTextDebug) {
2913             writeIndent(textStream, indent + 1);
2914             textStream << "(tiled backing " << tiledBacking() << ")\n";
2915         }
2916
2917         IntRect tileCoverageRect = tiledBacking()->tileCoverageRect();
2918         writeIndent(textStream, indent + 1);
2919         textStream << "(tile cache coverage " << tileCoverageRect.x() << ", " << tileCoverageRect.y() << " " << tileCoverageRect.width() << " x " << tileCoverageRect.height() << ")\n";
2920
2921         IntSize tileSize = tiledBacking()->tileSize();
2922         writeIndent(textStream, indent + 1);
2923         textStream << "(tile size " << tileSize.width() << " x " << tileSize.height() << ")\n";
2924         
2925         IntRect gridExtent = tiledBacking()->tileGridExtent();
2926         writeIndent(textStream, indent + 1);
2927         textStream << "(top left tile " << gridExtent.x() << ", " << gridExtent.y() << " tiles grid " << gridExtent.width() << " x " << gridExtent.height() << ")\n";
2928     }
2929     
2930     if (behavior & LayerTreeAsTextIncludeContentLayers) {
2931         if (m_contentsClippingLayer) {
2932             writeIndent(textStream, indent + 1);
2933             textStream << "(contents clipping layer " << m_contentsClippingLayer->position().x() << ", " << m_contentsClippingLayer->position().y()
2934                 << " " << m_contentsClippingLayer->bounds().width() << " x " << m_contentsClippingLayer->bounds().height() << ")\n";
2935         }
2936
2937         if (m_contentsLayer) {
2938             writeIndent(textStream, indent + 1);
2939             textStream << "(contents layer " << m_contentsLayer->position().x() << ", " << m_contentsLayer->position().y()
2940                 << " " << m_contentsLayer->bounds().width() << " x " << m_contentsLayer->bounds().height() << ")\n";
2941         }
2942     }
2943 }
2944
2945 void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth)
2946 {    
2947     if (color.isValid()) {
2948         m_layer->setBorderColor(color);
2949         m_layer->setBorderWidth(borderWidth);
2950     } else {
2951         m_layer->setBorderColor(Color::transparent);
2952         m_layer->setBorderWidth(0);
2953     }
2954 }
2955
2956 void GraphicsLayerCA::setCustomAppearance(CustomAppearance customAppearance)
2957 {
2958     if (customAppearance == m_customAppearance)
2959         return;
2960
2961     GraphicsLayer::setCustomAppearance(customAppearance);
2962     noteLayerPropertyChanged(CustomAppearanceChanged);
2963 }
2964
2965 void GraphicsLayerCA::setCustomBehavior(CustomBehavior customBehavior)
2966 {
2967     if (customBehavior == m_customBehavior)
2968         return;
2969
2970     GraphicsLayer::setCustomBehavior(customBehavior);
2971     noteLayerPropertyChanged(CustomBehaviorChanged);
2972 }
2973
2974 bool GraphicsLayerCA::requiresTiledLayer(float pageScaleFactor) const
2975 {
2976     if (!m_drawsContent || m_isPageTiledBackingLayer)
2977         return false;
2978
2979     // FIXME: catch zero-size height or width here (or earlier)?
2980 #if PLATFORM(IOS)
2981     int maxPixelDimension = systemMemoryLevel() < cMemoryLevelToUseSmallerPixelDimension ? cMaxPixelDimensionLowMemory : cMaxPixelDimension;
2982     return m_size.width() * pageScaleFactor > maxPixelDimension || m_size.height() * pageScaleFactor > maxPixelDimension;
2983 #else
2984     return m_size.width() * pageScaleFactor > cMaxPixelDimension || m_size.height() * pageScaleFactor > cMaxPixelDimension;
2985 #endif
2986 }
2987
2988 void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer)
2989 {
2990     ASSERT(m_layer->layerType() != PlatformCALayer::LayerTypePageTiledBackingLayer);
2991     ASSERT(useTiledLayer != m_usingTiledBacking);
2992     RefPtr<PlatformCALayer> oldLayer = m_layer;
2993
2994     PlatformCALayer::LayerType layerType = useTiledLayer ? PlatformCALayer::LayerTypeTiledBackingLayer : PlatformCALayer::LayerTypeWebLayer;
2995
2996     m_layer = createPlatformCALayer(layerType, this);
2997
2998     m_usingTiledBacking = useTiledLayer;
2999     
3000     m_layer->adoptSublayers(oldLayer.get());
3001
3002 #ifdef VISIBLE_TILE_WASH
3003     if (m_visibleTileWashLayer)
3004         m_layer->appendSublayer(m_visibleTileWashLayer.get());
3005 #endif
3006
3007     if (isMaskLayer()) {
3008         // A mask layer's superlayer is the layer that it masks. Set the MaskLayerChanged dirty bit
3009         // so that the parent will fix up the platform layers in commitLayerChangesAfterSublayers().
3010         if (GraphicsLayer* parentLayer = parent())
3011             toGraphicsLayerCA(parentLayer)->noteLayerPropertyChanged(MaskLayerChanged);
3012     } else if (oldLayer->superlayer()) {
3013         // Skip this step if we don't have a superlayer. This is probably a benign
3014         // case that happens while restructuring the layer tree, and also occurs with
3015         // WebKit2 page overlays, which can become tiled but are out-of-tree.
3016         oldLayer->superlayer()->replaceSublayer(oldLayer.get(), m_layer.get());
3017     }
3018
3019     m_uncommittedChanges |= ChildrenChanged
3020         | GeometryChanged
3021         | TransformChanged
3022         | ChildrenTransformChanged
3023         | MasksToBoundsChanged
3024         | ContentsOpaqueChanged
3025         | BackfaceVisibilityChanged
3026         | BackgroundColorChanged
3027         | ContentsScaleChanged
3028         | AcceleratesDrawingChanged
3029         | FiltersChanged
3030         | MaskLayerChanged
3031         | OpacityChanged
3032         | DebugIndicatorsChanged;
3033     
3034     if (m_usingTiledBacking)
3035         m_uncommittedChanges |= VisibleRectChanged;
3036
3037 #ifndef NDEBUG
3038     String name = String::format("%sCALayer(%p) GraphicsLayer(%p) ", (m_layer->layerType() == PlatformCALayer::LayerTypeWebTiledLayer) ? "Tiled " : "", m_layer->platformLayer(), this) + m_name;
3039     m_layer->setName(name);
3040 #endif
3041
3042     // move over animations
3043     moveOrCopyAnimations(Move, oldLayer.get(), m_layer.get());
3044     
3045     // need to tell new layer to draw itself
3046     setNeedsDisplay();
3047     
3048     client().tiledBackingUsageChanged(this, m_usingTiledBacking);
3049 }
3050
3051 GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const
3052 {
3053     return CompositingCoordinatesTopDown;
3054 }
3055
3056 void GraphicsLayerCA::setupContentsLayer(PlatformCALayer* contentsLayer)
3057 {
3058     // Turn off implicit animations on the inner layer.
3059 #if !PLATFORM(IOS)
3060     contentsLayer->setMasksToBounds(true);
3061 #endif
3062
3063     if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) {
3064         TransformationMatrix flipper(
3065             1.0f, 0.0f, 0.0f, 0.0f,
3066             0.0f, -1.0f, 0.0f, 0.0f,
3067             0.0f, 0.0f, 1.0f, 0.0f,
3068             0.0f, 0.0f, 0.0f, 1.0f);
3069         contentsLayer->setTransform(flipper);
3070         contentsLayer->setAnchorPoint(FloatPoint3D(0, 1, 0));
3071     } else
3072         contentsLayer->setAnchorPoint(FloatPoint3D());
3073
3074     if (isShowingDebugBorder()) {
3075         contentsLayer->setBorderColor(Color(0, 0, 128, 180));
3076         contentsLayer->setBorderWidth(4);
3077     }
3078 }
3079
3080 PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, PlatformCALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel)
3081 {
3082     if (!sourceLayer)
3083         return 0;
3084
3085     RefPtr<PlatformCALayer> resultLayer;
3086
3087     // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells
3088     // us whether there's an item there. This technique avoids two hash lookups.
3089     RefPtr<PlatformCALayer> dummy;
3090     LayerMap::AddResult addResult = clones->add(cloneID, dummy);
3091     if (!addResult.isNewEntry) {
3092         // Value was not added, so it exists already.
3093         resultLayer = addResult.iterator->value.get();
3094     } else {
3095         resultLayer = cloneLayer(sourceLayer, cloneLevel);
3096 #ifndef NDEBUG
3097         resultLayer->setName(String::format("Clone %d of layer %llu", cloneID[0U], sourceLayer->layerID()));
3098 #endif
3099         addResult.iterator->value = resultLayer;
3100     }
3101
3102     return resultLayer;
3103 }   
3104
3105 void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer,
3106     RefPtr<PlatformCALayer>& contentsLayer, RefPtr<PlatformCALayer>& contentsClippingLayer, CloneLevel cloneLevel)
3107 {
3108     structuralLayer = 0;
3109     contentsLayer = 0;
3110
3111     if (!m_layerClones)
3112         m_layerClones = adoptPtr(new LayerMap);
3113
3114     if (!m_structuralLayerClones && m_structuralLayer)
3115         m_structuralLayerClones = adoptPtr(new LayerMap);
3116
3117     if (!m_contentsLayerClones && m_contentsLayer)
3118         m_contentsLayerClones = adoptPtr(new LayerMap);
3119
3120     if (!m_contentsClippingLayerClones && m_contentsClippingLayer)
3121         m_contentsClippingLayerClones = adoptPtr(new LayerMap);
3122
3123     primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel);
3124     structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel);
3125     contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel);
3126     contentsClippingLayer = findOrMakeClone(cloneID, m_contentsClippingLayer.get(), m_contentsClippingLayerClones.get(), cloneLevel);
3127 }
3128
3129 void GraphicsLayerCA::removeCloneLayers()
3130 {
3131     m_layerClones = nullptr;
3132     m_structuralLayerClones = nullptr;
3133     m_contentsLayerClones = nullptr;
3134     m_contentsClippingLayerClones = nullptr;
3135 }
3136
3137 FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const
3138 {
3139     // This can get called during a flush when we've just removed the m_replicaLayer.
3140     if (!m_replicaLayer)
3141         return FloatPoint();
3142
3143     FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition();
3144     return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(),
3145                       replicaPosition.y() + m_anchorPoint.y() * m_size.height());
3146 }
3147
3148 void GraphicsLayerCA::propagateLayerChangeToReplicas()
3149 {
3150     for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) {
3151         GraphicsLayerCA* currLayerCA = toGraphicsLayerCA(currLayer);
3152         if (!currLayerCA->hasCloneLayers())
3153             break;
3154
3155         if (currLayerCA->replicaLayer())
3156             toGraphicsLayerCA(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged);
3157     }
3158 }
3159
3160 PassRefPtr<PlatformCALayer> GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel)
3161 {
3162     RefPtr<PlatformCALayer> primaryLayer;
3163     RefPtr<PlatformCALayer> structuralLayer;
3164     RefPtr<PlatformCALayer> contentsLayer;
3165     RefPtr<PlatformCALayer> contentsClippingLayer;
3166     ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, contentsClippingLayer, cloneLevel);
3167
3168     if (m_maskLayer) {
3169         RefPtr<PlatformCALayer> maskClone = toGraphicsLayerCA(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
3170         primaryLayer->setMask(maskClone.get());
3171     }
3172
3173     if (m_replicatedLayer) {
3174         // We are a replica being asked for clones of our layers.
3175         RefPtr<PlatformCALayer> replicaRoot = replicatedLayerRoot(replicaState);
3176         if (!replicaRoot)
3177             return 0;
3178
3179         if (structuralLayer) {
3180             structuralLayer->insertSublayer(replicaRoot.get(), 0);
3181             return structuralLayer;
3182         }
3183         
3184         primaryLayer->insertSublayer(replicaRoot.get(), 0);
3185         return primaryLayer;
3186     }
3187
3188     const Vector<GraphicsLayer*>& childLayers = children();
3189     Vector<RefPtr<PlatformCALayer>> clonalSublayers;
3190
3191     RefPtr<PlatformCALayer> replicaLayer;
3192     
3193     if (m_replicaLayer && m_replicaLayer != replicaRoot) {
3194         // We have nested replicas. Ask the replica layer for a clone of its contents.
3195         replicaState.setBranchType(ReplicaState::ReplicaBranch);
3196         replicaLayer = toGraphicsLayerCA(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel);
3197         replicaState.setBranchType(ReplicaState::ChildBranch);
3198     }
3199
3200     if (contentsClippingLayer) {
3201         ASSERT(contentsLayer);
3202         contentsClippingLayer->appendSublayer(contentsLayer.get());
3203     }
3204     
3205     if (replicaLayer || structuralLayer || contentsLayer || contentsClippingLayer || childLayers.size() > 0) {
3206         if (structuralLayer) {
3207             // Replicas render behind the actual layer content.
3208             if (replicaLayer)
3209                 clonalSublayers.append(replicaLayer);
3210                 
3211             // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind.
3212             clonalSublayers.append(primaryLayer);
3213         } else if (contentsClippingLayer) {
3214             // FIXME: add the contents layer in the correct order with negative z-order children.
3215             // This does not cause visible rendering issues because currently contents layers are only used
3216             // for replaced elements that don't have children.
3217             clonalSublayers.append(contentsClippingLayer);
3218         } else if (contentsLayer) {
3219             // FIXME: add the contents layer in the correct order with negative z-order children.
3220             // This does not cause visible rendering issues because currently contents layers are only used
3221             // for replaced elements that don't have children.
3222             clonalSublayers.append(contentsLayer);
3223         }
3224         
3225         replicaState.push(ReplicaState::ChildBranch);
3226
3227         size_t numChildren = childLayers.size();
3228         for (size_t i = 0; i < numChildren; ++i) {
3229             GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
3230
3231             RefPtr<PlatformCALayer> childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
3232             if (childLayer)
3233                 clonalSublayers.append(childLayer);
3234         }
3235
3236         replicaState.pop();
3237
3238         for (size_t i = 0; i < clonalSublayers.size(); ++i)
3239             clonalSublayers[i]->removeFromSuperlayer();
3240     }
3241     
3242     RefPtr<PlatformCALayer> result;
3243     if (structuralLayer) {
3244         structuralLayer->setSublayers(clonalSublayers);
3245
3246         if (contentsClippingLayer || contentsLayer) {
3247             // If we have a transform layer, then the contents layer is parented in the 
3248             // primary layer (which is itself a child of the transform layer).
3249             primaryLayer->removeAllSublayers();
3250             primaryLayer->appendSublayer(contentsClippingLayer ? contentsClippingLayer.get() : contentsLayer.get());
3251         }
3252
3253         result = structuralLayer;
3254     } else {
3255         primaryLayer->setSublayers(clonalSublayers);
3256         result = primaryLayer;
3257     }
3258
3259     return result;
3260 }
3261
3262 PassRefPtr<PlatformCALayer> GraphicsLayerCA::cloneLayer(PlatformCALayer *layer, CloneLevel cloneLevel)
3263 {
3264     RefPtr<PlatformCALayer> newLayer = layer->clone(this);
3265
3266     if (cloneLevel == IntermediateCloneLevel) {
3267         newLayer->setOpacity(layer->opacity());
3268         moveOrCopyAnimations(Copy, layer, newLayer.get());
3269     }
3270     
3271     if (isShowingDebugBorder()) {
3272         newLayer->setBorderColor(Color(255, 122, 251));
3273         newLayer->setBorderWidth(2);
3274     }
3275     
3276     return newLayer;
3277 }
3278
3279 void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity)
3280 {
3281     LayerMap* layerCloneMap = 0;
3282     
3283     if (preserves3D()) {
3284         m_layer->setOpacity(accumulatedOpacity);
3285         layerCloneMap = m_layerClones.get();
3286     } else {
3287         primaryLayer()->setOpacity(accumulatedOpacity);
3288         layerCloneMap = primaryLayerClones();
3289     }
3290
3291     if (layerCloneMap) {
3292         LayerMap::const_iterator end = layerCloneMap->end();
3293         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
3294             if (m_replicaLayer && isReplicatedRootClone(it->key))
3295                 continue;
3296             it->value->setOpacity(m_opacity);
3297         }
3298     }
3299 }
3300
3301 void GraphicsLayerCA::updateOpacityOnLayer()
3302 {
3303     primaryLayer()->setOpacity(m_opacity);
3304
3305     if (LayerMap* layerCloneMap = primaryLayerClones()) {
3306         LayerMap::const_iterator end = layerCloneMap->end();
3307         for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
3308             if (m_replicaLayer && isReplicatedRootClone(it->key))
3309                 continue;
3310
3311             it->value->setOpacity(m_opacity);
3312         }
3313         
3314     }
3315 }
3316
3317 void GraphicsLayerCA::deviceOrPageScaleFactorChanged()
3318 {
3319     noteChangesForScaleSensitiveProperties();
3320 }
3321
3322 void GraphicsLayerCA::noteChangesForScaleSensitiveProperties()
3323 {
3324     noteLayerPropertyChanged(GeometryChanged | ContentsScaleChanged | ContentsOpaqueChanged);
3325 }
3326
3327 void GraphicsLayerCA::computePixelAlignment(float pageScale, const FloatPoint& positionRelativeToBase,
3328     FloatPoint& position, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset) const
3329 {
3330     FloatRect baseRelativeBounds(positionRelativeToBase, m_size);
3331     FloatRect scaledBounds = baseRelativeBounds;
3332     float contentsScale = pageScale * deviceScaleFactor();
3333     // Scale by the page scale factor to compute the screen-relative bounds.
3334     scaledBounds.scale(contentsScale);
3335     // Round to integer boundaries.
3336     FloatRect alignedBounds = encloseRectToDevicePixels(LayoutRect(scaledBounds), deviceScaleFactor());
3337     
3338     // Convert back to layer coordinates.
3339     alignedBounds.scale(1 / contentsScale);
3340
3341     alignmentOffset = baseRelativeBounds.location() - alignedBounds.location();
3342     position = m_position - alignmentOffset;
3343
3344     // Now we have to compute a new anchor point which compensates for rounding.
3345     float anchorPointX = m_anchorPoint.x();
3346     float anchorPointY = m_anchorPoint.y();
3347     
3348     if (alignedBounds.width())
3349         anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width();
3350     
3351     if (alignedBounds.height())
3352         anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height();
3353      
3354     anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * contentsScale);
3355 }
3356
3357 void GraphicsLayerCA::noteSublayersChanged(ScheduleFlushOrNot scheduleFlush)
3358 {
3359     noteLayerPropertyChanged(ChildrenChanged, scheduleFlush);
3360     propagateLayerChangeToReplicas();
3361 }
3362
3363 bool GraphicsLayerCA::canThrottleLayerFlush() const
3364 {
3365     // Tile layers are currently plain CA layers, attached directly by TileController. They require immediate flush as they may contain garbage.
3366     return !(m_uncommittedChanges & TilesAdded);
3367 }
3368
3369 void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags, ScheduleFlushOrNot scheduleFlush)
3370 {
3371     bool hadUncommittedChanges = !!m_uncommittedChanges;
3372     bool oldCanThrottleLayerFlush = canThrottleLayerFlush();
3373
3374     m_uncommittedChanges |= flags;
3375
3376     if (scheduleFlush == ScheduleFlush) {
3377         bool needsFlush = !hadUncommittedChanges || oldCanThrottleLayerFlush != canThrottleLayerFlush();
3378         if (needsFlush)
3379             client().notifyFlushRequired(this);
3380     }
3381 }
3382
3383 double GraphicsLayerCA::backingStoreMemoryEstimate() const
3384 {
3385     if (!drawsContent())
3386         return 0;
3387
3388     // contentsLayer is given to us, so we don't really know anything about its contents.
3389     // FIXME: ignores layer clones.
3390     
3391     if (TiledBacking* tiledBacking = this->tiledBacking())
3392         return tiledBacking->retainedTileBackingStoreMemory();
3393
3394     return 4.0 * size().width() * m_layer->contentsScale() * size().height() * m_layer->contentsScale();
3395 }
3396
3397 } // namespace WebCore