Bug 1532568 - Look up the animation generation on the primary frame for transform display items; r=hiro
authorBrian Birtles <birtles@gmail.com>
Thu, 07 Mar 2019 05:40:51 +0000
changeset 520704 f8b979bd590424560bf17a1877baa575b29b6013
parent 520703 bfe72a7c57bde0d1825ba43cbd9afa34d03ed00d
child 520705 47dfb7c2aa932121e3eb769c87f7d206ab059437
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershiro
bugs1532568
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1532568 - Look up the animation generation on the primary frame for transform display items; r=hiro Differential Revision: https://phabricator.services.mozilla.com/D22443
gfx/layers/AnimationInfo.cpp
layout/base/RestyleManager.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/painting/FrameLayerBuilder.cpp
--- a/gfx/layers/AnimationInfo.cpp
+++ b/gfx/layers/AnimationInfo.cpp
@@ -198,18 +198,24 @@ void AnimationInfo::EnumerateGenerationO
       layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
     // In case of continuation, nsDisplayItem uses its last continuation, so we
     // have to use the last continuation frame here.
     if (nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame)) {
       aFrame = nsLayoutUtils::LastContinuationOrIBSplitSibling(aFrame);
     }
 
     for (auto displayItem : LayerAnimationInfo::sDisplayItemTypes) {
+      // For transform animations, the animation is on the primary frame but
+      // |aFrame| is the style frame.
+      const nsIFrame* frameToQuery =
+          displayItem == DisplayItemType::TYPE_TRANSFORM
+              ? nsLayoutUtils::GetPrimaryFrameFromStyleFrame(aFrame)
+              : aFrame;
       RefPtr<WebRenderAnimationData> animationData =
-          GetWebRenderUserData<WebRenderAnimationData>(aFrame,
+          GetWebRenderUserData<WebRenderAnimationData>(frameToQuery,
                                                        (uint32_t)displayItem);
       Maybe<uint64_t> generation;
       if (animationData) {
         generation = animationData->GetAnimationInfo().GetAnimationGeneration();
       }
       aCallback(generation, displayItem);
     }
     return;
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -1880,24 +1880,24 @@ void RestyleManager::IncrementAnimationG
   // calls that occur while we are still processing restyles.
   if (!mInStyleRefresh) {
     ++mAnimationGeneration;
   }
 }
 
 /* static */
 void RestyleManager::AddLayerChangesForAnimation(
-    nsIFrame* aFrame, nsIContent* aContent, nsChangeHint aHintForThisFrame,
+    nsIFrame* aStyleFrame, nsIContent* aContent, nsChangeHint aHintForThisFrame,
     nsStyleChangeList& aChangeListToProcess) {
-  if (!aFrame || !aContent) {
+  if (!aStyleFrame || !aContent) {
     return;
   }
 
   uint64_t frameGeneration =
-      RestyleManager::GetAnimationGenerationForFrame(aFrame);
+      RestyleManager::GetAnimationGenerationForFrame(aStyleFrame);
 
   Maybe<nsCSSPropertyIDSet> effectiveAnimationProperties;
 
   nsChangeHint hint = nsChangeHint(0);
   auto maybeApplyChangeHint = [&](const Maybe<uint64_t>& aGeneration,
                                   DisplayItemType aDisplayItemType) -> bool {
     if (aGeneration && frameGeneration != *aGeneration) {
       // If we have a transform layer but don't have any transform style, we
@@ -1915,17 +1915,17 @@ void RestyleManager::AddLayerChangesForA
       // hints relevant to removing transform style (since we don't know exactly
       // what changes happened while the animation was running on the
       // compositor).
       //
       // Note that we *don't* add nsChangeHint_UpdateTransformLayer since if we
       // did, ApplyRenderingChangeToTree would complain that we're updating a
       // transform layer without a transform.
       if (aDisplayItemType == DisplayItemType::TYPE_TRANSFORM &&
-          !aFrame->StyleDisplay()->HasTransformStyle()) {
+          !aStyleFrame->StyleDisplay()->HasTransformStyle()) {
         // Add all the hints for a removing a transform if they are not already
         // set for this frame.
         if (!(NS_IsHintSubset(nsChangeHint_ComprehensiveAddOrRemoveTransform,
                               aHintForThisFrame))) {
           hint |= nsChangeHint_ComprehensiveAddOrRemoveTransform;
         }
         return true;
       }
@@ -1951,33 +1951,33 @@ void RestyleManager::AddLayerChangesForA
       // We don't need to apply the corresponding change hint if we already have
       // it.
       if (NS_IsHintSubset(hintForDisplayItem, aHintForThisFrame)) {
         return true;
       }
 
       if (!effectiveAnimationProperties) {
         effectiveAnimationProperties.emplace(
-            nsLayoutUtils::GetAnimationPropertiesForCompositor(aFrame));
+            nsLayoutUtils::GetAnimationPropertiesForCompositor(aStyleFrame));
       }
       const nsCSSPropertyIDSet& propertiesForDisplayItem =
           LayerAnimationInfo::GetCSSPropertiesFor(aDisplayItemType);
       if (effectiveAnimationProperties->Intersects(propertiesForDisplayItem)) {
         hint |= hintForDisplayItem;
       }
     }
     return true;
   };
 
   AnimationInfo::EnumerateGenerationOnFrame(
-      aFrame, aContent, LayerAnimationInfo::sDisplayItemTypes,
+      aStyleFrame, aContent, LayerAnimationInfo::sDisplayItemTypes,
       maybeApplyChangeHint);
 
   if (hint) {
-    aChangeListToProcess.AppendChange(aFrame, aContent, hint);
+    aChangeListToProcess.AppendChange(aStyleFrame, aContent, hint);
   }
 }
 
 RestyleManager::AnimationsWithDestroyedFrame::AnimationsWithDestroyedFrame(
     RestyleManager* aRestyleManager)
     : mRestyleManager(aRestyleManager),
       mRestorePointer(mRestyleManager->mAnimationsWithDestroyedFrame) {
   MOZ_ASSERT(!mRestyleManager->mAnimationsWithDestroyedFrame,
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1444,16 +1444,23 @@ nsIFrame* nsLayoutUtils::GetStyleFrame(c
 }
 
 /* static */
 nsIFrame* nsLayoutUtils::GetPrimaryFrameFromStyleFrame(nsIFrame* aStyleFrame) {
   nsIFrame* parent = aStyleFrame->GetParent();
   return parent && parent->IsTableWrapperFrame() ? parent : aStyleFrame;
 }
 
+/* static */
+const nsIFrame* nsLayoutUtils::GetPrimaryFrameFromStyleFrame(
+    const nsIFrame* aStyleFrame) {
+  return nsLayoutUtils::GetPrimaryFrameFromStyleFrame(
+      const_cast<nsIFrame*>(aStyleFrame));
+}
+
 /*static*/
 bool nsLayoutUtils::IsPrimaryStyleFrame(const nsIFrame* aFrame) {
   if (aFrame->IsTableWrapperFrame()) {
     return false;
   }
 
   const nsIFrame* parent = aFrame->GetParent();
   if (parent && parent->IsTableWrapperFrame()) {
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -393,16 +393,18 @@ class nsLayoutUtils {
    */
   static nsIFrame* GetStyleFrame(const nsIContent* aContent);
 
   /**
    * The inverse of GetStyleFrame. Returns |aStyleFrame| unless it is an inner
    * table frame, in which case the table wrapper frame is returned.
    */
   static nsIFrame* GetPrimaryFrameFromStyleFrame(nsIFrame* aStyleFrame);
+  static const nsIFrame* GetPrimaryFrameFromStyleFrame(
+      const nsIFrame* aStyleFrame);
 
   /**
    * Similar to nsIFrame::IsPrimaryFrame except that this will return true
    * for the inner table frame rather than for its wrapper frame.
    */
   static bool IsPrimaryStyleFrame(const nsIFrame* aFrame);
 
   /**
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -6422,67 +6422,73 @@ Layer* FrameLayerBuilder::GetDedicatedLa
 }
 
 /* static */
 void FrameLayerBuilder::EnumerateGenerationForDedicatedLayers(
     const nsIFrame* aFrame,
     const CompositorAnimatableDisplayItemTypes& aDisplayItemTypes,
     const AnimationGenerationCallback& aCallback) {
   std::bitset<static_cast<uint32_t>(DisplayItemType::TYPE_MAX)> notFoundTypes;
-  for (auto displayItem : aDisplayItemTypes) {
-    notFoundTypes.set(static_cast<uint32_t>(displayItem));
-  }
-
-  const SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
-
-  for (uint32_t i = 0; i < array.Length(); i++) {
-    DisplayItemData* element =
-        DisplayItemData::AssertDisplayItemData(array.ElementAt(i));
-    if (!element->mParent->mLayerManager->IsWidgetLayerManager()) {
-      continue;
-    }
-
-    DisplayItemType foundType = DisplayItemType::TYPE_ZERO;
-    for (auto displayItem : aDisplayItemTypes) {
-      if (GetDisplayItemTypeFromKey(element->mDisplayItemKey) == displayItem) {
-        foundType = displayItem;
-        notFoundTypes.reset(static_cast<uint32_t>(displayItem));
-        break;
+  for (auto displayItemType : aDisplayItemTypes) {
+    notFoundTypes.set(static_cast<uint32_t>(displayItemType));
+  }
+
+  for (auto displayItemType : aDisplayItemTypes) {
+    // For transform animations, the animation is on the primary frame but
+    // |aFrame| is the style frame.
+    const nsIFrame* frameToQuery =
+        displayItemType == DisplayItemType::TYPE_TRANSFORM
+            ? nsLayoutUtils::GetPrimaryFrameFromStyleFrame(aFrame)
+            : aFrame;
+    const nsIFrame::DisplayItemDataArray& displayItemDataArray =
+        frameToQuery->DisplayItemData();
+
+    for (uint32_t i = 0; i < displayItemDataArray.Length(); i++) {
+      DisplayItemData* element = DisplayItemData::AssertDisplayItemData(
+          displayItemDataArray.ElementAt(i));
+      if (!element->mParent->mLayerManager->IsWidgetLayerManager()) {
+        continue;
       }
-    }
-    if (foundType == DisplayItemType::TYPE_ZERO) {
-      continue;
-    }
-
-    Maybe<uint64_t> generation;
-    if (element->mOptLayer) {
-      generation = element->mOptLayer->GetAnimationGeneration();
-    } else if (!element->mLayer->HasUserData(&gColorLayerUserData) &&
-               !element->mLayer->HasUserData(&gImageLayerUserData) &&
-               !element->mLayer->HasUserData(
-                   &gPaintedDisplayItemLayerUserData)) {
-      generation = element->mLayer->GetAnimationGeneration();
-    }
-
-    if (!aCallback(generation, foundType)) {
-      return;
+
+      if (GetDisplayItemTypeFromKey(element->mDisplayItemKey) !=
+          displayItemType) {
+        continue;
+      }
+
+      notFoundTypes.reset(static_cast<uint32_t>(displayItemType));
+
+      Maybe<uint64_t> generation;
+      if (element->mOptLayer) {
+        generation = element->mOptLayer->GetAnimationGeneration();
+      } else if (!element->mLayer->HasUserData(&gColorLayerUserData) &&
+                 !element->mLayer->HasUserData(&gImageLayerUserData) &&
+                 !element->mLayer->HasUserData(
+                     &gPaintedDisplayItemLayerUserData)) {
+        generation = element->mLayer->GetAnimationGeneration();
+      }
+
+      if (!aCallback(generation, displayItemType)) {
+        return;
+      }
+
+      break;
     }
   }
 
   // Bail out if we have already enumerated all possible layers for the given
   // display item types.
   if (notFoundTypes.none()) {
     return;
   }
 
   // If there are any display item types that the nsIFrame doesn't have, we need
   // to call the callback function for them respectively.
-  for (auto displayItem : aDisplayItemTypes) {
-    if (notFoundTypes[static_cast<uint32_t>(displayItem)] &&
-        !aCallback(Nothing(), displayItem)) {
+  for (auto displayItemType : aDisplayItemTypes) {
+    if (notFoundTypes[static_cast<uint32_t>(displayItemType)] &&
+        !aCallback(Nothing(), displayItemType)) {
       return;
     }
   }
 }
 
 gfxSize FrameLayerBuilder::GetPaintedLayerScaleForFrame(nsIFrame* aFrame) {
   MOZ_ASSERT(aFrame, "need a frame");