Bug 1305325 - Part 14: Compose base values on the compositor. r?birtles
MozReview-Commit-ID: EWumBqQ82RT
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -300,16 +300,44 @@ KeyframeEffectReadOnly::UpdateProperties
CalculateCumulativeChangeHint(aStyleContext);
}
MarkCascadeNeedsUpdate();
RequestRestyle(EffectCompositor::RestyleType::Layer);
}
+/* static */ StyleAnimationValue
+KeyframeEffectReadOnly::CompositeValue(
+ nsCSSPropertyID aProperty,
+ const StyleAnimationValue& aValueToComposite,
+ const StyleAnimationValue& aUnderlyingValue,
+ CompositeOperation aCompositeOperation)
+{
+ switch (aCompositeOperation) {
+ case dom::CompositeOperation::Replace:
+ return aValueToComposite;
+ case dom::CompositeOperation::Add:
+ // So far nothing to do since we come to here only in case of missing
+ // keyframe, that means we have only to use the base value or the
+ // underlying value as the composited value.
+ // FIXME: Bug 1311620: Once we implement additive operation, we need to
+ // calculate it here.
+ return aUnderlyingValue;
+ case dom::CompositeOperation::Accumulate:
+ // FIXME: Bug 1291468: Implement accumulate operation.
+ MOZ_ASSERT_UNREACHABLE("Not implemented yet");
+ break;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unknown compisite operation type");
+ break;
+ }
+ return StyleAnimationValue();
+}
+
StyleAnimationValue
KeyframeEffectReadOnly::CompositeValue(
nsCSSPropertyID aProperty,
const RefPtr<AnimValuesStyleRule>& aAnimationRule,
const StyleAnimationValue& aValueToComposite,
CompositeOperation aCompositeOperation)
{
MOZ_ASSERT(mTarget, "CompositeValue should be called with target element");
@@ -345,36 +373,20 @@ KeyframeEffectReadOnly::CompositeValue(
result = EffectCompositor::GetBaseStyle(aProperty,
styleContext,
*mTarget->mElement,
mTarget->mPseudoType);
MOZ_ASSERT(!result.IsNull(), "The base style should be set");
SetNeedsBaseStyle(aProperty);
}
- switch (aCompositeOperation) {
- case dom::CompositeOperation::Add:
- // So far nothing to do since we come to here only in case of missing
- // keyframe, that means we just use the base value as the composited
- // value.
- // FIXME: Bug 1311620: Once we implement additive composition, we need to
- // use it here only if |aValueToCompose| is not null.
- return result;
- case dom::CompositeOperation::Accumulate:
- // FIXME: Bug 1291468: Implement accumulate operation.
- MOZ_ASSERT_UNREACHABLE("Not implemented yet");
- break;
- case dom::CompositeOperation::Replace:
- MOZ_ASSERT_UNREACHABLE("Replace should have already handled");
- break;
- default:
- MOZ_ASSERT_UNREACHABLE("Unknown compisite operation type");
- break;
- }
- return result;
+ return CompositeValue(aProperty,
+ aValueToComposite,
+ result,
+ aCompositeOperation);
}
void
KeyframeEffectReadOnly::ComposeStyle(
RefPtr<AnimValuesStyleRule>& aStyleRule,
const nsCSSPropertyIDSet& aPropertiesToSkip)
{
ComputedTiming computedTiming = GetComputedTiming();
--- a/dom/animation/KeyframeEffectReadOnly.h
+++ b/dom/animation/KeyframeEffectReadOnly.h
@@ -284,16 +284,26 @@ public:
// |aStyleContext| to resolve specified values.
void UpdateProperties(nsStyleContext* aStyleContext);
// Updates |aStyleRule| with the animation values produced by this
// AnimationEffect for the current time except any properties contained
// in |aPropertiesToSkip|.
void ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
const nsCSSPropertyIDSet& aPropertiesToSkip);
+
+ // Composite |aValueToComposite| on |aUnderlyingValue| with
+ // |aCompositeOperation|.
+ // Returns |aValueToComposite| if |aCompositeOperation| is Replace.
+ static StyleAnimationValue CompositeValue(
+ nsCSSPropertyID aProperty,
+ const StyleAnimationValue& aValueToComposite,
+ const StyleAnimationValue& aUnderlyingValue,
+ CompositeOperation aCompositeOperation);
+
// Returns true if at least one property is being animated on compositor.
bool IsRunningOnCompositor() const;
void SetIsRunningOnCompositor(nsCSSPropertyID aProperty, bool aIsRunning);
void ResetIsRunningOnCompositor();
// Returns true if this effect, applied to |aFrame|, contains properties
// that mean we shouldn't run transform compositor animations on this element.
//
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1413,16 +1413,21 @@ public:
AnimationArray& GetAnimations() { return mAnimations; }
InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
uint64_t GetAnimationGeneration() { return mAnimationGeneration; }
void SetAnimationGeneration(uint64_t aCount) { mAnimationGeneration = aCount; }
bool HasTransformAnimation() const;
+ StyleAnimationValue GetBaseAnimationStyle() const
+ {
+ return mBaseAnimationStyle;
+ }
+
/**
* Returns the local transform for this layer: either mTransform or,
* for shadow layers, GetShadowBaseTransform(), in either case with the
* pre- and post-scales applied.
*/
gfx::Matrix4x4 GetLocalTransform();
/**
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -571,28 +571,45 @@ AsyncCompositionManager::AlignFixedAndSt
AlignFixedAndStickyLayers(aTransformedSubtreeRoot, child, aTransformScrollId,
aPreviousTransformForRoot, newTransform, aFixedLayerMargins, aClipPartsCache);
}
}
return;
}
+struct StyleAnimationValueCompositePair {
+ StyleAnimationValue mValue;
+ dom::CompositeOperation mComposite;
+};
+
static StyleAnimationValue
-SampleValue(float aPortion, Animation& aAnimation,
- const StyleAnimationValue& aStart, const StyleAnimationValue& aEnd,
- const StyleAnimationValue& aLastValue, uint64_t aCurrentIteration)
+SampleValue(float aPortion, const Animation& aAnimation,
+ const StyleAnimationValueCompositePair& aStart,
+ const StyleAnimationValueCompositePair& aEnd,
+ const StyleAnimationValue& aLastValue,
+ uint64_t aCurrentIteration,
+ const StyleAnimationValue& aUnderlyingValue)
{
- NS_ASSERTION(aStart.GetUnit() == aEnd.GetUnit() ||
- aStart.GetUnit() == StyleAnimationValue::eUnit_None ||
- aEnd.GetUnit() == StyleAnimationValue::eUnit_None,
+ NS_ASSERTION(aStart.mValue.GetUnit() == aEnd.mValue.GetUnit() ||
+ aStart.mValue.GetUnit() == StyleAnimationValue::eUnit_None ||
+ aEnd.mValue.GetUnit() == StyleAnimationValue::eUnit_None,
"Must have same unit");
- StyleAnimationValue startValue = aStart;
- StyleAnimationValue endValue = aEnd;
+ StyleAnimationValue startValue =
+ dom::KeyframeEffectReadOnly::CompositeValue(aAnimation.property(),
+ aStart.mValue,
+ aUnderlyingValue,
+ aStart.mComposite);
+ StyleAnimationValue endValue =
+ dom::KeyframeEffectReadOnly::CompositeValue(aAnimation.property(),
+ aEnd.mValue,
+ aUnderlyingValue,
+ aEnd.mComposite);
+
// Iteration composition for accumulate
if (static_cast<dom::IterationCompositeOperation>
(aAnimation.iterationComposite()) ==
dom::IterationCompositeOperation::Accumulate &&
aCurrentIteration > 0) {
// FIXME: Bug 1293492: Add a utility function to calculate both of
// below StyleAnimationValues.
startValue =
@@ -683,17 +700,19 @@ SampleAnimations(Layer* aLayer, TimeStam
{
AnimationArray& animations = layer->GetAnimations();
if (animations.IsEmpty()) {
return;
}
InfallibleTArray<AnimData>& animationData = layer->GetAnimationData();
- StyleAnimationValue interpolatedValue;
+ StyleAnimationValue animationValue = layer->GetBaseAnimationStyle();
+ bool hasInEffectAnimations = false;
+
// Process in order, since later animations override earlier ones.
for (size_t i = 0, iEnd = animations.Length(); i < iEnd; ++i) {
Animation& animation = animations[i];
AnimData& animData = animationData[i];
activeAnimations = true;
MOZ_ASSERT(!animation.startTime().IsNull() ||
@@ -740,23 +759,32 @@ SampleAnimations(Layer* aLayer, TimeStam
(computedTiming.mProgress.Value() - segment->startPortion()) /
(segment->endPortion() - segment->startPortion());
double portion =
ComputedTimingFunction::GetPortion(animData.mFunctions[segmentIndex],
positionInSegment,
computedTiming.mBeforeFlag);
+ StyleAnimationValueCompositePair from {
+ animData.mStartValues[segmentIndex],
+ static_cast<dom::CompositeOperation>(segment->startComposite())
+ };
+ StyleAnimationValueCompositePair to {
+ animData.mEndValues[segmentIndex],
+ static_cast<dom::CompositeOperation>(segment->endComposite())
+ };
// interpolate the property
- interpolatedValue =
- SampleValue(portion, animation,
- animData.mStartValues[segmentIndex],
- animData.mEndValues[segmentIndex],
- animData.mEndValues.LastElement(),
- computedTiming.mCurrentIteration);
+ animationValue = SampleValue(portion,
+ animation,
+ from, to,
+ animData.mEndValues.LastElement(),
+ computedTiming.mCurrentIteration,
+ animationValue);
+ hasInEffectAnimations = true;
}
#ifdef DEBUG
// Sanity check that all of animation data are the same.
const AnimationData& lastData = animations.LastElement().data();
for (const Animation& animation : animations) {
const AnimationData& data = animation.data();
MOZ_ASSERT(data.type() == lastData.type(),
@@ -772,22 +800,23 @@ SampleAnimations(Layer* aLayer, TimeStam
transformData.transformOrigin() ==
lastTransformData.transformOrigin() &&
transformData.bounds() == lastTransformData.bounds() &&
transformData.appUnitsPerDevPixel() ==
lastTransformData.appUnitsPerDevPixel(),
"All of members of TransformData should be the same");
}
#endif
- if (!interpolatedValue.IsNull()) {
+ // If all of animations are
+ if (hasInEffectAnimations) {
Animation& animation = animations.LastElement();
ApplyAnimatedValue(layer,
animation.property(),
animation.data(),
- interpolatedValue);
+ animationValue);
}
});
return activeAnimations;
}
static bool
SampleAPZAnimations(const LayerMetricsWrapper& aLayer, TimeStamp aSampleTime)
{
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -165,16 +165,18 @@ union BaseAnimationStyle {
Animatable;
};
struct AnimationSegment {
Animatable startState;
Animatable endState;
float startPortion;
float endPortion;
+ uint8_t startComposite;
+ uint8_t endComposite;
TimingFunction sampleFn;
};
// Transforms need extra information to correctly convert the list of transform
// functions to a Matrix4x4 that can be applied directly to the layer.
struct TransformData {
// the origin of the frame being transformed in app units
nsPoint origin;
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -532,16 +532,20 @@ AddAnimationForProperty(nsIFrame* aFrame
animSegment->startState());
SetAnimatable(aProperty.mProperty,
segment.mToValue,
aFrame, refBox,
animSegment->endState());
animSegment->startPortion() = segment.mFromKey;
animSegment->endPortion() = segment.mToKey;
+ animSegment->startComposite() =
+ static_cast<uint8_t>(segment.mFromComposite);
+ animSegment->endComposite() =
+ static_cast<uint8_t>(segment.mToComposite);
animSegment->sampleFn() = ToTimingFunction(segment.mTimingFunction);
}
}
static void
AddAnimationsForProperty(nsIFrame* aFrame, nsCSSPropertyID aProperty,
nsTArray<RefPtr<dom::Animation>>& aAnimations,
Layer* aLayer, AnimationData& aData,