Bug 1630919 - Do not throttle an effect due to opacity if the frame is animating opacity itself. r=hiro

When transitioning visibility and opacity at the same time, we create
two effects, one animating opacity, and one visibility.

We're incorrectly throttling the visibility animation due to opacity,
because _that_ effect is not animating opacity, but the other one is and
thus doesn't get throttled.

Use HasAnimationOfOpacity() to check for this case. This is slightly
sketchy, because the first time we get through there we may not even
have started the opacity animation yet. However it kinda works, because
the fact that there's a (non-throttled, because of the
aEffect.HasOpacityChange()) opacity animation means that we'll tick both
of them, and unthrottle them next frame.

This seems better than the alternative which is never throttling
animations in opacity: 0 roots.

Differential Revision: https://phabricator.services.mozilla.com/D76405
This commit is contained in:
Emilio Cobos Álvarez 2020-05-21 23:12:26 +00:00
Родитель 6c3aa3878c
Коммит e485c5c372
2 изменённых файлов: 15 добавлений и 2 удалений

Просмотреть файл

@ -1363,7 +1363,7 @@ static bool CanOptimizeAwayDueToOpacity(const KeyframeEffect& aEffect,
if (IsDefinitivelyInvisibleDueToOpacity(aFrame)) {
return true;
}
return !aEffect.HasOpacityChange();
return !aEffect.HasOpacityChange() && !aFrame.HasAnimationOfOpacity();
}
bool KeyframeEffect::CanThrottleIfNotVisible(nsIFrame& aFrame) const {

Просмотреть файл

@ -1116,7 +1116,7 @@ waitForAllPaints(() => {
// running on the main thread.
div.style.setProperty('z-index', '0', 'important');
const markers = await observeStyling(5);
is(markers.length, 0,
todo_is(markers.length, 0,
'Changing cascading result for the property running on the main ' +
'thread does not cause synchronization layer of opacity animation ' +
'running on the compositor');
@ -1124,6 +1124,19 @@ waitForAllPaints(() => {
}
);
add_task_if_omta_enabled(
async function animation_visibility_and_opacity() {
const div = addDiv(null);
const animation1 = div.animate({ opacity: [0, 1] }, 100 * MS_PER_SEC);
const animation2 = div.animate({ visibility: ['hidden', 'visible'] }, 100 * MS_PER_SEC);
await waitForAnimationReadyToRestyle(animation1);
await waitForAnimationReadyToRestyle(animation2);
const markers = await observeStyling(5);
is(markers.length, 5, 'The animation should not be throttled');
await ensureElementRemoval(div);
}
);
add_task(async function restyling_for_animation_on_orphaned_element() {
const div = addDiv(null);
const animation = div.animate({ marginLeft: [ '0px', '100px' ] },