Bug 1323328 - Part 2: Implement VRServiceTest backend at VRManager; r=kip
authorDaosheng Mu <daoshengmu@gmail.com>
Wed, 01 Mar 2017 23:58:31 +0800
changeset 345934 39365e72a1133d38439489a779c800cc1cca4eb9
parent 345933 41193207cd699f23f1e020bf3f2ec41ef5a1bd87
child 345935 659795097ae3e147629d539a423bc5d6a8c22ccf
push id38351
push userdmu@mozilla.com
push dateSat, 04 Mar 2017 20:09:02 +0000
treeherderautoland@473acbe8453d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskip
bugs1323328
milestone54.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 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