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