Coverage Report

Created: 2018-09-25 14:53

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