mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1754562, make parent process' idle detection be aware of active RefreshDrivers in the other processes, r=mstange
Differential Revision: https://phabricator.services.mozilla.com/D138504
This commit is contained in:
parent
2057b98f7b
commit
1edf4c885e
@ -1172,11 +1172,7 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
|
||||
|
||||
/* static */
|
||||
bool ChromeUtils::VsyncEnabled(GlobalObject& aGlobal) {
|
||||
mozilla::gfx::VsyncSource* vsyncSource =
|
||||
gfxPlatform::GetPlatform()->GetHardwareVsync();
|
||||
MOZ_ASSERT(vsyncSource != nullptr);
|
||||
|
||||
return vsyncSource->GetGlobalDisplay().IsVsyncEnabled();
|
||||
return mozilla::gfx::VsyncSource::GetFastestVsyncRate().isSome();
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -8,6 +8,11 @@
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/VsyncDispatcher.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
#ifdef MOZ_WAYLAND
|
||||
# include "WaylandVsyncSource.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
@ -271,6 +276,33 @@ VsyncSource::Display::GetRefreshTimerVsyncDispatcher() {
|
||||
return mRefreshTimerVsyncDispatcher;
|
||||
}
|
||||
|
||||
// static
|
||||
Maybe<TimeDuration> VsyncSource::GetFastestVsyncRate() {
|
||||
Maybe<TimeDuration> retVal;
|
||||
if (!gfxPlatform::Initialized()) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
mozilla::gfx::VsyncSource* vsyncSource =
|
||||
gfxPlatform::GetPlatform()->GetHardwareVsync();
|
||||
if (vsyncSource && vsyncSource->GetGlobalDisplay().IsVsyncEnabled()) {
|
||||
retVal.emplace(vsyncSource->GetGlobalDisplay().GetVsyncRate());
|
||||
}
|
||||
|
||||
#ifdef MOZ_WAYLAND
|
||||
Maybe<TimeDuration> waylandRate = WaylandVsyncSource::GetFastestVsyncRate();
|
||||
if (waylandRate) {
|
||||
if (!retVal) {
|
||||
retVal.emplace(*waylandRate);
|
||||
} else if (*waylandRate < *retVal) {
|
||||
retVal = waylandRate;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void VsyncSource::Shutdown() { GetGlobalDisplay().Shutdown(); }
|
||||
|
||||
} // namespace gfx
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
@ -125,6 +126,9 @@ class VsyncSource {
|
||||
virtual Display& GetGlobalDisplay() = 0; // Works across all displays
|
||||
void Shutdown();
|
||||
|
||||
// Returns the rate of the fastest enabled VsyncSource::Display or Nothing().
|
||||
static Maybe<TimeDuration> GetFastestVsyncRate();
|
||||
|
||||
protected:
|
||||
virtual ~VsyncSource() = default;
|
||||
};
|
||||
|
@ -260,6 +260,7 @@ LOCAL_INCLUDES += [
|
||||
"/dom/media/platforms/apple",
|
||||
"/dom/xml",
|
||||
"/gfx/cairo/cairo/src",
|
||||
"/widget/gtk",
|
||||
]
|
||||
|
||||
if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("android", "gtk"):
|
||||
|
@ -2927,7 +2927,8 @@ void nsRefreshDriver::CancelPendingAnimationEvents(
|
||||
}
|
||||
|
||||
/* static */
|
||||
TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault) {
|
||||
TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault,
|
||||
IdleCheck aCheckType) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!aDefault.IsNull());
|
||||
|
||||
@ -2938,7 +2939,10 @@ TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault) {
|
||||
// busy but tasks resulting from a tick on sThrottledRateTimer
|
||||
// counts as being idle.
|
||||
if (sRegularRateTimer) {
|
||||
return sRegularRateTimer->GetIdleDeadlineHint(aDefault);
|
||||
TimeStamp retVal = sRegularRateTimer->GetIdleDeadlineHint(aDefault);
|
||||
if (retVal != aDefault) {
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
// The following calculation is only used on platform using per-BrowserChild
|
||||
@ -2950,6 +2954,8 @@ TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault) {
|
||||
// For now we use a somewhat simplistic approach that in many situations
|
||||
// gives us similar behaviour to what we would get using sRegularRateTimer:
|
||||
// use the highest result that is still lower than the aDefault fallback.
|
||||
// XXXsmaug None of this makes much sense. We should always return the
|
||||
// lowest result, not highest.
|
||||
TimeStamp hint = TimeStamp();
|
||||
if (sRegularRateTimerList) {
|
||||
for (RefreshDriverTimer* timer : *sRegularRateTimerList) {
|
||||
@ -2960,7 +2966,23 @@ TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault) {
|
||||
}
|
||||
}
|
||||
|
||||
return hint.IsNull() ? aDefault : hint;
|
||||
if (!hint.IsNull()) {
|
||||
return hint;
|
||||
}
|
||||
|
||||
if (aCheckType == IdleCheck::AllVsyncListeners && XRE_IsParentProcess()) {
|
||||
Maybe<TimeDuration> rate = mozilla::gfx::VsyncSource::GetFastestVsyncRate();
|
||||
if (rate.isSome()) {
|
||||
TimeStamp newHint = TimeStamp::Now() + *rate -
|
||||
TimeDuration::FromMilliseconds(
|
||||
StaticPrefs::layout_idle_period_time_limit());
|
||||
if (newHint < aDefault) {
|
||||
return newHint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -359,8 +359,19 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||
*
|
||||
* If we're animating and we have skipped paints a time in the past
|
||||
* is returned.
|
||||
*
|
||||
* If aCheckType is AllVsyncListeners and we're in the parent process,
|
||||
* which doesn't have a RefreshDriver ticking, but some other process does
|
||||
* have, the return value is
|
||||
* (now + refreshrate - layout.idle_period.time_limit) as an approximation
|
||||
* when something will happen.
|
||||
* This can be useful check when parent process tries to avoid having too
|
||||
* long idle periods for example when it is sending input events to an
|
||||
* active child process.
|
||||
*/
|
||||
static mozilla::TimeStamp GetIdleDeadlineHint(mozilla::TimeStamp aDefault);
|
||||
enum IdleCheck { OnlyThisProcessRefreshDriver, AllVsyncListeners };
|
||||
static mozilla::TimeStamp GetIdleDeadlineHint(mozilla::TimeStamp aDefault,
|
||||
IdleCheck aCheckType);
|
||||
|
||||
/**
|
||||
* It returns the expected timestamp of the next tick or nothing if the next
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifdef MOZ_WAYLAND
|
||||
|
||||
# include "WaylandVsyncSource.h"
|
||||
# include "mozilla/UniquePtr.h"
|
||||
# include "nsThreadUtils.h"
|
||||
# include "nsISupportsImpl.h"
|
||||
# include "MainThreadUtils.h"
|
||||
@ -50,6 +51,27 @@ static float GetFPS(TimeDuration aVsyncRate) {
|
||||
return 1000.0 / aVsyncRate.ToMilliseconds();
|
||||
}
|
||||
|
||||
static UniquePtr<LinkedList<WaylandVsyncSource::WaylandDisplay>>
|
||||
gWaylandDisplays;
|
||||
|
||||
Maybe<TimeDuration> WaylandVsyncSource::GetFastestVsyncRate() {
|
||||
Maybe<TimeDuration> retVal;
|
||||
if (gWaylandDisplays) {
|
||||
for (auto* display : *gWaylandDisplays) {
|
||||
if (display->IsVsyncEnabled()) {
|
||||
TimeDuration rate = display->GetVsyncRate();
|
||||
if (!retVal.isSome()) {
|
||||
retVal.emplace(rate);
|
||||
} else if (rate < *retVal) {
|
||||
retVal.ref() = rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
WaylandVsyncSource::WaylandDisplay::WaylandDisplay()
|
||||
: mMutex("WaylandVsyncSource"),
|
||||
mIsShutdown(false),
|
||||
@ -60,6 +82,19 @@ WaylandVsyncSource::WaylandDisplay::WaylandDisplay()
|
||||
mVsyncRate(TimeDuration::FromMilliseconds(1000.0 / 60.0)),
|
||||
mLastVsyncTimeStamp(TimeStamp::Now()) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!gWaylandDisplays) {
|
||||
gWaylandDisplays =
|
||||
MakeUnique<LinkedList<WaylandVsyncSource::WaylandDisplay>>();
|
||||
}
|
||||
gWaylandDisplays->insertBack(this);
|
||||
}
|
||||
|
||||
WaylandVsyncSource::WaylandDisplay::~WaylandDisplay() {
|
||||
remove(); // Remove from the linked list.
|
||||
if (gWaylandDisplays->isEmpty()) {
|
||||
gWaylandDisplays = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandVsyncSource::WaylandDisplay::MaybeUpdateSource(
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "base/thread.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/layers/NativeLayerWayland.h"
|
||||
@ -48,7 +50,10 @@ class WaylandVsyncSource final : public gfx::VsyncSource {
|
||||
|
||||
virtual Display& GetGlobalDisplay() override { return *mGlobalDisplay; }
|
||||
|
||||
class WaylandDisplay final : public mozilla::gfx::VsyncSource::Display {
|
||||
static Maybe<TimeDuration> GetFastestVsyncRate();
|
||||
|
||||
class WaylandDisplay final : public mozilla::gfx::VsyncSource::Display,
|
||||
public LinkedListElement<WaylandDisplay> {
|
||||
public:
|
||||
WaylandDisplay();
|
||||
|
||||
@ -72,7 +77,7 @@ class WaylandVsyncSource final : public gfx::VsyncSource {
|
||||
virtual void Shutdown() override;
|
||||
|
||||
private:
|
||||
virtual ~WaylandDisplay() = default;
|
||||
~WaylandDisplay() override;
|
||||
void Refresh(const MutexAutoLock& aProofOfLock);
|
||||
void SetupFrameCallback(const MutexAutoLock& aProofOfLock);
|
||||
void CalculateVsyncRate(const MutexAutoLock& aProofOfLock,
|
||||
|
@ -188,7 +188,10 @@ void IdleTaskRunner::Schedule(bool aAllowIdleDispatch) {
|
||||
if (now >= mStartTime) {
|
||||
// Detect whether the refresh driver is ticking by checking if
|
||||
// GetIdleDeadlineHint returns its input parameter.
|
||||
useRefreshDriver = (nsRefreshDriver::GetIdleDeadlineHint(now) != now);
|
||||
useRefreshDriver =
|
||||
(nsRefreshDriver::GetIdleDeadlineHint(
|
||||
now, nsRefreshDriver::IdleCheck::OnlyThisProcessRefreshDriver) !=
|
||||
now);
|
||||
} else {
|
||||
NS_WARNING_ASSERTION(!aAllowIdleDispatch,
|
||||
"early callback, or time went backwards");
|
||||
|
@ -38,7 +38,8 @@ MainThreadIdlePeriod::GetIdlePeriodHint(TimeStamp* aIdleDeadline) {
|
||||
TimeStamp currentGuess =
|
||||
now + TimeDuration::FromMilliseconds(kLongIdlePeriodMS);
|
||||
|
||||
currentGuess = nsRefreshDriver::GetIdleDeadlineHint(currentGuess);
|
||||
currentGuess = nsRefreshDriver::GetIdleDeadlineHint(
|
||||
currentGuess, nsRefreshDriver::IdleCheck::AllVsyncListeners);
|
||||
if (XRE_IsContentProcess()) {
|
||||
currentGuess = gfx::VRManagerChild::GetIdleDeadlineHint(currentGuess);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user