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