Bug 1406327 - Part 4: RefreshVRDisplays needs to be at VRListenerThread; r?kip draft
authorDaosheng Mu <daoshengmu@gmail.com>
Wed, 01 Nov 2017 22:15:06 +0800
changeset 694067 6cfba4678a8824d89e89f2e3e357d58633bf81ee
parent 694066 6cfe3420d920c3dd5015e751acdeeadde29cefd9
child 694068 0b518e5e025671b4261f6ebf8e0e9c99bc455bf2
push id88034
push userbmo:dmu@mozilla.com
push dateTue, 07 Nov 2017 10:40:18 +0000
reviewerskip
bugs1406327
milestone58.0a1
Bug 1406327 - Part 4: RefreshVRDisplays needs to be at VRListenerThread; r?kip MozReview-Commit-ID: KuhPFqMhTDB
gfx/vr/VRManager.cpp
gfx/vr/VRManager.h
gfx/vr/gfxVROpenVR.cpp
gfx/vr/ipc/VRManagerParent.cpp
xpcom/threads/nsThreadUtils.h
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -254,16 +254,33 @@ VRManager::NotifyVRVsync(const uint32_t&
   }
 
   RefreshVRDisplays();
 }
 
 void
 VRManager::RefreshVRDisplays(bool aMustDispatch)
 {
+  if (VRListenerThreadHolder::IsInVRListenerThread()) {
+    RefreshVRDisplaysInternal(aMustDispatch);
+  } else {
+   if (VRListenerThreadHolder::IsActive()) {
+     MessageLoop* loop = VRListenerThreadHolder::Loop();
+      loop->PostTask(NewRunnableMethod<bool>(
+        "gfx::VRManager::RefreshVRDisplaysInternal",
+        this, &VRManager::RefreshVRDisplaysInternal, aMustDispatch
+      ));
+   }
+  }
+}
+
+void
+VRManager::RefreshVRDisplaysInternal(bool aMustDispatch)
+{
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
   nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
   mLastVRListenerThreadActiveTime = TimeStamp::Now();
   /** We don't wish to enumerate the same display from multiple managers,
    * so stop as soon as we get a display.
    * It is still possible to get multiple displays from a single manager,
    * but do not wish to mix-and-match for risk of reporting a duplicate.
    *
    * XXX - Perhaps there will be a better way to detect duplicate displays
@@ -441,16 +458,24 @@ VRManager::CreateVRTestSystem()
     return;
   }
 
   RefPtr<VRSystemManager> mgr = VRSystemManagerPuppet::Create();
   if (mgr) {
     mManagers.AppendElement(mgr);
     mVRTestSystemCreated = true;
   }
+
+  // Force to refresh VRPuppet display here
+  // because we need it to setup data early.
+  nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
+  mgr->GetHMDs(displays);
+  for (const auto& display: displays) {
+    mVRDisplays.Put(display->GetDisplayInfo().GetDisplayID(), display);
+  }
 }
 
 template<class T>
 void
 VRManager::NotifyGamepadChange(uint32_t aIndex, const T& aInfo)
 {
   dom::GamepadChangeEventBody body(aInfo);
   dom::GamepadChangeEvent e(aIndex, dom::GamepadServiceType::VR, body);
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -60,16 +60,17 @@ protected:
 
 private:
 
   void Init();
   void Destroy();
   void Shutdown();
 
   void DispatchVRDisplayInfoUpdate();
+  void RefreshVRDisplaysInternal(bool aMustDispatch);
   void NotifyGamepadChangeEventsToContent(const dom::GamepadChangeEvent& aEvent);
   void NotifyVibrateHapticCompletedToContent(uint32_t aPromiseID);
 
   typedef nsTHashtable<nsRefPtrHashKey<VRManagerParent>> VRManagerParentSet;
   VRManagerParentSet mVRManagerParents;
 
   typedef nsTArray<RefPtr<VRSystemManager>> VRSystemManagerArray;
   VRSystemManagerArray mManagers;
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -631,23 +631,16 @@ VRSystemManagerOpenVR::Shutdown()
   }
   RemoveControllers();
   mVRSystem = nullptr;
 }
 
 bool
 VRSystemManagerOpenVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
 {
-  // When running VR tests on local machines which have SteamVR runtime.
-  // VR_IsHmdPresent() would have chance to be true. Then, it makes us can't
-  // get the VRPuppet display.
-  if (gfxPrefs::VRPuppetEnabled()) {
-    return false;
-  }
-
   if (!::vr::VR_IsHmdPresent() ||
       (mOpenVRHMD && !mOpenVRHMD->GetIsHmdPresent())) {
     // OpenVR runtime could be quit accidentally,
     // and we make it re-initialize.
     mOpenVRHMD = nullptr;
     mVRSystem = nullptr;
   } else if (mOpenVRHMD == nullptr) {
     ::vr::HmdError err;
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -277,17 +277,16 @@ VRManagerParent::RecvCreateVRTestSystem(
 }
 
 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;
--- a/xpcom/threads/nsThreadUtils.h
+++ b/xpcom/threads/nsThreadUtils.h
@@ -339,18 +339,16 @@ SpinEventLoopUntil(Pred&& aPredicate, ns
  * Returns true if we're in the compositor thread.
  *
  * We declare this here because the headers required to invoke
  * CompositorThreadHolder::IsInCompositorThread() also pull in a bunch of system
  * headers that #define various tokens in a way that can break the build.
  */
 extern bool NS_IsInCompositorThread();
 
-extern bool NS_IsInVRThread();
-
 //-----------------------------------------------------------------------------
 // Helpers that work with nsCOMPtr:
 
 inline already_AddRefed<nsIThread>
 do_GetCurrentThread()
 {
   nsIThread* thread = nullptr;
   NS_GetCurrentThread(&thread);