Bug 630127. Use a precise timer when we have animation frame callbacks. r=dbaron

This commit is contained in:
Boris Zbarsky 2011-03-07 11:58:48 -05:00
Родитель ebb2194875
Коммит a477fc5489
3 изменённых файлов: 48 добавлений и 12 удалений

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

@ -58,6 +58,15 @@ using mozilla::TimeStamp;
#define DEFAULT_FRAME_RATE 60
#define DEFAULT_THROTTLED_FRAME_RATE 1
static PRBool sPrecisePref;
/* static */ void
nsRefreshDriver::InitializeStatics()
{
nsContentUtils::AddBoolPrefVarCache("layout.frame_rate.precise",
&sPrecisePref,
PR_FALSE);
}
// Compute the interval to use for the refresh driver timer, in
// milliseconds
PRInt32
@ -85,16 +94,17 @@ nsRefreshDriver::GetRefreshTimerType() const
if (mThrottled) {
return nsITimer::TYPE_ONE_SHOT;
}
PRBool precise =
nsContentUtils::GetBoolPref("layout.frame_rate.precise", PR_FALSE);
return precise ? (PRInt32)nsITimer::TYPE_REPEATING_PRECISE
: (PRInt32)nsITimer::TYPE_REPEATING_SLACK;
if (HaveAnimationFrameListeners() || sPrecisePref) {
return nsITimer::TYPE_REPEATING_PRECISE;
}
return nsITimer::TYPE_REPEATING_SLACK;
}
nsRefreshDriver::nsRefreshDriver(nsPresContext *aPresContext)
: mPresContext(aPresContext),
mFrozen(false),
mThrottled(false)
mThrottled(false),
mTimerIsPrecise(false)
{
}
@ -157,9 +167,12 @@ nsRefreshDriver::EnsureTimerStarted()
return;
}
PRInt32 timerType = GetRefreshTimerType();
mTimerIsPrecise = (timerType == nsITimer::TYPE_REPEATING_PRECISE);
nsresult rv = mTimer->InitWithCallback(this,
GetRefreshTimerInterval(),
GetRefreshTimerType());
timerType);
if (NS_FAILED(rv)) {
mTimer = nsnull;
}
@ -338,12 +351,19 @@ nsRefreshDriver::Notify(nsITimer * /* unused */)
}
}
if (mThrottled) {
// Stop the timer now and restart it here. Stopping is ok because either
// it's already one-shot, and it just fired, and all we need to do is null
// it out, or it's repeating and we need to reset it to be one-shot. Note
// that the EnsureTimerStarted() call here is ok because EnsureTimerStarted
// makes sure to not start the timer if it shouldn't be started.
if (mThrottled ||
(mTimerIsPrecise !=
(GetRefreshTimerType() == nsITimer::TYPE_REPEATING_PRECISE))) {
// Stop the timer now and restart it here. Stopping is in the mThrottled
// case ok because either it's already one-shot, and it just fired, and all
// we need to do is null it out, or it's repeating and we need to reset it
// to be one-shot. Stopping and restarting in the case when we need to
// switch from precise to slack timers or vice versa is unfortunately
// required.
// Note that the EnsureTimerStarted() call here is ok because
// EnsureTimerStarted makes sure to not start the timer if it shouldn't be
// started.
StopTimer();
EnsureTimerStarted();
}
@ -421,6 +441,8 @@ nsRefreshDriver::ScheduleAnimationFrameListeners(nsIDocument* aDocument)
mAnimationFrameListenerDocs.NoIndex,
"Don't schedule the same document multiple times");
mAnimationFrameListenerDocs.AppendElement(aDocument);
// No need to worry about restarting our timer in precise mode if it's
// already running; that will happen automatically when it fires.
EnsureTimerStarted();
}
@ -434,4 +456,6 @@ void
nsRefreshDriver::RevokeAnimationFrameListeners(nsIDocument* aDocument)
{
mAnimationFrameListenerDocs.RemoveElement(aDocument);
// No need to worry about restarting our timer in slack mode if it's already
// running; that will happen automatically when it fires.
}

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

@ -79,6 +79,8 @@ public:
nsRefreshDriver(nsPresContext *aPresContext);
~nsRefreshDriver();
static void InitializeStatics();
// nsISupports implementation
NS_DECL_ISUPPORTS
@ -221,6 +223,10 @@ private:
PRInt32 GetRefreshTimerInterval() const;
PRInt32 GetRefreshTimerType() const;
bool HaveAnimationFrameListeners() const {
return mAnimationFrameListenerDocs.Length() != 0;
}
nsCOMPtr<nsITimer> mTimer;
mozilla::TimeStamp mMostRecentRefresh; // only valid when mTimer non-null
PRInt64 mMostRecentRefreshEpochTime; // same thing as mMostRecentRefresh,
@ -231,6 +237,10 @@ private:
bool mFrozen;
bool mThrottled;
/* If mTimer is non-null, this boolean indicates whether the timer is
a precise timer. If mTimer is null, this boolean's value can be
anything. */
bool mTimerIsPrecise;
// separate arrays for each flush type we support
ObserverArray mObservers[3];

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

@ -128,6 +128,7 @@
#include "nsJSEnvironment.h"
#include "nsContentSink.h"
#include "nsFrameMessageManager.h"
#include "nsRefreshDriver.h"
extern void NS_ShutdownChainItemPool();
@ -273,6 +274,7 @@ nsLayoutStatics::Initialize()
nsContentSink::InitializeStatics();
nsHtml5Module::InitializeStatics();
nsIPresShell::InitializeStatics();
nsRefreshDriver::InitializeStatics();
nsCrossSiteListenerProxy::Startup();