Bug 1494556 - Remove VRListenerThread r=daoshengmu

We are refactoring much of the code in gfx/vr, moving
most of the code that runs in the VRListenerThread into
it's own process.  The remaining code will be non-blocking
once this refactoring is complete.

In order to resolve some shutdown crashes, it is simpler
to remove the VRListenerThread and the related code
starting and stopping this thread.  If this is done
prior to completion of the refactoring for Bug 1473399
(Enable VRService thread by default), there would be a
regression in responsiveness during detection of VR
hardware due to blocking API calls moving off the thread.

Differential Revision: https://phabricator.services.mozilla.com/D7227

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kearwood Gilbert 2018-10-02 21:17:05 +00:00
Родитель dcea35a098
Коммит 7a3eb1a6a2
16 изменённых файлов: 36 добавлений и 220 удалений

Просмотреть файл

@ -46,7 +46,6 @@
#include "VRGPUChild.h"
#include "VRManager.h"
#include "VRManagerParent.h"
#include "VRThread.h"
#include "VsyncBridgeParent.h"
#if defined(XP_WIN)
# include "mozilla/gfx/DeviceManagerDx.h"
@ -134,8 +133,6 @@ GPUParent::Init(base::ProcessId aParentPid,
}
CompositorThreadHolder::Start();
// TODO: Bug 1406327, Start VRListenerThreadHolder when loading VR content.
VRListenerThreadHolder::Start();
APZThreadUtils::SetControllerThread(MessageLoop::current());
apz::InitializeGlobalState();
LayerTreeOwnerTracker::Initialize();
@ -533,7 +530,6 @@ GPUParent::ActorDestroy(ActorDestroyReason aWhy)
}
dom::VideoDecoderManagerParent::ShutdownVideoBridge();
CompositorThreadHolder::Shutdown();
VRListenerThreadHolder::Shutdown();
// There is a case that RenderThread exists when gfxVars::UseWebRender() is false.
// This could happen when WebRender was fallbacked to compositor.
if (wr::RenderThread::Get()) {

Просмотреть файл

@ -35,7 +35,6 @@
#endif
#include "mozilla/widget/CompositorWidget.h"
#include "VRManager.h"
#include "VRThread.h"
namespace mozilla {
@ -82,8 +81,8 @@ CompositorVsyncScheduler::CompositorVsyncScheduler(CompositorVsyncSchedulerOwner
, mWidget(aWidget)
, mCurrentCompositeTaskMonitor("CurrentCompositeTaskMonitor")
, mCurrentCompositeTask(nullptr)
, mCurrentVRListenerTaskMonitor("CurrentVRTaskMonitor")
, mCurrentVRListenerTask(nullptr)
, mCurrentVRTaskMonitor("CurrentVRTaskMonitor")
, mCurrentVRTask(nullptr)
{
mVsyncObserver = new Observer(this);
@ -137,15 +136,15 @@ CompositorVsyncScheduler::PostCompositeTask(TimeStamp aCompositeTimestamp)
void
CompositorVsyncScheduler::PostVRTask(TimeStamp aTimestamp)
{
MonitorAutoLock lockVR(mCurrentVRListenerTaskMonitor);
if (mCurrentVRListenerTask == nullptr && VRListenerThreadHolder::Loop()) {
MonitorAutoLock lockVR(mCurrentVRTaskMonitor);
if (mCurrentVRTask == nullptr && CompositorThreadHolder::Loop()) {
RefPtr<Runnable> task = NewRunnableMethod<TimeStamp>(
"layers::CompositorVsyncScheduler::DispatchVREvents",
this,
&CompositorVsyncScheduler::DispatchVREvents,
aTimestamp);
mCurrentVRListenerTask = task;
VRListenerThreadHolder::Loop()->PostDelayedTask(task.forget(), 0);
mCurrentVRTask = task;
CompositorThreadHolder::Loop()->PostDelayedTask(task.forget(), 0);
}
}
@ -320,13 +319,13 @@ void
CompositorVsyncScheduler::DispatchVREvents(TimeStamp aVsyncTimestamp)
{
{
MonitorAutoLock lock(mCurrentVRListenerTaskMonitor);
mCurrentVRListenerTask = nullptr;
MonitorAutoLock lock(mCurrentVRTaskMonitor);
mCurrentVRTask = nullptr;
}
// This only allows to be called by CompositorVsyncScheduler::PostVRTask()
// When the process is going to shutdown, the runnable has chance to be executed
// by other threads, we only want it to be run at VRListenerThread.
if (!VRListenerThreadHolder::IsInVRListenerThread()) {
// by other threads, we only want it to be run in the compositor thread.
if (!CompositorThreadHolder::IsInCompositorThread()) {
return;
}

Просмотреть файл

@ -149,8 +149,8 @@ private:
mozilla::Monitor mCurrentCompositeTaskMonitor;
RefPtr<CancelableRunnable> mCurrentCompositeTask;
mozilla::Monitor mCurrentVRListenerTaskMonitor;
RefPtr<Runnable> mCurrentVRListenerTask;
mozilla::Monitor mCurrentVRTaskMonitor;
RefPtr<Runnable> mCurrentVRTask;
};
} // namespace layers

Просмотреть файл

@ -1170,7 +1170,6 @@ gfxPlatform::InitLayersIPC()
}
layers::CompositorThreadHolder::Start();
gfx::VRListenerThreadHolder::Start();
}
}
@ -1199,7 +1198,6 @@ gfxPlatform::ShutdownLayersIPC()
layers::ImageBridgeChild::ShutDown();
// This has to happen after shutting down the child protocols.
layers::CompositorThreadHolder::Shutdown();
gfx::VRListenerThreadHolder::Shutdown();
image::ImageMemoryReporter::ShutdownForWebRender();
// There is a case that RenderThread exists when gfxVars::UseWebRender() is false.
// This could happen when WebRender was fallbacked to compositor.

Просмотреть файл

@ -8,6 +8,7 @@
#include "gfxPrefs.h"
#include "gfxVR.h"
#include "ipc/VRLayerParent.h"
#include "mozilla/layers/CompositorThread.h" // for CompositorThreadHolder
#include "mozilla/layers/TextureHost.h"
#include "mozilla/dom/GamepadBinding.h" // For GamepadMappingType
#include "VRThread.h"
@ -342,7 +343,7 @@ VRDisplayHost::SubmitFrameInternal(const layers::SurfaceDescriptor &aTexture,
* succeeds again.
*/
VRManager* vm = VRManager::Get();
MessageLoop* loop = VRListenerThreadHolder::Loop();
MessageLoop* loop = CompositorThreadHolder::Loop();
loop->PostTask(NewRunnableMethod<const uint32_t>(
"gfx::VRManager::NotifyVRVsync",

Просмотреть файл

@ -263,8 +263,6 @@ VRManager::UpdateRequestedDevices()
void
VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
{
MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
for (const auto& manager : mManagers) {
manager->NotifyVSync();
}
@ -273,11 +271,10 @@ VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
void
VRManager::StartTasks()
{
MOZ_ASSERT(VRListenerThread());
if (!mTaskTimer) {
mTaskInterval = GetOptimalTaskInterval();
mTaskTimer = NS_NewTimer();
mTaskTimer->SetTarget(VRListenerThreadHolder::Loop()->SerialEventTarget());
mTaskTimer->SetTarget(CompositorThreadHolder::Loop()->SerialEventTarget());
mTaskTimer->InitWithNamedFuncCallback(
TaskTimerCallback,
this,
@ -291,20 +288,11 @@ void
VRManager::StopTasks()
{
if (mTaskTimer) {
MOZ_ASSERT(VRListenerThread());
mTaskTimer->Cancel();
mTaskTimer = nullptr;
}
}
/*static*/ void
VRManager::StopVRListenerThreadTasks()
{
if (sVRManagerSingleton) {
sVRManagerSingleton->StopTasks();
}
}
/*static*/ void
VRManager::TaskTimerCallback(nsITimer* aTimer, void* aClosure)
{
@ -322,13 +310,6 @@ VRManager::TaskTimerCallback(nsITimer* aTimer, void* aClosure)
void
VRManager::RunTasks()
{
// During shutdown, this might be called outside of the
// VR Listener Thread; however, we no longer need to
// execute any tasks during this time.
if (!VRListenerThreadHolder::IsInVRListenerThread()) {
return;
}
// Will be called once every 1ms when a VR presentation
// is active or once per vsync when a VR presentation is
// not active.
@ -397,8 +378,6 @@ VRManager::GetOptimalTaskInterval()
void
VRManager::Run1msTasks(double aDeltaTime)
{
MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
for (const auto& manager : mManagers) {
manager->Run1msTasks(aDeltaTime);
}
@ -419,8 +398,6 @@ VRManager::Run1msTasks(double aDeltaTime)
void
VRManager::Run10msTasks()
{
MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
UpdateRequestedDevices();
for (const auto& manager : mManagers) {
@ -443,8 +420,6 @@ VRManager::Run10msTasks()
void
VRManager::Run100msTasks()
{
MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
// We must continually refresh the VR display enumeration to check
// for events that we must fire such as Window.onvrdisplayconnect
// Note that enumeration itself may activate display hardware, such
@ -495,7 +470,6 @@ VRManager::CheckForInactiveTimeout()
void
VRManager::NotifyVRVsync(const uint32_t& aDisplayID)
{
MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
for (const auto& manager: mManagers) {
if (manager->GetIsPresenting()) {
manager->HandleInput();

Просмотреть файл

@ -63,7 +63,6 @@ public:
void DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameResultInfo& aResult);
void StartVRNavigation(const uint32_t& aDisplayID);
void StopVRNavigation(const uint32_t& aDisplayID, const TimeDuration& aTimeout);
static void StopVRListenerThreadTasks();
protected:
VRManager();

Просмотреть файл

@ -14,123 +14,9 @@ namespace mozilla {
namespace gfx {
static StaticRefPtr<VRListenerThreadHolder> sVRListenerThreadHolder;
static bool sFinishedVRListenerShutDown = true;
static const uint32_t kDefaultThreadLifeTime = 60; // in 60 seconds.
static const uint32_t kDelayPostTaskTime = 20000; // in 20000 ms.
VRListenerThreadHolder* GetVRListenerThreadHolder()
{
return sVRListenerThreadHolder;
}
base::Thread*
VRListenerThread()
{
return sVRListenerThreadHolder
? sVRListenerThreadHolder->GetThread()
: nullptr;
}
/* static */ MessageLoop*
VRListenerThreadHolder::Loop()
{
return VRListenerThread() ? VRListenerThread()->message_loop() : nullptr;
}
VRListenerThreadHolder*
VRListenerThreadHolder::GetSingleton()
{
return sVRListenerThreadHolder;
}
VRListenerThreadHolder::VRListenerThreadHolder()
: mThread(CreateThread())
{
MOZ_ASSERT(NS_IsMainThread());
}
VRListenerThreadHolder::~VRListenerThreadHolder()
{
MOZ_ASSERT(NS_IsMainThread());
if (mThread) {
DestroyThread(mThread);
}
}
/* static */ void
VRListenerThreadHolder::DestroyThread(base::Thread* aThread)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!sVRListenerThreadHolder,
"We shouldn't be destroying the VR listener thread yet.");
delete aThread;
sFinishedVRListenerShutDown = true;
}
/* static */ base::Thread*
VRListenerThreadHolder::CreateThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!sVRListenerThreadHolder, "The VR listener thread has already been started!");
base::Thread* vrThread = new base::Thread("VRListener");
base::Thread::Options options;
/* Timeout values are powers-of-two to enable us get better data.
128ms is chosen for transient hangs because 8Hz should be the minimally
acceptable goal for Compositor responsiveness (normal goal is 60Hz). */
options.transient_hang_timeout = 128; // milliseconds
/* 2048ms is chosen for permanent hangs because it's longer than most
* Compositor hangs seen in the wild, but is short enough to not miss getting
* native hang stacks. */
options.permanent_hang_timeout = 2048; // milliseconds
if (!vrThread->StartWithOptions(options)) {
delete vrThread;
return nullptr;
}
return vrThread;
}
void
VRListenerThreadHolder::Start()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread!");
MOZ_ASSERT(!sVRListenerThreadHolder, "The VR listener thread has already been started!");
sFinishedVRListenerShutDown = false;
sVRListenerThreadHolder = new VRListenerThreadHolder();
if (!sVRListenerThreadHolder->GetThread()) {
MOZ_ASSERT(false, "VR listener thread not started.");
sVRListenerThreadHolder = nullptr;
}
}
void
VRListenerThreadHolder::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread!");
VRManager::StopVRListenerThreadTasks();
if (!sVRListenerThreadHolder) {
// We've already shutdown or never started.
return;
}
sVRListenerThreadHolder = nullptr;
SpinEventLoopUntil([&]() { return sFinishedVRListenerShutDown; });
}
/* static */ bool
VRListenerThreadHolder::IsInVRListenerThread()
{
return VRListenerThread() &&
VRListenerThread()->thread_id() == PlatformThread::CurrentId();
}
VRThread::VRThread(const nsCString& aName)
: mThread(nullptr)
, mLifeTime(kDefaultThreadLifeTime)
@ -147,8 +33,6 @@ VRThread::~VRThread()
void
VRThread::Start()
{
MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
if (!mThread) {
nsresult rv = NS_NewNamedThread(mName, getter_AddRefs(mThread));
MOZ_ASSERT(mThread);

Просмотреть файл

@ -13,39 +13,6 @@
namespace mozilla {
namespace gfx {
class VRListenerThreadHolder final
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(VRListenerThreadHolder)
public:
VRListenerThreadHolder();
base::Thread* GetThread() const {
return mThread;
}
static VRListenerThreadHolder* GetSingleton();
static bool IsActive() {
return GetSingleton() && Loop();
}
static void Start();
static void Shutdown();
static MessageLoop* Loop();
static bool IsInVRListenerThread();
private:
~VRListenerThreadHolder();
base::Thread* const mThread;
static base::Thread* CreateThread();
static void DestroyThread(base::Thread* aThread);
};
base::Thread* VRListenerThread();
class VRThread final
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRThread)

Просмотреть файл

@ -1492,7 +1492,7 @@ VRControllerOculus::VibrateHapticComplete(ovrSession aSession, const VRManagerPr
VRManager *vm = VRManager::Get();
MOZ_ASSERT(vm);
VRListenerThreadHolder::Loop()->PostTask(
CompositorThreadHolder::Loop()->PostTask(
NewRunnableMethod<StoreCopyPassByConstLRef<VRManagerPromise>>(
"VRManager::NotifyVibrateHapticCompleted",
vm, &VRManager::NotifyVibrateHapticCompleted, aPromise));

Просмотреть файл

@ -72,7 +72,6 @@ private:
VRTelemetry mTelemetry;
bool mRequestPresentation;
bool mRequestTracking;
bool mTracking;
bool mDrawBlack;
bool mIsConnected;
bool mIsMounted;

Просмотреть файл

@ -546,7 +546,7 @@ void
VRControllerOpenVR::VibrateHapticComplete(const VRManagerPromise& aPromise)
{
VRManager *vm = VRManager::Get();
VRListenerThreadHolder::Loop()->PostTask(
CompositorThreadHolder::Loop()->PostTask(
NewRunnableMethod<StoreCopyPassByConstLRef<VRManagerPromise>>(
"VRManager::NotifyVibrateHapticCompleted",
vm, &VRManager::NotifyVibrateHapticCompleted, aPromise));

Просмотреть файл

@ -14,6 +14,7 @@
#include "mozilla/Base64.h"
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/layers/CompositorThread.h" // for CompositorThreadHolder
#include "gfxPrefs.h"
#include "gfxUtils.h"
#include "gfxVRPuppet.h"
@ -394,7 +395,7 @@ VRDisplayPuppet::SubmitFrame(ID3D11Texture2D* aSource,
}
// Dispatch the base64 encoded string to the DOM side. Then, it will be decoded
// and convert to a PNG image there.
MessageLoop* loop = VRListenerThreadHolder::Loop();
MessageLoop* loop = CompositorThreadHolder::Loop();
loop->PostTask(NewRunnableMethod<const uint32_t, VRSubmitFrameResultInfo>(
"VRManager::DispatchSubmitFrameResult",
vm, &VRManager::DispatchSubmitFrameResult, mDisplayInfo.mDisplayID, result
@ -540,7 +541,7 @@ VRDisplayPuppet::SubmitFrame(MacIOSurface* aMacIOSurface,
}
// Dispatch the base64 encoded string to the DOM side. Then, it will be decoded
// and convert to a PNG image there.
MessageLoop* loop = VRListenerThreadHolder::Loop();
MessageLoop* loop = CompositorThreadHolder::Loop();
loop->PostTask(NewRunnableMethod<const uint32_t, VRSubmitFrameResultInfo>(
"VRManager::DispatchSubmitFrameResult",
vm, &VRManager::DispatchSubmitFrameResult, mDisplayInfo.mDisplayID, result

Просмотреть файл

@ -118,7 +118,7 @@ VRManagerChild::InitSameProcess()
sVRManagerChildSingleton = new VRManagerChild();
sVRManagerParentSingleton = VRManagerParent::CreateSameProcess();
sVRManagerChildSingleton->Open(sVRManagerParentSingleton->GetIPCChannel(),
VRListenerThreadHolder::Loop(),
CompositorThreadHolder::Loop(),
mozilla::ipc::ChildSide);
}

Просмотреть файл

@ -85,7 +85,7 @@ VRManagerParent::UnregisterFromManager()
/* static */ bool
VRManagerParent::CreateForContent(Endpoint<PVRManagerParent>&& aEndpoint)
{
MessageLoop* loop = VRListenerThreadHolder::Loop();
MessageLoop* loop = CompositorThreadHolder::Loop();
RefPtr<VRManagerParent> vmp = new VRManagerParent(aEndpoint.OtherPid(), true);
loop->PostTask(NewRunnableMethod<Endpoint<PVRManagerParent>&&>(
@ -109,7 +109,7 @@ VRManagerParent::Bind(Endpoint<PVRManagerParent>&& aEndpoint)
}
/*static*/ void
VRManagerParent::RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager)
VRManagerParent::RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager)
{
aVRManager->RegisterWithManager();
}
@ -117,22 +117,22 @@ VRManagerParent::RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager
/*static*/ VRManagerParent*
VRManagerParent::CreateSameProcess()
{
MessageLoop* loop = VRListenerThreadHolder::Loop();
MessageLoop* loop = CompositorThreadHolder::Loop();
RefPtr<VRManagerParent> vmp = new VRManagerParent(base::GetCurrentProcId(), false);
vmp->mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton();
vmp->mCompositorThreadHolder = CompositorThreadHolder::GetSingleton();
vmp->mSelfRef = vmp;
loop->PostTask(NewRunnableFunction("RegisterVRManagerInVRListenerThreadRunnable",
RegisterVRManagerInVRListenerThread, vmp.get()));
loop->PostTask(NewRunnableFunction("RegisterVRManagerIncompositorThreadRunnable",
RegisterVRManagerInCompositorThread, vmp.get()));
return vmp.get();
}
bool
VRManagerParent::CreateForGPUProcess(Endpoint<PVRManagerParent>&& aEndpoint)
{
MessageLoop* loop = VRListenerThreadHolder::Loop();
MessageLoop* loop = CompositorThreadHolder::Loop();
RefPtr<VRManagerParent> vmp = new VRManagerParent(aEndpoint.OtherPid(), false);
vmp->mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton();
vmp->mCompositorThreadHolder = CompositorThreadHolder::GetSingleton();
vmp->mSelfRef = vmp;
loop->PostTask(NewRunnableMethod<Endpoint<PVRManagerParent>&&>(
"gfx::VRManagerParent::Bind",
@ -145,7 +145,7 @@ VRManagerParent::CreateForGPUProcess(Endpoint<PVRManagerParent>&& aEndpoint)
void
VRManagerParent::DeferredDestroy()
{
mVRListenerThreadHolder = nullptr;
mCompositorThreadHolder = nullptr;
mSelfRef = nullptr;
}
@ -162,15 +162,12 @@ 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());
// 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
@ -276,7 +273,7 @@ VRManagerParent::RecvCreateVRServiceTestController(const nsCString& aID, const u
VRManager* vm = VRManager::Get();
/**
* The controller is created asynchronously in the VRListener thread.
* The controller is created asynchronously.
* We will wait up to kMaxControllerCreationTime milliseconds before
* assuming that the controller will never be created.
*/

Просмотреть файл

@ -7,13 +7,13 @@
#ifndef MOZILLA_GFX_VR_VRMANAGERPARENT_H
#define MOZILLA_GFX_VR_VRMANAGERPARENT_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;
@ -81,7 +81,7 @@ private:
void Bind(Endpoint<PVRManagerParent>&& aEndpoint);
static void RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager);
static void RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager);
void DeferredDestroy();
already_AddRefed<impl::VRControllerPuppet> GetControllerPuppet(uint32_t aDeviceID);
@ -89,7 +89,8 @@ private:
// This keeps us alive until ActorDestroy(), at which point we do a
// deferred destruction of ourselves.
RefPtr<VRManagerParent> mSelfRef;
RefPtr<VRListenerThreadHolder> mVRListenerThreadHolder;
// Keep the compositor thread alive, until we have destroyed ourselves.
RefPtr<CompositorThreadHolder> mCompositorThreadHolder;
// Keep the VRManager alive, until we have destroyed ourselves.
RefPtr<VRManager> mVRManagerHolder;