Bug 1395971 - Wait for few frames until sending target animation to the compositor. r?hiro
This patch is a workaround for
bug 1341294.
This test checks compositor's animation properties, so we should check this
values after sending animation to the compositor.
This patch adds waiting for few frames until sending target animation to the
compositor.
MozReview-Commit-ID: 3dCG3gj46tA
--- a/dom/animation/test/mozilla/file_deferred_start.html
+++ b/dom/animation/test/mozilla/file_deferred_start.html
@@ -96,26 +96,21 @@ promise_test(function(t) {
// for paints and only then do we commence the test. Even doing that, this
// test can sometimes pass when it should not due to a stray paint. Most of
// the time, however, it will correctly fail so hopefully even if we do
// occasionally produce a false negative on one platform, another platform
// will fail as expected.
return waitForDocLoad().then(() => waitForIdle())
.then(() => waitForPaints())
.then(() => {
- div.animate({ transform: [ 'translate(0px)', 'translate(100px)' ] },
- { duration: 400 * MS_PER_SEC,
- delay: -200 * MS_PER_SEC });
-
- // TODO: Current waitForPaint() will not wait for MozAfterPaint in this
- // case(Bug 1341294), so this waiting code is workaround for it.
- // This waitForFrame() uses Promise, but bug 1193394 will be using same
- // handling of microtask, so if landed bug 1193394 this test might be
- // failure since this promise will resolve in same tick of Element.animate.
- return waitForFrame();
+ const anim = div.animate(
+ { transform: [ 'translate(0px)', 'translate(100px)' ] },
+ { duration: 400 * MS_PER_SEC,
+ delay: -200 * MS_PER_SEC });
+ return waitForBeginAnimationSentToCompositor(anim);
}).then(() => waitForPaints())
.then(() => {
const transformStr =
SpecialPowers.DOMWindowUtils.getOMTAStyle(div, 'transform');
const translateX = getTranslateXFromTransform(transformStr);
// If the delay has been applied we should be about half-way through
// the animation. However, if we applied it twice we will be at the
@@ -149,21 +144,18 @@ promise_test(function(t) {
.then(() => waitForPaints())
.then(() => {
const animation =
div.animate({ transform: [ 'translate(0px)', 'translate(100px)' ] },
200 * MS_PER_SEC);
animation.currentTime = 100 * MS_PER_SEC;
animation.playbackRate = 0.1;
- // As the above test case, we should fix bug 1341294 before bug 1193394
- // lands.
- return waitForFrame();
- }).then(() => waitForPaints())
- .then(() => {
+ return waitForBeginAnimationSentToCompositor(animation);
+ }).then(() => {
const transformStr =
SpecialPowers.DOMWindowUtils.getOMTAStyle(div, 'transform');
const translateX = getTranslateXFromTransform(transformStr);
// We pass the playback rate to the compositor independently and we have
// tests to ensure that it is correctly applied there. However, if, when
// we resolve the start time of the pending animation, we fail to
// incorporate the playback rate, we will end up starting from the wrong
--- a/dom/animation/test/testcommon.js
+++ b/dom/animation/test/testcommon.js
@@ -250,16 +250,39 @@ function waitForIdle() {
*/
function waitForAllAnimations(animations) {
return Promise.all(animations.map(function(animation) {
return animation.ready;
}));
}
/**
+ * Wait for few frames until sending animation to the compositor.
+ */
+function waitForBeginAnimationSentToCompositor(animation) {
+ // For present, An animation doesn't sent to compositor immediately, we should
+ // wait 3 frames at least. This value is fluctuant, the three times is
+ // empirically defined maximum value from try result.
+ let maxWaitForFrames = 3;
+ return new Promise(resolve => {
+ function handleFrame() {
+ if (SpecialPowers.wrap(animation).isRunningOnCompositor) {
+ resolve();
+ }
+ if (--maxWaitForFrames <= 0) {
+ resolve();
+ } else {
+ window.requestAnimationFrame(handleFrame);
+ }
+ }
+ window.requestAnimationFrame(handleFrame);
+ });
+}
+
+/**
* Flush the computed style for the given element. This is useful, for example,
* when we are testing a transition and need the initial value of a property
* to be computed so that when we synchronouslyet set it to a different value
* we actually get a transition instead of that being the initial value.
*/
function flushComputedStyle(elem) {
var cs = getComputedStyle(elem);
cs.marginLeft;