Bug 1468675 - Fix way of relasing RenderTextureHosts r=nical
authorsotaro <sotaro.ikeda.g@gmail.com>
Thu, 14 Jun 2018 15:18:48 -0700
changeset 479366 3358555f18d50e95704f37c053e6a6168c7bf812
parent 479365 1037fff80f05618b68fc81ce5698deaba9c172de
child 479367 7fc2698f9e19d42e59c3ce640dba0667801fd8f2
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1468675
milestone62.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 1468675 - Fix way of relasing RenderTextureHosts r=nical
gfx/webrender_bindings/RenderThread.cpp
gfx/webrender_bindings/RenderThread.h
--- a/gfx/webrender_bindings/RenderThread.cpp
+++ b/gfx/webrender_bindings/RenderThread.cpp
@@ -35,16 +35,17 @@ RenderThread::RenderThread(base::Thread*
   , mHasShutdown(false)
   , mHandlingDeviceReset(false)
 {
 
 }
 
 RenderThread::~RenderThread()
 {
+  MOZ_ASSERT(mRenderTexturesDeferred.empty());
   delete mThread;
 }
 
 // static
 RenderThread*
 RenderThread::Get()
 {
   return sRenderThread;
@@ -502,19 +503,20 @@ RenderThread::UnregisterExternalImage(ui
     // deletion task here.
     // The shmem and raw buffer are owned by compositor ipc channel. It's
     // possible that RenderTextureHost is still exist after the shmem/raw buffer
     // deletion. Then the buffer in RenderTextureHost becomes invalid. It's fine
     // for this situation. Gecko will only release the buffer if WR doesn't need
     // it. So, no one will access the invalid buffer in RenderTextureHost.
     RefPtr<RenderTextureHost> texture;
     mRenderTextures.Remove(aExternalImageId, getter_AddRefs(texture));
-    Loop()->PostTask(NewRunnableMethod<RefPtr<RenderTextureHost>>(
+    mRenderTexturesDeferred.emplace_back(std::move(texture));
+    Loop()->PostTask(NewRunnableMethod(
       "RenderThread::DeferredRenderTextureHostDestroy",
-      this, &RenderThread::DeferredRenderTextureHostDestroy, std::move(texture)
+      this, &RenderThread::DeferredRenderTextureHostDestroy
     ));
   } else {
     mRenderTextures.Remove(aExternalImageId);
   }
 }
 
 void
 RenderThread::UnregisterExternalImageDuringShutdown(uint64_t aExternalImageId)
@@ -522,19 +524,20 @@ RenderThread::UnregisterExternalImageDur
   MOZ_ASSERT(IsInRenderThread());
   MutexAutoLock lock(mRenderTextureMapLock);
   MOZ_ASSERT(mHasShutdown);
   MOZ_ASSERT(mRenderTextures.GetWeak(aExternalImageId));
   mRenderTextures.Remove(aExternalImageId);
 }
 
 void
-RenderThread::DeferredRenderTextureHostDestroy(RefPtr<RenderTextureHost>)
+RenderThread::DeferredRenderTextureHostDestroy()
 {
-  // Do nothing. Just decrease the ref-count of RenderTextureHost.
+  MutexAutoLock lock(mRenderTextureMapLock);
+  mRenderTexturesDeferred.clear();
 }
 
 RenderTextureHost*
 RenderThread::GetRenderTexture(wr::WrExternalImageId aExternalImageId)
 {
   MOZ_ASSERT(IsInRenderThread());
 
   MutexAutoLock lock(mRenderTextureMapLock);
@@ -557,18 +560,22 @@ RenderThread::HandleDeviceReset(const ch
     return;
   }
 
   gfxCriticalNote << "GFX: RenderThread detected a device reset in " << aWhere;
   if (XRE_IsGPUProcess()) {
     gfx::GPUParent::GetSingleton()->NotifyDeviceReset();
   }
 
-  for (auto iter = mRenderTextures.Iter(); !iter.Done(); iter.Next()) {
-    iter.UserData()->ClearCachedResources();
+  {
+    MutexAutoLock lock(mRenderTextureMapLock);
+    mRenderTexturesDeferred.clear();
+    for (auto iter = mRenderTextures.Iter(); !iter.Done(); iter.Next()) {
+      iter.UserData()->ClearCachedResources();
+    }
   }
 
   mHandlingDeviceReset = true;
   // All RenderCompositors will be destroyed by GPUChild::RecvNotifyDeviceReset()
 }
 
 bool
 RenderThread::IsHandlingDeviceReset()
--- a/gfx/webrender_bindings/RenderThread.h
+++ b/gfx/webrender_bindings/RenderThread.h
@@ -15,16 +15,18 @@
 #include "nsRefPtrHashtable.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/webrender/webrender_ffi.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/webrender/WebRenderTypes.h"
 #include "mozilla/layers/SynchronousTask.h"
 
+#include <list>
+
 namespace mozilla {
 namespace wr {
 
 class RendererOGL;
 class RenderTextureHost;
 class RenderThread;
 
 /// A rayon thread pool that is shared by all WebRender instances within a process.
@@ -170,17 +172,17 @@ public:
   /// Can only be called from the render thread.
   bool IsHandlingDeviceReset();
 
   size_t RendererCount();
 
 private:
   explicit RenderThread(base::Thread* aThread);
 
-  void DeferredRenderTextureHostDestroy(RefPtr<RenderTextureHost> aTexture);
+  void DeferredRenderTextureHostDestroy();
   void ShutDownTask(layers::SynchronousTask* aTask);
   void ProgramCacheTask();
 
   ~RenderThread();
 
   base::Thread* const mThread;
 
   WebRenderThreadPool mThreadPool;
@@ -194,16 +196,20 @@ private:
     int64_t mRenderingCount = 0;
   };
 
   Mutex mFrameCountMapLock;
   nsDataHashtable<nsUint64HashKey, WindowInfo> mWindowInfos;
 
   Mutex mRenderTextureMapLock;
   nsRefPtrHashtable<nsUint64HashKey, RenderTextureHost> mRenderTextures;
+  // Used to remove all RenderTextureHost that are going to be removed by
+  // a deferred callback and remove them right away without waiting for the callback.
+  // On device reset we have to remove all GL related resources right away.
+  std::list<RefPtr<RenderTextureHost>> mRenderTexturesDeferred;
   bool mHasShutdown;
 
   bool mHandlingDeviceReset;
 };
 
 } // namespace wr
 } // namespace mozilla