author | peter chang <pchang@mozilla.com> |
Thu, 26 Jan 2017 15:04:16 +0800 | |
changeset 341001 | 61dc0a725d0fa21b5d3472ee5741c8bd3682004f |
parent 341000 | 4fe2c1b809e8191a6d00c86f37d98e5ca04c2d81 |
child 341002 | 8c4afac0dcbad4a3ed5694e8df0d4171a5d8c148 |
push id | 86615 |
push user | kwierso@gmail.com |
push date | Tue, 07 Feb 2017 01:52:08 +0000 |
treeherder | mozilla-inbound@f0453084d86e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | hiro |
bugs | 1332211 |
milestone | 54.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/layers/AnimationHelper.cpp +++ b/gfx/layers/AnimationHelper.cpp @@ -1,24 +1,201 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AnimationHelper.h" #include "mozilla/ComputedTimingFunction.h" // for ComputedTimingFunction -#include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for FillMode -#include "mozilla/layers/LayerAnimationUtils.h" // for TimingFunctionToComputedTimingFunction -#include "mozilla/layers/LayersMessages.h" // for TransformFunction, etc +#include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for dom::FillMode +#include "mozilla/dom/KeyframeEffectBinding.h" // for dom::IterationComposite +#include "mozilla/dom/KeyframeEffectReadOnly.h" // for dom::KeyFrameEffectReadOnly +#include "mozilla/layers/LayerAnimationUtils.h" // for TimingFunctionToComputedTimingFunction +#include "mozilla/layers/LayersMessages.h" // for TransformFunction, etc #include "mozilla/StyleAnimationValue.h" // for StyleAnimationValue, etc namespace mozilla { namespace layers { +struct StyleAnimationValueCompositePair { + StyleAnimationValue mValue; + dom::CompositeOperation mComposite; +}; + +static StyleAnimationValue +SampleValue(float aPortion, const layers::Animation& aAnimation, + const StyleAnimationValueCompositePair& aStart, + const StyleAnimationValueCompositePair& aEnd, + const StyleAnimationValue& aLastValue, + uint64_t aCurrentIteration, + const StyleAnimationValue& aUnderlyingValue) +{ + NS_ASSERTION(aStart.mValue.IsNull() || aEnd.mValue.IsNull() || + aStart.mValue.GetUnit() == aEnd.mValue.GetUnit(), + "Must have same unit"); + + 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 = + StyleAnimationValue::Accumulate(aAnimation.property(), + aLastValue.IsNull() + ? aUnderlyingValue + : aLastValue, + Move(startValue), + aCurrentIteration); + endValue = + StyleAnimationValue::Accumulate(aAnimation.property(), + aLastValue.IsNull() + ? aUnderlyingValue + : aLastValue, + Move(endValue), + aCurrentIteration); + } + + StyleAnimationValue interpolatedValue; + // This should never fail because we only pass transform and opacity values + // to the compositor and they should never fail to interpolate. + DebugOnly<bool> uncomputeResult = + StyleAnimationValue::Interpolate(aAnimation.property(), + startValue, endValue, + aPortion, interpolatedValue); + MOZ_ASSERT(uncomputeResult, "could not uncompute value"); + return interpolatedValue; +} + +bool +AnimationHelper::SampleAnimationForEachNode(TimeStamp aPoint, + AnimationArray& aAnimations, + InfallibleTArray<AnimData>& aAnimationData, + StyleAnimationValue& aAnimationValue, + bool& aHasInEffectAnimations) +{ + bool activeAnimations = false; + + if (aAnimations.IsEmpty()) { + return activeAnimations; + } + + // Process in order, since later aAnimations override earlier ones. + for (size_t i = 0, iEnd = aAnimations.Length(); i < iEnd; ++i) { + Animation& animation = aAnimations[i]; + AnimData& animData = aAnimationData[i]; + + activeAnimations = true; + + MOZ_ASSERT(!animation.startTime().IsNull() || + animation.isNotPlaying(), + "Failed to resolve start time of play-pending animations"); + // If the animation is not currently playing , e.g. paused or + // finished, then use the hold time to stay at the same position. + TimeDuration elapsedDuration = animation.isNotPlaying() + ? animation.holdTime() + : (aPoint - animation.startTime()) + .MultDouble(animation.playbackRate()); + TimingParams timing; + timing.mDuration.emplace(animation.duration()); + timing.mDelay = animation.delay(); + timing.mEndDelay = animation.endDelay(); + timing.mIterations = animation.iterations(); + timing.mIterationStart = animation.iterationStart(); + timing.mDirection = + static_cast<dom::PlaybackDirection>(animation.direction()); + timing.mFill = static_cast<dom::FillMode>(animation.fillMode()); + timing.mFunction = + AnimationUtils::TimingFunctionToComputedTimingFunction( + animation.easingFunction()); + + ComputedTiming computedTiming = + dom::AnimationEffectReadOnly::GetComputedTimingAt( + Nullable<TimeDuration>(elapsedDuration), timing, + animation.playbackRate()); + + if (computedTiming.mProgress.IsNull()) { + continue; + } + + uint32_t segmentIndex = 0; + size_t segmentSize = animation.segments().Length(); + AnimationSegment* segment = animation.segments().Elements(); + while (segment->endPortion() < computedTiming.mProgress.Value() && + segmentIndex < segmentSize - 1) { + ++segment; + ++segmentIndex; + } + + double positionInSegment = + (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 + aAnimationValue = SampleValue(portion, + animation, + from, to, + animData.mEndValues.LastElement(), + computedTiming.mCurrentIteration, + aAnimationValue); + aHasInEffectAnimations = true; + } + +#ifdef DEBUG + // Sanity check that all of animation data are the same. + const AnimationData& lastData = aAnimations.LastElement().data(); + for (const Animation& animation : aAnimations) { + const AnimationData& data = animation.data(); + MOZ_ASSERT(data.type() == lastData.type(), + "The type of AnimationData should be the same"); + if (data.type() == AnimationData::Tnull_t) { + continue; + } + + MOZ_ASSERT(data.type() == AnimationData::TTransformData); + const TransformData& transformData = data.get_TransformData(); + const TransformData& lastTransformData = lastData.get_TransformData(); + MOZ_ASSERT(transformData.origin() == lastTransformData.origin() && + transformData.transformOrigin() == + lastTransformData.transformOrigin() && + transformData.bounds() == lastTransformData.bounds() && + transformData.appUnitsPerDevPixel() == + lastTransformData.appUnitsPerDevPixel(), + "All of members of TransformData should be the same"); + } +#endif + return activeAnimations; +} + static inline void SetCSSAngle(const CSSAngle& aAngle, nsCSSValue& aValue) { aValue.SetFloatValue(aAngle.value(), nsCSSUnit(aAngle.unit())); } static nsCSSValueSharedList* CreateCSSValueList(const InfallibleTArray<TransformFunction>& aFunctions)
--- a/gfx/layers/AnimationHelper.h +++ b/gfx/layers/AnimationHelper.h @@ -22,16 +22,24 @@ struct AnimData { InfallibleTArray<mozilla::StyleAnimationValue> mStartValues; InfallibleTArray<mozilla::StyleAnimationValue> mEndValues; InfallibleTArray<Maybe<mozilla::ComputedTimingFunction>> mFunctions; }; class AnimationHelper { public: + + static bool + SampleAnimationForEachNode(TimeStamp aPoint, + AnimationArray& aAnimations, + InfallibleTArray<AnimData>& aAnimationData, + StyleAnimationValue& aAnimationValue, + bool& aHasInEffectAnimations); + static void SetAnimations(AnimationArray& aAnimations, InfallibleTArray<AnimData>& aAnimData, StyleAnimationValue& aBaseAnimationStyle); }; } // namespace layers } // namespace mozilla
--- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -9,19 +9,16 @@ #include "apz/src/AsyncPanZoomController.h" #include "FrameMetrics.h" // for FrameMetrics #include "LayerManagerComposite.h" // for LayerManagerComposite, etc #include "Layers.h" // for Layer, ContainerLayer, etc #include "gfxPoint.h" // for gfxPoint, gfxSize #include "gfxPrefs.h" // for gfxPrefs #include "mozilla/StyleAnimationValue.h" // for StyleAnimationValue, etc #include "mozilla/WidgetUtils.h" // for ComputeTransformForRotation -#include "mozilla/dom/KeyframeEffectReadOnly.h" -#include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for dom::FillMode -#include "mozilla/dom/KeyframeEffectBinding.h" // for dom::IterationComposite #include "mozilla/gfx/BaseRect.h" // for BaseRect #include "mozilla/gfx/Point.h" // for RoundedToInt, PointTyped #include "mozilla/gfx/Rect.h" // for RoundedToInt, RectTyped #include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor #include "mozilla/layers/AnimationHelper.h" #include "mozilla/layers/APZUtils.h" // for CompleteAsyncTransform #include "mozilla/layers/Compositor.h" // for Compositor #include "mozilla/layers/CompositorBridgeParent.h" // for CompositorBridgeParent, etc @@ -572,78 +569,16 @@ AsyncCompositionManager::AlignFixedAndSt AlignFixedAndStickyLayers(aTransformedSubtreeRoot, child, aTransformScrollId, aPreviousTransformForRoot, newTransform, aFixedLayerMargins, aClipPartsCache); } } return; } -struct StyleAnimationValueCompositePair { - StyleAnimationValue mValue; - dom::CompositeOperation mComposite; -}; - -static StyleAnimationValue -SampleValue(float aPortion, const Animation& aAnimation, - const StyleAnimationValueCompositePair& aStart, - const StyleAnimationValueCompositePair& aEnd, - const StyleAnimationValue& aLastValue, - uint64_t aCurrentIteration, - const StyleAnimationValue& aUnderlyingValue) -{ - NS_ASSERTION(aStart.mValue.IsNull() || aEnd.mValue.IsNull() || - aStart.mValue.GetUnit() == aEnd.mValue.GetUnit(), - "Must have same unit"); - - 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 = - StyleAnimationValue::Accumulate(aAnimation.property(), - aLastValue.IsNull() - ? aUnderlyingValue - : aLastValue, - Move(startValue), - aCurrentIteration); - endValue = - StyleAnimationValue::Accumulate(aAnimation.property(), - aLastValue.IsNull() - ? aUnderlyingValue - : aLastValue, - Move(endValue), - aCurrentIteration); - } - - StyleAnimationValue interpolatedValue; - // This should never fail because we only pass transform and opacity values - // to the compositor and they should never fail to interpolate. - DebugOnly<bool> uncomputeResult = - StyleAnimationValue::Interpolate(aAnimation.property(), - startValue, endValue, - aPortion, interpolatedValue); - MOZ_ASSERT(uncomputeResult, "could not uncompute value"); - return interpolatedValue; -} - static void ApplyAnimatedValue(Layer* aLayer, nsCSSPropertyID aProperty, const AnimationData& aAnimationData, const StyleAnimationValue& aValue) { HostLayer* layerCompositor = aLayer->AsHostLayer(); switch (aProperty) { @@ -689,144 +624,32 @@ ApplyAnimatedValue(Layer* aLayer, break; } default: MOZ_ASSERT_UNREACHABLE("Unhandled animated property"); } } static bool -SampleAnimationForEachNode(TimeStamp aPoint, - AnimationArray& aAnimations, - InfallibleTArray<AnimData>& aAnimationData, - StyleAnimationValue& aAnimationValue, - bool& aHasInEffectAnimations) -{ - bool activeAnimations = false; - - if (aAnimations.IsEmpty()) { - return activeAnimations; - } - - // Process in order, since later aAnimations override earlier ones. - for (size_t i = 0, iEnd = aAnimations.Length(); i < iEnd; ++i) { - Animation& animation = aAnimations[i]; - AnimData& animData = aAnimationData[i]; - - activeAnimations = true; - - MOZ_ASSERT(!animation.startTime().IsNull() || - animation.isNotPlaying(), - "Failed to resolve start time of play-pending animations"); - // If the animation is not currently playing , e.g. paused or - // finished, then use the hold time to stay at the same position. - TimeDuration elapsedDuration = animation.isNotPlaying() - ? animation.holdTime() - : (aPoint - animation.startTime()) - .MultDouble(animation.playbackRate()); - TimingParams timing; - timing.mDuration.emplace(animation.duration()); - timing.mDelay = animation.delay(); - timing.mEndDelay = animation.endDelay(); - timing.mIterations = animation.iterations(); - timing.mIterationStart = animation.iterationStart(); - timing.mDirection = - static_cast<dom::PlaybackDirection>(animation.direction()); - timing.mFill = static_cast<dom::FillMode>(animation.fillMode()); - timing.mFunction = - AnimationUtils::TimingFunctionToComputedTimingFunction( - animation.easingFunction()); - - ComputedTiming computedTiming = - dom::AnimationEffectReadOnly::GetComputedTimingAt( - Nullable<TimeDuration>(elapsedDuration), timing, - animation.playbackRate()); - - if (computedTiming.mProgress.IsNull()) { - continue; - } - - uint32_t segmentIndex = 0; - size_t segmentSize = animation.segments().Length(); - AnimationSegment* segment = animation.segments().Elements(); - while (segment->endPortion() < computedTiming.mProgress.Value() && - segmentIndex < segmentSize - 1) { - ++segment; - ++segmentIndex; - } - - double positionInSegment = - (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 - aAnimationValue = SampleValue(portion, - animation, - from, to, - animData.mEndValues.LastElement(), - computedTiming.mCurrentIteration, - aAnimationValue); - aHasInEffectAnimations = true; - } - -#ifdef DEBUG - // Sanity check that all of animation data are the same. - const AnimationData& lastData = aAnimations.LastElement().data(); - for (const Animation& animation : aAnimations) { - const AnimationData& data = animation.data(); - MOZ_ASSERT(data.type() == lastData.type(), - "The type of AnimationData should be the same"); - if (data.type() == AnimationData::Tnull_t) { - continue; - } - - MOZ_ASSERT(data.type() == AnimationData::TTransformData); - const TransformData& transformData = data.get_TransformData(); - const TransformData& lastTransformData = lastData.get_TransformData(); - MOZ_ASSERT(transformData.origin() == lastTransformData.origin() && - transformData.transformOrigin() == - lastTransformData.transformOrigin() && - transformData.bounds() == lastTransformData.bounds() && - transformData.appUnitsPerDevPixel() == - lastTransformData.appUnitsPerDevPixel(), - "All of members of TransformData should be the same"); - } -#endif - return activeAnimations; -} - -static bool SampleAnimations(Layer* aLayer, TimeStamp aPoint) { bool activeAnimations = false; ForEachNode<ForwardIterator>( aLayer, [&activeAnimations, &aPoint] (Layer* layer) { bool hasInEffectAnimations = false; StyleAnimationValue animationValue = layer->GetBaseAnimationStyle(); - activeAnimations |= SampleAnimationForEachNode(aPoint, - layer->GetAnimations(), - layer->GetAnimationData(), - animationValue, - hasInEffectAnimations); + activeAnimations |= + AnimationHelper::SampleAnimationForEachNode(aPoint, + layer->GetAnimations(), + layer->GetAnimationData(), + animationValue, + hasInEffectAnimations); if (hasInEffectAnimations) { Animation& animation = layer->GetAnimations().LastElement(); ApplyAnimatedValue(layer, animation.property(), animation.data(), animationValue); } });