Bug 1299937 - Part 4: Handling vibrate haptic promise in VRManager; r=qdot
authorDaosheng Mu <daoshengmu@gmail.com>
Thu, 02 Feb 2017 14:59:44 +0800
changeset 349324 3381a8485d054b31ada9f67fd880267db1d6b0ef
parent 349323 ed20b557e9a5745a37fce239dcff94cb35b90c2c
child 349325 3c1984bdf4047df79fde8e84264f17de80351f20
push id31550
push usercbook@mozilla.com
push dateFri, 24 Mar 2017 13:22:27 +0000
treeherdermozilla-central@473e0b201761 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs1299937
milestone55.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 1299937 - Part 4: Handling vibrate haptic promise in VRManager; r=qdot MozReview-Commit-ID: 3KZ8MNx3Dnq
dom/gamepad/GamepadManager.cpp
dom/gamepad/GamepadManager.h
gfx/vr/VRManager.cpp
gfx/vr/VRManager.h
gfx/vr/ipc/PVRManager.ipdl
gfx/vr/ipc/VRManagerChild.cpp
gfx/vr/ipc/VRManagerChild.h
gfx/vr/ipc/VRManagerParent.cpp
gfx/vr/ipc/VRManagerParent.h
--- a/dom/gamepad/GamepadManager.cpp
+++ b/dom/gamepad/GamepadManager.cpp
@@ -55,17 +55,18 @@ const uint32_t VR_GAMEPAD_IDX_OFFSET = 0
 
 } // namespace
 
 NS_IMPL_ISUPPORTS(GamepadManager, nsIObserver)
 
 GamepadManager::GamepadManager()
   : mEnabled(false),
     mNonstandardEventsEnabled(false),
-    mShuttingDown(false)
+    mShuttingDown(false),
+    mPromiseID(0)
 {}
 
 nsresult
 GamepadManager::Init()
 {
   mEnabled = IsAPIEnabled();
   mNonstandardEventsEnabled =
     Preferences::GetBool(kGamepadEventsEnabledPref, false);
@@ -662,27 +663,39 @@ GamepadManager::Update(const GamepadChan
     NewPoseEvent(a.index(), a.service_type(), a.pose_state());
     return;
   }
 
   MOZ_CRASH("We shouldn't be here!");
 
 }
 
-void
+already_AddRefed<Promise>
 GamepadManager::VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
-                              double aIntensity, double aDuration)
+                              double aIntensity, double aDuration,
+                              nsIGlobalObject* aGlobal, ErrorResult& aRv)
 {
+  RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
   if (aControllerIdx >= VR_GAMEPAD_IDX_OFFSET) {
     uint32_t index = aControllerIdx - VR_GAMEPAD_IDX_OFFSET;
+    mVRChannelChild->AddPromise(mPromiseID, promise);
     mVRChannelChild->SendVibrateHaptic(index, aHapticIndex,
-                                       aIntensity, aDuration);
+                                       aIntensity, aDuration,
+                                       mPromiseID);
   } else {
     // TODO: Bug 680289, implement for standard gamepads
   }
+
+  ++mPromiseID;
+  return promise.forget();
 }
 
 //Override nsIIPCBackgroundChildCreateCallback
 void
 GamepadManager::ActorCreated(PBackgroundChild *aActor)
 {
   MOZ_ASSERT(aActor);
   GamepadEventChannelChild *child = new GamepadEventChannelChild();
--- a/dom/gamepad/GamepadManager.h
+++ b/dom/gamepad/GamepadManager.h
@@ -80,18 +80,19 @@ class GamepadManager final : public nsIO
 
   // Returns gamepad object if index exists, null otherwise
   already_AddRefed<Gamepad> GetGamepad(uint32_t aIndex) const;
 
   // Receive GamepadChangeEvent messages from parent process to fire DOM events
   void Update(const GamepadChangeEvent& aGamepadEvent);
 
   // Trigger vibrate haptic event to gamepad channels.
-  void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
-                     double aIntensity, double aDuration);
+  already_AddRefed<Promise> VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
+                                          double aIntensity, double aDuration,
+                                          nsIGlobalObject* aGlobal, ErrorResult& aRv);
 
  protected:
   GamepadManager();
   ~GamepadManager() {};
 
   // Fire a gamepadconnected or gamepaddisconnected event for the gamepad
   // at |aIndex| to all windows that are listening and have received
   // gamepad input.
@@ -148,14 +149,15 @@ class GamepadManager final : public nsIO
   uint32_t GetGamepadIndexWithServiceType(uint32_t aIndex, GamepadServiceType aServiceType);
 
   // Gamepads connected to the system. Copies of these are handed out
   // to each window.
   nsRefPtrHashtable<nsUint32HashKey, Gamepad> mGamepads;
   // Inner windows that are listening for gamepad events.
   // has been sent to that window.
   nsTArray<RefPtr<nsGlobalWindow>> mListeners;
+  uint32_t mPromiseID;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_GamepadManager_h_
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -420,18 +420,19 @@ VRManager::NotifyGamepadChange(const T& 
 
   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     Unused << iter.Get()->GetKey()->SendGamepadUpdate(e);
   }
 }
 
 void
 VRManager::VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
-                         double aIntensity, double aDuration)
+                         double aIntensity, double aDuration, uint32_t aPromiseID)
+
 {
   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     mManagers[i]->VibrateHaptic(aControllerIdx, aHapticIndex,
-                                aIntensity, aDuration);
+                                aIntensity, aDuration, aPromiseID);
   }
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -45,17 +45,17 @@ public:
 
   void SubmitFrame(VRLayerParent* aLayer, layers::PTextureParent* aTexture,
                    const gfx::Rect& aLeftEyeRect,
                    const gfx::Rect& aRightEyeRect);
   RefPtr<gfx::VRControllerHost> GetController(const uint32_t& aControllerID);
   void GetVRControllerInfo(nsTArray<VRControllerInfo>& aControllerInfo);
   void CreateVRTestSystem();
   void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
-                     double aIntensity, double aDuration);
+                     double aIntensity, double aDuration, uint32_t aPromiseID);
 
 protected:
   VRManager();
   ~VRManager();
 
 private:
   RefPtr<layers::TextureHost> mLastFrame;
 
--- a/gfx/vr/ipc/PVRManager.ipdl
+++ b/gfx/vr/ipc/PVRManager.ipdl
@@ -50,17 +50,17 @@ parent:
   async ResetSensor(uint32_t aDisplayID);
 
   sync GetSensorState(uint32_t aDisplayID) returns(VRHMDSensorState aState);
   async SetHaveEventListener(bool aHaveEventListener);
 
   async ControllerListenerAdded();
   async ControllerListenerRemoved();
   async VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
-                      double aIntensity, double aDuration);
+                      double aIntensity, double aDuration, uint32_t aPromiseID);
 
   async CreateVRTestSystem();
   async CreateVRServiceTestDisplay(nsCString aID, uint32_t aPromiseID);
   async CreateVRServiceTestController(nsCString aID, uint32_t aPromiseID);
   async SetDisplayInfoToMockDisplay(uint32_t aDeviceID, VRDisplayInfo aDisplayInfo);
   async SetSensorStateToMockDisplay(uint32_t aDeviceID, VRHMDSensorState aSensorState);
 
   async NewButtonEventToMockController(uint32_t aDeviceID, long aButton,
@@ -77,16 +77,18 @@ child:
   // be sent to all children when the parent receives RefreshDisplays, even
   // if no changes have been detected.  This ensures that Promises exposed
   // through DOM calls are always resolved.
   async UpdateDisplayInfo(VRDisplayInfo[] aDisplayUpdates);
 
   async NotifyVSync();
   async NotifyVRVSync(uint32_t aDisplayID);
   async GamepadUpdate(GamepadChangeEvent aGamepadEvent);
+  async ReplyGamepadVibrateHaptic(uint32_t aPromiseID);
+
   async ReplyCreateVRServiceTestDisplay(nsCString aID, uint32_t aPromiseID,
                                         uint32_t aDeviceID);
   async ReplyCreateVRServiceTestController(nsCString aID, uint32_t aPromiseID,
                                            uint32_t aDeviceID);
 
   async __delete__();
 
 };
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -672,10 +672,30 @@ VRManagerChild::RemoveListener(dom::VREv
 }
 
 void
 VRManagerChild::HandleFatalError(const char* aName, const char* aMsg) const
 {
   dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
 }
 
+void
+VRManagerChild::AddPromise(const uint32_t& aID, dom::Promise* aPromise)
+{
+  MOZ_ASSERT(!mGamepadPromiseList.Get(aID, nullptr));
+  mGamepadPromiseList.Put(aID, aPromise);
+}
+
+mozilla::ipc::IPCResult
+VRManagerChild::RecvReplyGamepadVibrateHaptic(const uint32_t& aPromiseID)
+{
+  RefPtr<dom::Promise> p;
+  if (!mGamepadPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
+    MOZ_CRASH("We should always have a promise.");
+  }
+
+  p->MaybeResolve(true);
+  mGamepadPromiseList.Remove(aPromiseID);
+  return IPC_OK();
+}
+
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -12,16 +12,17 @@
 #include "mozilla/ipc/SharedMemory.h"   // for SharedMemory, etc
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
 #include "mozilla/layers/TextureForwarder.h"
 
 namespace mozilla {
 namespace dom {
+class Promise;
 class GamepadManager;
 class Navigator;
 class VRDisplay;
 class VREventObserver;
 class VRMockDisplay;
 } // namespace dom
 namespace layers {
 class TextureClient;
@@ -45,16 +46,18 @@ public:
   // Indicate that an observer wants to receive VR events.
   void AddListener(dom::VREventObserver* aObserver);
   // Indicate that an observer should no longer receive VR events.
   void RemoveListener(dom::VREventObserver* aObserver);
 
   int GetInputFrameID();
   bool GetVRDisplays(nsTArray<RefPtr<VRDisplayClient> >& aDisplays);
   bool RefreshVRDisplaysWithCallback(uint64_t aWindowId);
+  void AddPromise(const uint32_t& aID, dom::Promise* aPromise);
+
   void CreateVRServiceTestDisplay(const nsCString& aID, dom::Promise* aPromise);
   void CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise);
 
   static void InitSameProcess();
   static void InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint);
   static bool InitForContent(Endpoint<PVRManagerChild>&& aEndpoint);
   static bool ReinitForContent(Endpoint<PVRManagerChild>&& aEndpoint);
   static void ShutDown();
@@ -115,16 +118,18 @@ protected:
 
   virtual mozilla::ipc::IPCResult RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates) override;
 
   virtual mozilla::ipc::IPCResult RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
 
   virtual mozilla::ipc::IPCResult RecvNotifyVSync() override;
   virtual mozilla::ipc::IPCResult RecvNotifyVRVSync(const uint32_t& aDisplayID) override;
   virtual mozilla::ipc::IPCResult RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override;
+  virtual mozilla::ipc::IPCResult RecvReplyGamepadVibrateHaptic(const uint32_t& aPromiseID) override;
+
   virtual mozilla::ipc::IPCResult RecvReplyCreateVRServiceTestDisplay(const nsCString& aID,
                                                                       const uint32_t& aPromiseID,
                                                                       const uint32_t& aDeviceID) override;
   virtual mozilla::ipc::IPCResult RecvReplyCreateVRServiceTestController(const nsCString& aID,
                                                                          const uint32_t& aPromiseID,
                                                                          const uint32_t& aDeviceID) override;
 
   // ShmemAllocator
@@ -181,16 +186,17 @@ private:
   /**
   * Hold TextureClients refs until end of their usages on host side.
   * It defer calling of TextureClient recycle callback.
   */
   nsDataHashtable<nsUint64HashKey, RefPtr<layers::TextureClient> > mTexturesWaitingRecycled;
 
   layers::LayersBackend mBackend;
   RefPtr<layers::SyncObject> mSyncObject;
+  nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mGamepadPromiseList; // TODO: check if it can merge into one list?
   uint32_t mPromiseID;
   nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList;
   RefPtr<dom::VRMockDisplay> mVRMockDisplay;
 
   DISALLOW_COPY_AND_ASSIGN(VRManagerChild);
 };
 
 } // namespace mozilla
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -437,21 +437,22 @@ VRManagerParent::RecvNewPoseMoveToMockCo
   controllerPuppet->SetPoseMoveState(pose);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 VRManagerParent::RecvVibrateHaptic(const uint32_t& aControllerIdx,
                                    const uint32_t& aHapticIndex,
                                    const double& aIntensity,
-                                   const double& aDuration)
+                                   const double& aDuration,
+                                   const uint32_t& aPromiseID)
 {
   VRManager* vm = VRManager::Get();
   vm->VibrateHaptic(aControllerIdx, aHapticIndex, aIntensity,
-                    aDuration);
+                    aDuration, aPromiseID);
   return IPC_OK();
 }
 
 bool
 VRManagerParent::SendGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
 {
   // GamepadManager only exists at the content process
   // or the same process in non-e10s mode.
--- a/gfx/vr/ipc/VRManagerParent.h
+++ b/gfx/vr/ipc/VRManagerParent.h
@@ -87,17 +87,18 @@ protected:
 
   virtual mozilla::ipc::IPCResult RecvRefreshDisplays() override;
   virtual mozilla::ipc::IPCResult RecvResetSensor(const uint32_t& aDisplayID) override;
   virtual mozilla::ipc::IPCResult RecvGetSensorState(const uint32_t& aDisplayID, VRHMDSensorState* aState) override;
   virtual mozilla::ipc::IPCResult RecvSetHaveEventListener(const bool& aHaveEventListener) override;
   virtual mozilla::ipc::IPCResult RecvControllerListenerAdded() override;
   virtual mozilla::ipc::IPCResult RecvControllerListenerRemoved() override;
   virtual mozilla::ipc::IPCResult RecvVibrateHaptic(const uint32_t& aControllerIdx, const uint32_t& aHapticIndex,
-                                                    const double& aIntensity, const double& aDuration) override;
+                                                    const double& aIntensity, const double& aDuration, const uint32_t& aPromiseID) override;
+  
   virtual mozilla::ipc::IPCResult RecvCreateVRTestSystem() override;
   virtual mozilla::ipc::IPCResult RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint32_t& aPromiseID) override;
   virtual mozilla::ipc::IPCResult RecvCreateVRServiceTestController(const nsCString& aID, const uint32_t& aPromiseID) override;
   virtual mozilla::ipc::IPCResult RecvSetDisplayInfoToMockDisplay(const uint32_t& aDeviceID,
                                                                   const VRDisplayInfo& aDisplayInfo) override;
   virtual mozilla::ipc::IPCResult RecvSetSensorStateToMockDisplay(const uint32_t& aDeviceID,
                                                                   const VRHMDSensorState& aSensorState) override;
   virtual mozilla::ipc::IPCResult RecvNewButtonEventToMockController(const uint32_t& aDeviceID, const long& aButton,