LCOV - code coverage report
Current view: top level - dom/animation - EffectCompositor.h (source / functions) Hit Total Coverage
Test: output.info Lines: 20 20 100.0 %
Date: 2017-07-14 16:53:18 Functions: 10 11 90.9 %
Legend: Lines: hit not hit

          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_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 "nsCSSPropertyID.h"
      16             : #include "nsCycleCollectionParticipant.h"
      17             : #include "nsDataHashtable.h"
      18             : #include "nsIStyleRuleProcessor.h"
      19             : #include "nsTArray.h"
      20             : 
      21             : class nsCSSPropertyIDSet;
      22             : class nsIAtom;
      23             : class nsIFrame;
      24             : class nsIStyleRule;
      25             : class nsPresContext;
      26             : class nsStyleContext;
      27             : struct RawServoAnimationValueMap;
      28             : typedef RawServoAnimationValueMap* RawServoAnimationValueMapBorrowedMut;
      29             : 
      30             : namespace mozilla {
      31             : 
      32             : class EffectSet;
      33             : class RestyleTracker;
      34             : class StyleAnimationValue;
      35             : struct AnimationPerformanceWarning;
      36             : struct AnimationProperty;
      37             : struct NonOwningAnimationTarget;
      38             : 
      39             : namespace dom {
      40             : class Animation;
      41             : class Element;
      42             : }
      43             : 
      44             : class EffectCompositor
      45             : {
      46             : public:
      47          28 :   explicit EffectCompositor(nsPresContext* aPresContext)
      48          28 :     : mPresContext(aPresContext)
      49             :   {
      50          84 :     for (size_t i = 0; i < kCascadeLevelCount; i++) {
      51          56 :       CascadeLevel cascadeLevel = CascadeLevel(i);
      52          56 :       mRuleProcessors[cascadeLevel] =
      53         112 :         new AnimationStyleRuleProcessor(this, cascadeLevel);
      54             :     }
      55          28 :   }
      56             : 
      57          32 :   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(EffectCompositor)
      58          41 :   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(EffectCompositor)
      59             : 
      60           4 :   void Disconnect() {
      61           4 :     mPresContext = nullptr;
      62           4 :   }
      63             : 
      64             :   // Animations can be applied at two different levels in the CSS cascade:
      65             :   enum class CascadeLevel : uint32_t {
      66             :     // The animations sheet (CSS animations, script-generated animations,
      67             :     // and CSS transitions that are no longer tied to CSS markup)
      68             :     Animations = 0,
      69             :     // The transitions sheet (CSS transitions that are tied to CSS markup)
      70             :     Transitions = 1
      71             :   };
      72             :   // We don't define this as part of CascadeLevel as then we'd have to add
      73             :   // explicit checks for the Count enum value everywhere CascadeLevel is used.
      74             :   static const size_t kCascadeLevelCount =
      75             :     static_cast<size_t>(CascadeLevel::Transitions) + 1;
      76             : 
      77             :   // NOTE: This can return null after Disconnect().
      78             :   nsPresContext* PresContext() const { return mPresContext; }
      79             : 
      80             :   enum class RestyleType {
      81             :     // Animation style has changed but the compositor is applying the same
      82             :     // change so we might be able to defer updating the main thread until it
      83             :     // becomes necessary.
      84             :     Throttled,
      85             :     // Animation style has changed and needs to be updated on the main thread.
      86             :     Standard,
      87             :     // Animation style has changed and needs to be updated on the main thread
      88             :     // as well as forcing animations on layers to be updated.
      89             :     // This is needed in cases such as when an animation becomes paused or has
      90             :     // its playback rate changed. In such cases, although the computed style
      91             :     // and refresh driver time might not change, we still need to ensure the
      92             :     // corresponding animations on layers are updated to reflect the new
      93             :     // configuration of the animation.
      94             :     Layer
      95             :   };
      96             : 
      97             :   // Notifies the compositor that the animation rule for the specified
      98             :   // (pseudo-)element at the specified cascade level needs to be updated.
      99             :   // The specified steps taken to update the animation rule depend on
     100             :   // |aRestyleType| whose values are described above.
     101             :   void RequestRestyle(dom::Element* aElement,
     102             :                       CSSPseudoElementType aPseudoType,
     103             :                       RestyleType aRestyleType,
     104             :                       CascadeLevel aCascadeLevel);
     105             : 
     106             :   // Schedule an animation restyle. This is called automatically by
     107             :   // RequestRestyle when necessary. However, it is exposed here since we also
     108             :   // need to perform this step when triggering transitions *without* also
     109             :   // invalidating the animation style rule (which RequestRestyle would do).
     110             :   void PostRestyleForAnimation(dom::Element* aElement,
     111             :                                CSSPseudoElementType aPseudoType,
     112             :                                CascadeLevel aCascadeLevel);
     113             : 
     114             :   // Posts an animation restyle for any elements whose animation style rule
     115             :   // is out of date but for which an animation restyle has not yet been
     116             :   // posted because updates on the main thread are throttled.
     117             :   void PostRestyleForThrottledAnimations();
     118             : 
     119             :   // Called when computed style on the specified (pseudo-) element might
     120             :   // have changed so that any context-sensitive values stored within
     121             :   // animation effects (e.g. em-based endpoints used in keyframe effects)
     122             :   // can be re-resolved to computed values.
     123             :   template<typename StyleType>
     124             :   void UpdateEffectProperties(StyleType* aStyleType,
     125             :                               dom::Element* aElement,
     126             :                               CSSPseudoElementType aPseudoType);
     127             : 
     128             :   // Updates the animation rule stored on the EffectSet for the
     129             :   // specified (pseudo-)element for cascade level |aLevel|.
     130             :   // If the animation rule is not marked as needing an update,
     131             :   // no work is done.
     132             :   // |aStyleContext| is used for UpdateCascadingResults.
     133             :   // |aStyleContext| can be nullptr if style context, which is associated with
     134             :   // the primary frame of the specified (pseudo-)element, is the current style
     135             :   // context.
     136             :   // If we are resolving a new style context, we shoud pass the newly created
     137             :   // style context, otherwise we may use an old style context, it will result
     138             :   // unexpected cascading results.
     139             :   void MaybeUpdateAnimationRule(dom::Element* aElement,
     140             :                                 CSSPseudoElementType aPseudoType,
     141             :                                 CascadeLevel aCascadeLevel,
     142             :                                 nsStyleContext *aStyleContext);
     143             : 
     144             :   // We need to pass the newly resolved style context as |aStyleContext| when
     145             :   // we call this function during resolving style context because this function
     146             :   // calls UpdateCascadingResults with a style context if necessary, at the
     147             :   // time, we end up using the previous style context if we don't pass the new
     148             :   // style context.
     149             :   // When we are not resolving style context, |aStyleContext| can be nullptr, we
     150             :   // will use a style context associated with the primary frame of the specified
     151             :   // (pseudo-)element.
     152             :   nsIStyleRule* GetAnimationRule(dom::Element* aElement,
     153             :                                  CSSPseudoElementType aPseudoType,
     154             :                                  CascadeLevel aCascadeLevel,
     155             :                                  nsStyleContext* aStyleContext);
     156             : 
     157             :   // Get animation rule for stylo. This is an equivalent of GetAnimationRule
     158             :   // and will be called from servo side.
     159             :   // The animation rule is stored in |RawServoAnimationValueMapBorrowed|.
     160             :   // We need to be careful while doing any modification because it may cause
     161             :   // some thread-safe issues.
     162             :   bool GetServoAnimationRule(
     163             :     const dom::Element* aElement,
     164             :     CSSPseudoElementType aPseudoType,
     165             :     CascadeLevel aCascadeLevel,
     166             :     RawServoAnimationValueMapBorrowedMut aAnimationValues);
     167             : 
     168             :   bool HasPendingStyleUpdates() const;
     169             :   bool HasThrottledStyleUpdates() const;
     170             : 
     171             :   // Tell the restyle tracker about all the animated styles that have
     172             :   // pending updates so that it can update the animation rule for these
     173             :   // elements.
     174             :   void AddStyleUpdatesTo(RestyleTracker& aTracker);
     175             : 
     176          56 :   nsIStyleRuleProcessor* RuleProcessor(CascadeLevel aCascadeLevel) const
     177             :   {
     178          56 :     return mRuleProcessors[aCascadeLevel];
     179             :   }
     180             : 
     181             :   static bool HasAnimationsForCompositor(const nsIFrame* aFrame,
     182             :                                          nsCSSPropertyID aProperty);
     183             : 
     184             :   static nsTArray<RefPtr<dom::Animation>>
     185             :   GetAnimationsForCompositor(const nsIFrame* aFrame,
     186             :                              nsCSSPropertyID aProperty);
     187             : 
     188             :   static void ClearIsRunningOnCompositor(const nsIFrame* aFrame,
     189             :                                          nsCSSPropertyID aProperty);
     190             : 
     191             :   // Update animation cascade results for the specified (pseudo-)element
     192             :   // but only if we have marked the cascade as needing an update due a
     193             :   // the change in the set of effects or a change in one of the effects'
     194             :   // "in effect" state.
     195             :   //
     196             :   // When |aBackendType| is StyleBackendType::Gecko, |aStyleContext| is used to
     197             :   // find overridden properties. If it is nullptr, the nsStyleContext of the
     198             :   // primary frame of the specified (pseudo-)element, if available, is used.
     199             :   //
     200             :   // When |aBackendType| is StyleBackendType::Servo, we fetch the rule node
     201             :   // from the |aElement| (i.e. |aStyleContext| is ignored).
     202             :   //
     203             :   // This method does NOT detect if other styles that apply above the
     204             :   // animation level of the cascade have changed.
     205             :   static void
     206             :   MaybeUpdateCascadeResults(StyleBackendType aBackendType,
     207             :                             dom::Element* aElement,
     208             :                             CSSPseudoElementType aPseudoType,
     209             :                             nsStyleContext* aStyleContext);
     210             : 
     211             :   // Helper to fetch the corresponding element and pseudo-type from a frame.
     212             :   //
     213             :   // For frames corresponding to pseudo-elements, the returned element is the
     214             :   // element on which we store the animations (i.e. the EffectSet and/or
     215             :   // AnimationCollection), *not* the generated content.
     216             :   //
     217             :   // Returns an empty result when a suitable element cannot be found including
     218             :   // when the frame represents a pseudo-element on which we do not support
     219             :   // animations.
     220             :   static Maybe<NonOwningAnimationTarget>
     221             :   GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame);
     222             : 
     223             :   // Associates a performance warning with effects on |aFrame| that animates
     224             :   // |aProperty|.
     225             :   static void SetPerformanceWarning(
     226             :     const nsIFrame* aFrame,
     227             :     nsCSSPropertyID aProperty,
     228             :     const AnimationPerformanceWarning& aWarning);
     229             : 
     230             :   // The type which represents what kind of animation restyle we want.
     231             :   enum class AnimationRestyleType {
     232             :     Throttled, // Restyle elements that have posted animation restyles.
     233             :     Full       // Restyle all elements with animations (i.e. even if the
     234             :                // animations are throttled).
     235             :   };
     236             : 
     237             :   // Do a bunch of stuff that we should avoid doing during the parallel
     238             :   // traversal (e.g. changing member variables) for all elements that we expect
     239             :   // to restyle on the next traversal.
     240             :   //
     241             :   // Returns true if there are elements needing a restyle for animation.
     242             :   bool PreTraverse(AnimationRestyleType aRestyleType);
     243             : 
     244             :   // Similar to the above but only for the (pseudo-)element.
     245             :   bool PreTraverse(dom::Element* aElement, CSSPseudoElementType aPseudoType);
     246             : 
     247             :   // Similar to the above but for all elements in the subtree rooted
     248             :   // at aElement.
     249             :   bool PreTraverseInSubtree(dom::Element* aElement,
     250             :                             AnimationRestyleType aRestyleType);
     251             : 
     252             :   // Returns the target element for restyling.
     253             :   //
     254             :   // If |aPseudoType| is ::after or ::before, returns the generated content
     255             :   // element of which |aElement| is the parent. If |aPseudoType| is any other
     256             :   // pseudo type (other thant CSSPseudoElementType::NotPseudo) returns nullptr.
     257             :   // Otherwise, returns |aElement|.
     258             :   static dom::Element* GetElementToRestyle(dom::Element* aElement,
     259             :                                            CSSPseudoElementType aPseudoType);
     260             : 
     261             : private:
     262           3 :   ~EffectCompositor() = default;
     263             : 
     264             :   // Rebuilds the animation rule corresponding to |aCascadeLevel| on the
     265             :   // EffectSet associated with the specified (pseudo-)element.
     266             :   static void ComposeAnimationRule(dom::Element* aElement,
     267             :                                    CSSPseudoElementType aPseudoType,
     268             :                                    CascadeLevel aCascadeLevel);
     269             : 
     270             :   // Get the properties in |aEffectSet| that we are able to animate on the
     271             :   // compositor but which are also specified at a higher level in the cascade
     272             :   // than the animations level.
     273             :   //
     274             :   // When |aBackendType| is StyleBackendType::Gecko, we determine which
     275             :   // properties are specified using the provided |aStyleContext| and
     276             :   // |aElement| and |aPseudoType| are ignored. If |aStyleContext| is nullptr,
     277             :   // we automatically look up the style context of primary frame of the
     278             :   // (pseudo-)element.
     279             :   //
     280             :   // When |aBackendType| is StyleBackendType::Servo, we use the |StrongRuleNode|
     281             :   // stored on the (pseudo-)element indicated by |aElement| and |aPseudoType|.
     282             :   static nsCSSPropertyIDSet
     283             :   GetOverriddenProperties(StyleBackendType aBackendType,
     284             :                           EffectSet& aEffectSet,
     285             :                           dom::Element* aElement,
     286             :                           CSSPseudoElementType aPseudoType,
     287             :                           nsStyleContext* aStyleContext);
     288             : 
     289             :   // Update the mPropertiesWithImportantRules and
     290             :   // mPropertiesForAnimationsLevel members of the given EffectSet.
     291             :   //
     292             :   // This can be expensive so we should only call it if styles that apply
     293             :   // above the animation level of the cascade might have changed. For all
     294             :   // other cases we should call MaybeUpdateCascadeResults.
     295             :   //
     296             :   // As with MaybeUpdateCascadeResults, |aStyleContext| is only used
     297             :   // when |aBackendType| is StyleBackendType::Gecko. When |aBackendType| is
     298             :   // StyleBackendType::Servo, it is ignored.
     299             :   static void
     300             :   UpdateCascadeResults(StyleBackendType aBackendType,
     301             :                        EffectSet& aEffectSet,
     302             :                        dom::Element* aElement,
     303             :                        CSSPseudoElementType aPseudoType,
     304             :                        nsStyleContext* aStyleContext);
     305             : 
     306             :   static nsPresContext* GetPresContext(dom::Element* aElement);
     307             : 
     308             :   nsPresContext* mPresContext;
     309             : 
     310             :   // Elements with a pending animation restyle. The associated bool value is
     311             :   // true if a pending animation restyle has also been dispatched. For
     312             :   // animations that can be throttled, we will add an entry to the hashtable to
     313             :   // indicate that the style rule on the element is out of date but without
     314             :   // posting a restyle to update it.
     315             :   EnumeratedArray<CascadeLevel, CascadeLevel(kCascadeLevelCount),
     316             :                   nsDataHashtable<PseudoElementHashEntry, bool>>
     317             :                     mElementsToRestyle;
     318             : 
     319             :   bool mIsInPreTraverse = false;
     320             : 
     321             :   class AnimationStyleRuleProcessor final : public nsIStyleRuleProcessor
     322             :   {
     323             :   public:
     324          56 :     AnimationStyleRuleProcessor(EffectCompositor* aCompositor,
     325             :                                 CascadeLevel aCascadeLevel)
     326          56 :       : mCompositor(aCompositor)
     327          56 :       , mCascadeLevel(aCascadeLevel)
     328             :     {
     329          56 :       MOZ_ASSERT(aCompositor);
     330          56 :     }
     331             : 
     332             :     NS_DECL_ISUPPORTS
     333             : 
     334             :     // nsIStyleRuleProcessor (parts)
     335             :     nsRestyleHint HasStateDependentStyle(
     336             :                         StateRuleProcessorData* aData) override;
     337             :     nsRestyleHint HasStateDependentStyle(
     338             :                         PseudoElementStateRuleProcessorData* aData) override;
     339             :     bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override;
     340             :     nsRestyleHint HasAttributeDependentStyle(
     341             :                         AttributeRuleProcessorData* aData,
     342             :                         RestyleHintData& aRestyleHintDataResult) override;
     343             :     bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
     344             :     void RulesMatching(ElementRuleProcessorData* aData) override;
     345             :     void RulesMatching(PseudoElementRuleProcessorData* aData) override;
     346             :     void RulesMatching(AnonBoxRuleProcessorData* aData) override;
     347             : #ifdef MOZ_XUL
     348             :     void RulesMatching(XULTreeRuleProcessorData* aData) override;
     349             : #endif
     350             :     size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf)
     351             :       const MOZ_MUST_OVERRIDE override;
     352             :     size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
     353             :       const MOZ_MUST_OVERRIDE override;
     354             : 
     355             :   private:
     356             :     ~AnimationStyleRuleProcessor() = default;
     357             : 
     358             :     EffectCompositor* mCompositor;
     359             :     CascadeLevel      mCascadeLevel;
     360             :   };
     361             : 
     362             :   EnumeratedArray<CascadeLevel, CascadeLevel(kCascadeLevelCount),
     363             :                   OwningNonNull<AnimationStyleRuleProcessor>>
     364             :                     mRuleProcessors;
     365             : };
     366             : 
     367             : } // namespace mozilla
     368             : 
     369             : #endif // mozilla_EffectCompositor_h

Generated by: LCOV version 1.13