Bug 1383239 - Don't throttle non-visible changes involved animations on out-of-view elements when they are newly in-effect. r?birtles
MozReview-Commit-ID: G9OL3pPZarr
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -120,33 +120,35 @@ KeyframeEffectReadOnly::NotifyAnimationT
// the compositor and hence they won't have their compositor status
// updated. As a result, we need to make sure we clear their compositor
// status here.
bool isRelevant = mAnimation && mAnimation->IsRelevant();
if (!isRelevant) {
ResetIsRunningOnCompositor();
}
- // Detect changes to "in effect" status since we need to recalculate the
- // animation cascade for this element whenever that changes.
- bool inEffect = IsInEffect();
- if (inEffect != mInEffectOnLastAnimationTimingUpdate) {
- MarkCascadeNeedsUpdate();
- mInEffectOnLastAnimationTimingUpdate = inEffect;
- }
-
// Request restyle if necessary.
if (mAnimation && !mProperties.IsEmpty() && HasComputedTimingChanged()) {
EffectCompositor::RestyleType restyleType =
CanThrottle() ?
EffectCompositor::RestyleType::Throttled :
EffectCompositor::RestyleType::Standard;
RequestRestyle(restyleType);
}
+ // Detect changes to "in effect" status since we need to recalculate the
+ // animation cascade for this element whenever that changes.
+ // Note that updating mInEffectOnLastAnimationTimingUpdate has to be done
+ // after above CanThrottle() call since the function uses the flag inside it.
+ bool inEffect = IsInEffect();
+ if (inEffect != mInEffectOnLastAnimationTimingUpdate) {
+ MarkCascadeNeedsUpdate();
+ mInEffectOnLastAnimationTimingUpdate = inEffect;
+ }
+
// If we're no longer "in effect", our ComposeStyle method will never be
// called and we will never have a chance to update mProgressOnLastCompose
// and mCurrentIterationOnLastCompose.
// We clear them here to ensure that if we later become "in effect" we will
// request a restyle (above).
if (!inEffect) {
mProgressOnLastCompose.SetNull();
mCurrentIterationOnLastCompose = 0;
@@ -1370,19 +1372,20 @@ KeyframeEffectReadOnly::CanThrottle() co
// a) No target element
// b) The target element has no frame, e.g. because it is in a display:none
// subtree.
// In either case we can throttle the animation because there is no
// need to update on the main thread.
return true;
}
- // We can throttle the animation if the animation is paint only and
- // the target frame is out of view or the document is in background tabs.
- if (CanIgnoreIfNotVisible()) {
+ // Unless we are newly in-effect, we can throttle the animation if the
+ // animation is paint only and the target frame is out of view or the document
+ // is in background tabs.
+ if (mInEffectOnLastAnimationTimingUpdate && CanIgnoreIfNotVisible()) {
nsIPresShell* presShell = GetPresShell();
if ((presShell && !presShell->IsActive()) ||
frame->IsScrolledOutOfView()) {
return true;
}
}
// First we need to check layer generation and transform overflow
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-animations/animation-initially-out-of-view-with-delay-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<title>Bug 1383239</title>
+<style>
+div {
+ position: absolute;
+ background: orange;
+ width: 20px;
+ height: 20px;
+ left: 0px;
+}
+</style>
+<div></div>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-animations/animation-initially-out-of-view-with-delay.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait reftest-no-flush">
+<title>Bug 1383239</title>
+<style>
+div {
+ position: absolute;
+ left: -9999px;
+ background: orange;
+ width: 20px;
+ height: 20px;
+ animation: anim 100s 0.1s infinite;
+}
+
+@keyframes anim {
+ 0% {
+ left: 0px;
+ }
+ 100% {
+ left: 0px;
+ }
+}
+</style>
+<div></div>
+<script>
+document.querySelector('div').addEventListener('animationstart', ()=> {
+ document.documentElement.classList.remove('reftest-wait');
+});
+</script>
+</html>
--- a/layout/reftests/css-animations/reftest.list
+++ b/layout/reftests/css-animations/reftest.list
@@ -1,14 +1,15 @@
== screen-animations.html screen-animations-ref.html
!= screen-animations.html screen-animations-notref.html
skip-if(stylo) fails == print-no-animations.html print-no-animations-ref.html # reftest harness doesn't actually make pres context non-dynamic for reftest-paged tests. Bug 1374154 for stylo
skip-if(stylo) fails != print-no-animations.html print-no-animations-notref.html # reftest harness doesn't actually make pres context non-dynamic for reftest-paged tests. Bug 1374154 for stylo
== animate-opacity.html animate-opacity-ref.html
== animate-preserves3d.html animate-preserves3d-ref.html
+== animation-initially-out-of-view-with-delay.html animation-initially-out-of-view-with-delay-ref.html
== animation-on-empty-height-frame.html about:blank
== in-visibility-hidden-animation.html in-visibility-hidden-animation-ref.html
== in-visibility-hidden-animation-pseudo-element.html in-visibility-hidden-animation-pseudo-element-ref.html
== partially-out-of-view-animation.html partially-out-of-view-animation-ref.html
== animate-display-table-opacity.html animate-display-table-opacity-ref.html
# We need to run 100% opacity test case when OMTA is disabled to check that the animation creates a stacking context even if the animation is not running on the compositor
test-pref(layers.offmainthreadcomposition.async-animations,false) == stacking-context-opacity-1-animation.html stacking-context-animation-ref.html
# We need to run transform:none test case when OMTA is disabled to check that the animation creates a stacking context even if the animation is not running on the compositor