Bug 1392216 - Part 2: Support VR listener thread in VR; r?kip draft
authorDaosheng Mu <daoshengmu@gmail.com>
Thu, 05 Oct 2017 18:16:16 +0800
changeset 679936 5b09a3271874b6ac88608ae866d3190239018bb5
parent 679935 2f0fc103f93611aa70272a68da98333f09199cbb
child 679937 eb17cd9f1b09a9f325c94464c41581a209f8be2c
push id84349
push userbmo:dmu@mozilla.com
push dateFri, 13 Oct 2017 07:51:03 +0000
reviewerskip
bugs1392216
milestone58.0a1
Bug 1392216 - Part 2: Support VR listener thread in VR; r?kip MozReview-Commit-ID: 62PZ5opXoZ6
gfx/vr/VRDisplayHost.cpp
gfx/vr/VRManager.cpp
gfx/vr/gfxVROculus.cpp
gfx/vr/gfxVROpenVR.cpp
gfx/vr/ipc/VRLayerParent.cpp
gfx/vr/ipc/VRLayerParent.h
gfx/vr/ipc/VRManagerChild.cpp
gfx/vr/ipc/VRManagerParent.cpp
gfx/vr/ipc/VRManagerParent.h
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -3,16 +3,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 "VRDisplayHost.h"
 #include "gfxVR.h"
 #include "ipc/VRLayerParent.h"
 #include "mozilla/layers/TextureHost.h"
 #include "mozilla/dom/GamepadBinding.h" // For GamepadMappingType
+#include "VRThread.h"
 
 #if defined(XP_WIN)
 
 #include <d3d11.h>
 #include "gfxWindowsPlatform.h"
 #include "../layers/d3d11/CompositorD3D11.h"
 #include "mozilla/gfx/DeviceManagerDx.h"
 #include "mozilla/layers/TextureD3D11.h"
@@ -340,30 +341,33 @@ VRDisplayHost::SubmitFrame(VRLayerParent
 #endif
     default: {
       NS_WARNING("Unsupported SurfaceDescriptor type for VR layer texture");
       return;
     }
   }
 
 #if defined(XP_WIN) || defined(XP_MACOSX)
-
   /**
    * Trigger the next VSync immediately after we are successfully
    * submitting frames.  As SubmitFrame is responsible for throttling
    * the render loop, if we don't successfully call it, we shouldn't trigger
    * NotifyVRVsync immediately, as it will run unbounded.
    * If NotifyVRVsync is not called here due to SubmitFrame failing, the
    * fallback "watchdog" code in VRDisplayHost::NotifyVSync() will cause
    * frames to continue at a lower refresh rate until frame submission
    * succeeds again.
    */
-  VRManager *vm = VRManager::Get();
-  MOZ_ASSERT(vm);
-  vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
+  VRManager* vm = VRManager::Get();
+  MessageLoop* loop = VRListenerThreadHolder::Loop();
+
+  loop->PostTask(NewRunnableMethod<const uint32_t>(
+    "gfx::VRLayerParent::SubmitFrame",
+    vm, &VRManager::NotifyVRVsync, mDisplayInfo.mDisplayID
+  ));
 #endif
 }
 
 bool
 VRDisplayHost::CheckClearDisplayInfoDirty()
 {
   if (mDisplayInfo == mLastUpdateDisplayInfo) {
     return false;
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -1,21 +1,23 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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 "VRManager.h"
 #include "VRManagerParent.h"
+#include "VRThread.h"
 #include "gfxVR.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/VRDisplay.h"
 #include "mozilla/dom/GamepadEventTypes.h"
 #include "mozilla/layers/TextureHost.h"
+#include "mozilla/layers/CompositorThread.h"
 #include "mozilla/Unused.h"
 
 #include "gfxPrefs.h"
 #include "gfxVR.h"
 #if defined(XP_WIN)
 #include "gfxVROculus.h"
 #endif
 #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
@@ -156,16 +158,17 @@ VRManager::RemoveVRManagerParent(VRManag
   if (mVRManagerParents.IsEmpty()) {
     Destroy();
   }
 }
 
 void
 VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
 {
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
   const double kVRDisplayRefreshMaxDuration = 5000; // milliseconds
   const double kVRDisplayInactiveMaxDuration = 30000; // milliseconds
 
   bool bHaveEventListener = false;
   bool bHaveControllerListener = false;
 
   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     VRManagerParent *vmp = iter.Get()->GetKey();
@@ -231,16 +234,17 @@ VRManager::NotifyVsync(const TimeStamp& 
       Shutdown();
     }
   }
 }
 
 void
 VRManager::NotifyVRVsync(const uint32_t& aDisplayID)
 {
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
   for (const auto& manager: mManagers) {
     if (manager->GetIsPresenting()) {
       manager->HandleInput();
     }
   }
 
   RefPtr<VRDisplayHost> display = GetDisplay(aDisplayID);
   if (display) {
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -22,18 +22,18 @@
 
 #include "mozilla/gfx/Quaternion.h"
 
 #include <d3d11.h>
 #include "CompositorD3D11.h"
 #include "TextureD3D11.h"
 
 #include "gfxVROculus.h"
+#include "VRThread.h"
 
-#include "mozilla/layers/CompositorThread.h"
 #include "mozilla/dom/GamepadEventTypes.h"
 #include "mozilla/dom/GamepadBinding.h"
 #include "mozilla/Telemetry.h"
 
 /** XXX The DX11 objects and quad blitting could be encapsulated
  *    into a separate object if either Oculus starts supporting
  *     non-Windows platforms or the blit is needed by other HMD\
  *     drivers.
@@ -1380,19 +1380,19 @@ VRControllerOculus::VibrateHapticComplet
       printf_stderr("%s Haptics skipped.\n",
                     GamepadHandValues::strings[uint32_t(GetHand())].value);
     }
   }
 
   VRManager *vm = VRManager::Get();
   MOZ_ASSERT(vm);
 
-  CompositorThreadHolder::Loop()->PostTask(NewRunnableMethod<uint32_t>(
-                                             "VRManager::NotifyVibrateHapticCompleted",
-                                             vm, &VRManager::NotifyVibrateHapticCompleted, aPromiseID));
+  VRListenerThreadHolder::Loop()->PostTask(NewRunnableMethod<uint32_t>(
+                                           "VRManager::NotifyVibrateHapticCompleted",
+                                           vm, &VRManager::NotifyVibrateHapticCompleted, aPromiseID));
 }
 
 void
 VRControllerOculus::VibrateHaptic(ovrSession aSession,
                                   uint32_t aHapticIndex,
                                   double aIntensity,
                                   double aDuration,
                                   uint32_t aPromiseID)
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -16,21 +16,21 @@
 #include "CompositorD3D11.h"
 #include "TextureD3D11.h"
 #elif defined(XP_MACOSX)
 #include "mozilla/gfx/MacIOSurface.h"
 #endif
 
 #include "gfxVROpenVR.h"
 #include "VRManager.h"
+#include "VRThread.h"
 
 #include "nsServiceManagerUtils.h"
 #include "nsIScreenManager.h"
 
-#include "mozilla/layers/CompositorThread.h"
 #include "mozilla/dom/GamepadEventTypes.h"
 #include "mozilla/dom/GamepadBinding.h"
 #include "mozilla/Telemetry.h"
 
 #ifndef M_PI
 # define M_PI 3.14159265358979323846
 #endif
 
@@ -526,19 +526,19 @@ VRControllerOpenVR::UpdateVibrateHaptic(
   }
 }
 
 void
 VRControllerOpenVR::VibrateHapticComplete(uint32_t aPromiseID)
 {
   VRManager *vm = VRManager::Get();
 
-  CompositorThreadHolder::Loop()->PostTask(NewRunnableMethod<uint32_t>
-    ("VRManager::NotifyVibrateHapticCompleted",
-     vm, &VRManager::NotifyVibrateHapticCompleted, aPromiseID));
+  VRListenerThreadHolder::Loop()->PostTask(NewRunnableMethod<uint32_t>(
+                                           "VRManager::NotifyVibrateHapticCompleted",
+                                           vm, &VRManager::NotifyVibrateHapticCompleted, aPromiseID));
 }
 
 void
 VRControllerOpenVR::VibrateHaptic(::vr::IVRSystem* aVRSystem,
                                   uint32_t aHapticIndex,
                                   double aIntensity,
                                   double aDuration,
                                   uint32_t aPromiseID)
--- a/gfx/vr/ipc/VRLayerParent.cpp
+++ b/gfx/vr/ipc/VRLayerParent.cpp
@@ -2,18 +2,20 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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 "VRLayerParent.h"
 #include "mozilla/Unused.h"
 #include "VRDisplayHost.h"
+#include "mozilla/layers/CompositorThread.h"
 
 namespace mozilla {
+using namespace layers;
 namespace gfx {
 
 VRLayerParent::VRLayerParent(uint32_t aVRDisplayID, const uint32_t aGroup)
   : mIPCOpen(true)
   , mVRDisplayID(aVRDisplayID)
   , mGroup(aGroup)
 {
 }
@@ -57,22 +59,36 @@ VRLayerParent::Destroy()
 
 mozilla::ipc::IPCResult
 VRLayerParent::RecvSubmitFrame(const layers::SurfaceDescriptor &aTexture,
                                const uint64_t& aFrameId,
                                const gfx::Rect& aLeftEyeRect,
                                const gfx::Rect& aRightEyeRect)
 {
   if (mVRDisplayID) {
+    MessageLoop* loop = layers::CompositorThreadHolder::Loop();
     VRManager* vm = VRManager::Get();
     RefPtr<VRDisplayHost> display = vm->GetDisplay(mVRDisplayID);
     if (display) {
-      display->SubmitFrame(this, aTexture, aFrameId,
-                           aLeftEyeRect, aRightEyeRect);
+      // Because VR compositor still shares the same graphics device with Compositor thread.
+      // We have to post sumbit frame tasks to Compositor thread.
+      // TODO: Move SubmitFrame to Bug 1392217.
+      loop->PostTask(NewRunnableMethod<VRDisplayHost*, const layers::SurfaceDescriptor&, uint64_t,
+                                       const gfx::Rect&, const gfx::Rect&>(
+                     "gfx::VRLayerParent::SubmitFrame",
+                     this,
+                     &VRLayerParent::SubmitFrame, display, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect));
     }
   }
 
   return IPC_OK();
 }
 
+void
+VRLayerParent::SubmitFrame(VRDisplayHost* aDisplay, const layers::SurfaceDescriptor& aTexture,
+                           uint64_t aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect)
+{
+  aDisplay->SubmitFrame(this, aTexture, aFrameId,
+                        aLeftEyeRect, aRightEyeRect);
+}
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/vr/ipc/VRLayerParent.h
+++ b/gfx/vr/ipc/VRLayerParent.h
@@ -34,14 +34,18 @@ protected:
   void Destroy();
 
   bool mIPCOpen;
 
   uint32_t mVRDisplayID;
   gfx::Rect mLeftEyeRect;
   gfx::Rect mRightEyeRect;
   uint32_t mGroup;
+
+private:
+  void SubmitFrame(VRDisplayHost* aDisplay, const layers::SurfaceDescriptor& aTexture,
+                   uint64_t aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect);
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -2,16 +2,17 @@
  * vim: sw=2 ts=8 et :
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 "VRManagerChild.h"
 #include "VRManagerParent.h"
+#include "VRThread.h"
 #include "VRDisplayClient.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/StaticPtr.h"
 #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"
@@ -114,17 +115,17 @@ VRManagerChild::ReinitForContent(Endpoin
 VRManagerChild::InitSameProcess()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!sVRManagerChildSingleton);
 
   sVRManagerChildSingleton = new VRManagerChild();
   sVRManagerParentSingleton = VRManagerParent::CreateSameProcess();
   sVRManagerChildSingleton->Open(sVRManagerParentSingleton->GetIPCChannel(),
-                                 mozilla::layers::CompositorThreadHolder::Loop(),
+                                 VRListenerThreadHolder::Loop(),
                                  mozilla::ipc::ChildSide);
 }
 
 /* static */ void
 VRManagerChild::InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!sVRManagerChildSingleton);
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -6,19 +6,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "VRManagerParent.h"
 #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 "VRThread.h"
 #include "gfxVRPuppet.h"
 
 namespace mozilla {
 using namespace layers;
 namespace gfx {
 
 VRManagerParent::VRManagerParent(ProcessId aChildProcessId, bool aIsContentChild)
   : mDisplayTestID(0)
@@ -82,17 +82,17 @@ VRManagerParent::UnregisterFromManager()
   VRManager* vm = VRManager::Get();
   vm->RemoveVRManagerParent(this);
   mVRManagerHolder = nullptr;
 }
 
 /* static */ bool
 VRManagerParent::CreateForContent(Endpoint<PVRManagerParent>&& aEndpoint)
 {
-  MessageLoop* loop = layers::CompositorThreadHolder::Loop();
+  MessageLoop* loop = VRListenerThreadHolder::Loop();
 
   RefPtr<VRManagerParent> vmp = new VRManagerParent(aEndpoint.OtherPid(), true);
   loop->PostTask(NewRunnableMethod<Endpoint<PVRManagerParent>&&>(
     "gfx::VRManagerParent::Bind",
     vmp,
     &VRManagerParent::Bind,
     Move(aEndpoint)));
 
@@ -106,73 +106,76 @@ VRManagerParent::Bind(Endpoint<PVRManage
     return;
   }
   mSelfRef = this;
 
   RegisterWithManager();
 }
 
 /*static*/ void
-VRManagerParent::RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager)
+VRManagerParent::RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager)
 {
   aVRManager->RegisterWithManager();
 }
 
 /*static*/ VRManagerParent*
 VRManagerParent::CreateSameProcess()
 {
-  MessageLoop* loop = mozilla::layers::CompositorThreadHolder::Loop();
+  MessageLoop* loop = VRListenerThreadHolder::Loop();
   RefPtr<VRManagerParent> vmp = new VRManagerParent(base::GetCurrentProcId(), false);
-  vmp->mCompositorThreadHolder = layers::CompositorThreadHolder::GetSingleton();
+  vmp->mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton();
   vmp->mSelfRef = vmp;
-  loop->PostTask(NewRunnableFunction(RegisterVRManagerInCompositorThread, vmp.get()));
+  loop->PostTask(NewRunnableFunction(RegisterVRManagerInVRListenerThread, vmp.get()));
   return vmp.get();
 }
 
 bool
 VRManagerParent::CreateForGPUProcess(Endpoint<PVRManagerParent>&& aEndpoint)
 {
-  MessageLoop* loop = mozilla::layers::CompositorThreadHolder::Loop();
+  MessageLoop* loop = VRListenerThreadHolder::Loop();
 
   RefPtr<VRManagerParent> vmp = new VRManagerParent(aEndpoint.OtherPid(), false);
-  vmp->mCompositorThreadHolder = layers::CompositorThreadHolder::GetSingleton();
+  vmp->mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton();
   loop->PostTask(NewRunnableMethod<Endpoint<PVRManagerParent>&&>(
     "gfx::VRManagerParent::Bind",
     vmp,
     &VRManagerParent::Bind,
     Move(aEndpoint)));
   return true;
 }
 
 void
 VRManagerParent::DeferredDestroy()
 {
-  mCompositorThreadHolder = nullptr;
+  mVRListenerThreadHolder = nullptr;
   mSelfRef = nullptr;
 }
 
 void
 VRManagerParent::ActorDestroy(ActorDestroyReason why)
 {
   UnregisterFromManager();
   MessageLoop::current()->PostTask(
     NewRunnableMethod("gfx::VRManagerParent::DeferredDestroy",
                       this,
                       &VRManagerParent::DeferredDestroy));
 }
 
 void
 VRManagerParent::OnChannelConnected(int32_t aPid)
 {
-  mCompositorThreadHolder = layers::CompositorThreadHolder::GetSingleton();
+  mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton();
 }
 
 mozilla::ipc::IPCResult
 VRManagerParent::RecvRefreshDisplays()
 {
+  // TODO: Bug 1406327, Launch VR listener thread here.
+  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
+
   // This is called to refresh the VR Displays for Navigator.GetVRDevices().
   // We must pass "true" to VRManager::RefreshVRDisplays()
   // to ensure that the promise returned by Navigator.GetVRDevices
   // can resolve even if there are no changes to the VR Displays.
   VRManager* vm = VRManager::Get();
   vm->RefreshVRDisplays(true);
 
   return IPC_OK();
--- a/gfx/vr/ipc/VRManagerParent.h
+++ b/gfx/vr/ipc/VRManagerParent.h
@@ -3,23 +3,23 @@
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 #ifndef MOZILLA_GFX_VR_VRMANAGERPARENT_H
 #define MOZILLA_GFX_VR_VRMANAGERPARENT_H
 
-#include "mozilla/layers/CompositableTransactionParent.h"
-#include "mozilla/layers/CompositorThread.h" // for CompositorThreadHolder
+#include "mozilla/layers/CompositableTransactionParent.h"  // need?
 #include "mozilla/gfx/PVRManagerParent.h" // for PVRManagerParent
 #include "mozilla/gfx/PVRLayerParent.h"   // for PVRLayerParent
 #include "mozilla/ipc/ProtocolUtils.h"    // for IToplevelProtocol
 #include "mozilla/TimeStamp.h"            // for TimeStamp
 #include "gfxVR.h"                        // for VRFieldOfView
+#include "VRThread.h"                     // for VRListenerThreadHolder
 
 namespace mozilla {
 using namespace layers;
 namespace gfx {
 
 class VRManager;
 
 namespace impl {
@@ -76,26 +76,24 @@ protected:
   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);
+  static void RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager);
 
   void DeferredDestroy();
 
   // This keeps us alive until ActorDestroy(), at which point we do a
   // deferred destruction of ourselves.
   RefPtr<VRManagerParent> mSelfRef;
-
-  // Keep the compositor thread alive, until we have destroyed ourselves.
-  RefPtr<layers::CompositorThreadHolder> mCompositorThreadHolder;
+  RefPtr<VRListenerThreadHolder> mVRListenerThreadHolder;
 
   // 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;