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 */
|
/* static */
|
||||||
bool ChromeUtils::VsyncEnabled(GlobalObject& aGlobal) {
|
bool ChromeUtils::VsyncEnabled(GlobalObject& aGlobal) {
|
||||||
mozilla::gfx::VsyncSource* vsyncSource =
|
return mozilla::gfx::VsyncSource::GetFastestVsyncRate().isSome();
|
||||||
gfxPlatform::GetPlatform()->GetHardwareVsync();
|
|
||||||
MOZ_ASSERT(vsyncSource != nullptr);
|
|
||||||
|
|
||||||
return vsyncSource->GetGlobalDisplay().IsVsyncEnabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
|
@ -8,6 +8,11 @@
|
|||||||
#include "nsXULAppAPI.h"
|
#include "nsXULAppAPI.h"
|
||||||
#include "mozilla/VsyncDispatcher.h"
|
#include "mozilla/VsyncDispatcher.h"
|
||||||
#include "MainThreadUtils.h"
|
#include "MainThreadUtils.h"
|
||||||
|
#include "gfxPlatform.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_WAYLAND
|
||||||
|
# include "WaylandVsyncSource.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
@ -271,6 +276,33 @@ VsyncSource::Display::GetRefreshTimerVsyncDispatcher() {
|
|||||||
return mRefreshTimerVsyncDispatcher;
|
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(); }
|
void VsyncSource::Shutdown() { GetGlobalDisplay().Shutdown(); }
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
@ -125,6 +126,9 @@ class VsyncSource {
|
|||||||
virtual Display& GetGlobalDisplay() = 0; // Works across all displays
|
virtual Display& GetGlobalDisplay() = 0; // Works across all displays
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
|
// Returns the rate of the fastest enabled VsyncSource::Display or Nothing().
|
||||||
|
static Maybe<TimeDuration> GetFastestVsyncRate();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~VsyncSource() = default;
|
virtual ~VsyncSource() = default;
|
||||||
};
|
};
|
||||||
|
@ -260,6 +260,7 @@ LOCAL_INCLUDES += [
|
|||||||
"/dom/media/platforms/apple",
|
"/dom/media/platforms/apple",
|
||||||
"/dom/xml",
|
"/dom/xml",
|
||||||
"/gfx/cairo/cairo/src",
|
"/gfx/cairo/cairo/src",
|
||||||
|
"/widget/gtk",
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("android", "gtk"):
|
if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("android", "gtk"):
|
||||||
|
@ -2927,7 +2927,8 @@ void nsRefreshDriver::CancelPendingAnimationEvents(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault) {
|
TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault,
|
||||||
|
IdleCheck aCheckType) {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!aDefault.IsNull());
|
MOZ_ASSERT(!aDefault.IsNull());
|
||||||
|
|
||||||
@ -2938,7 +2939,10 @@ TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault) {
|
|||||||
// busy but tasks resulting from a tick on sThrottledRateTimer
|
// busy but tasks resulting from a tick on sThrottledRateTimer
|
||||||
// counts as being idle.
|
// counts as being idle.
|
||||||
if (sRegularRateTimer) {
|
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
|
// 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
|
// For now we use a somewhat simplistic approach that in many situations
|
||||||
// gives us similar behaviour to what we would get using sRegularRateTimer:
|
// gives us similar behaviour to what we would get using sRegularRateTimer:
|
||||||
// use the highest result that is still lower than the aDefault fallback.
|
// 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();
|
TimeStamp hint = TimeStamp();
|
||||||
if (sRegularRateTimerList) {
|
if (sRegularRateTimerList) {
|
||||||
for (RefreshDriverTimer* timer : *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 */
|
/* 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
|
* If we're animating and we have skipped paints a time in the past
|
||||||
* is returned.
|
* 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
|
* It returns the expected timestamp of the next tick or nothing if the next
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#ifdef MOZ_WAYLAND
|
#ifdef MOZ_WAYLAND
|
||||||
|
|
||||||
# include "WaylandVsyncSource.h"
|
# include "WaylandVsyncSource.h"
|
||||||
|
# include "mozilla/UniquePtr.h"
|
||||||
# include "nsThreadUtils.h"
|
# include "nsThreadUtils.h"
|
||||||
# include "nsISupportsImpl.h"
|
# include "nsISupportsImpl.h"
|
||||||
# include "MainThreadUtils.h"
|
# include "MainThreadUtils.h"
|
||||||
@ -50,6 +51,27 @@ static float GetFPS(TimeDuration aVsyncRate) {
|
|||||||
return 1000.0 / aVsyncRate.ToMilliseconds();
|
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()
|
WaylandVsyncSource::WaylandDisplay::WaylandDisplay()
|
||||||
: mMutex("WaylandVsyncSource"),
|
: mMutex("WaylandVsyncSource"),
|
||||||
mIsShutdown(false),
|
mIsShutdown(false),
|
||||||
@ -60,6 +82,19 @@ WaylandVsyncSource::WaylandDisplay::WaylandDisplay()
|
|||||||
mVsyncRate(TimeDuration::FromMilliseconds(1000.0 / 60.0)),
|
mVsyncRate(TimeDuration::FromMilliseconds(1000.0 / 60.0)),
|
||||||
mLastVsyncTimeStamp(TimeStamp::Now()) {
|
mLastVsyncTimeStamp(TimeStamp::Now()) {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
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(
|
void WaylandVsyncSource::WaylandDisplay::MaybeUpdateSource(
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "base/thread.h"
|
#include "base/thread.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/LinkedList.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "mozilla/Monitor.h"
|
#include "mozilla/Monitor.h"
|
||||||
#include "mozilla/layers/NativeLayerWayland.h"
|
#include "mozilla/layers/NativeLayerWayland.h"
|
||||||
@ -48,7 +50,10 @@ class WaylandVsyncSource final : public gfx::VsyncSource {
|
|||||||
|
|
||||||
virtual Display& GetGlobalDisplay() override { return *mGlobalDisplay; }
|
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:
|
public:
|
||||||
WaylandDisplay();
|
WaylandDisplay();
|
||||||
|
|
||||||
@ -72,7 +77,7 @@ class WaylandVsyncSource final : public gfx::VsyncSource {
|
|||||||
virtual void Shutdown() override;
|
virtual void Shutdown() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~WaylandDisplay() = default;
|
~WaylandDisplay() override;
|
||||||
void Refresh(const MutexAutoLock& aProofOfLock);
|
void Refresh(const MutexAutoLock& aProofOfLock);
|
||||||
void SetupFrameCallback(const MutexAutoLock& aProofOfLock);
|
void SetupFrameCallback(const MutexAutoLock& aProofOfLock);
|
||||||
void CalculateVsyncRate(const MutexAutoLock& aProofOfLock,
|
void CalculateVsyncRate(const MutexAutoLock& aProofOfLock,
|
||||||
|
@ -188,7 +188,10 @@ void IdleTaskRunner::Schedule(bool aAllowIdleDispatch) {
|
|||||||
if (now >= mStartTime) {
|
if (now >= mStartTime) {
|
||||||
// Detect whether the refresh driver is ticking by checking if
|
// Detect whether the refresh driver is ticking by checking if
|
||||||
// GetIdleDeadlineHint returns its input parameter.
|
// GetIdleDeadlineHint returns its input parameter.
|
||||||
useRefreshDriver = (nsRefreshDriver::GetIdleDeadlineHint(now) != now);
|
useRefreshDriver =
|
||||||
|
(nsRefreshDriver::GetIdleDeadlineHint(
|
||||||
|
now, nsRefreshDriver::IdleCheck::OnlyThisProcessRefreshDriver) !=
|
||||||
|
now);
|
||||||
} else {
|
} else {
|
||||||
NS_WARNING_ASSERTION(!aAllowIdleDispatch,
|
NS_WARNING_ASSERTION(!aAllowIdleDispatch,
|
||||||
"early callback, or time went backwards");
|
"early callback, or time went backwards");
|
||||||
|
@ -38,7 +38,8 @@ MainThreadIdlePeriod::GetIdlePeriodHint(TimeStamp* aIdleDeadline) {
|
|||||||
TimeStamp currentGuess =
|
TimeStamp currentGuess =
|
||||||
now + TimeDuration::FromMilliseconds(kLongIdlePeriodMS);
|
now + TimeDuration::FromMilliseconds(kLongIdlePeriodMS);
|
||||||
|
|
||||||
currentGuess = nsRefreshDriver::GetIdleDeadlineHint(currentGuess);
|
currentGuess = nsRefreshDriver::GetIdleDeadlineHint(
|
||||||
|
currentGuess, nsRefreshDriver::IdleCheck::AllVsyncListeners);
|
||||||
if (XRE_IsContentProcess()) {
|
if (XRE_IsContentProcess()) {
|
||||||
currentGuess = gfx::VRManagerChild::GetIdleDeadlineHint(currentGuess);
|
currentGuess = gfx::VRManagerChild::GetIdleDeadlineHint(currentGuess);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user