2 * Copyright (C) 2010-2017 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.
27 #include "GraphicsLayerCA.h"
31 #include "Animation.h"
32 #include "DisplayListRecorder.h"
33 #include "DisplayListReplayer.h"
34 #include "FloatConversion.h"
35 #include "FloatRect.h"
36 #include "GraphicsLayerFactory.h"
39 #include "PlatformCAFilters.h"
40 #include "PlatformCALayer.h"
41 #include "PlatformScreen.h"
42 #include "RotateTransformOperation.h"
43 #include "ScaleTransformOperation.h"
44 #include "TiledBacking.h"
45 #include "TransformState.h"
46 #include "TranslateTransformOperation.h"
47 #include <QuartzCore/CATransform3D.h>
49 #include <pal/spi/cf/CFUtilitiesSPI.h>
50 #include <wtf/MathExtras.h>
51 #include <wtf/NeverDestroyed.h>
52 #include <wtf/SetForScope.h>
53 #include <wtf/SystemTracing.h>
54 #include <wtf/text/TextStream.h>
55 #include <wtf/text/WTFString.h>
58 #include "SystemMemory.h"
59 #include "WebCoreThread.h"
63 #include "PlatformCAAnimationCocoa.h"
64 #include "PlatformCALayerCocoa.h"
68 #include "PlatformCAAnimationWin.h"
69 #include "PlatformCALayerWin.h"
73 // See https://msdn.microsoft.com/en-us/library/1wea5zwe.aspx
74 #pragma warning(disable: 4701)
79 // The threshold width or height above which a tiled layer will be used. This should be
80 // large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL
81 // texture size limit on all supported hardware.
83 static const int cMaxPixelDimension = 1280;
84 static const int cMaxPixelDimensionLowMemory = 1024;
85 static const int cMemoryLevelToUseSmallerPixelDimension = 35;
87 static const int cMaxPixelDimension = 2048;
90 // Derived empirically: <rdar://problem/13401861>
91 static const int cMaxLayerTreeDepth = 250;
93 // If we send a duration of 0 to CA, then it will use the default duration
94 // of 250ms. So send a very small value instead.
95 static const float cAnimationAlmostZeroDuration = 1e-3f;
97 static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType)
99 switch (transformType) {
100 case TransformOperation::SKEW_X:
101 case TransformOperation::SKEW_Y:
102 case TransformOperation::SKEW:
103 case TransformOperation::MATRIX:
104 case TransformOperation::ROTATE_3D:
105 case TransformOperation::MATRIX_3D:
106 case TransformOperation::PERSPECTIVE:
107 case TransformOperation::IDENTITY:
108 case TransformOperation::NONE:
115 static bool isTransformTypeFloatPoint3D(TransformOperation::OperationType transformType)
117 switch (transformType) {
118 case TransformOperation::SCALE:
119 case TransformOperation::SCALE_3D:
120 case TransformOperation::TRANSLATE:
121 case TransformOperation::TRANSLATE_3D:
128 static bool isTransformTypeNumber(TransformOperation::OperationType transformType)
130 return !isTransformTypeTransformationMatrix(transformType) && !isTransformTypeFloatPoint3D(transformType);
133 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const FloatSize& size, float& value)
135 switch (transformType) {
136 case TransformOperation::ROTATE:
137 case TransformOperation::ROTATE_X:
138 case TransformOperation::ROTATE_Y:
139 value = transformOp ? narrowPrecisionToFloat(deg2rad(downcast<RotateTransformOperation>(*transformOp).angle())) : 0;
141 case TransformOperation::SCALE_X:
142 value = transformOp ? narrowPrecisionToFloat(downcast<ScaleTransformOperation>(*transformOp).x()) : 1;
144 case TransformOperation::SCALE_Y:
145 value = transformOp ? narrowPrecisionToFloat(downcast<ScaleTransformOperation>(*transformOp).y()) : 1;
147 case TransformOperation::SCALE_Z:
148 value = transformOp ? narrowPrecisionToFloat(downcast<ScaleTransformOperation>(*transformOp).z()) : 1;
150 case TransformOperation::TRANSLATE_X:
151 value = transformOp ? narrowPrecisionToFloat(downcast<TranslateTransformOperation>(*transformOp).x(size)) : 0;
153 case TransformOperation::TRANSLATE_Y:
154 value = transformOp ? narrowPrecisionToFloat(downcast<TranslateTransformOperation>(*transformOp).y(size)) : 0;
156 case TransformOperation::TRANSLATE_Z:
157 value = transformOp ? narrowPrecisionToFloat(downcast<TranslateTransformOperation>(*transformOp).z(size)) : 0;
164 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const FloatSize& size, FloatPoint3D& value)
166 switch (transformType) {
167 case TransformOperation::SCALE:
168 case TransformOperation::SCALE_3D: {
169 const auto* scaleTransformOp = downcast<ScaleTransformOperation>(transformOp);
170 value.setX(scaleTransformOp ? narrowPrecisionToFloat(scaleTransformOp->x()) : 1);
171 value.setY(scaleTransformOp ? narrowPrecisionToFloat(scaleTransformOp->y()) : 1);
172 value.setZ(scaleTransformOp ? narrowPrecisionToFloat(scaleTransformOp->z()) : 1);
175 case TransformOperation::TRANSLATE:
176 case TransformOperation::TRANSLATE_3D: {
177 const auto* translateTransformOp = downcast<TranslateTransformOperation>(transformOp);
178 value.setX(translateTransformOp ? narrowPrecisionToFloat(translateTransformOp->x(size)) : 0);
179 value.setY(translateTransformOp ? narrowPrecisionToFloat(translateTransformOp->y(size)) : 0);
180 value.setZ(translateTransformOp ? narrowPrecisionToFloat(translateTransformOp->z(size)) : 0);
188 static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const FloatSize& size, TransformationMatrix& value)
190 switch (transformType) {
191 case TransformOperation::SKEW_X:
192 case TransformOperation::SKEW_Y:
193 case TransformOperation::SKEW:
194 case TransformOperation::MATRIX:
195 case TransformOperation::ROTATE_3D:
196 case TransformOperation::MATRIX_3D:
197 case TransformOperation::PERSPECTIVE:
198 case TransformOperation::IDENTITY:
199 case TransformOperation::NONE:
201 transformOp->apply(value, size);
203 value.makeIdentity();
210 static PlatformCAAnimation::ValueFunctionType getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType)
212 // Use literal strings to avoid link-time dependency on those symbols.
213 switch (transformType) {
214 case TransformOperation::ROTATE_X:
215 return PlatformCAAnimation::RotateX;
216 case TransformOperation::ROTATE_Y:
217 return PlatformCAAnimation::RotateY;
218 case TransformOperation::ROTATE:
219 return PlatformCAAnimation::RotateZ;
220 case TransformOperation::SCALE_X:
221 return PlatformCAAnimation::ScaleX;
222 case TransformOperation::SCALE_Y:
223 return PlatformCAAnimation::ScaleY;
224 case TransformOperation::SCALE_Z:
225 return PlatformCAAnimation::ScaleZ;
226 case TransformOperation::TRANSLATE_X:
227 return PlatformCAAnimation::TranslateX;
228 case TransformOperation::TRANSLATE_Y:
229 return PlatformCAAnimation::TranslateY;
230 case TransformOperation::TRANSLATE_Z:
231 return PlatformCAAnimation::TranslateZ;
232 case TransformOperation::SCALE:
233 case TransformOperation::SCALE_3D:
234 return PlatformCAAnimation::Scale;
235 case TransformOperation::TRANSLATE:
236 case TransformOperation::TRANSLATE_3D:
237 return PlatformCAAnimation::Translate;
239 return PlatformCAAnimation::NoValueFunction;
243 static ASCIILiteral propertyIdToString(AnimatedPropertyID property)
246 case AnimatedPropertyTransform:
247 return ASCIILiteral("transform");
248 case AnimatedPropertyOpacity:
249 return ASCIILiteral("opacity");
250 case AnimatedPropertyBackgroundColor:
251 return ASCIILiteral("backgroundColor");
252 case AnimatedPropertyFilter:
253 return ASCIILiteral("filters");
254 #if ENABLE(FILTERS_LEVEL_2)
255 case AnimatedPropertyWebkitBackdropFilter:
256 return ASCIILiteral("backdropFilters");
258 case AnimatedPropertyInvalid:
259 ASSERT_NOT_REACHED();
261 ASSERT_NOT_REACHED();
262 return ASCIILiteral("");
265 static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index, int subIndex)
267 return animationName + '_' + String::number(property) + '_' + String::number(index) + '_' + String::number(subIndex);
270 static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim)
272 if (is<StepsTimingFunction>(anim->timingFunction()))
275 for (unsigned i = 0; i < valueList.size(); ++i) {
276 if (const TimingFunction* timingFunction = valueList.at(i).timingFunction()) {
277 if (is<StepsTimingFunction>(timingFunction))
285 static bool animationHasFramesTimingFunction(const KeyframeValueList& valueList, const Animation* anim)
287 if (is<FramesTimingFunction>(anim->timingFunction()))
290 for (unsigned i = 0; i < valueList.size(); ++i) {
291 if (const TimingFunction* timingFunction = valueList.at(i).timingFunction()) {
292 if (is<FramesTimingFunction>(timingFunction))
300 static inline bool supportsAcceleratedFilterAnimations()
309 bool GraphicsLayer::supportsLayerType(Type type)
313 case Type::PageTiledBacking:
314 case Type::Scrolling:
318 // FIXME: we can use shaper layers on Windows when PlatformCALayerCocoa::setShapePath() etc are implemented.
324 ASSERT_NOT_REACHED();
328 bool GraphicsLayer::supportsBackgroundColorContent()
333 bool GraphicsLayer::supportsSubpixelAntialiasedLayerText()
342 std::unique_ptr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client, Type layerType)
344 std::unique_ptr<GraphicsLayer> graphicsLayer;
346 graphicsLayer = std::make_unique<GraphicsLayerCA>(layerType, client);
348 graphicsLayer = factory->createGraphicsLayer(layerType, client);
350 graphicsLayer->initialize(layerType);
352 return graphicsLayer;
355 bool GraphicsLayerCA::filtersCanBeComposited(const FilterOperations& filters)
358 return PlatformCALayerCocoa::filtersCanBeComposited(filters);
360 return PlatformCALayerWin::filtersCanBeComposited(filters);
364 Ref<PlatformCALayer> GraphicsLayerCA::createPlatformCALayer(PlatformCALayer::LayerType layerType, PlatformCALayerClient* owner)
367 auto result = PlatformCALayerCocoa::create(layerType, owner);
369 if (result->canHaveBackingStore())
370 result->setWantsDeepColorBackingStore(screenSupportsExtendedColor());
374 return PlatformCALayerWin::create(layerType, owner);
378 Ref<PlatformCALayer> GraphicsLayerCA::createPlatformCALayer(PlatformLayer* platformLayer, PlatformCALayerClient* owner)
381 return PlatformCALayerCocoa::create(platformLayer, owner);
383 return PlatformCALayerWin::create(platformLayer, owner);
387 Ref<PlatformCAAnimation> GraphicsLayerCA::createPlatformCAAnimation(PlatformCAAnimation::AnimationType type, const String& keyPath)
390 return PlatformCAAnimationCocoa::create(type, keyPath);
392 return PlatformCAAnimationWin::create(type, keyPath);
396 typedef HashMap<const GraphicsLayerCA*, std::pair<FloatRect, std::unique_ptr<DisplayList::DisplayList>>> LayerDisplayListHashMap;
398 static LayerDisplayListHashMap& layerDisplayListMap()
400 static NeverDestroyed<LayerDisplayListHashMap> sharedHashMap;
401 return sharedHashMap;
404 GraphicsLayerCA::GraphicsLayerCA(Type layerType, GraphicsLayerClient& client)
405 : GraphicsLayer(layerType, client)
409 void GraphicsLayerCA::initialize(Type layerType)
411 PlatformCALayer::LayerType platformLayerType;
414 platformLayerType = PlatformCALayer::LayerType::LayerTypeWebLayer;
416 case Type::PageTiledBacking:
417 platformLayerType = PlatformCALayer::LayerType::LayerTypePageTiledBackingLayer;
419 case Type::Scrolling:
420 platformLayerType = PlatformCALayer::LayerType::LayerTypeScrollingLayer;
423 platformLayerType = PlatformCALayer::LayerType::LayerTypeShapeLayer;
426 m_layer = createPlatformCALayer(platformLayerType, this);
427 noteLayerPropertyChanged(ContentsScaleChanged);
430 GraphicsLayerCA::~GraphicsLayerCA()
432 if (UNLIKELY(isTrackingDisplayListReplay()))
433 layerDisplayListMap().remove(this);
435 // Do cleanup while we can still safely call methods on the derived class.
439 void GraphicsLayerCA::willBeDestroyed()
441 // We release our references to the PlatformCALayers here, but do not actively unparent them,
442 // since that will cause a commit and break our batched commit model. The layers will
443 // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers.
445 // Clean up the layer.
447 m_layer->setOwner(nullptr);
450 m_contentsLayer->setOwner(nullptr);
452 if (m_contentsClippingLayer)
453 m_contentsClippingLayer->setOwner(nullptr);
455 if (m_contentsShapeMaskLayer)
456 m_contentsShapeMaskLayer->setOwner(nullptr);
458 if (m_shapeMaskLayer)
459 m_shapeMaskLayer->setOwner(nullptr);
461 if (m_structuralLayer)
462 m_structuralLayer->setOwner(nullptr);
465 m_backdropLayer->setOwner(nullptr);
467 if (m_backdropClippingLayer)
468 m_backdropClippingLayer->setOwner(nullptr);
472 GraphicsLayer::willBeDestroyed();
475 void GraphicsLayerCA::setName(const String& name)
477 #if ENABLE(TREE_DEBUGGING)
478 String caLayerDescription;
480 if (!m_layer->isPlatformCALayerRemote())
481 caLayerDescription = String::format("CALayer(%p) ", m_layer->platformLayer());
483 GraphicsLayer::setName(caLayerDescription + String::format("GraphicsLayer(%p, %llu) ", this, primaryLayerID()) + name);
485 GraphicsLayer::setName(name);
488 noteLayerPropertyChanged(NameChanged);
491 GraphicsLayer::PlatformLayerID GraphicsLayerCA::primaryLayerID() const
493 return primaryLayer()->layerID();
496 PlatformLayer* GraphicsLayerCA::platformLayer() const
498 return primaryLayer()->platformLayer();
501 bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children)
503 bool childrenChanged = GraphicsLayer::setChildren(children);
505 noteSublayersChanged();
507 return childrenChanged;
510 void GraphicsLayerCA::addChild(GraphicsLayer* childLayer)
512 GraphicsLayer::addChild(childLayer);
513 noteSublayersChanged();
516 void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index)
518 GraphicsLayer::addChildAtIndex(childLayer, index);
519 noteSublayersChanged();
522 void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
524 GraphicsLayer::addChildBelow(childLayer, sibling);
525 noteSublayersChanged();
528 void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
530 GraphicsLayer::addChildAbove(childLayer, sibling);
531 noteSublayersChanged();
534 bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
536 if (GraphicsLayer::replaceChild(oldChild, newChild)) {
537 noteSublayersChanged();
543 void GraphicsLayerCA::removeFromParent()
546 downcast<GraphicsLayerCA>(*m_parent).noteSublayersChanged();
547 GraphicsLayer::removeFromParent();
550 void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer)
552 if (layer == m_maskLayer)
555 GraphicsLayer::setMaskLayer(layer);
556 noteLayerPropertyChanged(MaskLayerChanged);
558 propagateLayerChangeToReplicas();
560 if (m_replicatedLayer)
561 downcast<GraphicsLayerCA>(*m_replicatedLayer).propagateLayerChangeToReplicas();
564 void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer)
566 if (layer == m_replicatedLayer)
569 GraphicsLayer::setReplicatedLayer(layer);
570 noteLayerPropertyChanged(ReplicatedLayerChanged);
573 void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer)
575 if (layer == m_replicaLayer)
578 GraphicsLayer::setReplicatedByLayer(layer);
579 noteSublayersChanged();
580 noteLayerPropertyChanged(ReplicatedLayerChanged);
583 void GraphicsLayerCA::setPosition(const FloatPoint& point)
585 if (point == m_position)
588 GraphicsLayer::setPosition(point);
589 noteLayerPropertyChanged(GeometryChanged);
592 void GraphicsLayerCA::syncPosition(const FloatPoint& point)
594 if (point == m_position)
597 GraphicsLayer::syncPosition(point);
598 // Ensure future flushes will recompute the coverage rect and update tiling.
599 noteLayerPropertyChanged(NeedsComputeVisibleAndCoverageRect, DontScheduleFlush);
602 void GraphicsLayerCA::setApproximatePosition(const FloatPoint& point)
604 if (point == m_approximatePosition)
607 GraphicsLayer::setApproximatePosition(point);
608 // Ensure future flushes will recompute the coverage rect and update tiling.
609 noteLayerPropertyChanged(NeedsComputeVisibleAndCoverageRect, DontScheduleFlush);
612 void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point)
614 if (point == m_anchorPoint)
617 GraphicsLayer::setAnchorPoint(point);
618 noteLayerPropertyChanged(GeometryChanged);
621 void GraphicsLayerCA::setSize(const FloatSize& size)
626 GraphicsLayer::setSize(size);
627 noteLayerPropertyChanged(GeometryChanged);
630 void GraphicsLayerCA::setBoundsOrigin(const FloatPoint& origin)
632 if (origin == m_boundsOrigin)
635 GraphicsLayer::setBoundsOrigin(origin);
636 noteLayerPropertyChanged(GeometryChanged);
639 void GraphicsLayerCA::syncBoundsOrigin(const FloatPoint& origin)
641 if (origin == m_boundsOrigin)
644 GraphicsLayer::syncBoundsOrigin(origin);
645 noteLayerPropertyChanged(NeedsComputeVisibleAndCoverageRect, DontScheduleFlush);
648 void GraphicsLayerCA::setTransform(const TransformationMatrix& t)
650 if (t == m_transform)
653 GraphicsLayer::setTransform(t);
654 noteLayerPropertyChanged(TransformChanged);
657 void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t)
659 if (t == m_childrenTransform)
662 GraphicsLayer::setChildrenTransform(t);
663 noteLayerPropertyChanged(ChildrenTransformChanged);
666 void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
668 RefPtr<PlatformCAAnimation> anim = fromLayer->animationForKey(animationIdentifier);
674 fromLayer->removeAnimationForKey(animationIdentifier);
675 toLayer->addAnimationForKey(animationIdentifier, *anim);
679 toLayer->addAnimationForKey(animationIdentifier, *anim);
684 void GraphicsLayerCA::moveOrCopyAnimations(MoveOrCopy operation, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
686 // Look for running animations affecting this property.
687 AnimationsMap::const_iterator end = m_runningAnimations.end();
688 for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
689 const Vector<LayerPropertyAnimation>& propertyAnimations = it->value;
690 size_t numAnimations = propertyAnimations.size();
691 for (size_t i = 0; i < numAnimations; ++i) {
692 const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
694 if (currAnimation.m_property == AnimatedPropertyTransform
695 || currAnimation.m_property == AnimatedPropertyOpacity
696 || currAnimation.m_property == AnimatedPropertyBackgroundColor
697 || currAnimation.m_property == AnimatedPropertyFilter)
698 moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index, currAnimation.m_subIndex), fromLayer, toLayer);
703 void GraphicsLayerCA::setPreserves3D(bool preserves3D)
705 if (preserves3D == m_preserves3D)
708 GraphicsLayer::setPreserves3D(preserves3D);
709 noteLayerPropertyChanged(Preserves3DChanged);
712 void GraphicsLayerCA::setMasksToBounds(bool masksToBounds)
714 if (masksToBounds == m_masksToBounds)
717 GraphicsLayer::setMasksToBounds(masksToBounds);
718 noteLayerPropertyChanged(MasksToBoundsChanged | DebugIndicatorsChanged);
721 void GraphicsLayerCA::setDrawsContent(bool drawsContent)
723 if (drawsContent == m_drawsContent)
726 GraphicsLayer::setDrawsContent(drawsContent);
727 noteLayerPropertyChanged(DrawsContentChanged | DebugIndicatorsChanged);
730 void GraphicsLayerCA::setContentsVisible(bool contentsVisible)
732 if (contentsVisible == m_contentsVisible)
735 GraphicsLayer::setContentsVisible(contentsVisible);
736 noteLayerPropertyChanged(ContentsVisibilityChanged);
737 // Visibility affects whether the contentsLayer is parented.
739 noteSublayersChanged();
742 void GraphicsLayerCA::setUserInteractionEnabled(bool userInteractionEnabled)
744 if (userInteractionEnabled == m_userInteractionEnabled)
747 GraphicsLayer::setUserInteractionEnabled(userInteractionEnabled);
748 noteLayerPropertyChanged(UserInteractionEnabledChanged);
751 void GraphicsLayerCA::setAcceleratesDrawing(bool acceleratesDrawing)
753 if (acceleratesDrawing == m_acceleratesDrawing)
756 GraphicsLayer::setAcceleratesDrawing(acceleratesDrawing);
757 noteLayerPropertyChanged(AcceleratesDrawingChanged);
760 void GraphicsLayerCA::setUsesDisplayListDrawing(bool usesDisplayListDrawing)
762 if (usesDisplayListDrawing == m_usesDisplayListDrawing)
766 GraphicsLayer::setUsesDisplayListDrawing(usesDisplayListDrawing);
769 void GraphicsLayerCA::setBackgroundColor(const Color& color)
771 if (m_backgroundColor == color)
774 GraphicsLayer::setBackgroundColor(color);
775 noteLayerPropertyChanged(BackgroundColorChanged);
778 void GraphicsLayerCA::setContentsOpaque(bool opaque)
780 if (m_contentsOpaque == opaque)
783 GraphicsLayer::setContentsOpaque(opaque);
784 noteLayerPropertyChanged(ContentsOpaqueChanged);
787 void GraphicsLayerCA::setSupportsSubpixelAntialiasedText(bool supportsSubpixelAntialiasedText)
789 if (m_supportsSubpixelAntialiasedText == supportsSubpixelAntialiasedText)
792 GraphicsLayer::setSupportsSubpixelAntialiasedText(supportsSubpixelAntialiasedText);
793 noteLayerPropertyChanged(SupportsSubpixelAntialiasedTextChanged);
796 void GraphicsLayerCA::setBackfaceVisibility(bool visible)
798 if (m_backfaceVisibility == visible)
801 GraphicsLayer::setBackfaceVisibility(visible);
802 noteLayerPropertyChanged(BackfaceVisibilityChanged);
805 void GraphicsLayerCA::setOpacity(float opacity)
807 float clampedOpacity = std::max(0.0f, std::min(opacity, 1.0f));
809 if (clampedOpacity == m_opacity)
812 GraphicsLayer::setOpacity(clampedOpacity);
813 noteLayerPropertyChanged(OpacityChanged);
816 bool GraphicsLayerCA::setFilters(const FilterOperations& filterOperations)
818 bool canCompositeFilters = filtersCanBeComposited(filterOperations);
820 if (m_filters == filterOperations)
821 return canCompositeFilters;
823 // Filters cause flattening, so we should never have filters on a layer with preserves3D().
824 ASSERT(!filterOperations.size() || !preserves3D());
826 if (canCompositeFilters) {
827 GraphicsLayer::setFilters(filterOperations);
828 noteLayerPropertyChanged(FiltersChanged);
829 } else if (filters().size()) {
830 // In this case filters are rendered in software, so we need to remove any
831 // previously attached hardware filters.
833 noteLayerPropertyChanged(FiltersChanged);
835 return canCompositeFilters;
838 bool GraphicsLayerCA::setBackdropFilters(const FilterOperations& filterOperations)
840 bool canCompositeFilters = filtersCanBeComposited(filterOperations);
842 if (m_backdropFilters == filterOperations)
843 return canCompositeFilters;
845 // Filters cause flattening, so we should never have filters on a layer with preserves3D().
846 ASSERT(!filterOperations.size() || !preserves3D());
848 if (canCompositeFilters)
849 GraphicsLayer::setBackdropFilters(filterOperations);
851 // FIXME: This would clear the backdrop filters if we had a software implementation.
852 clearBackdropFilters();
855 noteLayerPropertyChanged(BackdropFiltersChanged | DebugIndicatorsChanged);
856 return canCompositeFilters;
859 void GraphicsLayerCA::setBackdropFiltersRect(const FloatRoundedRect& backdropFiltersRect)
861 if (backdropFiltersRect == m_backdropFiltersRect)
864 GraphicsLayer::setBackdropFiltersRect(backdropFiltersRect);
865 noteLayerPropertyChanged(BackdropFiltersRectChanged);
868 #if ENABLE(CSS_COMPOSITING)
869 void GraphicsLayerCA::setBlendMode(BlendMode blendMode)
871 if (GraphicsLayer::blendMode() == blendMode)
874 GraphicsLayer::setBlendMode(blendMode);
875 noteLayerPropertyChanged(BlendModeChanged);
879 bool GraphicsLayerCA::backingStoreAttached() const
881 return m_layer->backingStoreAttached();
884 void GraphicsLayerCA::setNeedsDisplay()
889 if (!backingStoreAttached())
892 m_needsFullRepaint = true;
893 m_dirtyRects.clear();
894 noteLayerPropertyChanged(DirtyRectsChanged);
895 addRepaintRect(FloatRect(FloatPoint(), m_size));
898 void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& r, ShouldClipToLayer shouldClip)
903 if (m_needsFullRepaint)
907 if (shouldClip == ClipToLayer) {
908 FloatRect layerBounds(FloatPoint(), m_size);
909 rect.intersect(layerBounds);
915 const size_t maxDirtyRects = 32;
917 for (size_t i = 0; i < m_dirtyRects.size(); ++i) {
918 if (m_dirtyRects[i].contains(rect))
922 if (m_dirtyRects.size() < maxDirtyRects)
923 m_dirtyRects.append(rect);
925 m_dirtyRects[0].unite(rect);
927 noteLayerPropertyChanged(DirtyRectsChanged);
929 addRepaintRect(rect);
932 void GraphicsLayerCA::setContentsNeedsDisplay()
934 noteLayerPropertyChanged(ContentsNeedsDisplay);
937 void GraphicsLayerCA::setContentsRect(const FloatRect& rect)
939 if (rect == m_contentsRect)
942 GraphicsLayer::setContentsRect(rect);
943 noteLayerPropertyChanged(ContentsRectsChanged);
946 void GraphicsLayerCA::setContentsClippingRect(const FloatRoundedRect& rect)
948 if (rect == m_contentsClippingRect)
951 GraphicsLayer::setContentsClippingRect(rect);
952 noteLayerPropertyChanged(ContentsRectsChanged);
955 bool GraphicsLayerCA::setMasksToBoundsRect(const FloatRoundedRect& roundedRect)
957 if (roundedRect == m_masksToBoundsRect)
960 GraphicsLayer::setMasksToBoundsRect(roundedRect);
961 noteLayerPropertyChanged(MasksToBoundsRectChanged);
965 void GraphicsLayerCA::setShapeLayerPath(const Path& path)
967 // FIXME: need to check for path equality. No bool Path::operator==(const Path&)!.
968 GraphicsLayer::setShapeLayerPath(path);
969 noteLayerPropertyChanged(ShapeChanged);
972 void GraphicsLayerCA::setShapeLayerWindRule(WindRule windRule)
974 if (windRule == m_shapeLayerWindRule)
977 GraphicsLayer::setShapeLayerWindRule(windRule);
978 noteLayerPropertyChanged(WindRuleChanged);
981 bool GraphicsLayerCA::shouldRepaintOnSizeChange() const
983 return drawsContent() && !tiledBacking();
986 bool GraphicsLayerCA::animationCanBeAccelerated(const KeyframeValueList& valueList, const Animation* anim) const
988 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
991 if (animationHasStepsTimingFunction(valueList, anim))
994 if (animationHasFramesTimingFunction(valueList, anim))
997 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
998 // If there is a trigger that depends on the scroll position, we cannot accelerate the animation.
999 if (is<ScrollAnimationTrigger>(anim->trigger())) {
1000 auto& scrollTrigger = downcast<ScrollAnimationTrigger>(*anim->trigger());
1001 if (scrollTrigger.hasEndValue())
1009 void GraphicsLayerCA::addProcessingActionForAnimation(const String& animationName, AnimationProcessingAction processingAction)
1011 auto& processingActions = m_animationsToProcess.ensure(animationName, [] {
1012 return Vector<AnimationProcessingAction> { };
1015 if (!processingActions.isEmpty() && processingActions.last().action == Remove)
1018 processingActions.append(processingAction);
1021 bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& animationName, double timeOffset)
1023 LOG(Animations, "GraphicsLayerCA %p addAnimation %s (can be accelerated %d)", this, animationName.utf8().data(), animationCanBeAccelerated(valueList, anim));
1025 ASSERT(!animationName.isEmpty());
1027 if (!animationCanBeAccelerated(valueList, anim))
1030 bool createdAnimations = false;
1031 if (valueList.property() == AnimatedPropertyTransform)
1032 createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, Seconds { timeOffset }, boxSize);
1033 else if (valueList.property() == AnimatedPropertyFilter) {
1034 if (supportsAcceleratedFilterAnimations())
1035 createdAnimations = createFilterAnimationsFromKeyframes(valueList, anim, animationName, Seconds { timeOffset });
1037 #if ENABLE(FILTERS_LEVEL_2)
1038 else if (valueList.property() == AnimatedPropertyWebkitBackdropFilter) {
1039 if (supportsAcceleratedFilterAnimations())
1040 createdAnimations = createFilterAnimationsFromKeyframes(valueList, anim, animationName, Seconds { timeOffset });
1044 createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, Seconds { timeOffset });
1046 if (createdAnimations)
1047 noteLayerPropertyChanged(AnimationChanged);
1049 return createdAnimations;
1052 void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset)
1054 LOG(Animations, "GraphicsLayerCA %p pauseAnimation %s (running %d)", this, animationName.utf8().data(), animationIsRunning(animationName));
1056 // Call add since if there is already a Remove in there, we don't want to overwrite it with a Pause.
1057 addProcessingActionForAnimation(animationName, AnimationProcessingAction { Pause, Seconds { timeOffset } });
1059 noteLayerPropertyChanged(AnimationChanged);
1062 void GraphicsLayerCA::seekAnimation(const String& animationName, double timeOffset)
1064 LOG(Animations, "GraphicsLayerCA %p seekAnimation %s (running %d)", this, animationName.utf8().data(), animationIsRunning(animationName));
1066 // Call add since if there is already a Remove in there, we don't want to overwrite it with a Pause.
1067 addProcessingActionForAnimation(animationName, AnimationProcessingAction { Seek, Seconds { timeOffset } });
1069 noteLayerPropertyChanged(AnimationChanged);
1072 void GraphicsLayerCA::removeAnimation(const String& animationName)
1074 LOG(Animations, "GraphicsLayerCA %p removeAnimation %s (running %d)", this, animationName.utf8().data(), animationIsRunning(animationName));
1076 if (!animationIsRunning(animationName))
1079 addProcessingActionForAnimation(animationName, AnimationProcessingAction(Remove));
1080 noteLayerPropertyChanged(AnimationChanged);
1083 void GraphicsLayerCA::platformCALayerAnimationStarted(const String& animationKey, MonotonicTime startTime)
1085 LOG(Animations, "GraphicsLayerCA %p platformCALayerAnimationStarted %s at %f", this, animationKey.utf8().data(), startTime.secondsSinceEpoch().seconds());
1086 client().notifyAnimationStarted(this, animationKey, startTime);
1089 void GraphicsLayerCA::platformCALayerAnimationEnded(const String& animationKey)
1091 LOG(Animations, "GraphicsLayerCA %p platformCALayerAnimationEnded %s", this, animationKey.utf8().data());
1092 client().notifyAnimationEnded(this, animationKey);
1095 void GraphicsLayerCA::setContentsToSolidColor(const Color& color)
1097 if (color == m_contentsSolidColor)
1100 m_contentsSolidColor = color;
1102 bool contentsLayerChanged = false;
1104 if (m_contentsSolidColor.isVisible()) {
1105 if (!m_contentsLayer || m_contentsLayerPurpose != ContentsLayerForBackgroundColor) {
1106 m_contentsLayerPurpose = ContentsLayerForBackgroundColor;
1107 m_contentsLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
1108 #if ENABLE(TREE_DEBUGGING)
1109 m_contentsLayer->setName(String::format("contents color %llu", m_contentsLayer->layerID()));
1111 m_contentsLayer->setName("contents color");
1113 contentsLayerChanged = true;
1116 contentsLayerChanged = m_contentsLayer;
1117 m_contentsLayerPurpose = NoContentsLayer;
1118 m_contentsLayer = nullptr;
1121 if (contentsLayerChanged)
1122 noteSublayersChanged();
1124 noteLayerPropertyChanged(ContentsColorLayerChanged);
1127 void GraphicsLayerCA::setContentsToImage(Image* image)
1130 auto newImage = image->nativeImageForCurrentFrame();
1134 // FIXME: probably don't need m_uncorrectedContentsImage at all now.
1135 if (m_uncorrectedContentsImage == newImage)
1138 m_uncorrectedContentsImage = WTFMove(newImage);
1139 m_pendingContentsImage = m_uncorrectedContentsImage;
1141 m_contentsLayerPurpose = ContentsLayerForImage;
1142 if (!m_contentsLayer)
1143 noteSublayersChanged();
1145 m_uncorrectedContentsImage = nullptr;
1146 m_pendingContentsImage = nullptr;
1147 m_contentsLayerPurpose = NoContentsLayer;
1148 if (m_contentsLayer)
1149 noteSublayersChanged();
1152 noteLayerPropertyChanged(ContentsImageChanged);
1155 void GraphicsLayerCA::setContentsToPlatformLayer(PlatformLayer* platformLayer, ContentsLayerPurpose purpose)
1157 if (m_contentsLayer && platformLayer == m_contentsLayer->platformLayer())
1160 if (m_contentsClippingLayer && m_contentsLayer)
1161 m_contentsLayer->removeFromSuperlayer();
1163 // FIXME: The passed in layer might be a raw layer or an externally created
1164 // PlatformCALayer. To determine this we attempt to get the
1165 // PlatformCALayer pointer. If this returns a null pointer we assume it's
1166 // raw. This test might be invalid if the raw layer is, for instance, the
1167 // PlatformCALayer is using a user data pointer in the raw layer, and
1168 // the creator of the raw layer is using it for some other purpose.
1169 // For now we don't support such a case.
1170 PlatformCALayer* platformCALayer = PlatformCALayer::platformCALayer(platformLayer);
1171 m_contentsLayer = platformLayer ? (platformCALayer ? platformCALayer : createPlatformCALayer(platformLayer, this).ptr()) : nullptr;
1172 m_contentsLayerPurpose = platformLayer ? purpose : NoContentsLayer;
1174 if (m_contentsClippingLayer && m_contentsLayer)
1175 m_contentsClippingLayer->appendSublayer(*m_contentsLayer);
1177 noteSublayersChanged();
1178 noteLayerPropertyChanged(ContentsPlatformLayerChanged);
1182 PlatformLayer* GraphicsLayerCA::contentsLayerForMedia() const
1184 return m_contentsLayerPurpose == ContentsLayerForMedia ? m_contentsLayer->platformLayer() : nullptr;
1188 void GraphicsLayerCA::layerDidDisplay(PlatformCALayer* layer)
1190 LayerMap* layerCloneMap;
1192 if (layer == m_layer)
1193 layerCloneMap = m_layerClones.get();
1194 else if (layer == m_contentsLayer)
1195 layerCloneMap = m_contentsLayerClones.get();
1199 if (layerCloneMap) {
1200 LayerMap::const_iterator end = layerCloneMap->end();
1201 for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
1202 PlatformCALayer* currClone = it->value.get();
1206 currClone->copyContentsFromLayer(layer);
1211 FloatPoint GraphicsLayerCA::computePositionRelativeToBase(float& pageScale) const
1216 for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) {
1217 if (currLayer->appliesPageScale()) {
1218 pageScale = currLayer->pageScaleFactor();
1222 offset += currLayer->position();
1225 return FloatPoint();
1228 void GraphicsLayerCA::flushCompositingState(const FloatRect& visibleRect)
1230 TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(visibleRect));
1231 FloatQuad coverageQuad(visibleRect);
1232 state.setSecondaryQuad(&coverageQuad);
1234 CommitState commitState;
1235 commitState.ancestorHadChanges = visibleRect != m_previousCommittedVisibleRect;
1236 m_previousCommittedVisibleRect = visibleRect;
1239 // In WK1, UIKit may be changing layer bounds behind our back in overflow-scroll layers, so disable the optimization.
1240 // See the similar test in computeVisibleAndCoverageRect().
1241 if (m_layer->isPlatformCALayerCocoa())
1242 commitState.ancestorHadChanges = true;
1245 recursiveCommitChanges(commitState, state);
1248 void GraphicsLayerCA::flushCompositingStateForThisLayerOnly()
1250 float pageScaleFactor;
1251 bool hadChanges = m_uncommittedChanges;
1253 CommitState commitState;
1255 FloatPoint offset = computePositionRelativeToBase(pageScaleFactor);
1256 commitLayerChangesBeforeSublayers(commitState, pageScaleFactor, offset);
1257 commitLayerChangesAfterSublayers(commitState);
1260 client().didCommitChangesForLayer(this);
1263 static inline bool accumulatesTransform(const GraphicsLayerCA& layer)
1265 return !layer.masksToBounds() && (layer.preserves3D() || (layer.parent() && layer.parent()->preserves3D()));
1268 bool GraphicsLayerCA::recursiveVisibleRectChangeRequiresFlush(const CommitState& commitState, const TransformState& state) const
1270 TransformState localState = state;
1271 CommitState childCommitState = commitState;
1273 // This may be called at times when layout has not been updated, so we want to avoid calling out to the client
1274 // for animating transforms.
1275 VisibleAndCoverageRects rects = computeVisibleAndCoverageRect(localState, accumulatesTransform(*this), 0);
1276 adjustCoverageRect(rects, m_visibleRect);
1278 auto bounds = FloatRect(m_boundsOrigin, size());
1280 bool isViewportConstrained = m_isViewportConstrained || commitState.ancestorIsViewportConstrained;
1281 bool intersectsCoverageRect = isViewportConstrained || rects.coverageRect.intersects(bounds);
1282 if (intersectsCoverageRect != m_intersectsCoverageRect)
1285 if (rects.coverageRect != m_coverageRect) {
1286 if (TiledBacking* tiledBacking = this->tiledBacking()) {
1287 if (tiledBacking->tilesWouldChangeForCoverageRect(rects.coverageRect))
1292 childCommitState.ancestorIsViewportConstrained |= m_isViewportConstrained;
1295 GraphicsLayerCA& maskLayerCA = downcast<GraphicsLayerCA>(*m_maskLayer);
1296 if (maskLayerCA.recursiveVisibleRectChangeRequiresFlush(childCommitState, localState))
1300 const Vector<GraphicsLayer*>& childLayers = children();
1301 size_t numChildren = childLayers.size();
1303 for (size_t i = 0; i < numChildren; ++i) {
1304 GraphicsLayerCA& currentChild = downcast<GraphicsLayerCA>(*childLayers[i]);
1305 if (currentChild.recursiveVisibleRectChangeRequiresFlush(childCommitState, localState))
1310 if (downcast<GraphicsLayerCA>(*m_replicaLayer).recursiveVisibleRectChangeRequiresFlush(childCommitState, localState))
1316 bool GraphicsLayerCA::visibleRectChangeRequiresFlush(const FloatRect& clipRect) const
1318 TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(clipRect));
1319 CommitState commitState;
1320 return recursiveVisibleRectChangeRequiresFlush(commitState, state);
1323 TiledBacking* GraphicsLayerCA::tiledBacking() const
1325 return m_layer->tiledBacking();
1328 TransformationMatrix GraphicsLayerCA::layerTransform(const FloatPoint& position, const TransformationMatrix* customTransform) const
1330 TransformationMatrix transform;
1331 transform.translate(position.x(), position.y());
1333 TransformationMatrix currentTransform = customTransform ? *customTransform : m_transform;
1335 if (!currentTransform.isIdentity()) {
1336 FloatPoint3D absoluteAnchorPoint(anchorPoint());
1337 absoluteAnchorPoint.scale(size().width(), size().height(), 1);
1338 transform.translate3d(absoluteAnchorPoint.x(), absoluteAnchorPoint.y(), absoluteAnchorPoint.z());
1339 transform.multiply(currentTransform);
1340 transform.translate3d(-absoluteAnchorPoint.x(), -absoluteAnchorPoint.y(), -absoluteAnchorPoint.z());
1343 if (GraphicsLayer* parentLayer = parent()) {
1344 if (!parentLayer->childrenTransform().isIdentity()) {
1345 FloatPoint3D parentAnchorPoint(parentLayer->anchorPoint());
1346 parentAnchorPoint.scale(parentLayer->size().width(), parentLayer->size().height(), 1);
1348 transform.translateRight3d(-parentAnchorPoint.x(), -parentAnchorPoint.y(), -parentAnchorPoint.z());
1349 transform = parentLayer->childrenTransform() * transform;
1350 transform.translateRight3d(parentAnchorPoint.x(), parentAnchorPoint.y(), parentAnchorPoint.z());
1357 GraphicsLayerCA::VisibleAndCoverageRects GraphicsLayerCA::computeVisibleAndCoverageRect(TransformState& state, bool preserves3D, ComputeVisibleRectFlags flags) const
1359 FloatPoint position = approximatePosition();
1360 client().customPositionForVisibleRectComputation(this, position);
1362 TransformationMatrix layerTransform;
1363 TransformationMatrix currentTransform;
1364 if ((flags & RespectAnimatingTransforms) && client().getCurrentTransform(this, currentTransform))
1365 layerTransform = this->layerTransform(position, ¤tTransform);
1367 layerTransform = this->layerTransform(position);
1369 bool applyWasClamped;
1370 TransformState::TransformAccumulation accumulation = preserves3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform;
1371 state.applyTransform(layerTransform, accumulation, &applyWasClamped);
1374 FloatRect clipRectForChildren = state.mappedQuad(&mapWasClamped).boundingBox();
1375 FloatPoint boundsOrigin = m_boundsOrigin;
1377 // In WK1, UIKit may be changing layer bounds behind our back in overflow-scroll layers, so use the layer's origin.
1378 if (m_layer->isPlatformCALayerCocoa())
1379 boundsOrigin = m_layer->bounds().location();
1381 clipRectForChildren.move(boundsOrigin.x(), boundsOrigin.y());
1383 FloatRect clipRectForSelf(boundsOrigin, m_size);
1384 if (!applyWasClamped && !mapWasClamped)
1385 clipRectForSelf.intersect(clipRectForChildren);
1387 if (masksToBounds()) {
1388 ASSERT(accumulation == TransformState::FlattenTransform);
1389 // Flatten, and replace the quad in the TransformState with one that is clipped to this layer's bounds.
1391 state.setQuad(clipRectForSelf);
1392 if (state.isMappingSecondaryQuad()) {
1393 FloatQuad secondaryQuad(clipRectForSelf);
1394 state.setSecondaryQuad(&secondaryQuad);
1398 FloatRect coverageRect = clipRectForSelf;
1399 std::optional<FloatQuad> quad = state.mappedSecondaryQuad(&mapWasClamped);
1400 if (quad && !mapWasClamped && !applyWasClamped)
1401 coverageRect = (*quad).boundingBox();
1403 return { clipRectForSelf, coverageRect, currentTransform };
1406 bool GraphicsLayerCA::adjustCoverageRect(VisibleAndCoverageRects& rects, const FloatRect& oldVisibleRect) const
1408 FloatRect coverageRect = rects.coverageRect;
1410 // FIXME: TileController's computeTileCoverageRect() code should move here, and we should unify these different
1411 // ways of computing coverage.
1413 case Type::PageTiledBacking:
1414 tiledBacking()->adjustTileCoverageRect(coverageRect, size(), oldVisibleRect, rects.visibleRect, pageScaleFactor() * deviceScaleFactor());
1417 if (m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
1418 coverageRect.unite(adjustTiledLayerVisibleRect(tiledBacking(), oldVisibleRect, rects.visibleRect, m_sizeAtLastCoverageRectUpdate, m_size));
1424 if (rects.coverageRect == coverageRect)
1427 rects.coverageRect = coverageRect;
1431 void GraphicsLayerCA::setVisibleAndCoverageRects(const VisibleAndCoverageRects& rects, bool isViewportConstrained)
1433 bool visibleRectChanged = rects.visibleRect != m_visibleRect;
1434 bool coverageRectChanged = rects.coverageRect != m_coverageRect;
1435 if (!visibleRectChanged && !coverageRectChanged && !animationExtent())
1438 auto bounds = FloatRect(m_boundsOrigin, size());
1439 if (auto extent = animationExtent()) {
1440 // Adjust the animation extent to match the current animation position.
1441 bounds = rects.animatingTransform.inverse().value_or(TransformationMatrix()).mapRect(*extent);
1444 // FIXME: we need to take reflections into account when determining whether this layer intersects the coverage rect.
1445 bool intersectsCoverageRect = isViewportConstrained || rects.coverageRect.intersects(bounds);
1446 if (intersectsCoverageRect != m_intersectsCoverageRect) {
1447 addUncommittedChanges(CoverageRectChanged);
1448 m_intersectsCoverageRect = intersectsCoverageRect;
1451 if (visibleRectChanged) {
1452 addUncommittedChanges(CoverageRectChanged);
1453 m_visibleRect = rects.visibleRect;
1456 if (coverageRectChanged) {
1457 addUncommittedChanges(CoverageRectChanged);
1458 m_coverageRect = rects.coverageRect;
1462 bool GraphicsLayerCA::needsCommit(const CommitState& commitState)
1464 if (commitState.ancestorHadChanges)
1466 if (m_uncommittedChanges)
1468 if (hasDescendantsWithUncommittedChanges())
1470 // Accelerated transforms move the underlying layers without GraphicsLayers getting invalidated.
1471 if (isRunningTransformAnimation())
1473 if (hasDescendantsWithRunningTransformAnimations())
1479 // rootRelativeTransformForScaling is a transform from the root, but for layers with transform animations, it cherry-picked the state of the
1480 // animation that contributes maximally to the scale (on every layer with animations down the hierarchy).
1481 void GraphicsLayerCA::recursiveCommitChanges(const CommitState& commitState, const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale)
1483 if (!needsCommit(commitState))
1486 TransformState localState = state;
1487 CommitState childCommitState = commitState;
1489 bool affectedByTransformAnimation = commitState.ancestorHasTransformAnimation;
1491 bool accumulateTransform = accumulatesTransform(*this);
1492 VisibleAndCoverageRects rects = computeVisibleAndCoverageRect(localState, accumulateTransform);
1493 if (adjustCoverageRect(rects, m_visibleRect)) {
1494 if (state.isMappingSecondaryQuad()) {
1495 FloatQuad secondaryQuad(rects.coverageRect);
1496 localState.setLastPlanarSecondaryQuad(&secondaryQuad);
1499 setVisibleAndCoverageRects(rects, m_isViewportConstrained || commitState.ancestorIsViewportConstrained);
1501 if (commitState.ancestorStartedOrEndedTransformAnimation)
1502 addUncommittedChanges(CoverageRectChanged);
1504 #ifdef VISIBLE_TILE_WASH
1505 // Use having a transform as a key to making the tile wash layer. If every layer gets a wash,
1506 // they start to obscure useful information.
1507 if ((!m_transform.isIdentity() || tiledBacking()) && !m_visibleTileWashLayer) {
1508 static NeverDestroyed<Color> washFillColor(255, 0, 0, 50);
1509 static NeverDestroyed<Color> washBorderColor(255, 0, 0, 100);
1511 m_visibleTileWashLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
1512 String name = String::format("Visible Tile Wash Layer %p", m_visibleTileWashLayer->platformLayer());
1513 m_visibleTileWashLayer->setName(name);
1514 m_visibleTileWashLayer->setAnchorPoint(FloatPoint3D(0, 0, 0));
1515 m_visibleTileWashLayer->setBorderColor(washBorderColor);
1516 m_visibleTileWashLayer->setBorderWidth(8);
1517 m_visibleTileWashLayer->setBackgroundColor(washFillColor);
1518 noteSublayersChanged(DontScheduleFlush);
1521 if (m_visibleTileWashLayer) {
1522 m_visibleTileWashLayer->setPosition(m_visibleRect.location());
1523 m_visibleTileWashLayer->setBounds(FloatRect(FloatPoint(), m_visibleRect.size()));
1527 bool hadChanges = m_uncommittedChanges;
1529 // FIXME: This could be more fine-grained. Only some types of changes have impact on sublayers.
1530 if (!childCommitState.ancestorHadChanges)
1531 childCommitState.ancestorHadChanges = hadChanges;
1533 if (appliesPageScale()) {
1534 pageScaleFactor = this->pageScaleFactor();
1535 affectedByPageScale = true;
1538 // Accumulate an offset from the ancestral pixel-aligned layer.
1539 FloatPoint baseRelativePosition = positionRelativeToBase;
1540 if (affectedByPageScale)
1541 baseRelativePosition += m_position;
1543 bool wasRunningTransformAnimation = isRunningTransformAnimation();
1545 commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition);
1547 bool nowRunningTransformAnimation = wasRunningTransformAnimation;
1548 if (m_uncommittedChanges & AnimationChanged)
1549 nowRunningTransformAnimation = isRunningTransformAnimation();
1551 if (wasRunningTransformAnimation != nowRunningTransformAnimation)
1552 childCommitState.ancestorStartedOrEndedTransformAnimation = true;
1554 if (nowRunningTransformAnimation) {
1555 childCommitState.ancestorHasTransformAnimation = true;
1556 if (m_intersectsCoverageRect)
1557 childCommitState.ancestorWithTransformAnimationIntersectsCoverageRect = true;
1558 affectedByTransformAnimation = true;
1561 childCommitState.ancestorIsViewportConstrained |= m_isViewportConstrained;
1563 if (GraphicsLayerCA* maskLayer = downcast<GraphicsLayerCA>(m_maskLayer)) {
1564 maskLayer->setVisibleAndCoverageRects(rects, m_isViewportConstrained || commitState.ancestorIsViewportConstrained);
1565 maskLayer->commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition);
1568 const Vector<GraphicsLayer*>& childLayers = children();
1569 size_t numChildren = childLayers.size();
1571 bool hasDescendantsWithRunningTransformAnimations = false;
1573 for (size_t i = 0; i < numChildren; ++i) {
1574 GraphicsLayerCA& currentChild = downcast<GraphicsLayerCA>(*childLayers[i]);
1575 currentChild.recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
1577 if (currentChild.isRunningTransformAnimation() || currentChild.hasDescendantsWithRunningTransformAnimations())
1578 hasDescendantsWithRunningTransformAnimations = true;
1581 if (GraphicsLayerCA* replicaLayer = downcast<GraphicsLayerCA>(m_replicaLayer))
1582 replicaLayer->recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
1584 if (GraphicsLayerCA* maskLayer = downcast<GraphicsLayerCA>(m_maskLayer))
1585 maskLayer->commitLayerChangesAfterSublayers(childCommitState);
1587 setHasDescendantsWithUncommittedChanges(false);
1588 setHasDescendantsWithRunningTransformAnimations(hasDescendantsWithRunningTransformAnimations);
1590 bool hadDirtyRects = m_uncommittedChanges & DirtyRectsChanged;
1591 commitLayerChangesAfterSublayers(childCommitState);
1593 if (affectedByTransformAnimation && m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
1594 client().notifyFlushBeforeDisplayRefresh(this);
1597 client().didCommitChangesForLayer(this);
1599 if (usesDisplayListDrawing() && m_drawsContent && (!m_hasEverPainted || hadDirtyRects)) {
1600 TraceScope tracingScope(DisplayListRecordStart, DisplayListRecordEnd);
1602 m_displayList = std::make_unique<DisplayList::DisplayList>();
1604 FloatRect initialClip(boundsOrigin(), size());
1606 GraphicsContext context([&](GraphicsContext& context) {
1607 return std::make_unique<DisplayList::Recorder>(context, *m_displayList, GraphicsContextState(), initialClip, AffineTransform());
1609 paintGraphicsLayerContents(context, FloatRect(FloatPoint(), size()));
1613 void GraphicsLayerCA::platformCALayerCustomSublayersChanged(PlatformCALayer*)
1615 noteLayerPropertyChanged(ChildrenChanged, m_isCommittingChanges ? DontScheduleFlush : ScheduleFlush);
1618 bool GraphicsLayerCA::platformCALayerShowRepaintCounter(PlatformCALayer* platformLayer) const
1620 // The repaint counters are painted into the TileController tiles (which have no corresponding platform layer),
1621 // so we don't want to overpaint the repaint counter when called with the TileController's own layer.
1622 if (isPageTiledBackingLayer() && platformLayer)
1625 return isShowingRepaintCounter();
1628 void GraphicsLayerCA::platformCALayerPaintContents(PlatformCALayer*, GraphicsContext& context, const FloatRect& clip, GraphicsLayerPaintBehavior layerPaintBehavior)
1630 m_hasEverPainted = true;
1631 if (m_displayList) {
1632 DisplayList::Replayer replayer(context, *m_displayList);
1634 if (UNLIKELY(isTrackingDisplayListReplay())) {
1635 auto replayList = replayer.replay(clip, isTrackingDisplayListReplay());
1636 layerDisplayListMap().add(this, std::pair<FloatRect, std::unique_ptr<DisplayList::DisplayList>>(clip, WTFMove(replayList)));
1638 replayer.replay(clip);
1643 TraceScope tracingScope(PaintLayerStart, PaintLayerEnd);
1644 paintGraphicsLayerContents(context, clip, layerPaintBehavior);
1647 void GraphicsLayerCA::platformCALayerSetNeedsToRevalidateTiles()
1649 noteLayerPropertyChanged(TilingAreaChanged, m_isCommittingChanges ? DontScheduleFlush : ScheduleFlush);
1652 float GraphicsLayerCA::platformCALayerDeviceScaleFactor() const
1654 return deviceScaleFactor();
1657 float GraphicsLayerCA::platformCALayerContentsScaleMultiplierForNewTiles(PlatformCALayer*) const
1659 return client().contentsScaleMultiplierForNewTiles(this);
1662 bool GraphicsLayerCA::platformCALayerShouldAggressivelyRetainTiles(PlatformCALayer*) const
1664 return client().shouldAggressivelyRetainTiles(this);
1667 bool GraphicsLayerCA::platformCALayerShouldTemporarilyRetainTileCohorts(PlatformCALayer*) const
1669 return client().shouldTemporarilyRetainTileCohorts(this);
1672 bool GraphicsLayerCA::platformCALayerUseGiantTiles() const
1674 return client().useGiantTiles();
1677 void GraphicsLayerCA::platformCALayerLogFilledVisibleFreshTile(unsigned blankPixelCount)
1679 client().logFilledVisibleFreshTile(blankPixelCount);
1682 static PlatformCALayer::LayerType layerTypeForCustomBackdropAppearance(GraphicsLayer::CustomAppearance appearance)
1684 return appearance == GraphicsLayer::LightBackdropAppearance ? PlatformCALayer::LayerTypeLightSystemBackdropLayer : PlatformCALayer::LayerTypeDarkSystemBackdropLayer;
1687 static bool isCustomBackdropLayerType(PlatformCALayer::LayerType layerType)
1689 return layerType == PlatformCALayer::LayerTypeLightSystemBackdropLayer || layerType == PlatformCALayer::LayerTypeDarkSystemBackdropLayer;
1692 void GraphicsLayerCA::commitLayerChangesBeforeSublayers(CommitState& commitState, float pageScaleFactor, const FloatPoint& positionRelativeToBase)
1694 SetForScope<bool> committingChangesChange(m_isCommittingChanges, true);
1696 ++commitState.treeDepth;
1697 if (m_structuralLayer)
1698 ++commitState.treeDepth;
1700 if (!m_uncommittedChanges) {
1701 // Ensure that we cap layer depth in commitLayerChangesAfterSublayers().
1702 if (commitState.treeDepth > cMaxLayerTreeDepth)
1703 addUncommittedChanges(ChildrenChanged);
1706 bool needTiledLayer = requiresTiledLayer(pageScaleFactor);
1707 bool needBackdropLayerType = (customAppearance() == LightBackdropAppearance || customAppearance() == DarkBackdropAppearance);
1709 PlatformCALayer::LayerType currentLayerType = m_layer->layerType();
1710 PlatformCALayer::LayerType neededLayerType = currentLayerType;
1712 if (needBackdropLayerType)
1713 neededLayerType = layerTypeForCustomBackdropAppearance(customAppearance());
1714 else if (needTiledLayer)
1715 neededLayerType = PlatformCALayer::LayerTypeTiledBackingLayer;
1716 else if (currentLayerType == PlatformCALayer::LayerTypeTiledBackingLayer || isCustomBackdropLayerType(m_layer->layerType()))
1717 neededLayerType = PlatformCALayer::LayerTypeWebLayer;
1719 if (neededLayerType != m_layer->layerType())
1720 changeLayerTypeTo(neededLayerType);
1722 // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to
1723 if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged | BackdropFiltersChanged))
1724 updateStructuralLayer();
1726 if (m_uncommittedChanges & GeometryChanged)
1727 updateGeometry(pageScaleFactor, positionRelativeToBase);
1729 if (m_uncommittedChanges & DrawsContentChanged)
1730 updateDrawsContent();
1732 if (m_uncommittedChanges & NameChanged)
1735 if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged
1736 updateContentsImage();
1738 if (m_uncommittedChanges & ContentsPlatformLayerChanged) // Needs to happen before ChildrenChanged
1739 updateContentsPlatformLayer();
1741 if (m_uncommittedChanges & ContentsColorLayerChanged) // Needs to happen before ChildrenChanged
1742 updateContentsColorLayer();
1744 if (m_uncommittedChanges & BackgroundColorChanged)
1745 updateBackgroundColor();
1747 if (m_uncommittedChanges & TransformChanged)
1750 if (m_uncommittedChanges & ChildrenTransformChanged)
1751 updateChildrenTransform();
1753 if (m_uncommittedChanges & MasksToBoundsChanged)
1754 updateMasksToBounds();
1756 if (m_uncommittedChanges & ContentsVisibilityChanged)
1757 updateContentsVisibility();
1759 if (m_uncommittedChanges & UserInteractionEnabledChanged)
1760 updateUserInteractionEnabled();
1762 // Note that contentsScale can affect whether the layer can be opaque.
1763 if (m_uncommittedChanges & ContentsOpaqueChanged)
1764 updateContentsOpaque(pageScaleFactor);
1766 if (m_uncommittedChanges & BackfaceVisibilityChanged)
1767 updateBackfaceVisibility();
1769 if (m_uncommittedChanges & OpacityChanged)
1770 updateOpacityOnLayer();
1772 if (m_uncommittedChanges & FiltersChanged)
1775 if (m_uncommittedChanges & BackdropFiltersChanged)
1776 updateBackdropFilters();
1778 if (m_uncommittedChanges & BackdropFiltersRectChanged)
1779 updateBackdropFiltersRect();
1781 #if ENABLE(CSS_COMPOSITING)
1782 if (m_uncommittedChanges & BlendModeChanged)
1786 if (m_uncommittedChanges & ShapeChanged)
1789 if (m_uncommittedChanges & WindRuleChanged)
1792 if (m_uncommittedChanges & AnimationChanged)
1795 // Updating the contents scale can cause parts of the layer to be invalidated,
1796 // so make sure to update the contents scale before updating the dirty rects.
1797 if (m_uncommittedChanges & ContentsScaleChanged)
1798 updateContentsScale(pageScaleFactor);
1800 if (m_uncommittedChanges & CoverageRectChanged)
1801 updateCoverage(commitState);
1803 if (m_uncommittedChanges & AcceleratesDrawingChanged) // Needs to happen before TilingAreaChanged.
1804 updateAcceleratesDrawing();
1806 if (m_uncommittedChanges & TilingAreaChanged) // Needs to happen after CoverageRectChanged, ContentsScaleChanged
1809 if (m_uncommittedChanges & DirtyRectsChanged)
1810 repaintLayerDirtyRects();
1812 if (m_uncommittedChanges & ContentsRectsChanged) // Needs to happen before ChildrenChanged
1813 updateContentsRects();
1815 if (m_uncommittedChanges & MasksToBoundsRectChanged) // Needs to happen before ChildrenChanged
1816 updateMasksToBoundsRect();
1818 if (m_uncommittedChanges & MaskLayerChanged) {
1820 // If the mask layer becomes tiled it can set this flag again. Clear the flag so that
1821 // commitLayerChangesAfterSublayers doesn't update the mask again in the normal case.
1822 m_uncommittedChanges &= ~MaskLayerChanged;
1825 if (m_uncommittedChanges & ContentsNeedsDisplay)
1826 updateContentsNeedsDisplay();
1828 if (m_uncommittedChanges & SupportsSubpixelAntialiasedTextChanged)
1829 updateSupportsSubpixelAntialiasedText();
1831 if (m_uncommittedChanges & DebugIndicatorsChanged)
1832 updateDebugIndicators();
1834 if (m_uncommittedChanges & CustomAppearanceChanged)
1835 updateCustomAppearance();
1837 if (m_uncommittedChanges & ChildrenChanged) {
1838 updateSublayerList();
1839 // Sublayers may set this flag again, so clear it to avoid always updating sublayers in commitLayerChangesAfterSublayers().
1840 m_uncommittedChanges &= ~ChildrenChanged;
1843 // Ensure that we cap layer depth in commitLayerChangesAfterSublayers().
1844 if (commitState.treeDepth > cMaxLayerTreeDepth)
1845 addUncommittedChanges(ChildrenChanged);
1848 void GraphicsLayerCA::commitLayerChangesAfterSublayers(CommitState& commitState)
1850 if (!m_uncommittedChanges)
1853 SetForScope<bool> committingChangesChange(m_isCommittingChanges, true);
1855 if (m_uncommittedChanges & MaskLayerChanged)
1858 if (m_uncommittedChanges & ChildrenChanged)
1859 updateSublayerList(commitState.treeDepth > cMaxLayerTreeDepth);
1861 if (m_uncommittedChanges & ReplicatedLayerChanged)
1862 updateReplicatedLayers();
1864 m_uncommittedChanges = NoChange;
1867 void GraphicsLayerCA::updateNames()
1869 switch (structuralLayerPurpose()) {
1870 case StructuralLayerForPreserves3D:
1871 m_structuralLayer->setName("preserve-3d: " + name());
1873 case StructuralLayerForReplicaFlattening:
1874 m_structuralLayer->setName("replica flattening: " + name());
1876 case StructuralLayerForBackdrop:
1877 m_structuralLayer->setName("backdrop hosting: " + name());
1879 case NoStructuralLayer:
1882 m_layer->setName(name());
1885 void GraphicsLayerCA::updateSublayerList(bool maxLayerDepthReached)
1887 if (maxLayerDepthReached) {
1888 m_layer->setSublayers(PlatformCALayerList());
1892 const PlatformCALayerList* customSublayers = m_layer->customSublayers();
1894 PlatformCALayerList structuralLayerChildren;
1895 PlatformCALayerList primaryLayerChildren;
1897 PlatformCALayerList& childListForSublayers = m_structuralLayer ? structuralLayerChildren : primaryLayerChildren;
1899 if (customSublayers)
1900 primaryLayerChildren.appendVector(*customSublayers);
1902 if (m_structuralLayer) {
1903 if (m_backdropLayer)
1904 structuralLayerChildren.append(m_backdropLayer);
1907 structuralLayerChildren.append(downcast<GraphicsLayerCA>(*m_replicaLayer).primaryLayer());
1909 structuralLayerChildren.append(m_layer);
1912 if (m_contentsLayer && m_contentsVisible) {
1913 // FIXME: add the contents layer in the correct order with negative z-order children.
1914 // This does not cause visible rendering issues because currently contents layers are only used
1915 // for replaced elements that don't have children.
1916 primaryLayerChildren.append(m_contentsClippingLayer ? m_contentsClippingLayer : m_contentsLayer);
1919 const Vector<GraphicsLayer*>& childLayers = children();
1920 size_t numChildren = childLayers.size();
1921 for (size_t i = 0; i < numChildren; ++i) {
1922 GraphicsLayerCA& currentChild = downcast<GraphicsLayerCA>(*childLayers[i]);
1923 PlatformCALayer* childLayer = currentChild.layerForSuperlayer();
1924 childListForSublayers.append(childLayer);
1927 #ifdef VISIBLE_TILE_WASH
1928 if (m_visibleTileWashLayer)
1929 childListForSublayers.append(m_visibleTileWashLayer);
1932 if (m_structuralLayer)
1933 m_structuralLayer->setSublayers(structuralLayerChildren);
1935 m_layer->setSublayers(primaryLayerChildren);
1938 void GraphicsLayerCA::updateGeometry(float pageScaleFactor, const FloatPoint& positionRelativeToBase)
1940 FloatPoint scaledPosition = m_position;
1941 FloatPoint3D scaledAnchorPoint = m_anchorPoint;
1942 FloatSize scaledSize = m_size;
1943 FloatSize pixelAlignmentOffset;
1945 // FIXME: figure out if we really need to pixel align the graphics layer here.
1946 if (m_client.needsPixelAligment() && !WTF::isIntegral(pageScaleFactor) && m_drawsContent && !m_masksToBounds)
1947 computePixelAlignment(pageScaleFactor, positionRelativeToBase, scaledPosition, scaledAnchorPoint, pixelAlignmentOffset);
1950 // Position is offset on the layer by the layer anchor point.
1951 FloatPoint adjustedPosition(scaledPosition.x() + scaledAnchorPoint.x() * scaledSize.width(), scaledPosition.y() + scaledAnchorPoint.y() * scaledSize.height());
1953 if (m_structuralLayer) {
1954 FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(), m_position.y() + m_anchorPoint.y() * m_size.height());
1955 FloatRect layerBounds(m_boundsOrigin, m_size);
1957 m_structuralLayer->setPosition(layerPosition);
1958 m_structuralLayer->setBounds(layerBounds);
1959 m_structuralLayer->setAnchorPoint(m_anchorPoint);
1961 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
1962 for (auto& clone : *layerCloneMap) {
1963 PlatformCALayer* cloneLayer = clone.value.get();
1964 FloatPoint clonePosition = layerPosition;
1966 if (m_replicaLayer && isReplicatedRootClone(clone.key)) {
1967 // Maintain the special-case position for the root of a clone subtree,
1968 // which we set up in replicatedLayerRoot().
1969 clonePosition = positionForCloneRootLayer();
1972 cloneLayer->setPosition(clonePosition);
1973 cloneLayer->setBounds(layerBounds);
1974 cloneLayer->setAnchorPoint(m_anchorPoint);
1978 // If we have a structural layer, we just use 0.5, 0.5 for the anchor point of the main layer.
1979 scaledAnchorPoint = FloatPoint(0.5f, 0.5f);
1980 adjustedPosition = FloatPoint(scaledAnchorPoint.x() * scaledSize.width() - pixelAlignmentOffset.width(), scaledAnchorPoint.y() * scaledSize.height() - pixelAlignmentOffset.height());
1983 m_pixelAlignmentOffset = pixelAlignmentOffset;
1985 // Push the layer to device pixel boundary (setPosition()), but move the content back to its original position (setBounds())
1986 m_layer->setPosition(adjustedPosition);
1987 FloatRect adjustedBounds = FloatRect(FloatPoint(m_boundsOrigin - pixelAlignmentOffset), m_size);
1988 m_layer->setBounds(adjustedBounds);
1989 m_layer->setAnchorPoint(scaledAnchorPoint);
1991 if (LayerMap* layerCloneMap = m_layerClones.get()) {
1992 for (auto& clone : *layerCloneMap) {
1993 PlatformCALayer* cloneLayer = clone.value.get();
1994 FloatPoint clonePosition = adjustedPosition;
1996 if (!m_structuralLayer && m_replicaLayer && isReplicatedRootClone(clone.key)) {
1997 // Maintain the special-case position for the root of a clone subtree,
1998 // which we set up in replicatedLayerRoot().
1999 clonePosition = positionForCloneRootLayer();
2002 cloneLayer->setPosition(clonePosition);
2003 cloneLayer->setBounds(adjustedBounds);
2004 cloneLayer->setAnchorPoint(scaledAnchorPoint);
2009 void GraphicsLayerCA::updateTransform()
2011 primaryLayer()->setTransform(m_transform);
2013 if (LayerMap* layerCloneMap = primaryLayerClones()) {
2014 for (auto& clone : *layerCloneMap) {
2015 PlatformCALayer* currLayer = clone.value.get();
2016 if (m_replicaLayer && isReplicatedRootClone(clone.key)) {
2017 // Maintain the special-case transform for the root of a clone subtree,
2018 // which we set up in replicatedLayerRoot().
2019 currLayer->setTransform(TransformationMatrix());
2021 currLayer->setTransform(m_transform);
2026 void GraphicsLayerCA::updateChildrenTransform()
2028 primaryLayer()->setSublayerTransform(m_childrenTransform);
2030 if (LayerMap* layerCloneMap = primaryLayerClones()) {
2031 for (auto& layer : layerCloneMap->values())
2032 layer->setSublayerTransform(m_childrenTransform);
2036 void GraphicsLayerCA::updateMasksToBounds()
2038 m_layer->setMasksToBounds(m_masksToBounds);
2040 if (LayerMap* layerCloneMap = m_layerClones.get()) {
2041 for (auto& layer : layerCloneMap->values())
2042 layer->setMasksToBounds(m_masksToBounds);
2046 void GraphicsLayerCA::updateContentsVisibility()
2048 // Note that m_contentsVisible also affects whether m_contentsLayer is parented.
2049 if (m_contentsVisible) {
2051 m_layer->setNeedsDisplay();
2053 if (m_backdropLayer)
2054 m_backdropLayer->setHidden(false);
2056 m_layer->setContents(nullptr);
2058 if (LayerMap* layerCloneMap = m_layerClones.get()) {
2059 for (auto& layer : layerCloneMap->values())
2060 layer->setContents(nullptr);
2063 if (m_backdropLayer)
2064 m_backdropLayer->setHidden(true);
2067 m_layer->setContentsHidden(!m_contentsVisible);
2070 void GraphicsLayerCA::updateUserInteractionEnabled()
2072 m_layer->setUserInteractionEnabled(m_userInteractionEnabled);
2075 void GraphicsLayerCA::updateContentsOpaque(float pageScaleFactor)
2077 bool contentsOpaque = m_contentsOpaque;
2078 if (contentsOpaque) {
2079 float contentsScale = pageScaleFactor * deviceScaleFactor();
2080 if (!WTF::isIntegral(contentsScale) && !m_client.paintsOpaquelyAtNonIntegralScales(this))
2081 contentsOpaque = false;
2084 m_layer->setOpaque(contentsOpaque);
2086 if (LayerMap* layerCloneMap = m_layerClones.get()) {
2087 for (auto& layer : layerCloneMap->values())
2088 layer->setOpaque(contentsOpaque);
2092 void GraphicsLayerCA::updateBackfaceVisibility()
2094 if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) {
2095 m_structuralLayer->setDoubleSided(m_backfaceVisibility);
2097 if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
2098 for (auto& layer : layerCloneMap->values())
2099 layer->setDoubleSided(m_backfaceVisibility);
2103 m_layer->setDoubleSided(m_backfaceVisibility);
2105 if (LayerMap* layerCloneMap = m_layerClones.get()) {
2106 for (auto& layer : layerCloneMap->values())
2107 layer->setDoubleSided(m_backfaceVisibility);
2111 void GraphicsLayerCA::updateFilters()
2113 m_layer->setFilters(m_filters);
2115 if (LayerMap* layerCloneMap = m_layerClones.get()) {
2116 for (auto& clone : *layerCloneMap) {
2117 if (m_replicaLayer && isReplicatedRootClone(clone.key))
2120 clone.value->setFilters(m_filters);
2125 void GraphicsLayerCA::updateBackdropFilters()
2127 if (m_backdropFilters.isEmpty()) {
2128 if (m_backdropLayer) {
2129 m_backdropLayer->removeFromSuperlayer();
2130 m_backdropLayer->setOwner(nullptr);
2131 m_backdropLayer = nullptr;
2136 bool madeLayer = !m_backdropLayer;
2137 if (!m_backdropLayer) {
2138 m_backdropLayer = createPlatformCALayer(PlatformCALayer::LayerTypeBackdropLayer, this);
2139 m_backdropLayer->setAnchorPoint(FloatPoint3D());
2140 m_backdropLayer->setMasksToBounds(true);
2141 m_backdropLayer->setName("backdrop");
2144 m_backdropLayer->setHidden(!m_contentsVisible);
2145 m_backdropLayer->setFilters(m_backdropFilters);
2147 if (LayerMap* layerCloneMap = m_backdropLayerClones.get()) {
2148 for (auto& clone : *layerCloneMap) {
2149 PlatformCALayer* cloneLayer = clone.value.get();
2150 cloneLayer->setHidden(!m_contentsVisible);
2151 cloneLayer->setFilters(m_backdropFilters);
2156 updateBackdropFiltersRect();
2159 void GraphicsLayerCA::updateBackdropFiltersRect()
2161 if (!m_backdropLayer)
2164 FloatRect contentBounds(0, 0, m_backdropFiltersRect.rect().width(), m_backdropFiltersRect.rect().height());
2165 m_backdropLayer->setBounds(contentBounds);
2166 m_backdropLayer->setPosition(m_backdropFiltersRect.rect().location());
2168 updateClippingStrategy(*m_backdropLayer, m_backdropClippingLayer, m_backdropFiltersRect);
2170 if (m_backdropLayerClones) {
2171 for (auto& clone : *m_backdropLayerClones) {
2172 PlatformCALayer* backdropCloneLayer = clone.value.get();
2173 backdropCloneLayer->setBounds(contentBounds);
2174 backdropCloneLayer->setPosition(m_backdropFiltersRect.rect().location());
2176 CloneID cloneID = clone.key;
2177 RefPtr<PlatformCALayer> backdropClippingLayerClone;
2178 if (m_backdropClippingLayerClones)
2179 backdropClippingLayerClone = m_backdropClippingLayerClones->get(cloneID);
2181 bool hadBackdropClippingLayer = backdropClippingLayerClone;
2182 updateClippingStrategy(*backdropCloneLayer, backdropClippingLayerClone, m_backdropFiltersRect);
2184 if (!backdropClippingLayerClone && m_backdropClippingLayerClones)
2185 m_backdropClippingLayerClones->remove(cloneID);
2186 else if (backdropClippingLayerClone && !hadBackdropClippingLayer)
2187 m_backdropClippingLayerClones->add(cloneID, backdropClippingLayerClone);
2192 #if ENABLE(CSS_COMPOSITING)
2193 void GraphicsLayerCA::updateBlendMode()
2195 primaryLayer()->setBlendMode(m_blendMode);
2197 if (LayerMap* layerCloneMap = primaryLayerClones()) {
2198 for (auto& clone : *layerCloneMap) {
2199 if (m_replicaLayer && isReplicatedRootClone(clone.key))
2201 clone.value->setBlendMode(m_blendMode);
2207 void GraphicsLayerCA::updateShape()
2209 m_layer->setShapePath(m_shapeLayerPath);
2211 if (LayerMap* layerCloneMap = primaryLayerClones()) {
2212 for (auto& layer : layerCloneMap->values())
2213 layer->setShapePath(m_shapeLayerPath);
2217 void GraphicsLayerCA::updateWindRule()
2219 m_layer->setShapeWindRule(m_shapeLayerWindRule);
2222 void GraphicsLayerCA::updateStructuralLayer()
2224 ensureStructuralLayer(structuralLayerPurpose());
2227 void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose)
2229 const LayerChangeFlags structuralLayerChangeFlags = NameChanged
2232 | ChildrenTransformChanged
2234 | BackfaceVisibilityChanged
2236 | BackdropFiltersChanged
2240 if (purpose == NoStructuralLayer) {
2241 if (m_structuralLayer) {
2242 // Replace the transformLayer in the parent with this layer.
2243 m_layer->removeFromSuperlayer();
2245 // If m_layer doesn't have a parent, it means it's the root layer and
2246 // is likely hosted by something that is not expecting to be changed
2247 ASSERT(m_structuralLayer->superlayer());
2248 m_structuralLayer->superlayer()->replaceSublayer(*m_structuralLayer, *m_layer);
2250 moveAnimations(m_structuralLayer.get(), m_layer.get());
2252 // Release the structural layer.
2253 m_structuralLayer = nullptr;
2255 addUncommittedChanges(structuralLayerChangeFlags);
2260 bool structuralLayerChanged = false;
2262 if (purpose == StructuralLayerForPreserves3D) {
2263 if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeTransformLayer)
2264 m_structuralLayer = nullptr;
2266 if (!m_structuralLayer) {
2267 m_structuralLayer = createPlatformCALayer(PlatformCALayer::LayerTypeTransformLayer, this);
2268 structuralLayerChanged = true;
2271 if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeLayer)
2272 m_structuralLayer = nullptr;
2274 if (!m_structuralLayer) {
2275 m_structuralLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
2276 structuralLayerChanged = true;
2280 if (!structuralLayerChanged)
2283 addUncommittedChanges(structuralLayerChangeFlags);
2285 // We've changed the layer that our parent added to its sublayer list, so tell it to update
2286 // sublayers again in its commitLayerChangesAfterSublayers().
2287 downcast<GraphicsLayerCA>(*parent()).noteSublayersChanged(DontScheduleFlush);
2289 // Set properties of m_layer to their default values, since these are expressed on on the structural layer.
2290 FloatPoint point(m_size.width() / 2.0f, m_size.height() / 2.0f);
2291 FloatPoint3D anchorPoint(0.5f, 0.5f, 0);
2292 m_layer->setPosition(point);
2293 m_layer->setAnchorPoint(anchorPoint);
2294 m_layer->setTransform(TransformationMatrix());
2295 m_layer->setOpacity(1);
2296 if (m_layerClones) {
2297 LayerMap::const_iterator end = m_layerClones->end();
2298 for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) {
2299 PlatformCALayer* currLayer = it->value.get();
2300 currLayer->setPosition(point);
2301 currLayer->setAnchorPoint(anchorPoint);
2302 currLayer->setTransform(TransformationMatrix());
2303 currLayer->setOpacity(1);
2307 moveAnimations(m_layer.get(), m_structuralLayer.get());
2310 GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const
2313 return StructuralLayerForPreserves3D;
2316 return StructuralLayerForReplicaFlattening;
2318 if (needsBackdrop())
2319 return StructuralLayerForBackdrop;
2321 return NoStructuralLayer;
2324 void GraphicsLayerCA::updateDrawsContent()
2326 if (m_drawsContent) {
2327 m_layer->setNeedsDisplay();
2328 m_hasEverPainted = false;
2330 m_layer->setContents(0);
2331 if (m_layerClones) {
2332 LayerMap::const_iterator end = m_layerClones->end();
2333 for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it)
2334 it->value->setContents(0);
2339 void GraphicsLayerCA::updateCoverage(const CommitState& commitState)
2341 // FIXME: Need to set coverage on clone layers too.
2342 if (TiledBacking* backing = tiledBacking()) {
2343 backing->setVisibleRect(m_visibleRect);
2344 backing->setCoverageRect(m_coverageRect);
2347 if (canDetachBackingStore()) {
2348 bool requiresBacking = m_intersectsCoverageRect
2349 || commitState.ancestorWithTransformAnimationIntersectsCoverageRect // FIXME: Compute backing exactly for descendants of animating layers.
2350 || (isRunningTransformAnimation() && !animationExtent()); // Create backing if we don't know the animation extent.
2352 m_layer->setBackingStoreAttached(requiresBacking);
2353 if (m_layerClones) {
2354 for (auto& it : *m_layerClones)
2355 it.value->setBackingStoreAttached(requiresBacking);
2359 m_sizeAtLastCoverageRectUpdate = m_size;
2362 void GraphicsLayerCA::updateAcceleratesDrawing()
2364 m_layer->setAcceleratesDrawing(m_acceleratesDrawing);
2367 void GraphicsLayerCA::updateSupportsSubpixelAntialiasedText()
2369 m_layer->setSupportsSubpixelAntialiasedText(m_supportsSubpixelAntialiasedText);
2372 static void setLayerDebugBorder(PlatformCALayer& layer, Color borderColor, float borderWidth)
2374 layer.setBorderColor(borderColor);
2375 layer.setBorderWidth(borderColor.isValid() ? borderWidth : 0);
2378 static const float contentsLayerBorderWidth = 4;
2379 static Color contentsLayerDebugBorderColor(bool showingBorders)
2381 return showingBorders ? Color(0, 0, 128, 180) : Color();
2384 static const float cloneLayerBorderWidth = 2;
2385 static Color cloneLayerDebugBorderColor(bool showingBorders)
2387 return showingBorders ? Color(255, 122, 251) : Color();
2390 void GraphicsLayerCA::updateDebugIndicators()
2395 bool showDebugBorders = isShowingDebugBorder();
2396 if (showDebugBorders)
2397 getDebugBorderInfo(borderColor, width);
2399 // Paint repaint counter.
2400 m_layer->setNeedsDisplay();
2402 setLayerDebugBorder(*m_layer, borderColor, width);
2403 if (m_contentsLayer)
2404 setLayerDebugBorder(*m_contentsLayer, contentsLayerDebugBorderColor(showDebugBorders), contentsLayerBorderWidth);
2406 if (m_layerClones) {
2407 for (auto& clone : m_layerClones->values())
2408 setLayerDebugBorder(*clone, borderColor, width);
2411 if (m_structuralLayerClones) {
2412 Color cloneLayerBorderColor = cloneLayerDebugBorderColor(showDebugBorders);
2413 for (auto& clone : m_structuralLayerClones->values())
2414 setLayerDebugBorder(*clone, cloneLayerBorderColor, cloneLayerBorderWidth);
2417 if (m_contentsLayerClones) {
2418 Color contentsLayerBorderColor = contentsLayerDebugBorderColor(showDebugBorders);
2419 for (auto& contentsLayerClone : m_contentsLayerClones->values())
2420 setLayerDebugBorder(*contentsLayerClone, contentsLayerBorderColor, contentsLayerBorderWidth);
2424 FloatRect GraphicsLayerCA::adjustTiledLayerVisibleRect(TiledBacking* tiledBacking, const FloatRect& oldVisibleRect, const FloatRect& newVisibleRect, const FloatSize& oldSize, const FloatSize& newSize)
2426 // If the old visible rect is empty, we have no information about how the visible area is changing
2427 // (maybe the layer was just created), so don't attempt to expand. Also don't attempt to expand
2428 // if the size changed or the rects don't overlap.
2429 if (oldVisibleRect.isEmpty() || newSize != oldSize || !newVisibleRect.intersects(oldVisibleRect))
2430 return newVisibleRect;
2432 const float paddingMultiplier = 2;
2434 float leftEdgeDelta = paddingMultiplier * (newVisibleRect.x() - oldVisibleRect.x());
2435 float rightEdgeDelta = paddingMultiplier * (newVisibleRect.maxX() - oldVisibleRect.maxX());
2437 float topEdgeDelta = paddingMultiplier * (newVisibleRect.y() - oldVisibleRect.y());
2438 float bottomEdgeDelta = paddingMultiplier * (newVisibleRect.maxY() - oldVisibleRect.maxY());
2440 FloatRect existingTileBackingRect = tiledBacking->visibleRect();
2441 FloatRect expandedRect = newVisibleRect;
2443 // More exposed on left side.
2444 if (leftEdgeDelta < 0) {
2445 float newLeft = expandedRect.x() + leftEdgeDelta;
2446 // Pad to the left, but don't reduce padding that's already in the backing store (since we're still exposing to the left).
2447 if (newLeft < existingTileBackingRect.x())
2448 expandedRect.shiftXEdgeTo(newLeft);
2450 expandedRect.shiftXEdgeTo(existingTileBackingRect.x());
2453 // More exposed on right.
2454 if (rightEdgeDelta > 0) {
2455 float newRight = expandedRect.maxX() + rightEdgeDelta;
2456 // Pad to the right, but don't reduce padding that's already in the backing store (since we're still exposing to the right).
2457 if (newRight > existingTileBackingRect.maxX())
2458 expandedRect.setWidth(newRight - expandedRect.x());
2460 expandedRect.setWidth(existingTileBackingRect.maxX() - expandedRect.x());
2463 // More exposed at top.
2464 if (topEdgeDelta < 0) {
2465 float newTop = expandedRect.y() + topEdgeDelta;
2466 if (newTop < existingTileBackingRect.y())
2467 expandedRect.shiftYEdgeTo(newTop);
2469 expandedRect.shiftYEdgeTo(existingTileBackingRect.y());
2472 // More exposed on bottom.
2473 if (bottomEdgeDelta > 0) {
2474 float newBottom = expandedRect.maxY() + bottomEdgeDelta;
2475 if (newBottom > existingTileBackingRect.maxY())
2476 expandedRect.setHeight(newBottom - expandedRect.y());
2478 expandedRect.setHeight(existingTileBackingRect.maxY() - expandedRect.y());
2481 expandedRect.intersect(tiledBacking->boundsWithoutMargin());
2482 return expandedRect;
2485 void GraphicsLayerCA::updateTiles()
2487 if (!m_layer->usesTiledBackingLayer())
2490 tiledBacking()->revalidateTiles();
2493 void GraphicsLayerCA::updateBackgroundColor()
2495 m_layer->setBackgroundColor(m_backgroundColor);
2498 void GraphicsLayerCA::updateContentsImage()
2500 if (m_pendingContentsImage) {
2501 if (!m_contentsLayer.get()) {
2502 m_contentsLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
2503 #if ENABLE(TREE_DEBUGGING)
2504 m_contentsLayer->setName(String::format("contents image %llu", m_contentsLayer->layerID()));
2506 m_contentsLayer->setName("contents image");
2508 setupContentsLayer(m_contentsLayer.get());
2509 // m_contentsLayer will be parented by updateSublayerList
2512 // FIXME: maybe only do trilinear if the image is being scaled down,
2513 // but then what if the layer size changes?
2514 m_contentsLayer->setMinificationFilter(PlatformCALayer::Trilinear);
2515 m_contentsLayer->setContents(m_pendingContentsImage.get());
2516 m_pendingContentsImage = nullptr;
2518 if (m_contentsLayerClones) {
2519 LayerMap::const_iterator end = m_contentsLayerClones->end();
2520 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it)
2521 it->value->setContents(m_contentsLayer->contents());
2524 updateContentsRects();
2527 // m_contentsLayer will be removed via updateSublayerList.
2528 m_contentsLayer = nullptr;
2532 void GraphicsLayerCA::updateContentsPlatformLayer()
2534 if (!m_contentsLayer)
2537 // Platform layer was set as m_contentsLayer, and will get parented in updateSublayerList().
2538 setupContentsLayer(m_contentsLayer.get());
2540 if (m_contentsLayerPurpose == ContentsLayerForCanvas)
2541 m_contentsLayer->setNeedsDisplay();
2543 updateContentsRects();
2546 void GraphicsLayerCA::updateContentsColorLayer()
2548 // Color layer was set as m_contentsLayer, and will get parented in updateSublayerList().
2549 if (!m_contentsLayer || m_contentsLayerPurpose != ContentsLayerForBackgroundColor)
2552 setupContentsLayer(m_contentsLayer.get());
2553 updateContentsRects();
2554 ASSERT(m_contentsSolidColor.isValid());
2555 m_contentsLayer->setBackgroundColor(m_contentsSolidColor);
2557 if (m_contentsLayerClones) {
2558 LayerMap::const_iterator end = m_contentsLayerClones->end();
2559 for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it)
2560 it->value->setBackgroundColor(m_contentsSolidColor);
2564 // The clipping strategy depends on whether the rounded rect has equal corner radii.
2565 void GraphicsLayerCA::updateClippingStrategy(PlatformCALayer& clippingLayer, RefPtr<PlatformCALayer>& shapeMaskLayer, const FloatRoundedRect& roundedRect)
2567 if (roundedRect.radii().isUniformCornerRadius()) {
2568 clippingLayer.setMask(nullptr);
2569 if (shapeMaskLayer) {
2570 shapeMaskLayer->setOwner(nullptr);
2571 shapeMaskLayer = nullptr;
2574 clippingLayer.setMasksToBounds(true);
2575 clippingLayer.setCornerRadius(roundedRect.radii().topLeft().width());
2579 if (!shapeMaskLayer) {
2580 shapeMaskLayer = createPlatformCALayer(PlatformCALayer::LayerTypeShapeLayer, this);
2581 shapeMaskLayer->setAnchorPoint(FloatPoint3D());
2582 shapeMaskLayer->setName("shape mask");
2585 shapeMaskLayer->setPosition(FloatPoint());
2586 shapeMaskLayer->setBounds(clippingLayer.bounds());
2588 clippingLayer.setCornerRadius(0);
2589 clippingLayer.setMask(shapeMaskLayer.get());
2591 FloatRoundedRect offsetRoundedRect(clippingLayer.bounds(), roundedRect.radii());
2592 shapeMaskLayer->setShapeRoundedRect(offsetRoundedRect);
2595 void GraphicsLayerCA::updateContentsRects()
2597 if (!m_contentsLayer)
2600 FloatPoint contentOrigin;
2601 const FloatRect contentBounds(0, 0, m_contentsRect.width(), m_contentsRect.height());
2603 FloatPoint clippingOrigin(m_contentsClippingRect.rect().location());
2604 FloatRect clippingBounds(FloatPoint(), m_contentsClippingRect.rect().size());
2606 bool gainedOrLostClippingLayer = false;
2607 if (m_contentsClippingRect.isRounded() || !m_contentsClippingRect.rect().contains(m_contentsRect)) {
2608 if (!m_contentsClippingLayer) {
2609 m_contentsClippingLayer = createPlatformCALayer(PlatformCALayer::LayerTypeLayer, this);
2610 m_contentsClippingLayer->setAnchorPoint(FloatPoint());
2611 #if ENABLE(TREE_DEBUGGING)
2612 m_contentsClippingLayer->setName(String::format("contents clipping %llu", m_contentsClippingLayer->layerID()));
2614 m_contentsClippingLayer->setName("contents clipping");
2616 gainedOrLostClippingLayer = true;
2619 m_contentsClippingLayer->setPosition(clippingOrigin);
2620 m_contentsClippingLayer->setBounds(clippingBounds);
2622 updateClippingStrategy(*m_contentsClippingLayer, m_contentsShapeMaskLayer, m_contentsClippingRect);
2624 if (gainedOrLostClippingLayer) {
2625 m_contentsLayer->removeFromSuperlayer();
2626 m_contentsClippingLayer->appendSublayer(*m_contentsLayer);
2629 contentOrigin = FloatPoint(m_contentsRect.location() - m_contentsClippingRect.rect().location());
2631 if (m_contentsClippingLayer) {
2632 m_contentsLayer->removeFromSuperlayer();
2634 m_contentsClippingLayer->removeFromSuperlayer();
2635 m_contentsClippingLayer->setOwner(nullptr);
2636 m_contentsClippingLayer->setMask(nullptr);
2637 m_contentsClippingLayer = nullptr;
2638 gainedOrLostClippingLayer = true;
2641 if (m_contentsShapeMaskLayer) {
2642 m_contentsShapeMaskLayer->setOwner(nullptr);
2643 m_contentsShapeMaskLayer = nullptr;
2646 contentOrigin = m_contentsRect.location();
2649 if (gainedOrLostClippingLayer)
2650 noteSublayersChanged(DontScheduleFlush);
2652 m_contentsLayer->setPosition(contentOrigin);
2653 m_contentsLayer->setBounds(contentBounds);
2655 if (m_contentsLayerClones) {
2656 for (auto& layer : m_contentsLayerClones->values()) {
2657 layer->setPosition(contentOrigin);
2658 layer->setBounds(contentBounds);
2662 if (m_contentsClippingLayerClones) {
2663 if (!m_contentsShapeMaskLayerClones && m_contentsShapeMaskLayer)
2664 m_contentsShapeMaskLayerClones = std::make_unique<LayerMap>();
2666 for (auto& clone : *m_contentsClippingLayerClones) {
2667 CloneID cloneID = clone.key;
2668 RefPtr<PlatformCALayer> shapeMaskLayerClone;
2669 if (m_contentsShapeMaskLayerClones)
2670 shapeMaskLayerClone = m_contentsShapeMaskLayerClones->get(cloneID);
2672 bool hadShapeMask = shapeMaskLayerClone;
2673 updateClippingStrategy(*clone.value, shapeMaskLayerClone, m_contentsClippingRect);
2675 if (!shapeMaskLayerClone && m_contentsShapeMaskLayerClones)
2676 m_contentsShapeMaskLayerClones->remove(cloneID);
2677 else if (shapeMaskLayerClone && !hadShapeMask)
2678 m_contentsShapeMaskLayerClones->add(cloneID, shapeMaskLayerClone);
2683 void GraphicsLayerCA::updateMasksToBoundsRect()
2685 updateClippingStrategy(*m_layer, m_shapeMaskLayer, m_masksToBoundsRect);
2687 if (m_layerClones) {
2688 for (auto& clone : *m_layerClones) {
2689 CloneID cloneID = clone.key;
2690 RefPtr<PlatformCALayer> shapeMaskLayerClone;
2691 if (m_shapeMaskLayerClones)
2692 shapeMaskLayerClone = m_shapeMaskLayerClones->get(cloneID);
2694 bool hadShapeMask = shapeMaskLayerClone;
2695 updateClippingStrategy(*clone.value, shapeMaskLayerClone, m_masksToBoundsRect);
2697 if (!shapeMaskLayerClone && m_shapeMaskLayerClones)
2698 m_shapeMaskLayerClones->remove(cloneID);
2699 else if (shapeMaskLayerClone && !hadShapeMask)
2700 m_shapeMaskLayerClones->add(cloneID, shapeMaskLayerClone);
2705 void GraphicsLayerCA::updateMaskLayer()
2707 PlatformCALayer* maskCALayer = m_maskLayer ? downcast<GraphicsLayerCA>(*m_maskLayer).primaryLayer() : nullptr;
2709 LayerMap* layerCloneMap;
2710 if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForBackdrop) {
2711 m_structuralLayer->setMask(maskCALayer);
2712 layerCloneMap = m_structuralLayerClones.get();
2714 m_layer->setMask(maskCALayer);
2715 layerCloneMap = m_layerClones.get();
2718 LayerMap* maskLayerCloneMap = m_maskLayer ? downcast<GraphicsLayerCA>(*m_maskLayer).primaryLayerClones() : nullptr;
2719 if (layerCloneMap) {
2720 for (auto& clone : *layerCloneMap) {
2721 PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(clone.key) : nullptr;
2722 clone.value->setMask(maskClone);
2727 void GraphicsLayerCA::updateReplicatedLayers()
2729 // Clone the descendants of the replicated layer, and parent under us.
2730 ReplicaState replicaState(ReplicaState::ReplicaBranch);
2732 RefPtr<PlatformCALayer>replicaRoot = replicatedLayerRoot(replicaState);
2736 if (m_structuralLayer)
2737 m_structuralLayer->insertSublayer(*replicaRoot, 0);
2739 m_layer->insertSublayer(*replicaRoot, 0);
2742 // For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1.
2743 GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const
2745 size_t depth = m_replicaBranches.size();
2747 const size_t bitsPerUChar = sizeof(UChar) * 8;
2748 size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar;
2750 Vector<UChar> result(vectorSize);
2753 // Create a string from the bit sequence which we can use to identify the clone.
2754 // Note that the string may contain embedded nulls, but that's OK.
2755 for (size_t i = 0; i < depth; ++i) {
2756 UChar& currChar = result[i / bitsPerUChar];
2757 currChar = (currChar << 1) | m_replicaBranches[i];
2760 return String::adopt(WTFMove(result));
2763 RefPtr<PlatformCALayer> GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState)
2765 // Limit replica nesting, to avoid 2^N explosion of replica layers.
2766 if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth)
2769 GraphicsLayerCA& replicatedLayer = downcast<GraphicsLayerCA>(*m_replicatedLayer);
2771 RefPtr<PlatformCALayer> clonedLayerRoot = replicatedLayer.fetchCloneLayers(this, replicaState, RootCloneLevel);
2772 FloatPoint cloneRootPosition = replicatedLayer.positionForCloneRootLayer();
2774 // Replica root has no offset or transform
2775 clonedLayerRoot->setPosition(cloneRootPosition);
2776 clonedLayerRoot->setTransform(TransformationMatrix());
2778 return clonedLayerRoot;
2781 void GraphicsLayerCA::updateAnimations()
2783 size_t numAnimations;
2784 if ((numAnimations = m_uncomittedAnimations.size())) {
2785 for (size_t i = 0; i < numAnimations; ++i) {
2786 const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i];
2787 setAnimationOnLayer(*pendingAnimation.m_animation, pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_subIndex, pendingAnimation.m_timeOffset);
2789 AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name);
2790 if (it == m_runningAnimations.end()) {
2791 Vector<LayerPropertyAnimation> animations;
2792 animations.append(pendingAnimation);
2793 m_runningAnimations.add(pendingAnimation.m_name, animations);
2795 Vector<LayerPropertyAnimation>& animations = it->value;
2796 animations.append(pendingAnimation);
2799 m_uncomittedAnimations.clear();
2802 if (m_animationsToProcess.size()) {
2803 AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end();
2804 for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) {
2805 const String& currentAnimationName = it->key;
2806 auto animationIterator = m_runningAnimations.find(currentAnimationName);
2807 if (animationIterator == m_runningAnimations.end())
2810 for (const auto& processingInfo : it->value) {
2811 const Vector<LayerPropertyAnimation>& animations = animationIterator->value;
2812 for (const auto& currentAnimation : animations) {
2813 switch (processingInfo.action) {
2815 removeCAAnimationFromLayer(currentAnimation.m_property, currentAnimationName, currentAnimation.m_index, currentAnimation.m_subIndex);
2818 pauseCAAnimationOnLayer(currentAnimation.m_property, currentAnimationName, currentAnimation.m_index, currentAnimation.m_subIndex, processingInfo.timeOffset);
2821 seekCAAnimationOnLayer(currentAnimation.m_property, currentAnimationName, currentAnimation.m_index, currentAnimation.m_subIndex, processingInfo.timeOffset);
2826 if (processingInfo.action == Remove)
2827 m_runningAnimations.remove(currentAnimationName);
2832 m_animationsToProcess.clear();
2836 bool GraphicsLayerCA::isRunningTransformAnimation() const
2838 AnimationsMap::const_iterator end = m_runningAnimations.end();
2839 for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
2840 const Vector<LayerPropertyAnimation>& propertyAnimations = it->value;
2841 size_t numAnimations = propertyAnimations.size();
2842 for (size_t i = 0; i < numAnimations; ++i) {
2843 const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
2844 if (currAnimation.m_property == AnimatedPropertyTransform)
2851 void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation& caAnim, AnimatedPropertyID property, const String& animationName, int index, int subIndex, Seconds timeOffset)
2853 PlatformCALayer* layer = animatedLayer(property);
2856 caAnim.setBeginTime(CACurrentMediaTime() - timeOffset.seconds());
2858 String animationID = animationIdentifier(animationName, property, index, subIndex);
2860 layer->removeAnimationForKey(animationID);
2861 layer->addAnimationForKey(animationID, caAnim);
2863 if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
2864 for (auto& clone : *layerCloneMap) {
2865 // Skip immediate replicas, since they move with the original.
2866 if (m_replicaLayer && isReplicatedRootClone(clone.key))
2869 clone.value->removeAnimationForKey(animationID);
2870 clone.value->addAnimationForKey(animationID, caAnim);
2875 // Workaround for <rdar://problem/7311367>
2876 static void bug7311367Workaround(PlatformCALayer* transformLayer, const TransformationMatrix& transform)
2878 if (!transformLayer)
2881 TransformationMatrix caTransform = transform;
2882 caTransform.setM41(caTransform.m41() + 1);
2883 transformLayer->setTransform(caTransform);
2885 caTransform.setM41(caTransform.m41() - 1);
2886 transformLayer->setTransform(caTransform);
2889 bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index, int subIndex)
2891 PlatformCALayer* layer = animatedLayer(property);
2893 String animationID = animationIdentifier(animationName, property, index, subIndex);
2895 if (!layer->animationForKey(animationID))
2898 layer->removeAnimationForKey(animationID);
2899 bug7311367Workaround(m_structuralLayer.get(), m_transform);
2901 if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
2902 for (auto& clone : *layerCloneMap) {
2903 // Skip immediate replicas, since they move with the original.
2904 if (m_replicaLayer && isReplicatedRootClone(clone.key))
2907 clone.value->removeAnimationForKey(animationID);
2913 void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, int subIndex, Seconds timeOffset)
2915 PlatformCALayer* layer = animatedLayer(property);
2917 String animationID = animationIdentifier(animationName, property, index, subIndex);
2919 RefPtr<PlatformCAAnimation> curAnim = layer->animationForKey(animationID);
2923 // Animations on the layer are immutable, so we have to clone and modify.
2924 RefPtr<PlatformCAAnimation> newAnim = curAnim->copy();
2926 newAnim->setSpeed(0);
2927 newAnim->setTimeOffset(timeOffset.seconds());
2929 layer->addAnimationForKey(animationID, *newAnim); // This will replace the running animation.
2931 // Pause the animations on the clones too.
2932 if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
2933 for (auto& clone : *layerCloneMap) {
2934 // Skip immediate replicas, since they move with the original.
2935 if (m_replicaLayer && isReplicatedRootClone(clone.key))
2937 clone.value->addAnimationForKey(animationID, *newAnim);
2942 void GraphicsLayerCA::seekCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, int subIndex, Seconds timeOffset)
2944 // FIXME: this can be refactored a fair bit or merged with pauseCAAnimationOnLayer() with an operation flag.
2945 PlatformCALayer* layer = animatedLayer(property);
2947 String animationID = animationIdentifier(animationName, property, index, subIndex);
2949 RefPtr<PlatformCAAnimation> currentAnimation = layer->animationForKey(animationID);
2950 if (!currentAnimation)
2953 // Animations on the layer are immutable, so we have to clone and modify.
2954 RefPtr<PlatformCAAnimation> newAnim = currentAnimation->copy();
2956 newAnim->setTimeOffset(timeOffset.seconds());
2958 layer->addAnimationForKey(animationID, *newAnim); // This will replace the running animation.
2960 // Pause the animations on the clones too.
2961 if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
2962 for (auto& clone : *layerCloneMap) {
2963 // Skip immediate replicas, since they move with the original.
2964 if (m_replicaLayer && isReplicatedRootClone(clone.key))
2966 clone.value->addAnimationForKey(animationID, *newAnim);
2971 void GraphicsLayerCA::repaintLayerDirtyRects()
2973 if (m_needsFullRepaint) {
2974 ASSERT(!m_dirtyRects.size());
2975 m_layer->setNeedsDisplay();
2976 m_needsFullRepaint = false;
2980 for (auto& dirtyRect : m_dirtyRects)
2981 m_layer->setNeedsDisplayInRect(dirtyRect);
2983 m_dirtyRects.clear();
2986 void GraphicsLayerCA::updateContentsNeedsDisplay()
2988 if (m_contentsLayer)
2989 m_contentsLayer->setNeedsDisplay();
2992 bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, Seconds timeOffset)
2994 ASSERT(valueList.property() != AnimatedPropertyTransform && (!supportsAcceleratedFilterAnimations() || valueList.property() != AnimatedPropertyFilter));
2996 bool isKeyframe = valueList.size() > 2;
2999 bool additive = false;
3000 int animationIndex = 0;
3002 RefPtr<PlatformCAAnimation> caAnimation;
3005 caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive);
3006 valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get());
3008 if (animation->timingFunction()->isSpringTimingFunction())
3009 caAnimation = createSpringAnimation(animation, propertyIdToString(valueList.property()), additive);
3011 caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive);
3012 valuesOK = setAnimationEndpoints(valueList, animation, caAnimation.get());
3018 appendToUncommittedAnimations(LayerPropertyAnimation(caAnimation.releaseNonNull(), animationName, valueList.property(), animationIndex, 0, timeOffset));
3023 bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const TransformOperations* operations, const Animation* animation, const String& animationName, const FloatSize& boxSize, int animationIndex, Seconds timeOffset, bool isMatrixAnimation)
3025 TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : operations->operations().at(animationIndex)->type();
3026 bool additive = animationIndex > 0;
3027 bool isKeyframe = valueList.size() > 2;
3029 RefPtr<PlatformCAAnimation> caAnimation;
3030 bool validMatrices = true;
3032 caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive);
3033 validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
3035 if (animation->timingFunction()->isSpringTimingFunction())
3036 caAnimation = createSpringAnimation(animation, propertyIdToString(valueList.property()), additive);
3038 caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive);
3039 validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
3045 appendToUncommittedAnimations(LayerPropertyAnimation(caAnimation.releaseNonNull(), animationName, valueList.property(), animationIndex, 0, timeOffset));
3049 bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, Seconds timeOffset, const FloatSize& boxSize)
3051 ASSERT(valueList.property() == AnimatedPropertyTransform);
3053 bool hasBigRotation;
3054 int listIndex = validateTransformOperations(valueList, hasBigRotation);
3055 const TransformOperations* operations = (listIndex >= 0) ? &static_cast<const TransformAnimationValue&>(valueList.at(listIndex)).value() : 0;
3057 bool validMatrices = true;
3059 // If function lists don't match we do a matrix animation, otherwise we do a component hardware animation.
3060 bool isMatrixAnimation = listIndex < 0;
3061 int numAnimations = isMatrixAnimation ? 1 : operations->size();
3064 for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
3066 // QuartzCore on Windows expects animation lists to be applied in reverse order (<rdar://problem/9112233>).
3067 for (int animationIndex = numAnimations - 1; animationIndex >= 0; --animationIndex) {
3069 if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
3070 validMatrices = false;
3075 return validMatrices;
3078 bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const FilterOperation* operation, const Animation* animation, const String& animationName, int animationIndex, Seconds timeOffset)
3080 bool isKeyframe = valueList.size() > 2;
3082 FilterOperation::OperationType filterOp = operation->type();
3083 int numAnimatedProperties = PlatformCAFilters::numAnimatedFilterProperties(filterOp);
3085 // Each filter might need to animate multiple properties, each with their own keyPath. The keyPath is always of the form:
3087 // filter.filter_<animationIndex>.<filterPropertyName>
3089 // PlatformCAAnimation tells us how many properties each filter has and we iterate that many times and create an animation
3090 // for each. This internalFilterPropertyIndex gets passed to PlatformCAAnimation so it can properly create the property animation
3092 for (int internalFilterPropertyIndex = 0; internalFilterPropertyIndex < numAnimatedProperties; ++internalFilterPropertyIndex) {
3094 RefPtr<PlatformCAAnimation> caAnimation;
3095 String keyPath = String::format("filters.filter_%d.%s", animationIndex, PlatformCAFilters::animatedFilterPropertyName(filterOp, internalFilterPropertyIndex));
3098 caAnimation = createKeyframeAnimation(animation, keyPath, false);
3099 valuesOK = setFilterAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex, filterOp);
3101 caAnimation = createBasicAnimation(animation, keyPath, false);
3102 valuesOK = setFilterAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex);
3107 appendToUncommittedAnimations(LayerPropertyAnimation(caAnimation.releaseNonNull(), animationName, valueList.property(), animationIndex, internalFilterPropertyIndex, timeOffset));
3113 void GraphicsLayerCA::appendToUncommittedAnimations(LayerPropertyAnimation&& animation)
3115 // Since we're adding a new animation, make sure we clear any pending AnimationProcessingAction for this animation
3116 // as these are applied after we've committed new animations.
3117 m_animationsToProcess.remove(animation.m_name);
3119 m_uncomittedAnimations.append(WTFMove(animation));
3122 bool GraphicsLayerCA::createFilterAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, Seconds timeOffset)
3124 #if ENABLE(FILTERS_LEVEL_2)
3125 ASSERT(valueList.property() == AnimatedPropertyFilter || valueList.property() == AnimatedPropertyWebkitBackdropFilter);
3127 ASSERT(valueList.property() == AnimatedPropertyFilter);
3130 int listIndex = validateFilterOperations(valueList);
3134 const FilterOperations& operations = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
3135 // Make sure the platform layer didn't fallback to using software filter compositing instead.
3136 if (!filtersCanBeComposited(operations))
3139 int numAnimations = operations.size();
3141 // FIXME: We can't currently hardware animate shadows.
3142 for (int i = 0; i < numAnimations; ++i) {
3143 if (operations.at(i)->type() == FilterOperation::DROP_SHADOW)
3147 for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
3148 if (!appendToUncommittedAnimations(valueList, operations.operations().at(animationIndex).get(), animation, animationName, animationIndex, timeOffset))
3155 Ref<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, const String& keyPath, bool additive)
3157 auto basicAnim = createPlatformCAAnimation(PlatformCAAnimation::Basic, keyPath);
3158 setupAnimation(basicAnim.ptr(), anim, additive);
3162 Ref<PlatformCAAnimation> GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, const String& keyPath, bool additive)
3164 auto keyframeAnim = createPlatformCAAnimation(PlatformCAAnimation::Keyframe, keyPath);
3165 setupAnimation(keyframeAnim.ptr(), anim, additive);
3166 return keyframeAnim;
3169 Ref<PlatformCAAnimation> GraphicsLayerCA::createSpringAnimation(const Animation* anim, const String& keyPath, bool additive)
3171 auto basicAnim = createPlatformCAAnimation(PlatformCAAnimation::Spring, keyPath);
3172 setupAnimation(basicAnim.ptr(), anim, additive);
3176 void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive)
3178 double duration = anim->duration();
3180 duration = cAnimationAlmostZeroDuration;
3182 float repeatCount = anim->iterationCount();
3183 if (repeatCount == Animation::IterationCountInfinite)
3184 repeatCount = std::numeric_limits<float>::max();
3185 else if (anim->direction() == Animation::AnimationDirectionAlternate || anim->direction() == Animation::AnimationDirectionAlternateReverse)
3188 PlatformCAAnimation::FillModeType fillMode = PlatformCAAnimation::NoFillMode;
3189 switch (anim->fillMode()) {
3190 case AnimationFillModeNone:
3191 fillMode = PlatformCAAnimation::Forwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash.
3193 case AnimationFillModeBackwards:
3194 fillMode = PlatformCAAnimation::Both; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash.
3196 case AnimationFillModeForwards:
3197 fillMode = PlatformCAAnimation::Forwards;
3199 case AnimationFillModeBoth:
3200 fillMode = PlatformCAAnimation::Both;
3204 propertyAnim->setDuration(duration);
3205 propertyAnim->setRepeatCount(repeatCount);
3206 propertyAnim->setAutoreverses(anim->direction() == Animation::AnimationDirectionAlternate || anim->direction() == Animation::AnimationDirectionAlternateReverse);
3207 propertyAnim->setRemovedOnCompletion(false);
3208 propertyAnim->setAdditive(additive);
3209 propertyAnim->setFillMode(fillMode);
3212 const TimingFunction& GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue& animValue, const Animation& anim)
3214 if (animValue.timingFunction())
3215 return *animValue.timingFunction();
3216 if (anim.isTimingFunctionSet())
3217 return *anim.timingFunction();
3218 return CubicBezierTimingFunction::defaultTimingFunction();
3221 bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim)
3223 bool forwards = animation->directionIsForwards();
3225 unsigned fromIndex = !forwards;
3226 unsigned toIndex = forwards;
3228 switch (valueList.property()) {
3229 case AnimatedPropertyOpacity: {
3230 basicAnim->setFromValue(static_cast<const FloatAnimationValue&>(valueList.at(fromIndex)).value());
3231 basicAnim->setToValue(static_cast<const FloatAnimationValue&>(valueList.at(toIndex)).value());
3235 ASSERT_NOT_REACHED(); // we don't animate color yet
3239 // This codepath is used for 2-keyframe animations, so we still need to look in the start
3240 // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
3241 basicAnim->setTimingFunction(&timingFunctionForAnimationValue(valueList.at(0), *animation), !forwards);
3246 bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim)
3248 Vector<float> keyTimes;
3249 Vector<float> values;
3250 Vector<const TimingFunction*> timingFunctions;
3252 bool forwards = animation->directionIsForwards();
3254 for (unsigned i = 0; i < valueList.size(); ++i) {
3255 unsigned index = forwards ? i : (valueList.size() - i - 1);
3256 const AnimationValue& curValue = valueList.at(index);
3257 keyTimes.append(forwards ? curValue.keyTime() : (1 - curValue.keyTime()));
3259 switch (valueList.property()) {
3260 case AnimatedPropertyOpacity: {
3261 const FloatAnimationValue& floatValue = static_cast<const FloatAnimationValue&>(curValue);
3262 values.append(floatValue.value());
3266 ASSERT_NOT_REACHED(); // we don't animate color yet
3270 if (i < (valueList.size() - 1))
3271 timingFunctions.append(&timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation));
3274 keyframeAnim->setKeyTimes(keyTimes);
3275 keyframeAnim->setValues(values);
3276 keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
3281 bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const FloatSize& boxSize)
3283 ASSERT(valueList.size() == 2);
3285 bool forwards = animation->directionIsForwards();
3287 unsigned fromIndex = !forwards;
3288 unsigned toIndex = forwards;
3290 auto& startValue = static_cast<const TransformAnimationValue&>(valueList.at(fromIndex));
3291 auto& endValue = static_cast<const TransformAnimationValue&>(valueList.at(toIndex));
3293 if (isMatrixAnimation) {
3294 TransformationMatrix fromTransform, toTransform;
3295 startValue.value().apply(boxSize, fromTransform);
3296 endValue.value().apply(boxSize, toTransform);
3298 // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
3299 if (!fromTransform.isInvertible() || !toTransform.isInvertible())
3302 basicAnim->setFromValue(fromTransform);
3303 basicAnim->setToValue(toTransform);
3305 if (isTransformTypeNumber(transformOpType)) {
3307 getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue);
3308 basicAnim->setFromValue(fromValue);
3311 getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue);
3312 basicAnim->setToValue(toValue);
3313 } else if (isTransformTypeFloatPoint3D(transformOpType)) {
3314 FloatPoint3D fromValue;
3315 getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue);
3316 basicAnim->setFromValue(fromValue);
3318 FloatPoint3D toValue;
3319 getTransformFunctionValue(endValue.value().at(functionIndex), transformOpType, boxSize, toValue);
3320 basicAnim->setToValue(toValue);
3322 TransformationMatrix fromValue;
3323 getTransformFunctionValue(startValue.value().at(functionIndex), transformOpType, boxSize, fromValue);