forked from mirrors/gecko-dev
Instead of starting transitions and animations as a result of a paint, use the refresh driver tick to do this. This sets the transition-ready time to the current time during the next refresh driver tick that it was started on (see mSawTickWhilePending). This is similar to what's described in the bugs comments, and seems to work nicely in practice. We could easily change that (current time) by a paint-based time if needed (when available), which would be more similar to what we were doing. But I'd rather do the simple thing for now, and land this shortly after the soft freeze is over so that we have time to watch out for regressions. There's one regression on a test that birtles wrote (using an XHR doc and switching the timeline to a rendered doc's timeline). We use the timeline's document rather than the target document to determine whether to trigger animations now. That's one of the cases where we'd keep vsync perma-running without this patch, and Chrome also fails that test. Maybe the test should be removed / the spec should be tweaked to allow this behavior? This causes some progression in some CSS transitions tests too, and I added an extra test for the vsync behavior. Over-all this is much simpler to reason about and I think we should try to do this. Differential Revision: https://phabricator.services.mozilla.com/D193583
48 lines
2.1 KiB
C++
48 lines
2.1 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "ScrollTimelineAnimationTracker.h"
|
|
|
|
#include "mozilla/dom/Document.h"
|
|
|
|
namespace mozilla {
|
|
|
|
NS_IMPL_CYCLE_COLLECTION(ScrollTimelineAnimationTracker, mPendingSet, mDocument)
|
|
|
|
void ScrollTimelineAnimationTracker::TriggerPendingAnimations() {
|
|
for (auto iter = mPendingSet.begin(), end = mPendingSet.end(); iter != end;
|
|
++iter) {
|
|
dom::Animation* animation = *iter;
|
|
|
|
MOZ_ASSERT(animation->GetTimeline() &&
|
|
!animation->GetTimeline()->IsMonotonicallyIncreasing());
|
|
|
|
// FIXME: Trigger now may not be correct because the spec says:
|
|
// If a user agent determines that animation is immediately ready, it may
|
|
// schedule the task (i.e. ResumeAt()) as a microtask such that it runs at
|
|
// the next microtask checkpoint, but it must not perform the task
|
|
// synchronously.
|
|
// Note: So, for now, we put the animation into the tracker, and trigger
|
|
// them immediately until the frames are ready. Using TriggerOnNextTick()
|
|
// for scroll-driven animations may have issues because we don't tick if
|
|
// no one does scroll.
|
|
if (!animation->TryTriggerNow()) {
|
|
// Note: We keep this animation pending even if its timeline is always
|
|
// inactive. It's pretty hard to tell its future status, for example, it's
|
|
// possible that the scroll container is in display:none subtree but the
|
|
// animating element isn't the subtree, then we need to keep tracking the
|
|
// situation until the scroll container gets framed. so in general we make
|
|
// this animation be pending (i.e. not ready) if its scroll-timeline is
|
|
// inactive, and this also matches the current spec definition.
|
|
continue;
|
|
}
|
|
|
|
// Note: Remove() is legitimately called once per entry during the loop.
|
|
mPendingSet.Remove(iter);
|
|
}
|
|
}
|
|
|
|
} // namespace mozilla
|