Commit 2b037bdc authored by Majid Valipour's avatar Majid Valipour Committed by Commit Bot

[Animation Worklet] Fix flaky worklet-animation-with-fill-mode.https.html

Use a more robust method for waiting on receiving local times on main
thread when test is running with threaded compositing.

Previously we would wait for one async frame and some more time to ensure
we have received the local times on main thread. This can be flaky.
Instead wait until local time is no longer null which means worklet has
produced at least one frame and that frame has been synced with main.

To this end WorkletAnimation now exposes its effect (similar to regular
animations) and we use that to access the effect's local time.


Bug: 915352
Change-Id: I05ab560d90a55ff68e048b2c8ed19e87435dffeb
Reviewed-on: https://chromium-review.googlesource.com/c/1496478
Commit-Queue: Majid Valipour <majidvp@chromium.org>
Reviewed-by: default avatarYi Gu <yigu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#636970}
parent 1e1fca23
...@@ -70,6 +70,7 @@ class MODULES_EXPORT WorkletAnimation : public WorkletAnimationBase, ...@@ -70,6 +70,7 @@ class MODULES_EXPORT WorkletAnimation : public WorkletAnimationBase,
scoped_refptr<SerializedScriptValue>); scoped_refptr<SerializedScriptValue>);
~WorkletAnimation() override = default; ~WorkletAnimation() override = default;
AnimationEffect* effect() { return GetEffect(); }
AnimationTimeline* timeline() { return timeline_; } AnimationTimeline* timeline() { return timeline_; }
String playState(); String playState();
double currentTime(bool& is_null); double currentTime(bool& is_null);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
MeasureAs=WorkletAnimationConstructor, MeasureAs=WorkletAnimationConstructor,
OriginTrialEnabled=AnimationWorklet OriginTrialEnabled=AnimationWorklet
] interface WorkletAnimation { ] interface WorkletAnimation {
readonly attribute AnimationEffect? effect;
readonly attribute AnimationTimeline? timeline; readonly attribute AnimationTimeline? timeline;
readonly attribute AnimationPlayState playState; readonly attribute AnimationPlayState playState;
readonly attribute double? currentTime; readonly attribute double? currentTime;
......
...@@ -5937,7 +5937,6 @@ crbug.com/936827 external/wpt/fullscreen/api/element-request-fullscreen-and-remo ...@@ -5937,7 +5937,6 @@ crbug.com/936827 external/wpt/fullscreen/api/element-request-fullscreen-and-remo
crbug.com/915352 virtual/threaded/external/wpt/animation-worklet/playback-rate.https.html [ Pass Failure ] crbug.com/915352 virtual/threaded/external/wpt/animation-worklet/playback-rate.https.html [ Pass Failure ]
crbug.com/915352 virtual/threaded/external/wpt/animation-worklet/scroll-timeline-writing-modes.https.html [ Pass Failure ] crbug.com/915352 virtual/threaded/external/wpt/animation-worklet/scroll-timeline-writing-modes.https.html [ Pass Failure ]
crbug.com/915352 virtual/threaded/external/wpt/animation-worklet/worklet-animation-pause-resume.https.html [ Pass Failure ] crbug.com/915352 virtual/threaded/external/wpt/animation-worklet/worklet-animation-pause-resume.https.html [ Pass Failure ]
crbug.com/915352 virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-fill-mode.https.html [ Pass Failure ]
crbug.com/915352 [ Mac10.10 Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Pass Failure ] crbug.com/915352 [ Mac10.10 Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Pass Failure ]
crbug.com/915352 [ Mac10.10 Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html [ Pass Failure ] crbug.com/915352 [ Mac10.10 Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html [ Pass Failure ]
......
...@@ -35,7 +35,7 @@ async function waitForAnimationFrameWithCondition(condition) { ...@@ -35,7 +35,7 @@ async function waitForAnimationFrameWithCondition(condition) {
do { do {
await new Promise(window.requestAnimationFrame); await new Promise(window.requestAnimationFrame);
} while (!condition()) } while (!condition())
}; }
async function waitForDocumentTimelineAdvance() { async function waitForDocumentTimelineAdvance() {
const timeAtStart = document.timeline.currentTime; const timeAtStart = document.timeline.currentTime;
...@@ -43,3 +43,10 @@ async function waitForDocumentTimelineAdvance() { ...@@ -43,3 +43,10 @@ async function waitForDocumentTimelineAdvance() {
await new Promise(window.requestAnimationFrame); await new Promise(window.requestAnimationFrame);
} while (timeAtStart === document.timeline.currentTime) } while (timeAtStart === document.timeline.currentTime)
} }
// Wait until animation's effect has a non-null localTime.
async function waitForNotNullLocalTime(animation) {
await waitForAnimationFrameWithCondition(_ => {
return animation.effect.getComputedTiming().localTime !== null;
});
}
\ No newline at end of file
...@@ -50,110 +50,98 @@ function setupAndRegisterTests() { ...@@ -50,110 +50,98 @@ function setupAndRegisterTests() {
} }
async function effect_with_fill_mode_forwards(t) { async function effect_with_fill_mode_forwards(t) {
const effect_with_fill_forwards = new KeyframeEffect( const effect_with_fill_forwards = new KeyframeEffect(
target, target,
{ opacity: [0.5, 0] }, { opacity: [0.5, 0] },
{ duration: 1000, fill: 'forwards' }); { duration: 1000, fill: 'forwards' });
const animation = new WorkletAnimation( const animation = new WorkletAnimation(
'constant_time', 'constant_time',
effect_with_fill_forwards); effect_with_fill_forwards);
animation.play(); animation.play();
await waitForNotNullLocalTime(animation);
await waitForAsyncAnimationFrames(1);
await waitForNextFrame(); assert_equals(getComputedStyle(target).opacity, '0');
assert_equals(getComputedStyle(target).opacity, '0'); animation.cancel();
animation.cancel();
} }
async function effect_without_fill_mode_forwards(t) { async function effect_without_fill_mode_forwards(t) {
const effect_without_fill_forwards = new KeyframeEffect( const effect_without_fill_forwards = new KeyframeEffect(
target, target,
{ opacity: [0.5, 0] }, { opacity: [0.5, 0] },
{ duration: 1000 }); { duration: 1000 });
const animation = new WorkletAnimation( const animation = new WorkletAnimation(
'constant_time', 'constant_time',
effect_without_fill_forwards); effect_without_fill_forwards);
animation.play(); animation.play();
await waitForNotNullLocalTime(animation);
await waitForAsyncAnimationFrames(1);
await waitForNextFrame(); assert_equals(getComputedStyle(target).opacity, '1');
assert_equals(getComputedStyle(target).opacity, '1'); animation.cancel();
animation.cancel();
} }
async function effect_without_fill_forwards_at_end(t) { async function effect_without_fill_forwards_at_end(t) {
const effect_without_fill_forwards_at_end = new KeyframeEffect( const effect_without_fill_forwards_at_end = new KeyframeEffect(
target, target,
{ opacity: [0.5, 0] }, { opacity: [0.5, 0] },
{ duration: 2000 }); { duration: 2000 });
const animation = new WorkletAnimation( const animation = new WorkletAnimation(
'constant_time', 'constant_time',
effect_without_fill_forwards_at_end); effect_without_fill_forwards_at_end);
animation.play(); animation.play();
await waitForNotNullLocalTime(animation);
await waitForAsyncAnimationFrames(1);
await waitForNextFrame(); assert_equals(getComputedStyle(target).opacity, '1');
assert_equals(getComputedStyle(target).opacity, '1'); animation.cancel();
animation.cancel();
} }
async function effect_with_fill_backwards(t) { async function effect_with_fill_backwards(t) {
const effect_with_fill_backwards = new KeyframeEffect( const effect_with_fill_backwards = new KeyframeEffect(
target, target,
{ opacity: [0.5, 0] }, { opacity: [0.5, 0] },
{ duration: 1000, delay: 2001, fill: 'backwards' }); { duration: 1000, delay: 2001, fill: 'backwards' });
const animation = new WorkletAnimation( const animation = new WorkletAnimation(
'constant_time', 'constant_time',
effect_with_fill_backwards); effect_with_fill_backwards);
animation.play(); animation.play();
await waitForNotNullLocalTime(animation);
await waitForAsyncAnimationFrames(1);
await waitForNextFrame(); assert_equals(getComputedStyle(target).opacity, '0.5');
assert_equals(getComputedStyle(target).opacity, '0.5'); animation.cancel();
animation.cancel();
} }
async function effect_without_fill_backwards(t) { async function effect_without_fill_backwards(t) {
const effect_without_fill_backwards = new KeyframeEffect( const effect_without_fill_backwards = new KeyframeEffect(
target, target,
{ opacity: [0.5, 0] }, { opacity: [0.5, 0] },
{ duration: 1000, delay: 2001 }); { duration: 1000, delay: 2001 });
const animation = new WorkletAnimation( const animation = new WorkletAnimation(
'constant_time', 'constant_time',
effect_without_fill_backwards); effect_without_fill_backwards);
animation.play(); animation.play();
waitForNotNullLocalTime(animation);
await waitForAsyncAnimationFrames(1);
await waitForNextFrame(); assert_equals(getComputedStyle(target).opacity, '1');
assert_equals(getComputedStyle(target).opacity, '1'); animation.cancel();
animation.cancel();
} }
async function effect_without_fill_backwards_at_start(t) { async function effect_without_fill_backwards_at_start(t) {
const effect_without_fill_backwards_at_start = new KeyframeEffect( const effect_without_fill_backwards_at_start = new KeyframeEffect(
target, target,
{ opacity: [0.5, 0] }, { opacity: [0.5, 0] },
{ duration: 1000, delay: 2000 }); { duration: 1000, delay: 2000 });
const animation = new WorkletAnimation( const animation = new WorkletAnimation(
'constant_time', 'constant_time',
effect_without_fill_backwards_at_start); effect_without_fill_backwards_at_start);
animation.play(); animation.play();
await waitForNotNullLocalTime(animation);
await waitForAsyncAnimationFrames(1);
await waitForNextFrame(); assert_equals(getComputedStyle(target).opacity, '0.5');
assert_equals(getComputedStyle(target).opacity, '0.5'); animation.cancel();
animation.cancel();
} }
</script> </script>
...@@ -10351,6 +10351,7 @@ interface Worklet ...@@ -10351,6 +10351,7 @@ interface Worklet
interface WorkletAnimation interface WorkletAnimation
attribute @@toStringTag attribute @@toStringTag
getter currentTime getter currentTime
getter effect
getter playState getter playState
getter playbackRate getter playbackRate
getter startTime getter startTime
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment