Bug 1445570 - Remove EnsureEventualAfterPaint timer. r=tnikkel

MozReview-Commit-ID: C7WICJ5Q0ES

Differential Revision: https://phabricator.services.mozilla.com/D5005

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Mantaroh Yoshinaga 2018-09-06 02:21:39 +00:00
Родитель aef6842da1
Коммит 1deccd7ac1
7 изменённых файлов: 109 добавлений и 109 удалений

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

@ -392,6 +392,7 @@ nsDOMWindowUtils::UpdateLayerTree()
RefPtr<nsViewManager> vm = presShell->GetViewManager();
nsView* view = vm->GetRootView();
if (view) {
nsAutoScriptBlocker scriptBlocker;
presShell->Paint(view, view->GetBounds(),
nsIPresShell::PAINT_LAYERS | nsIPresShell::PAINT_SYNC_DECODE_IMAGES);
presShell->GetLayerManager()->WaitOnTransactionProcessed();

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

@ -138,6 +138,7 @@ nsPresContext::IsDOMPaintEventPending()
if (!mTransactions.IsEmpty()) {
return true;
}
nsRootPresContext* drpc = GetRootPresContext();
if (drpc && drpc->mRefreshDriver->ViewManagerFlushIsPending()) {
// Since we're promising that there will be a MozAfterPaint event
@ -342,9 +343,6 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(nsPresContext, LastRelease())
void
nsPresContext::LastRelease()
{
if (IsRoot()) {
static_cast<nsRootPresContext*>(this)->CancelAllDidPaintTimers();
}
if (mMissingFonts) {
mMissingFonts->Clear();
}
@ -963,9 +961,6 @@ nsPresContext::DetachShell()
// Have to cancel our plugin geometry timer, because the
// callback for that depends on a non-null presshell.
thisRoot->CancelApplyPluginGeometryTimer();
// The did-paint timer also depends on a non-null pres shell.
thisRoot->CancelAllDidPaintTimers();
}
}
@ -2434,12 +2429,6 @@ nsPresContext::NotifyInvalidation(TransactionId aTransactionId, const nsRect& aR
transaction->mTransactionId = aTransactionId;
}
}
if (!pc) {
nsRootPresContext* rpc = GetRootPresContext();
if (rpc) {
rpc->EnsureEventualDidPaintEvent(aTransactionId);
}
}
TransactionInvalidations* transaction = GetInvalidations(aTransactionId);
MOZ_ASSERT(transaction);
@ -2508,6 +2497,18 @@ nsPresContext::NotifyDidPaintSubdocumentCallback(nsIDocument* aDocument, void* a
return true;
}
/* static */ bool
nsPresContext::NotifyRevokingDidPaintSubdocumentCallback(nsIDocument* aDocument, void* aData)
{
NotifyDidPaintSubdocumentCallbackClosure* closure =
static_cast<NotifyDidPaintSubdocumentCallbackClosure*>(aData);
nsPresContext* pc = aDocument->GetPresContext();
if (pc) {
pc->NotifyRevokingDidPaint(closure->mTransactionId);
}
return true;
}
class DelayedFireDOMPaintEvent : public Runnable {
public:
DelayedFireDOMPaintEvent(
@ -2540,16 +2541,52 @@ public:
nsTArray<nsRect> mList;
};
void
nsPresContext::NotifyRevokingDidPaint(TransactionId aTransactionId)
{
if ((IsRoot() || !PresShell()->IsVisible()) && mTransactions.IsEmpty()) {
return;
}
TransactionInvalidations* transaction = nullptr;
for (auto& t : mTransactions) {
if (t.mTransactionId == aTransactionId) {
transaction = &t;
break;
}
}
// If there are no transaction invalidations (which imply callers waiting
// on the event) for this revoked id, then we don't need to fire a
// MozAfterPaint.
if (!transaction) {
return;
}
// If there are queued transactions with an earlier id, we can't send
// our event now since it will arrive out of order. Set the waiting for
// previous transaction flag to true, and we'll send the event when
// the others are completed.
// If this is the only transaction, then we can send it immediately.
if (mTransactions.Length() == 1) {
nsCOMPtr<nsIRunnable> ev =
new DelayedFireDOMPaintEvent(this, &transaction->mInvalidations,
transaction->mTransactionId, mozilla::TimeStamp());
nsContentUtils::AddScriptRunner(ev);
mTransactions.RemoveElementAt(0);
} else {
transaction->mIsWaitingForPreviousTransaction = true;
}
NotifyDidPaintSubdocumentCallbackClosure closure = { aTransactionId, mozilla::TimeStamp() };
mDocument->EnumerateSubDocuments(nsPresContext::NotifyRevokingDidPaintSubdocumentCallback, &closure);
}
void
nsPresContext::NotifyDidPaintForSubtree(TransactionId aTransactionId,
const mozilla::TimeStamp& aTimeStamp)
{
if (IsRoot()) {
static_cast<nsRootPresContext*>(this)->CancelDidPaintTimers(aTransactionId);
if (mTransactions.IsEmpty()) {
return;
}
if (IsRoot() && mTransactions.IsEmpty()) {
return;
}
if (!PresShell()->IsVisible() && mTransactions.IsEmpty()) {
@ -2575,6 +2612,17 @@ nsPresContext::NotifyDidPaintForSubtree(TransactionId aTransactionId,
}
mTransactions.RemoveElementAt(i);
} else {
// If there are transaction which is waiting for this transaction,
// we should fire a MozAfterPaint immediately.
if (sent && mTransactions[i].mIsWaitingForPreviousTransaction) {
nsCOMPtr<nsIRunnable> ev =
new DelayedFireDOMPaintEvent(this, &mTransactions[i].mInvalidations,
mTransactions[i].mTransactionId, aTimeStamp);
nsContentUtils::AddScriptRunner(ev);
sent = true;
mTransactions.RemoveElementAt(i);
continue;
}
i++;
}
}
@ -2956,14 +3004,12 @@ nsRootPresContext::~nsRootPresContext()
{
NS_ASSERTION(mRegisteredPlugins.Count() == 0,
"All plugins should have been unregistered");
CancelAllDidPaintTimers();
CancelApplyPluginGeometryTimer();
}
/* virtual */ void
nsRootPresContext::Detach()
{
CancelAllDidPaintTimers();
// XXXmats maybe also CancelApplyPluginGeometryTimer(); ?
nsPresContext::Detach();
}
@ -3218,55 +3264,6 @@ nsRootPresContext::CollectPluginGeometryUpdates(LayerManager* aLayerManager)
#endif // #ifndef XP_MACOSX
}
void
nsRootPresContext::EnsureEventualDidPaintEvent(TransactionId aTransactionId)
{
for (NotifyDidPaintTimer& t : mNotifyDidPaintTimers) {
if (t.mTransactionId == aTransactionId) {
return;
}
}
nsCOMPtr<nsITimer> timer;
RefPtr<nsRootPresContext> self = this;
nsresult rv = NS_NewTimerWithCallback(
getter_AddRefs(timer),
NewNamedTimerCallback([self, aTransactionId](){
nsAutoScriptBlocker blockScripts;
self->NotifyDidPaintForSubtree(aTransactionId);
}, "NotifyDidPaintForSubtree"), 100, nsITimer::TYPE_ONE_SHOT,
Document()->EventTargetFor(TaskCategory::Other));
if (NS_SUCCEEDED(rv)) {
NotifyDidPaintTimer* t = mNotifyDidPaintTimers.AppendElement();
t->mTransactionId = aTransactionId;
t->mTimer = timer;
}
}
void
nsRootPresContext::CancelDidPaintTimers(TransactionId aTransactionId)
{
uint32_t i = 0;
while (i < mNotifyDidPaintTimers.Length()) {
if (mNotifyDidPaintTimers[i].mTransactionId <= aTransactionId) {
mNotifyDidPaintTimers[i].mTimer->Cancel();
mNotifyDidPaintTimers.RemoveElementAt(i);
} else {
i++;
}
}
}
void
nsRootPresContext::CancelAllDidPaintTimers()
{
for (uint32_t i = 0; i < mNotifyDidPaintTimers.Length(); i++) {
mNotifyDidPaintTimers[i].mTimer->Cancel();
}
mNotifyDidPaintTimers.Clear();
}
void
nsRootPresContext::AddWillPaintObserver(nsIRunnable* aRunnable)
{
@ -3299,7 +3296,6 @@ nsRootPresContext::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
// Measurement of the following members may be added later if DMD finds it is
// worthwhile:
// - mNotifyDidPaintTimer
// - mRegisteredPlugins
// - mWillPaintObservers
// - mWillPaintFallbackEvent

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

@ -1017,6 +1017,7 @@ public:
void NotifyInvalidation(TransactionId aTransactionId, const nsIntRect& aRect);
void NotifyDidPaintForSubtree(TransactionId aTransactionId = TransactionId{0},
const mozilla::TimeStamp& aTimeStamp = mozilla::TimeStamp());
void NotifyRevokingDidPaint(TransactionId aTransactionId);
void FireDOMPaintEvent(nsTArray<nsRect>* aList,
TransactionId aTransactionId,
mozilla::TimeStamp aTimeStamp = mozilla::TimeStamp());
@ -1215,6 +1216,8 @@ protected:
void UpdateCharSet(NotNull<const Encoding*> aCharSet);
static bool NotifyDidPaintSubdocumentCallback(nsIDocument* aDocument, void* aData);
static bool NotifyRevokingDidPaintSubdocumentCallback(nsIDocument* aDocument, void* aData);
public:
// Used by the PresShell to force a reflow when some aspect of font info
@ -1254,6 +1257,7 @@ protected:
struct TransactionInvalidations {
TransactionId mTransactionId;
nsTArray<nsRect> mInvalidations;
bool mIsWaitingForPreviousTransaction = false;
};
TransactionInvalidations* GetInvalidations(TransactionId aTransactionId);
@ -1500,23 +1504,6 @@ public:
virtual ~nsRootPresContext();
virtual void Detach() override;
/**
* Ensure that NotifyDidPaintForSubtree is eventually called on this
* object after a timeout.
*/
void EnsureEventualDidPaintEvent(TransactionId aTransactionId);
/**
* Cancels any pending eventual did paint timer for transaction
* ids up to and including aTransactionId.
*/
void CancelDidPaintTimers(TransactionId aTransactionId);
/**
* Cancel all pending eventual did paint timers.
*/
void CancelAllDidPaintTimers();
/**
* Registers a plugin to receive geometry updates (position and clip
* region) so it can update its widget.
@ -1608,12 +1595,6 @@ protected:
friend class nsPresContext;
struct NotifyDidPaintTimer {
TransactionId mTransactionId;
nsCOMPtr<nsITimer> mTimer;
};
AutoTArray<NotifyDidPaintTimer, 4> mNotifyDidPaintTimers;
nsCOMPtr<nsITimer> mApplyPluginGeometryTimer;
nsTHashtable<nsRefPtrHashKey<nsIContent> > mRegisteredPlugins;
nsTArray<nsCOMPtr<nsIRunnable> > mWillPaintObservers;

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

@ -1110,7 +1110,8 @@ nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext)
: mActiveTimer(nullptr),
mPresContext(aPresContext),
mRootRefresh(nullptr),
mPendingTransaction{0},
mNextTransactionId{0},
mOutstandingTransactionId{0},
mCompletedTransaction{0},
mFreezeCount(0),
mThrottledFrameRequestInterval(TimeDuration::FromMilliseconds(
@ -1187,7 +1188,7 @@ nsRefreshDriver::RestoreNormalRefresh()
{
mTestControllingRefreshes = false;
EnsureTimerStarted(eAllowTimeToGoBackwards);
mCompletedTransaction = mPendingTransaction;
mCompletedTransaction = mOutstandingTransactionId = mNextTransactionId;
}
TimeStamp
@ -2155,10 +2156,11 @@ nsRefreshDriver::FinishedWaitingForTransaction()
mozilla::layers::TransactionId
nsRefreshDriver::GetTransactionId(bool aThrottle)
{
mPendingTransaction = mPendingTransaction.Next();
mOutstandingTransactionId = mOutstandingTransactionId.Next();
mNextTransactionId = mNextTransactionId.Next();
if (aThrottle &&
mPendingTransaction - mCompletedTransaction >= 2 &&
mOutstandingTransactionId - mCompletedTransaction >= 2 &&
!mWaitingForTransaction &&
!mTestControllingRefreshes) {
mWaitingForTransaction = true;
@ -2166,38 +2168,48 @@ nsRefreshDriver::GetTransactionId(bool aThrottle)
mWarningThreshold = 1;
}
return mPendingTransaction;
return mNextTransactionId;
}
mozilla::layers::TransactionId
nsRefreshDriver::LastTransactionId() const
{
return mPendingTransaction;
return mNextTransactionId;
}
void
nsRefreshDriver::RevokeTransactionId(mozilla::layers::TransactionId aTransactionId)
{
MOZ_ASSERT(aTransactionId == mPendingTransaction);
if (mPendingTransaction - mCompletedTransaction == 2 &&
MOZ_ASSERT(aTransactionId == mNextTransactionId);
if (mOutstandingTransactionId - mCompletedTransaction == 2 &&
mWaitingForTransaction) {
MOZ_ASSERT(!mSkippedPaints, "How did we skip a paint when we're in the middle of one?");
FinishedWaitingForTransaction();
}
mPendingTransaction = mPendingTransaction.Prev();
// Notify the pres context so that it can deliver MozAfterPaint for this
// id if any caller was expecting it.
nsPresContext* pc = GetPresContext();
if (pc) {
pc->NotifyRevokingDidPaint(aTransactionId);
}
// Revert the outstanding transaction since we're no longer waiting on it to be
// completed, but don't revert mNextTransactionId since we can't use the id
// again.
mOutstandingTransactionId = mOutstandingTransactionId.Prev();
}
void
nsRefreshDriver::ClearPendingTransactions()
{
mCompletedTransaction = mPendingTransaction;
mCompletedTransaction = mOutstandingTransactionId = mNextTransactionId;
mWaitingForTransaction = false;
}
void
nsRefreshDriver::ResetInitialTransactionId(mozilla::layers::TransactionId aTransactionId)
{
mCompletedTransaction = mPendingTransaction = aTransactionId;
mCompletedTransaction = mOutstandingTransactionId = mNextTransactionId = aTransactionId;
}
mozilla::TimeStamp
@ -2210,7 +2222,7 @@ void
nsRefreshDriver::NotifyTransactionCompleted(mozilla::layers::TransactionId aTransactionId)
{
if (aTransactionId > mCompletedTransaction) {
if (mPendingTransaction - mCompletedTransaction > 1 &&
if (mOutstandingTransactionId - mCompletedTransaction > 1 &&
mWaitingForTransaction) {
mCompletedTransaction = aTransactionId;
FinishedWaitingForTransaction();
@ -2218,6 +2230,11 @@ nsRefreshDriver::NotifyTransactionCompleted(mozilla::layers::TransactionId aTran
mCompletedTransaction = aTransactionId;
}
}
// If completed transaction id get ahead of outstanding id, reset to distance id.
if (mCompletedTransaction > mOutstandingTransactionId) {
mOutstandingTransactionId = mCompletedTransaction;
}
}
void

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

@ -465,7 +465,12 @@ private:
RefPtr<nsRefreshDriver> mRootRefresh;
// The most recently allocated transaction id.
TransactionId mPendingTransaction;
TransactionId mNextTransactionId;
// This number is mCompletedTransaction + (pending transaction count).
// When we revoke a transaction id, we revert this number (since it's
// no longer outstanding), but not mNextTransactionId (since we don't
// want to reuse the number).
TransactionId mOutstandingTransactionId;
// The most recently completed transaction id.
TransactionId mCompletedTransaction;

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

@ -321,7 +321,7 @@ pref(gfx.font_rendering.graphite.enabled,true) == glyph-decomposition-graphite.h
== hyphenation-control-2.html hyphenation-control-2-ref.html
== hyphenation-control-3.html hyphenation-control-3-ref.html
== hyphenation-control-4.html hyphenation-control-4-ref.html
fuzzy-if(winWidget,0-47,0-6) == hyphenation-control-5.html hyphenation-control-5-ref.html
fuzzy-if(winWidget,0-56,0-6) == hyphenation-control-5.html hyphenation-control-5-ref.html
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == hyphenation-control-6.html hyphenation-control-6-ref.html # Bug 1392106
== hyphenation-control-7.html hyphenation-control-7-ref.html

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

@ -77,7 +77,7 @@ add_task(async function smil_is_in_display_none_subtree() {
animate.setAttribute("repeatCount", "indefinite");
document.getElementById("svg-rect").appendChild(animate);
await waitForPaintFlushed();
await waitForAnimationFrames(2);
var displayMarkers = await observeStyling(5);
// FIXME: Bug 866411: SMIL animations sometimes skip restyles when the target
@ -97,7 +97,7 @@ add_task(async function smil_is_in_display_none_subtree() {
div.style.display = "";
getComputedStyle(div).display;
await waitForPaintFlushed();
await waitForAnimationFrames(2);
var displayAgainMarkers = await observeStyling(5);
// FIXME: Bug 866411: SMIL animations sometimes skip restyles when the target