Bug 1406327 - Part 1: Shutdown VR listener thread when no VR content in seconds; r?kip, dvander
MozReview-Commit-ID: AnYJT8WBkI7
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -116,18 +116,16 @@ GPUParent::Init(base::ProcessId aParentP
DeviceManagerDx::Init();
#endif
if (NS_FAILED(NS_InitMinimalXPCOM())) {
return false;
}
CompositorThreadHolder::Start();
- // TODO: Bug 1406327, Start VRListenerThreadHolder when loading VR content.
- VRListenerThreadHolder::Start();
APZThreadUtils::SetControllerThread(CompositorThreadHolder::Loop());
APZCTreeManager::InitializeGlobalState();
LayerTreeOwnerTracker::Initialize();
mozilla::ipc::SetThisProcessName("GPU Process");
#ifdef XP_WIN
wmf::MFStartup();
#endif
return true;
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -27,17 +27,16 @@
#include "mozilla/DebugOnly.h" // for DebugOnly
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/GPUChild.h" // for GfxPrefValue
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/Rect.h" // for IntSize
#include "mozilla/gfx/gfxVars.h" // for gfxVars
-#include "VRManager.h" // for VRManager
#include "mozilla/ipc/Transport.h" // for Transport
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUParent.h"
#include "mozilla/layers/AnimationHelper.h" // for CompositorAnimationStorage
#include "mozilla/layers/APZCTreeManager.h" // for APZCTreeManager
#include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent
#include "mozilla/layers/APZThreadUtils.h" // for APZCTreeManager
#include "mozilla/layers/AsyncCompositionManager.h"
--- a/gfx/layers/ipc/CompositorVsyncScheduler.cpp
+++ b/gfx/layers/ipc/CompositorVsyncScheduler.cpp
@@ -128,29 +128,48 @@ CompositorVsyncScheduler::PostCompositeT
RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<TimeStamp>(
"layers::CompositorVsyncScheduler::Composite",
this,
&CompositorVsyncScheduler::Composite,
aCompositeTimestamp);
mCurrentCompositeTask = task;
ScheduleTask(task.forget(), 0);
}
- if (mCurrentVRListenerTask == nullptr && VRListenerThreadHolder::Loop()) {
- RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<TimeStamp>(
- "layers::CompositorVsyncScheduler::DispatchVREvents",
- this,
- &CompositorVsyncScheduler::DispatchVREvents,
- aCompositeTimestamp);
- mCurrentVRListenerTask = task;
- MOZ_ASSERT(VRListenerThreadHolder::Loop());
- VRListenerThreadHolder::Loop()->PostDelayedTask(Move(task.forget()), 0);
+ if (mCurrentVRListenerTask == nullptr && VRListenerThreadHolder::IsActive()) {
+ const TimeDuration timeout = TimeDuration::FromSeconds(45);
+ VRManager* vm = VRManager::Get();
+ TimeStamp activeTime(vm->GetLastVRListenerThreadActiveTime());
+
+ // Shutdown VR listener thread when no VR content in 45 sec. Shutdown threads
+ // only allows to be run at the main thread.
+ if (!activeTime.IsNull() && ((aCompositeTimestamp - activeTime) > timeout)) {
+ RefPtr<Runnable> runnable = NewRunnableMethod(
+ "layers::CompositorVsyncScheduler::ShutdownVRListenerThread",
+ this, &CompositorVsyncScheduler::ShutdownVRListenerThread);
+ NS_DispatchToMainThread(runnable.forget());
+ } else {
+ RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<TimeStamp>(
+ "layers::CompositorVsyncScheduler::DispatchVREvents",
+ this,
+ &CompositorVsyncScheduler::DispatchVREvents,
+ aCompositeTimestamp);
+ mCurrentVRListenerTask = task;
+ MOZ_ASSERT(VRListenerThreadHolder::Loop());
+ VRListenerThreadHolder::Loop()->PostTask(Move(task.forget()));
+ }
}
}
void
+CompositorVsyncScheduler::ShutdownVRListenerThread()
+{
+ VRListenerThreadHolder::Shutdown();
+}
+
+void
CompositorVsyncScheduler::ScheduleComposition()
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (!mVsyncObserver) {
// Destroy was already called on this object.
return;
}
--- a/gfx/layers/ipc/CompositorVsyncScheduler.h
+++ b/gfx/layers/ipc/CompositorVsyncScheduler.h
@@ -78,16 +78,17 @@ private:
virtual ~CompositorVsyncScheduler();
void NotifyCompositeTaskExecuted();
void ObserveVsync();
void UnobserveVsync();
void DispatchTouchEvents(TimeStamp aVsyncTimestamp);
void DispatchVREvents(TimeStamp aVsyncTimestamp);
void CancelCurrentSetNeedsCompositeTask();
+ void ShutdownVRListenerThread();
class Observer final : public VsyncObserver
{
public:
explicit Observer(CompositorVsyncScheduler* aOwner);
virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) override;
void Destroy();
private:
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1039,17 +1039,16 @@ gfxPlatform::InitLayersIPC()
layers::PaintThread::Start();
}
} else if (XRE_IsParentProcess()) {
if (gfxVars::UseWebRender()) {
wr::RenderThread::Start();
}
layers::CompositorThreadHolder::Start();
- gfx::VRListenerThreadHolder::Start();
}
}
/* static */ void
gfxPlatform::ShutdownLayersIPC()
{
if (!sLayersIPCIsUp) {
return;
--- a/gfx/vr/VRThread.cpp
+++ b/gfx/vr/VRThread.cpp
@@ -8,16 +8,17 @@
#include "VRThread.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace gfx {
static StaticRefPtr<VRListenerThreadHolder> sVRListenerThreadHolder;
+static TimeStamp sStartTime;
static bool sFinishedVRListenerShutDown = false;
VRListenerThreadHolder* GetVRListenerThreadHolder()
{
return sVRListenerThreadHolder;
}
base::Thread*
@@ -89,34 +90,45 @@ VRListenerThreadHolder::CreateThread()
void
VRListenerThreadHolder::Start()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread!");
MOZ_ASSERT(!sVRListenerThreadHolder, "The VR listener thread has already been started!");
sVRListenerThreadHolder = new VRListenerThreadHolder();
+ sStartTime = TimeStamp::Now();
+}
+
+TimeStamp
+VRListenerThreadHolder::GetStartTime()
+{
+ return sStartTime;
}
void
VRListenerThreadHolder::Shutdown()
{
+ if (!IsActive()) {
+ return;
+ }
+
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread!");
MOZ_ASSERT(sVRListenerThreadHolder, "The VR listener thread has already been shut down!");
sVRListenerThreadHolder = nullptr;
SpinEventLoopUntil([&]() { return sFinishedVRListenerShutDown; });
}
/* static */ bool
VRListenerThreadHolder::IsInVRListenerThread()
{
return VRListenerThread() &&
- VRListenerThread()->thread_id() == PlatformThread::CurrentId();
+ VRListenerThread()->thread_id() == PlatformThread::CurrentId();
}
} // namespace gfx
} // namespace mozilla
bool
NS_IsInVRListenerThread()
{
--- a/gfx/vr/VRThread.h
+++ b/gfx/vr/VRThread.h
@@ -22,31 +22,32 @@ public:
base::Thread* GetThread() const {
return mThread;
}
static VRListenerThreadHolder* GetSingleton();
static bool IsActive() {
- return !!GetSingleton();
+ return !!GetSingleton() && !!Loop();
}
static void Start();
static void Shutdown();
static MessageLoop* Loop();
static bool IsInVRListenerThread();
+ static TimeStamp GetStartTime();
private:
~VRListenerThreadHolder();
- base::Thread* const mThread;
-
static base::Thread* CreateThread();
static void DestroyThread(base::Thread* aThread);
+
+ base::Thread* const mThread;
};
base::Thread* VRListenerThread();
} // namespace gfx
} // namespace mozilla
#endif // GFX_VR_THREAD_H
\ No newline at end of file