Bug 1425837 - Part 9: Throttle transform-like properties animations without 0% or 100% keyframe. r=hiro
authorBoris Chiou <boris.chiou@gmail.com>
Mon, 18 Mar 2019 18:05:06 +0000
changeset 464942 08126c1f53fe82ab685bd3e75e97ce7bf516a3d9
parent 464941 9fe743aa6c94f49346902934f40f8f55663bc54d
child 464943 408ad1db01684276e4354f80e489d612f63a41fb
push id80792
push userbchiou@mozilla.com
push dateTue, 19 Mar 2019 08:04:11 +0000
treeherderautoland@08126c1f53fe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershiro
bugs1425837
milestone68.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 1425837 - Part 9: Throttle transform-like properties animations without 0% or 100% keyframe. r=hiro We should also throttle other transform-like animations which can run on the compositor thread, on visibility hidden element without 0% or 100% keyframe. Depends on D22568 Differential Revision: https://phabricator.services.mozilla.com/D19634
dom/animation/KeyframeEffect.cpp
dom/animation/test/mozilla/file_restyles.html
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -1577,17 +1577,18 @@ void KeyframeEffect::CalculateCumulative
     }
 
     for (const AnimationPropertySegment& segment : property.mSegments) {
       // In case composite operation is not 'replace' or value is null,
       // we can't throttle animations which will not cause any layout changes
       // on invisible elements because we can't calculate the change hint for
       // such properties until we compose it.
       if (!segment.HasReplaceableValues()) {
-        if (property.mProperty != eCSSProperty_transform) {
+        if (!nsCSSPropertyIDSet::TransformLikeProperties().HasProperty(
+                property.mProperty)) {
           mCumulativeChangeHint = ~nsChangeHint_Hints_CanIgnoreIfNotVisible;
           return;
         }
         // We try a little harder to optimize transform animations simply
         // because they are so common (the second-most commonly animated
         // property at the time of writing).  So if we encounter a transform
         // segment that needs composing with the underlying value, we just add
         // all the change hints a transform animation is known to be able to
--- a/dom/animation/test/mozilla/file_restyles.html
+++ b/dom/animation/test/mozilla/file_restyles.html
@@ -1777,16 +1777,76 @@ waitForAllPaints(() => {
     const markers = await observeStyling(5);
 
     is(markers.length, 0,
        'Transform animations without 100% keyframe on visibility hidden ' +
        'element should be throttled');
     await ensureElementRemoval(div);
   });
 
+  add_task(async function restyling_translate_animations_on_invisible_element() {
+    const div = addDiv(null, { style: 'visibility: hidden;' });
+
+    const animation =
+      div.animate([ { translate: '100px' } ],
+                  { duration: 100 * MS_PER_SEC,
+                    iterations: Infinity });
+
+    await waitForAnimationReadyToRestyle(animation);
+
+    ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
+
+    const markers = await observeStyling(5);
+
+    is(markers.length, 0,
+       'Translate animations without 100% keyframe on visibility hidden ' +
+       'element should be throttled');
+    await ensureElementRemoval(div);
+  });
+
+  add_task(async function restyling_rotate_animations_on_invisible_element() {
+    const div = addDiv(null, { style: 'visibility: hidden;' });
+
+    const animation =
+      div.animate([ { rotate: '45deg' } ],
+                  { duration: 100 * MS_PER_SEC,
+                    iterations: Infinity });
+
+    await waitForAnimationReadyToRestyle(animation);
+
+    ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
+
+    const markers = await observeStyling(5);
+
+    is(markers.length, 0,
+       'Rotate animations without 100% keyframe on visibility hidden ' +
+       'element should be throttled');
+    await ensureElementRemoval(div);
+  });
+
+  add_task(async function restyling_scale_animations_on_invisible_element() {
+    const div = addDiv(null, { style: 'visibility: hidden;' });
+
+    const animation =
+      div.animate([ { scale: '2 2' } ],
+                  { duration: 100 * MS_PER_SEC,
+                    iterations: Infinity });
+
+    await waitForAnimationReadyToRestyle(animation);
+
+    ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
+
+    const markers = await observeStyling(5);
+
+    is(markers.length, 0,
+       'Scale animations without 100% keyframe on visibility hidden ' +
+       'element should be throttled');
+    await ensureElementRemoval(div);
+  });
+
   add_task(
     async function restyling_transform_animations_having_abs_pos_child_on_invisible_element() {
       const div = addDiv(null, { style: 'visibility: hidden;' });
       const child = addDiv(null, { style: 'position: absolute; top: 100px;' });
       div.appendChild(child);
 
       const animation =
         div.animate({ transform: [ 'none',  'rotate(360deg)' ] },