tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

EffectSet.h (9134B)


      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/AnimationTarget.h"
     11 #include "mozilla/EffectCompositor.h"
     12 #include "mozilla/TimeStamp.h"
     13 #include "mozilla/dom/KeyframeEffect.h"
     14 #include "nsHashKeys.h"  // For nsPtrHashKey
     15 #include "nsTHashSet.h"
     16 
     17 class nsPresContext;
     18 enum class DisplayItemType : uint8_t;
     19 
     20 namespace mozilla {
     21 
     22 namespace dom {
     23 class Element;
     24 }  // namespace dom
     25 
     26 struct PseudoStyleRequest;
     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 public:
     32  EffectSet()
     33      : mCascadeNeedsUpdate(false),
     34        mMayHaveOpacityAnim(false),
     35        mMayHaveTransformAnim(false) {
     36    MOZ_COUNT_CTOR(EffectSet);
     37  }
     38 
     39  ~EffectSet() {
     40    MOZ_ASSERT(!IsBeingEnumerated(),
     41               "Effect set should not be destroyed while it is being "
     42               "enumerated");
     43    MOZ_COUNT_DTOR(EffectSet);
     44  }
     45 
     46  // Methods for supporting cycle-collection
     47  void Traverse(nsCycleCollectionTraversalCallback& aCallback);
     48 
     49  static EffectSet* Get(const dom::Element* aElement,
     50                        const PseudoStyleRequest& aPseudoRequest);
     51  static EffectSet* Get(const NonOwningAnimationTarget& aTarget) {
     52    return Get(aTarget.mElement, aTarget.mPseudoRequest);
     53  }
     54  static EffectSet* Get(const OwningAnimationTarget& aTarget) {
     55    return Get(aTarget.mElement, aTarget.mPseudoRequest);
     56  }
     57 
     58  static EffectSet* GetOrCreate(dom::Element* aElement,
     59                                const PseudoStyleRequest& aPseudoRequest);
     60  static EffectSet* GetOrCreate(const OwningAnimationTarget& aTarget) {
     61    return GetOrCreate(aTarget.mElement, aTarget.mPseudoRequest);
     62  }
     63 
     64  static EffectSet* GetForFrame(const nsIFrame* aFrame,
     65                                const nsCSSPropertyIDSet& aProperties);
     66  static EffectSet* GetForFrame(const nsIFrame* aFrame,
     67                                DisplayItemType aDisplayItemType);
     68  // Gets the EffectSet associated with the specified frame's content.
     69  //
     70  // Typically the specified frame should be a "style frame".
     71  //
     72  // That is because display:table content:
     73  //
     74  // - makes a distinction between the primary frame and style frame,
     75  // - associates the EffectSet with the style frame's content,
     76  // - applies transform animations to the primary frame.
     77  //
     78  // In such a situation, passing in the primary frame here will return nullptr
     79  // despite the fact that it has a transform animation applied to it.
     80  //
     81  // GetForFrame, above, handles this by automatically looking up the
     82  // EffectSet on the corresponding style frame when querying transform
     83  // properties. Unless you are sure you know what you are doing, you should
     84  // try using GetForFrame first.
     85  //
     86  // If you decide to use this, consider documenting why you are sure it is ok
     87  // to use this.
     88  static EffectSet* GetForStyleFrame(const nsIFrame* aStyleFrame);
     89 
     90  static EffectSet* GetForEffect(const dom::KeyframeEffect* aEffect);
     91 
     92  static void DestroyEffectSet(dom::Element* aElement,
     93                               const PseudoStyleRequest& aPseudoRequest);
     94  static void DestroyEffectSet(const OwningAnimationTarget& aTarget) {
     95    return DestroyEffectSet(aTarget.mElement, aTarget.mPseudoRequest);
     96  }
     97 
     98  void AddEffect(dom::KeyframeEffect& aEffect);
     99  void RemoveEffect(dom::KeyframeEffect& aEffect);
    100 
    101  void SetMayHaveOpacityAnimation() { mMayHaveOpacityAnim = true; }
    102  bool MayHaveOpacityAnimation() const { return mMayHaveOpacityAnim; }
    103  void SetMayHaveTransformAnimation() { mMayHaveTransformAnim = true; }
    104  bool MayHaveTransformAnimation() const { return mMayHaveTransformAnim; }
    105 
    106 private:
    107  using OwningEffectSet = nsTHashSet<nsRefPtrHashKey<dom::KeyframeEffect>>;
    108 
    109 public:
    110  // A simple iterator to support iterating over the effects in this object in
    111  // range-based for loops.
    112  //
    113  // This allows us to avoid exposing mEffects directly and saves the
    114  // caller from having to dereference hashtable iterators using
    115  // the rather complicated: iter.Get()->GetKey().
    116  //
    117  // XXX Except for the active iterator checks, this could be replaced by the
    118  // STL-style iterators of nsTHashSet directly now.
    119  class Iterator {
    120   public:
    121    explicit Iterator(EffectSet& aEffectSet)
    122        : Iterator(aEffectSet, aEffectSet.mEffects.begin()) {}
    123 
    124    Iterator() = delete;
    125    Iterator(const Iterator&) = delete;
    126    Iterator(Iterator&&) = delete;
    127    Iterator& operator=(const Iterator&) = delete;
    128    Iterator& operator=(Iterator&&) = delete;
    129 
    130    static Iterator EndIterator(EffectSet& aEffectSet) {
    131      return {aEffectSet, aEffectSet.mEffects.end()};
    132    }
    133 
    134 #ifdef DEBUG
    135    ~Iterator() {
    136      MOZ_ASSERT(mEffectSet.mActiveIterators > 0);
    137      mEffectSet.mActiveIterators--;
    138    }
    139 #endif
    140 
    141    bool operator!=(const Iterator& aOther) const {
    142      return mHashIterator != aOther.mHashIterator;
    143    }
    144 
    145    Iterator& operator++() {
    146      ++mHashIterator;
    147      return *this;
    148    }
    149 
    150    dom::KeyframeEffect* operator*() { return *mHashIterator; }
    151 
    152   private:
    153    Iterator(EffectSet& aEffectSet,
    154             OwningEffectSet::const_iterator aHashIterator)
    155        :
    156 #ifdef DEBUG
    157          mEffectSet(aEffectSet),
    158 #endif
    159          mHashIterator(std::move(aHashIterator)) {
    160 #ifdef DEBUG
    161      mEffectSet.mActiveIterators++;
    162 #endif
    163    }
    164 
    165 #ifdef DEBUG
    166    EffectSet& mEffectSet;
    167 #endif
    168    OwningEffectSet::const_iterator mHashIterator;
    169  };
    170 
    171  friend class Iterator;
    172 
    173  Iterator begin() { return Iterator(*this); }
    174  Iterator end() { return Iterator::EndIterator(*this); }
    175 #ifdef DEBUG
    176  bool IsBeingEnumerated() const { return mActiveIterators != 0; }
    177 #endif
    178 
    179  bool IsEmpty() const { return mEffects.IsEmpty(); }
    180 
    181  size_t Count() const { return mEffects.Count(); }
    182 
    183  const TimeStamp& LastOverflowAnimationSyncTime() const {
    184    return mLastOverflowAnimationSyncTime;
    185  }
    186  void UpdateLastOverflowAnimationSyncTime(const TimeStamp& aRefreshTime) {
    187    mLastOverflowAnimationSyncTime = aRefreshTime;
    188  }
    189 
    190  bool CascadeNeedsUpdate() const { return mCascadeNeedsUpdate; }
    191  void MarkCascadeNeedsUpdate() { mCascadeNeedsUpdate = true; }
    192  void MarkCascadeUpdated() { mCascadeNeedsUpdate = false; }
    193 
    194  void UpdateAnimationGeneration(nsPresContext* aPresContext);
    195  uint64_t GetAnimationGeneration() const { return mAnimationGeneration; }
    196 
    197  const nsCSSPropertyIDSet& PropertiesWithImportantRules() const {
    198    return mPropertiesWithImportantRules;
    199  }
    200  nsCSSPropertyIDSet& PropertiesWithImportantRules() {
    201    return mPropertiesWithImportantRules;
    202  }
    203  const AnimatedPropertyIDSet& PropertiesForAnimationsLevel() const {
    204    return mPropertiesForAnimationsLevel;
    205  }
    206  AnimatedPropertyIDSet& PropertiesForAnimationsLevel() {
    207    return mPropertiesForAnimationsLevel;
    208  }
    209 
    210 private:
    211  OwningEffectSet mEffects;
    212 
    213  // Refresh driver timestamp from the moment when the animations which produce
    214  // overflow change hints in this effect set were last updated.
    215 
    216  // This is used for animations whose main-thread restyling is throttled either
    217  // because they are running on the compositor or because they are not visible.
    218  // We still need to update them on the main thread periodically, however (e.g.
    219  // so scrollbars can be updated), so this tracks the last time we did that.
    220  TimeStamp mLastOverflowAnimationSyncTime;
    221 
    222  // RestyleManager keeps track of the number of animation restyles.
    223  // 'mini-flushes' (see nsTransitionManager::UpdateAllThrottledStyles()).
    224  // mAnimationGeneration is the sequence number of the last flush where a
    225  // transition/animation changed.  We keep a similar count on the
    226  // corresponding layer so we can check that the layer is up to date with
    227  // the animation manager.
    228  uint64_t mAnimationGeneration = 0;
    229 
    230  // Specifies the compositor-animatable properties that are overridden by
    231  // !important rules.
    232  nsCSSPropertyIDSet mPropertiesWithImportantRules;
    233  // Specifies the properties for which the result will be added to the
    234  // animations level of the cascade and hence should be skipped when we are
    235  // composing the animation style for the transitions level of the cascede.
    236  AnimatedPropertyIDSet mPropertiesForAnimationsLevel;
    237 
    238 #ifdef DEBUG
    239  // Track how many iterators are referencing this effect set when we are
    240  // destroyed, we can assert that nothing is still pointing to us.
    241  uint64_t mActiveIterators = 0;
    242 #endif
    243 
    244  // Dirty flag to represent when the mPropertiesWithImportantRules and
    245  // mPropertiesForAnimationsLevel on effects in this set might need to be
    246  // updated.
    247  //
    248  // Set to true any time the set of effects is changed or when
    249  // one the effects goes in or out of the "in effect" state.
    250  bool mCascadeNeedsUpdate = false;
    251 
    252  bool mMayHaveOpacityAnim = false;
    253  bool mMayHaveTransformAnim = false;
    254 };
    255 
    256 }  // namespace mozilla
    257 
    258 #endif  // mozilla_EffectSet_h