Bug 779598 - Do animations of transforms with preserve-3d at compositor. r?mattwoodrow
MozReview-Commit-ID: CAHPuIDk90a
--- 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.