Bug 1829488 - Move animated image processing to its own function. r=smaug

Just a minor cleanup that I think it's worth it after bug 1828587.

Differential Revision: https://phabricator.services.mozilla.com/D176216
This commit is contained in:
Emilio Cobos Álvarez 2023-04-22 20:37:49 +00:00
Родитель 57309ebbbf
Коммит fba7195d18
2 изменённых файлов: 78 добавлений и 68 удалений

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

@ -2423,7 +2423,7 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime,
return;
}
TimeStamp previousRefresh = mMostRecentRefresh;
const TimeStamp previousRefresh = mMostRecentRefresh;
mMostRecentRefresh = aNowTime;
if (mRootRefresh) {
@ -2703,73 +2703,7 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime,
UpdateIntersectionObservations(aNowTime);
// Perform notification to imgIRequests subscribed to listen for refresh
// events. Don't do this when throttled, as (just like when painting) the
// compositor might be paused and we don't want to queue a lot of paints, see
// bug 1828587.
if (!mThrottled) {
for (const auto& entry : mStartTable) {
const uint32_t& delay = entry.GetKey();
ImageStartData* data = entry.GetWeak();
if (data->mEntries.IsEmpty()) {
continue;
}
if (data->mStartTime) {
TimeStamp& start = *data->mStartTime;
if (previousRefresh >= start && aNowTime >= start) {
TimeDuration prev = previousRefresh - start;
TimeDuration curr = aNowTime - start;
uint32_t prevMultiple = uint32_t(prev.ToMilliseconds()) / delay;
// We want to trigger images' refresh if we've just crossed over a
// multiple of the first image's start time. If so, set the animation
// start time to the nearest multiple of the delay and move all the
// images in this table to the main requests table.
if (prevMultiple != uint32_t(curr.ToMilliseconds()) / delay) {
mozilla::TimeStamp desired =
start + TimeDuration::FromMilliseconds(prevMultiple * delay);
BeginRefreshingImages(data->mEntries, desired);
}
} else {
// Sometimes the start time can be in the future if we spin a nested
// event loop and re-entrantly tick. In that case, setting the
// animation start time to the start time seems like the least bad
// thing we can do.
mozilla::TimeStamp desired = start;
BeginRefreshingImages(data->mEntries, desired);
}
} else {
// This is the very first time we've drawn images with this time delay.
// Set the animation start time to "now" and move all the images in this
// table to the main requests table.
mozilla::TimeStamp desired = aNowTime;
BeginRefreshingImages(data->mEntries, desired);
data->mStartTime.emplace(aNowTime);
}
}
if (!mRequests.IsEmpty()) {
// RequestRefresh may run scripts, so it's not safe to directly call it
// while using a hashtable enumerator to enumerate mRequests in case
// script modifies the hashtable. Instead, we build a (local) array of
// images to refresh, and then we refresh each image in that array.
nsTArray<nsCOMPtr<imgIContainer>> imagesToRefresh(mRequests.Count());
for (const auto& req : mRequests) {
nsCOMPtr<imgIContainer> image;
if (NS_SUCCEEDED(req->GetImage(getter_AddRefs(image)))) {
imagesToRefresh.AppendElement(image.forget());
}
}
for (const auto& image : imagesToRefresh) {
image->RequestRefresh(aNowTime);
}
}
}
UpdateAnimatedImages(previousRefresh, aNowTime);
double phasePaint = 0.0;
bool dispatchTasksAfterTick = false;
@ -2900,6 +2834,78 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime,
}
}
void nsRefreshDriver::UpdateAnimatedImages(TimeStamp aPreviousRefresh,
TimeStamp aNowTime) {
if (mThrottled) {
// Don't do this when throttled, as the compositor might be paused and we
// don't want to queue a lot of paints, see bug 1828587.
return;
}
// Perform notification to imgIRequests subscribed to listen for refresh
// events.
for (const auto& entry : mStartTable) {
const uint32_t& delay = entry.GetKey();
ImageStartData* data = entry.GetWeak();
if (data->mEntries.IsEmpty()) {
continue;
}
if (data->mStartTime) {
TimeStamp& start = *data->mStartTime;
if (aPreviousRefresh >= start && aNowTime >= start) {
TimeDuration prev = aPreviousRefresh - start;
TimeDuration curr = aNowTime - start;
uint32_t prevMultiple = uint32_t(prev.ToMilliseconds()) / delay;
// We want to trigger images' refresh if we've just crossed over a
// multiple of the first image's start time. If so, set the animation
// start time to the nearest multiple of the delay and move all the
// images in this table to the main requests table.
if (prevMultiple != uint32_t(curr.ToMilliseconds()) / delay) {
mozilla::TimeStamp desired =
start + TimeDuration::FromMilliseconds(prevMultiple * delay);
BeginRefreshingImages(data->mEntries, desired);
}
} else {
// Sometimes the start time can be in the future if we spin a nested
// event loop and re-entrantly tick. In that case, setting the
// animation start time to the start time seems like the least bad
// thing we can do.
mozilla::TimeStamp desired = start;
BeginRefreshingImages(data->mEntries, desired);
}
} else {
// This is the very first time we've drawn images with this time delay.
// Set the animation start time to "now" and move all the images in this
// table to the main requests table.
mozilla::TimeStamp desired = aNowTime;
BeginRefreshingImages(data->mEntries, desired);
data->mStartTime.emplace(aNowTime);
}
}
if (!mRequests.IsEmpty()) {
// RequestRefresh may run scripts, so it's not safe to directly call it
// while using a hashtable enumerator to enumerate mRequests in case
// script modifies the hashtable. Instead, we build a (local) array of
// images to refresh, and then we refresh each image in that array.
nsTArray<nsCOMPtr<imgIContainer>> imagesToRefresh(mRequests.Count());
for (const auto& req : mRequests) {
nsCOMPtr<imgIContainer> image;
if (NS_SUCCEEDED(req->GetImage(getter_AddRefs(image)))) {
imagesToRefresh.AppendElement(image.forget());
}
}
for (const auto& image : imagesToRefresh) {
image->RequestRefresh(aNowTime);
}
}
}
void nsRefreshDriver::BeginRefreshingImages(RequestTable& aEntries,
mozilla::TimeStamp aDesired) {
for (const auto& req : aEntries) {

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

@ -519,6 +519,10 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
// Trigger a refresh immediately, if haven't been disconnected or frozen.
void DoRefresh();
// Starts pending image animations, and refreshes ongoing animations.
void UpdateAnimatedImages(mozilla::TimeStamp aPreviousRefresh,
mozilla::TimeStamp aNowTime);
TickReasons GetReasonsToTick() const;
void AppendTickReasonsToString(TickReasons aReasons, nsACString& aStr) const;