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