LCOV - code coverage report
Current view: top level - layout/painting - ActiveLayerTracker.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 54 202 26.7 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
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             : #include "ActiveLayerTracker.h"
       8             : 
       9             : #include "mozilla/AnimationUtils.h"
      10             : #include "mozilla/ArrayUtils.h"
      11             : #include "mozilla/gfx/Matrix.h"
      12             : #include "mozilla/EffectSet.h"
      13             : #include "mozilla/PodOperations.h"
      14             : #include "gfx2DGlue.h"
      15             : #include "nsExpirationTracker.h"
      16             : #include "nsContainerFrame.h"
      17             : #include "nsIContent.h"
      18             : #include "nsRefreshDriver.h"
      19             : #include "nsPIDOMWindow.h"
      20             : #include "nsIDocument.h"
      21             : #include "nsAnimationManager.h"
      22             : #include "nsStyleTransformMatrix.h"
      23             : #include "nsTransitionManager.h"
      24             : #include "nsDisplayList.h"
      25             : #include "nsDOMCSSDeclaration.h"
      26             : 
      27             : namespace mozilla {
      28             : 
      29             : using namespace gfx;
      30             : 
      31             : /**
      32             :  * This tracks the state of a frame that may need active layers due to
      33             :  * ongoing content changes or style changes that indicate animation.
      34             :  *
      35             :  * When no changes of *any* kind are detected after 75-100ms we remove this
      36             :  * object. Because we only track all kinds of activity with a single
      37             :  * nsExpirationTracker, it's possible a frame might remain active somewhat
      38             :  * spuriously if different kinds of changes kept happening, but that almost
      39             :  * certainly doesn't matter.
      40             :  */
      41             : class LayerActivity {
      42             : public:
      43             :   enum ActivityIndex {
      44             :     ACTIVITY_OPACITY,
      45             :     ACTIVITY_TRANSFORM,
      46             :     ACTIVITY_LEFT,
      47             :     ACTIVITY_TOP,
      48             :     ACTIVITY_RIGHT,
      49             :     ACTIVITY_BOTTOM,
      50             :     ACTIVITY_BACKGROUND_POSITION,
      51             : 
      52             :     ACTIVITY_SCALE,
      53             :     ACTIVITY_TRIGGERED_REPAINT,
      54             : 
      55             :     // keep as last item
      56             :     ACTIVITY_COUNT
      57             :   };
      58             : 
      59           0 :   explicit LayerActivity(nsIFrame* aFrame)
      60           4 :     : mFrame(aFrame)
      61             :     , mContent(nullptr)
      62          20 :     , mContentActive(false)
      63             :   {
      64           0 :     PodArrayZero(mRestyleCounts);
      65           4 :   }
      66             :   ~LayerActivity();
      67             :   nsExpirationState* GetExpirationState() { return &mState; }
      68             :   uint8_t& RestyleCountForProperty(nsCSSPropertyID aProperty)
      69             :   {
      70           6 :     return mRestyleCounts[GetActivityIndexForProperty(aProperty)];
      71             :   }
      72             : 
      73           6 :   static ActivityIndex GetActivityIndexForProperty(nsCSSPropertyID aProperty)
      74             :   {
      75           6 :     switch (aProperty) {
      76             :     case eCSSProperty_opacity: return ACTIVITY_OPACITY;
      77           0 :     case eCSSProperty_transform: return ACTIVITY_TRANSFORM;
      78           0 :     case eCSSProperty_left: return ACTIVITY_LEFT;
      79           0 :     case eCSSProperty_top: return ACTIVITY_TOP;
      80           0 :     case eCSSProperty_right: return ACTIVITY_RIGHT;
      81           0 :     case eCSSProperty_bottom: return ACTIVITY_BOTTOM;
      82           0 :     case eCSSProperty_background_position: return ACTIVITY_BACKGROUND_POSITION;
      83           0 :     case eCSSProperty_background_position_x: return ACTIVITY_BACKGROUND_POSITION;
      84           0 :     case eCSSProperty_background_position_y: return ACTIVITY_BACKGROUND_POSITION;
      85           0 :     default: MOZ_ASSERT(false); return ACTIVITY_OPACITY;
      86             :     }
      87             :   }
      88             : 
      89             :   // While tracked, exactly one of mFrame or mContent is non-null, depending
      90             :   // on whether this property is stored on a frame or on a content node.
      91             :   // When this property is expired by the layer activity tracker, both mFrame
      92             :   // and mContent are nulled-out and the property is deleted.
      93             :   nsIFrame* mFrame;
      94             :   nsIContent* mContent;
      95             : 
      96             :   nsExpirationState mState;
      97             : 
      98             :   // Previous scale due to the CSS transform property.
      99             :   Maybe<Size> mPreviousTransformScale;
     100             : 
     101             :   // The scroll frame during for which we most recently received a call to
     102             :   // NotifyAnimatedFromScrollHandler.
     103             :   WeakFrame mAnimatingScrollHandlerFrame;
     104             :   // The set of activities that were triggered during
     105             :   // mAnimatingScrollHandlerFrame's scroll event handler.
     106             :   EnumSet<ActivityIndex> mScrollHandlerInducedActivity;
     107             : 
     108             :   // Number of restyle operations detected
     109             :   uint8_t mRestyleCounts[ACTIVITY_COUNT];
     110             :   bool mContentActive;
     111             : };
     112             : 
     113             : class LayerActivityTracker final : public nsExpirationTracker<LayerActivity,4> {
     114             : public:
     115             :   // 75-100ms is a good timeout period. We use 4 generations of 25ms each.
     116             :   enum { GENERATION_MS = 100 };
     117           0 :   explicit LayerActivityTracker(nsIEventTarget* aEventTarget)
     118           1 :     : nsExpirationTracker<LayerActivity,4>(GENERATION_MS,
     119             :                                            "LayerActivityTracker",
     120             :                                            aEventTarget)
     121           0 :     , mDestroying(false)
     122           0 :   {}
     123           0 :   ~LayerActivityTracker() {
     124           0 :     mDestroying = true;
     125           0 :     AgeAllGenerations();
     126           0 :   }
     127             : 
     128             :   virtual void NotifyExpired(LayerActivity* aObject) override;
     129             : 
     130             : public:
     131             :   WeakFrame mCurrentScrollHandlerFrame;
     132             : 
     133             : private:
     134             :   bool mDestroying;
     135             : };
     136             : 
     137             : static LayerActivityTracker* gLayerActivityTracker = nullptr;
     138             : 
     139          12 : LayerActivity::~LayerActivity()
     140             : {
     141           0 :   if (mFrame || mContent) {
     142           0 :     NS_ASSERTION(gLayerActivityTracker, "Should still have a tracker");
     143           0 :     gLayerActivityTracker->RemoveObject(this);
     144             :   }
     145           4 : }
     146             : 
     147             : // Frames with this property have NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY set
     148             : NS_DECLARE_FRAME_PROPERTY_DELETABLE(LayerActivityProperty, LayerActivity)
     149             : 
     150             : void
     151           4 : LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
     152             : {
     153           8 :   if (!mDestroying && aObject->mAnimatingScrollHandlerFrame.IsAlive()) {
     154             :     // Reset the restyle counts, but let the layer activity survive.
     155           0 :     PodArrayZero(aObject->mRestyleCounts);
     156           0 :     MarkUsed(aObject);
     157           0 :     return;
     158             :   }
     159             : 
     160           4 :   RemoveObject(aObject);
     161             : 
     162           0 :   nsIFrame* f = aObject->mFrame;
     163           0 :   nsIContent* c = aObject->mContent;
     164           0 :   aObject->mFrame = nullptr;
     165           4 :   aObject->mContent = nullptr;
     166             : 
     167           4 :   MOZ_ASSERT((f == nullptr) != (c == nullptr),
     168             :              "A LayerActivity object should always have a reference to either its frame or its content");
     169             : 
     170           4 :   if (f) {
     171             :     // The pres context might have been detached during the delay -
     172             :     // that's fine, just skip the paint.
     173           0 :     if (f->PresContext()->GetContainerWeak()) {
     174           4 :       f->SchedulePaint();
     175             :     }
     176           0 :     f->RemoveStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
     177           4 :     f->DeleteProperty(LayerActivityProperty());
     178             :   } else {
     179           0 :     c->DeleteProperty(nsGkAtoms::LayerActivity);
     180             :   }
     181             : }
     182             : 
     183             : static LayerActivity*
     184         869 : GetLayerActivity(nsIFrame* aFrame)
     185             : {
     186        1738 :   if (!aFrame->HasAnyStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY)) {
     187             :     return nullptr;
     188             :   }
     189           4 :   return aFrame->GetProperty(LayerActivityProperty());
     190             : }
     191             : 
     192             : static LayerActivity*
     193           6 : GetLayerActivityForUpdate(nsIFrame* aFrame)
     194             : {
     195           0 :   LayerActivity* layerActivity = GetLayerActivity(aFrame);
     196           0 :   if (layerActivity) {
     197           2 :     gLayerActivityTracker->MarkUsed(layerActivity);
     198             :   } else {
     199           0 :     if (!gLayerActivityTracker) {
     200           0 :       gLayerActivityTracker = new LayerActivityTracker(
     201           2 :         SystemGroup::EventTargetFor(TaskCategory::Other));
     202             :     }
     203           0 :     layerActivity = new LayerActivity(aFrame);
     204           0 :     gLayerActivityTracker->AddObject(layerActivity);
     205           0 :     aFrame->AddStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
     206           4 :     aFrame->SetProperty(LayerActivityProperty(), layerActivity);
     207             :   }
     208           6 :   return layerActivity;
     209             : }
     210             : 
     211             : static void
     212           6 : IncrementMutationCount(uint8_t* aCount)
     213             : {
     214           0 :   *aCount = uint8_t(std::min(0xFF, *aCount + 1));
     215           6 : }
     216             : 
     217             : /* static */ void
     218          42 : ActiveLayerTracker::TransferActivityToContent(nsIFrame* aFrame, nsIContent* aContent)
     219             : {
     220          84 :   if (!aFrame->HasAnyStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY)) {
     221             :     return;
     222             :   }
     223           0 :   LayerActivity* layerActivity = aFrame->RemoveProperty(LayerActivityProperty());
     224           0 :   aFrame->RemoveStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
     225           0 :   if (!layerActivity) {
     226             :     return;
     227             :   }
     228           0 :   layerActivity->mFrame = nullptr;
     229           0 :   layerActivity->mContent = aContent;
     230           0 :   aContent->SetProperty(nsGkAtoms::LayerActivity, layerActivity,
     231           0 :                         nsINode::DeleteProperty<LayerActivity>, true);
     232             : }
     233             : 
     234             : /* static */ void
     235         257 : ActiveLayerTracker::TransferActivityToFrame(nsIContent* aContent, nsIFrame* aFrame)
     236             : {
     237             :   LayerActivity* layerActivity = static_cast<LayerActivity*>(
     238           0 :     aContent->UnsetProperty(nsGkAtoms::LayerActivity));
     239         257 :   if (!layerActivity) {
     240             :     return;
     241             :   }
     242           0 :   layerActivity->mContent = nullptr;
     243           0 :   layerActivity->mFrame = aFrame;
     244           0 :   aFrame->AddStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
     245           0 :   aFrame->SetProperty(LayerActivityProperty(), layerActivity);
     246             : }
     247             : 
     248             : static void
     249           0 : IncrementScaleRestyleCountIfNeeded(nsIFrame* aFrame, LayerActivity* aActivity)
     250             : {
     251           0 :   const nsStyleDisplay* display = aFrame->StyleDisplay();
     252           0 :   RefPtr<nsCSSValueSharedList> transformList = display->GetCombinedTransform();
     253           0 :   if (!transformList) {
     254             :     // The transform was removed.
     255           0 :     aActivity->mPreviousTransformScale = Nothing();
     256           0 :     IncrementMutationCount(&aActivity->mRestyleCounts[LayerActivity::ACTIVITY_SCALE]);
     257           0 :     return;
     258             :   }
     259             : 
     260             :   // Compute the new scale due to the CSS transform property.
     261             :   bool dummyBool;
     262           0 :   nsStyleTransformMatrix::TransformReferenceBox refBox(aFrame);
     263             :   Matrix4x4 transform =
     264           0 :     nsStyleTransformMatrix::ReadTransforms(transformList->mHead,
     265             :                                            refBox,
     266             :                                            nsPresContext::AppUnitsPerCSSPixel(),
     267           0 :                                            &dummyBool);
     268           0 :   Matrix transform2D;
     269           0 :   if (!transform.Is2D(&transform2D)) {
     270             :     // We don't attempt to handle 3D transforms; just assume the scale changed.
     271           0 :     aActivity->mPreviousTransformScale = Nothing();
     272           0 :     IncrementMutationCount(&aActivity->mRestyleCounts[LayerActivity::ACTIVITY_SCALE]);
     273           0 :     return;
     274             :   }
     275             : 
     276           0 :   Size scale = transform2D.ScaleFactors(true);
     277           0 :   if (aActivity->mPreviousTransformScale == Some(scale)) {
     278             :     return;  // Nothing changed.
     279             :   }
     280             : 
     281           0 :   aActivity->mPreviousTransformScale = Some(scale);
     282           0 :   IncrementMutationCount(&aActivity->mRestyleCounts[LayerActivity::ACTIVITY_SCALE]);
     283             : }
     284             : 
     285             : /* static */ void
     286           6 : ActiveLayerTracker::NotifyRestyle(nsIFrame* aFrame, nsCSSPropertyID aProperty)
     287             : {
     288           0 :   LayerActivity* layerActivity = GetLayerActivityForUpdate(aFrame);
     289           0 :   uint8_t& mutationCount = layerActivity->RestyleCountForProperty(aProperty);
     290           6 :   IncrementMutationCount(&mutationCount);
     291             : 
     292           0 :   if (aProperty == eCSSProperty_transform) {
     293           0 :     IncrementScaleRestyleCountIfNeeded(aFrame, layerActivity);
     294             :   }
     295           6 : }
     296             : 
     297             : /* static */ void
     298           0 : ActiveLayerTracker::NotifyOffsetRestyle(nsIFrame* aFrame)
     299             : {
     300           0 :   LayerActivity* layerActivity = GetLayerActivityForUpdate(aFrame);
     301           0 :   IncrementMutationCount(&layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_LEFT]);
     302           0 :   IncrementMutationCount(&layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_TOP]);
     303           0 :   IncrementMutationCount(&layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_RIGHT]);
     304           0 :   IncrementMutationCount(&layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_BOTTOM]);
     305           0 : }
     306             : 
     307             : /* static */ void
     308           0 : ActiveLayerTracker::NotifyAnimated(nsIFrame* aFrame,
     309             :                                    nsCSSPropertyID aProperty,
     310             :                                    const nsAString& aNewValue,
     311             :                                    nsDOMCSSDeclaration* aDOMCSSDecl)
     312             : {
     313           0 :   LayerActivity* layerActivity = GetLayerActivityForUpdate(aFrame);
     314           0 :   uint8_t& mutationCount = layerActivity->RestyleCountForProperty(aProperty);
     315           0 :   if (mutationCount != 0xFF) {
     316           0 :     nsAutoString oldValue;
     317           0 :     aDOMCSSDecl->GetPropertyValue(aProperty, oldValue);
     318           0 :     if (aNewValue != oldValue) {
     319             :       // We know this is animated, so just hack the mutation count.
     320           0 :       mutationCount = 0xFF;
     321             :     }
     322             :   }
     323           0 : }
     324             : 
     325             : /* static */ void
     326           0 : ActiveLayerTracker::NotifyAnimatedFromScrollHandler(nsIFrame* aFrame, nsCSSPropertyID aProperty,
     327             :                                                     nsIFrame* aScrollFrame)
     328             : {
     329           0 :   if (aFrame->PresContext() != aScrollFrame->PresContext()) {
     330             :     // Don't allow cross-document dependencies.
     331             :     return;
     332             :   }
     333           0 :   LayerActivity* layerActivity = GetLayerActivityForUpdate(aFrame);
     334           0 :   LayerActivity::ActivityIndex activityIndex = LayerActivity::GetActivityIndexForProperty(aProperty);
     335             : 
     336           0 :   if (layerActivity->mAnimatingScrollHandlerFrame.GetFrame() != aScrollFrame) {
     337             :     // Discard any activity of a different scroll frame. We only track the
     338             :     // most recent scroll handler induced activity.
     339           0 :     layerActivity->mScrollHandlerInducedActivity.clear();
     340           0 :     layerActivity->mAnimatingScrollHandlerFrame = aScrollFrame;
     341             :   }
     342             : 
     343           0 :   layerActivity->mScrollHandlerInducedActivity += activityIndex;
     344             : }
     345             : 
     346             : static bool
     347           0 : IsPresContextInScriptAnimationCallback(nsPresContext* aPresContext)
     348             : {
     349           0 :   if (aPresContext->RefreshDriver()->IsInRefresh()) {
     350             :     return true;
     351             :   }
     352             :   // Treat timeouts/setintervals as scripted animation callbacks for our
     353             :   // purposes.
     354           0 :   nsPIDOMWindowInner* win = aPresContext->Document()->GetInnerWindow();
     355           0 :   return win && win->IsRunningTimeout();
     356             : }
     357             : 
     358             : /* static */ void
     359           0 : ActiveLayerTracker::NotifyInlineStyleRuleModified(nsIFrame* aFrame,
     360             :                                                   nsCSSPropertyID aProperty,
     361             :                                                   const nsAString& aNewValue,
     362             :                                                   nsDOMCSSDeclaration* aDOMCSSDecl)
     363             : {
     364           0 :   if (IsPresContextInScriptAnimationCallback(aFrame->PresContext())) {
     365           0 :     NotifyAnimated(aFrame, aProperty, aNewValue, aDOMCSSDecl);
     366             :   }
     367           0 :   if (gLayerActivityTracker &&
     368           0 :       gLayerActivityTracker->mCurrentScrollHandlerFrame.IsAlive()) {
     369           0 :     NotifyAnimatedFromScrollHandler(aFrame, aProperty,
     370           0 :       gLayerActivityTracker->mCurrentScrollHandlerFrame.GetFrame());
     371             :   }
     372           0 : }
     373             : 
     374             : /* static */ void
     375           0 : ActiveLayerTracker::NotifyNeedsRepaint(nsIFrame* aFrame)
     376             : {
     377           0 :   LayerActivity* layerActivity = GetLayerActivityForUpdate(aFrame);
     378           0 :   if (IsPresContextInScriptAnimationCallback(aFrame->PresContext())) {
     379             :     // This is mirroring NotifyInlineStyleRuleModified's NotifyAnimated logic. Just max out
     380             :     // the restyle count if we're in an animation callback.
     381           0 :     layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_TRIGGERED_REPAINT] = 0xFF;
     382             :   } else {
     383           0 :     IncrementMutationCount(&layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_TRIGGERED_REPAINT]);
     384             :   }
     385           0 : }
     386             : 
     387             : /* static */ bool
     388           0 : ActiveLayerTracker::IsStyleMaybeAnimated(nsIFrame* aFrame, nsCSSPropertyID aProperty)
     389             : {
     390          11 :   return IsStyleAnimated(nullptr, aFrame, aProperty);
     391             : }
     392             : 
     393             : /* static */ bool
     394          14 : ActiveLayerTracker::IsBackgroundPositionAnimated(nsDisplayListBuilder* aBuilder,
     395             :                                                  nsIFrame* aFrame)
     396             : {
     397          28 :   return IsStyleAnimated(aBuilder, aFrame, eCSSProperty_background_position_x) ||
     398           1 :          IsStyleAnimated(aBuilder, aFrame, eCSSProperty_background_position_y);
     399             : }
     400             : 
     401             : static bool
     402           0 : CheckScrollInducedActivity(LayerActivity* aLayerActivity,
     403             :                            LayerActivity::ActivityIndex aActivityIndex,
     404             :                            nsDisplayListBuilder* aBuilder)
     405             : {
     406           0 :   if (!aLayerActivity->mScrollHandlerInducedActivity.contains(aActivityIndex) ||
     407           0 :       !aLayerActivity->mAnimatingScrollHandlerFrame.IsAlive()) {
     408             :     return false;
     409             :   }
     410             : 
     411             :   nsIScrollableFrame* scrollFrame =
     412           0 :     do_QueryFrame(aLayerActivity->mAnimatingScrollHandlerFrame.GetFrame());
     413           0 :   if (scrollFrame && (!aBuilder || scrollFrame->IsScrollingActive(aBuilder))) {
     414             :     return true;
     415             :   }
     416             : 
     417             :   // The scroll frame has been destroyed or has become inactive. Clear it from
     418             :   // the layer activity so that it can expire.
     419           0 :   aLayerActivity->mAnimatingScrollHandlerFrame = nullptr;
     420           0 :   aLayerActivity->mScrollHandlerInducedActivity.clear();
     421           0 :   return false;
     422             : }
     423             : 
     424             : /* static */ bool
     425         121 : ActiveLayerTracker::IsStyleAnimated(nsDisplayListBuilder* aBuilder,
     426             :                                     nsIFrame* aFrame, nsCSSPropertyID aProperty)
     427             : {
     428             :   // TODO: Add some abuse restrictions
     429           0 :   if ((aFrame->StyleDisplay()->mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM) &&
     430         121 :       aProperty == eCSSProperty_transform &&
     431           0 :       (!aBuilder || aBuilder->IsInWillChangeBudget(aFrame, aFrame->GetSize()))) {
     432             :     return true;
     433             :   }
     434         242 :   if ((aFrame->StyleDisplay()->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) &&
     435         121 :       aProperty == eCSSProperty_opacity &&
     436           0 :       (!aBuilder || aBuilder->IsInWillChangeBudget(aFrame, aFrame->GetSize()))) {
     437             :     return true;
     438             :   }
     439             : 
     440           0 :   LayerActivity* layerActivity = GetLayerActivity(aFrame);
     441         121 :   if (layerActivity) {
     442           0 :     LayerActivity::ActivityIndex activityIndex = LayerActivity::GetActivityIndexForProperty(aProperty);
     443           0 :     if (layerActivity->mRestyleCounts[activityIndex] >= 2) {
     444           0 :       // If the frame needs to be repainted frequently, we probably don't get
     445             :       // much from treating the property as animated, *unless* this frame's
     446             :       // 'scale' (which includes the bounds changes of a rotation) is changing.
     447           0 :       // Marking a scaling transform as animating allows us to avoid resizing
     448             :       // the texture, even if we have to repaint the contents of that texture.
     449             :       if (layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_TRIGGERED_REPAINT] < 2 ||
     450             :           (aProperty == eCSSProperty_transform && IsScaleSubjectToAnimation(aFrame))) {
     451           0 :         return true;
     452           0 :       }
     453             :     }
     454           0 :     if (CheckScrollInducedActivity(layerActivity, activityIndex, aBuilder)) {
     455         110 :       return true;
     456             :     }
     457          11 :   }
     458             :   if (aProperty == eCSSProperty_transform && aFrame->Combines3DTransformWithAncestors()) {
     459             :     return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty);
     460             :   }
     461             :   return nsLayoutUtils::HasEffectiveAnimation(aFrame, aProperty);
     462         713 : }
     463             : 
     464         713 : /* static */ bool
     465         713 : ActiveLayerTracker::IsOffsetStyleAnimated(nsIFrame* aFrame)
     466           0 : {
     467           0 :   LayerActivity* layerActivity = GetLayerActivity(aFrame);
     468           0 :   if (layerActivity) {
     469           0 :     if (layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_LEFT] >= 2 ||
     470             :         layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_TOP] >= 2 ||
     471             :         layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_RIGHT] >= 2 ||
     472             :         layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_BOTTOM] >= 2) {
     473             :       return true;
     474             :     }
     475             :   }
     476             :   // We should also check for running CSS animations of these properties once
     477             :   // bug 1009693 is fixed. Until that happens, layerization isn't useful for
     478           0 :   // animations of these properties because we'll invalidate the layer contents
     479             :   // on every change anyway.
     480             :   // See bug 1151346 for a patch that adds a check for CSS animations.
     481             :   return false;
     482          29 : }
     483             : 
     484             : /* static */ bool
     485          29 : ActiveLayerTracker::IsScaleSubjectToAnimation(nsIFrame* aFrame)
     486          29 : {
     487             :   // Check whether JavaScript is animating this frame's scale.
     488             :   LayerActivity* layerActivity = GetLayerActivity(aFrame);
     489             :   if (layerActivity && layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_SCALE] >= 2) {
     490             :     return true;
     491             :   }
     492          29 : 
     493          29 :   // Check if any animations, transitions, etc. associated with this frame may
     494           0 :   // animate its scale.
     495             :   EffectSet* effects = EffectSet::GetEffectSet(aFrame);
     496             :   if (effects &&
     497             :       AnimationUtils::EffectSetContainsAnimatedScale(*effects, aFrame)) {
     498          29 :     return true;
     499             :   }
     500             : 
     501             :   return false;
     502           0 : }
     503             : 
     504           0 : /* static */ void
     505           0 : ActiveLayerTracker::NotifyContentChange(nsIFrame* aFrame)
     506           0 : {
     507             :   LayerActivity* layerActivity = GetLayerActivityForUpdate(aFrame);
     508             :   layerActivity->mContentActive = true;
     509           0 : }
     510             : 
     511           0 : /* static */ bool
     512           0 : ActiveLayerTracker::IsContentActive(nsIFrame* aFrame)
     513             : {
     514             :   LayerActivity* layerActivity = GetLayerActivity(aFrame);
     515             :   return layerActivity && layerActivity->mContentActive;
     516             : }
     517             : 
     518             : /* static */ void
     519             : ActiveLayerTracker::SetCurrentScrollHandlerFrame(nsIFrame* aFrame)
     520             : {
     521             :   if (!gLayerActivityTracker) {
     522             :     gLayerActivityTracker = new LayerActivityTracker(
     523             :       SystemGroup::EventTargetFor(TaskCategory::Other));
     524             :   }
     525             :   gLayerActivityTracker->mCurrentScrollHandlerFrame = aFrame;
     526             : }
     527             : 
     528             : /* static */ void
     529             : ActiveLayerTracker::Shutdown()
     530             : {
     531             :   delete gLayerActivityTracker;
     532             :   gLayerActivityTracker = nullptr;
     533             : }
     534             : 
     535             : } // namespace mozilla

Generated by: LCOV version 1.13-14-ga5dd952