Bug 854421 - Part 8: Try find a 'root' refresh driver to see if it's blocked. r=vlad

This commit is contained in:
Matt Woodrow 2014-05-29 09:43:41 +12:00
parent 7f11d1f162
commit 2946d172f5
4 changed files with 73 additions and 8 deletions

View File

@ -58,7 +58,7 @@ parent:
// We don't need to send a sync transaction if
// no transaction operate require a swap.
async UpdateNoSwap(Edit[] cset, uin64_t id, TargetConfig targetConfig, bool isFirstPaint,
async UpdateNoSwap(Edit[] cset, uint64_t id, TargetConfig targetConfig, bool isFirstPaint,
bool scheduleComposite, uint32_t paintSequenceNumber);
// Testing APIs

View File

@ -4039,10 +4039,14 @@ PresShell::FlushPendingNotifications(mozilla::ChangesToFlush aFlush)
if (aFlush.mFlushAnimations &&
!mPresContext->StyleUpdateForAllAnimationsIsUpToDate()) {
mPresContext->AnimationManager()->
FlushAnimations(CommonAnimationManager::Cannot_Throttle);
mPresContext->TransitionManager()->
FlushTransitions(CommonAnimationManager::Cannot_Throttle);
if (mPresContext->AnimationManager()) {
mPresContext->AnimationManager()->
FlushAnimations(CommonAnimationManager::Cannot_Throttle);
}
if (mPresContext->TransitionManager()) {
mPresContext->TransitionManager()->
FlushTransitions(CommonAnimationManager::Cannot_Throttle);
}
mPresContext->TickLastStyleUpdateForAllAnimations();
}

View File

@ -686,6 +686,7 @@ nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext)
mReflowCause(nullptr),
mStyleCause(nullptr),
mPresContext(aPresContext),
mRootRefresh(nullptr),
mPendingTransaction(0),
mCompletedTransaction(0),
mFreezeCount(0),
@ -707,6 +708,10 @@ nsRefreshDriver::~nsRefreshDriver()
"observers should have unregistered");
NS_ABORT_IF_FALSE(!mActiveTimer, "timer should be gone");
if (mRootRefresh) {
mRootRefresh->RemoveRefreshObserver(this, Flush_Style);
mRootRefresh = nullptr;
}
for (uint32_t i = 0; i < mPresShellsToInvalidateIfHidden.Length(); i++) {
mPresShellsToInvalidateIfHidden[i]->InvalidatePresShellIfHidden();
}
@ -1065,13 +1070,17 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
mMostRecentRefresh = aNowTime;
mMostRecentRefreshEpochTime = aNowEpoch;
if (mWaitingForTransaction) {
if (IsWaitingForPaint()) {
// We're currently suspended waiting for earlier Tick's to
// be completed (on the Compositor). Mark that we missed the paint
// and keep waiting.
mSkippedPaint = true;
return;
}
if (mRootRefresh) {
mRootRefresh->RemoveRefreshObserver(this, Flush_Style);
mRootRefresh = nullptr;
}
mSkippedPaint = false;
nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
if (!presShell || (ObserverCount() == 0 && ImageRequestCount() == 0)) {
@ -1424,6 +1433,49 @@ nsRefreshDriver::NotifyTransactionCompleted(uint64_t aTransactionId)
}
}
void
nsRefreshDriver::WillRefresh(mozilla::TimeStamp aTime)
{
mRootRefresh->RemoveRefreshObserver(this, Flush_Style);
mRootRefresh = nullptr;
if (mSkippedPaint) {
DoRefresh();
}
}
bool
nsRefreshDriver::IsWaitingForPaint()
{
if (mTestControllingRefreshes) {
return false;
}
if (mWaitingForTransaction) {
mSkippedPaint = true;
return true;
}
// Try find the 'root' refresh driver for the current window and check
// if that is waiting for a paint.
nsPresContext *displayRoot = PresContext()->GetDisplayRootPresContext();
if (displayRoot) {
nsRefreshDriver *rootRefresh = displayRoot->GetRootPresContext()->RefreshDriver();
if (rootRefresh && rootRefresh != this) {
if (rootRefresh->IsWaitingForPaint()) {
if (mRootRefresh != rootRefresh) {
if (mRootRefresh) {
mRootRefresh->RemoveRefreshObserver(this, Flush_Style);
}
rootRefresh->AddRefreshObserver(this, Flush_Style);
mRootRefresh = rootRefresh;
}
mSkippedPaint = true;
return true;
}
}
}
return false;
}
void
nsRefreshDriver::SetThrottled(bool aThrottled)
{

View File

@ -63,7 +63,8 @@ public:
virtual void DidRefresh() = 0;
};
class nsRefreshDriver MOZ_FINAL : public mozilla::layers::TransactionIdAllocator {
class nsRefreshDriver MOZ_FINAL : public mozilla::layers::TransactionIdAllocator,
public nsARefreshObserver {
public:
nsRefreshDriver(nsPresContext *aPresContext);
~nsRefreshDriver();
@ -275,6 +276,12 @@ public:
void NotifyTransactionCompleted(uint64_t aTransactionId) MOZ_OVERRIDE;
void RevokeTransactionId(uint64_t aTransactionId) MOZ_OVERRIDE;
bool IsWaitingForPaint();
// nsARefreshObserver
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) { return TransactionIdAllocator::AddRef(); }
NS_IMETHOD_(MozExternalRefCountType) Release(void) { return TransactionIdAllocator::Release(); }
virtual void WillRefresh(mozilla::TimeStamp aTime);
private:
typedef nsTObserverArray<nsARefreshObserver*> ObserverArray;
typedef nsTHashtable<nsISupportsHashKey> RequestTable;
@ -328,6 +335,8 @@ private:
nsPresContext *mPresContext; // weak; pres context passed in constructor
// and unset in Disconnect
nsRefPtr<nsRefreshDriver> mRootRefresh;
// The most recently allocated transaction id.
uint64_t mPendingTransaction;
// The most recently completed transaction id.