2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "GraphicsLayerCA.h"
30 #include "Animation.h"
31 #include "FloatConversion.h"
32 #include "FloatRect.h"
33 #include "GraphicsLayerFactory.h"
35 #include "PlatformCAFilters.h"
36 #include "PlatformCALayer.h"
37 #include "RotateTransformOperation.h"
38 #include "ScaleTransformOperation.h"
39 #include "TextStream.h"
40 #include "TiledBacking.h"
41 #include "TransformState.h"
42 #include "TranslateTransformOperation.h"
43 #include <QuartzCore/CATransform3D.h>
45 #include <wtf/CurrentTime.h>
46 #include <wtf/TemporaryChange.h>
47 #include <wtf/text/WTFString.h>
50 #include "SystemMemory.h"
51 #include "WebCoreThread.h"
55 #include "PlatformCAAnimationMac.h"
56 #include "PlatformCALayerMac.h"
57 #include "WebCoreSystemInterface.h"
61 #include "PlatformCAAnimationWin.h"
62 #include "PlatformCALayerWin.h"
67 // The threshold width or height above which a tiled layer will be used. This should be
68 // large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL
69 // texture size limit on all supported hardware.
71 static const int cMaxPixelDimension = 1280;
72 static const int cMaxPixelDimensionLowMemory = 1024;
73 static const int cMemoryLevelToUseSmallerPixelDimension = 35;
75 static const int cMaxPixelDimension = 2000;
78 // Derived empirically: <rdar://problem/13401861>
79 static const int cMaxLayerTreeDepth = 250;
81 // If we send a duration of 0 to CA, then it will use the default duration
82 // of 250ms. So send a very small value instead.
83 static const float cAnimationAlmostZeroDuration = 1e-3f;
85 static inline bool isIntegral(float value)
87 return static_cast<int>(value) == value;
90 static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType)
92 switch (transformType) {
93 case TransformOperation::SKEW_X:
94 case TransformOperation::SKEW_Y:
95 case TransformOperation::SKEW:
96 case TransformOperation::MATRIX:
97 case TransformOperation::ROTATE_3D:
98 case TransformOperation::MATRIX_3D:
99 case TransformOperation::PERSPECTIVE:
100 case TransformOperation::IDENTITY:
101 case TransformOperation::NONE:
108 static bool isTransformTypeFloatPoint3D(TransformOperation::OperationType transformType)
110 switch (transformType) {
111 case TransformOperation::SCALE:
112 case TransformOperation::SCALE_3D:
113 case TransformOperation::TRANSLATE:
114 case TransformOperation::TRANSLATE_3D:
121 static bool isTransformTypeNumber(TransformOperation::OperationType transformType)
123 return !isTransformTypeTransformationMatrix(transformType) && !isTransformTypeFloatPoint3D(transformType);
126 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const FloatSize& size, float& value)
128 switch (transformType) {
129 case TransformOperation::ROTATE:
130 case TransformOperation::ROTATE_X:
131 case TransformOperation::ROTATE_Y:
132 value = transformOp ? narrowPrecisionToFloat(deg2rad(toRotateTransformOperation(transformOp)->angle())) : 0;
134 case TransformOperation::SCALE_X:
135 value = transformOp ? narrowPrecisionToFloat(toScaleTransformOperation(transformOp)->x()) : 1;
137 case TransformOperation::SCALE_Y:
138 value = transformOp ? narrowPrecisionToFloat(toScaleTransformOperation(transformOp)->y()) : 1;
140 case TransformOperation::SCALE_Z:
141 value = transformOp ? narrowPrecisionToFloat(toScaleTransformOperation(transformOp)->z()) : 1;
143 case TransformOperation::TRANSLATE_X:
144 value = transformOp ? narrowPrecisionToFloat(toTranslateTransformOperation(transformOp)->x(size)) : 0;
146 case TransformOperation::TRANSLATE_Y:
147 value = transformOp ? narrowPrecisionToFloat(toTranslateTransformOperation(transformOp)->y(size)) : 0;
149 case TransformOperation::TRANSLATE_Z:
150 value = transformOp ? narrowPrecisionToFloat(toTranslateTransformOperation(transformOp)->z(size)) : 0;
157 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const FloatSize& size, FloatPoint3D& value)
159 switch (transformType) {
160 case TransformOperation::SCALE:
161 case TransformOperation::SCALE_3D: {
162 const ScaleTransformOperation* scaleTransformOp = toScaleTransformOperation(transformOp);
163 value.setX(scaleTransformOp ? narrowPrecisionToFloat(scaleTransformOp->x()) : 1);
164 value.setY(scaleTransformOp ? narrowPrecisionToFloat(scaleTransformOp->y()) : 1);
165 value.setZ(scaleTransformOp ? narrowPrecisionToFloat(scaleTransformOp->z()) : 1);
168 case TransformOperation::TRANSLATE:
169 case TransformOperation::TRANSLATE_3D: {
170 const TranslateTransformOperation* translateTransformOp = toTranslateTransformOperation(transformOp);
171 value.setX(translateTransformOp ? narrowPrecisionToFloat(translateTransformOp->x(size)) : 0);
172 value.setY(translateTransformOp ? narrowPrecisionToFloat(translateTransformOp->y(size)) : 0);
173 value.setZ(translateTransformOp ? narrowPrecisionToFloat(translateTransformOp->z(size)) : 0);
181 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const FloatSize& size, TransformationMatrix& value)
183 switch (transformType) {
184 case TransformOperation::SKEW_X:
185 case TransformOperation::SKEW_Y:
186 case TransformOperation::SKEW:
187 case TransformOperation::MATRIX:
188 case TransformOperation::ROTATE_3D:
189 case TransformOperation::MATRIX_3D:
190 case TransformOperation::PERSPECTIVE:
191 case TransformOperation::IDENTITY:
192 case TransformOperation::NONE:
194 transformOp->apply(value, size);
196 value.makeIdentity();
203 static PlatformCAAnimation::ValueFunctionType getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType)
205 // Use literal strings to avoid link-time dependency on those symbols.
206 switch (transformType) {
207 case TransformOperation::ROTATE_X:
208 return PlatformCAAnimation::RotateX;
209 case TransformOperation::ROTATE_Y:
210 return PlatformCAAnimation::RotateY;
211 case TransformOperation::ROTATE:
212 return PlatformCAAnimation::RotateZ;
213 case TransformOperation::SCALE_X:
214 return PlatformCAAnimation::ScaleX;
215 case TransformOperation::SCALE_Y:
216 return PlatformCAAnimation::ScaleY;
217 case TransformOperation::SCALE_Z:
218 return PlatformCAAnimation::ScaleZ;
219 case TransformOperation::TRANSLATE_X:
220 return PlatformCAAnimation::TranslateX;
221 case TransformOperation::TRANSLATE_Y:
222 return PlatformCAAnimation::TranslateY;
223 case TransformOperation::TRANSLATE_Z:
224 return PlatformCAAnimation::TranslateZ;
225 case TransformOperation::SCALE:
226 case TransformOperation::SCALE_3D:
227 return PlatformCAAnimation::Scale;
228 case TransformOperation::TRANSLATE:
229 case TransformOperation::TRANSLATE_3D:
230 return PlatformCAAnimation::Translate;
232 return PlatformCAAnimation::NoValueFunction;
236 static String propertyIdToString(AnimatedPropertyID property)
239 case AnimatedPropertyWebkitTransform:
241 case AnimatedPropertyOpacity:
243 case AnimatedPropertyBackgroundColor:
244 return "backgroundColor";
245 case AnimatedPropertyWebkitFilter:
246 #if ENABLE(CSS_FILTERS)
249 ASSERT_NOT_REACHED();
251 case AnimatedPropertyInvalid:
252 ASSERT_NOT_REACHED();
254 ASSERT_NOT_REACHED();
258 static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index, int subIndex)
260 return animationName + '_' + String::number(property) + '_' + String::number(index) + '_' + String::number(subIndex);
263 static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim)
265 if (anim->timingFunction()->isStepsTimingFunction())
268 for (unsigned i = 0; i < valueList.size(); ++i) {
269 if (const TimingFunction* timingFunction = valueList.at(i).timingFunction()) {
270 if (timingFunction->isStepsTimingFunction())
278 #if ENABLE(CSS_FILTERS) || !ASSERT_DISABLED
279 static inline bool supportsAcceleratedFilterAnimations()
281 // <rdar://problem/10907251> - WebKit2 doesn't support CA animations of CI filters on Lion and below
282 #if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
290 std::unique_ptr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client)
292 std::unique_ptr<GraphicsLayer> graphicsLayer;
294 graphicsLayer = std::make_unique<GraphicsLayerCA>(client);
296 graphicsLayer = factory->createGraphicsLayer(client);
298 graphicsLayer->initialize();
300 return graphicsLayer;
303 #if ENABLE(CSS_FILTERS)
304 bool GraphicsLayerCA::filtersCanBeComposited(const FilterOperations& filters)
307 return PlatformCALayerMac::filtersCanBeComposited(filters);
309 return PlatformCALayerWin::filtersCanBeComposited(filters);
314 PassRefPtr<PlatformCALayer> GraphicsLayerCA::createPlatformCALayer(PlatformCALayer::LayerType layerType, PlatformCALayerClient* owner)
317 return PlatformCALayerMac::create(layerType, owner);
319 return PlatformCALayerWin::create(layerType, owner);
323 PassRefPtr<PlatformCALayer> GraphicsLayerCA::createPlatformCALayer(PlatformLayer* platformLayer, PlatformCALayerClient* owner)
326 return PlatformCALayerMac::create(platformLayer, owner);
328 return PlatformCALayerWin::create(platformLayer, owner);
332 PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createPlatformCAAnimation(PlatformCAAnimation::AnimationType type, const String& keyPath)
335 return PlatformCAAnimationMac::create(type, keyPath);
337 return PlatformCAAnimationWin::create(type, keyPath);
341 GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient& client)
342 : GraphicsLayer(client)
343 , m_contentsLayerPurpose(NoContentsLayer)
344 , m_isPageTiledBackingLayer(false)
345 , m_needsFullRepaint(false)
346 , m_uncommittedChanges(0)
347 , m_isCommittingChanges(false)
351 void GraphicsLayerCA::initialize()
353 PlatformCALayer::LayerType layerType = PlatformCALayer::LayerTypeWebLayer;
354 if (client().shouldUseTiledBacking(this)) {
355 layerType = PlatformCALayer::LayerTypePageTiledBackingLayer;
356 m_isPageTiledBackingLayer = true;
359 m_layer = createPlatformCALayer(layerType, this);
360 noteLayerPropertyChanged(ContentsScaleChanged);
363 GraphicsLayerCA::~GraphicsLayerCA()
365 // Do cleanup while we can still safely call methods on the derived class.
369 void GraphicsLayerCA::willBeDestroyed()
371 // We release our references to the PlatformCALayers here, but do not actively unparent them,
372 // since that will cause a commit and break our batched commit model. The layers will
373 // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers.
375 // Clean up the layer.
377 m_layer->setOwner(nullptr);
380 m_contentsLayer->setOwner(nullptr);
382 if (m_contentsClippingLayer)
383 m_contentsClippingLayer->setOwner(nullptr);
385 if (m_structuralLayer)
386 m_structuralLayer->setOwner(nullptr);
390 GraphicsLayer::willBeDestroyed();
393 void GraphicsLayerCA::setName(const String& name)
395 String caLayerDescription;
397 if (!m_layer->isPlatformCALayerRemote())
398 caLayerDescription = String::format("CALayer(%p) ", m_layer->platformLayer());
400 String longName = caLayerDescription + String::format("GraphicsLayer(%p) ", this) + name;
401 GraphicsLayer::setName(longName);
402 noteLayerPropertyChanged(NameChanged);
405 GraphicsLayer::PlatformLayerID GraphicsLayerCA::primaryLayerID() const
407 return primaryLayer()->layerID();
410 PlatformLayer* GraphicsLayerCA::platformLayer() const
412 return primaryLayer()->platformLayer();
415 bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children)
417 bool childrenChanged = GraphicsLayer::setChildren(children);
419 noteSublayersChanged();
421 return childrenChanged;
424 void GraphicsLayerCA::addChild(GraphicsLayer* childLayer)
426 GraphicsLayer::addChild(childLayer);
427 noteSublayersChanged();
430 void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index)
432 GraphicsLayer::addChildAtIndex(childLayer, index);
433 noteSublayersChanged();
436 void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
438 GraphicsLayer::addChildBelow(childLayer, sibling);
439 noteSublayersChanged();
442 void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
444 GraphicsLayer::addChildAbove(childLayer, sibling);
445 noteSublayersChanged();
448 bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
450 if (GraphicsLayer::replaceChild(oldChild, newChild)) {
451 noteSublayersChanged();
457 void GraphicsLayerCA::removeFromParent()
460 toGraphicsLayerCA(m_parent)->noteSublayersChanged();
461 GraphicsLayer::removeFromParent();
464 void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer)
466 if (layer == m_maskLayer)
469 GraphicsLayer::setMaskLayer(layer);
470 noteLayerPropertyChanged(MaskLayerChanged);
472 propagateLayerChangeToReplicas();
474 if (m_replicatedLayer)
475 toGraphicsLayerCA(m_replicatedLayer)->propagateLayerChangeToReplicas();
478 void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer)
480 if (layer == m_replicatedLayer)
483 GraphicsLayer::setReplicatedLayer(layer);
484 noteLayerPropertyChanged(ReplicatedLayerChanged);
487 void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer)
489 if (layer == m_replicaLayer)
492 GraphicsLayer::setReplicatedByLayer(layer);
493 noteSublayersChanged();
494 noteLayerPropertyChanged(ReplicatedLayerChanged);
497 void GraphicsLayerCA::setPosition(const FloatPoint& point)
499 if (point == m_position)
502 GraphicsLayer::setPosition(point);
503 noteLayerPropertyChanged(GeometryChanged);
506 void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point)
508 if (point == m_anchorPoint)
511 GraphicsLayer::setAnchorPoint(point);
512 noteLayerPropertyChanged(GeometryChanged);
515 void GraphicsLayerCA::setSize(const FloatSize& size)
520 GraphicsLayer::setSize(size);
521 noteLayerPropertyChanged(GeometryChanged);
524 void GraphicsLayerCA::setBoundsOrigin(const FloatPoint& origin)
526 if (origin == m_boundsOrigin)
529 GraphicsLayer::setBoundsOrigin(origin);
530 noteLayerPropertyChanged(GeometryChanged);
533 void GraphicsLayerCA::setTransform(const TransformationMatrix& t)
535 if (t == m_transform)
538 GraphicsLayer::setTransform(t);
539 noteLayerPropertyChanged(TransformChanged);
542 void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t)
544 if (t == m_childrenTransform)
547 GraphicsLayer::setChildrenTransform(t);
548 noteLayerPropertyChanged(ChildrenTransformChanged);
551 void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
553 RefPtr<PlatformCAAnimation> anim = fromLayer->animationForKey(animationIdentifier);
559 fromLayer->removeAnimationForKey(animationIdentifier);
560 toLayer->addAnimationForKey(animationIdentifier, anim.get());
564 toLayer->addAnimationForKey(animationIdentifier, anim.get());
569 void GraphicsLayerCA::moveOrCopyAnimations(MoveOrCopy operation, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
571 // Look for running animations affecting this property.
572 AnimationsMap::const_iterator end = m_runningAnimations.end();
573 for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
574 const Vector<LayerPropertyAnimation>& propertyAnimations = it->value;
575 size_t numAnimations = propertyAnimations.size();
576 for (size_t i = 0; i < numAnimations; ++i) {
577 const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
579 if (currAnimation.m_property == AnimatedPropertyWebkitTransform || currAnimation.m_property == AnimatedPropertyOpacity
580 || currAnimation.m_property == AnimatedPropertyBackgroundColor
581 #if ENABLE(CSS_FILTERS)
582 || currAnimation.m_property == AnimatedPropertyWebkitFilter
585 moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index, currAnimation.m_subIndex), fromLayer, toLayer);
590 void GraphicsLayerCA::setPreserves3D(bool preserves3D)
592 if (preserves3D == m_preserves3D)
595 GraphicsLayer::setPreserves3D(preserves3D);
596 noteLayerPropertyChanged(Preserves3DChanged);
599 void GraphicsLayerCA::setMasksToBounds(bool masksToBounds)
601 if (masksToBounds == m_masksToBounds)
604 GraphicsLayer::setMasksToBounds(masksToBounds);
605 noteLayerPropertyChanged(MasksToBoundsChanged | DebugIndicatorsChanged);
608 void GraphicsLayerCA::setDrawsContent(bool drawsContent)
610 if (drawsContent == m_drawsContent)
613 GraphicsLayer::setDrawsContent(drawsContent);
614 noteLayerPropertyChanged(DrawsContentChanged | DebugIndicatorsChanged);
617 void GraphicsLayerCA::setContentsVisible(bool contentsVisible)
619 if (contentsVisible == m_contentsVisible)
622 GraphicsLayer::setContentsVisible(contentsVisible);
623 noteLayerPropertyChanged(ContentsVisibilityChanged);
624 // Visibility affects whether the contentsLayer is parented.
626 noteSublayersChanged();
629 void GraphicsLayerCA::setAcceleratesDrawing(bool acceleratesDrawing)
631 if (acceleratesDrawing == m_acceleratesDrawing)
634 GraphicsLayer::setAcceleratesDrawing(acceleratesDrawing);
635 noteLayerPropertyChanged(AcceleratesDrawingChanged);
638 void GraphicsLayerCA::setBackgroundColor(const Color& color)
640 if (m_backgroundColor == color)
643 GraphicsLayer::setBackgroundColor(color);
644 noteLayerPropertyChanged(BackgroundColorChanged);
647 void GraphicsLayerCA::setContentsOpaque(bool opaque)
649 if (m_contentsOpaque == opaque)
652 GraphicsLayer::setContentsOpaque(opaque);
653 noteLayerPropertyChanged(ContentsOpaqueChanged);
656 void GraphicsLayerCA::setBackfaceVisibility(bool visible)
658 if (m_backfaceVisibility == visible)
661 GraphicsLayer::setBackfaceVisibility(visible);
662 noteLayerPropertyChanged(BackfaceVisibilityChanged);
665 void GraphicsLayerCA::setOpacity(float opacity)
667 float clampedOpacity = std::max(0.0f, std::min(opacity, 1.0f));
669 if (clampedOpacity == m_opacity)
672 GraphicsLayer::setOpacity(clampedOpacity);
673 noteLayerPropertyChanged(OpacityChanged);
676 #if ENABLE(CSS_FILTERS)
677 bool GraphicsLayerCA::setFilters(const FilterOperations& filterOperations)
679 bool canCompositeFilters = filtersCanBeComposited(filterOperations);
681 if (m_filters == filterOperations)
682 return canCompositeFilters;
684 // Filters cause flattening, so we should never have filters on a layer with preserves3D().
685 ASSERT(!filterOperations.size() || !preserves3D());
687 if (canCompositeFilters) {
688 GraphicsLayer::setFilters(filterOperations);
689 noteLayerPropertyChanged(FiltersChanged);
690 } else if (filters().size()) {
691 // In this case filters are rendered in software, so we need to remove any
692 // previously attached hardware filters.
694 noteLayerPropertyChanged(FiltersChanged);
696 return canCompositeFilters;
700 #if ENABLE(CSS_COMPOSITING)
701 void GraphicsLayerCA::setBlendMode(BlendMode blendMode)
703 if (GraphicsLayer::blendMode() == blendMode)
706 GraphicsLayer::setBlendMode(blendMode);
707 noteLayerPropertyChanged(BlendModeChanged);
711 void GraphicsLayerCA::setNeedsDisplay()
716 m_needsFullRepaint = true;
717 m_dirtyRects.clear();
718 noteLayerPropertyChanged(DirtyRectsChanged);
719 addRepaintRect(FloatRect(FloatPoint(), m_size));
722 void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& r, ShouldClipToLayer shouldClip)
727 if (m_needsFullRepaint)
731 if (shouldClip == ClipToLayer) {
732 FloatRect layerBounds(FloatPoint(), m_size);
733 rect.intersect(layerBounds);
739 const size_t maxDirtyRects = 32;
741 for (size_t i = 0; i < m_dirtyRects.size(); ++i) {
742 if (m_dirtyRects[i].contains(rect))
746 if (m_dirtyRects.size() < maxDirtyRects)
747 m_dirtyRects.append(rect);
749 m_dirtyRects[0].unite(rect);
751 noteLayerPropertyChanged(DirtyRectsChanged);
753 addRepaintRect(rect);
756 void GraphicsLayerCA::setContentsNeedsDisplay()
758 noteLayerPropertyChanged(ContentsNeedsDisplay);
761 void GraphicsLayerCA::setContentsRect(const FloatRect& rect)
763 if (rect == m_contentsRect)
766 GraphicsLayer::setContentsRect(rect);
767 noteLayerPropertyChanged(ContentsRectsChanged);
770 void GraphicsLayerCA::setContentsClippingRect(const FloatRect& rect)
772 if (rect == m_contentsClippingRect)
775 GraphicsLayer::setContentsClippingRect(rect);
776 noteLayerPropertyChanged(ContentsRectsChanged);
779 bool GraphicsLayerCA::shouldRepaintOnSizeChange() const
781 return drawsContent() && !tiledBacking();
784 bool GraphicsLayerCA::animationCanBeAccelerated(const KeyframeValueList& valueList, const Animation* anim) const
786 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
789 if (animationHasStepsTimingFunction(valueList, anim))
795 bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& animationName, double timeOffset)
797 ASSERT(!animationName.isEmpty());
799 if (!animationCanBeAccelerated(valueList, anim))
802 bool createdAnimations = false;
803 if (valueList.property() == AnimatedPropertyWebkitTransform)
804 createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize);
805 #if ENABLE(CSS_FILTERS)
806 else if (valueList.property() == AnimatedPropertyWebkitFilter) {
807 if (supportsAcceleratedFilterAnimations())
808 createdAnimations = createFilterAnimationsFromKeyframes(valueList, anim, animationName, timeOffset);
812 createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset);
814 if (createdAnimations)
815 noteLayerPropertyChanged(AnimationChanged);
817 return createdAnimations;
820 void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset)
822 if (!animationIsRunning(animationName))
825 AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName);
826 if (it != m_animationsToProcess.end()) {
827 AnimationProcessingAction& processingInfo = it->value;
828 // If an animation is scheduled to be removed, don't change the remove to a pause.
829 if (processingInfo.action != Remove)
830 processingInfo.action = Pause;
832 m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset));
834 noteLayerPropertyChanged(AnimationChanged);
837 void GraphicsLayerCA::removeAnimation(const String& animationName)
839 if (!animationIsRunning(animationName))
842 m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove));
843 noteLayerPropertyChanged(AnimationChanged);
846 void GraphicsLayerCA::platformCALayerAnimationStarted(const String& animationKey, CFTimeInterval startTime)
848 client().notifyAnimationStarted(this, animationKey, startTime);
851 void GraphicsLayerCA::platformCALayerAnimationEnded(const String& animationKey)
853 client().notifyAnimationEnded(this, animationKey);
856 void GraphicsLayerCA::setContentsToSolidColor(const Color& color)
858 if (color == m_contentsSolidColor)
861 m_contentsSolidColor = color;
863 bool contentsLayerChanged = false;
865 if (m_contentsSolidColor.isValid() && m_contentsSolidColor.alpha()) {
866 if (!m_contentsLayer || m_contentsLayerPurpose != ContentsLayerForBackgroundColor) {
867 m_contentsLayerPurpose = ContentsLayerForBackgroundColor;
868 m_contentsLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
870 m_contentsLayer->setName("Background Color Layer");
872 contentsLayerChanged = true;
875 contentsLayerChanged = m_contentsLayer;
876 m_contentsLayerPurpose = NoContentsLayer;
880 if (contentsLayerChanged)
881 noteSublayersChanged();
883 noteLayerPropertyChanged(ContentsColorLayerChanged);
886 void GraphicsLayerCA::setContentsToImage(Image* image)
889 CGImageRef newImage = image->nativeImageForCurrentFrame();
893 // Check to see if the image changed; we have to do this because the call to
894 // CGImageCreateCopyWithColorSpace() below can create a new image every time.
895 if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage)
898 m_uncorrectedContentsImage = newImage;
899 m_pendingContentsImage = newImage;
901 #if !PLATFORM(WIN) && !PLATFORM(IOS)
902 CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get());
904 static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
905 if (colorSpace && CFEqual(colorSpace, deviceRGB)) {
906 // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such
907 // images to CA we need to tag them similarly so CA rendering matches CG rendering.
908 static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
909 m_pendingContentsImage = adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB));
912 m_contentsLayerPurpose = ContentsLayerForImage;
913 if (!m_contentsLayer)
914 noteSublayersChanged();
916 m_uncorrectedContentsImage = 0;
917 m_pendingContentsImage = 0;
918 m_contentsLayerPurpose = NoContentsLayer;
920 noteSublayersChanged();
923 noteLayerPropertyChanged(ContentsImageChanged);
926 void GraphicsLayerCA::setContentsToPlatformLayer(PlatformLayer* platformLayer, ContentsLayerPurpose purpose)
928 if (m_contentsLayer && platformLayer == m_contentsLayer->platformLayer())
931 // FIXME: The passed in layer might be a raw layer or an externally created
932 // PlatformCALayer. To determine this we attempt to get the
933 // PlatformCALayer pointer. If this returns a null pointer we assume it's
934 // raw. This test might be invalid if the raw layer is, for instance, the
935 // PlatformCALayer is using a user data pointer in the raw layer, and
936 // the creator of the raw layer is using it for some other purpose.
937 // For now we don't support such a case.
938 PlatformCALayer* platformCALayer = PlatformCALayer::platformCALayer(platformLayer);
939 m_contentsLayer = platformLayer ? (platformCALayer ? platformCALayer : createPlatformCALayer(platformLayer, this)) : 0;
940 m_contentsLayerPurpose = platformLayer ? purpose : NoContentsLayer;
942 noteSublayersChanged();
943 noteLayerPropertyChanged(ContentsPlatformLayerChanged);
947 PlatformLayer* GraphicsLayerCA::contentsLayerForMedia() const
949 return m_contentsLayerPurpose == ContentsLayerForMedia ? m_contentsLayer->platformLayer() : nullptr;
953 void GraphicsLayerCA::layerDidDisplay(PlatformCALayer* layer)
955 LayerMap* layerCloneMap;
957 if (layer == m_layer)
958 layerCloneMap = m_layerClones.get();
959 else if (layer == m_contentsLayer)
960 layerCloneMap = m_contentsLayerClones.get();
965 LayerMap::const_iterator end = layerCloneMap->end();
966 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
967 PlatformCALayer* currClone = it->value.get();
971 currClone->copyContentsFromLayer(layer);
976 FloatPoint GraphicsLayerCA::computePositionRelativeToBase(float& pageScale) const
981 for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) {
982 if (currLayer->appliesPageScale()) {
983 pageScale = currLayer->pageScaleFactor();
987 offset += currLayer->position();
993 void GraphicsLayerCA::flushCompositingState(const FloatRect& clipRect)
995 TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(clipRect));
996 recursiveCommitChanges(CommitState(), state);
999 void GraphicsLayerCA::flushCompositingStateForThisLayerOnly()
1001 float pageScaleFactor;
1002 bool hadChanges = m_uncommittedChanges;
1004 CommitState commitState;
1006 FloatPoint offset = computePositionRelativeToBase(pageScaleFactor);
1007 commitLayerChangesBeforeSublayers(commitState, pageScaleFactor, offset, m_visibleRect);
1008 commitLayerChangesAfterSublayers(commitState);
1011 client().didCommitChangesForLayer(this);
1014 bool GraphicsLayerCA::recursiveVisibleRectChangeRequiresFlush(const TransformState& state) const
1016 TransformState localState = state;
1018 // This may be called at times when layout has not been updated, so we want to avoid calling out to the client
1019 // for animating transforms.
1020 FloatRect newVisibleRect = computeVisibleRect(localState, 0);
1021 if (m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
1022 newVisibleRect = adjustTiledLayerVisibleRect(tiledBacking(), m_visibleRect, newVisibleRect, m_sizeAtLastVisibleRectUpdate, m_size);
1024 if (newVisibleRect != m_visibleRect) {
1025 if (TiledBacking* tiledBacking = this->tiledBacking()) {
1026 if (tiledBacking->tilesWouldChangeForVisibleRect(newVisibleRect))
1032 GraphicsLayerCA* maskLayerCA = toGraphicsLayerCA(m_maskLayer);
1033 if (maskLayerCA->recursiveVisibleRectChangeRequiresFlush(localState))
1037 const Vector<GraphicsLayer*>& childLayers = children();
1038 size_t numChildren = childLayers.size();
1040 for (size_t i = 0; i < numChildren; ++i) {
1041 GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
1042 if (curChild->recursiveVisibleRectChangeRequiresFlush(localState))
1047 if (toGraphicsLayerCA(m_replicaLayer)->recursiveVisibleRectChangeRequiresFlush(localState))
1053 bool GraphicsLayerCA::visibleRectChangeRequiresFlush(const FloatRect& clipRect) const
1055 TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(clipRect));
1056 return recursiveVisibleRectChangeRequiresFlush(state);
1059 TiledBacking* GraphicsLayerCA::tiledBacking() const
1061 return m_layer->tiledBacking();
1064 TransformationMatrix GraphicsLayerCA::layerTransform(const FloatPoint& position, const TransformationMatrix* customTransform) const
1066 TransformationMatrix transform;
1067 transform.translate(position.x(), position.y());
1069 TransformationMatrix currentTransform = customTransform ? *customTransform : m_transform;
1071 if (!currentTransform.isIdentity()) {
1072 FloatPoint3D absoluteAnchorPoint(anchorPoint());
1073 absoluteAnchorPoint.scale(size().width(), size().height(), 1);
1074 transform.translate3d(absoluteAnchorPoint.x(), absoluteAnchorPoint.y(), absoluteAnchorPoint.z());
1075 transform.multiply(currentTransform);
1076 transform.translate3d(-absoluteAnchorPoint.x(), -absoluteAnchorPoint.y(), -absoluteAnchorPoint.z());
1079 if (GraphicsLayer* parentLayer = parent()) {
1080 if (!parentLayer->childrenTransform().isIdentity()) {
1081 FloatPoint3D parentAnchorPoint(parentLayer->anchorPoint());
1082 parentAnchorPoint.scale(parentLayer->size().width(), parentLayer->size().height(), 1);
1084 transform.translateRight3d(-parentAnchorPoint.x(), -parentAnchorPoint.y(), -parentAnchorPoint.z());
1085 transform = parentLayer->childrenTransform() * transform;
1086 transform.translateRight3d(parentAnchorPoint.x(), parentAnchorPoint.y(), parentAnchorPoint.z());
1093 FloatRect GraphicsLayerCA::computeVisibleRect(TransformState& state, ComputeVisibleRectFlags flags) const
1095 bool preserve3D = preserves3D() || (parent() ? parent()->preserves3D() : false);
1096 TransformState::TransformAccumulation accumulation = preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform;
1098 FloatPoint position = m_position;
1099 client().customPositionForVisibleRectComputation(this, position);
1101 TransformationMatrix layerTransform;
1102 TransformationMatrix currentTransform;
1103 if ((flags & RespectAnimatingTransforms) && client().getCurrentTransform(this, currentTransform))
1104 layerTransform = this->layerTransform(position, ¤tTransform);
1106 layerTransform = this->layerTransform(position);
1108 bool applyWasClamped;
1109 state.applyTransform(layerTransform, accumulation, &applyWasClamped);
1112 FloatRect clipRectForChildren = state.mappedQuad(&mapWasClamped).boundingBox();
1113 FloatPoint boundsOrigin = m_boundsOrigin;
1115 // In WK1, UIKit may be changing layer bounds behind our back in overflow-scroll layers, so use the layer's origin.
1116 if (m_layer->isPlatformCALayerMac())
1117 boundsOrigin = m_layer->bounds().location();
1119 clipRectForChildren.move(boundsOrigin.x(), boundsOrigin.y());
1121 FloatRect clipRectForSelf(boundsOrigin, m_size);
1122 if (!applyWasClamped && !mapWasClamped)
1123 clipRectForSelf.intersect(clipRectForChildren);
1125 if (masksToBounds()) {
1126 ASSERT(accumulation == TransformState::FlattenTransform);
1127 // Replace the quad in the TransformState with one that is clipped to this layer's bounds
1128 state.setQuad(clipRectForSelf);
1131 return clipRectForSelf;
1134 // rootRelativeTransformForScaling is a transform from the root, but for layers with transform animations, it cherry-picked the state of the
1135 // animation that contributes maximally to the scale (on every layer with animations down the hierarchy).
1136 void GraphicsLayerCA::recursiveCommitChanges(const CommitState& commitState, const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale)
1138 TransformState localState = state;
1139 CommitState childCommitState = commitState;
1140 bool affectedByTransformAnimation = commitState.ancestorHasTransformAnimation;
1142 FloatRect visibleRect = computeVisibleRect(localState);
1143 FloatRect oldVisibleRect = m_visibleRect;
1144 if (visibleRect != m_visibleRect) {
1145 m_uncommittedChanges |= VisibleRectChanged;
1146 m_visibleRect = visibleRect;
1148 if (GraphicsLayerCA* maskLayer = toGraphicsLayerCA(m_maskLayer)) {
1149 // FIXME: this assumes that the mask layer has the same geometry as this layer (which is currently always true).
1150 maskLayer->m_uncommittedChanges |= VisibleRectChanged;
1151 maskLayer->m_visibleRect = visibleRect;
1155 #ifdef VISIBLE_TILE_WASH
1156 // Use having a transform as a key to making the tile wash layer. If every layer gets a wash,
1157 // they start to obscure useful information.
1158 if ((!m_transform.isIdentity() || m_usingTiledBacking) && !m_visibleTileWashLayer) {
1159 static Color washFillColor(255, 0, 0, 50);
1160 static Color washBorderColor(255, 0, 0, 100);
1162 m_visibleTileWashLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
1163 String name = String::format("Visible Tile Wash Layer %p", m_visibleTileWashLayer->platformLayer());
1164 m_visibleTileWashLayer->setName(name);
1165 m_visibleTileWashLayer->setAnchorPoint(FloatPoint3D(0, 0, 0));
1166 m_visibleTileWashLayer->setBorderColor(washBorderColor);
1167 m_visibleTileWashLayer->setBorderWidth(8);
1168 m_visibleTileWashLayer->setBackgroundColor(washFillColor);
1169 noteSublayersChanged(DontScheduleFlush);
1172 if (m_visibleTileWashLayer) {
1173 m_visibleTileWashLayer->setPosition(m_visibleRect.location());
1174 m_visibleTileWashLayer->setBounds(FloatRect(FloatPoint(), m_visibleRect.size()));
1178 bool hadChanges = m_uncommittedChanges;
1180 if (appliesPageScale()) {
1181 pageScaleFactor = this->pageScaleFactor();
1182 affectedByPageScale = true;
1185 // Accumulate an offset from the ancestral pixel-aligned layer.
1186 FloatPoint baseRelativePosition = positionRelativeToBase;
1187 if (affectedByPageScale)
1188 baseRelativePosition += m_position;
1190 commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, oldVisibleRect);
1192 if (isRunningTransformAnimation()) {
1193 childCommitState.ancestorHasTransformAnimation = true;
1194 affectedByTransformAnimation = true;
1197 if (GraphicsLayerCA* maskLayer = toGraphicsLayerCA(m_maskLayer))
1198 maskLayer->commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, oldVisibleRect);
1200 const Vector<GraphicsLayer*>& childLayers = children();
1201 size_t numChildren = childLayers.size();
1203 for (size_t i = 0; i < numChildren; ++i) {
1204 GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
1205 curChild->recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
1208 if (GraphicsLayerCA* replicaLayer = toGraphicsLayerCA(m_replicaLayer))
1209 replicaLayer->recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
1211 if (GraphicsLayerCA* maskLayer = toGraphicsLayerCA(m_maskLayer))
1212 maskLayer->commitLayerChangesAfterSublayers(childCommitState);
1214 commitLayerChangesAfterSublayers(childCommitState);
1216 if (affectedByTransformAnimation && m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
1217 client().notifyFlushBeforeDisplayRefresh(this);
1220 client().didCommitChangesForLayer(this);
1223 bool GraphicsLayerCA::platformCALayerShowRepaintCounter(PlatformCALayer* platformLayer) const
1225 // The repaint counters are painted into the TileController tiles (which have no corresponding platform layer),
1226 // so we don't want to overpaint the repaint counter when called with the TileController's own layer.
1227 if (m_isPageTiledBackingLayer && platformLayer)
1230 return isShowingRepaintCounter();
1233 void GraphicsLayerCA::platformCALayerPaintContents(PlatformCALayer*, GraphicsContext& context, const FloatRect& clip)
1235 paintGraphicsLayerContents(context, clip);
1238 void GraphicsLayerCA::platformCALayerSetNeedsToRevalidateTiles()
1240 noteLayerPropertyChanged(TilingAreaChanged, m_isCommittingChanges ? DontScheduleFlush : ScheduleFlush);
1243 float GraphicsLayerCA::platformCALayerDeviceScaleFactor() const
1245 return deviceScaleFactor();
1248 float GraphicsLayerCA::platformCALayerContentsScaleMultiplierForNewTiles(PlatformCALayer*) const
1250 return client().contentsScaleMultiplierForNewTiles(this);
1253 bool GraphicsLayerCA::platformCALayerShouldAggressivelyRetainTiles(PlatformCALayer*) const
1255 return client().shouldAggressivelyRetainTiles(this);
1258 bool GraphicsLayerCA::platformCALayerShouldTemporarilyRetainTileCohorts(PlatformCALayer*) const
1260 return client().shouldTemporarilyRetainTileCohorts(this);
1263 void GraphicsLayerCA::commitLayerChangesBeforeSublayers(CommitState& commitState, float pageScaleFactor, const FloatPoint& positionRelativeToBase, const FloatRect& oldVisibleRect)
1265 TemporaryChange<bool> committingChangesChange(m_isCommittingChanges, true);
1267 ++commitState.treeDepth;
1268 if (m_structuralLayer)
1269 ++commitState.treeDepth;
1271 if (!m_uncommittedChanges) {
1272 // Ensure that we cap layer depth in commitLayerChangesAfterSublayers().
1273 if (commitState.treeDepth > cMaxLayerTreeDepth)
1274 m_uncommittedChanges |= ChildrenChanged;
1277 bool needTiledLayer = requiresTiledLayer(pageScaleFactor);
1278 if (needTiledLayer != m_usingTiledBacking)
1279 swapFromOrToTiledLayer(needTiledLayer);
1281 // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to
1282 if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged))
1283 updateStructuralLayer();
1285 if (m_uncommittedChanges & GeometryChanged)
1286 updateGeometry(pageScaleFactor, positionRelativeToBase);
1288 if (m_uncommittedChanges & DrawsContentChanged)
1289 updateLayerDrawsContent();
1291 if (m_uncommittedChanges & NameChanged)
1294 if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged
1295 updateContentsImage();
1297 if (m_uncommittedChanges & ContentsPlatformLayerChanged) // Needs to happen before ChildrenChanged
1298 updateContentsPlatformLayer();
1300 if (m_uncommittedChanges & ContentsColorLayerChanged) // Needs to happen before ChildrenChanged
1301 updateContentsColorLayer();
1303 if (m_uncommittedChanges & BackgroundColorChanged)
1304 updateBackgroundColor();
1306 if (m_uncommittedChanges & TransformChanged)
1309 if (m_uncommittedChanges & ChildrenTransformChanged)
1310 updateChildrenTransform();
1312 if (m_uncommittedChanges & MasksToBoundsChanged)
1313 updateMasksToBounds();
1315 if (m_uncommittedChanges & ContentsVisibilityChanged)
1316 updateContentsVisibility();
1318 // Note that contentsScale can affect whether the layer can be opaque.
1319 if (m_uncommittedChanges & ContentsOpaqueChanged)
1320 updateContentsOpaque(pageScaleFactor);
1322 if (m_uncommittedChanges & BackfaceVisibilityChanged)
1323 updateBackfaceVisibility();
1325 if (m_uncommittedChanges & OpacityChanged)
1326 updateOpacityOnLayer();
1328 #if ENABLE(CSS_FILTERS)
1329 if (m_uncommittedChanges & FiltersChanged)
1333 #if ENABLE(CSS_COMPOSITING)
1334 if (m_uncommittedChanges & BlendModeChanged)
1338 if (m_uncommittedChanges & AnimationChanged)
1341 // Updating the contents scale can cause parts of the layer to be invalidated,
1342 // so make sure to update the contents scale before updating the dirty rects.
1343 if (m_uncommittedChanges & ContentsScaleChanged)
1344 updateContentsScale(pageScaleFactor);
1346 if (m_uncommittedChanges & VisibleRectChanged)
1347 updateVisibleRect(oldVisibleRect);
1349 if (m_uncommittedChanges & TilingAreaChanged) // Needs to happen after VisibleRectChanged, ContentsScaleChanged
1352 if (m_uncommittedChanges & DirtyRectsChanged)
1353 repaintLayerDirtyRects();
1355 if (m_uncommittedChanges & ContentsRectsChanged) // Needs to happen before ChildrenChanged
1356 updateContentsRects();
1358 if (m_uncommittedChanges & MaskLayerChanged) {
1360 // If the mask layer becomes tiled it can set this flag again. Clear the flag so that
1361 // commitLayerChangesAfterSublayers doesn't update the mask again in the normal case.
1362 m_uncommittedChanges &= ~MaskLayerChanged;
1365 if (m_uncommittedChanges & ContentsNeedsDisplay)
1366 updateContentsNeedsDisplay();
1368 if (m_uncommittedChanges & AcceleratesDrawingChanged)
1369 updateAcceleratesDrawing();
1371 if (m_uncommittedChanges & DebugIndicatorsChanged)
1372 updateDebugBorder();
1374 if (m_uncommittedChanges & CustomAppearanceChanged)
1375 updateCustomAppearance();
1377 if (m_uncommittedChanges & CustomBehaviorChanged)
1378 updateCustomBehavior();
1380 if (m_uncommittedChanges & ChildrenChanged) {
1381 updateSublayerList();
1382 // Sublayers may set this flag again, so clear it to avoid always updating sublayers in commitLayerChangesAfterSublayers().
1383 m_uncommittedChanges &= ~ChildrenChanged;
1386 // Ensure that we cap layer depth in commitLayerChangesAfterSublayers().
1387 if (commitState.treeDepth > cMaxLayerTreeDepth)
1388 m_uncommittedChanges |= ChildrenChanged;
1391 void GraphicsLayerCA::commitLayerChangesAfterSublayers(CommitState& commitState)
1393 if (!m_uncommittedChanges)
1396 TemporaryChange<bool> committingChangesChange(m_isCommittingChanges, true);
1398 if (m_uncommittedChanges & MaskLayerChanged)
1401 if (m_uncommittedChanges & ChildrenChanged)
1402 updateSublayerList(commitState.treeDepth > cMaxLayerTreeDepth);
1404 if (m_uncommittedChanges & ReplicatedLayerChanged)
1405 updateReplicatedLayers();
1407 m_uncommittedChanges = NoChange;
1410 void GraphicsLayerCA::updateLayerNames()
1412 switch (structuralLayerPurpose()) {
1413 case StructuralLayerForPreserves3D:
1414 m_structuralLayer->setName("Transform layer " + name());
1416 case StructuralLayerForReplicaFlattening:
1417 m_structuralLayer->setName("Replica flattening layer " + name());
1419 case NoStructuralLayer:
1422 m_layer->setName(name());
1425 void GraphicsLayerCA::updateSublayerList(bool maxLayerDepthReached)
1427 if (maxLayerDepthReached) {
1428 m_layer->setSublayers(PlatformCALayerList());
1432 const PlatformCALayerList* customSublayers = m_layer->customSublayers();
1434 PlatformCALayerList structuralLayerChildren;
1435 PlatformCALayerList primaryLayerChildren;
1437 PlatformCALayerList& childListForSublayers = m_structuralLayer ? structuralLayerChildren : primaryLayerChildren;
1439 if (customSublayers)
1440 primaryLayerChildren.appendVector(*customSublayers);
1442 if (m_structuralLayer) {
1444 structuralLayerChildren.append(toGraphicsLayerCA(m_replicaLayer)->primaryLayer());
1446 structuralLayerChildren.append(m_layer);
1449 if (m_contentsLayer && m_contentsVisible) {
1450 // FIXME: add the contents layer in the correct order with negative z-order children.
1451 // This does not cause visible rendering issues because currently contents layers are only used
1452 // for replaced elements that don't have children.
1453 primaryLayerChildren.append(m_contentsClippingLayer ? m_contentsClippingLayer : m_contentsLayer);
1456 const Vector<GraphicsLayer*>& childLayers = children();
1457 size_t numChildren = childLayers.size();
1458 for (size_t i = 0; i < numChildren; ++i) {
1459 GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
1460 PlatformCALayer* childLayer = curChild->layerForSuperlayer();
1461 childListForSublayers.append(childLayer);
1464 #ifdef VISIBLE_TILE_WASH
1465 if (m_visibleTileWashLayer)
1466 childListForSublayers.append(m_visibleTileWashLayer);
1469 if (m_structuralLayer)
1470 m_structuralLayer->setSublayers(structuralLayerChildren);
1472 m_layer->setSublayers(primaryLayerChildren);
1475 void GraphicsLayerCA::updateGeometry(float pageScaleFactor, const FloatPoint& positionRelativeToBase)
1477 FloatPoint scaledPosition = m_position;
1478 FloatPoint3D scaledAnchorPoint = m_anchorPoint;
1479 FloatSize scaledSize = m_size;
1480 FloatSize pixelAlignmentOffset;
1482 // FIXME: figure out if we really need to pixel align the graphics layer here.
1483 if (m_client.needsPixelAligment() && !isIntegral(pageScaleFactor) && m_drawsContent && !m_masksToBounds)
1484 computePixelAlignment(pageScaleFactor, positionRelativeToBase, scaledPosition, scaledAnchorPoint, pixelAlignmentOffset);
1487 // Position is offset on the layer by the layer anchor point.
1488 FloatPoint adjustedPosition(scaledPosition.x() + scaledAnchorPoint.x() * scaledSize.width(), scaledPosition.y() + scaledAnchorPoint.y() * scaledSize.height());
1490 if (m_structuralLayer) {
1491 FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(), m_position.y() + m_anchorPoint.y() * m_size.height());
1492 FloatRect layerBounds(m_boundsOrigin, m_size);
1494 m_structuralLayer->setPosition(layerPosition);
1495 m_structuralLayer->setBounds(layerBounds);
1496 m_structuralLayer->setAnchorPoint(m_anchorPoint);
1498 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
1499 LayerMap::const_iterator end = layerCloneMap->end();
1500 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1501 PlatformCALayer* clone = it->value.get();
1502 FloatPoint clonePosition = layerPosition;
1504 if (m_replicaLayer && isReplicatedRootClone(it->key)) {
1505 // Maintain the special-case position for the root of a clone subtree,
1506 // which we set up in replicatedLayerRoot().
1507 clonePosition = positionForCloneRootLayer();
1510 clone->setPosition(clonePosition);
1511 clone->setBounds(layerBounds);
1512 clone->setAnchorPoint(m_anchorPoint);
1516 // If we have a structural layer, we just use 0.5, 0.5 for the anchor point of the main layer.
1517 scaledAnchorPoint = FloatPoint(0.5f, 0.5f);
1518 adjustedPosition = FloatPoint(scaledAnchorPoint.x() * scaledSize.width() - pixelAlignmentOffset.width(), scaledAnchorPoint.y() * scaledSize.height() - pixelAlignmentOffset.height());
1521 m_pixelAlignmentOffset = pixelAlignmentOffset;
1523 // Push the layer to device pixel boundary (setPosition()), but move the content back to its original position (setBounds())
1524 m_layer->setPosition(adjustedPosition);
1525 FloatRect adjustedBounds = FloatRect(FloatPoint(m_boundsOrigin - pixelAlignmentOffset), m_size);
1526 m_layer->setBounds(adjustedBounds);
1527 m_layer->setAnchorPoint(scaledAnchorPoint);
1529 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1530 LayerMap::const_iterator end = layerCloneMap->end();
1531 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1532 PlatformCALayer* clone = it->value.get();
1533 FloatPoint clonePosition = adjustedPosition;
1535 if (!m_structuralLayer && m_replicaLayer && isReplicatedRootClone(it->key)) {
1536 // Maintain the special-case position for the root of a clone subtree,
1537 // which we set up in replicatedLayerRoot().
1538 clonePosition = positionForCloneRootLayer();
1541 clone->setPosition(clonePosition);
1542 clone->setBounds(adjustedBounds);
1543 clone->setAnchorPoint(scaledAnchorPoint);
1548 void GraphicsLayerCA::updateTransform()
1550 primaryLayer()->setTransform(m_transform);
1552 if (LayerMap* layerCloneMap = primaryLayerClones()) {
1553 LayerMap::const_iterator end = layerCloneMap->end();
1554 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1555 PlatformCALayer* currLayer = it->value.get();
1556 if (m_replicaLayer && isReplicatedRootClone(it->key)) {
1557 // Maintain the special-case transform for the root of a clone subtree,
1558 // which we set up in replicatedLayerRoot().
1559 currLayer->setTransform(TransformationMatrix());
1561 currLayer->setTransform(m_transform);
1566 void GraphicsLayerCA::updateChildrenTransform()
1568 primaryLayer()->setSublayerTransform(m_childrenTransform);
1570 if (LayerMap* layerCloneMap = primaryLayerClones()) {
1571 LayerMap::const_iterator end = layerCloneMap->end();
1572 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1573 it->value->setSublayerTransform(m_childrenTransform);
1577 void GraphicsLayerCA::updateMasksToBounds()
1579 m_layer->setMasksToBounds(m_masksToBounds);
1581 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1582 LayerMap::const_iterator end = layerCloneMap->end();
1583 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1584 it->value->setMasksToBounds(m_masksToBounds);
1588 void GraphicsLayerCA::updateContentsVisibility()
1590 // Note that m_contentsVisible also affects whether m_contentsLayer is parented.
1591 if (m_contentsVisible) {
1593 m_layer->setNeedsDisplay();
1595 m_layer->setContents(0);
1597 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1598 LayerMap::const_iterator end = layerCloneMap->end();
1599 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1600 it->value->setContents(0);
1605 void GraphicsLayerCA::updateContentsOpaque(float pageScaleFactor)
1607 bool contentsOpaque = m_contentsOpaque;
1608 if (contentsOpaque) {
1609 float contentsScale = pageScaleFactor * deviceScaleFactor();
1610 if (!isIntegral(contentsScale) && !m_client.paintsOpaquelyAtNonIntegralScales(this))
1611 contentsOpaque = false;
1614 m_layer->setOpaque(contentsOpaque);
1616 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1617 LayerMap::const_iterator end = layerCloneMap->end();
1618 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1619 it->value->setOpaque(contentsOpaque);
1623 void GraphicsLayerCA::updateBackfaceVisibility()
1625 if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) {
1626 m_structuralLayer->setDoubleSided(m_backfaceVisibility);
1628 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
1629 LayerMap::const_iterator end = layerCloneMap->end();
1630 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1631 it->value->setDoubleSided(m_backfaceVisibility);
1635 m_layer->setDoubleSided(m_backfaceVisibility);
1637 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1638 LayerMap::const_iterator end = layerCloneMap->end();
1639 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
1640 it->value->setDoubleSided(m_backfaceVisibility);
1644 #if ENABLE(CSS_FILTERS)
1645 void GraphicsLayerCA::updateFilters()
1647 m_layer->setFilters(m_filters);
1649 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1650 LayerMap::const_iterator end = layerCloneMap->end();
1651 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1652 if (m_replicaLayer && isReplicatedRootClone(it->key))
1655 it->value->setFilters(m_filters);
1661 #if ENABLE(CSS_COMPOSITING)
1662 void GraphicsLayerCA::updateBlendMode()
1664 primaryLayer()->setBlendMode(m_blendMode);
1666 if (LayerMap* layerCloneMap = primaryLayerClones()) {
1667 LayerMap::const_iterator end = layerCloneMap->end();
1668 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1669 if (m_replicaLayer && isReplicatedRootClone(it->key))
1671 it->value->setBlendMode(m_blendMode);
1677 void GraphicsLayerCA::updateStructuralLayer()
1679 ensureStructuralLayer(structuralLayerPurpose());
1682 void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose)
1684 const LayerChangeFlags structuralLayerChangeFlags = NameChanged
1687 | ChildrenTransformChanged
1689 | BackfaceVisibilityChanged
1690 #if ENABLE(CSS_FILTERS)
1695 if (purpose == NoStructuralLayer) {
1696 if (m_structuralLayer) {
1697 // Replace the transformLayer in the parent with this layer.
1698 m_layer->removeFromSuperlayer();
1700 // If m_layer doesn't have a parent, it means it's the root layer and
1701 // is likely hosted by something that is not expecting to be changed
1702 ASSERT(m_structuralLayer->superlayer());
1703 m_structuralLayer->superlayer()->replaceSublayer(m_structuralLayer.get(), m_layer.get());
1705 moveOrCopyAnimations(Move, m_structuralLayer.get(), m_layer.get());
1707 // Release the structural layer.
1708 m_structuralLayer = 0;
1710 m_uncommittedChanges |= structuralLayerChangeFlags;
1716 RefPtr<PlatformCALayer> oldPrimaryLayer = m_structuralLayer ? m_structuralLayer.get() : m_layer.get();
1719 bool structuralLayerChanged = false;
1721 if (purpose == StructuralLayerForPreserves3D) {
1722 if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeTransformLayer)
1723 m_structuralLayer = 0;
1725 if (!m_structuralLayer) {
1726 m_structuralLayer = createPlatformCALayer(PlatformCALayer::LayerTypeTransformLayer, this);
1727 structuralLayerChanged = true;
1730 if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeLayer)
1731 m_structuralLayer = 0;
1733 if (!m_structuralLayer) {
1734 m_structuralLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
1735 structuralLayerChanged = true;
1739 if (!structuralLayerChanged)
1742 m_uncommittedChanges |= structuralLayerChangeFlags;
1744 // We've changed the layer that our parent added to its sublayer list, so tell it to update
1745 // sublayers again in its commitLayerChangesAfterSublayers().
1746 toGraphicsLayerCA(parent())->noteSublayersChanged(DontScheduleFlush);
1748 // Set properties of m_layer to their default values, since these are expressed on on the structural layer.
1749 FloatPoint point(m_size.width() / 2.0f, m_size.height() / 2.0f);
1750 FloatPoint3D anchorPoint(0.5f, 0.5f, 0);
1751 m_layer->setPosition(point);
1752 m_layer->setAnchorPoint(anchorPoint);
1753 m_layer->setTransform(TransformationMatrix());
1754 m_layer->setOpacity(1);
1755 if (m_layerClones) {
1756 LayerMap::const_iterator end = m_layerClones->end();
1757 for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) {
1758 PlatformCALayer* currLayer = it->value.get();
1759 currLayer->setPosition(point);
1760 currLayer->setAnchorPoint(anchorPoint);
1761 currLayer->setTransform(TransformationMatrix());
1762 currLayer->setOpacity(1);
1766 moveOrCopyAnimations(Move, m_layer.get(), m_structuralLayer.get());
1769 GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const
1772 return StructuralLayerForPreserves3D;
1775 return StructuralLayerForReplicaFlattening;
1777 return NoStructuralLayer;
1780 void GraphicsLayerCA::updateLayerDrawsContent()
1783 m_layer->setNeedsDisplay();
1785 m_layer->setContents(0);
1786 if (m_layerClones) {
1787 LayerMap::const_iterator end = m_layerClones->end();
1788 for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it)
1789 it->value->setContents(0);
1794 void GraphicsLayerCA::updateAcceleratesDrawing()
1796 m_layer->setAcceleratesDrawing(m_acceleratesDrawing);
1799 void GraphicsLayerCA::updateDebugBorder()
1801 if (isShowingDebugBorder())
1802 updateDebugIndicators();
1804 m_layer->setBorderWidth(0);
1807 FloatRect GraphicsLayerCA::adjustTiledLayerVisibleRect(TiledBacking* tiledBacking, const FloatRect& oldVisibleRect, const FloatRect& newVisibleRect, const FloatSize& oldSize, const FloatSize& newSize)
1809 // If the old visible rect is empty, we have no information about how the visible area is changing
1810 // (maybe the layer was just created), so don't attempt to expand. Also don't attempt to expand
1811 // if the size changed or the rects don't overlap.
1812 if (oldVisibleRect.isEmpty() || newSize != oldSize || !newVisibleRect.intersects(oldVisibleRect))
1813 return newVisibleRect;
1815 const float paddingMultiplier = 2;
1817 float leftEdgeDelta = paddingMultiplier * (newVisibleRect.x() - oldVisibleRect.x());
1818 float rightEdgeDelta = paddingMultiplier * (newVisibleRect.maxX() - oldVisibleRect.maxX());
1820 float topEdgeDelta = paddingMultiplier * (newVisibleRect.y() - oldVisibleRect.y());
1821 float bottomEdgeDelta = paddingMultiplier * (newVisibleRect.maxY() - oldVisibleRect.maxY());
1823 FloatRect existingTileBackingRect = tiledBacking->visibleRect();
1824 FloatRect expandedRect = newVisibleRect;
1826 // More exposed on left side.
1827 if (leftEdgeDelta < 0) {
1828 float newLeft = expandedRect.x() + leftEdgeDelta;
1829 // Pad to the left, but don't reduce padding that's already in the backing store (since we're still exposing to the left).
1830 if (newLeft < existingTileBackingRect.x())
1831 expandedRect.shiftXEdgeTo(newLeft);
1833 expandedRect.shiftXEdgeTo(existingTileBackingRect.x());
1836 // More exposed on right.
1837 if (rightEdgeDelta > 0) {
1838 float newRight = expandedRect.maxX() + rightEdgeDelta;
1839 // Pad to the right, but don't reduce padding that's already in the backing store (since we're still exposing to the right).
1840 if (newRight > existingTileBackingRect.maxX())
1841 expandedRect.setWidth(newRight - expandedRect.x());
1843 expandedRect.setWidth(existingTileBackingRect.maxX() - expandedRect.x());
1846 // More exposed at top.
1847 if (topEdgeDelta < 0) {
1848 float newTop = expandedRect.y() + topEdgeDelta;
1849 if (newTop < existingTileBackingRect.y())
1850 expandedRect.shiftYEdgeTo(newTop);
1852 expandedRect.shiftYEdgeTo(existingTileBackingRect.y());
1855 // More exposed on bottom.
1856 if (bottomEdgeDelta > 0) {
1857 float newBottom = expandedRect.maxY() + bottomEdgeDelta;
1858 if (newBottom > existingTileBackingRect.maxY())
1859 expandedRect.setHeight(newBottom - expandedRect.y());
1861 expandedRect.setHeight(existingTileBackingRect.maxY() - expandedRect.y());
1864 expandedRect.intersect(tiledBacking->boundsWithoutMargin());
1865 return expandedRect;
1868 void GraphicsLayerCA::updateVisibleRect(const FloatRect& oldVisibleRect)
1870 if (!m_layer->usesTiledBackingLayer())
1873 FloatRect tileArea = m_visibleRect;
1874 if (m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
1875 tileArea = adjustTiledLayerVisibleRect(tiledBacking(), oldVisibleRect, tileArea, m_sizeAtLastVisibleRectUpdate, m_size);
1877 tiledBacking()->setVisibleRect(tileArea);
1879 m_sizeAtLastVisibleRectUpdate = m_size;
1882 void GraphicsLayerCA::updateTiles()
1884 if (!m_layer->usesTiledBackingLayer())
1887 tiledBacking()->revalidateTiles();
1890 void GraphicsLayerCA::updateBackgroundColor()
1892 m_layer->setBackgroundColor(m_backgroundColor);
1895 void GraphicsLayerCA::updateContentsImage()
1897 if (m_pendingContentsImage) {
1898 if (!m_contentsLayer.get()) {
1899 m_contentsLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
1901 m_contentsLayer->setName("Image Layer");
1903 setupContentsLayer(m_contentsLayer.get());
1904 // m_contentsLayer will be parented by updateSublayerList
1907 // FIXME: maybe only do trilinear if the image is being scaled down,
1908 // but then what if the layer size changes?
1909 m_contentsLayer->setMinificationFilter(PlatformCALayer::Trilinear);
1910 m_contentsLayer->setContents(m_pendingContentsImage.get());
1911 m_pendingContentsImage = 0;
1913 if (m_contentsLayerClones) {
1914 LayerMap::const_iterator end = m_contentsLayerClones->end();
1915 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it)
1916 it->value->setContents(m_contentsLayer->contents());
1919 updateContentsRects();
1922 // m_contentsLayer will be removed via updateSublayerList.
1923 m_contentsLayer = 0;
1927 void GraphicsLayerCA::updateContentsPlatformLayer()
1929 if (!m_contentsLayer)
1932 // Platform layer was set as m_contentsLayer, and will get parented in updateSublayerList().
1933 setupContentsLayer(m_contentsLayer.get());
1935 if (m_contentsLayerPurpose == ContentsLayerForCanvas)
1936 m_contentsLayer->setNeedsDisplay();
1938 updateContentsRects();
1941 void GraphicsLayerCA::updateContentsColorLayer()
1943 // Color layer was set as m_contentsLayer, and will get parented in updateSublayerList().
1944 if (!m_contentsLayer || m_contentsLayerPurpose != ContentsLayerForBackgroundColor)
1947 setupContentsLayer(m_contentsLayer.get());
1948 updateContentsRects();
1949 ASSERT(m_contentsSolidColor.isValid());
1950 m_contentsLayer->setBackgroundColor(m_contentsSolidColor);
1952 if (m_contentsLayerClones) {
1953 LayerMap::const_iterator end = m_contentsLayerClones->end();
1954 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it)
1955 it->value->setBackgroundColor(m_contentsSolidColor);
1959 void GraphicsLayerCA::updateContentsRects()
1961 if (!m_contentsLayer)
1964 FloatPoint contentOrigin;
1965 FloatRect contentBounds(0, 0, m_contentsRect.width(), m_contentsRect.height());
1967 FloatPoint clippingOrigin;
1968 FloatRect clippingBounds;
1970 bool gainedOrLostClippingLayer = false;
1971 if (!m_contentsClippingRect.contains(m_contentsRect)) {
1972 if (!m_contentsClippingLayer) {
1973 m_contentsClippingLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
1974 m_contentsClippingLayer->setMasksToBounds(true);
1975 m_contentsClippingLayer->setAnchorPoint(FloatPoint());
1977 m_contentsClippingLayer->setName("Contents Clipping");
1979 m_contentsLayer->removeFromSuperlayer();
1980 m_contentsClippingLayer->appendSublayer(m_contentsLayer.get());
1981 gainedOrLostClippingLayer = true;
1984 clippingOrigin = m_contentsClippingRect.location();
1985 clippingBounds.setSize(m_contentsClippingRect.size());
1987 contentOrigin = FloatPoint(m_contentsRect.location() - m_contentsClippingRect.location());
1989 m_contentsClippingLayer->setPosition(clippingOrigin);
1990 m_contentsClippingLayer->setBounds(clippingBounds);
1992 m_contentsLayer->setPosition(contentOrigin);
1993 m_contentsLayer->setBounds(contentBounds);
1996 if (m_contentsClippingLayer) {
1997 m_contentsLayer->removeFromSuperlayer();
1999 m_contentsClippingLayer->removeFromSuperlayer();
2000 m_contentsClippingLayer->setOwner(0);
2001 m_contentsClippingLayer = nullptr;
2002 gainedOrLostClippingLayer = true;
2005 contentOrigin = m_contentsRect.location();
2008 if (gainedOrLostClippingLayer)
2009 noteSublayersChanged(DontScheduleFlush);
2011 m_contentsLayer->setPosition(contentOrigin);
2012 m_contentsLayer->setBounds(contentBounds);
2014 if (m_contentsLayerClones) {
2015 LayerMap::const_iterator end = m_contentsLayerClones->end();
2016 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) {
2017 it->value->setPosition(contentOrigin);
2018 it->value->setBounds(contentBounds);
2022 if (m_contentsClippingLayerClones) {
2023 LayerMap::const_iterator end = m_contentsClippingLayerClones->end();
2024 for (LayerMap::const_iterator it = m_contentsClippingLayerClones->begin(); it != end; ++it) {
2025 it->value->setPosition(clippingOrigin);
2026 it->value->setBounds(clippingBounds);
2031 void GraphicsLayerCA::updateMaskLayer()
2033 PlatformCALayer* maskCALayer = m_maskLayer ? toGraphicsLayerCA(m_maskLayer)->primaryLayer() : 0;
2034 m_layer->setMask(maskCALayer);
2036 LayerMap* maskLayerCloneMap = m_maskLayer ? toGraphicsLayerCA(m_maskLayer)->primaryLayerClones() : 0;
2038 if (LayerMap* layerCloneMap = m_layerClones.get()) {
2039 LayerMap::const_iterator end = layerCloneMap->end();
2040 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2041 PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->key) : 0;
2042 it->value->setMask(maskClone);
2047 void GraphicsLayerCA::updateReplicatedLayers()
2049 // Clone the descendants of the replicated layer, and parent under us.
2050 ReplicaState replicaState(ReplicaState::ReplicaBranch);
2052 RefPtr<PlatformCALayer>replicaRoot = replicatedLayerRoot(replicaState);
2056 if (m_structuralLayer)
2057 m_structuralLayer->insertSublayer(replicaRoot.get(), 0);
2059 m_layer->insertSublayer(replicaRoot.get(), 0);
2062 // For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1.
2063 GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const
2065 size_t depth = m_replicaBranches.size();
2067 const size_t bitsPerUChar = sizeof(UChar) * 8;
2068 size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar;
2070 Vector<UChar> result(vectorSize);
2073 // Create a string from the bit sequence which we can use to identify the clone.
2074 // Note that the string may contain embedded nulls, but that's OK.
2075 for (size_t i = 0; i < depth; ++i) {
2076 UChar& currChar = result[i / bitsPerUChar];
2077 currChar = (currChar << 1) | m_replicaBranches[i];
2080 return String::adopt(result);
2083 PassRefPtr<PlatformCALayer> GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState)
2085 // Limit replica nesting, to avoid 2^N explosion of replica layers.
2086 if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth)
2089 GraphicsLayerCA* replicatedLayer = toGraphicsLayerCA(m_replicatedLayer);
2091 RefPtr<PlatformCALayer> clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel);
2092 FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer();
2094 // Replica root has no offset or transform
2095 clonedLayerRoot->setPosition(cloneRootPosition);
2096 clonedLayerRoot->setTransform(TransformationMatrix());
2098 return clonedLayerRoot;
2101 void GraphicsLayerCA::updateAnimations()
2103 if (m_animationsToProcess.size()) {
2104 AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end();
2105 for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) {
2106 const String& currAnimationName = it->key;
2107 AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName);
2108 if (animationIt == m_runningAnimations.end())
2111 const AnimationProcessingAction& processingInfo = it->value;
2112 const Vector<LayerPropertyAnimation>& animations = animationIt->value;
2113 for (size_t i = 0; i < animations.size(); ++i) {
2114 const LayerPropertyAnimation& currAnimation = animations[i];
2115 switch (processingInfo.action) {
2117 removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, currAnimation.m_subIndex);
2120 pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, currAnimation.m_subIndex, processingInfo.timeOffset);
2125 if (processingInfo.action == Remove)
2126 m_runningAnimations.remove(currAnimationName);
2129 m_animationsToProcess.clear();
2132 size_t numAnimations;
2133 if ((numAnimations = m_uncomittedAnimations.size())) {
2134 for (size_t i = 0; i < numAnimations; ++i) {
2135 const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i];
2136 setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_subIndex, pendingAnimation.m_timeOffset);
2138 AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name);
2139 if (it == m_runningAnimations.end()) {
2140 Vector<LayerPropertyAnimation> animations;
2141 animations.append(pendingAnimation);
2142 m_runningAnimations.add(pendingAnimation.m_name, animations);
2145 Vector<LayerPropertyAnimation>& animations = it->value;
2146 animations.append(pendingAnimation);
2149 m_uncomittedAnimations.clear();
2153 bool GraphicsLayerCA::isRunningTransformAnimation() const
2155 AnimationsMap::const_iterator end = m_runningAnimations.end();
2156 for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
2157 const Vector<LayerPropertyAnimation>& propertyAnimations = it->value;
2158 size_t numAnimations = propertyAnimations.size();
2159 for (size_t i = 0; i < numAnimations; ++i) {
2160 const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
2161 if (currAnimation.m_property == AnimatedPropertyWebkitTransform)
2168 void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, int subIndex, double timeOffset)
2170 PlatformCALayer* layer = animatedLayer(property);
2173 caAnim->setBeginTime(CACurrentMediaTime() - timeOffset);
2175 String animationID = animationIdentifier(animationName, property, index, subIndex);
2177 layer->removeAnimationForKey(animationID);
2178 layer->addAnimationForKey(animationID, caAnim);
2180 if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
2181 LayerMap::const_iterator end = layerCloneMap->end();
2182 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2183 // Skip immediate replicas, since they move with the original.
2184 if (m_replicaLayer && isReplicatedRootClone(it->key))
2187 it->value->removeAnimationForKey(animationID);
2188 it->value->addAnimationForKey(animationID, caAnim);
2193 // Workaround for <rdar://problem/7311367>
2194 static void bug7311367Workaround(PlatformCALayer* transformLayer, const TransformationMatrix& transform)
2196 if (!transformLayer)
2199 TransformationMatrix caTransform = transform;
2200 caTransform.setM41(caTransform.m41() + 1);
2201 transformLayer->setTransform(caTransform);
2203 caTransform.setM41(caTransform.m41() - 1);
2204 transformLayer->setTransform(caTransform);
2207 bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index, int subIndex)
2209 PlatformCALayer* layer = animatedLayer(property);
2211 String animationID = animationIdentifier(animationName, property, index, subIndex);
2213 if (!layer->animationForKey(animationID))
2216 layer->removeAnimationForKey(animationID);
2217 bug7311367Workaround(m_structuralLayer.get(), m_transform);
2219 if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
2220 LayerMap::const_iterator end = layerCloneMap->end();
2221 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2222 // Skip immediate replicas, since they move with the original.
2223 if (m_replicaLayer && isReplicatedRootClone(it->key))
2226 it->value->removeAnimationForKey(animationID);
2232 void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, int subIndex, double timeOffset)
2234 PlatformCALayer* layer = animatedLayer(property);
2236 String animationID = animationIdentifier(animationName, property, index, subIndex);
2238 RefPtr<PlatformCAAnimation> curAnim = layer->animationForKey(animationID);
2242 // Animations on the layer are immutable, so we have to clone and modify.
2243 RefPtr<PlatformCAAnimation> newAnim = curAnim->copy();
2245 newAnim->setSpeed(0);
2246 newAnim->setTimeOffset(timeOffset);
2248 layer->addAnimationForKey(animationID, newAnim.get()); // This will replace the running animation.
2250 // Pause the animations on the clones too.
2251 if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
2252 LayerMap::const_iterator end = layerCloneMap->end();
2253 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2254 // Skip immediate replicas, since they move with the original.
2255 if (m_replicaLayer && isReplicatedRootClone(it->key))
2257 it->value->addAnimationForKey(animationID, newAnim.get());
2262 void GraphicsLayerCA::repaintLayerDirtyRects()
2264 if (m_needsFullRepaint) {
2265 ASSERT(!m_dirtyRects.size());
2266 m_layer->setNeedsDisplay();
2267 m_needsFullRepaint = false;
2271 if (!m_dirtyRects.size())
2274 for (size_t i = 0; i < m_dirtyRects.size(); ++i)
2275 m_layer->setNeedsDisplayInRect(m_dirtyRects[i]);
2277 m_dirtyRects.clear();
2280 void GraphicsLayerCA::updateContentsNeedsDisplay()
2282 if (m_contentsLayer)
2283 m_contentsLayer->setNeedsDisplay();
2286 bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset)
2288 ASSERT(valueList.property() != AnimatedPropertyWebkitTransform && (!supportsAcceleratedFilterAnimations() || valueList.property() != AnimatedPropertyWebkitFilter));
2290 bool isKeyframe = valueList.size() > 2;
2293 bool additive = false;
2294 int animationIndex = 0;
2296 RefPtr<PlatformCAAnimation> caAnimation;
2299 caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive);
2300 valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get());
2302 caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive);
2303 valuesOK = setAnimationEndpoints(valueList, animation, caAnimation.get());
2309 m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, 0, timeOffset));
2314 bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const TransformOperations* operations, const Animation* animation, const String& animationName, const FloatSize& boxSize, int animationIndex, double timeOffset, bool isMatrixAnimation)
2316 TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : operations->operations().at(animationIndex)->type();
2317 bool additive = animationIndex > 0;
2318 bool isKeyframe = valueList.size() > 2;
2320 RefPtr<PlatformCAAnimation> caAnimation;
2321 bool validMatrices = true;
2323 caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive);
2324 validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
2326 caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive);
2327 validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
2333 m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, 0, timeOffset));
2337 bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const FloatSize& boxSize)
2339 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
2341 bool hasBigRotation;
2342 int listIndex = validateTransformOperations(valueList, hasBigRotation);
2343 const TransformOperations* operations = (listIndex >= 0) ? &static_cast<const TransformAnimationValue&>(valueList.at(listIndex)).value() : 0;
2345 bool validMatrices = true;
2347 // If function lists don't match we do a matrix animation, otherwise we do a component hardware animation.
2348 bool isMatrixAnimation = listIndex < 0;
2349 int numAnimations = isMatrixAnimation ? 1 : operations->size();
2352 bool reverseAnimationList = false;
2354 bool reverseAnimationList = true;
2356 // Old versions of Core Animation apply animations in reverse order (<rdar://problem/7095638>) so we need to flip the list.
2357 // to be non-additive. For binary compatibility, the current version of Core Animation preserves this behavior for applications linked
2358 // on or before Snow Leopard.
2359 // FIXME: This fix has not been added to QuartzCore on Windows yet (<rdar://problem/9112233>) so we expect the
2360 // reversed animation behavior
2361 static bool executableWasLinkedOnOrBeforeSnowLeopard = wkExecutableWasLinkedOnOrBeforeSnowLeopard();
2362 if (!executableWasLinkedOnOrBeforeSnowLeopard)
2363 reverseAnimationList = false;
2365 #endif // PLATFORM(IOS)
2366 if (reverseAnimationList) {
2367 for (int animationIndex = numAnimations - 1; animationIndex >= 0; --animationIndex) {
2368 if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
2369 validMatrices = false;
2374 for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
2375 if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
2376 validMatrices = false;
2382 return validMatrices;
2385 #if ENABLE(CSS_FILTERS)
2386 bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const FilterOperation* operation, const Animation* animation, const String& animationName, int animationIndex, double timeOffset)
2388 bool isKeyframe = valueList.size() > 2;
2390 FilterOperation::OperationType filterOp = operation->type();
2391 int numAnimatedProperties = PlatformCAFilters::numAnimatedFilterProperties(filterOp);
2393 // Each filter might need to animate multiple properties, each with their own keyPath. The keyPath is always of the form:
2395 // filter.filter_<animationIndex>.<filterPropertyName>
2397 // PlatformCAAnimation tells us how many properties each filter has and we iterate that many times and create an animation
2398 // for each. This internalFilterPropertyIndex gets passed to PlatformCAAnimation so it can properly create the property animation
2400 for (int internalFilterPropertyIndex = 0; internalFilterPropertyIndex < numAnimatedProperties; ++internalFilterPropertyIndex) {
2402 RefPtr<PlatformCAAnimation> caAnimation;
2403 String keyPath = String::format("filters.filter_%d.%s", animationIndex, PlatformCAFilters::animatedFilterPropertyName(filterOp, internalFilterPropertyIndex));
2406 caAnimation = createKeyframeAnimation(animation, keyPath, false);
2407 valuesOK = setFilterAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex, filterOp);
2409 caAnimation = createBasicAnimation(animation, keyPath, false);
2410 valuesOK = setFilterAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex);
2415 m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, internalFilterPropertyIndex, timeOffset));
2421 bool GraphicsLayerCA::createFilterAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset)
2423 ASSERT(valueList.property() == AnimatedPropertyWebkitFilter);
2425 int listIndex = validateFilterOperations(valueList);
2429 const FilterOperations& operations = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
2430 // Make sure the platform layer didn't fallback to using software filter compositing instead.
2431 if (!filtersCanBeComposited(operations))
2434 int numAnimations = operations.size();
2436 // FIXME: We can't currently hardware animate shadows.
2437 for (int i = 0; i < numAnimations; ++i) {
2438 if (operations.at(i)->type() == FilterOperation::DROP_SHADOW)
2442 for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
2443 if (!appendToUncommittedAnimations(valueList, operations.operations().at(animationIndex).get(), animation, animationName, animationIndex, timeOffset))
2451 PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, const String& keyPath, bool additive)
2453 RefPtr<PlatformCAAnimation> basicAnim = createPlatformCAAnimation(PlatformCAAnimation::Basic, keyPath);
2454 setupAnimation(basicAnim.get(), anim, additive);
2458 PassRefPtr<PlatformCAAnimation>GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, const String& keyPath, bool additive)
2460 RefPtr<PlatformCAAnimation> keyframeAnim = createPlatformCAAnimation(PlatformCAAnimation::Keyframe, keyPath);
2461 setupAnimation(keyframeAnim.get(), anim, additive);
2462 return keyframeAnim;
2465 void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive)
2467 double duration = anim->duration();
2469 duration = cAnimationAlmostZeroDuration;
2471 float repeatCount = anim->iterationCount();
2472 if (repeatCount == Animation::IterationCountInfinite)
2473 repeatCount = std::numeric_limits<float>::max();
2474 else if (anim->direction() == Animation::AnimationDirectionAlternate || anim->direction() == Animation::AnimationDirectionAlternateReverse)
2477 PlatformCAAnimation::FillModeType fillMode = PlatformCAAnimation::NoFillMode;
2478 switch (anim->fillMode()) {
2479 case AnimationFillModeNone:
2480 fillMode = PlatformCAAnimation::Forwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash.
2482 case AnimationFillModeBackwards:
2483 fillMode = PlatformCAAnimation::Both; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash.
2485 case AnimationFillModeForwards:
2486 fillMode = PlatformCAAnimation::Forwards;
2488 case AnimationFillModeBoth:
2489 fillMode = PlatformCAAnimation::Both;
2493 propertyAnim->setDuration(duration);
2494 propertyAnim->setRepeatCount(repeatCount);
2495 propertyAnim->setAutoreverses(anim->direction() == Animation::AnimationDirectionAlternate || anim->direction() == Animation::AnimationDirectionAlternateReverse);
2496 propertyAnim->setRemovedOnCompletion(false);
2497 propertyAnim->setAdditive(additive);
2498 propertyAnim->setFillMode(fillMode);
2501 const TimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue& animValue, const Animation& anim)
2503 if (animValue.timingFunction())
2504 return animValue.timingFunction();
2505 if (anim.isTimingFunctionSet())
2506 return anim.timingFunction().get();
2508 return CubicBezierTimingFunction::defaultTimingFunction();
2511 bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim)
2513 bool forwards = animation->directionIsForwards();
2515 unsigned fromIndex = !forwards;
2516 unsigned toIndex = forwards;
2518 switch (valueList.property()) {
2519 case AnimatedPropertyOpacity: {
2520 basicAnim->setFromValue(static_cast<const FloatAnimationValue&>(valueList.at(fromIndex)).value());
2521 basicAnim->setToValue(static_cast<const FloatAnimationValue&>(valueList.at(toIndex)).value());
2525 ASSERT_NOT_REACHED(); // we don't animate color yet
2529 // This codepath is used for 2-keyframe animations, so we still need to look in the start
2530 // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
2531 const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), *animation);
2533 basicAnim->setTimingFunction(timingFunction, !forwards);
2538 bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim)
2540 Vector<float> keyTimes;
2541 Vector<float> values;
2542 Vector<const TimingFunction*> timingFunctions;
2544 bool forwards = animation->directionIsForwards();
2546 for (unsigned i = 0; i < valueList.size(); ++i) {
2547 unsigned index = forwards ? i : (valueList.size() - i - 1);
2548 const AnimationValue& curValue = valueList.at(index);
2549 keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime()));
2551 switch (valueList.property()) {
2552 case AnimatedPropertyOpacity: {
2553 const FloatAnimationValue& floatValue = static_cast<const FloatAnimationValue&>(curValue);
2554 values.append(floatValue.value());
2558 ASSERT_NOT_REACHED(); // we don't animate color yet
2562 if (i < (valueList.size() - 1))
2563 timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation));
2566 keyframeAnim->setKeyTimes(keyTimes);
2567 keyframeAnim->setValues(values);
2568 keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
2573 bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const FloatSize& boxSize)
2575 ASSERT(valueList.size() == 2);
2577 bool forwards = animation->directionIsForwards();
2579 unsigned fromIndex = !forwards;
2580 unsigned toIndex = forwards;
2582 const TransformAnimationValue& startValue = static_cast<const TransformAnimationValue&>(valueList.at(fromIndex));
2583 const TransformAnimationValue& endValue = static_cast<const TransformAnimationValue&>(valueList.at(toIndex));
2585 if (isMatrixAnimation) {
2586 TransformationMatrix fromTransform, toTransform;
2587 startValue.value().apply(boxSize, fromTransform);
2588 endValue.value().apply(boxSize, toTransform);
2590 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
2591 if (!fromTransform.isInvertible() || !toTransform.isInvertible())
2594 basicAnim->setFromValue(fromTransform);
2595 basicAnim->setToValue(toTransform);
2597 if (isTransformTypeNumber(transformOpType)) {
2599 getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue);
2600 basicAnim->setFromValue(fromValue);
2603 getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue);
2604 basicAnim->setToValue(toValue);
2605 } else if (isTransformTypeFloatPoint3D(transformOpType)) {
2606 FloatPoint3D fromValue;
2607 getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue);
2608 basicAnim->setFromValue(fromValue);
2610 FloatPoint3D toValue;
2611 getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue);
2612 basicAnim->setToValue(toValue);
2614 TransformationMatrix fromValue;
2615 getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue);
2616 basicAnim->setFromValue(fromValue);
2618 TransformationMatrix toValue;
2619 getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue);
2620 basicAnim->setToValue(toValue);
2624 // This codepath is used for 2-keyframe animations, so we still need to look in the start
2625 // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
2626 const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), *animation);
2627 basicAnim->setTimingFunction(timingFunction, !forwards);
2629 PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
2630 if (valueFunction != PlatformCAAnimation::NoValueFunction)
2631 basicAnim->setValueFunction(valueFunction);
2636 bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const FloatSize& boxSize)
2638 Vector<float> keyTimes;
2639 Vector<float> floatValues;
2640 Vector<FloatPoint3D> floatPoint3DValues;
2641 Vector<TransformationMatrix> transformationMatrixValues;
2642 Vector<const TimingFunction*> timingFunctions;
2644 bool forwards = animation->directionIsForwards();
2646 for (unsigned i = 0; i < valueList.size(); ++i) {
2647 unsigned index = forwards ? i : (valueList.size() - i - 1);
2648 const TransformAnimationValue& curValue = static_cast<const TransformAnimationValue&>(valueList.at(index));
2649 keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime()));
2651 TransformationMatrix transform;
2653 if (isMatrixAnimation) {
2654 curValue.value().apply(boxSize, transform);
2656 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
2657 if (!transform.isInvertible())
2660 transformationMatrixValues.append(transform);
2662 const TransformOperation* transformOp = curValue.value().at(functionIndex);
2663 if (isTransformTypeNumber(transformOpType)) {
2665 getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
2666 floatValues.append(value);
2667 } else if (isTransformTypeFloatPoint3D(transformOpType)) {
2669 getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
2670 floatPoint3DValues.append(value);
2672 TransformationMatrix value;
2673 getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
2674 transformationMatrixValues.append(value);
2677 curValue.value().apply(boxSize, transform);
2680 if (i < (valueList.size() - 1))
2681 timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation));
2684 keyframeAnim->setKeyTimes(keyTimes);
2686 if (isTransformTypeNumber(transformOpType))
2687 keyframeAnim->setValues(floatValues);
2688 else if (isTransformTypeFloatPoint3D(transformOpType))
2689 keyframeAnim->setValues(floatPoint3DValues);
2691 keyframeAnim->setValues(transformationMatrixValues);
2693 keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
2695 PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
2696 if (valueFunction != PlatformCAAnimation::NoValueFunction)
2697 keyframeAnim->setValueFunction(valueFunction);
2702 #if ENABLE(CSS_FILTERS)
2703 bool GraphicsLayerCA::setFilterAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim, int functionIndex, int internalFilterPropertyIndex)
2705 ASSERT(valueList.size() == 2);
2707 bool forwards = animation->directionIsForwards();
2709 unsigned fromIndex = !forwards;
2710 unsigned toIndex = forwards;
2712 const FilterAnimationValue& fromValue = static_cast<const FilterAnimationValue&>(valueList.at(fromIndex));
2713 const FilterAnimationValue& toValue = static_cast<const FilterAnimationValue&>(valueList.at(toIndex));
2715 const FilterOperation* fromOperation = fromValue.value().at(functionIndex);
2716 const FilterOperation* toOperation = toValue.value().at(functionIndex);
2718 RefPtr<DefaultFilterOperation> defaultFromOperation;
2719 RefPtr<DefaultFilterOperation> defaultToOperation;
2721 ASSERT(fromOperation || toOperation);
2723 if (!fromOperation) {
2724 defaultFromOperation = DefaultFilterOperation::create(toOperation->type());
2725 fromOperation = defaultFromOperation.get();
2729 defaultToOperation = DefaultFilterOperation::create(fromOperation->type());
2730 toOperation = defaultToOperation.get();
2733 basicAnim->setFromValue(fromOperation, internalFilterPropertyIndex);
2734 basicAnim->setToValue(toOperation, internalFilterPropertyIndex);
2736 // This codepath is used for 2-keyframe animations, so we still need to look in the start
2737 // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
2738 basicAnim->setTimingFunction(timingFunctionForAnimationValue(valueList.at(0), *animation), !forwards);
2743 bool GraphicsLayerCA::setFilterAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, int internalFilterPropertyIndex, FilterOperation::OperationType filterOp)
2745 Vector<float> keyTimes;
2746 Vector<RefPtr<FilterOperation>> values;
2747 Vector<const TimingFunction*> timingFunctions;
2748 RefPtr<DefaultFilterOperation> defaultOperation;
2750 bool forwards = animation->directionIsForwards();
2752 for (unsigned i = 0; i < valueList.size(); ++i) {
2753 unsigned index = forwards ? i : (valueList.size() - i - 1);
2754 const FilterAnimationValue& curValue = static_cast<const FilterAnimationValue&>(valueList.at(index));
2755 keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime()));
2757 if (curValue.value().operations().size() > static_cast<size_t>(functionIndex))
2758 values.append(curValue.value().operations()[functionIndex]);
2760 if (!defaultOperation)
2761 defaultOperation = DefaultFilterOperation::create(filterOp);
2762 values.append(defaultOperation);
2765 if (i < (valueList.size() - 1))
2766 timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation));
2769 keyframeAnim->setKeyTimes(keyTimes);
2770 keyframeAnim->setValues(values, internalFilterPropertyIndex);
2771 keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
2777 void GraphicsLayerCA::suspendAnimations(double time)
2779 double t = PlatformCALayer::currentTimeToMediaTime(time ? time : monotonicallyIncreasingTime());
2780 primaryLayer()->setSpeed(0);
2781 primaryLayer()->setTimeOffset(t);
2783 // Suspend the animations on the clones too.
2784 if (LayerMap* layerCloneMap = primaryLayerClones()) {
2785 LayerMap::const_iterator end = layerCloneMap->end();
2786 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2787 it->value->setSpeed(0);
2788 it->value->setTimeOffset(t);
2793 void GraphicsLayerCA::resumeAnimations()
2795 primaryLayer()->setSpeed(1);
2796 primaryLayer()->setTimeOffset(0);
2798 // Resume the animations on the clones too.
2799 if (LayerMap* layerCloneMap = primaryLayerClones()) {
2800 LayerMap::const_iterator end = layerCloneMap->end();
2801 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
2802 it->value->setSpeed(1);
2803 it->value->setTimeOffset(0);
2808 PlatformCALayer* GraphicsLayerCA::hostLayerForSublayers() const
2810 return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get();
2813 PlatformCALayer* GraphicsLayerCA::layerForSuperlayer() const
2815 return m_structuralLayer ? m_structuralLayer.get() : m_layer.get();
2818 PlatformCALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const
2820 return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer();
2823 GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const
2825 return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones();
2828 void GraphicsLayerCA::updateContentsScale(float pageScaleFactor)
2830 float contentsScale = pageScaleFactor * deviceScaleFactor();
2832 if (m_isPageTiledBackingLayer && tiledBacking()) {
2833 float zoomedOutScale = m_client.zoomedOutPageScaleFactor() * deviceScaleFactor();
2834 tiledBacking()->setZoomedOutContentsScale(zoomedOutScale);
2837 if (contentsScale == m_layer->contentsScale())
2840 m_layer->setContentsScale(contentsScale);
2842 if (tiledBacking()) {
2843 // Scale change may swap in a different set of tiles changing the custom child layers.
2844 if (m_isPageTiledBackingLayer)
2845 m_uncommittedChanges |= ChildrenChanged;
2846 // Tiled backing repaints automatically on scale change.
2851 m_layer->setNeedsDisplay();
2854 void GraphicsLayerCA::updateCustomAppearance()
2856 m_layer->updateCustomAppearance(m_customAppearance);
2859 void GraphicsLayerCA::updateCustomBehavior()
2861 m_layer->updateCustomBehavior(m_customBehavior);
2864 void GraphicsLayerCA::setShowDebugBorder(bool showBorder)
2866 if (showBorder == m_showDebugBorder)
2869 GraphicsLayer::setShowDebugBorder(showBorder);
2870 noteLayerPropertyChanged(DebugIndicatorsChanged);
2873 void GraphicsLayerCA::setShowRepaintCounter(bool showCounter)
2875 if (showCounter == m_showRepaintCounter)
2878 GraphicsLayer::setShowRepaintCounter(showCounter);
2879 noteLayerPropertyChanged(DebugIndicatorsChanged);
2882 void GraphicsLayerCA::setDebugBackgroundColor(const Color& color)
2884 if (color.isValid())
2885 m_layer->setBackgroundColor(color);
2887 m_layer->setBackgroundColor(Color::transparent);
2890 void GraphicsLayerCA::getDebugBorderInfo(Color& color, float& width) const
2892 if (m_isPageTiledBackingLayer) {
2893 color = Color(0, 0, 128, 128); // tile cache layer: dark blue
2898 GraphicsLayer::getDebugBorderInfo(color, width);
2901 void GraphicsLayerCA::dumpAdditionalProperties(TextStream& textStream, int indent, LayerTreeAsTextBehavior behavior) const
2903 if (behavior & LayerTreeAsTextIncludeVisibleRects) {
2904 writeIndent(textStream, indent + 1);
2905 textStream << "(visible rect " << m_visibleRect.x() << ", " << m_visibleRect.y() << " " << m_visibleRect.width() << " x " << m_visibleRect.height() << ")\n";
2907 writeIndent(textStream, indent + 1);
2908 textStream << "(contentsScale " << m_layer->contentsScale() << ")\n";
2911 if (tiledBacking() && (behavior & LayerTreeAsTextIncludeTileCaches)) {
2912 if (behavior & LayerTreeAsTextDebug) {
2913 writeIndent(textStream, indent + 1);
2914 textStream << "(tiled backing " << tiledBacking() << ")\n";
2917 IntRect tileCoverageRect = tiledBacking()->tileCoverageRect();
2918 writeIndent(textStream, indent + 1);
2919 textStream << "(tile cache coverage " << tileCoverageRect.x() << ", " << tileCoverageRect.y() << " " << tileCoverageRect.width() << " x " << tileCoverageRect.height() << ")\n";
2921 IntSize tileSize = tiledBacking()->tileSize();
2922 writeIndent(textStream, indent + 1);
2923 textStream << "(tile size " << tileSize.width() << " x " << tileSize.height() << ")\n";
2925 IntRect gridExtent = tiledBacking()->tileGridExtent();
2926 writeIndent(textStream, indent + 1);
2927 textStream << "(top left tile " << gridExtent.x() << ", " << gridExtent.y() << " tiles grid " << gridExtent.width() << " x " << gridExtent.height() << ")\n";
2930 if (behavior & LayerTreeAsTextIncludeContentLayers) {
2931 if (m_contentsClippingLayer) {
2932 writeIndent(textStream, indent + 1);
2933 textStream << "(contents clipping layer " << m_contentsClippingLayer->position().x() << ", " << m_contentsClippingLayer->position().y()
2934 << " " << m_contentsClippingLayer->bounds().width() << " x " << m_contentsClippingLayer->bounds().height() << ")\n";
2937 if (m_contentsLayer) {
2938 writeIndent(textStream, indent + 1);
2939 textStream << "(contents layer " << m_contentsLayer->position().x() << ", " << m_contentsLayer->position().y()
2940 << " " << m_contentsLayer->bounds().width() << " x " << m_contentsLayer->bounds().height() << ")\n";
2945 void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth)
2947 if (color.isValid()) {
2948 m_layer->setBorderColor(color);
2949 m_layer->setBorderWidth(borderWidth);
2951 m_layer->setBorderColor(Color::transparent);
2952 m_layer->setBorderWidth(0);
2956 void GraphicsLayerCA::setCustomAppearance(CustomAppearance customAppearance)
2958 if (customAppearance == m_customAppearance)
2961 GraphicsLayer::setCustomAppearance(customAppearance);
2962 noteLayerPropertyChanged(CustomAppearanceChanged);
2965 void GraphicsLayerCA::setCustomBehavior(CustomBehavior customBehavior)
2967 if (customBehavior == m_customBehavior)
2970 GraphicsLayer::setCustomBehavior(customBehavior);
2971 noteLayerPropertyChanged(CustomBehaviorChanged);
2974 bool GraphicsLayerCA::requiresTiledLayer(float pageScaleFactor) const
2976 if (!m_drawsContent || m_isPageTiledBackingLayer)
2979 // FIXME: catch zero-size height or width here (or earlier)?
2981 int maxPixelDimension = systemMemoryLevel() < cMemoryLevelToUseSmallerPixelDimension ? cMaxPixelDimensionLowMemory : cMaxPixelDimension;
2982 return m_size.width() * pageScaleFactor > maxPixelDimension || m_size.height() * pageScaleFactor > maxPixelDimension;
2984 return m_size.width() * pageScaleFactor > cMaxPixelDimension || m_size.height() * pageScaleFactor > cMaxPixelDimension;
2988 void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer)
2990 ASSERT(m_layer->layerType() != PlatformCALayer::LayerTypePageTiledBackingLayer);
2991 ASSERT(useTiledLayer != m_usingTiledBacking);
2992 RefPtr<PlatformCALayer> oldLayer = m_layer;
2994 PlatformCALayer::LayerType layerType = useTiledLayer ? PlatformCALayer::LayerTypeTiledBackingLayer : PlatformCALayer::LayerTypeWebLayer;
2996 m_layer = createPlatformCALayer(layerType, this);
2998 m_usingTiledBacking = useTiledLayer;
3000 m_layer->adoptSublayers(oldLayer.get());
3002 #ifdef VISIBLE_TILE_WASH
3003 if (m_visibleTileWashLayer)
3004 m_layer->appendSublayer(m_visibleTileWashLayer.get());
3007 if (isMaskLayer()) {
3008 // A mask layer's superlayer is the layer that it masks. Set the MaskLayerChanged dirty bit
3009 // so that the parent will fix up the platform layers in commitLayerChangesAfterSublayers().
3010 if (GraphicsLayer* parentLayer = parent())
3011 toGraphicsLayerCA(parentLayer)->noteLayerPropertyChanged(MaskLayerChanged);
3012 } else if (oldLayer->superlayer()) {
3013 // Skip this step if we don't have a superlayer. This is probably a benign
3014 // case that happens while restructuring the layer tree, and also occurs with
3015 // WebKit2 page overlays, which can become tiled but are out-of-tree.
3016 oldLayer->superlayer()->replaceSublayer(oldLayer.get(), m_layer.get());
3019 m_uncommittedChanges |= ChildrenChanged
3022 | ChildrenTransformChanged
3023 | MasksToBoundsChanged
3024 | ContentsOpaqueChanged
3025 | BackfaceVisibilityChanged
3026 | BackgroundColorChanged
3027 | ContentsScaleChanged
3028 | AcceleratesDrawingChanged
3032 | DebugIndicatorsChanged;
3034 if (m_usingTiledBacking)
3035 m_uncommittedChanges |= VisibleRectChanged;
3038 String name = String::format("%sCALayer(%p) GraphicsLayer(%p) ", (m_layer->layerType() == PlatformCALayer::LayerTypeWebTiledLayer) ? "Tiled " : "", m_layer->platformLayer(), this) + m_name;
3039 m_layer->setName(name);
3042 // move over animations
3043 moveOrCopyAnimations(Move, oldLayer.get(), m_layer.get());
3045 // need to tell new layer to draw itself
3048 client().tiledBackingUsageChanged(this, m_usingTiledBacking);
3051 GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const
3053 return CompositingCoordinatesTopDown;
3056 void GraphicsLayerCA::setupContentsLayer(PlatformCALayer* contentsLayer)
3058 // Turn off implicit animations on the inner layer.
3060 contentsLayer->setMasksToBounds(true);
3063 if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) {
3064 TransformationMatrix flipper(
3065 1.0f, 0.0f, 0.0f, 0.0f,
3066 0.0f, -1.0f, 0.0f, 0.0f,
3067 0.0f, 0.0f, 1.0f, 0.0f,
3068 0.0f, 0.0f, 0.0f, 1.0f);
3069 contentsLayer->setTransform(flipper);
3070 contentsLayer->setAnchorPoint(FloatPoint3D(0, 1, 0));
3072 contentsLayer->setAnchorPoint(FloatPoint3D());
3074 if (isShowingDebugBorder()) {
3075 contentsLayer->setBorderColor(Color(0, 0, 128, 180));
3076 contentsLayer->setBorderWidth(4);
3080 PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, PlatformCALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel)
3085 RefPtr<PlatformCALayer> resultLayer;
3087 // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells
3088 // us whether there's an item there. This technique avoids two hash lookups.
3089 RefPtr<PlatformCALayer> dummy;
3090 LayerMap::AddResult addResult = clones->add(cloneID, dummy);
3091 if (!addResult.isNewEntry) {
3092 // Value was not added, so it exists already.
3093 resultLayer = addResult.iterator->value.get();
3095 resultLayer = cloneLayer(sourceLayer, cloneLevel);
3097 resultLayer->setName(String::format("Clone %d of layer %llu", cloneID[0U], sourceLayer->layerID()));
3099 addResult.iterator->value = resultLayer;
3105 void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer,
3106 RefPtr<PlatformCALayer>& contentsLayer, RefPtr<PlatformCALayer>& contentsClippingLayer, CloneLevel cloneLevel)
3108 structuralLayer = 0;
3112 m_layerClones = adoptPtr(new LayerMap);
3114 if (!m_structuralLayerClones && m_structuralLayer)
3115 m_structuralLayerClones = adoptPtr(new LayerMap);
3117 if (!m_contentsLayerClones && m_contentsLayer)
3118 m_contentsLayerClones = adoptPtr(new LayerMap);
3120 if (!m_contentsClippingLayerClones && m_contentsClippingLayer)
3121 m_contentsClippingLayerClones = adoptPtr(new LayerMap);
3123 primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel);
3124 structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel);
3125 contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel);
3126 contentsClippingLayer = findOrMakeClone(cloneID, m_contentsClippingLayer.get(), m_contentsClippingLayerClones.get(), cloneLevel);
3129 void GraphicsLayerCA::removeCloneLayers()
3131 m_layerClones = nullptr;
3132 m_structuralLayerClones = nullptr;
3133 m_contentsLayerClones = nullptr;
3134 m_contentsClippingLayerClones = nullptr;
3137 FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const
3139 // This can get called during a flush when we've just removed the m_replicaLayer.
3140 if (!m_replicaLayer)
3141 return FloatPoint();
3143 FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition();
3144 return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(),
3145 replicaPosition.y() + m_anchorPoint.y() * m_size.height());
3148 void GraphicsLayerCA::propagateLayerChangeToReplicas()
3150 for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) {
3151 GraphicsLayerCA* currLayerCA = toGraphicsLayerCA(currLayer);
3152 if (!currLayerCA->hasCloneLayers())
3155 if (currLayerCA->replicaLayer())
3156 toGraphicsLayerCA(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged);
3160 PassRefPtr<PlatformCALayer> GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel)
3162 RefPtr<PlatformCALayer> primaryLayer;
3163 RefPtr<PlatformCALayer> structuralLayer;
3164 RefPtr<PlatformCALayer> contentsLayer;
3165 RefPtr<PlatformCALayer> contentsClippingLayer;
3166 ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, contentsClippingLayer, cloneLevel);
3169 RefPtr<PlatformCALayer> maskClone = toGraphicsLayerCA(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
3170 primaryLayer->setMask(maskClone.get());
3173 if (m_replicatedLayer) {
3174 // We are a replica being asked for clones of our layers.
3175 RefPtr<PlatformCALayer> replicaRoot = replicatedLayerRoot(replicaState);
3179 if (structuralLayer) {
3180 structuralLayer->insertSublayer(replicaRoot.get(), 0);
3181 return structuralLayer;
3184 primaryLayer->insertSublayer(replicaRoot.get(), 0);
3185 return primaryLayer;
3188 const Vector<GraphicsLayer*>& childLayers = children();
3189 Vector<RefPtr<PlatformCALayer>> clonalSublayers;
3191 RefPtr<PlatformCALayer> replicaLayer;
3193 if (m_replicaLayer && m_replicaLayer != replicaRoot) {
3194 // We have nested replicas. Ask the replica layer for a clone of its contents.
3195 replicaState.setBranchType(ReplicaState::ReplicaBranch);
3196 replicaLayer = toGraphicsLayerCA(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel);
3197 replicaState.setBranchType(ReplicaState::ChildBranch);
3200 if (contentsClippingLayer) {
3201 ASSERT(contentsLayer);
3202 contentsClippingLayer->appendSublayer(contentsLayer.get());
3205 if (replicaLayer || structuralLayer || contentsLayer || contentsClippingLayer || childLayers.size() > 0) {
3206 if (structuralLayer) {
3207 // Replicas render behind the actual layer content.
3209 clonalSublayers.append(replicaLayer);
3211 // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind.
3212 clonalSublayers.append(primaryLayer);
3213 } else if (contentsClippingLayer) {
3214 // FIXME: add the contents layer in the correct order with negative z-order children.
3215 // This does not cause visible rendering issues because currently contents layers are only used
3216 // for replaced elements that don't have children.
3217 clonalSublayers.append(contentsClippingLayer);
3218 } else if (contentsLayer) {
3219 // FIXME: add the contents layer in the correct order with negative z-order children.
3220 // This does not cause visible rendering issues because currently contents layers are only used
3221 // for replaced elements that don't have children.
3222 clonalSublayers.append(contentsLayer);
3225 replicaState.push(ReplicaState::ChildBranch);
3227 size_t numChildren = childLayers.size();
3228 for (size_t i = 0; i < numChildren; ++i) {
3229 GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
3231 RefPtr<PlatformCALayer> childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
3233 clonalSublayers.append(childLayer);
3238 for (size_t i = 0; i < clonalSublayers.size(); ++i)
3239 clonalSublayers[i]->removeFromSuperlayer();
3242 RefPtr<PlatformCALayer> result;
3243 if (structuralLayer) {
3244 structuralLayer->setSublayers(clonalSublayers);
3246 if (contentsClippingLayer || contentsLayer) {
3247 // If we have a transform layer, then the contents layer is parented in the
3248 // primary layer (which is itself a child of the transform layer).
3249 primaryLayer->removeAllSublayers();
3250 primaryLayer->appendSublayer(contentsClippingLayer ? contentsClippingLayer.get() : contentsLayer.get());
3253 result = structuralLayer;
3255 primaryLayer->setSublayers(clonalSublayers);
3256 result = primaryLayer;
3262 PassRefPtr<PlatformCALayer> GraphicsLayerCA::cloneLayer(PlatformCALayer *layer, CloneLevel cloneLevel)
3264 RefPtr<PlatformCALayer> newLayer = layer->clone(this);
3266 if (cloneLevel == IntermediateCloneLevel) {
3267 newLayer->setOpacity(layer->opacity());
3268 moveOrCopyAnimations(Copy, layer, newLayer.get());
3271 if (isShowingDebugBorder()) {
3272 newLayer->setBorderColor(Color(255, 122, 251));
3273 newLayer->setBorderWidth(2);
3279 void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity)
3281 LayerMap* layerCloneMap = 0;
3283 if (preserves3D()) {
3284 m_layer->setOpacity(accumulatedOpacity);
3285 layerCloneMap = m_layerClones.get();
3287 primaryLayer()->setOpacity(accumulatedOpacity);
3288 layerCloneMap = primaryLayerClones();
3291 if (layerCloneMap) {
3292 LayerMap::const_iterator end = layerCloneMap->end();
3293 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
3294 if (m_replicaLayer && isReplicatedRootClone(it->key))
3296 it->value->setOpacity(m_opacity);
3301 void GraphicsLayerCA::updateOpacityOnLayer()
3303 primaryLayer()->setOpacity(m_opacity);
3305 if (LayerMap* layerCloneMap = primaryLayerClones()) {
3306 LayerMap::const_iterator end = layerCloneMap->end();
3307 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
3308 if (m_replicaLayer && isReplicatedRootClone(it->key))
3311 it->value->setOpacity(m_opacity);
3317 void GraphicsLayerCA::deviceOrPageScaleFactorChanged()
3319 noteChangesForScaleSensitiveProperties();
3322 void GraphicsLayerCA::noteChangesForScaleSensitiveProperties()
3324 noteLayerPropertyChanged(GeometryChanged | ContentsScaleChanged | ContentsOpaqueChanged);
3327 void GraphicsLayerCA::computePixelAlignment(float pageScale, const FloatPoint& positionRelativeToBase,
3328 FloatPoint& position, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset) const
3330 FloatRect baseRelativeBounds(positionRelativeToBase, m_size);
3331 FloatRect scaledBounds = baseRelativeBounds;
3332 float contentsScale = pageScale * deviceScaleFactor();
3333 // Scale by the page scale factor to compute the screen-relative bounds.
3334 scaledBounds.scale(contentsScale);
3335 // Round to integer boundaries.
3336 FloatRect alignedBounds = encloseRectToDevicePixels(LayoutRect(scaledBounds), deviceScaleFactor());
3338 // Convert back to layer coordinates.
3339 alignedBounds.scale(1 / contentsScale);
3341 alignmentOffset = baseRelativeBounds.location() - alignedBounds.location();
3342 position = m_position - alignmentOffset;
3344 // Now we have to compute a new anchor point which compensates for rounding.
3345 float anchorPointX = m_anchorPoint.x();
3346 float anchorPointY = m_anchorPoint.y();
3348 if (alignedBounds.width())
3349 anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width();
3351 if (alignedBounds.height())
3352 anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height();
3354 anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * contentsScale);
3357 void GraphicsLayerCA::noteSublayersChanged(ScheduleFlushOrNot scheduleFlush)
3359 noteLayerPropertyChanged(ChildrenChanged, scheduleFlush);
3360 propagateLayerChangeToReplicas();
3363 bool GraphicsLayerCA::canThrottleLayerFlush() const
3365 // Tile layers are currently plain CA layers, attached directly by TileController. They require immediate flush as they may contain garbage.
3366 return !(m_uncommittedChanges & TilesAdded);
3369 void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags, ScheduleFlushOrNot scheduleFlush)
3371 bool hadUncommittedChanges = !!m_uncommittedChanges;
3372 bool oldCanThrottleLayerFlush = canThrottleLayerFlush();
3374 m_uncommittedChanges |= flags;
3376 if (scheduleFlush == ScheduleFlush) {
3377 bool needsFlush = !hadUncommittedChanges || oldCanThrottleLayerFlush != canThrottleLayerFlush();
3379 client().notifyFlushRequired(this);
3383 double GraphicsLayerCA::backingStoreMemoryEstimate() const
3385 if (!drawsContent())
3388 // contentsLayer is given to us, so we don't really know anything about its contents.
3389 // FIXME: ignores layer clones.
3391 if (TiledBacking* tiledBacking = this->tiledBacking())
3392 return tiledBacking->retainedTileBackingStoreMemory();
3394 return 4.0 * size().width() * m_layer->contentsScale() * size().height() * m_layer->contentsScale();
3397 } // namespace WebCore