/src/mozilla-central/dom/animation/EffectCompositor.h
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
7 | | #ifndef mozilla_EffectCompositor_h |
8 | | #define mozilla_EffectCompositor_h |
9 | | |
10 | | #include "mozilla/EnumeratedArray.h" |
11 | | #include "mozilla/Maybe.h" |
12 | | #include "mozilla/OwningNonNull.h" |
13 | | #include "mozilla/PseudoElementHashEntry.h" |
14 | | #include "mozilla/RefPtr.h" |
15 | | #include "mozilla/ServoTypes.h" |
16 | | #include "nsCSSPropertyID.h" |
17 | | #include "nsCycleCollectionParticipant.h" |
18 | | #include "nsDataHashtable.h" |
19 | | #include "nsTArray.h" |
20 | | |
21 | | class nsCSSPropertyIDSet; |
22 | | class nsAtom; |
23 | | class nsIFrame; |
24 | | class nsPresContext; |
25 | | struct RawServoAnimationValueMap; |
26 | | typedef RawServoAnimationValueMap* RawServoAnimationValueMapBorrowedMut; |
27 | | |
28 | | namespace mozilla { |
29 | | |
30 | | class ComputedStyle; |
31 | | class EffectSet; |
32 | | class RestyleTracker; |
33 | | class StyleAnimationValue; |
34 | | struct AnimationPerformanceWarning; |
35 | | struct AnimationProperty; |
36 | | struct NonOwningAnimationTarget; |
37 | | |
38 | | namespace dom { |
39 | | class Animation; |
40 | | class Element; |
41 | | } |
42 | | |
43 | | class EffectCompositor |
44 | | { |
45 | | public: |
46 | | explicit EffectCompositor(nsPresContext* aPresContext) |
47 | | : mPresContext(aPresContext) |
48 | | { |
49 | | } |
50 | | |
51 | | NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(EffectCompositor) |
52 | | NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(EffectCompositor) |
53 | | |
54 | | void Disconnect() { |
55 | | mPresContext = nullptr; |
56 | | } |
57 | | |
58 | | // Animations can be applied at two different levels in the CSS cascade: |
59 | | enum class CascadeLevel : uint32_t { |
60 | | // The animations sheet (CSS animations, script-generated animations, |
61 | | // and CSS transitions that are no longer tied to CSS markup) |
62 | | Animations = 0, |
63 | | // The transitions sheet (CSS transitions that are tied to CSS markup) |
64 | | Transitions = 1 |
65 | | }; |
66 | | // We don't define this as part of CascadeLevel as then we'd have to add |
67 | | // explicit checks for the Count enum value everywhere CascadeLevel is used. |
68 | | static const size_t kCascadeLevelCount = |
69 | | static_cast<size_t>(CascadeLevel::Transitions) + 1; |
70 | | |
71 | | // NOTE: This can return null after Disconnect(). |
72 | | nsPresContext* PresContext() const { return mPresContext; } |
73 | | |
74 | | enum class RestyleType { |
75 | | // Animation style has changed but the compositor is applying the same |
76 | | // change so we might be able to defer updating the main thread until it |
77 | | // becomes necessary. |
78 | | Throttled, |
79 | | // Animation style has changed and needs to be updated on the main thread. |
80 | | Standard, |
81 | | // Animation style has changed and needs to be updated on the main thread |
82 | | // as well as forcing animations on layers to be updated. |
83 | | // This is needed in cases such as when an animation becomes paused or has |
84 | | // its playback rate changed. In such cases, although the computed style |
85 | | // and refresh driver time might not change, we still need to ensure the |
86 | | // corresponding animations on layers are updated to reflect the new |
87 | | // configuration of the animation. |
88 | | Layer |
89 | | }; |
90 | | |
91 | | // Notifies the compositor that the animation rule for the specified |
92 | | // (pseudo-)element at the specified cascade level needs to be updated. |
93 | | // The specified steps taken to update the animation rule depend on |
94 | | // |aRestyleType| whose values are described above. |
95 | | void RequestRestyle(dom::Element* aElement, |
96 | | CSSPseudoElementType aPseudoType, |
97 | | RestyleType aRestyleType, |
98 | | CascadeLevel aCascadeLevel); |
99 | | |
100 | | // Schedule an animation restyle. This is called automatically by |
101 | | // RequestRestyle when necessary. However, it is exposed here since we also |
102 | | // need to perform this step when triggering transitions *without* also |
103 | | // invalidating the animation style rule (which RequestRestyle would do). |
104 | | void PostRestyleForAnimation(dom::Element* aElement, |
105 | | CSSPseudoElementType aPseudoType, |
106 | | CascadeLevel aCascadeLevel); |
107 | | |
108 | | // Posts an animation restyle for any elements whose animation style rule |
109 | | // is out of date but for which an animation restyle has not yet been |
110 | | // posted because updates on the main thread are throttled. |
111 | | void PostRestyleForThrottledAnimations(); |
112 | | |
113 | | // Clear all pending restyle requests for the given (pseudo-) element (and its |
114 | | // ::before and ::after elements if the given element is not pseudo). |
115 | | void ClearRestyleRequestsFor(dom::Element* aElement); |
116 | | |
117 | | // Called when computed style on the specified (pseudo-) element might |
118 | | // have changed so that any context-sensitive values stored within |
119 | | // animation effects (e.g. em-based endpoints used in keyframe effects) |
120 | | // can be re-resolved to computed values. |
121 | | void UpdateEffectProperties(const ComputedStyle* aStyle, |
122 | | dom::Element* aElement, |
123 | | CSSPseudoElementType aPseudoType); |
124 | | |
125 | | |
126 | | // Get animation rule for stylo. This is an equivalent of GetAnimationRule |
127 | | // and will be called from servo side. |
128 | | // The animation rule is stored in |RawServoAnimationValueMapBorrowed|. |
129 | | // We need to be careful while doing any modification because it may cause |
130 | | // some thread-safe issues. |
131 | | bool GetServoAnimationRule( |
132 | | const dom::Element* aElement, |
133 | | CSSPseudoElementType aPseudoType, |
134 | | CascadeLevel aCascadeLevel, |
135 | | RawServoAnimationValueMapBorrowedMut aAnimationValues); |
136 | | |
137 | | bool HasPendingStyleUpdates() const; |
138 | | |
139 | | |
140 | | static bool HasAnimationsForCompositor(const nsIFrame* aFrame, |
141 | | nsCSSPropertyID aProperty); |
142 | | |
143 | | static nsTArray<RefPtr<dom::Animation>> |
144 | | GetAnimationsForCompositor(const nsIFrame* aFrame, |
145 | | nsCSSPropertyID aProperty); |
146 | | |
147 | | static void ClearIsRunningOnCompositor(const nsIFrame* aFrame, |
148 | | nsCSSPropertyID aProperty); |
149 | | |
150 | | // Update animation cascade results for the specified (pseudo-)element |
151 | | // but only if we have marked the cascade as needing an update due a |
152 | | // the change in the set of effects or a change in one of the effects' |
153 | | // "in effect" state. |
154 | | // |
155 | | // This method does NOT detect if other styles that apply above the |
156 | | // animation level of the cascade have changed. |
157 | | static void |
158 | | MaybeUpdateCascadeResults(dom::Element* aElement, |
159 | | CSSPseudoElementType aPseudoType); |
160 | | |
161 | | // Update the mPropertiesWithImportantRules and |
162 | | // mPropertiesForAnimationsLevel members of the given EffectSet, and also |
163 | | // request any restyles required by changes to the cascade result. |
164 | | // |
165 | | // NOTE: This can be expensive so we should only call it if styles that apply |
166 | | // above the animation level of the cascade might have changed. For all |
167 | | // other cases we should call MaybeUpdateCascadeResults. |
168 | | // |
169 | | // This is typically reserved for internal callers but is public here since |
170 | | // when we detect changes to the cascade on the Servo side we can't call |
171 | | // MarkCascadeNeedsUpdate during the traversal so instead we call this as part |
172 | | // of a follow-up sequential task. |
173 | | static void |
174 | | UpdateCascadeResults(EffectSet& aEffectSet, |
175 | | dom::Element* aElement, |
176 | | CSSPseudoElementType aPseudoType); |
177 | | |
178 | | // Helper to fetch the corresponding element and pseudo-type from a frame. |
179 | | // |
180 | | // For frames corresponding to pseudo-elements, the returned element is the |
181 | | // element on which we store the animations (i.e. the EffectSet and/or |
182 | | // AnimationCollection), *not* the generated content. |
183 | | // |
184 | | // Returns an empty result when a suitable element cannot be found including |
185 | | // when the frame represents a pseudo-element on which we do not support |
186 | | // animations. |
187 | | static Maybe<NonOwningAnimationTarget> |
188 | | GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame); |
189 | | |
190 | | // Associates a performance warning with effects on |aFrame| that animates |
191 | | // |aProperty|. |
192 | | static void SetPerformanceWarning( |
193 | | const nsIFrame* aFrame, |
194 | | nsCSSPropertyID aProperty, |
195 | | const AnimationPerformanceWarning& aWarning); |
196 | | |
197 | | // Do a bunch of stuff that we should avoid doing during the parallel |
198 | | // traversal (e.g. changing member variables) for all elements that we expect |
199 | | // to restyle on the next traversal. |
200 | | // |
201 | | // Returns true if there are elements needing a restyle for animation. |
202 | | bool PreTraverse(ServoTraversalFlags aFlags); |
203 | | |
204 | | // Similar to the above but only for the (pseudo-)element. |
205 | | bool PreTraverse(dom::Element* aElement, CSSPseudoElementType aPseudoType); |
206 | | |
207 | | // Similar to the above but for all elements in the subtree rooted |
208 | | // at aElement. |
209 | | bool PreTraverseInSubtree(ServoTraversalFlags aFlags, dom::Element* aElement); |
210 | | |
211 | | // Returns the target element for restyling. |
212 | | // |
213 | | // If |aPseudoType| is ::after or ::before, returns the generated content |
214 | | // element of which |aElement| is the parent. If |aPseudoType| is any other |
215 | | // pseudo type (other thant CSSPseudoElementType::NotPseudo) returns nullptr. |
216 | | // Otherwise, returns |aElement|. |
217 | | static dom::Element* GetElementToRestyle(dom::Element* aElement, |
218 | | CSSPseudoElementType aPseudoType); |
219 | | |
220 | | private: |
221 | 0 | ~EffectCompositor() = default; |
222 | | |
223 | | |
224 | | // Get the properties in |aEffectSet| that we are able to animate on the |
225 | | // compositor but which are also specified at a higher level in the cascade |
226 | | // than the animations level. |
227 | | static nsCSSPropertyIDSet |
228 | | GetOverriddenProperties(EffectSet& aEffectSet, |
229 | | dom::Element* aElement, |
230 | | CSSPseudoElementType aPseudoType); |
231 | | |
232 | | static nsPresContext* GetPresContext(dom::Element* aElement); |
233 | | |
234 | | nsPresContext* mPresContext; |
235 | | |
236 | | // Elements with a pending animation restyle. The associated bool value is |
237 | | // true if a pending animation restyle has also been dispatched. For |
238 | | // animations that can be throttled, we will add an entry to the hashtable to |
239 | | // indicate that the style rule on the element is out of date but without |
240 | | // posting a restyle to update it. |
241 | | EnumeratedArray<CascadeLevel, CascadeLevel(kCascadeLevelCount), |
242 | | nsDataHashtable<PseudoElementHashEntry, bool>> |
243 | | mElementsToRestyle; |
244 | | |
245 | | bool mIsInPreTraverse = false; |
246 | | |
247 | | }; |
248 | | |
249 | | } // namespace mozilla |
250 | | |
251 | | #endif // mozilla_EffectCompositor_h |