Bug 1419307 - Make WebRenderAPI::~WebRenderAPI() fast r=nical
authorsotaro <sotaro.ikeda.g@gmail.com>
Fri, 24 Nov 2017 18:34:50 +0900
changeset 438045 928b22b815e5df909537649ff168f9b1b920afb9
parent 438044 c6f9187b0b2e9c42f5eeca898bf81640174573fe
child 438087 f9b391e62608afe47cb5d9269a4afee6472bb1d4
push id117
push userfmarier@mozilla.com
push dateTue, 28 Nov 2017 20:17:16 +0000
reviewersnical
bugs1419307
milestone59.0a1
Bug 1419307 - Make WebRenderAPI::~WebRenderAPI() fast r=nical
gfx/webrender_bindings/RenderThread.cpp
gfx/webrender_bindings/RenderThread.h
gfx/webrender_bindings/WebRenderAPI.cpp
--- a/gfx/webrender_bindings/RenderThread.cpp
+++ b/gfx/webrender_bindings/RenderThread.cpp
@@ -113,32 +113,32 @@ RenderThread::AddRenderer(wr::WindowId a
 
   if (mHasShutdown) {
     return;
   }
 
   mRenderers[aWindowId] = Move(aRenderer);
 
   MutexAutoLock lock(mFrameCountMapLock);
-  mPendingFrameCounts.Put(AsUint64(aWindowId), FrameCount());
+  mWindowInfos.Put(AsUint64(aWindowId), WindowInfo());
 }
 
 void
 RenderThread::RemoveRenderer(wr::WindowId aWindowId)
 {
   MOZ_ASSERT(IsInRenderThread());
 
   if (mHasShutdown) {
     return;
   }
 
   mRenderers.erase(aWindowId);
 
   MutexAutoLock lock(mFrameCountMapLock);
-  mPendingFrameCounts.Remove(AsUint64(aWindowId));
+  mWindowInfos.Remove(AsUint64(aWindowId));
 }
 
 RendererOGL*
 RenderThread::GetRenderer(wr::WindowId aWindowId)
 {
   MOZ_ASSERT(IsInRenderThread());
 
   auto it = mRenderers.find(aWindowId);
@@ -162,16 +162,20 @@ RenderThread::NewFrameReady(wr::WindowId
     Loop()->PostTask(
       NewRunnableMethod<wr::WindowId>("wr::RenderThread::NewFrameReady",
                                       this,
                                       &RenderThread::NewFrameReady,
                                       aWindowId));
     return;
   }
 
+  if (IsDestroyed(aWindowId)) {
+    return;
+  }
+
   UpdateAndRender(aWindowId);
   DecPendingFrameCount(aWindowId);
 }
 
 void
 RenderThread::RunEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aEvent)
 {
   if (!IsInRenderThread()) {
@@ -269,78 +273,103 @@ bool
 RenderThread::TooManyPendingFrames(wr::WindowId aWindowId)
 {
   const int64_t maxFrameCount = 1;
 
   // Too many pending frames if pending frames exit more than maxFrameCount
   // or if RenderBackend is still processing a frame.
 
   MutexAutoLock lock(mFrameCountMapLock);
-  FrameCount count;
-  if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
+  WindowInfo info;
+  if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
     MOZ_ASSERT(false);
     return true;
   }
 
-  if (count.mPendingCount > maxFrameCount) {
+  if (info.mPendingCount > maxFrameCount) {
+    return true;
+  }
+  MOZ_ASSERT(info.mPendingCount >= info.mRenderingCount);
+  return info.mPendingCount > info.mRenderingCount;
+}
+
+bool
+RenderThread::IsDestroyed(wr::WindowId aWindowId)
+{
+  MutexAutoLock lock(mFrameCountMapLock);
+  WindowInfo info;
+  if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
     return true;
   }
-  MOZ_ASSERT(count.mPendingCount >= count.mRenderingCount);
-  return count.mPendingCount > count.mRenderingCount;
+
+  return info.mIsDestroyed;
+}
+
+void
+RenderThread::SetDestroyed(wr::WindowId aWindowId)
+{
+  MutexAutoLock lock(mFrameCountMapLock);
+  WindowInfo info;
+  if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
+    MOZ_ASSERT(false);
+    return;
+  }
+  info.mIsDestroyed = true;
+  mWindowInfos.Put(AsUint64(aWindowId), info);
 }
 
 void
 RenderThread::IncPendingFrameCount(wr::WindowId aWindowId)
 {
   MutexAutoLock lock(mFrameCountMapLock);
   // Get the old count.
-  FrameCount count;
-  if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
+  WindowInfo info;
+  if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
     MOZ_ASSERT(false);
     return;
   }
   // Update pending frame count.
-  count.mPendingCount = count.mPendingCount + 1;
-  mPendingFrameCounts.Put(AsUint64(aWindowId), count);
+  info.mPendingCount = info.mPendingCount + 1;
+  mWindowInfos.Put(AsUint64(aWindowId), info);
 }
 
 void
 RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId)
 {
   MutexAutoLock lock(mFrameCountMapLock);
   // Get the old count.
-  FrameCount count;
-  if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
+  WindowInfo info;
+  if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
     MOZ_ASSERT(false);
     return;
   }
   // Update rendering frame count.
-  count.mRenderingCount = count.mRenderingCount + 1;
-  mPendingFrameCounts.Put(AsUint64(aWindowId), count);
+  info.mRenderingCount = info.mRenderingCount + 1;
+  mWindowInfos.Put(AsUint64(aWindowId), info);
 }
 
 void
 RenderThread::DecPendingFrameCount(wr::WindowId aWindowId)
 {
   MutexAutoLock lock(mFrameCountMapLock);
   // Get the old count.
-  FrameCount count;
-  if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
+  WindowInfo info;
+  if (!mWindowInfos.Get(AsUint64(aWindowId), &info)) {
     MOZ_ASSERT(false);
     return;
   }
-  MOZ_ASSERT(count.mPendingCount > 0);
-  MOZ_ASSERT(count.mRenderingCount > 0);
-  if (count.mPendingCount <= 0) {
+  MOZ_ASSERT(info.mPendingCount > 0);
+  MOZ_ASSERT(info.mRenderingCount > 0);
+  if (info.mPendingCount <= 0) {
     return;
   }
   // Update frame counts.
-  count.mPendingCount = count.mPendingCount - 1;
-  count.mRenderingCount = count.mRenderingCount - 1;
-  mPendingFrameCounts.Put(AsUint64(aWindowId), count);
+  info.mPendingCount = info.mPendingCount - 1;
+  info.mRenderingCount = info.mRenderingCount - 1;
+  mWindowInfos.Put(AsUint64(aWindowId), info);
 }
 
 void
 RenderThread::RegisterExternalImage(uint64_t aExternalImageId, already_AddRefed<RenderTextureHost> aTexture)
 {
   MutexAutoLock lock(mRenderTextureMapLock);
 
   if (mHasShutdown) {
--- a/gfx/webrender_bindings/RenderThread.h
+++ b/gfx/webrender_bindings/RenderThread.h
@@ -123,16 +123,20 @@ public:
 
   /// Can be called from any thread.
   void UnregisterExternalImage(uint64_t aExternalImageId);
 
   /// Can only be called from the render thread.
   RenderTextureHost* GetRenderTexture(WrExternalImageId aExternalImageId);
 
   /// Can be called from any thread.
+  bool IsDestroyed(wr::WindowId aWindowId);
+  /// Can be called from any thread.
+  void SetDestroyed(wr::WindowId aWindowId);
+  /// Can be called from any thread.
   bool TooManyPendingFrames(wr::WindowId aWindowId);
   /// Can be called from any thread.
   void IncPendingFrameCount(wr::WindowId aWindowId);
   /// Can be called from any thread.
   void IncRenderingFrameCount(wr::WindowId aWindowId);
   /// Can be called from any thread.
   void DecPendingFrameCount(wr::WindowId aWindowId);
 
@@ -148,23 +152,24 @@ private:
   ~RenderThread();
 
   base::Thread* const mThread;
 
   WebRenderThreadPool mThreadPool;
 
   std::map<wr::WindowId, UniquePtr<RendererOGL>> mRenderers;
 
-  struct FrameCount {
+  struct WindowInfo {
+    bool mIsDestroyed = false;
     int64_t mPendingCount = 0;
     int64_t mRenderingCount = 0;
   };
 
   Mutex mFrameCountMapLock;
-  nsDataHashtable<nsUint64HashKey, FrameCount> mPendingFrameCounts;
+  nsDataHashtable<nsUint64HashKey, WindowInfo> mWindowInfos;
 
   Mutex mRenderTextureMapLock;
   nsRefPtrHashtable<nsUint64HashKey, RenderTextureHost> mRenderTextures;
   bool mHasShutdown;
 };
 
 } // namespace wr
 } // namespace mozilla
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -199,16 +199,19 @@ WebRenderAPI::Clone()
 wr::WrIdNamespace
 WebRenderAPI::GetNamespace() {
   return wr_api_get_namespace(mDocHandle);
 }
 
 WebRenderAPI::~WebRenderAPI()
 {
   if (!mRootApi) {
+
+    RenderThread::Get()->SetDestroyed(GetId());
+
     layers::SynchronousTask task("Destroy WebRenderAPI");
     auto event = MakeUnique<RemoveRenderer>(&task);
     RunOnRenderThread(Move(event));
     task.Wait();
   }
 
   wr_api_delete(mDocHandle);
 }