Bug 1323328 - Part 2: Implement VRServiceTest backend at VRManager; r?kip draft
authorDaosheng Mu <daoshengmu@gmail.com>
Wed, 01 Mar 2017 23:58:31 +0800
changeset 493251 f48d74c699fe96402aa6b3ec183d123563ab5e87
parent 493250 da904954b72a320c425fea00488c86315ca1d6f0
child 493252 7ae56c4a1118b060401e16e9c106094d6e4af67c
child 493539 9045fcde6dd4abd3c6867c1c36ecc1bc91198489
push id47700
push userbmo:dmu@mozilla.com
push dateFri, 03 Mar 2017 17:48:54 +0000
reviewerskip
bugs1323328
milestone54.0a1
Bug 1323328 - Part 2: Implement VRServiceTest backend at VRManager; r?kip MozReview-Commit-ID: EpW7BqeICLo
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/gfx/vr/ipc/PVRManager.ipdl
+++ b/gfx/vr/ipc/PVRManager.ipdl
@@ -57,29 +57,42 @@ parent:
   sync GetImmediateSensorState(uint32_t aDisplayID) returns(VRHMDSensorState aState);
   sync SetHaveEventListener(bool aHaveEventListener);
 
   async ControllerListenerAdded();
   async ControllerListenerRemoved();
   // GetControllers synchronously returns the VR controllers that have already been
   // enumerated by RefreshVRControllers() but does not enumerate new ones.
   sync GetControllers() returns(VRControllerInfo[] aControllerInfo);
+  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,
+                                       bool aPressed);
+  async NewAxisMoveEventToMockController(uint32_t aDeviceID, long aAxis,
+                                         double aValue);
+  async NewPoseMoveToMockController(uint32_t aDeviceID, GamepadPoseState aPose);
 
 child:
 
   async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
 
   // Notify children of updated VR display enumeration and details.  This will
   // 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 ReplyCreateVRServiceTestDisplay(nsCString aID, uint32_t aPromiseID,
+                                        uint32_t aDeviceID);
+  async ReplyCreateVRServiceTestController(nsCString aID, uint32_t aPromiseID,
+                                           uint32_t aDeviceID);
 
   async __delete__();
 
 };
 
 } // gfx
 } // mozilla
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -13,16 +13,17 @@
 #include "mozilla/layers/CompositorThread.h" // for CompositorThread
 #include "mozilla/dom/Navigator.h"
 #include "mozilla/dom/VREventObserver.h"
 #include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/layers/TextureClient.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/GamepadManager.h"
+#include "mozilla/dom/VRServiceTest.h"
 
 using layers::TextureClient;
 
 namespace {
 const nsTArray<RefPtr<dom::VREventObserver>>::index_type kNoIndex =
   nsTArray<RefPtr<dom::VREventObserver> >::NoIndex;
 } // namespace
 
@@ -38,16 +39,17 @@ void ReleaseVRManagerParentSingleton() {
 
 VRManagerChild::VRManagerChild()
   : TextureForwarder()
   , mDisplaysInitialized(false)
   , mInputFrameID(-1)
   , mMessageLoop(MessageLoop::current())
   , mFrameRequestCallbackCounter(0)
   , mBackend(layers::LayersBackend::LAYERS_NONE)
+  , mPromiseID(0)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mStartTimeStamp = TimeStamp::Now();
 }
 
 VRManagerChild::~VRManagerChild()
 {
@@ -309,16 +311,32 @@ VRManagerChild::RefreshVRDisplaysWithCal
 {
   bool success = SendRefreshDisplays();
   if (success) {
     mNavigatorCallbacks.AppendElement(aWindowId);
   }
   return success;
 }
 
+void
+VRManagerChild::CreateVRServiceTestDisplay(const nsCString& aID, dom::Promise* aPromise)
+{
+  SendCreateVRServiceTestDisplay(aID, mPromiseID);
+  mPromiseList.Put(mPromiseID, aPromise);
+  ++mPromiseID;
+}
+
+void
+VRManagerChild::CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise)
+{
+  SendCreateVRServiceTestController(aID, mPromiseID);
+  mPromiseList.Put(mPromiseID, aPromise);
+  ++mPromiseID;
+}
+
 int
 VRManagerChild::GetInputFrameID()
 {
   return mInputFrameID;
 }
 
 mozilla::ipc::IPCResult
 VRManagerChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages)
@@ -486,16 +504,46 @@ VRManagerChild::RecvGamepadUpdate(const 
   RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
   if (gamepadManager) {
     gamepadManager->Update(aGamepadEvent);
   }
 
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult
+VRManagerChild::RecvReplyCreateVRServiceTestDisplay(const nsCString& aID,
+                                                    const uint32_t& aPromiseID,
+                                                    const uint32_t& aDeviceID)
+{
+  RefPtr<dom::Promise> p;
+  if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
+    MOZ_CRASH("We should always have a promise.");
+  }
+
+  p->MaybeResolve(new VRMockDisplay(aID, aDeviceID));
+  mPromiseList.Remove(aPromiseID);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerChild::RecvReplyCreateVRServiceTestController(const nsCString& aID,
+                                                       const uint32_t& aPromiseID,
+                                                       const uint32_t& aDeviceID)
+{
+  RefPtr<dom::Promise> p;
+  if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
+    MOZ_CRASH("We should always have a promise.");
+  }
+
+  p->MaybeResolve(new VRMockController(aID, aDeviceID));
+  mPromiseList.Remove(aPromiseID);
+  return IPC_OK();
+}
+
 void
 VRManagerChild::RunFrameRequestCallbacks()
 {
   TimeStamp nowTime = TimeStamp::Now();
   mozilla::TimeDuration duration = nowTime - mStartTimeStamp;
   DOMHighResTimeStamp timeStamp = duration.ToMilliseconds();
 
 
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -44,16 +44,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 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();
 
   static bool IsCreated();
@@ -112,16 +114,22 @@ 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 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
 
   virtual bool AllocShmem(size_t aSize,
                           ipc::SharedMemory::SharedMemoryType aType,
                           ipc::Shmem* aShmem) override;
 
   virtual bool AllocUnsafeShmem(size_t aSize,
@@ -172,16 +180,18 @@ 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;
+  uint32_t mPromiseID;
+  nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList;
 
   DISALLOW_COPY_AND_ASSIGN(VRManagerChild);
 };
 
 } // namespace mozilla
 } // namespace gfx
 
 #endif // MOZILLA_GFX_VR_VRMANAGERCHILD_H
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -9,23 +9,26 @@
 #include "ipc/VRLayerParent.h"
 #include "mozilla/gfx/PVRManagerParent.h"
 #include "mozilla/ipc/ProtocolTypes.h"
 #include "mozilla/ipc/ProtocolUtils.h"       // for IToplevelProtocol
 #include "mozilla/TimeStamp.h"               // for TimeStamp
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/Unused.h"
 #include "VRManager.h"
+#include "gfxVRPuppet.h"
 
 namespace mozilla {
 using namespace layers;
 namespace gfx {
 
 VRManagerParent::VRManagerParent(ProcessId aChildProcessId, bool aIsContentChild)
   : HostIPCAllocator()
+  , mDisplayTestID(0)
+  , mControllerTestID(0)
   , mHaveEventListener(false)
   , mHaveControllerListener(false)
   , mIsContentChild(aIsContentChild)
 {
   MOZ_COUNT_CTOR(VRManagerParent);
   MOZ_ASSERT(NS_IsMainThread());
 
   SetOtherProcessId(aChildProcessId);
@@ -321,16 +324,139 @@ VRManagerParent::RecvControllerListenerR
 mozilla::ipc::IPCResult
 VRManagerParent::RecvGetControllers(nsTArray<VRControllerInfo> *aControllers)
 {
   VRManager* vm = VRManager::Get();
   vm->GetVRControllerInfo(*aControllers);
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult
+VRManagerParent::RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint32_t& aPromiseID)
+{
+  nsTArray<VRDisplayInfo> displayInfoArray;
+  impl::VRDisplayPuppet* displayPuppet = nullptr;
+  VRManager* vm = VRManager::Get();
+  vm->RefreshVRDisplays();
+
+  // Get VRDisplayPuppet from VRManager
+  vm->GetVRDisplayInfo(displayInfoArray);
+  for (auto& displayInfo : displayInfoArray) {
+    if (displayInfo.GetType() == VRDeviceType::Puppet) {
+        displayPuppet = static_cast<impl::VRDisplayPuppet*>(
+                        vm->GetDisplay(displayInfo.GetDisplayID()).get());
+        break;
+    }
+  }
+
+  MOZ_ASSERT(displayPuppet);
+  MOZ_ASSERT(!mDisplayTestID); // We have only one display in VRSystemManagerPuppet.
+
+  if (!mVRDisplayTests.Get(mDisplayTestID, nullptr)) {
+    mVRDisplayTests.Put(mDisplayTestID, displayPuppet);
+  }
+
+  if (SendReplyCreateVRServiceTestDisplay(aID, aPromiseID, mDisplayTestID)) {
+    return IPC_OK();
+  }
+
+  return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvCreateVRServiceTestController(const nsCString& aID, const uint32_t& aPromiseID)
+{
+  uint32_t controllerIdx = 0;
+  nsTArray<VRControllerInfo> controllerInfoArray;
+  impl::VRControllerPuppet* controllerPuppet = nullptr;
+  VRManager* vm = VRManager::Get();
+
+  // Get VRControllerPuppet from VRManager
+  vm->GetVRControllerInfo(controllerInfoArray);
+  for (auto& controllerInfo : controllerInfoArray) {
+    if (controllerInfo.GetType() == VRDeviceType::Puppet) {
+      if (controllerIdx == mControllerTestID) {
+        controllerPuppet = static_cast<impl::VRControllerPuppet*>(
+                           vm->GetController(controllerInfo.GetControllerID()).get());
+        break;
+      }
+      ++controllerIdx;
+    }
+  }
+
+  MOZ_ASSERT(controllerPuppet);
+  MOZ_ASSERT(mControllerTestID < 2); // We have only two controllers in VRSystemManagerPuppet.
+
+  if (!mVRControllerTests.Get(mControllerTestID, nullptr)) {
+    mVRControllerTests.Put(mControllerTestID, controllerPuppet);
+  }
+
+  if (SendReplyCreateVRServiceTestController(aID, aPromiseID, mControllerTestID)) {
+    ++mControllerTestID;
+    return IPC_OK();
+  }
+
+  return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvSetDisplayInfoToMockDisplay(const uint32_t& aDeviceID,
+                                                 const VRDisplayInfo& aDisplayInfo)
+{
+  RefPtr<impl::VRDisplayPuppet> displayPuppet;
+  MOZ_ASSERT(mVRDisplayTests.Get(mDisplayTestID,
+                                 getter_AddRefs(displayPuppet)));
+  displayPuppet->SetDisplayInfo(aDisplayInfo);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvSetSensorStateToMockDisplay(const uint32_t& aDeviceID,
+                                                 const VRHMDSensorState& aSensorState)
+{
+  RefPtr<impl::VRDisplayPuppet> displayPuppet;
+  MOZ_ASSERT(mVRDisplayTests.Get(mControllerTestID,
+                                 getter_AddRefs(displayPuppet)));
+  displayPuppet->SetSensorState(aSensorState);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvNewButtonEventToMockController(const uint32_t& aDeviceID, const long& aButton,
+                                                    const bool& aPressed)
+{
+  RefPtr<impl::VRControllerPuppet> controllerPuppet;
+  MOZ_ASSERT(mVRControllerTests.Get(mControllerTestID,
+                                    getter_AddRefs(controllerPuppet)));
+  controllerPuppet->SetButtonPressState(aButton, aPressed);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvNewAxisMoveEventToMockController(const uint32_t& aDeviceID, const long& aAxis,
+                                                      const double& aValue)
+{
+  RefPtr<impl::VRControllerPuppet> controllerPuppet;
+  MOZ_ASSERT(mVRControllerTests.Get(mControllerTestID,
+                                    getter_AddRefs(controllerPuppet)));
+  controllerPuppet->SetAxisMoveState(aAxis, aValue);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvNewPoseMoveToMockController(const uint32_t& aDeviceID,
+                                                 const GamepadPoseState& pose)
+{
+  RefPtr<impl::VRControllerPuppet> controllerPuppet;
+  MOZ_ASSERT(mVRControllerTests.Get(mControllerTestID,
+                                    getter_AddRefs(controllerPuppet)));
+  controllerPuppet->SetPoseMoveState(pose);
+  return IPC_OK();
+}
+
 bool
 VRManagerParent::SendGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
 {
   // GamepadManager only exists at the content process
   // or the same process in non-e10s mode.
   if (mIsContentChild || IsSameProcess()) {
     return PVRManagerParent::SendGamepadUpdate(aGamepadEvent);
   } else {
--- a/gfx/vr/ipc/VRManagerParent.h
+++ b/gfx/vr/ipc/VRManagerParent.h
@@ -17,16 +17,21 @@
 #include "gfxVR.h"                        // for VRFieldOfView
 
 namespace mozilla {
 using namespace layers;
 namespace gfx {
 
 class VRManager;
 
+namespace impl {
+class VRDisplayPuppet;
+class VRControllerPuppet;
+} // namespace impl
+
 class VRManagerParent final : public PVRManagerParent
                             , public HostIPCAllocator
                             , public ShmemAllocator
 {
 public:
   explicit VRManagerParent(ProcessId aChildProcessId, bool aIsContentChild);
 
   static VRManagerParent* CreateSameProcess();
@@ -84,16 +89,27 @@ protected:
   virtual mozilla::ipc::IPCResult RecvGetDisplays(nsTArray<VRDisplayInfo> *aDisplays) 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 RecvGetImmediateSensorState(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 RecvGetControllers(nsTArray<VRControllerInfo> *aControllers) 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,
+                                                                     const bool& aPressed) override;
+  virtual mozilla::ipc::IPCResult RecvNewAxisMoveEventToMockController(const uint32_t& aDeviceID, const long& aAxis,
+                                                                       const double& aValue) override;
+  virtual mozilla::ipc::IPCResult RecvNewPoseMoveToMockController(const uint32_t& aDeviceID, const GamepadPoseState& pose) override;
 
 private:
   void RegisterWithManager();
   void UnregisterFromManager();
 
   void Bind(Endpoint<PVRManagerParent>&& aEndpoint);
 
   static void RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager);
@@ -104,16 +120,20 @@ private:
   // deferred destruction of ourselves.
   RefPtr<VRManagerParent> mSelfRef;
 
   // Keep the compositor thread alive, until we have destroyed ourselves.
   RefPtr<layers::CompositorThreadHolder> mCompositorThreadHolder;
 
   // Keep the VRManager alive, until we have destroyed ourselves.
   RefPtr<VRManager> mVRManagerHolder;
+  nsRefPtrHashtable<nsUint32HashKey, impl::VRDisplayPuppet> mVRDisplayTests;
+  nsRefPtrHashtable<nsUint32HashKey, impl::VRControllerPuppet> mVRControllerTests;
+  uint32_t mDisplayTestID;
+  uint32_t mControllerTestID;
   bool mHaveEventListener;
   bool mHaveControllerListener;
   bool mIsContentChild;
 };
 
 } // namespace mozilla
 } // namespace gfx