Bug 1300676 - Part 1: Allow asynchronous deletion of Shmem for VideoDecoderManagerChild. r=dvander
authorMatt Woodrow <mwoodrow@mozilla.com>
Fri, 04 Nov 2016 13:28:28 +1300
changeset 347674 5771d02d895e876ed321d5707ec984114c93e128
parent 347673 f6aba4ec09af240e3688ba634b43a5d593ec8d9d
child 347675 65e8b3590892e203b8a5e1ab97afae95824bd7f3
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1300676
milestone52.0a1
Bug 1300676 - Part 1: Allow asynchronous deletion of Shmem for VideoDecoderManagerChild. r=dvander
dom/media/ipc/VideoDecoderManagerChild.cpp
dom/media/ipc/VideoDecoderManagerChild.h
gfx/layers/ipc/CompositorBridgeChild.cpp
gfx/layers/ipc/CompositorBridgeChild.h
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/TextureForwarder.h
gfx/layers/ipc/VideoBridgeChild.cpp
gfx/layers/ipc/VideoBridgeChild.h
gfx/vr/ipc/VRManagerChild.cpp
gfx/vr/ipc/VRManagerChild.h
--- a/dom/media/ipc/VideoDecoderManagerChild.cpp
+++ b/dom/media/ipc/VideoDecoderManagerChild.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "VideoDecoderManagerChild.h"
 #include "VideoDecoderChild.h"
 #include "mozilla/dom/ContentChild.h"
 #include "MediaPrefs.h"
 #include "nsThreadUtils.h"
 #include "mozilla/ipc/ProtocolUtils.h"
+#include "mozilla/layers/ISurfaceAllocator.h"
 
 namespace mozilla {
 namespace dom {
 
 using namespace ipc;
 using namespace layers;
 using namespace gfx;
 
@@ -148,16 +149,33 @@ VideoDecoderManagerChild::ActorDestroy(A
 }
 
 void
 VideoDecoderManagerChild::DeallocPVideoDecoderManagerChild()
 {
   Release();
 }
 
+bool
+VideoDecoderManagerChild::DeallocShmem(mozilla::ipc::Shmem& aShmem)
+{
+  if (NS_GetCurrentThread() != sVideoDecoderChildThread) {
+    RefPtr<VideoDecoderManagerChild> self = this;
+    mozilla::ipc::Shmem shmem = aShmem;
+    sVideoDecoderChildThread->Dispatch(NS_NewRunnableFunction([self, shmem]() {
+      if (self->mCanSend) {
+        mozilla::ipc::Shmem shmemCopy = shmem;
+        self->DeallocShmem(shmemCopy);
+      }
+    }), NS_DISPATCH_NORMAL);
+    return true;
+  }
+  return PVideoDecoderManagerChild::DeallocShmem(aShmem);
+}
+
 void
 VideoDecoderManagerChild::DeallocateSurfaceDescriptorGPUVideo(const SurfaceDescriptorGPUVideo& aSD)
 {
   RefPtr<VideoDecoderManagerChild> ref = this;
   SurfaceDescriptorGPUVideo sd = Move(aSD);
   sVideoDecoderChildThread->Dispatch(NS_NewRunnableFunction([ref, sd]() {
     if (ref->mCanSend) {
       ref->SendDeallocateSurfaceDescriptorGPUVideo(sd);
--- a/dom/media/ipc/VideoDecoderManagerChild.h
+++ b/dom/media/ipc/VideoDecoderManagerChild.h
@@ -8,31 +8,49 @@
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/PVideoDecoderManagerChild.h"
 
 namespace mozilla {
 namespace dom {
 
 class VideoDecoderManagerChild final : public PVideoDecoderManagerChild
+                                     , public mozilla::ipc::IShmemAllocator
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderManagerChild)
 
   // Can only be called from the manager thread
   static VideoDecoderManagerChild* GetSingleton();
 
   // Can be called from any thread.
   static nsIThread* GetManagerThread();
   static AbstractThread* GetManagerAbstractThread();
 
   // Can be called from any thread, dispatches the request to the IPDL thread internally
   // and will be ignored if the IPDL actor has been destroyed.
   void DeallocateSurfaceDescriptorGPUVideo(const SurfaceDescriptorGPUVideo& aSD);
 
+  bool AllocShmem(size_t aSize,
+                  mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
+                  mozilla::ipc::Shmem* aShmem) override
+  {
+    return PVideoDecoderManagerChild::AllocShmem(aSize, aShmType, aShmem);
+  }
+  bool AllocUnsafeShmem(size_t aSize,
+                        mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
+                        mozilla::ipc::Shmem* aShmem) override
+  {
+    return PVideoDecoderManagerChild::AllocUnsafeShmem(aSize, aShmType, aShmem);
+  }
+
+  // Can be called from any thread, dispatches the request to the IPDL thread internally
+  // and will be ignored if the IPDL actor has been destroyed.
+  bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
+
   // Main thread only
   static void Initialize();
   static void Shutdown();
 
 protected:
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeallocPVideoDecoderManagerChild() override;
 
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -1026,23 +1026,23 @@ bool
 CompositorBridgeChild::AllocShmem(size_t aSize,
                              ipc::SharedMemory::SharedMemoryType aType,
                              ipc::Shmem* aShmem)
 {
   ShmemAllocated(this);
   return PCompositorBridgeChild::AllocShmem(aSize, aType, aShmem);
 }
 
-void
+bool
 CompositorBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
 {
   if (!mCanSend) {
-    return;
+    return false;
   }
-  PCompositorBridgeChild::DeallocShmem(aShmem);
+  return PCompositorBridgeChild::DeallocShmem(aShmem);
 }
 
 widget::PCompositorWidgetChild*
 CompositorBridgeChild::AllocPCompositorWidgetChild(const CompositorWidgetInitData& aInitData)
 {
   // We send the constructor manually.
   MOZ_CRASH("Should not be called");
   return nullptr;
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -205,17 +205,17 @@ public:
   virtual base::ProcessId GetParentPid() const override { return OtherPid(); }
 
   virtual bool AllocUnsafeShmem(size_t aSize,
                                 mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
                                 mozilla::ipc::Shmem* aShmem) override;
   virtual bool AllocShmem(size_t aSize,
                           mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
                           mozilla::ipc::Shmem* aShmem) override;
-  virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
+  virtual bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
 
   PCompositorWidgetChild* AllocPCompositorWidgetChild(const CompositorWidgetInitData& aInitData) override;
   bool DeallocPCompositorWidgetChild(PCompositorWidgetChild* aActor) override;
 
   RefPtr<IAPZCTreeManager> GetAPZCTreeManager(uint64_t aLayerTreeId);
 
   PAPZCTreeManagerChild* AllocPAPZCTreeManagerChild(const uint64_t& aLayersId) override;
   bool DeallocPAPZCTreeManagerChild(PAPZCTreeManagerChild* aActor) override;
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -1068,47 +1068,50 @@ ImageBridgeChild::DispatchAllocShmemInte
 
   task.Wait();
 
   return params.mSuccess;
 }
 
 void
 ImageBridgeChild::ProxyDeallocShmemNow(SynchronousTask* aTask,
-                                       ipc::Shmem* aShmem)
+                                       ipc::Shmem* aShmem,
+                                       bool* aResult)
 {
   AutoCompleteTask complete(aTask);
 
   if (!CanSend()) {
     return;
   }
-  DeallocShmem(*aShmem);
+  *aResult = DeallocShmem(*aShmem);
 }
 
-void
+bool
 ImageBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
 {
   if (InImageBridgeChildThread()) {
     if (!CanSend()) {
-      return;
+      return false;
     }
-    PImageBridgeChild::DeallocShmem(aShmem);
-    return;
+    return PImageBridgeChild::DeallocShmem(aShmem);
   }
 
   SynchronousTask task("AllocatorProxy Dealloc");
+  bool result = false;
 
   RefPtr<Runnable> runnable = WrapRunnable(
     RefPtr<ImageBridgeChild>(this),
     &ImageBridgeChild::ProxyDeallocShmemNow,
     &task,
-    &aShmem);
+    &aShmem,
+    &result);
   GetMessageLoop()->PostTask(runnable.forget());
 
   task.Wait();
+  return result;
 }
 
 PTextureChild*
 ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
                                      const LayersBackend&,
                                      const TextureFlags&,
                                      const uint64_t& aSerial)
 {
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -253,17 +253,17 @@ private:
     AsyncCanvasRenderer* aWrapper);
 
   void FlushAllImagesSync(
     SynchronousTask* aTask,
     ImageClient* aClient,
     ImageContainer* aContainer);
 
   void ProxyAllocShmemNow(SynchronousTask* aTask, AllocShmemParams* aParams);
-  void ProxyDeallocShmemNow(SynchronousTask* aTask, Shmem* aShmem);
+  void ProxyDeallocShmemNow(SynchronousTask* aTask, Shmem* aShmem, bool* aResult);
 
 public:
   // CompositableForwarder
 
   virtual void Connect(CompositableClient* aCompositable,
                        ImageContainer* aImageContainer) override;
 
   virtual bool UsesImageBridge() const override { return true; }
@@ -327,17 +327,17 @@ public:
                           mozilla::ipc::Shmem* aShmem) override;
 
   /**
    * See ISurfaceAllocator.h
    * Can be used from any thread.
    * If used outside the ImageBridgeChild thread, it will proxy a synchronous
    * call on the ImageBridgeChild thread.
    */
-  virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
+  virtual bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
 
   virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
                                        LayersBackend aLayersBackend,
                                        TextureFlags aFlags,
                                        uint64_t aSerial) override;
 
   virtual bool IsSameProcess() const override;
 
--- a/gfx/layers/ipc/TextureForwarder.h
+++ b/gfx/layers/ipc/TextureForwarder.h
@@ -9,16 +9,19 @@
 
 #include <stdint.h>                     // for int32_t, uint64_t
 #include "gfxTypes.h"
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
 #include "mozilla/layers/TextureClient.h"  // for TextureClient
 #include "mozilla/layers/KnowsCompositor.h"
 
 namespace mozilla {
+namespace ipc {
+class IShmemAllocator;
+}
 namespace layers {
 
 /**
  * An abstract interface for classes that implement the autogenerated
  * IPDL actor class. Lets us check if they are still valid for IPC.
  */
 class LayersIPCActor {
 public:
@@ -26,41 +29,34 @@ public:
 };
 
 /**
  * An abstract interface for LayersIPCActors that implement a top-level
  * IPDL protocol so also have their own channel.
  * Has their own MessageLoop for message dispatch, and can allocate
  * shmem.
  */
-class LayersIPCChannel : public LayersIPCActor {
+class LayersIPCChannel : public LayersIPCActor
+                       , public mozilla::ipc::IShmemAllocator {
 public:
   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
   NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
 
   virtual bool IsSameProcess() const = 0;
 
   virtual bool UsesImageBridge() const { return false; }
 
   virtual base::ProcessId GetParentPid() const = 0;
 
   virtual MessageLoop* GetMessageLoop() const = 0;
 
   virtual FixedSizeSmallShmemSectionAllocator* GetTileLockAllocator() { return nullptr; }
 
   virtual void CancelWaitForRecycle(uint64_t aTextureId) = 0;
 
-  virtual bool AllocShmem(size_t aSize,
-                          mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
-                          mozilla::ipc::Shmem* aShmem) = 0;
-  virtual bool AllocUnsafeShmem(size_t aSize,
-                                mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
-                                mozilla::ipc::Shmem* aShmem) = 0;
-  virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) = 0;
-
 protected:
   virtual ~LayersIPCChannel() {}
 };
 
 /**
  * An abstract interface for classes that can allocate PTexture objects
  * across IPDL. Currently a sub-class of LayersIPCChannel for simplicity
  * since all our implementations use both, but could be independant if needed.
--- a/gfx/layers/ipc/VideoBridgeChild.cpp
+++ b/gfx/layers/ipc/VideoBridgeChild.cpp
@@ -61,20 +61,20 @@ bool
 VideoBridgeChild::AllocShmem(size_t aSize,
                              ipc::SharedMemory::SharedMemoryType aType,
                              ipc::Shmem* aShmem)
 {
   MOZ_ASSERT(CanSend());
   return PVideoBridgeChild::AllocShmem(aSize, aType, aShmem);
 }
 
-void
+bool
 VideoBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
 {
-  PVideoBridgeChild::DeallocShmem(aShmem);
+  return PVideoBridgeChild::DeallocShmem(aShmem);
 }
 
 PTextureChild*
 VideoBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
                                      const LayersBackend&,
                                      const TextureFlags&,
                                      const uint64_t& aSerial)
 {
--- a/gfx/layers/ipc/VideoBridgeChild.h
+++ b/gfx/layers/ipc/VideoBridgeChild.h
@@ -33,17 +33,17 @@ public:
 
   // ISurfaceAllocator
   bool AllocUnsafeShmem(size_t aSize,
                         mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
                         mozilla::ipc::Shmem* aShmem) override;
   bool AllocShmem(size_t aSize,
                   mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
                   mozilla::ipc::Shmem* aShmem) override;
-  void DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
+  bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
 
   // TextureForwarder
   PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
                                LayersBackend aLayersBackend,
                                TextureFlags aFlags,
                                uint64_t aSerial) override;
 
   // ClientIPCAllocator
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -372,20 +372,20 @@ VRManagerChild::AllocShmem(size_t aSize,
 bool
 VRManagerChild::AllocUnsafeShmem(size_t aSize,
                                  ipc::SharedMemory::SharedMemoryType aType,
                                  ipc::Shmem* aShmem)
 {
   return PVRManagerChild::AllocUnsafeShmem(aSize, aType, aShmem);
 }
 
-void
+bool
 VRManagerChild::DeallocShmem(ipc::Shmem& aShmem)
 {
-  PVRManagerChild::DeallocShmem(aShmem);
+  return PVRManagerChild::DeallocShmem(aShmem);
 }
 
 PVRLayerChild*
 VRManagerChild::CreateVRLayer(uint32_t aDisplayID, const Rect& aLeftEyeRect, const Rect& aRightEyeRect)
 {
   return SendPVRLayerConstructor(aDisplayID,
                                  aLeftEyeRect.x, aLeftEyeRect.y, aLeftEyeRect.width, aLeftEyeRect.height,
                                  aRightEyeRect.x, aRightEyeRect.y, aRightEyeRect.width, aRightEyeRect.height);
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -125,17 +125,17 @@ protected:
   virtual bool AllocShmem(size_t aSize,
                           ipc::SharedMemory::SharedMemoryType aType,
                           ipc::Shmem* aShmem) override;
 
   virtual bool AllocUnsafeShmem(size_t aSize,
                                 ipc::SharedMemory::SharedMemoryType aType,
                                 ipc::Shmem* aShmem) override;
 
-  virtual void DeallocShmem(ipc::Shmem& aShmem) override;
+  virtual bool DeallocShmem(ipc::Shmem& aShmem) override;
 
   virtual bool IsSameProcess() const override
   {
     return OtherPid() == base::GetCurrentProcId();
   }
 
   friend class layers::CompositorBridgeChild;