Bug 1338347 - Have the animation-sampling code track which process the animations are in. r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 20 Mar 2017 11:41:05 -0400
changeset 552135 043fa58a556cc07be2d15ea47384cfe39eca2438
parent 552134 fc32a6e7fdb3dd3416f1e8f459e6af038ef0f338
child 552136 59f8c2560e6f96fdc70748540898b7b17ac207de
push id51252
push userhikezoe@mozilla.com
push dateTue, 28 Mar 2017 02:10:27 +0000
reviewersbotond
bugs1338347
milestone55.0a1
Bug 1338347 - Have the animation-sampling code track which process the animations are in. r=botond This allows the AsyncCompositionManager to know whether compositor animations are coming from chrome layers or content layers (using the rootmost RefLayer as the boundary). This information is needed to have the compositor animation telemetry probes separate information by chrome/content. MozReview-Commit-ID: GqHczgrzXE5
gfx/layers/composite/AnimationMetricsTracker.h
gfx/layers/composite/AsyncCompositionManager.cpp
--- a/gfx/layers/composite/AnimationMetricsTracker.h
+++ b/gfx/layers/composite/AnimationMetricsTracker.h
@@ -2,20 +2,29 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_AnimationMetricsTracker_h
 #define mozilla_layers_AnimationMetricsTracker_h
 
 #include "mozilla/TimeStamp.h"
+#include "mozilla/TypedEnumBits.h"
 
 namespace mozilla {
 namespace layers {
 
+enum class AnimationProcessTypes {
+  eNone = 0x0,
+  eContent = 0x1,
+  eChrome = 0x2
+};
+
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(AnimationProcessTypes)
+
 /**
  * Tracks the start and end of compositor animations.
  */
 class AnimationMetricsTracker {
 public:
   AnimationMetricsTracker();
   ~AnimationMetricsTracker();
 
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -640,50 +640,72 @@ ApplyAnimatedValue(Layer* aLayer,
                                  transformData);
       break;
     }
     default:
       MOZ_ASSERT_UNREACHABLE("Unhandled animated property");
   }
 }
 
-static bool
+static AnimationProcessTypes
 SampleAnimations(Layer* aLayer,
                  CompositorAnimationStorage* aStorage,
                  TimeStamp aPoint,
                  uint64_t* aLayerAreaAnimated)
 {
-  bool activeAnimations = false;
+  // This tracks the first-encountered RefLayer in the layer tree. Since we are
+  // doing a depth-first traversal, it is set to a non-null value if and only if
+  // the currently-being-traversed node has a RefLayer ancestor. In the case of
+  // nested RefLayers it points to the rootmost RefLayer.
+  RefLayer* ancestorRefLayer = nullptr;
+
+  // This bitfield-enum tracks which processes have active animations. Anything
+  // "above" the |ancestorRefLayer| in the layer tree is assumed to be the
+  // chrome process, and anything "below" is assumed to be the content process.
+  AnimationProcessTypes animProcess = AnimationProcessTypes::eNone;
 
   ForEachNode<ForwardIterator>(
       aLayer,
-      [aStorage, &activeAnimations, &aPoint, &aLayerAreaAnimated] (Layer* layer)
+      [&] (Layer* layer)
       {
+        if (!ancestorRefLayer) {
+          ancestorRefLayer = layer->AsRefLayer();
+        }
+
         bool hasInEffectAnimations = false;
         StyleAnimationValue animationValue = layer->GetBaseAnimationStyle();
-        activeAnimations |=
-          AnimationHelper::SampleAnimationForEachNode(aPoint,
-                                                      layer->GetAnimations(),
-                                                      layer->GetAnimationData(),
-                                                      animationValue,
-                                                      hasInEffectAnimations);
+        if (AnimationHelper::SampleAnimationForEachNode(aPoint,
+                                                        layer->GetAnimations(),
+                                                        layer->GetAnimationData(),
+                                                        animationValue,
+                                                        hasInEffectAnimations)) {
+          animProcess |= (ancestorRefLayer ? AnimationProcessTypes::eContent
+                                           : AnimationProcessTypes::eChrome);
+        }
         if (hasInEffectAnimations) {
           Animation& animation = layer->GetAnimations().LastElement();
           ApplyAnimatedValue(layer,
                              aStorage,
                              animation.property(),
                              animation.data(),
                              animationValue);
           if (aLayerAreaAnimated) {
             *aLayerAreaAnimated += (layer->GetVisibleRegion().Area());
           }
         }
+      },
+      [&ancestorRefLayer] (Layer* aLayer)
+      {
+        // If we're unwinding up past the rootmost RefLayer, clear our pointer
+        if (ancestorRefLayer && aLayer->AsRefLayer() == ancestorRefLayer) {
+          ancestorRefLayer = nullptr;
+        }
       });
 
-  return activeAnimations;
+  return animProcess;
 }
 
 static bool
 SampleAPZAnimations(const LayerMetricsWrapper& aLayer, TimeStamp aSampleTime)
 {
   bool activeAnimations = false;
 
   ForEachNodePostOrder<ForwardIterator>(aLayer,
@@ -1331,22 +1353,23 @@ AsyncCompositionManager::TransformShadow
   // First, compute and set the shadow transforms from OMT animations.
   // NB: we must sample animations *before* sampling pan/zoom
   // transforms.
   // Use a previous vsync time to make main thread animations and compositor
   // more in sync with each other.
   // On the initial frame we use aVsyncTimestamp here so the timestamp on the
   // second frame are the same as the initial frame, but it does not matter.
   uint64_t layerAreaAnimated = 0;
-  bool wantNextFrame =
+  AnimationProcessTypes animationProcess =
     SampleAnimations(root,
                      storage,
                      !mPreviousFrameTimeStamp.IsNull() ?
                        mPreviousFrameTimeStamp : aCurrentFrame,
                      &layerAreaAnimated);
+  bool wantNextFrame = (animationProcess != AnimationProcessTypes::eNone);
 
   mAnimationMetricsTracker.UpdateAnimationInProgress(
     wantNextFrame, layerAreaAnimated);
 
   if (!wantNextFrame) {
     // Clean up the CompositorAnimationStorage because
     // there are no active animations running
     storage->Clear();