Bug 1338347 - Have the animation-sampling code track which process the animations are in. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 20 Mar 2017 11:41:05 -0400
changeset 501570 89a36d902d408c4e8be09833f62aae5eec75f93d
parent 501569 05bfa2831c0ba4a26fa72328ffe6a99aba9c356a
child 501571 4db7db2c0b17701d5fe3fc6098d32046f3ae8dd8
push id50031
push userkgupta@mozilla.com
push dateMon, 20 Mar 2017 15:42:18 +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();