Bug 1196114 - Part 2: Add AnimationPropertyStatus interface and KeyframeEffectReadOnly.runningStatus(). r?birtles draft
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Fri, 12 Feb 2016 10:46:01 +0900
changeset 330606 2b21e2fcd7100cb69753225a924bd2eeac85373e
parent 330605 99279e691ab49797426762ee405a5cae8395676c
child 330607 06ae879caf7b6d5b7e3adf4ba7896c2770fc6a2f
push id10781
push userhiikezoe@mozilla-japan.org
push dateFri, 12 Feb 2016 01:47:31 +0000
reviewersbirtles
bugs1196114
milestone47.0a1
Bug 1196114 - Part 2: Add AnimationPropertyStatus interface and KeyframeEffectReadOnly.runningStatus(). r?birtles MozReview-Commit-ID: KVB64Frrg7B
dom/animation/KeyframeEffect.cpp
dom/animation/KeyframeEffect.h
dom/animation/test/chrome.ini
dom/animation/test/chrome/test_running_status.html
dom/webidl/KeyframeEffect.webidl
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -1797,16 +1797,41 @@ KeyframeEffectReadOnly::GetFrames(JSCont
       previousEntry = entry;
       entry = &entries[i];
     } while (entry->SameKeyframe(*previousEntry));
 
     aResult.AppendElement(keyframe);
   }
 }
 
+
+void
+KeyframeEffectReadOnly::RunningStatus(
+    nsTArray<AnimationPropertyStatus>& aStatus)
+{
+  for (AnimationProperty& property : mProperties) {
+    if (!property.mWinsInCascade) {
+      continue;
+    }
+
+    AnimationPropertyStatus status;
+    status.mProperty.Construct(
+      NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(property.mProperty)));
+    status.mRunningOnCompositor.Construct(property.mIsRunningOnCompositor);
+
+    if (!property.mWarningMessage.IsEmpty()) {
+      AnimationPerformanceWarning warning;
+      warning.mMessage.Construct(property.mWarningMessage);
+      status.mWarning = warning;
+    }
+
+    aStatus.AppendElement(status);
+  }
+}
+
 /* static */ const TimeDuration
 KeyframeEffectReadOnly::OverflowRegionRefreshInterval()
 {
   // The amount of time we can wait between updating throttled animations
   // on the main thread that influence the overflow region.
   static const TimeDuration kOverflowRegionRefreshInterval =
     TimeDuration::FromMilliseconds(200);
 
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -39,16 +39,17 @@ struct AnimationCollection;
 class AnimValuesStyleRule;
 
 namespace dom {
 class ElementOrCSSPseudoElement;
 class OwningElementOrCSSPseudoElement;
 class UnrestrictedDoubleOrKeyframeEffectOptions;
 enum class IterationCompositeOperation : uint32_t;
 enum class CompositeOperation : uint32_t;
+struct AnimationPropertyStatus;
 }
 
 /**
  * Stores the results of calculating the timing properties of an animation
  * at a given sample time.
  */
 struct ComputedTiming
 {
@@ -303,16 +304,18 @@ public:
   // contained in |aSetProperties|.
   // Any updated properties are added to |aSetProperties|.
   void ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
                     nsCSSPropertySet& aSetProperties);
   // Returns true if at least one property is being animated on compositor.
   bool IsRunningOnCompositor() const;
   void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning);
 
+  void RunningStatus(nsTArray<AnimationPropertyStatus>& aStatus);
+
   // Returns true if this effect, applied to |aFrame|, contains
   // properties that mean we shouldn't run *any* compositor animations on this
   // element.
   //
   // For example, if we have an animation of geometric properties like 'left'
   // and 'top' on an element, we force all 'transform' and 'opacity' animations
   // running at the same time on the same element to run on the main thread.
   //
--- a/dom/animation/test/chrome.ini
+++ b/dom/animation/test/chrome.ini
@@ -5,8 +5,9 @@ support-files =
   ../../imptests/testharnessreport.js
 [chrome/test_animate_xrays.html]
 # file_animate_xrays.html needs to go in mochitest.ini since it is served
 # over HTTP
 [chrome/test_animation_observers.html]
 [chrome/test_restyles.html]
 [chrome/test_running_on_compositor.html]
 skip-if = buildapp == 'b2g'
+[chrome/test_running_status.html]
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/chrome/test_running_status.html
@@ -0,0 +1,127 @@
+<!doctype html>
+<head>
+<meta charset=utf-8>
+<title>Bug 1196114 - Animation property which indicates
+       running on the compositor or not</title>
+<script type="application/javascript" src="../testharness.js"></script>
+<script type="application/javascript" src="../testharnessreport.js"></script>
+<script type="application/javascript" src="../testcommon.js"></script>
+<style>
+div {
+  /* Element needs geometry to be eligible for layerization */
+  width: 100px;
+  height: 100px;
+  background-color: white;
+}
+</style>
+</head>
+<body>
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1196114"
+  target="_blank">Mozilla Bug 1196114</a>
+<div id="log"></div>
+<script>
+'use strict';
+
+function compare_property_status(a, b) {
+  if (a.property > b.property) {
+    return -1;
+  } else if (a.property < b.property) {
+    return 1;
+  }
+  if (a.runningOnCompositor != b.runningOnCompositor) {
+    return a.runningOnCompositor ? 1 : -1;
+  }
+  return a.warning > b.warning ? -1 : 1;
+}
+
+function assert_running_status_equals(actual, expected) {
+  assert_equals(actual.length, expected.length);
+
+  var sortedActual = actual.sort(compare_property_status);
+  var sortedExpected = expected.sort(compare_property_status);
+
+  for (var i = 0; i < sortedActual.length; i++) {
+    assert_equals(sortedActual[i].property,
+                  sortedExpected[i].property,
+                  'CSS property name should be ' + sortedExpected[i].property);
+    assert_equals(sortedActual[i].runningOnCompositor,
+                  sortedExpected[i].runningOnCompositor,
+                  'runningOnCompositor property should be ' +
+                  sortedExpected[i].runningOnCompositor);
+  }
+}
+
+var gAnimationsTests = [
+  {
+    desc: 'animations on compositor',
+    frames: {
+      opacity: [0, 1]
+    },
+    expected: [
+      {
+        property: 'opacity',
+        runningOnCompositor: true
+      }
+    ]
+  },
+  {
+    desc: 'animations on main thread',
+    frames: {
+      backgroundColor: ['white', 'red']
+    },
+    expected: [
+      {
+        property: 'background-color',
+        runningOnCompositor: false
+      }
+    ]
+  },
+  {
+    desc: 'animations on both threads',
+    frames: {
+      backgroundColor: ['white', 'red'],
+      transform: ['translate(0px)', 'translate(100px)']
+    },
+    expected: [
+      {
+        property: 'background-color',
+        runningOnCompositor: false
+      },
+      {
+        property: 'transform',
+        runningOnCompositor: true
+      }
+    ]
+  },
+  {
+    desc: 'two animation properties on compositor thread',
+    frames: {
+      opacity: [0, 1],
+      transform: ['translate(0px)', 'translate(100px)']
+    },
+    expected: [
+      {
+        property: 'opacity',
+        runningOnCompositor: true
+      },
+      {
+        property: 'transform',
+        runningOnCompositor: true
+      }
+    ]
+  }
+];
+
+gAnimationsTests.forEach(function(subtest) {
+  promise_test(function(t) {
+    var div = addDiv(t);
+    var animation = div.animate(subtest.frames, 100000);
+    return animation.ready.then(t.step_func(function() {
+      assert_running_status_equals(animation.effect.runningStatus(),
+                                   subtest.expected);
+    }));
+  }, subtest.desc);
+});
+
+</script>
+</body>
--- a/dom/webidl/KeyframeEffect.webidl
+++ b/dom/webidl/KeyframeEffect.webidl
@@ -39,8 +39,23 @@ interface KeyframeEffectReadOnly : Anima
 
   // Not yet implemented:
   // KeyframeEffect             clone();
 
   // We use object instead of ComputedKeyframe so that we can put the
   // property-value pairs on the object.
   [Throws] sequence<object> getFrames();
 };
+
+// Non-standard extensions
+dictionary AnimationPropertyStatus {
+  DOMString property;
+  boolean runningOnCompositor;
+  AnimationPerformanceWarning warning;
+};
+
+dictionary AnimationPerformanceWarning {
+  DOMString message;
+};
+
+partial interface KeyframeEffectReadOnly {
+  [ChromeOnly] sequence<AnimationPropertyStatus> runningStatus();
+};