From 03cf16992f6cb965e27cca4501dbcdaac06166b1 Mon Sep 17 00:00:00 2001 From: Daosheng Mu Date: Thu, 26 Oct 2017 17:28:37 +0800 Subject: [PATCH] Bug 1406327 - Part 2: When loading VR content, launching the VR listener thread; r=kip MozReview-Commit-ID: IyBzJyDEVdv --HG-- extra : rebase_source : c4d11a77045d8baef94002e4f42e8cea5148e900 --- gfx/vr/VRManager.cpp | 50 ++++++++++++++++++++++++--- gfx/vr/VRManager.h | 8 +++-- gfx/vr/ipc/VRLayerParent.cpp | 12 ++----- gfx/vr/ipc/VRManagerChild.cpp | 2 +- gfx/vr/ipc/VRManagerParent.cpp | 62 +++++++++++++++++++++++----------- gfx/vr/ipc/VRManagerParent.h | 11 +++--- 6 files changed, 105 insertions(+), 40 deletions(-) diff --git a/gfx/vr/VRManager.cpp b/gfx/vr/VRManager.cpp index d09d61c1f5c9..315ddef06d1d 100644 --- a/gfx/vr/VRManager.cpp +++ b/gfx/vr/VRManager.cpp @@ -227,6 +227,7 @@ VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp) if (bHaveEventListener || bHaveControllerListener) { // We are using a VR device, keep it alive mLastActiveTime = TimeStamp::Now(); + mLastVRListenerThreadActiveTime = mLastActiveTime; } else if (mLastActiveTime.IsNull()) { Shutdown(); } else { @@ -259,7 +260,7 @@ void VRManager::RefreshVRDisplays(bool aMustDispatch) { nsTArray > 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, @@ -308,13 +309,20 @@ VRManager::RefreshVRDisplays(bool aMustDispatch) } if (displayInfoChanged || displaySetChanged || aMustDispatch) { - DispatchVRDisplayInfoUpdate(); + // Due to PVRManager is at Compositor thread. We have to post tasks + // to Compositor thread when sending to them the content processes. + MessageLoop* loop = CompositorThreadHolder::Loop(); + loop->PostTask( + NewRunnableMethod("gfx::VRManager::DispatchVRDisplayInfoUpdate", + this, + &VRManager::DispatchVRDisplayInfoUpdate)); } } void VRManager::DispatchVRDisplayInfoUpdate() { + MOZ_ASSERT(NS_IsInCompositorThread()); nsTArray update; GetVRDisplayInfo(update); @@ -323,7 +331,6 @@ VRManager::DispatchVRDisplayInfoUpdate() } } - /** * Get any VR displays that have already been enumerated without * activating any new devices. @@ -368,6 +375,12 @@ VRManager::GetVRControllerInfo(nsTArray& aControllerInfo) } } +TimeStamp +VRManager::GetLastVRListenerThreadActiveTime() +{ + return mLastVRListenerThreadActiveTime; +} + void VRManager::RefreshVRControllers() { @@ -442,8 +455,22 @@ VRManager::NotifyGamepadChange(uint32_t aIndex, const T& aInfo) dom::GamepadChangeEventBody body(aInfo); dom::GamepadChangeEvent e(aIndex, dom::GamepadServiceType::VR, body); + // Due to PVRManager is at Compositor thread. We have to post + // tasks to Compositor thread. + MessageLoop* loop = CompositorThreadHolder::Loop(); + loop->PostTask( + NewRunnableMethod( + "gfx::VRManager::NotifyGamepadChangeEventsToContent", + this, + &VRManager::NotifyGamepadChangeEventsToContent, e)); +} + +void +VRManager::NotifyGamepadChangeEventsToContent(const dom::GamepadChangeEvent& aEvent) +{ + MOZ_ASSERT(NS_IsInCompositorThread()); for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) { - Unused << iter.Get()->GetKey()->SendGamepadUpdate(e); + Unused << iter.Get()->GetKey()->SendGamepadUpdate(aEvent); } } @@ -469,6 +496,20 @@ VRManager::StopVibrateHaptic(uint32_t aControllerIdx) void VRManager::NotifyVibrateHapticCompleted(uint32_t aPromiseID) { + // Due to PVRManager is at Compositor thread. We have to post + // tasks to Compositor thread. + MessageLoop* loop = CompositorThreadHolder::Loop(); + loop->PostTask( + NewRunnableMethod( + "gfx::VRManager::NotifyVibrateHapticCompletedToContent", + this, + &VRManager::NotifyVibrateHapticCompletedToContent, aPromiseID)); +} + +void +VRManager::NotifyVibrateHapticCompletedToContent(uint32_t aPromiseID) +{ + MOZ_ASSERT(NS_IsInCompositorThread()); for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) { Unused << iter.Get()->GetKey()->SendReplyGamepadVibrateHaptic(aPromiseID); } @@ -477,6 +518,7 @@ VRManager::NotifyVibrateHapticCompleted(uint32_t aPromiseID) void VRManager::DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameResultInfo& aResult) { + MOZ_ASSERT(NS_IsInCompositorThread()); for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) { Unused << iter.Get()->GetKey()->SendDispatchSubmitFrameResult(aDisplayID, aResult); } diff --git a/gfx/vr/VRManager.h b/gfx/vr/VRManager.h index 7c79922ed442..b10fb9fd906d 100644 --- a/gfx/vr/VRManager.h +++ b/gfx/vr/VRManager.h @@ -15,8 +15,8 @@ #include "gfxVR.h" namespace mozilla { -namespace layers { -class TextureHost; +namespace dom { +class GamepadChangeEvent; } namespace gfx { @@ -52,6 +52,7 @@ public: void StopVibrateHaptic(uint32_t aControllerIdx); void NotifyVibrateHapticCompleted(uint32_t aPromiseID); void DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameResultInfo& aResult); + TimeStamp GetLastVRListenerThreadActiveTime(); protected: VRManager(); @@ -64,6 +65,8 @@ private: void Shutdown(); void DispatchVRDisplayInfoUpdate(); + void NotifyGamepadChangeEventsToContent(const dom::GamepadChangeEvent& aEvent); + void NotifyVibrateHapticCompletedToContent(uint32_t aPromiseID); typedef nsTHashtable> VRManagerParentSet; VRManagerParentSet mVRManagerParents; @@ -81,6 +84,7 @@ private: TimeStamp mLastRefreshTime; TimeStamp mLastActiveTime; + TimeStamp mLastVRListenerThreadActiveTime; bool mVRTestSystemCreated; }; diff --git a/gfx/vr/ipc/VRLayerParent.cpp b/gfx/vr/ipc/VRLayerParent.cpp index 4f04e574dc31..f8935536d89b 100644 --- a/gfx/vr/ipc/VRLayerParent.cpp +++ b/gfx/vr/ipc/VRLayerParent.cpp @@ -8,7 +8,6 @@ #include "VRLayerParent.h" #include "mozilla/Unused.h" #include "VRDisplayHost.h" -#include "mozilla/layers/CompositorThread.h" namespace mozilla { using namespace layers; @@ -65,18 +64,11 @@ VRLayerParent::RecvSubmitFrame(const layers::SurfaceDescriptor &aTexture, const gfx::Rect& aRightEyeRect) { if (mVRDisplayID) { - MessageLoop* loop = layers::CompositorThreadHolder::Loop(); VRManager* vm = VRManager::Get(); RefPtr display = vm->GetDisplay(mVRDisplayID); if (display) { - // 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( - "gfx::VRLayerParent::SubmitFrame", - this, - &VRLayerParent::SubmitFrame, display, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect)); + // TODO: Move SubmitFrame to VRSubmitFrame thread in Bug 1392217. + SubmitFrame(display, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect); } } diff --git a/gfx/vr/ipc/VRManagerChild.cpp b/gfx/vr/ipc/VRManagerChild.cpp index 03dc89771c0e..ce262f4185fa 100644 --- a/gfx/vr/ipc/VRManagerChild.cpp +++ b/gfx/vr/ipc/VRManagerChild.cpp @@ -118,7 +118,7 @@ VRManagerChild::InitSameProcess() sVRManagerChildSingleton = new VRManagerChild(); sVRManagerParentSingleton = VRManagerParent::CreateSameProcess(); sVRManagerChildSingleton->Open(sVRManagerParentSingleton->GetIPCChannel(), - VRListenerThreadHolder::Loop(), + mozilla::layers::CompositorThreadHolder::Loop(), mozilla::ipc::ChildSide); } diff --git a/gfx/vr/ipc/VRManagerParent.cpp b/gfx/vr/ipc/VRManagerParent.cpp index 0c5da625d7b7..38ac984cdb8c 100644 --- a/gfx/vr/ipc/VRManagerParent.cpp +++ b/gfx/vr/ipc/VRManagerParent.cpp @@ -86,15 +86,13 @@ VRManagerParent::UnregisterFromManager() /* static */ bool VRManagerParent::CreateForContent(Endpoint&& aEndpoint) { - MessageLoop* loop = VRListenerThreadHolder::Loop(); - + MessageLoop* loop = CompositorThreadHolder::Loop(); RefPtr vmp = new VRManagerParent(aEndpoint.OtherPid(), true); loop->PostTask(NewRunnableMethod&&>( "gfx::VRManagerParent::Bind", vmp, &VRManagerParent::Bind, Move(aEndpoint))); - return true; } @@ -110,7 +108,7 @@ VRManagerParent::Bind(Endpoint&& aEndpoint) } /*static*/ void -VRManagerParent::RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager) +VRManagerParent::RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager) { aVRManager->RegisterWithManager(); } @@ -118,21 +116,21 @@ VRManagerParent::RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager /*static*/ VRManagerParent* VRManagerParent::CreateSameProcess() { - MessageLoop* loop = VRListenerThreadHolder::Loop(); + MessageLoop* loop = CompositorThreadHolder::Loop(); RefPtr vmp = new VRManagerParent(base::GetCurrentProcId(), false); - vmp->mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton(); + vmp->mCompositorThreadHolder = CompositorThreadHolder::GetSingleton(); vmp->mSelfRef = vmp; - loop->PostTask(NewRunnableFunction(RegisterVRManagerInVRListenerThread, vmp.get())); + loop->PostTask(NewRunnableFunction(RegisterVRManagerInCompositorThread, vmp.get())); return vmp.get(); } bool VRManagerParent::CreateForGPUProcess(Endpoint&& aEndpoint) { - MessageLoop* loop = VRListenerThreadHolder::Loop(); + MessageLoop* loop = CompositorThreadHolder::Loop(); RefPtr vmp = new VRManagerParent(aEndpoint.OtherPid(), false); - vmp->mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton(); + vmp->mCompositorThreadHolder = CompositorThreadHolder::GetSingleton(); loop->PostTask(NewRunnableMethod&&>( "gfx::VRManagerParent::Bind", vmp, @@ -144,10 +142,25 @@ VRManagerParent::CreateForGPUProcess(Endpoint&& aEndpoint) void VRManagerParent::DeferredDestroy() { - mVRListenerThreadHolder = nullptr; + mCompositorThreadHolder = nullptr; mSelfRef = nullptr; } +void +VRManagerParent::RefreshDisplays() +{ + // 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(); + MessageLoop* loop = VRListenerThreadHolder::Loop(); + loop->PostTask( + NewRunnableMethod( + "gfx::VRManager::RefreshVRDisplays", + vm, &VRManager::RefreshVRDisplays, true)); +} + void VRManagerParent::ActorDestroy(ActorDestroyReason why) { @@ -161,21 +174,25 @@ VRManagerParent::ActorDestroy(ActorDestroyReason why) void VRManagerParent::OnChannelConnected(int32_t aPid) { - mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton(); + mCompositorThreadHolder = CompositorThreadHolder::GetSingleton(); } mozilla::ipc::IPCResult VRManagerParent::RecvRefreshDisplays() { - // TODO: Bug 1406327, Launch VR listener thread here. - MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread()); + MOZ_ASSERT(NS_IsInCompositorThread()); - // 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); + // When receiving refresh display messages at the first time, + // it is time to start the VR listener thread. + // Spawning threads needs to be at the main thread. + if (!VRListenerThreadHolder::IsActive()) { + RefPtr runnable = NewRunnableMethod( + "gfx::VRManagerParent::StartVRListenerThread", + this, &VRManagerParent::StartVRListenerThread); + NS_DispatchToMainThread(runnable.forget()); + } else { + RefreshDisplays(); + } return IPC_OK(); } @@ -203,6 +220,13 @@ VRManagerParent::RecvSetGroupMask(const uint32_t& aDisplayID, const uint32_t& aG return IPC_OK(); } +void +VRManagerParent::StartVRListenerThread() +{ + VRListenerThreadHolder::Start(); + RefreshDisplays(); +} + bool VRManagerParent::HaveEventListener() { diff --git a/gfx/vr/ipc/VRManagerParent.h b/gfx/vr/ipc/VRManagerParent.h index 9129a3bbbef0..9a405051a23c 100644 --- a/gfx/vr/ipc/VRManagerParent.h +++ b/gfx/vr/ipc/VRManagerParent.h @@ -7,7 +7,7 @@ #ifndef MOZILLA_GFX_VR_VRMANAGERPARENT_H #define MOZILLA_GFX_VR_VRMANAGERPARENT_H -#include "mozilla/layers/CompositableTransactionParent.h" // need? +#include "mozilla/layers/CompositorThread.h" // for CompositorThreadHolder #include "mozilla/gfx/PVRManagerParent.h" // for PVRManagerParent #include "mozilla/gfx/PVRLayerParent.h" // for PVRLayerParent #include "mozilla/ipc/ProtocolUtils.h" // for IToplevelProtocol @@ -16,7 +16,6 @@ #include "VRThread.h" // for VRListenerThreadHolder namespace mozilla { -using namespace layers; namespace gfx { class VRManager; @@ -41,6 +40,7 @@ public: bool HaveControllerListener(); bool SendGamepadUpdate(const GamepadChangeEvent& aGamepadEvent); bool SendReplyGamepadVibrateHaptic(const uint32_t& aPromiseID); + void StartVRListenerThread(); protected: ~VRManagerParent(); @@ -80,14 +80,17 @@ private: void Bind(Endpoint&& aEndpoint); - static void RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager); + static void RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager); void DeferredDestroy(); + void RefreshDisplays(); // This keeps us alive until ActorDestroy(), at which point we do a // deferred destruction of ourselves. RefPtr mSelfRef; - RefPtr mVRListenerThreadHolder; + + // Keep the compositor thread alive, until we have destroyed ourselves. + RefPtr mCompositorThreadHolder; // Keep the VRManager alive, until we have destroyed ourselves. RefPtr mVRManagerHolder;