gecko/layout/style/test/test_animations_omta_start.html
Brian Birtles 07bc4e1535 Bug 975261 part 5 - Fix OMTA animations with backwards fill; r=dzbarsky
When we have a backwards fill and we sample at *exactly* the start of the
animation on the next refresh driver tick, when we get to
RestyleManager::ComputeStyleChangeFor (or more specifically
ElementRestyler::CaptureChange) we notice that the style hasn't changed (since
the first frame of the animation produces the same value as the backwards fill)
and end up with an empty change list. As a result we never schedule a view
manager flush and rebuild the layer. Hence, the animation never gets sent to the
compositor thread. On the next tick we're already throttling the main thread.

This patch fixes this by applying the same approach as is used for transitions,
that is, explicitly marking which animations are running on the compositor
thread so we know if we need to trigger a layer transaction or not. This should
not only be more robust than the previous code but also facilitate aligning
animations and transitions code (bug 880596).
2014-03-22 05:59:58 +08:00

142 lines
4.0 KiB
HTML

<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=975261
-->
<head>
<meta charset="utf-8">
<title>Test OMTA animations start correctly (Bug 975261)</title>
<script type="application/javascript"
src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="/tests/SimpleTest/paint_listener.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<style type="text/css">
@keyframes anim-opacity {
0% { opacity: 0.5 }
100% { opacity: 0.5 }
}
@keyframes anim-transform {
0% { transform: translate(50px); }
100% { transform: translate(50px); }
}
@keyframes anim-transform-2 {
0% { transform: translate(0px); }
100% { transform: translate(100px); }
}
.target {
/* These two lines are needed so that an opacity/transform layer
* already exists when the animation is applied. */
opacity: 0.99;
transform: translate(99px);
/* Element needs geometry in order to be animated on the
* compositor. */
width: 100px;
height: 100px;
background-color: white;
}
</style>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=975261">Mozilla Bug
975261</a>
<div id="display"></div>
<pre id="test">
<script type="application/javascript">
"use strict";
var gUtils = SpecialPowers.DOMWindowUtils;
var gOMTAPrefKey = "layers.offmainthreadcomposition.async-animations";
var gOMTCEnabled = gUtils.layerManagerRemote;
if (gOMTCEnabled && SpecialPowers.getBoolPref(gOMTAPrefKey)) {
SimpleTest.waitForExplicitFinish();
window.addEventListener("load", function() {
// Using paint_listener.js functions inside an onload handler is not safe
// (bug 986367) so spin the event loop first
SimpleTest.executeSoon(testDelay);
});
} else {
ok(true, "OMTA not available");
}
function newTarget() {
var target = document.createElement("div");
target.classList.add("target");
document.getElementById("display").appendChild(target);
return target;
}
function testDelay() {
gUtils.advanceTimeAndRefresh(0);
var target = newTarget();
target.setAttribute("style", "animation: 10s 10s anim-opacity linear");
gUtils.advanceTimeAndRefresh(0);
waitForAllPaints(function() {
gUtils.advanceTimeAndRefresh(10100);
waitForAllPaints(function() {
var opacity = gUtils.getOMTAStyle(target, "opacity");
is(opacity, 0.5,
"opacity is set on compositor thread after delayed start");
target.removeAttribute("style");
gUtils.restoreNormalRefresh();
testTransform();
});
});
}
function testTransform() {
gUtils.advanceTimeAndRefresh(0);
var target = newTarget();
target.setAttribute("style", "animation: 10s 10s anim-transform linear");
gUtils.advanceTimeAndRefresh(0);
waitForAllPaints(function() {
gUtils.advanceTimeAndRefresh(10100);
waitForAllPaints(function() {
var transform = gUtils.getOMTAStyle(target, "transform");
is(transform, "matrix(1, 0, 0, 1, 50, 0)",
"transform is set on compositor thread after delayed start");
target.removeAttribute("style");
gUtils.restoreNormalRefresh();
testBackwardsFill();
});
});
}
function testBackwardsFill() {
gUtils.advanceTimeAndRefresh(0);
var target = newTarget();
target.setAttribute("style",
"transform: translate(30px); " +
"animation: 10s 10s anim-transform-2 linear backwards");
gUtils.advanceTimeAndRefresh(0);
waitForAllPaints(function() {
gUtils.advanceTimeAndRefresh(10000);
waitForAllPaints(function() {
gUtils.advanceTimeAndRefresh(100);
waitForAllPaints(function() {
var transform = gUtils.getOMTAStyle(target, "transform");
is(transform, "matrix(1, 0, 0, 1, 1, 0)",
"transform is set on compositor thread after delayed start " +
"with backwards fill");
target.removeAttribute("style");
gUtils.restoreNormalRefresh();
SimpleTest.finish();
});
});
});
}
</script>
</pre>
</body>
</html>