Bug 1769628 [wpt PR 34081] - Update wpt metadata, a=testonly
[gecko.git] / dom / animation / EffectCompositor.h
blob622fb2ec1bd9148971651f72a4a3a685bcf630bb
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_EffectCompositor_h
8 #define mozilla_EffectCompositor_h
10 #include "mozilla/AnimationPerformanceWarning.h"
11 #include "mozilla/AnimationTarget.h"
12 #include "mozilla/EnumeratedArray.h"
13 #include "mozilla/HashTable.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/OwningNonNull.h"
16 #include "mozilla/PseudoElementHashEntry.h"
17 #include "mozilla/RefPtr.h"
18 #include "mozilla/ServoTypes.h"
19 #include "nsCSSPropertyID.h"
20 #include "nsCycleCollectionParticipant.h"
21 #include "nsTHashMap.h"
22 #include "nsTArray.h"
24 class nsCSSPropertyIDSet;
25 class nsAtom;
26 class nsIFrame;
27 class nsPresContext;
28 enum class DisplayItemType : uint8_t;
29 struct RawServoAnimationValueMap;
31 namespace mozilla {
33 class ComputedStyle;
34 class EffectSet;
35 class RestyleTracker;
36 class StyleAnimationValue;
37 struct AnimationProperty;
38 struct NonOwningAnimationTarget;
40 namespace dom {
41 class Animation;
42 class Element;
43 class KeyframeEffect;
44 } // namespace dom
46 class EffectCompositor {
47 public:
48 explicit EffectCompositor(nsPresContext* aPresContext)
49 : mPresContext(aPresContext) {}
51 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(EffectCompositor)
52 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(EffectCompositor)
54 void Disconnect() { mPresContext = nullptr; }
56 // Animations can be applied at two different levels in the CSS cascade:
57 enum class CascadeLevel : uint32_t {
58 // The animations sheet (CSS animations, script-generated animations,
59 // and CSS transitions that are no longer tied to CSS markup)
60 Animations = 0,
61 // The transitions sheet (CSS transitions that are tied to CSS markup)
62 Transitions = 1
64 // We don't define this as part of CascadeLevel as then we'd have to add
65 // explicit checks for the Count enum value everywhere CascadeLevel is used.
66 static const size_t kCascadeLevelCount =
67 static_cast<size_t>(CascadeLevel::Transitions) + 1;
69 // NOTE: This can return null after Disconnect().
70 nsPresContext* PresContext() const { return mPresContext; }
72 enum class RestyleType {
73 // Animation style has changed but the compositor is applying the same
74 // change so we might be able to defer updating the main thread until it
75 // becomes necessary.
76 Throttled,
77 // Animation style has changed and needs to be updated on the main thread.
78 Standard,
79 // Animation style has changed and needs to be updated on the main thread
80 // as well as forcing animations on layers to be updated.
81 // This is needed in cases such as when an animation becomes paused or has
82 // its playback rate changed. In such cases, although the computed style
83 // and refresh driver time might not change, we still need to ensure the
84 // corresponding animations on layers are updated to reflect the new
85 // configuration of the animation.
86 Layer
89 // Notifies the compositor that the animation rule for the specified
90 // (pseudo-)element at the specified cascade level needs to be updated.
91 // The specified steps taken to update the animation rule depend on
92 // |aRestyleType| whose values are described above.
93 void RequestRestyle(dom::Element* aElement, PseudoStyleType aPseudoType,
94 RestyleType aRestyleType, CascadeLevel aCascadeLevel);
96 // Schedule an animation restyle. This is called automatically by
97 // RequestRestyle when necessary. However, it is exposed here since we also
98 // need to perform this step when triggering transitions *without* also
99 // invalidating the animation style rule (which RequestRestyle would do).
100 void PostRestyleForAnimation(dom::Element* aElement,
101 PseudoStyleType aPseudoType,
102 CascadeLevel aCascadeLevel);
104 // Posts an animation restyle for any elements whose animation style rule
105 // is out of date but for which an animation restyle has not yet been
106 // posted because updates on the main thread are throttled.
107 void PostRestyleForThrottledAnimations();
109 // Clear all pending restyle requests for the given (pseudo-) element (and its
110 // ::before, ::after and ::marker elements if the given element is not
111 // pseudo).
112 void ClearRestyleRequestsFor(dom::Element* aElement);
114 // Called when computed style on the specified (pseudo-) element might
115 // have changed so that any context-sensitive values stored within
116 // animation effects (e.g. em-based endpoints used in keyframe effects)
117 // can be re-resolved to computed values.
118 void UpdateEffectProperties(const ComputedStyle* aStyle,
119 dom::Element* aElement,
120 PseudoStyleType aPseudoType);
122 // Get the animation rule for the appropriate level of the cascade for
123 // a (pseudo-)element. Called from the Servo side.
125 // The animation rule is stored in |RawServoAnimationValueMap|.
126 // We need to be careful while doing any modification because it may cause
127 // some thread-safe issues.
128 bool GetServoAnimationRule(const dom::Element* aElement,
129 PseudoStyleType aPseudoType,
130 CascadeLevel aCascadeLevel,
131 RawServoAnimationValueMap* aAnimationValues);
133 // A variant on GetServoAnimationRule that composes all the effects for an
134 // element up to and including |aEffect|.
136 // Note that |aEffect| might not be in the EffectSet since we can use this for
137 // committing the computed style of a removed Animation.
138 bool ComposeServoAnimationRuleForEffect(
139 dom::KeyframeEffect& aEffect, CascadeLevel aCascadeLevel,
140 RawServoAnimationValueMap* aAnimationValues);
142 bool HasPendingStyleUpdates() const;
144 static bool HasAnimationsForCompositor(const nsIFrame* aFrame,
145 DisplayItemType aType);
147 static nsTArray<RefPtr<dom::Animation>> GetAnimationsForCompositor(
148 const nsIFrame* aFrame, const nsCSSPropertyIDSet& aPropertySet);
150 static void ClearIsRunningOnCompositor(const nsIFrame* aFrame,
151 DisplayItemType aType);
153 // Update animation cascade results for the specified (pseudo-)element
154 // but only if we have marked the cascade as needing an update due a
155 // the change in the set of effects or a change in one of the effects'
156 // "in effect" state.
158 // This method does NOT detect if other styles that apply above the
159 // animation level of the cascade have changed.
160 static void MaybeUpdateCascadeResults(dom::Element* aElement,
161 PseudoStyleType aPseudoType);
163 // Update the mPropertiesWithImportantRules and
164 // mPropertiesForAnimationsLevel members of the given EffectSet, and also
165 // request any restyles required by changes to the cascade result.
167 // NOTE: This can be expensive so we should only call it if styles that apply
168 // above the animation level of the cascade might have changed. For all
169 // other cases we should call MaybeUpdateCascadeResults.
171 // This is typically reserved for internal callers but is public here since
172 // when we detect changes to the cascade on the Servo side we can't call
173 // MarkCascadeNeedsUpdate during the traversal so instead we call this as part
174 // of a follow-up sequential task.
175 static void UpdateCascadeResults(EffectSet& aEffectSet,
176 dom::Element* aElement,
177 PseudoStyleType aPseudoType);
179 // Helper to fetch the corresponding element and pseudo-type from a frame.
181 // For frames corresponding to pseudo-elements, the returned element is the
182 // element on which we store the animations (i.e. the EffectSet and/or
183 // AnimationCollection), *not* the generated content.
185 // For display:table content, which maintains a distinction between primary
186 // frame (table wrapper frame) and style frame (inner table frame), animations
187 // are stored on the content associated with the _style_ frame even though
188 // some (particularly transform-like animations) may be applied to the
189 // _primary_ frame. As a result, callers will typically want to pass the style
190 // frame to this function.
192 // Returns an empty result when a suitable element cannot be found including
193 // when the frame represents a pseudo-element on which we do not support
194 // animations.
195 static Maybe<NonOwningAnimationTarget> GetAnimationElementAndPseudoForFrame(
196 const nsIFrame* aFrame);
198 // Associates a performance warning with effects on |aFrame| that animate
199 // properties in |aPropertySet|.
200 static void SetPerformanceWarning(
201 const nsIFrame* aFrame, const nsCSSPropertyIDSet& aPropertySet,
202 const AnimationPerformanceWarning& aWarning);
204 // Do a bunch of stuff that we should avoid doing during the parallel
205 // traversal (e.g. changing member variables) for all elements that we expect
206 // to restyle on the next traversal.
208 // Returns true if there are elements needing a restyle for animation.
209 bool PreTraverse(ServoTraversalFlags aFlags);
211 // Similar to the above but for all elements in the subtree rooted
212 // at aElement.
213 bool PreTraverseInSubtree(ServoTraversalFlags aFlags, dom::Element* aRoot);
215 // Record a (pseudo-)element that may have animations that can be removed.
216 void NoteElementForReducing(const NonOwningAnimationTarget& aTarget);
218 bool NeedsReducing() const { return !mElementsToReduce.empty(); }
219 void ReduceAnimations();
221 // Returns the target element for restyling.
223 // If |aPseudoType| is ::after, ::before or ::marker, returns the generated
224 // content element of which |aElement| is the parent. If |aPseudoType| is any
225 // other pseudo type (other than PseudoStyleType::NotPseudo) returns nullptr.
226 // Otherwise, returns |aElement|.
227 static dom::Element* GetElementToRestyle(dom::Element* aElement,
228 PseudoStyleType aPseudoType);
230 // Returns true if any type of compositor animations on |aFrame| allow
231 // runnning on the compositor.
232 // Sets the reason in |aWarning| if the result is false.
233 static bool AllowCompositorAnimationsOnFrame(
234 const nsIFrame* aFrame,
235 AnimationPerformanceWarning::Type& aWarning /* out */);
237 private:
238 ~EffectCompositor() = default;
240 // Get the properties in |aEffectSet| that we are able to animate on the
241 // compositor but which are also specified at a higher level in the cascade
242 // than the animations level.
243 static nsCSSPropertyIDSet GetOverriddenProperties(
244 EffectSet& aEffectSet, dom::Element* aElement,
245 PseudoStyleType aPseudoType);
247 static nsPresContext* GetPresContext(dom::Element* aElement);
249 nsPresContext* mPresContext;
251 // Elements with a pending animation restyle. The associated bool value is
252 // true if a pending animation restyle has also been dispatched. For
253 // animations that can be throttled, we will add an entry to the hashtable to
254 // indicate that the style rule on the element is out of date but without
255 // posting a restyle to update it.
256 EnumeratedArray<CascadeLevel, CascadeLevel(kCascadeLevelCount),
257 nsTHashMap<PseudoElementHashEntry, bool>>
258 mElementsToRestyle;
260 bool mIsInPreTraverse = false;
262 HashSet<OwningAnimationTarget> mElementsToReduce;
265 } // namespace mozilla
267 #endif // mozilla_EffectCompositor_h