Bug 1210261. Tick root refresh driver last. r=mattwoodrow

This commit is contained in:
Mason Chang 2015-11-16 08:12:38 -08:00
parent 5219bd1cea
commit 675f9bf1f2

View File

@ -104,17 +104,24 @@ public:
virtual ~RefreshDriverTimer()
{
NS_ASSERTION(mRefreshDrivers.Length() == 0, "Should have removed all refresh drivers from here by now!");
MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!");
MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!");
}
virtual void AddRefreshDriver(nsRefreshDriver* aDriver)
{
LOG("[%p] AddRefreshDriver %p", this, aDriver);
NS_ASSERTION(!mRefreshDrivers.Contains(aDriver), "AddRefreshDriver for a refresh driver that's already in the list!");
mRefreshDrivers.AppendElement(aDriver);
bool startTimer = mContentRefreshDrivers.IsEmpty() && mRootRefreshDrivers.IsEmpty();
if (IsRootRefreshDriver(aDriver)) {
NS_ASSERTION(!mRootRefreshDrivers.Contains(aDriver), "Adding a duplicate root refresh driver!");
mRootRefreshDrivers.AppendElement(aDriver);
} else {
NS_ASSERTION(!mContentRefreshDrivers.Contains(aDriver), "Adding a duplicate content refresh driver!");
mContentRefreshDrivers.AppendElement(aDriver);
}
if (mRefreshDrivers.Length() == 1) {
if (startTimer) {
StartTimer();
}
}
@ -123,10 +130,30 @@ public:
{
LOG("[%p] RemoveRefreshDriver %p", this, aDriver);
NS_ASSERTION(mRefreshDrivers.Contains(aDriver), "RemoveRefreshDriver for a refresh driver that's not in the list!");
mRefreshDrivers.RemoveElement(aDriver);
if (IsRootRefreshDriver(aDriver)) {
NS_ASSERTION(mRootRefreshDrivers.Contains(aDriver), "RemoveRefreshDriver for a refresh driver that's not in the root refresh list!");
mRootRefreshDrivers.RemoveElement(aDriver);
} else {
nsPresContext* displayRoot = aDriver->PresContext()->GetDisplayRootPresContext();
// During PresContext shutdown, we can't accurately detect
// if a root refresh driver exists or not. Therefore, we have to
// search and find out which list this driver exists in.
if (!displayRoot) {
if (mRootRefreshDrivers.Contains(aDriver)) {
mRootRefreshDrivers.RemoveElement(aDriver);
} else {
NS_ASSERTION(mContentRefreshDrivers.Contains(aDriver),
"RemoveRefreshDriver without a display root for a driver that is not in the content refresh list");
mContentRefreshDrivers.RemoveElement(aDriver);
}
} else {
NS_ASSERTION(mContentRefreshDrivers.Contains(aDriver), "RemoveRefreshDriver for a driver that is not in the content refresh list");
mContentRefreshDrivers.RemoveElement(aDriver);
}
}
if (mRefreshDrivers.Length() == 0) {
bool stopTimer = mContentRefreshDrivers.IsEmpty() && mRootRefreshDrivers.IsEmpty();
if (stopTimer) {
StopTimer();
}
}
@ -138,11 +165,17 @@ public:
{
MOZ_ASSERT(NS_IsMainThread());
for (nsRefreshDriver* driver : mRefreshDrivers) {
for (nsRefreshDriver* driver : mContentRefreshDrivers) {
aNewTimer->AddRefreshDriver(driver);
driver->mActiveTimer = aNewTimer;
}
mRefreshDrivers.Clear();
mContentRefreshDrivers.Clear();
for (nsRefreshDriver* driver : mRootRefreshDrivers) {
aNewTimer->AddRefreshDriver(driver);
driver->mActiveTimer = aNewTimer;
}
mRootRefreshDrivers.Clear();
aNewTimer->mLastFireEpoch = mLastFireEpoch;
aNewTimer->mLastFireTime = mLastFireTime;
@ -153,6 +186,17 @@ protected:
virtual void StopTimer() = 0;
virtual void ScheduleNextTick(TimeStamp aNowTime) = 0;
bool IsRootRefreshDriver(nsRefreshDriver* aDriver)
{
nsPresContext* displayRoot = aDriver->PresContext()->GetDisplayRootPresContext();
if (!displayRoot) {
return false;
}
nsRefreshDriver* rootRefreshDriver = displayRoot->GetRootPresContext()->RefreshDriver();
return aDriver == rootRefreshDriver;
}
/*
* Actually runs a tick, poking all the attached RefreshDrivers.
* Grabs the "now" time via JS_Now and TimeStamp::Now().
@ -164,6 +208,23 @@ protected:
Tick(jsnow, now);
}
void TickRefreshDrivers(int64_t aJsNow, TimeStamp aNow, nsTArray<RefPtr<nsRefreshDriver>>& aDrivers)
{
if (aDrivers.IsEmpty()) {
return;
}
nsTArray<RefPtr<nsRefreshDriver> > drivers(aDrivers);
for (nsRefreshDriver* driver : drivers) {
// don't poke this driver if it's in test mode
if (driver->IsTestControllingRefreshesEnabled()) {
continue;
}
TickDriver(driver, aJsNow, aNow);
}
}
/*
* Tick the refresh drivers based on the given timestamp.
*/
@ -175,17 +236,12 @@ protected:
mLastFireTime = now;
LOG("[%p] ticking drivers...", this);
nsTArray<RefPtr<nsRefreshDriver> > drivers(mRefreshDrivers);
// RD is short for RefreshDriver
profiler_tracing("Paint", "RD", TRACING_INTERVAL_START);
for (nsRefreshDriver* driver : drivers) {
// don't poke this driver if it's in test mode
if (driver->IsTestControllingRefreshesEnabled()) {
continue;
}
TickDriver(driver, jsnow, now);
}
TickRefreshDrivers(jsnow, now, mContentRefreshDrivers);
TickRefreshDrivers(jsnow, now, mRootRefreshDrivers);
profiler_tracing("Paint", "RD", TRACING_INTERVAL_END);
LOG("[%p] done.", this);
}
@ -200,7 +256,8 @@ protected:
TimeStamp mLastFireTime;
TimeStamp mTargetTime;
nsTArray<RefPtr<nsRefreshDriver> > mRefreshDrivers;
nsTArray<RefPtr<nsRefreshDriver> > mContentRefreshDrivers;
nsTArray<RefPtr<nsRefreshDriver> > mRootRefreshDrivers;
// useful callback for nsITimer-based derived classes, here
// bacause of c++ protected shenanigans
@ -558,13 +615,18 @@ public:
// we don't really have to start with the newly added one, but we may as well
// not tick the old ones at the fastest rate any more than we need to.
mNextDriverIndex = mRefreshDrivers.Length() - 1;
mNextDriverIndex = GetRefreshDriverCount() - 1;
StopTimer();
StartTimer();
}
protected:
uint32_t GetRefreshDriverCount()
{
return mContentRefreshDrivers.Length() + mRootRefreshDrivers.Length();
}
virtual void StartTimer()
{
mLastFireEpoch = JS_Now();
@ -593,7 +655,7 @@ protected:
}
// double the next tick time if we've already gone through all of them once
if (mNextDriverIndex >= mRefreshDrivers.Length()) {
if (mNextDriverIndex >= GetRefreshDriverCount()) {
mNextTickDuration *= 2.0;
mNextDriverIndex = 0;
}
@ -603,7 +665,7 @@ protected:
mTimer->InitWithFuncCallback(TimerTickOne, this, delay, nsITimer::TYPE_ONE_SHOT);
LOG("[%p] inactive timer next tick in %f ms [index %d/%d]", this, mNextTickDuration,
mNextDriverIndex, mRefreshDrivers.Length());
mNextDriverIndex, GetRefreshDriverCount());
}
/* Runs just one driver's tick. */
@ -617,7 +679,9 @@ protected:
mLastFireEpoch = jsnow;
mLastFireTime = now;
nsTArray<RefPtr<nsRefreshDriver> > drivers(mRefreshDrivers);
nsTArray<RefPtr<nsRefreshDriver> > drivers(mContentRefreshDrivers);
drivers.AppendElements(mRootRefreshDrivers);
if (mNextDriverIndex < drivers.Length() &&
!drivers[mNextDriverIndex]->IsTestControllingRefreshesEnabled())
{