Line data Source code
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_EffectSet_h
8 : #define mozilla_EffectSet_h
9 :
10 : #include "mozilla/AnimValuesStyleRule.h"
11 : #include "mozilla/DebugOnly.h"
12 : #include "mozilla/EffectCompositor.h"
13 : #include "mozilla/EnumeratedArray.h"
14 : #include "mozilla/TimeStamp.h"
15 : #include "mozilla/dom/KeyframeEffectReadOnly.h"
16 : #include "nsHashKeys.h" // For nsPtrHashKey
17 : #include "nsTHashtable.h" // For nsTHashtable
18 :
19 : class nsPresContext;
20 :
21 : namespace mozilla {
22 :
23 : namespace dom {
24 : class Element;
25 : } // namespace dom
26 :
27 : enum class CSSPseudoElementType : uint8_t;
28 :
29 : // A wrapper around a hashset of AnimationEffect objects to handle
30 : // storing the set as a property of an element.
31 : class EffectSet
32 : {
33 : public:
34 2 : EffectSet()
35 2 : : mCascadeNeedsUpdate(false)
36 : , mAnimationGeneration(0)
37 : #ifdef DEBUG
38 : , mActiveIterators(0)
39 : , mCalledPropertyDtor(false)
40 : #endif
41 : , mMayHaveOpacityAnim(false)
42 2 : , mMayHaveTransformAnim(false)
43 : {
44 2 : MOZ_COUNT_CTOR(EffectSet);
45 2 : }
46 :
47 2 : ~EffectSet()
48 2 : {
49 2 : MOZ_ASSERT(mCalledPropertyDtor,
50 : "must call destructor through element property dtor");
51 2 : MOZ_ASSERT(mActiveIterators == 0,
52 : "Effect set should not be destroyed while it is being "
53 : "enumerated");
54 2 : MOZ_COUNT_DTOR(EffectSet);
55 2 : }
56 : static void PropertyDtor(void* aObject, nsIAtom* aPropertyName,
57 : void* aPropertyValue, void* aData);
58 :
59 : // Methods for supporting cycle-collection
60 : void Traverse(nsCycleCollectionTraversalCallback& aCallback);
61 :
62 : static EffectSet* GetEffectSet(const dom::Element* aElement,
63 : CSSPseudoElementType aPseudoType);
64 : static EffectSet* GetEffectSet(const nsIFrame* aFrame);
65 : static EffectSet* GetOrCreateEffectSet(dom::Element* aElement,
66 : CSSPseudoElementType aPseudoType);
67 : static void DestroyEffectSet(dom::Element* aElement,
68 : CSSPseudoElementType aPseudoType);
69 :
70 : void AddEffect(dom::KeyframeEffectReadOnly& aEffect);
71 : void RemoveEffect(dom::KeyframeEffectReadOnly& aEffect);
72 :
73 2 : void SetMayHaveOpacityAnimation() { mMayHaveOpacityAnim = true; }
74 14 : bool MayHaveOpacityAnimation() const { return mMayHaveOpacityAnim; }
75 0 : void SetMayHaveTransformAnimation() { mMayHaveTransformAnim = true; }
76 15 : bool MayHaveTransformAnimation() const { return mMayHaveTransformAnim; }
77 :
78 : private:
79 : typedef nsTHashtable<nsRefPtrHashKey<dom::KeyframeEffectReadOnly>>
80 : OwningEffectSet;
81 :
82 : public:
83 : // A simple iterator to support iterating over the effects in this object in
84 : // range-based for loops.
85 : //
86 : // This allows us to avoid exposing mEffects directly and saves the
87 : // caller from having to dereference hashtable iterators using
88 : // the rather complicated: iter.Get()->GetKey().
89 : class Iterator
90 : {
91 : public:
92 80 : explicit Iterator(EffectSet& aEffectSet)
93 80 : : mEffectSet(aEffectSet)
94 160 : , mHashIterator(mozilla::Move(aEffectSet.mEffects.Iter()))
95 240 : , mIsEndIterator(false)
96 : {
97 : #ifdef DEBUG
98 80 : mEffectSet.mActiveIterators++;
99 : #endif
100 80 : }
101 :
102 : Iterator(Iterator&& aOther)
103 : : mEffectSet(aOther.mEffectSet)
104 : , mHashIterator(mozilla::Move(aOther.mHashIterator))
105 : , mIsEndIterator(aOther.mIsEndIterator)
106 : {
107 : #ifdef DEBUG
108 : mEffectSet.mActiveIterators++;
109 : #endif
110 : }
111 :
112 40 : static Iterator EndIterator(EffectSet& aEffectSet)
113 : {
114 40 : Iterator result(aEffectSet);
115 40 : result.mIsEndIterator = true;
116 40 : return result;
117 : }
118 :
119 80 : ~Iterator()
120 80 : {
121 : #ifdef DEBUG
122 80 : MOZ_ASSERT(mEffectSet.mActiveIterators > 0);
123 80 : mEffectSet.mActiveIterators--;
124 : #endif
125 80 : }
126 :
127 66 : bool operator!=(const Iterator& aOther) const {
128 66 : if (Done() || aOther.Done()) {
129 66 : return Done() != aOther.Done();
130 : }
131 0 : return mHashIterator.Get() != aOther.mHashIterator.Get();
132 : }
133 :
134 26 : Iterator& operator++() {
135 26 : MOZ_ASSERT(!Done());
136 26 : mHashIterator.Next();
137 26 : return *this;
138 : }
139 :
140 40 : dom::KeyframeEffectReadOnly* operator* ()
141 : {
142 40 : MOZ_ASSERT(!Done());
143 40 : return mHashIterator.Get()->GetKey();
144 : }
145 :
146 : private:
147 : Iterator() = delete;
148 : Iterator(const Iterator&) = delete;
149 : Iterator& operator=(const Iterator&) = delete;
150 : Iterator& operator=(const Iterator&&) = delete;
151 :
152 304 : bool Done() const {
153 304 : return mIsEndIterator || mHashIterator.Done();
154 : }
155 :
156 : EffectSet& mEffectSet;
157 : OwningEffectSet::Iterator mHashIterator;
158 : bool mIsEndIterator;
159 : };
160 :
161 : friend class Iterator;
162 :
163 40 : Iterator begin() { return Iterator(*this); }
164 40 : Iterator end() { return Iterator::EndIterator(*this); }
165 : #ifdef DEBUG
166 2 : bool IsBeingEnumerated() const { return mActiveIterators != 0; }
167 : #endif
168 :
169 10 : bool IsEmpty() const { return mEffects.IsEmpty(); }
170 :
171 12 : size_t Count() const { return mEffects.Count(); }
172 :
173 : RefPtr<AnimValuesStyleRule>&
174 30 : AnimationRule(EffectCompositor::CascadeLevel aCascadeLevel)
175 : {
176 30 : return mAnimationRule[aCascadeLevel];
177 : }
178 :
179 0 : const TimeStamp& LastTransformSyncTime() const
180 : {
181 0 : return mLastTransformSyncTime;
182 : }
183 0 : void UpdateLastTransformSyncTime(const TimeStamp& aRefreshTime)
184 : {
185 0 : mLastTransformSyncTime = aRefreshTime;
186 0 : }
187 :
188 44 : bool CascadeNeedsUpdate() const { return mCascadeNeedsUpdate; }
189 12 : void MarkCascadeNeedsUpdate() { mCascadeNeedsUpdate = true; }
190 8 : void MarkCascadeUpdated() { mCascadeNeedsUpdate = false; }
191 :
192 : void UpdateAnimationGeneration(nsPresContext* aPresContext);
193 14 : uint64_t GetAnimationGeneration() const { return mAnimationGeneration; }
194 :
195 : static nsIAtom** GetEffectSetPropertyAtoms();
196 :
197 26 : nsCSSPropertyIDSet& PropertiesWithImportantRules()
198 : {
199 26 : return mPropertiesWithImportantRules;
200 : }
201 12 : nsCSSPropertyIDSet& PropertiesForAnimationsLevel()
202 : {
203 12 : return mPropertiesForAnimationsLevel;
204 : }
205 : nsCSSPropertyIDSet PropertiesForAnimationsLevel() const
206 : {
207 : return mPropertiesForAnimationsLevel;
208 : }
209 :
210 : private:
211 : static nsIAtom* GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType);
212 :
213 : OwningEffectSet mEffects;
214 :
215 : // These style rules contain the style data for currently animating
216 : // values. They only match when styling with animation. When we
217 : // style without animation, we need to not use them so that we can
218 : // detect any new changes; if necessary we restyle immediately
219 : // afterwards with animation.
220 : EnumeratedArray<EffectCompositor::CascadeLevel,
221 : EffectCompositor::CascadeLevel(
222 : EffectCompositor::kCascadeLevelCount),
223 : RefPtr<AnimValuesStyleRule>> mAnimationRule;
224 :
225 : // Refresh driver timestamp from the moment when transform animations in this
226 : // effect set were last updated and sent to the compositor. This is used for
227 : // transform animations that run on the compositor but need to be updated on
228 : // the main thread periodically (e.g. so scrollbars can be updated).
229 : TimeStamp mLastTransformSyncTime;
230 :
231 : // Dirty flag to represent when the mPropertiesWithImportantRules and
232 : // mPropertiesForAnimationsLevel on effects in this set might need to be
233 : // updated.
234 : //
235 : // Set to true any time the set of effects is changed or when
236 : // one the effects goes in or out of the "in effect" state.
237 : bool mCascadeNeedsUpdate;
238 :
239 : // RestyleManager keeps track of the number of animation restyles.
240 : // 'mini-flushes' (see nsTransitionManager::UpdateAllThrottledStyles()).
241 : // mAnimationGeneration is the sequence number of the last flush where a
242 : // transition/animation changed. We keep a similar count on the
243 : // corresponding layer so we can check that the layer is up to date with
244 : // the animation manager.
245 : uint64_t mAnimationGeneration;
246 :
247 : // Specifies the compositor-animatable properties that are overridden by
248 : // !important rules.
249 : nsCSSPropertyIDSet mPropertiesWithImportantRules;
250 : // Specifies the properties for which the result will be added to the
251 : // animations level of the cascade and hence should be skipped when we are
252 : // composing the animation style for the transitions level of the cascede.
253 : nsCSSPropertyIDSet mPropertiesForAnimationsLevel;
254 :
255 : #ifdef DEBUG
256 : // Track how many iterators are referencing this effect set when we are
257 : // destroyed, we can assert that nothing is still pointing to us.
258 : uint64_t mActiveIterators;
259 :
260 : bool mCalledPropertyDtor;
261 : #endif
262 :
263 : bool mMayHaveOpacityAnim;
264 : bool mMayHaveTransformAnim;
265 : };
266 :
267 : } // namespace mozilla
268 :
269 : #endif // mozilla_EffectSet_h
|