Commit 2f3124ad authored by Kevin Ellis's avatar Kevin Ellis Committed by Chromium LUCI CQ

Fix calculation of the finished state of an animation.

Accommodate numerical precision errors when determining if an animation
is finished. The finish method explicitly sets current time to be
EffectEnd(); however, the value could be off by as much as 1.10155e-16
due to quantization error. The possibility for quantization error
triggered a 0.5% flakiness of one of the tests in
updating-the-finished-state.html. The test in question performed a
seek after calling finish, which should have triggered a finished event
even though the animation is no longer finished after the seek  (finish
is synchronous). The play state was still detected as running after
finish was called. This patch accommodates fuzzy equality when
calculating the play state.

Performed 1000 runs of the test after the patch with 0 flakes, which
gives 95% confidence that the probability of a failure has been reduced
to less than 0.052% (a 100x reduction).

Bug: 1139023
Change-Id: Ibf4104c3cb8fcacdc96abbb0cda8e7c05cc525c4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2621924Reviewed-by: default avatarXida Chen <xidachen@chromium.org>
Commit-Queue: Kevin Ellis <kevers@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842549}
parent c87a4a6b
......@@ -299,8 +299,12 @@ double Animation::EffectEnd() const {
}
bool Animation::Limited(base::Optional<double> current_time) const {
if (!current_time)
return false;
return (EffectivePlaybackRate() < 0 && current_time <= 0) ||
(EffectivePlaybackRate() > 0 && current_time >= EffectEnd());
(EffectivePlaybackRate() > 0 &&
GreaterThanOrEqualToWithinEpsilon(current_time.value(), EffectEnd()));
}
Document* Animation::GetDocument() const {
......
......@@ -56,10 +56,14 @@ static inline bool IsWithinAnimationTimeEpsilon(double a, double b) {
return std::abs(a - b) <= TimingCalculationEpsilon();
}
inline bool LessThanOrEqualToWithinEpsilon(double a, double b) {
static inline bool LessThanOrEqualToWithinEpsilon(double a, double b) {
return a <= b + TimingCalculationEpsilon();
}
static inline bool GreaterThanOrEqualToWithinEpsilon(double a, double b) {
return a >= b - TimingCalculationEpsilon();
}
static inline double MultiplyZeroAlwaysGivesZero(double x, double y) {
DCHECK(!std::isnan(x));
DCHECK(!std::isnan(y));
......
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