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