Bug 1382948 - Fix WebRenderBridgeParent::FlushTransactionIdsForEpoch() r=nical
authorsotaro <sotaro.ikeda.g@gmail.com>
Mon, 24 Jul 2017 21:20:22 +0900
changeset 419292 7c3361a87e461937246b93743a87e1869bf080af
parent 419291 4377bafde262dfe03a76c94d365df0cf535f45fc
child 419293 1547c1b9a0d216b9c7f2a0ff69d1ba1541da6233
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1382948
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1382948 - Fix WebRenderBridgeParent::FlushTransactionIdsForEpoch() r=nical
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -415,20 +415,20 @@ WebRenderBridgeParent::HandleDPEnd(const
       DestroyActor(op);
     }
     return;
   }
   // This ensures that destroy operations are always processed. It is not safe
   // to early-return from RecvDPEnd without doing so.
   AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
 
-  ++mWrEpoch; // Update webrender epoch
-  ProcessWebRenderCommands(aSize, aCommands, wr::NewEpoch(mWrEpoch),
+  uint32_t wrEpoch = GetNextWrEpoch();
+  ProcessWebRenderCommands(aSize, aCommands, wr::NewEpoch(wrEpoch),
                            aContentSize, dl, dlDesc, aIdNameSpace);
-  HoldPendingTransactionId(mWrEpoch, aTransactionId);
+  HoldPendingTransactionId(wrEpoch, aTransactionId);
 
   mScrollData = aScrollData;
   UpdateAPZ();
 
   if (mIdNameSpace != aIdNameSpace) {
     // Pretend we composited since someone is wating for this event,
     // though DisplayList was not pushed to webrender.
     TimeStamp now = TimeStamp::Now();
@@ -841,18 +841,17 @@ mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvClearCachedResources()
 {
   if (mDestroyed) {
     return IPC_OK();
   }
   mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), false);
 
   // Clear resources
-  ++mWrEpoch; // Update webrender epoch
-  mApi->ClearRootDisplayList(wr::NewEpoch(mWrEpoch), mPipelineId);
+  mApi->ClearRootDisplayList(wr::NewEpoch(GetNextWrEpoch()), mPipelineId);
   // Schedule composition to clean up Pipeline
   mCompositorScheduler->ScheduleComposition();
   DeleteOldImages();
   // Remove animations.
   for (std::unordered_set<uint64_t>::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) {
     mAnimStorage->ClearById(*iter);
   }
   mActiveAnimations.clear();
@@ -891,17 +890,17 @@ WebRenderBridgeParent::UpdateWebRender(C
   // XXX Stop to clear resources if webreder supports resources sharing between different webrender instances.
   ClearResources();
   mCompositorBridge = cBridge;
   mCompositorScheduler = aScheduler;
   mApi = aApi;
   mCompositableHolder = aHolder;
   mAnimStorage = aAnimStorage;
 
-  ++mWrEpoch; // Update webrender epoch
+  Unused << GetNextWrEpoch(); // Update webrender epoch
   // Register pipeline to updated CompositableHolder.
   mCompositableHolder->AddPipeline(mPipelineId);
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvForceComposite()
 {
   if (mDestroyed) {
@@ -1175,22 +1174,26 @@ WebRenderBridgeParent::FlushPendingTrans
   return id;
 }
 
 uint64_t
 WebRenderBridgeParent::FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch)
 {
   uint64_t id = 0;
   while (!mPendingTransactionIds.empty()) {
-    id = mPendingTransactionIds.front().mId;
-    if (mPendingTransactionIds.front().mEpoch == aEpoch) {
-      mPendingTransactionIds.pop();
+    int64_t diff =
+      static_cast<int64_t>(aEpoch.mHandle) - static_cast<int64_t>(mPendingTransactionIds.front().mEpoch.mHandle);
+    if (diff < 0) {
       break;
     }
+    id = mPendingTransactionIds.front().mId;
     mPendingTransactionIds.pop();
+    if (diff == 0) {
+      break;
+    }
   }
   return id;
 }
 
 uint64_t
 WebRenderBridgeParent::GetLayersId() const
 {
   return wr::AsUint64(mPipelineId);
@@ -1265,18 +1268,18 @@ WebRenderBridgeParent::Resume()
 
 void
 WebRenderBridgeParent::ClearResources()
 {
   if (!mApi) {
     return;
   }
 
-  ++mWrEpoch; // Update webrender epoch
-  mApi->ClearRootDisplayList(wr::NewEpoch(mWrEpoch), mPipelineId);
+  uint32_t wrEpoch = GetNextWrEpoch();
+  mApi->ClearRootDisplayList(wr::NewEpoch(wrEpoch), mPipelineId);
   // Schedule composition to clean up Pipeline
   mCompositorScheduler->ScheduleComposition();
   // XXX webrender does not hava a way to delete a group of resources/keys,
   // then delete keys one by one.
   for (std::unordered_set<uint64_t>::iterator iter = mFontKeys.begin(); iter != mFontKeys.end(); iter++) {
     mApi->DeleteFont(wr::AsFontKey(*iter));
   }
   mFontKeys.clear();
@@ -1293,17 +1296,17 @@ WebRenderBridgeParent::ClearResources()
     wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
     RefPtr<WebRenderImageHost> host = iter.Data();
     MOZ_ASSERT(host->GetAsyncRef());
     host->ClearWrBridge();
     mCompositableHolder->RemoveAsyncImagePipeline(mApi, pipelineId);
   }
   mAsyncCompositables.Clear();
 
-  mCompositableHolder->RemovePipeline(mPipelineId, wr::NewEpoch(mWrEpoch));
+  mCompositableHolder->RemovePipeline(mPipelineId, wr::NewEpoch(wrEpoch));
 
   for (std::unordered_set<uint64_t>::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) {
     mAnimStorage->ClearById(*iter);
   }
   mActiveAnimations.clear();
 
   if (mWidget) {
     mCompositorScheduler->Destroy();
@@ -1413,10 +1416,17 @@ WebRenderBridgeParent::GetTextureFactory
   MOZ_ASSERT(mApi);
 
   return TextureFactoryIdentifier(LayersBackend::LAYERS_WR,
                                   XRE_GetProcessType(),
                                   mApi->GetMaxTextureSize(),
                                   mApi->GetUseANGLE());
 }
 
+uint32_t
+WebRenderBridgeParent::GetNextWrEpoch()
+{
+  MOZ_RELEASE_ASSERT(mWrEpoch != UINT32_MAX);
+  return ++mWrEpoch;
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -247,16 +247,18 @@ private:
   // If scrollbars need their transforms updated, the provided aTransformArray
   // is populated with the property update details.
   bool PushAPZStateToWR(nsTArray<wr::WrTransformProperty>& aTransformArray);
 
   // Helper method to get an APZC reference from a scroll id. Uses the layers
   // id of this bridge, and may return null if the APZC wasn't found.
   already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const FrameMetrics::ViewID& aId);
 
+  uint32_t GetNextWrEpoch();
+
 private:
   struct PendingTransactionId {
     PendingTransactionId(wr::Epoch aEpoch, uint64_t aId)
       : mEpoch(aEpoch)
       , mId(aId)
     {}
     wr::Epoch mEpoch;
     uint64_t mId;