Bug 1419226 - Part 2. Remove MozAfterPaint timer and firing MozAfterPaint when revoke transaction. r?mattwoodrow
Current gecko will send MozAfterPaint event instead of finishing paint process
due to software timer. This patch will remove this timer and ensure that
firing MozAfterPaint when the paint ended up making no changes.
MozReview-Commit-ID: E0ZNyeWHnrl
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -440,19 +440,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPresContext)
NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(nsPresContext, LastRelease())
void
nsPresContext::LastRelease()
{
- if (IsRoot()) {
- static_cast<nsRootPresContext*>(this)->CancelAllDidPaintTimers();
- }
if (mMissingFonts) {
mMissingFonts->Clear();
}
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext)
@@ -1109,19 +1106,16 @@ nsPresContext::DetachShell()
}
if (IsRoot()) {
nsRootPresContext* thisRoot = static_cast<nsRootPresContext*>(this);
// 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();
}
}
void
nsPresContext::DoChangeCharSet(NotNull<const Encoding*> aCharSet)
{
UpdateCharSet(aCharSet);
mDeviceContext->FlushFontCache();
@@ -2613,34 +2607,22 @@ nsPresContext::NotifyInvalidation(uint64
NotifyInvalidation(aTransactionId, rect);
}
void
nsPresContext::NotifyInvalidation(uint64_t aTransactionId, const nsRect& aRect)
{
MOZ_ASSERT(GetContainerWeak(), "Invalidation in detached pres context");
- // If there is no paint event listener, then we don't need to fire
- // the asynchronous event. We don't even need to record invalidation.
- // MayHavePaintEventListener is pretty cheap and we could make it
- // even cheaper by providing a more efficient
- // nsPIDOMWindow::GetListenerManager.
-
nsPresContext* pc;
for (pc = this; pc; pc = pc->GetParentPresContext()) {
if (pc->mFireAfterPaintEvents)
break;
pc->mFireAfterPaintEvents = true;
}
- if (!pc) {
- nsRootPresContext* rpc = GetRootPresContext();
- if (rpc) {
- rpc->EnsureEventualDidPaintEvent(aTransactionId);
- }
- }
TransactionInvalidations* transaction = nullptr;
for (TransactionInvalidations& t : mTransactions) {
if (t.mTransactionId == aTransactionId) {
transaction = &t;
break;
}
}
@@ -2752,22 +2734,18 @@ public:
const mozilla::TimeStamp mTimeStamp;
nsTArray<nsRect> mList;
};
void
nsPresContext::NotifyDidPaintForSubtree(uint64_t aTransactionId,
const mozilla::TimeStamp& aTimeStamp)
{
- if (IsRoot()) {
- static_cast<nsRootPresContext*>(this)->CancelDidPaintTimers(aTransactionId);
-
- if (!mFireAfterPaintEvents) {
- return;
- }
+ if (IsRoot() && !mFireAfterPaintEvents) {
+ return;
}
if (!PresShell()->IsVisible() && !mFireAfterPaintEvents) {
return;
}
// Non-root prescontexts fire MozAfterPaint to all their descendants
// unconditionally, even if no invalidations have been collected. This is
@@ -3186,24 +3164,22 @@ nsRootPresContext::nsRootPresContext(nsI
: nsPresContext(aDocument, aType)
{
}
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();
}
void
nsRootPresContext::RegisterPluginForGeometryUpdates(nsIContent* aPlugin)
{
mRegisteredPlugins.PutEntry(aPlugin);
@@ -3449,65 +3425,16 @@ nsRootPresContext::CollectPluginGeometry
if (clm) {
clm->StorePluginWidgetConfigurations(configurations);
}
PluginDidSetGeometry(mRegisteredPlugins);
#endif // #ifndef XP_MACOSX
}
void
-nsRootPresContext::EnsureEventualDidPaintEvent(uint64_t 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(uint64_t 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)
{
if (!mWillPaintFallbackEvent.IsPending()) {
mWillPaintFallbackEvent = new RunWillPaintObservers(this);
Document()->Dispatch(TaskCategory::Other,
do_AddRef(mWillPaintFallbackEvent));
}
mWillPaintObservers.AppendElement(aRunnable);
@@ -3529,13 +3456,12 @@ nsRootPresContext::FlushWillPaintObserve
size_t
nsRootPresContext::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
return nsPresContext::SizeOfExcludingThis(aMallocSizeOf);
// Measurement of the following members may be added later if DMD finds it is
// worthwhile:
- // - mNotifyDidPaintTimer
// - mRegisteredPlugins
// - mWillPaintObservers
// - mWillPaintFallbackEvent
}
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -1536,33 +1536,16 @@ public:
class nsRootPresContext final : public nsPresContext {
public:
nsRootPresContext(nsIDocument* aDocument, nsPresContextType aType);
virtual ~nsRootPresContext();
virtual void Detach() override;
/**
- * Ensure that NotifyDidPaintForSubtree is eventually called on this
- * object after a timeout.
- */
- void EnsureEventualDidPaintEvent(uint64_t aTransactionId);
-
- /**
- * Cancels any pending eventual did paint timer for transaction
- * ids up to and including aTransactionId.
- */
- void CancelDidPaintTimers(uint64_t 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.
* Callers must call UnregisterPluginForGeometryUpdates before
* the aPlugin frame is destroyed.
*/
void RegisterPluginForGeometryUpdates(nsIContent* aPlugin);
/**
* Stops a plugin receiving geometry updates (position and clip
@@ -1643,22 +1626,16 @@ protected:
return NS_OK;
}
// The lifetime of this reference is handled by an nsRevocableEventPtr
nsRootPresContext* MOZ_NON_OWNING_REF mPresContext;
};
friend class nsPresContext;
- struct NotifyDidPaintTimer {
- uint64_t mTransactionId;
- nsCOMPtr<nsITimer> mTimer;
- };
- AutoTArray<NotifyDidPaintTimer, 4> mNotifyDidPaintTimers;
-
nsCOMPtr<nsITimer> mApplyPluginGeometryTimer;
nsTHashtable<nsRefPtrHashKey<nsIContent> > mRegisteredPlugins;
nsTArray<nsCOMPtr<nsIRunnable> > mWillPaintObservers;
nsRevocableEventPtr<RunWillPaintObservers> mWillPaintFallbackEvent;
};
#ifdef MOZ_REFLOW_PERF