Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (276965 => 276966)
--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp 2021-05-04 17:14:36 UTC (rev 276965)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp 2021-05-04 17:14:42 UTC (rev 276966)
@@ -1047,6 +1047,31 @@
return index != notFound && m_animations[index].m_playState == PlayState::Playing;
}
+static bool timingFunctionIsCubicTimingFunctionWithYValueOutOfRange(const TimingFunction* timingFunction)
+{
+ if (!is<CubicBezierTimingFunction>(timingFunction))
+ return false;
+
+ auto yValueIsOutOfRange = [](double y) -> bool {
+ return y < 0 || y > 1;
+ };
+
+ auto& cubicBezierTimingFunction = downcast<CubicBezierTimingFunction>(*timingFunction);
+ return yValueIsOutOfRange(cubicBezierTimingFunction.y1()) || yValueIsOutOfRange(cubicBezierTimingFunction.y2());
+}
+
+static bool keyframeValueListHasSingleIntervalWithLinearOrEquivalentTimingFunction(const KeyframeValueList& valueList)
+{
+ if (valueList.size() != 2)
+ return false;
+
+ auto* timingFunction = valueList.at(0).timingFunction();
+ if (!timingFunction || is<LinearTimingFunction>(timingFunction))
+ return true;
+
+ return is<CubicBezierTimingFunction>(timingFunction) && downcast<CubicBezierTimingFunction>(*timingFunction).isLinear();
+}
+
static bool animationCanBeAccelerated(const KeyframeValueList& valueList, const Animation* anim)
{
if (anim->playbackRate() != 1 || !anim->directionIsForwards())
@@ -1070,21 +1095,29 @@
if (!animationCanBeAccelerated(valueList, anim))
return false;
+ bool keyframesShouldUseAnimationWideTimingFunction = false;
+ // Core Animation clips values outside of the [0-1] range for animation-wide cubic timing functions.
+ if (timingFunctionIsCubicTimingFunctionWithYValueOutOfRange(anim->timingFunction())) {
+ if (!keyframeValueListHasSingleIntervalWithLinearOrEquivalentTimingFunction(valueList))
+ return false;
+ keyframesShouldUseAnimationWideTimingFunction = true;
+ }
+
bool createdAnimations = false;
if (animatedPropertyIsTransformOrRelated(valueList.property()))
- createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, Seconds { timeOffset }, boxSize);
+ createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, Seconds { timeOffset }, boxSize, keyframesShouldUseAnimationWideTimingFunction);
else if (valueList.property() == AnimatedPropertyFilter) {
if (supportsAcceleratedFilterAnimations())
- createdAnimations = createFilterAnimationsFromKeyframes(valueList, anim, animationName, Seconds { timeOffset });
+ createdAnimations = createFilterAnimationsFromKeyframes(valueList, anim, animationName, Seconds { timeOffset }, keyframesShouldUseAnimationWideTimingFunction);
}
#if ENABLE(FILTERS_LEVEL_2)
else if (valueList.property() == AnimatedPropertyWebkitBackdropFilter) {
if (supportsAcceleratedFilterAnimations())
- createdAnimations = createFilterAnimationsFromKeyframes(valueList, anim, animationName, Seconds { timeOffset });
+ createdAnimations = createFilterAnimationsFromKeyframes(valueList, anim, animationName, Seconds { timeOffset }, keyframesShouldUseAnimationWideTimingFunction);
}
#endif
else
- createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, Seconds { timeOffset });
+ createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, Seconds { timeOffset }, keyframesShouldUseAnimationWideTimingFunction);
if (createdAnimations)
noteLayerPropertyChanged(AnimationChanged | CoverageRectChanged);
@@ -3261,7 +3294,7 @@
return list.size() > 1;
}
-bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, Seconds timeOffset)
+bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, Seconds timeOffset, bool keyframesShouldUseAnimationWideTimingFunction)
{
ASSERT(!animatedPropertyIsTransformOrRelated(valueList.property()) && (!supportsAcceleratedFilterAnimations() || valueList.property() != AnimatedPropertyFilter));
@@ -3273,13 +3306,13 @@
RefPtr<PlatformCAAnimation> caAnimation;
if (isKeyframe(valueList)) {
- caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive);
- valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get());
+ caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive, keyframesShouldUseAnimationWideTimingFunction);
+ valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get(), keyframesShouldUseAnimationWideTimingFunction);
} else {
if (animation->timingFunction()->isSpringTimingFunction())
- caAnimation = createSpringAnimation(animation, propertyIdToString(valueList.property()), additive);
+ caAnimation = createSpringAnimation(animation, propertyIdToString(valueList.property()), additive, keyframesShouldUseAnimationWideTimingFunction);
else
- caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive);
+ caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive, keyframesShouldUseAnimationWideTimingFunction);
valuesOK = setAnimationEndpoints(valueList, animation, caAnimation.get());
}
@@ -3291,7 +3324,7 @@
return true;
}
-bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const TransformOperations* operations, const Animation* animation, const String& animationName, const FloatSize& boxSize, int animationIndex, Seconds timeOffset, bool isMatrixAnimation)
+bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const TransformOperations* operations, const Animation* animation, const String& animationName, const FloatSize& boxSize, int animationIndex, Seconds timeOffset, bool isMatrixAnimation, bool keyframesShouldUseAnimationWideTimingFunction)
{
TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : operations->operations().at(animationIndex)->type();
@@ -3298,13 +3331,13 @@
RefPtr<PlatformCAAnimation> caAnimation;
bool validMatrices = true;
if (isKeyframe(valueList)) {
- caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), false);
- validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
+ caAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), false, keyframesShouldUseAnimationWideTimingFunction);
+ validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize, keyframesShouldUseAnimationWideTimingFunction);
} else {
if (animation->timingFunction()->isSpringTimingFunction())
- caAnimation = createSpringAnimation(animation, propertyIdToString(valueList.property()), false);
+ caAnimation = createSpringAnimation(animation, propertyIdToString(valueList.property()), false, keyframesShouldUseAnimationWideTimingFunction);
else
- caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), false);
+ caAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), false, keyframesShouldUseAnimationWideTimingFunction);
validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
}
@@ -3315,7 +3348,7 @@
return true;
}
-bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, Seconds timeOffset, const FloatSize& boxSize)
+bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, Seconds timeOffset, const FloatSize& boxSize, bool keyframesShouldUseAnimationWideTimingFunction)
{
ASSERT(animatedPropertyIsTransformOrRelated(valueList.property()));
@@ -3330,7 +3363,7 @@
int numAnimations = isMatrixAnimation ? 1 : operations->size();
for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
- if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
+ if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation, keyframesShouldUseAnimationWideTimingFunction)) {
validMatrices = false;
break;
}
@@ -3339,7 +3372,7 @@
return validMatrices;
}
-bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const FilterOperation* operation, const Animation* animation, const String& animationName, int animationIndex, Seconds timeOffset)
+bool GraphicsLayerCA::appendToUncommittedAnimations(const KeyframeValueList& valueList, const FilterOperation* operation, const Animation* animation, const String& animationName, int animationIndex, Seconds timeOffset, bool keyframesShouldUseAnimationWideTimingFunction)
{
FilterOperation::OperationType filterOp = operation->type();
int numAnimatedProperties = PlatformCAFilters::numAnimatedFilterProperties(filterOp);
@@ -3357,10 +3390,10 @@
String keyPath = makeString("filters.filter_", animationIndex, '.', PlatformCAFilters::animatedFilterPropertyName(filterOp, internalFilterPropertyIndex));
if (isKeyframe(valueList)) {
- caAnimation = createKeyframeAnimation(animation, keyPath, false);
- valuesOK = setFilterAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex, filterOp);
+ caAnimation = createKeyframeAnimation(animation, keyPath, false, keyframesShouldUseAnimationWideTimingFunction);
+ valuesOK = setFilterAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex, filterOp, keyframesShouldUseAnimationWideTimingFunction);
} else {
- caAnimation = createBasicAnimation(animation, keyPath, false);
+ caAnimation = createBasicAnimation(animation, keyPath, false, keyframesShouldUseAnimationWideTimingFunction);
valuesOK = setFilterAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, internalFilterPropertyIndex);
}
@@ -3372,7 +3405,7 @@
return true;
}
-bool GraphicsLayerCA::createFilterAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, Seconds timeOffset)
+bool GraphicsLayerCA::createFilterAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, Seconds timeOffset, bool keyframesShouldUseAnimationWideTimingFunction)
{
#if ENABLE(FILTERS_LEVEL_2)
ASSERT(valueList.property() == AnimatedPropertyFilter || valueList.property() == AnimatedPropertyWebkitBackdropFilter);
@@ -3398,7 +3431,7 @@
}
for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
- if (!appendToUncommittedAnimations(valueList, operations.operations().at(animationIndex).get(), animation, animationName, animationIndex, timeOffset))
+ if (!appendToUncommittedAnimations(valueList, operations.operations().at(animationIndex).get(), animation, animationName, animationIndex, timeOffset, keyframesShouldUseAnimationWideTimingFunction))
return false;
}
@@ -3405,28 +3438,28 @@
return true;
}
-Ref<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, const String& keyPath, bool additive)
+Ref<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, const String& keyPath, bool additive, bool keyframesShouldUseAnimationWideTimingFunction)
{
auto basicAnim = createPlatformCAAnimation(PlatformCAAnimation::Basic, keyPath);
- setupAnimation(basicAnim.ptr(), anim, additive);
+ setupAnimation(basicAnim.ptr(), anim, additive, keyframesShouldUseAnimationWideTimingFunction);
return basicAnim;
}
-Ref<PlatformCAAnimation> GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, const String& keyPath, bool additive)
+Ref<PlatformCAAnimation> GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, const String& keyPath, bool additive, bool keyframesShouldUseAnimationWideTimingFunction)
{
auto keyframeAnim = createPlatformCAAnimation(PlatformCAAnimation::Keyframe, keyPath);
- setupAnimation(keyframeAnim.ptr(), anim, additive);
+ setupAnimation(keyframeAnim.ptr(), anim, additive, keyframesShouldUseAnimationWideTimingFunction);
return keyframeAnim;
}
-Ref<PlatformCAAnimation> GraphicsLayerCA::createSpringAnimation(const Animation* anim, const String& keyPath, bool additive)
+Ref<PlatformCAAnimation> GraphicsLayerCA::createSpringAnimation(const Animation* anim, const String& keyPath, bool additive, bool keyframesShouldUseAnimationWideTimingFunction)
{
auto basicAnim = createPlatformCAAnimation(PlatformCAAnimation::Spring, keyPath);
- setupAnimation(basicAnim.ptr(), anim, additive);
+ setupAnimation(basicAnim.ptr(), anim, additive, keyframesShouldUseAnimationWideTimingFunction);
return basicAnim;
}
-void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive)
+void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive, bool keyframesShouldUseAnimationWideTimingFunction)
{
double duration = anim->duration();
if (duration <= 0)
@@ -3465,13 +3498,13 @@
// A CSS Transition is the only scenario where Animation::property() will have
// its mode set to SingleProperty. In this case, we don't set the animation-wide
// timing function to work around a Core Animation limitation.
- if (anim->property().mode != Animation::TransitionMode::SingleProperty)
+ if (!keyframesShouldUseAnimationWideTimingFunction)
propertyAnim->setTimingFunction(anim->timingFunction());
}
-const TimingFunction& GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue& animValue, const Animation& anim)
+const TimingFunction& GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue& animValue, const Animation& anim, bool keyframesShouldUseAnimationWideTimingFunction)
{
- if (anim.property().mode == Animation::TransitionMode::SingleProperty && anim.timingFunction()) {
+ if (keyframesShouldUseAnimationWideTimingFunction && anim.timingFunction()) {
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=215918
// A CSS Transition is the only scenario where Animation::property() will have
// its mode set to SingleProperty. In this case, we chose not to set set the
@@ -3507,7 +3540,7 @@
return true;
}
-bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim)
+bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, bool keyframesShouldUseAnimationWideTimingFunction)
{
Vector<float> keyTimes;
Vector<float> values;
@@ -3532,7 +3565,7 @@
}
if (i < (valueList.size() - 1))
- timingFunctions.append(&timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation));
+ timingFunctions.append(&timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation, keyframesShouldUseAnimationWideTimingFunction));
}
keyframeAnim->setKeyTimes(keyTimes);
@@ -3600,7 +3633,7 @@
return true;
}
-bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const FloatSize& boxSize)
+bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const FloatSize& boxSize, bool keyframesShouldUseAnimationWideTimingFunction)
{
Vector<float> keyTimes;
Vector<float> floatValues;
@@ -3645,7 +3678,7 @@
}
if (i < (valueList.size() - 1))
- timingFunctions.append(&timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation));
+ timingFunctions.append(&timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation, keyframesShouldUseAnimationWideTimingFunction));
}
keyframeAnim->setKeyTimes(keyTimes);
@@ -3702,7 +3735,7 @@
return true;
}
-bool GraphicsLayerCA::setFilterAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, int internalFilterPropertyIndex, FilterOperation::OperationType filterOp)
+bool GraphicsLayerCA::setFilterAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, int internalFilterPropertyIndex, FilterOperation::OperationType filterOp, bool keyframesShouldUseAnimationWideTimingFunction)
{
Vector<float> keyTimes;
Vector<RefPtr<FilterOperation>> values;
@@ -3725,7 +3758,7 @@
}
if (i < (valueList.size() - 1))
- timingFunctions.append(&timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation));
+ timingFunctions.append(&timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), *animation, keyframesShouldUseAnimationWideTimingFunction));
}
keyframeAnim->setKeyTimes(keyTimes);
Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h (276965 => 276966)
--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h 2021-05-04 17:14:36 UTC (rev 276965)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h 2021-05-04 17:14:42 UTC (rev 276966)
@@ -255,26 +255,26 @@
LayerMap* animatedLayerClones(AnimatedPropertyID) const;
static void clearClones(LayerMap&);
- bool createAnimationFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, Seconds timeOffset);
- bool createTransformAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, Seconds timeOffset, const FloatSize& boxSize);
- bool createFilterAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, Seconds timeOffset);
+ bool createAnimationFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, Seconds timeOffset, bool keyframesShouldUseAnimationWideTimingFunction);
+ bool createTransformAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, Seconds timeOffset, const FloatSize& boxSize, bool keyframesShouldUseAnimationWideTimingFunction);
+ bool createFilterAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, Seconds timeOffset, bool keyframesShouldUseAnimationWideTimingFunction);
// Return autoreleased animation (use RetainPtr?)
- Ref<PlatformCAAnimation> createBasicAnimation(const Animation*, const String& keyPath, bool additive);
- Ref<PlatformCAAnimation> createKeyframeAnimation(const Animation*, const String&, bool additive);
- Ref<PlatformCAAnimation> createSpringAnimation(const Animation*, const String&, bool additive);
- void setupAnimation(PlatformCAAnimation*, const Animation*, bool additive);
+ Ref<PlatformCAAnimation> createBasicAnimation(const Animation*, const String& keyPath, bool additive, bool keyframesShouldUseAnimationWideTimingFunction);
+ Ref<PlatformCAAnimation> createKeyframeAnimation(const Animation*, const String&, bool additive, bool keyframesShouldUseAnimationWideTimingFunction);
+ Ref<PlatformCAAnimation> createSpringAnimation(const Animation*, const String&, bool additive, bool keyframesShouldUseAnimationWideTimingFunction);
+ void setupAnimation(PlatformCAAnimation*, const Animation*, bool additive, bool keyframesShouldUseAnimationWideTimingFunction);
- const TimingFunction& timingFunctionForAnimationValue(const AnimationValue&, const Animation&);
+ const TimingFunction& timingFunctionForAnimationValue(const AnimationValue&, const Animation&, bool keyframesShouldUseAnimationWideTimingFunction);
bool setAnimationEndpoints(const KeyframeValueList&, const Animation*, PlatformCAAnimation*);
- bool setAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*);
+ bool setAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, bool keyframesShouldUseAnimationWideTimingFunction);
bool setTransformAnimationEndpoints(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const FloatSize& boxSize);
- bool setTransformAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const FloatSize& boxSize);
+ bool setTransformAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const FloatSize& boxSize, bool keyframesShouldUseAnimationWideTimingFunction);
bool setFilterAnimationEndpoints(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, int internalFilterPropertyIndex);
- bool setFilterAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, int internalFilterPropertyIndex, FilterOperation::OperationType);
+ bool setFilterAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, int internalFilterPropertyIndex, FilterOperation::OperationType, bool keyframesShouldUseAnimationWideTimingFunction);
bool isRunningTransformAnimation() const;
@@ -511,8 +511,8 @@
moveOrCopyAnimations(Copy, fromLayer, toLayer);
}
- bool appendToUncommittedAnimations(const KeyframeValueList&, const TransformOperations*, const Animation*, const String& animationName, const FloatSize& boxSize, int animationIndex, Seconds timeOffset, bool isMatrixAnimation);
- bool appendToUncommittedAnimations(const KeyframeValueList&, const FilterOperation*, const Animation*, const String& animationName, int animationIndex, Seconds timeOffset);
+ bool appendToUncommittedAnimations(const KeyframeValueList&, const TransformOperations*, const Animation*, const String& animationName, const FloatSize& boxSize, int animationIndex, Seconds timeOffset, bool isMatrixAnimation, bool keyframesShouldUseAnimationWideTimingFunction);
+ bool appendToUncommittedAnimations(const KeyframeValueList&, const FilterOperation*, const Animation*, const String& animationName, int animationIndex, Seconds timeOffset, bool keyframesShouldUseAnimationWideTimingFunction);
enum LayerChange : uint64_t {
NoChange = 0,