Bug 779598 - Do animations of transforms with preserve-3d at compositor. r?mattwoodrow draft
authorThinker K.F. Li <thinker@codemud.net>
Tue, 24 Jul 2018 13:12:26 +0900
changeset 821851 07ee873392ad5f2aebea34cda321bcb695938dbf
parent 821850 0afa946b8eb53e0ef9f04bbf4bd93e66eda9817a
child 821852 3fe2c6114b6c8bb7b05aca321b41125e87c9d9db
push id117200
push userhikezoe@mozilla.com
push dateTue, 24 Jul 2018 04:13:09 +0000
reviewersmattwoodrow
bugs779598
milestone63.0a1
Bug 779598 - Do animations of transforms with preserve-3d at compositor. r?mattwoodrow MozReview-Commit-ID: CAHPuIDk90a
dom/animation/KeyframeEffect.cpp
dom/animation/test/chrome/test_animation_performance_warning.html
dom/locales/en-US/chrome/layout/layout_errors.properties
layout/generic/nsFrame.cpp
layout/painting/ActiveLayerTracker.cpp
layout/painting/nsDisplayList.cpp
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -1434,24 +1434,16 @@ KeyframeEffect::IsGeometricProperty(cons
   }
 }
 
 /* static */ bool
 KeyframeEffect::CanAnimateTransformOnCompositor(
   const nsIFrame* aFrame,
   AnimationPerformanceWarning::Type& aPerformanceWarning)
 {
-  // Disallow OMTA for preserve-3d transform. Note that we check the style property
-  // rather than Extend3DContext() since that can recurse back into this function
-  // via HasOpacity(). See bug 779598.
-  if (aFrame->Combines3DTransformWithAncestors() ||
-      aFrame->StyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D) {
-    aPerformanceWarning = AnimationPerformanceWarning::Type::TransformPreserve3D;
-    return false;
-  }
   // Note that testing BackfaceIsHidden() is not a sufficient test for
   // what we need for animating backface-visibility correctly if we
   // remove the above test for Extend3DContext(); that would require
   // looking at backface-visibility on descendants as well. See bug 1186204.
   if (aFrame->BackfaceIsHidden()) {
     aPerformanceWarning =
       AnimationPerformanceWarning::Type::TransformBackfaceVisibilityHidden;
     return false;
--- a/dom/animation/test/chrome/test_animation_performance_warning.html
+++ b/dom/animation/test/chrome/test_animation_performance_warning.html
@@ -340,18 +340,17 @@ function testStyleChanges() {
       desc: 'preserve-3d transform',
       frames: {
         transform: ['translate(0px)', 'translate(100px)']
       },
       style: 'transform-style: preserve-3d',
       expected: [
         {
           property: 'transform',
-          runningOnCompositor: false,
-          warning: 'CompositorAnimationWarningTransformPreserve3D'
+          runningOnCompositor: true,
         }
       ]
     },
     {
       desc: 'transform with backface-visibility:hidden',
       frames: {
         transform: ['translate(0px)', 'translate(100px)']
       },
@@ -373,18 +372,17 @@ function testStyleChanges() {
       style: 'transform-style: preserve-3d',
       expected: [
         {
           property: 'opacity',
           runningOnCompositor: true
         },
         {
           property: 'transform',
-          runningOnCompositor: false,
-          warning: 'CompositorAnimationWarningTransformPreserve3D'
+          runningOnCompositor: true,
         }
       ]
     },
     {
       desc: 'opacity and transform with backface-visibility:hidden',
       frames: {
         opacity: [0, 1],
         transform: ['translate(0px)', 'translate(100px)']
@@ -482,18 +480,17 @@ function testMultipleAnimations() {
       animations: [
         {
           frames: {
             transform: ['translate(0px)', 'translate(100px)']
           },
           expected: [
             {
               property: 'transform',
-              runningOnCompositor: false,
-              warning: 'CompositorAnimationWarningTransformPreserve3D'
+              runningOnCompositor: true,
             }
           ]
         },
         {
           frames: {
             opacity: [0, 1]
           },
           expected: [
--- a/dom/locales/en-US/chrome/layout/layout_errors.properties
+++ b/dom/locales/en-US/chrome/layout/layout_errors.properties
@@ -18,19 +18,16 @@ CompositorAnimationWarningContentTooLarg
 ## LOCALIZATION NOTE(CompositorAnimationWarningContentTooLarge2):
 ## (%1$S, %2$S) is a pair of integer values of the frame size
 ## (%3$S, %4$S) is a pair of integer values of a limit based on the viewport size
 ## (%5$S, %6$S) is a pair of integer values of an absolute limit
 CompositorAnimationWarningContentTooLarge2=Animation cannot be run on the compositor because the frame size (%1$S, %2$S) is too large relative to the viewport (larger than (%3$S, %4$S)) or larger than the maximum allowed value (%5$S, %6$S)
 ## LOCALIZATION NOTE(CompositorAnimationWarningTransformBackfaceVisibilityHidden):
 ## 'backface-visibility: hidden' is a CSS property, don't translate it.
 CompositorAnimationWarningTransformBackfaceVisibilityHidden=Animations of ‘backface-visibility: hidden’ transforms cannot be run on the compositor
-## LOCALIZATION NOTE(CompositorAnimationWarningTransformPreserve3D):
-## 'transform-style: preserve-3d' is a CSS property, don't translate it.
-CompositorAnimationWarningTransformPreserve3D=Animations of ‘transform-style: preserve-3d’ transforms cannot be run on the compositor
 ## LOCALIZATION NOTE(CompositorAnimationWarningTransformSVG,
 ##                   CompositorAnimationWarningTransformWithGeometricProperties,
 ##                   CompositorAnimationWarningTransformWithSyncGeometricAnimations,
 ##                   CompositorAnimationWarningTransformFrameInactive,
 ##                   CompositorAnimationWarningOpacityFrameInactive):
 ## 'transform' and 'opacity' mean CSS property names, don't translate it.
 CompositorAnimationWarningTransformSVG=Animations of ‘transform’ on elements with SVG transforms cannot be run on the compositor
 CompositorAnimationWarningTransformWithGeometricProperties=Animations of ‘transform’ cannot be run on the compositor when geometric properties are animated on the same element at the same time
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2847,19 +2847,19 @@ nsIFrame::BuildDisplayListForStackingCon
   // For preserves3d, use the dirty rect already installed on the
   // builder, since aDirtyRect maybe distorted for transforms along
   // the chain.
   nsRect visibleRect = aBuilder->GetVisibleRect();
   nsRect dirtyRect = aBuilder->GetDirtyRect();
 
   const bool isTransformed = IsTransformed(disp);
   const bool hasPerspective = isTransformed && HasPerspective(disp);
-  const bool extend3DContext = Extend3DContext(disp, effectSet);
+  const bool extend3DContext = Extend3DContext(disp, effectSet); // preserve-3d frame
   const bool combines3DTransformWithAncestors =
-    (extend3DContext || isTransformed) && Combines3DTransformWithAncestors(disp);
+    (extend3DContext || isTransformed) && Combines3DTransformWithAncestors(disp); // parent is preserve-3d
 
   Maybe<nsDisplayListBuilder::AutoPreserves3DContext> autoPreserves3DContext;
   if (extend3DContext && !combines3DTransformWithAncestors) {
     // Start a new preserves3d context to keep informations on
     // nsDisplayListBuilder.
     autoPreserves3DContext.emplace(aBuilder);
     // Save dirty rect on the builder to avoid being distorted for
     // multiple transforms along the chain.
--- a/layout/painting/ActiveLayerTracker.cpp
+++ b/layout/painting/ActiveLayerTracker.cpp
@@ -450,20 +450,25 @@ ActiveLayerTracker::IsStyleAnimated(nsDi
           (aProperty == eCSSProperty_transform && IsScaleSubjectToAnimation(aFrame))) {
         return true;
       }
     }
     if (CheckScrollInducedActivity(layerActivity, activityIndex, aBuilder)) {
       return true;
     }
   }
-  if (aProperty == eCSSProperty_transform && aFrame->Combines3DTransformWithAncestors()) {
-    return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty);
+
+  if (nsLayoutUtils::HasEffectiveAnimation(aFrame, aProperty)) {
+    return true;
   }
-  return nsLayoutUtils::HasEffectiveAnimation(aFrame, aProperty);
+  if (aProperty != eCSSProperty_transform ||
+      !aFrame->Combines3DTransformWithAncestors()) {
+    return false;
+  }
+  return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty);
 }
 
 /* static */ bool
 ActiveLayerTracker::IsOffsetStyleAnimated(nsIFrame* aFrame)
 {
   LayerActivity* layerActivity = GetLayerActivity(aFrame);
   if (layerActivity) {
     if (layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_LEFT] >= 2 ||
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -8070,16 +8070,24 @@ nsDisplayTransform::ShouldPrerenderTrans
 
   // If the incoming dirty rect already contains the entire overflow area,
   // we are already rendering the entire content.
   nsRect overflow = aFrame->GetVisualOverflowRectRelativeToSelf();
   if (aDirtyRect->Contains(overflow)) {
     return FullPrerender;
   }
 
+  if ((aFrame->Extend3DContext() || aFrame->IsPreserve3DLeaf()) &&
+      nsLayoutUtils::HasEffectiveAnimation(aFrame, eCSSProperty_transform)) {
+    // Layers participating any preserve-3d rendering context are
+    // force to prerendered to enable async animation at compositor
+    // thread.
+    return FullPrerender;
+  }
+
   float viewportRatioX = gfxPrefs::AnimationPrerenderViewportRatioLimitX();
   float viewportRatioY = gfxPrefs::AnimationPrerenderViewportRatioLimitY();
   uint32_t absoluteLimitX = gfxPrefs::AnimationPrerenderAbsoluteLimitX();
   uint32_t absoluteLimitY = gfxPrefs::AnimationPrerenderAbsoluteLimitY();
   nsSize refSize = aBuilder->RootReferenceFrame()->GetSize();
   // Only prerender if the transformed frame's size is <= a multiple of the
   // reference frame size (~viewport), and less than an absolute limit.
   // Both the ratio and the absolute limit are configurable.