Bug 1317209 - Part 1: Introduce ServoAnimationRule and implement uncompute FFI. r=heycam
1. Introduce ServoAnimationRule, which is an equivalent of AnimValuesStyleRule.
2. Wrap ServoAnimationRule and AnimValuesStyleRule into a struct, and
use it as the parameter of Animation::ComposeStyle and
KeyframeEffectReadOnly::ComposeStyle.
3. Uncompute the RawServoAnimationValues in ServoAnimationRule when we
need it.
MozReview-Commit-ID: HahXDYBCAhH
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -8,16 +8,17 @@
#include "AnimationUtils.h"
#include "mozilla/dom/AnimationBinding.h"
#include "mozilla/dom/AnimationPlaybackEvent.h"
#include "mozilla/dom/DocumentTimeline.h"
#include "mozilla/AnimationTarget.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/AsyncEventDispatcher.h" // For AsyncEventDispatcher
#include "mozilla/Maybe.h" // For Maybe
+#include "mozilla/AnimationRule.h" // For AnimationRule
#include "nsAnimationManager.h" // For CSSAnimation
#include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch
#include "nsIDocument.h" // For nsIDocument
#include "nsIPresShell.h" // For nsIPresShell
#include "nsThreadUtils.h" // For nsRunnableMethod and nsRevocableEventPtr
#include "nsTransitionManager.h" // For CSSTransition
#include "PendingAnimationTracker.h" // For PendingAnimationTracker
@@ -911,17 +912,17 @@ Animation::HasLowerCompositeOrderThan(co
"Animation indices should be unique");
// 3. Finally, generic animations sort by their position in the global
// animation array.
return mAnimationIndex < aOther.mAnimationIndex;
}
void
-Animation::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
+Animation::ComposeStyle(AnimationRule& aStyleRule,
const nsCSSPropertyIDSet& aPropertiesToSkip)
{
if (!mEffect) {
return;
}
// In order to prevent flicker, there are a few cases where we want to use
// a different time for rendering that would otherwise be returned by
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -35,17 +35,17 @@
struct JSContext;
class nsCSSPropertyIDSet;
class nsIDocument;
class nsIFrame;
namespace mozilla {
-class AnimValuesStyleRule;
+struct AnimationRule;
namespace dom {
class CSSAnimation;
class CSSTransition;
class Animation
: public DOMEventTargetHelper
@@ -312,17 +312,17 @@ public:
*/
bool CanThrottle() const;
/**
* Updates |aStyleRule| with the animation values of this animation's effect,
* if any.
* Any properties contained in |aPropertiesToSkip| will not be added or
* updated in |aStyleRule|.
*/
- void ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
+ void ComposeStyle(AnimationRule& aStyleRule,
const nsCSSPropertyIDSet& aPropertiesToSkip);
void NotifyEffectTimingUpdated();
void NotifyGeometricAnimationsStartingThisFrame();
/**
* Used by subclasses to synchronously queue a cancel event in situations
* where the Animation may have been cancelled.
new file mode 100644
--- /dev/null
+++ b/dom/animation/AnimationRule.h
@@ -0,0 +1,24 @@
+/* -*- 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/. */
+
+#ifndef mozilla_AnimationRule_h
+#define mozilla_AnimationRule_h
+
+#include "AnimValuesStyleRule.h"
+#include "ServoAnimationRule.h"
+
+namespace mozilla {
+
+// A wrapper for animation rules.
+struct AnimationRule
+{
+ RefPtr<AnimValuesStyleRule> mGecko;
+ RefPtr<ServoAnimationRule> mServo;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_AnimationRule_h
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -415,17 +415,17 @@ EffectCompositor::GetAnimationRule(dom::
}
#endif
EffectSet* effectSet = EffectSet::GetEffectSet(aElement, aPseudoType);
if (!effectSet) {
return nullptr;
}
- return effectSet->AnimationRule(aCascadeLevel);
+ return effectSet->AnimationRule(aCascadeLevel).mGecko;
}
/* static */ dom::Element*
EffectCompositor::GetElementToRestyle(dom::Element* aElement,
CSSPseudoElementType aPseudoType)
{
if (aPseudoType == CSSPseudoElementType::NotPseudo) {
return aElement;
@@ -680,29 +680,28 @@ EffectCompositor::ComposeAnimationRule(d
// Get a list of effects sorted by composite order.
nsTArray<KeyframeEffectReadOnly*> sortedEffectList(effects->Count());
for (KeyframeEffectReadOnly* effect : *effects) {
sortedEffectList.AppendElement(effect);
}
sortedEffectList.Sort(EffectCompositeOrderComparator());
- RefPtr<AnimValuesStyleRule>& animationRule =
- effects->AnimationRule(aCascadeLevel);
- animationRule = nullptr;
+ AnimationRule& animRule = effects->AnimationRule(aCascadeLevel);
+ animRule.mGecko = nullptr;
// If multiple animations affect the same property, animations with higher
// composite order (priority) override or add or animations with lower
// priority except properties in propertiesToSkip.
const nsCSSPropertyIDSet& propertiesToSkip =
aCascadeLevel == CascadeLevel::Animations
? effects->PropertiesForAnimationsLevel().Invert()
: effects->PropertiesForAnimationsLevel();
for (KeyframeEffectReadOnly* effect : sortedEffectList) {
- effect->GetAnimation()->ComposeStyle(animationRule, propertiesToSkip);
+ effect->GetAnimation()->ComposeStyle(animRule, propertiesToSkip);
}
MOZ_ASSERT(effects == EffectSet::GetEffectSet(aElement, aPseudoType),
"EffectSet should not change while composing style");
effects->UpdateAnimationRuleRefreshTime(aCascadeLevel, aRefreshTime);
}
--- a/dom/animation/EffectSet.h
+++ b/dom/animation/EffectSet.h
@@ -2,17 +2,17 @@
/* 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/. */
#ifndef mozilla_EffectSet_h
#define mozilla_EffectSet_h
-#include "mozilla/AnimValuesStyleRule.h"
+#include "mozilla/AnimationRule.h" // For AnimationRule
#include "mozilla/DebugOnly.h"
#include "mozilla/EffectCompositor.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/KeyframeEffectReadOnly.h"
#include "nsHashKeys.h" // For nsPtrHashKey
#include "nsTHashtable.h" // For nsTHashtable
@@ -158,18 +158,18 @@ public:
#ifdef DEBUG
bool IsBeingEnumerated() const { return mActiveIterators != 0; }
#endif
bool IsEmpty() const { return mEffects.IsEmpty(); }
size_t Count() const { return mEffects.Count(); }
- RefPtr<AnimValuesStyleRule>& AnimationRule(EffectCompositor::CascadeLevel
- aCascadeLevel)
+ struct AnimationRule&
+ AnimationRule(EffectCompositor::CascadeLevel aCascadeLevel)
{
return mAnimationRule[aCascadeLevel];
}
const TimeStamp& AnimationRuleRefreshTime(EffectCompositor::CascadeLevel
aCascadeLevel) const
{
return mAnimationRuleRefreshTime[aCascadeLevel];
@@ -227,17 +227,17 @@ private:
// These style rules contain the style data for currently animating
// values. They only match when styling with animation. When we
// style without animation, we need to not use them so that we can
// detect any new changes; if necessary we restyle immediately
// afterwards with animation.
EnumeratedArray<EffectCompositor::CascadeLevel,
EffectCompositor::CascadeLevel(
EffectCompositor::kCascadeLevelCount),
- RefPtr<AnimValuesStyleRule>> mAnimationRule;
+ mozilla::AnimationRule> mAnimationRule;
// A parallel array to mAnimationRule that records the refresh driver
// timestamp when the rule was last updated. This is used for certain
// animations which are updated only periodically (e.g. transform animations
// running on the compositor that affect the scrollable overflow region).
EnumeratedArray<EffectCompositor::CascadeLevel,
EffectCompositor::CascadeLevel(
EffectCompositor::kCascadeLevelCount),
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -5,16 +5,17 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/KeyframeEffectReadOnly.h"
#include "mozilla/dom/KeyframeAnimationOptionsBinding.h"
// For UnrestrictedDoubleOrKeyframeAnimationOptions;
#include "mozilla/dom/CSSPseudoElement.h"
#include "mozilla/dom/KeyframeEffectBinding.h"
+#include "mozilla/AnimationRule.h"
#include "mozilla/AnimationUtils.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/EffectSet.h"
#include "mozilla/FloatingPoint.h" // For IsFinite
#include "mozilla/LookAndFeel.h" // For LookAndFeel::GetInt
#include "mozilla/KeyframeUtils.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/StyleAnimationValue.h"
@@ -459,17 +460,17 @@ KeyframeEffectReadOnly::EnsureBaseStyles
SetNeedsBaseStyle(property.mProperty);
break;
}
}
}
void
KeyframeEffectReadOnly::ComposeStyle(
- RefPtr<AnimValuesStyleRule>& aStyleRule,
+ AnimationRule& aStyleRule,
const nsCSSPropertyIDSet& aPropertiesToSkip)
{
MOZ_DIAGNOSTIC_ASSERT(!mIsComposingStyle,
"Should not be called recursively");
if (mIsComposingStyle) {
return;
}
@@ -526,59 +527,59 @@ KeyframeEffectReadOnly::ComposeStyle(
MOZ_ASSERT(segment->mFromKey == (segment-1)->mToKey, "incorrect keys");
}
MOZ_ASSERT(segment->mFromKey <= segment->mToKey, "incorrect keys");
MOZ_ASSERT(segment >= prop.mSegments.Elements() &&
size_t(segment - prop.mSegments.Elements()) <
prop.mSegments.Length(),
"out of array bounds");
- if (!aStyleRule) {
+ if (!aStyleRule.mGecko) {
// Allocate the style rule now that we know we have animation data.
- aStyleRule = new AnimValuesStyleRule();
+ aStyleRule.mGecko = new AnimValuesStyleRule();
}
StyleAnimationValue fromValue =
- CompositeValue(prop.mProperty, aStyleRule,
+ CompositeValue(prop.mProperty, aStyleRule.mGecko,
segment->mFromValue,
segment->mFromComposite);
StyleAnimationValue toValue =
- CompositeValue(prop.mProperty, aStyleRule,
+ CompositeValue(prop.mProperty, aStyleRule.mGecko,
segment->mToValue,
segment->mToComposite);
// Iteration composition for accumulate
if (mEffectOptions.mIterationComposite ==
IterationCompositeOperation::Accumulate &&
computedTiming.mCurrentIteration > 0) {
const AnimationPropertySegment& lastSegment =
prop.mSegments.LastElement();
// FIXME: Bug 1293492: Add a utility function to calculate both of
// below StyleAnimationValues.
StyleAnimationValue lastValue = lastSegment.mToValue.IsNull()
- ? GetUnderlyingStyle(prop.mProperty, aStyleRule)
+ ? GetUnderlyingStyle(prop.mProperty, aStyleRule.mGecko)
: lastSegment.mToValue;
fromValue =
StyleAnimationValue::Accumulate(prop.mProperty,
lastValue,
Move(fromValue),
computedTiming.mCurrentIteration);
toValue =
StyleAnimationValue::Accumulate(prop.mProperty,
lastValue,
Move(toValue),
computedTiming.mCurrentIteration);
}
// Special handling for zero-length segments
if (segment->mToKey == segment->mFromKey) {
if (computedTiming.mProgress.Value() < 0) {
- aStyleRule->AddValue(prop.mProperty, Move(fromValue));
+ aStyleRule.mGecko->AddValue(prop.mProperty, Move(fromValue));
} else {
- aStyleRule->AddValue(prop.mProperty, Move(toValue));
+ aStyleRule.mGecko->AddValue(prop.mProperty, Move(toValue));
}
continue;
}
double positionInSegment =
(computedTiming.mProgress.Value() - segment->mFromKey) /
(segment->mToKey - segment->mFromKey);
double valuePosition =
@@ -587,21 +588,21 @@ KeyframeEffectReadOnly::ComposeStyle(
computedTiming.mBeforeFlag);
MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
StyleAnimationValue val;
if (StyleAnimationValue::Interpolate(prop.mProperty,
fromValue,
toValue,
valuePosition, val)) {
- aStyleRule->AddValue(prop.mProperty, Move(val));
+ aStyleRule.mGecko->AddValue(prop.mProperty, Move(val));
} else if (valuePosition < 0.5) {
- aStyleRule->AddValue(prop.mProperty, Move(fromValue));
+ aStyleRule.mGecko->AddValue(prop.mProperty, Move(fromValue));
} else {
- aStyleRule->AddValue(prop.mProperty, Move(toValue));
+ aStyleRule.mGecko->AddValue(prop.mProperty, Move(toValue));
}
}
// For properties that can be run on the compositor, we may need to prepare
// base styles to send to the compositor even if the current processing
// segment for properties does not have either an additive or accumulative
// composite mode, and even if the animation is not in-effect. That's because
// the animation may later progress to a segment which has an additive or
--- a/dom/animation/KeyframeEffectReadOnly.h
+++ b/dom/animation/KeyframeEffectReadOnly.h
@@ -35,16 +35,17 @@ class nsIFrame;
class nsIPresShell;
class nsPresContext;
namespace mozilla {
class AnimValuesStyleRule;
enum class CSSPseudoElementType : uint8_t;
class ErrorResult;
+struct AnimationRule;
struct TimingParams;
namespace dom {
class ElementOrCSSPseudoElement;
class GlobalObject;
class OwningElementOrCSSPseudoElement;
class UnrestrictedDoubleOrKeyframeAnimationOptions;
class UnrestrictedDoubleOrKeyframeEffectOptions;
@@ -286,17 +287,17 @@ public:
// Update |mProperties| by recalculating from |mKeyframes| using
// |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,
+ void ComposeStyle(AnimationRule& aStyleRule,
const nsCSSPropertyIDSet& aPropertiesToSkip);
// Composite |aValueToComposite| on |aUnderlyingValue| with
// |aCompositeOperation|.
// Returns |aValueToComposite| if |aCompositeOperation| is Replace.
static StyleAnimationValue CompositeValue(
nsCSSPropertyID aProperty,
const StyleAnimationValue& aValueToComposite,
new file mode 100644
--- /dev/null
+++ b/dom/animation/ServoAnimationRule.cpp
@@ -0,0 +1,32 @@
+/* -*- 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 "ServoAnimationRule.h"
+
+namespace mozilla {
+
+void
+ServoAnimationRule::AddValue(nsCSSPropertyID aProperty,
+ RawServoAnimationValue* aValue)
+{
+ MOZ_ASSERT(aProperty != eCSSProperty_UNKNOWN,
+ "Unexpected css property");
+ mAnimationValues.Put(aProperty, aValue);
+}
+
+RawServoDeclarationBlockStrong
+ServoAnimationRule::GetValues() const
+{
+ // FIXME: Pass the hash table into the FFI directly.
+ nsTArray<const RawServoAnimationValue*> values(mAnimationValues.Count());
+ auto iter = mAnimationValues.ConstIter();
+ for (; !iter.Done(); iter.Next()) {
+ values.AppendElement(iter.Data());
+ }
+ return Servo_AnimationValues_Uncompute(&values);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/animation/ServoAnimationRule.h
@@ -0,0 +1,39 @@
+/* -*- 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/. */
+
+#ifndef mozilla_ServoAnimationRule_h
+#define mozilla_ServoAnimationRule_h
+
+#include "nsCSSPropertyID.h"
+#include "nsHashKeys.h" // For nsUint32HashKey
+#include "nsRefPtrHashtable.h"
+#include "ServoBindings.h"
+
+namespace mozilla {
+
+/**
+ * A rule for Stylo Animation Rule.
+ */
+class ServoAnimationRule
+{
+public:
+ ServoAnimationRule() = default;
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ServoAnimationRule)
+
+ void AddValue(nsCSSPropertyID aProperty,
+ RawServoAnimationValue* aValue);
+ MOZ_MUST_USE RawServoDeclarationBlockStrong GetValues() const;
+
+private:
+ ~ServoAnimationRule() = default;
+
+ nsRefPtrHashtable<nsUint32HashKey, RawServoAnimationValue> mAnimationValues;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ServoAnimationRule_h
--- a/dom/animation/moz.build
+++ b/dom/animation/moz.build
@@ -17,27 +17,29 @@ EXPORTS.mozilla.dom += [
'DocumentTimeline.h',
'KeyframeEffect.h',
'KeyframeEffectReadOnly.h',
]
EXPORTS.mozilla += [
'AnimationComparator.h',
'AnimationPerformanceWarning.h',
+ 'AnimationRule.h',
'AnimationTarget.h',
'AnimationUtils.h',
'AnimValuesStyleRule.h',
'ComputedTiming.h',
'ComputedTimingFunction.h',
'EffectCompositor.h',
'EffectSet.h',
'KeyframeEffectParams.h',
'KeyframeUtils.h',
'PendingAnimationTracker.h',
'PseudoElementHashEntry.h',
+ 'ServoAnimationRule.h',
'TimingParams.h',
]
UNIFIED_SOURCES += [
'Animation.cpp',
'AnimationEffectReadOnly.cpp',
'AnimationEffectTiming.cpp',
'AnimationEffectTimingReadOnly.cpp',
@@ -50,16 +52,17 @@ UNIFIED_SOURCES += [
'DocumentTimeline.cpp',
'EffectCompositor.cpp',
'EffectSet.cpp',
'KeyframeEffect.cpp',
'KeyframeEffectParams.cpp',
'KeyframeEffectReadOnly.cpp',
'KeyframeUtils.cpp',
'PendingAnimationTracker.cpp',
+ 'ServoAnimationRule.cpp',
'TimingParams.cpp',
]
LOCAL_INCLUDES += [
'/dom/base',
'/layout/base',
'/layout/style',
]
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -108,16 +108,19 @@ SERVO_BINDING_FUNC(Servo_RestyleWithAdde
// AnimationValues handling
SERVO_BINDING_FUNC(Servo_AnimationValues_Populate, void,
RawGeckoAnimationValueListBorrowedMut,
RawServoDeclarationBlockBorrowed,
ServoComputedValuesBorrowed,
ServoComputedValuesBorrowedOrNull,
RawGeckoPresContextBorrowed)
+SERVO_BINDING_FUNC(Servo_AnimationValues_Uncompute,
+ RawServoDeclarationBlockStrong,
+ RawServoAnimationValueBorrowedListBorrowed value)
// Style attribute
SERVO_BINDING_FUNC(Servo_ParseStyleAttribute, RawServoDeclarationBlockStrong,
const nsACString* data)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_CreateEmpty,
RawServoDeclarationBlockStrong)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_Clone, RawServoDeclarationBlockStrong,
RawServoDeclarationBlockBorrowed declarations)
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -36,16 +36,17 @@ class nsPresContext;
using mozilla::dom::StyleChildrenIterator;
using mozilla::ServoElementSnapshot;
typedef nsINode RawGeckoNode;
typedef mozilla::dom::Element RawGeckoElement;
typedef nsIDocument RawGeckoDocument;
typedef nsPresContext RawGeckoPresContext;
typedef nsTArray<mozilla::PropertyStyleAnimationValuePair> RawGeckoAnimationValueList;
+typedef nsTArray<const RawServoAnimationValue*> RawServoAnimationValueBorrowedList;
// We have these helper types so that we can directly generate
// things like &T or Borrowed<T> on the Rust side in the function, providing
// additional safety benefits.
//
// FFI has a problem with templated types, so we just use raw pointers here.
//
// The "Borrowed" types generate &T or Borrowed<T> in the nullable case.
@@ -105,16 +106,17 @@ DECL_BORROWED_REF_TYPE_FOR(RawGeckoDocum
DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawGeckoDocument)
DECL_BORROWED_MUT_REF_TYPE_FOR(StyleChildrenIterator)
DECL_BORROWED_MUT_REF_TYPE_FOR(ServoElementSnapshot)
DECL_BORROWED_REF_TYPE_FOR(nsCSSValue)
DECL_BORROWED_MUT_REF_TYPE_FOR(nsCSSValue)
DECL_OWNED_REF_TYPE_FOR(RawGeckoPresContext)
DECL_BORROWED_REF_TYPE_FOR(RawGeckoPresContext)
DECL_BORROWED_MUT_REF_TYPE_FOR(RawGeckoAnimationValueList)
+DECL_BORROWED_REF_TYPE_FOR(RawServoAnimationValueBorrowedList)
#undef DECL_ARC_REF_TYPE_FOR
#undef DECL_OWNED_REF_TYPE_FOR
#undef DECL_NULLABLE_OWNED_REF_TYPE_FOR
#undef DECL_BORROWED_REF_TYPE_FOR
#undef DECL_NULLABLE_BORROWED_REF_TYPE_FOR
#undef DECL_BORROWED_MUT_REF_TYPE_FOR
#undef DECL_NULLABLE_BORROWED_MUT_REF_TYPE_FOR