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_EffectSet_h
8 #define mozilla_EffectSet_h
10 #include "mozilla/DebugOnly.h"
11 #include "mozilla/EffectCompositor.h"
12 #include "mozilla/EnumeratedArray.h"
13 #include "mozilla/TimeStamp.h"
14 #include "mozilla/dom/KeyframeEffect.h"
15 #include "nsHashKeys.h" // For nsPtrHashKey
16 #include "nsTHashSet.h"
19 enum class DisplayItemType
: uint8_t;
27 enum class PseudoStyleType
: uint8_t;
29 // A wrapper around a hashset of AnimationEffect objects to handle
30 // storing the set as a property of an element.
34 : mCascadeNeedsUpdate(false),
35 mMayHaveOpacityAnim(false),
36 mMayHaveTransformAnim(false) {
37 MOZ_COUNT_CTOR(EffectSet
);
41 MOZ_ASSERT(!IsBeingEnumerated(),
42 "Effect set should not be destroyed while it is being "
44 MOZ_COUNT_DTOR(EffectSet
);
47 // Methods for supporting cycle-collection
48 void Traverse(nsCycleCollectionTraversalCallback
& aCallback
);
50 static EffectSet
* Get(const dom::Element
* aElement
,
51 PseudoStyleType aPseudoType
);
52 static EffectSet
* GetOrCreate(dom::Element
* aElement
,
53 PseudoStyleType aPseudoType
);
55 static EffectSet
* GetForFrame(const nsIFrame
* aFrame
,
56 const nsCSSPropertyIDSet
& aProperties
);
57 static EffectSet
* GetForFrame(const nsIFrame
* aFrame
,
58 DisplayItemType aDisplayItemType
);
59 // Gets the EffectSet associated with the specified frame's content.
61 // Typically the specified frame should be a "style frame".
63 // That is because display:table content:
65 // - makes a distinction between the primary frame and style frame,
66 // - associates the EffectSet with the style frame's content,
67 // - applies transform animations to the primary frame.
69 // In such a situation, passing in the primary frame here will return nullptr
70 // despite the fact that it has a transform animation applied to it.
72 // GetForFrame, above, handles this by automatically looking up the
73 // EffectSet on the corresponding style frame when querying transform
74 // properties. Unless you are sure you know what you are doing, you should
75 // try using GetForFrame first.
77 // If you decide to use this, consider documenting why you are sure it is ok
79 static EffectSet
* GetForStyleFrame(const nsIFrame
* aStyleFrame
);
81 static EffectSet
* GetForEffect(const dom::KeyframeEffect
* aEffect
);
83 static void DestroyEffectSet(dom::Element
* aElement
,
84 PseudoStyleType aPseudoType
);
86 void AddEffect(dom::KeyframeEffect
& aEffect
);
87 void RemoveEffect(dom::KeyframeEffect
& aEffect
);
89 void SetMayHaveOpacityAnimation() { mMayHaveOpacityAnim
= true; }
90 bool MayHaveOpacityAnimation() const { return mMayHaveOpacityAnim
; }
91 void SetMayHaveTransformAnimation() { mMayHaveTransformAnim
= true; }
92 bool MayHaveTransformAnimation() const { return mMayHaveTransformAnim
; }
95 using OwningEffectSet
= nsTHashSet
<nsRefPtrHashKey
<dom::KeyframeEffect
>>;
98 // A simple iterator to support iterating over the effects in this object in
99 // range-based for loops.
101 // This allows us to avoid exposing mEffects directly and saves the
102 // caller from having to dereference hashtable iterators using
103 // the rather complicated: iter.Get()->GetKey().
105 // XXX Except for the active iterator checks, this could be replaced by the
106 // STL-style iterators of nsTHashSet directly now.
109 explicit Iterator(EffectSet
& aEffectSet
)
110 : Iterator(aEffectSet
, aEffectSet
.mEffects
.begin()) {}
113 Iterator(const Iterator
&) = delete;
114 Iterator(Iterator
&&) = delete;
115 Iterator
& operator=(const Iterator
&) = delete;
116 Iterator
& operator=(Iterator
&&) = delete;
118 static Iterator
EndIterator(EffectSet
& aEffectSet
) {
119 return {aEffectSet
, aEffectSet
.mEffects
.end()};
124 MOZ_ASSERT(mEffectSet
.mActiveIterators
> 0);
125 mEffectSet
.mActiveIterators
--;
129 bool operator!=(const Iterator
& aOther
) const {
130 return mHashIterator
!= aOther
.mHashIterator
;
133 Iterator
& operator++() {
138 dom::KeyframeEffect
* operator*() { return *mHashIterator
; }
141 Iterator(EffectSet
& aEffectSet
,
142 OwningEffectSet::const_iterator aHashIterator
)
145 mEffectSet(aEffectSet
),
147 mHashIterator(std::move(aHashIterator
)) {
149 mEffectSet
.mActiveIterators
++;
154 EffectSet
& mEffectSet
;
156 OwningEffectSet::const_iterator mHashIterator
;
159 friend class Iterator
;
161 Iterator
begin() { return Iterator(*this); }
162 Iterator
end() { return Iterator::EndIterator(*this); }
164 bool IsBeingEnumerated() const { return mActiveIterators
!= 0; }
167 bool IsEmpty() const { return mEffects
.IsEmpty(); }
169 size_t Count() const { return mEffects
.Count(); }
171 const TimeStamp
& LastOverflowAnimationSyncTime() const {
172 return mLastOverflowAnimationSyncTime
;
174 void UpdateLastOverflowAnimationSyncTime(const TimeStamp
& aRefreshTime
) {
175 mLastOverflowAnimationSyncTime
= aRefreshTime
;
178 bool CascadeNeedsUpdate() const { return mCascadeNeedsUpdate
; }
179 void MarkCascadeNeedsUpdate() { mCascadeNeedsUpdate
= true; }
180 void MarkCascadeUpdated() { mCascadeNeedsUpdate
= false; }
182 void UpdateAnimationGeneration(nsPresContext
* aPresContext
);
183 uint64_t GetAnimationGeneration() const { return mAnimationGeneration
; }
185 const nsCSSPropertyIDSet
& PropertiesWithImportantRules() const {
186 return mPropertiesWithImportantRules
;
188 nsCSSPropertyIDSet
& PropertiesWithImportantRules() {
189 return mPropertiesWithImportantRules
;
191 nsCSSPropertyIDSet
PropertiesForAnimationsLevel() const {
192 return mPropertiesForAnimationsLevel
;
194 nsCSSPropertyIDSet
& PropertiesForAnimationsLevel() {
195 return mPropertiesForAnimationsLevel
;
199 OwningEffectSet mEffects
;
201 // Refresh driver timestamp from the moment when the animations which produce
202 // overflow change hints in this effect set were last updated.
204 // This is used for animations whose main-thread restyling is throttled either
205 // because they are running on the compositor or because they are not visible.
206 // We still need to update them on the main thread periodically, however (e.g.
207 // so scrollbars can be updated), so this tracks the last time we did that.
208 TimeStamp mLastOverflowAnimationSyncTime
;
210 // RestyleManager keeps track of the number of animation restyles.
211 // 'mini-flushes' (see nsTransitionManager::UpdateAllThrottledStyles()).
212 // mAnimationGeneration is the sequence number of the last flush where a
213 // transition/animation changed. We keep a similar count on the
214 // corresponding layer so we can check that the layer is up to date with
215 // the animation manager.
216 uint64_t mAnimationGeneration
= 0;
218 // Specifies the compositor-animatable properties that are overridden by
220 nsCSSPropertyIDSet mPropertiesWithImportantRules
;
221 // Specifies the properties for which the result will be added to the
222 // animations level of the cascade and hence should be skipped when we are
223 // composing the animation style for the transitions level of the cascede.
224 nsCSSPropertyIDSet mPropertiesForAnimationsLevel
;
227 // Track how many iterators are referencing this effect set when we are
228 // destroyed, we can assert that nothing is still pointing to us.
229 uint64_t mActiveIterators
= 0;
232 // Dirty flag to represent when the mPropertiesWithImportantRules and
233 // mPropertiesForAnimationsLevel on effects in this set might need to be
236 // Set to true any time the set of effects is changed or when
237 // one the effects goes in or out of the "in effect" state.
238 bool mCascadeNeedsUpdate
= false;
240 bool mMayHaveOpacityAnim
= false;
241 bool mMayHaveTransformAnim
= false;
244 } // namespace mozilla
246 #endif // mozilla_EffectSet_h