Bug 1404091 - In layers-free mode, we should do NotifyInvalidation after EndTransaction if there is any scheduled flush. r=kats
MozReview-Commit-ID: D0LNF0LgWYq
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -37,17 +37,16 @@ WebRenderLayerManager::WebRenderLayerMan
: mWidget(aWidget)
, mLatestTransactionId(0)
, mLastAsr(nullptr)
, mNeedsComposite(false)
, mIsFirstPaint(false)
, mEndTransactionWithoutLayers(false)
, mTarget(nullptr)
, mPaintSequenceNumber(0)
- , mShouldNotifyInvalidation(false)
{
MOZ_COUNT_CTOR(WebRenderLayerManager);
}
KnowsCompositor*
WebRenderLayerManager::AsKnowsCompositor()
{
return mWrChild;
@@ -331,24 +330,16 @@ WebRenderLayerManager::CreateWebRenderCo
// If we're going to create a new layer data for this item, stash the
// ASR so that if we recurse into a sublist they will know where to stop
// walking up their ASR chain when building scroll metadata.
if (forceNewLayerData) {
mAsrStack.push_back(asr);
}
}
- // If there is any invalid item, we should notify nsPresContext after EndTransaction.
- if (!mShouldNotifyInvalidation) {
- nsRect invalid;
- if (item->IsInvalid(invalid)) {
- mShouldNotifyInvalidation = true;
- }
- }
-
{ // scope the ScrollingLayersHelper
ScrollingLayersHelper clip(item, aBuilder, aSc, mClipIdCache, AsyncPanZoomEnabled());
// Note: this call to CreateWebRenderCommands can recurse back into
// this function if the |item| is a wrapper for a sublist.
if (!item->CreateWebRenderCommands(aBuilder, aResources, aSc, this,
aDisplayListBuilder)) {
PushItemAsImage(item, aBuilder, aResources, aSc, aDisplayListBuilder);
@@ -513,25 +504,18 @@ PaintItemByDrawTarget(nsDisplayItem* aIt
if (layer) {
UniquePtr<LayerProperties> props;
props = Move(LayerProperties::CloneFrom(aManager->GetRoot()));
aManager->SetRoot(layer);
layerBuilder->WillEndTransaction();
- nsIntRegion invalid;
- props->ComputeDifferences(layer, invalid, nullptr);
-
static_cast<nsDisplayFilter*>(aItem)->PaintAsLayer(aDisplayListBuilder,
context, aManager);
-
- if (!invalid.IsEmpty()) {
- aWrManager->SetNotifyInvalidation(true);
- }
}
if (aManager->InTransaction()) {
aManager->AbortTransaction();
}
aManager->SetTarget(nullptr);
break;
}
@@ -768,19 +752,16 @@ WebRenderLayerManager::EndTransactionInt
}
DiscardCompositorAnimations();
wr::LayoutSize contentSize { (float)size.width, (float)size.height };
wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
wr::IpcResourceUpdateQueue resourceUpdates(WrBridge()->GetShmemAllocator());
if (mEndTransactionWithoutLayers) {
- // Reset the notification flag at the begin of the EndTransaction.
- mShouldNotifyInvalidation = false;
-
// aDisplayList being null here means this is an empty transaction following a layers-free
// transaction, so we reuse the previously built displaylist and scroll
// metadata information
if (aDisplayList && aDisplayListBuilder) {
StackingContextHelper sc;
mParentCommands.Clear();
mScrollData = WebRenderScrollData();
MOZ_ASSERT(mLayerScrollData.empty());
@@ -819,19 +800,16 @@ WebRenderLayerManager::EndTransactionInt
// Remove the user data those are not displayed on the screen and
// also reset the data to unused for next transaction.
RemoveUnusedAndResetWebRenderUserData();
} else {
for (auto iter = mLastCanvasDatas.Iter(); !iter.Done(); iter.Next()) {
RefPtr<WebRenderCanvasData> canvasData = iter.Get()->GetKey();
WebRenderCanvasRendererAsync* canvas = canvasData->GetCanvasRenderer();
- if (canvas->IsDirty()) {
- mShouldNotifyInvalidation = true;
- }
canvas->UpdateCompositableClient();
}
}
builder.PushBuiltDisplayList(mBuiltDisplayList);
WrBridge()->AddWebRenderParentCommands(mParentCommands);
} else {
mScrollData = WebRenderScrollData();
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -241,19 +241,16 @@ public:
if (T::Type() == WebRenderUserData::UserDataType::eCanvas) {
mLastCanvasDatas.PutEntry(data->AsCanvasData());
}
RefPtr<T> res = static_cast<T*>(data.get());
return res.forget();
}
- bool ShouldNotifyInvalidation() const { return mShouldNotifyInvalidation; }
- void SetNotifyInvalidation(bool aShouldNotifyInvalidation) { mShouldNotifyInvalidation = aShouldNotifyInvalidation; }
-
bool SetPendingScrollUpdateForNextTransaction(FrameMetrics::ViewID aScrollId,
const ScrollUpdateInfo& aUpdateInfo) override;
private:
/**
* Take a snapshot of the parent context, and copy
* it into mTarget.
*/
@@ -383,19 +380,15 @@ private:
uint32_t mPaintSequenceNumber;
// See equivalent field in ClientLayerManager
APZTestData mApzTestData;
typedef nsTHashtable<nsRefPtrHashKey<WebRenderCanvasData>> CanvasDataSet;
// Store of WebRenderCanvasData objects for use in empty transactions
CanvasDataSet mLastCanvasDatas;
- // True if the layers-free transaction has invalidation region and then
- // we should send notification after EndTransaction
- bool mShouldNotifyInvalidation;
-
WebRenderUserDataRefTable mWebRenderUserDatas;
};
} // namespace layers
} // namespace mozilla
#endif /* GFX_WEBRENDERLAYERMANAGER_H */
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1196,16 +1196,17 @@ nsRefreshDriver::nsRefreshDriver(nsPresC
mFreezeCount(0),
mThrottledFrameRequestInterval(TimeDuration::FromMilliseconds(
GetThrottledTimerInterval())),
mMinRecomputeVisibilityInterval(GetMinRecomputeVisibilityInterval()),
mThrottled(false),
mNeedToRecomputeVisibility(false),
mTestControllingRefreshes(false),
mViewManagerFlushIsPending(false),
+ mHasScheduleFlush(false),
mInRefresh(false),
mWaitingForTransaction(false),
mSkippedPaints(false),
mResizeSuppressed(false),
mWarningThreshold(REFRESH_WAIT_WARNING)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mPresContext,
@@ -2090,16 +2091,17 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
for (nsDocShell* docShell : profilingDocShells) {
MOZ_ASSERT(timelines);
MOZ_ASSERT(timelines->HasConsumer(docShell));
timelines->AddMarkerForDocShell(docShell, "Paint", MarkerTracingType::END);
}
dispatchRunnablesAfterTick = true;
+ mHasScheduleFlush = false;
}
#ifndef ANDROID /* bug 1142079 */
mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::REFRESH_DRIVER_TICK, mTickStart);
#endif
nsTObserverArray<nsAPostRefreshObserver*>::ForwardIterator iter(mPostRefreshObservers);
while (iter.HasMore()) {
@@ -2363,16 +2365,17 @@ nsRefreshDriver::IsRefreshObserver(nsARe
#endif
void
nsRefreshDriver::ScheduleViewManagerFlush()
{
NS_ASSERTION(mPresContext->IsRoot(),
"Should only schedule view manager flush on root prescontexts");
mViewManagerFlushIsPending = true;
+ mHasScheduleFlush = true;
EnsureTimerStarted(eNeverAdjustTimer);
}
void
nsRefreshDriver::ScheduleFrameRequestCallbacks(nsIDocument* aDocument)
{
NS_ASSERTION(mFrameRequestCallbackDocs.IndexOf(aDocument) ==
mFrameRequestCallbackDocs.NoIndex &&
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -212,16 +212,19 @@ public:
*/
void ScheduleViewManagerFlush();
void RevokeViewManagerFlush() {
mViewManagerFlushIsPending = false;
}
bool ViewManagerFlushIsPending() {
return mViewManagerFlushIsPending;
}
+ bool HasScheduleFlush() {
+ return mHasScheduleFlush;
+ }
/**
* Add a document for which we have FrameRequestCallbacks
*/
void ScheduleFrameRequestCallbacks(nsIDocument* aDocument);
/**
* Remove a document for which we have FrameRequestCallbacks
@@ -437,16 +440,21 @@ private:
// interval, we only recompute visibility when we've seen a layout or style
// flush since the last time we did it.
const mozilla::TimeDuration mMinRecomputeVisibilityInterval;
bool mThrottled;
bool mNeedToRecomputeVisibility;
bool mTestControllingRefreshes;
bool mViewManagerFlushIsPending;
+
+ // True if the view manager needs a flush. Layers-free mode uses this value
+ // to know when to notify invalidation.
+ bool mHasScheduleFlush;
+
bool mInRefresh;
// True if the refresh driver is suspended waiting for transaction
// id's to be returned and shouldn't do any work during Tick().
bool mWaitingForTransaction;
// True if Tick() was skipped because of mWaitingForTransaction and
// we should schedule a new Tick immediately when resumed instead
// of waiting until the next interval.
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -2182,17 +2182,17 @@ already_AddRefed<LayerManager> nsDisplay
frame->ClearInvalidationStateBits();
}
aBuilder->SetIsCompositingCheap(temp);
if (document && widgetTransaction) {
TriggerPendingAnimations(document, layerManager->GetAnimationReadyTime());
}
- if (wrManager->ShouldNotifyInvalidation()) {
+ if (presContext->RefreshDriver()->HasScheduleFlush()) {
presContext->NotifyInvalidation(layerManager->GetLastTransactionId(), nsIntRect());
}
return layerManager.forget();
}
NotifySubDocInvalidationFunc computeInvalidFunc =
presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;