From 043d85c9211e4c2bf3365138311d987c51d61dbb Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Thu, 30 Mar 2017 09:35:49 -0400 Subject: [PATCH] Bug 1351048 - Do not load VR libraries until necessary, Oculus cleanup r=daoshengmu - I have refactored the Oculus and OpenVR interfaces in gfx/vr so that initialization of the VR libraries only happens once a WebVR site is detected. - The Oculus interface has been cleaned up and updated to unload the Oculus runtime library when not in use. - The browser can now re-connect to Oculus home if it was restarted, without restarting the browser. - We no longer submit a black frame at the end of VR presentation, as this appears to be handled by the latest Oculus runtime automatically. - As we only hold on to the Oculus runtime when needed, this should reduce the likelihood of the GPU process being killed by the Oculus software updater. MozReview-Commit-ID: AyWeD4CxXLD --HG-- extra : rebase_source : 9eae07ef30b1a7559b5fe80e6698c248a55b970e --- dom/base/Navigator.cpp | 4 + gfx/vr/VRManager.cpp | 24 ++++- gfx/vr/VRManager.h | 1 + gfx/vr/gfxVR.h | 2 +- gfx/vr/gfxVROSVR.cpp | 8 +- gfx/vr/gfxVROSVR.h | 4 +- gfx/vr/gfxVROculus.cpp | 187 ++++++++++++++++---------------------- gfx/vr/gfxVROculus.h | 12 ++- gfx/vr/gfxVROpenVR.cpp | 43 +++------ gfx/vr/gfxVROpenVR.h | 3 +- gfx/vr/gfxVRPuppet.cpp | 8 +- gfx/vr/gfxVRPuppet.h | 2 +- gfx/vr/ovr_capi_dynamic.h | 2 - 13 files changed, 139 insertions(+), 161 deletions(-) diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index f2cf8ed476ba..c488177201ad 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -1574,6 +1574,10 @@ Navigator::NotifyActiveVRDisplaysChanged() VRServiceTest* Navigator::RequestVRServiceTest() { + // Ensure that the Mock VR devices are not released prematurely + nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow); + win->NotifyVREventListenerAdded(); + if (!mVRServiceTest) { mVRServiceTest = VRServiceTest::CreateTestService(mWindow); } diff --git a/gfx/vr/VRManager.cpp b/gfx/vr/VRManager.cpp index dc758b64eace..44d5fb563647 100644 --- a/gfx/vr/VRManager.cpp +++ b/gfx/vr/VRManager.cpp @@ -116,13 +116,19 @@ VRManager::Destroy() mInitialized = false; } +void +VRManager::Shutdown() +{ + mVRDisplays.Clear(); + mVRControllers.Clear(); + for (uint32_t i = 0; i < mManagers.Length(); ++i) { + mManagers[i]->Shutdown(); + } +} + void VRManager::Init() { - for (uint32_t i = 0; i < mManagers.Length(); ++i) { - mManagers[i]->Init(); - } - mInitialized = true; } @@ -159,6 +165,7 @@ VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp) bool bHaveEventListener = false; bool bHaveControllerListener = false; + bool bHaveActiveDisplay = false; for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) { VRManagerParent *vmp = iter.Get()->GetKey(); @@ -172,6 +179,9 @@ VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp) for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) { gfx::VRDisplayHost* display = iter.UserData(); display->NotifyVSync(); + if (display->GetDisplayInfo().GetIsPresenting()) { + bHaveActiveDisplay = true; + } } if (bHaveEventListener) { @@ -209,6 +219,11 @@ VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp) } } } + + if (!bHaveEventListener && !bHaveControllerListener && !bHaveActiveDisplay) { + // Shut down the VR devices when not in use + Shutdown(); + } } void @@ -406,7 +421,6 @@ VRManager::CreateVRTestSystem() RefPtr mgr = VRSystemManagerPuppet::Create(); if (mgr) { - mgr->Init(); mManagers.AppendElement(mgr); mVRTestSystemCreated = true; } diff --git a/gfx/vr/VRManager.h b/gfx/vr/VRManager.h index 2dea6962bd21..ab5859151b7b 100644 --- a/gfx/vr/VRManager.h +++ b/gfx/vr/VRManager.h @@ -63,6 +63,7 @@ private: void Init(); void Destroy(); + void Shutdown(); void DispatchVRDisplayInfoUpdate(); void RefreshVRControllers(); diff --git a/gfx/vr/gfxVR.h b/gfx/vr/gfxVR.h index bd379defc945..2dcfdc31ff4d 100644 --- a/gfx/vr/gfxVR.h +++ b/gfx/vr/gfxVR.h @@ -251,8 +251,8 @@ protected: public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRSystemManager) - virtual bool Init() = 0; virtual void Destroy() = 0; + virtual void Shutdown() = 0; virtual void GetHMDs(nsTArray>& aHMDResult) = 0; virtual bool GetIsPresenting() = 0; virtual void HandleInput() = 0; diff --git a/gfx/vr/gfxVROSVR.cpp b/gfx/vr/gfxVROSVR.cpp index 98713e8f5874..c9dabd26e147 100644 --- a/gfx/vr/gfxVROSVR.cpp +++ b/gfx/vr/gfxVROSVR.cpp @@ -493,6 +493,12 @@ VRSystemManagerOSVR::Init() void VRSystemManagerOSVR::Destroy() +{ + Shutdown(); +} + +void +VRSystemManagerOSVR::Shutdown() { if (mOSVRInitialized) { MOZ_ASSERT(NS_GetCurrentThread() == mOSVRThread); @@ -515,7 +521,7 @@ VRSystemManagerOSVR::GetHMDs(nsTArray>& aHMDResult) // make sure context, interface and display are initialized CheckOSVRStatus(); - if (!mOSVRInitialized) { + if (!Init()) { return; } diff --git a/gfx/vr/gfxVROSVR.h b/gfx/vr/gfxVROSVR.h index 909df4c22727..90b790aba7f1 100644 --- a/gfx/vr/gfxVROSVR.h +++ b/gfx/vr/gfxVROSVR.h @@ -64,8 +64,8 @@ class VRSystemManagerOSVR : public VRSystemManager { public: static already_AddRefed Create(); - virtual bool Init() override; virtual void Destroy() override; + virtual void Shutdown() override; virtual void GetHMDs(nsTArray>& aHMDResult) override; virtual bool GetIsPresenting() override; virtual void HandleInput() override; @@ -89,6 +89,8 @@ protected: { } + bool Init(); + RefPtr mHMDInfo; bool mOSVRInitialized; bool mClientContextInitialized; diff --git a/gfx/vr/gfxVROculus.cpp b/gfx/vr/gfxVROculus.cpp index d9ec479f95d8..3e821a502a83 100644 --- a/gfx/vr/gfxVROculus.cpp +++ b/gfx/vr/gfxVROculus.cpp @@ -57,7 +57,6 @@ using namespace mozilla::dom; namespace { -#ifdef OVR_CAPI_LIMITED_MOZILLA static pfn_ovr_Initialize ovr_Initialize = nullptr; static pfn_ovr_Shutdown ovr_Shutdown = nullptr; static pfn_ovr_GetLastErrorInfo ovr_GetLastErrorInfo = nullptr; @@ -148,24 +147,40 @@ static const uint32_t kNumOculusButton = static_cast NumButtonType); static const uint32_t kNumOculusHaptcs = 1; - -static bool -InitializeOculusCAPI() +ovrFovPort +ToFovPort(const VRFieldOfView& aFOV) { - static PRLibrary *ovrlib = nullptr; + ovrFovPort fovPort; + fovPort.LeftTan = tan(aFOV.leftDegrees * M_PI / 180.0); + fovPort.RightTan = tan(aFOV.rightDegrees * M_PI / 180.0); + fovPort.UpTan = tan(aFOV.upDegrees * M_PI / 180.0); + fovPort.DownTan = tan(aFOV.downDegrees * M_PI / 180.0); + return fovPort; +} - if (!ovrlib) { +VRFieldOfView +FromFovPort(const ovrFovPort& aFOV) +{ + VRFieldOfView fovInfo; + fovInfo.leftDegrees = atan(aFOV.LeftTan) * 180.0 / M_PI; + fovInfo.rightDegrees = atan(aFOV.RightTan) * 180.0 / M_PI; + fovInfo.upDegrees = atan(aFOV.UpTan) * 180.0 / M_PI; + fovInfo.downDegrees = atan(aFOV.DownTan) * 180.0 / M_PI; + return fovInfo; +} + +} // namespace + +bool +VRSystemManagerOculus::LoadOvrLib() +{ + if (!mOvrLib) { nsTArray libSearchPaths; nsCString libName; nsCString searchPath; #if defined(_WIN32) static const char dirSep = '\\'; -#else - static const char dirSep = '/'; -#endif - -#if defined(_WIN32) static const int pathLen = 260; searchPath.SetCapacity(pathLen); int realLen = ::GetSystemDirectoryA(searchPath.BeginWriting(), pathLen); @@ -174,37 +189,9 @@ InitializeOculusCAPI() libSearchPaths.AppendElement(searchPath); } libName.AppendPrintf("LibOVRRT%d_%d.dll", BUILD_BITS, OVR_PRODUCT_VERSION); -#elif defined(__APPLE__) - searchPath.Truncate(); - searchPath.AppendPrintf("/Library/Frameworks/LibOVRRT_%d.framework/Versions/%d", OVR_PRODUCT_VERSION, OVR_MAJOR_VERSION); - libSearchPaths.AppendElement(searchPath); - - if (PR_GetEnv("HOME")) { - searchPath.Truncate(); - searchPath.AppendPrintf("%s/Library/Frameworks/LibOVRRT_%d.framework/Versions/%d", PR_GetEnv("HOME"), OVR_PRODUCT_VERSION, OVR_MAJOR_VERSION); - libSearchPaths.AppendElement(searchPath); - } - // The following will match the va_list overload of AppendPrintf if the product version is 0 - // That's bad times. - //libName.AppendPrintf("LibOVRRT_%d", OVR_PRODUCT_VERSION); - libName.Append("LibOVRRT_"); - libName.AppendInt(OVR_PRODUCT_VERSION); #else - libSearchPaths.AppendElement(nsCString("/usr/local/lib")); - libSearchPaths.AppendElement(nsCString("/usr/lib")); - libName.AppendPrintf("libOVRRT%d_%d.so.%d", BUILD_BITS, OVR_PRODUCT_VERSION, OVR_MAJOR_VERSION); +#error "Unsupported platform!" #endif - - // If the pref is present, we override libName - nsAdoptingCString prefLibPath = mozilla::Preferences::GetCString("dom.vr.ovr_lib_path"); - if (prefLibPath && prefLibPath.get()) { - libSearchPaths.InsertElementsAt(0, 1, prefLibPath); - } - - nsAdoptingCString prefLibName = mozilla::Preferences::GetCString("dom.vr.ovr_lib_name"); - if (prefLibName && prefLibName.get()) { - libName.Assign(prefLibName); - } // search the path/module dir libSearchPaths.InsertElementsAt(0, 1, nsCString()); @@ -228,22 +215,19 @@ InitializeOculusCAPI() fullName.AppendPrintf("%s%c%s", libPath.BeginReading(), dirSep, libName.BeginReading()); } - ovrlib = PR_LoadLibrary(fullName.BeginReading()); - if (ovrlib) + mOvrLib = PR_LoadLibrary(fullName.BeginReading()); + if (mOvrLib) { break; + } } - if (!ovrlib) { + if (!mOvrLib) { return false; } } - // was it already initialized? - if (ovr_Initialize) - return true; - #define REQUIRE_FUNCTION(_x) do { \ - *(void **)&_x = (void *) PR_FindSymbol(ovrlib, #_x); \ + *(void **)&_x = (void *) PR_FindSymbol(mOvrLib, #_x); \ if (!_x) { printf_stderr(#_x " symbol missing\n"); goto fail; } \ } while (0) @@ -310,43 +294,20 @@ InitializeOculusCAPI() fail: ovr_Initialize = nullptr; + PR_UnloadLibrary(mOvrLib); + mOvrLib = nullptr; return false; } -#else -#include -// we're statically linked; it's available -static bool InitializeOculusCAPI() +void +VRSystemManagerOculus::UnloadOvrLib() { - return true; + if (mOvrLib) { + PR_UnloadLibrary(mOvrLib); + mOvrLib = nullptr; + } } -#endif - -ovrFovPort -ToFovPort(const VRFieldOfView& aFOV) -{ - ovrFovPort fovPort; - fovPort.LeftTan = tan(aFOV.leftDegrees * M_PI / 180.0); - fovPort.RightTan = tan(aFOV.rightDegrees * M_PI / 180.0); - fovPort.UpTan = tan(aFOV.upDegrees * M_PI / 180.0); - fovPort.DownTan = tan(aFOV.downDegrees * M_PI / 180.0); - return fovPort; -} - -VRFieldOfView -FromFovPort(const ovrFovPort& aFOV) -{ - VRFieldOfView fovInfo; - fovInfo.leftDegrees = atan(aFOV.LeftTan) * 180.0 / M_PI; - fovInfo.rightDegrees = atan(aFOV.RightTan) * 180.0 / M_PI; - fovInfo.upDegrees = atan(aFOV.UpTan) * 180.0 / M_PI; - fovInfo.downDegrees = atan(aFOV.DownTan) * 180.0 / M_PI; - return fovInfo; -} - -} // namespace - VRDisplayOculus::VRDisplayOculus(ovrSession aSession) : VRDisplayHost(VRDeviceType::Oculus) , mSession(aSession) @@ -684,8 +645,6 @@ VRDisplayOculus::StopPresentation() } mIsPresenting = false; - ovr_SubmitFrame(mSession, 0, nullptr, nullptr, 0); - if (mTextureSet) { ovr_DestroyTextureSwapChain(mSession, mTextureSet); mTextureSet = nullptr; @@ -1108,57 +1067,67 @@ VRSystemManagerOculus::Create() return nullptr; } - if (!InitializeOculusCAPI()) { - return nullptr; - } - RefPtr manager = new VRSystemManagerOculus(); return manager.forget(); } bool -VRSystemManagerOculus::Init() +VRSystemManagerOculus::Startup() { - if (!mOculusInitialized) { - nsIThread* thread = nullptr; - NS_GetCurrentThread(&thread); - mOculusThread = already_AddRefed(thread); - - ovrInitParams params; - memset(¶ms, 0, sizeof(params)); - params.Flags = ovrInit_RequestVersion; - params.RequestedMinorVersion = OVR_MINOR_VERSION; - params.LogCallback = nullptr; - params.ConnectionTimeoutMS = 0; - - ovrResult orv = ovr_Initialize(¶ms); - - if (orv == ovrSuccess) { - mOculusInitialized = true; - } + if (mStarted) { + return true; } - return mOculusInitialized; + if (!LoadOvrLib()) { + return false; + } + + nsIThread* thread = nullptr; + NS_GetCurrentThread(&thread); + mOculusThread = already_AddRefed(thread); + + ovrInitParams params; + memset(¶ms, 0, sizeof(params)); + params.Flags = ovrInit_RequestVersion; + params.RequestedMinorVersion = OVR_MINOR_VERSION; + params.LogCallback = nullptr; + params.ConnectionTimeoutMS = 0; + + ovrResult orv = ovr_Initialize(¶ms); + + if (orv == ovrSuccess) { + mStarted = true; + } + + return mStarted; } void VRSystemManagerOculus::Destroy() { - if (mOculusInitialized) { + Shutdown(); +} + +void +VRSystemManagerOculus::Shutdown() +{ + if (mStarted) { + RemoveControllers(); MOZ_ASSERT(NS_GetCurrentThread() == mOculusThread); mOculusThread = nullptr; mSession = nullptr; mHMDInfo = nullptr; ovr_Shutdown(); - mOculusInitialized = false; + UnloadOvrLib(); + mStarted = false; } } void VRSystemManagerOculus::GetHMDs(nsTArray>& aHMDResult) { - if (!mOculusInitialized) { + if (!Startup()) { return; } @@ -1437,10 +1406,6 @@ void VRSystemManagerOculus::GetControllers(nsTArray>& aControllerResult) { - if (!mOculusInitialized) { - return; - } - aControllerResult.Clear(); for (uint32_t i = 0; i < mOculusController.Length(); ++i) { aControllerResult.AppendElement(mOculusController[i]); diff --git a/gfx/vr/gfxVROculus.h b/gfx/vr/gfxVROculus.h index edc775312313..ac2cbef3b399 100644 --- a/gfx/vr/gfxVROculus.h +++ b/gfx/vr/gfxVROculus.h @@ -136,8 +136,8 @@ class VRSystemManagerOculus : public VRSystemManager { public: static already_AddRefed Create(); - virtual bool Init() override; virtual void Destroy() override; + virtual void Shutdown() override; virtual void GetHMDs(nsTArray >& aHMDResult) override; virtual bool GetIsPresenting() override; virtual void HandleInput() override; @@ -151,9 +151,13 @@ public: protected: VRSystemManagerOculus() - : mSession(nullptr), mOculusInitialized(false) + : mOvrLib(nullptr), mSession(nullptr), mStarted(false) { } + bool Startup(); + bool LoadOvrLib(); + void UnloadOvrLib(); + private: void HandleButtonPress(uint32_t aControllerIdx, uint32_t aButton, @@ -168,12 +172,12 @@ private: float aValue); void HandleTouchEvent(uint32_t aControllerIdx, uint32_t aButton, uint64_t aTouchMask, uint64_t aTouched); - + PRLibrary* mOvrLib; RefPtr mHMDInfo; nsTArray> mOculusController; RefPtr mOculusThread; ovrSession mSession; - bool mOculusInitialized; + bool mStarted; }; } // namespace gfx diff --git a/gfx/vr/gfxVROpenVR.cpp b/gfx/vr/gfxVROpenVR.cpp index 95a3ca66cbea..a58e0e2535c4 100644 --- a/gfx/vr/gfxVROpenVR.cpp +++ b/gfx/vr/gfxVROpenVR.cpp @@ -542,7 +542,6 @@ VRControllerOpenVR::StopVibrateHaptic() VRSystemManagerOpenVR::VRSystemManagerOpenVR() : mVRSystem(nullptr) - , mOpenVRInstalled(false) { } @@ -559,43 +558,33 @@ VRSystemManagerOpenVR::Create() return nullptr; } + if (!vr_IsRuntimeInstalled()) { + return nullptr; + } + RefPtr manager = new VRSystemManagerOpenVR(); return manager.forget(); } -bool -VRSystemManagerOpenVR::Init() -{ - if (mOpenVRInstalled) - return true; - - if (!vr_IsRuntimeInstalled()) - return false; - - mOpenVRInstalled = true; - return true; -} - void VRSystemManagerOpenVR::Destroy() { - if (mOpenVRInstalled) { - if (mOpenVRHMD) { - mOpenVRHMD = nullptr; - } - RemoveControllers(); - mVRSystem = nullptr; - mOpenVRInstalled = false; + Shutdown(); +} + +void +VRSystemManagerOpenVR::Shutdown() +{ + if (mOpenVRHMD) { + mOpenVRHMD = nullptr; } + RemoveControllers(); + mVRSystem = nullptr; } void VRSystemManagerOpenVR::GetHMDs(nsTArray>& aHMDResult) { - if (!mOpenVRInstalled) { - return; - } - if (!vr_IsHmdPresent()) { if (mOpenVRHMD) { mOpenVRHMD = nullptr; @@ -909,10 +898,6 @@ VRSystemManagerOpenVR::StopVibrateHaptic(uint32_t aControllerIdx) void VRSystemManagerOpenVR::GetControllers(nsTArray>& aControllerResult) { - if (!mOpenVRInstalled) { - return; - } - aControllerResult.Clear(); for (uint32_t i = 0; i < mOpenVRController.Length(); ++i) { aControllerResult.AppendElement(mOpenVRController[i]); diff --git a/gfx/vr/gfxVROpenVR.h b/gfx/vr/gfxVROpenVR.h index 5ac184718aee..068886f34606 100644 --- a/gfx/vr/gfxVROpenVR.h +++ b/gfx/vr/gfxVROpenVR.h @@ -111,8 +111,8 @@ class VRSystemManagerOpenVR : public VRSystemManager public: static already_AddRefed Create(); - virtual bool Init() override; virtual void Destroy() override; + virtual void Shutdown() override; virtual void GetHMDs(nsTArray >& aHMDResult) override; virtual bool GetIsPresenting() override; virtual void HandleInput() override; @@ -152,7 +152,6 @@ private: RefPtr mOpenVRHMD; nsTArray> mOpenVRController; vr::IVRSystem *mVRSystem; - bool mOpenVRInstalled; }; } // namespace gfx diff --git a/gfx/vr/gfxVRPuppet.cpp b/gfx/vr/gfxVRPuppet.cpp index b13a3997d550..6d7cda751a87 100644 --- a/gfx/vr/gfxVRPuppet.cpp +++ b/gfx/vr/gfxVRPuppet.cpp @@ -346,14 +346,14 @@ VRSystemManagerPuppet::Create() return manager.forget(); } -bool -VRSystemManagerPuppet::Init() +void +VRSystemManagerPuppet::Destroy() { - return true; + Shutdown(); } void -VRSystemManagerPuppet::Destroy() +VRSystemManagerPuppet::Shutdown() { mPuppetHMD = nullptr; } diff --git a/gfx/vr/gfxVRPuppet.h b/gfx/vr/gfxVRPuppet.h index 19df74d7297e..29c587c9d562 100644 --- a/gfx/vr/gfxVRPuppet.h +++ b/gfx/vr/gfxVRPuppet.h @@ -89,8 +89,8 @@ class VRSystemManagerPuppet : public VRSystemManager public: static already_AddRefed Create(); - virtual bool Init() override; virtual void Destroy() override; + virtual void Shutdown() override; virtual void GetHMDs(nsTArray>& aHMDResult) override; virtual bool GetIsPresenting() override; virtual void HandleInput() override; diff --git a/gfx/vr/ovr_capi_dynamic.h b/gfx/vr/ovr_capi_dynamic.h index 9a4ae06ba056..b16fdfd3af06 100644 --- a/gfx/vr/ovr_capi_dynamic.h +++ b/gfx/vr/ovr_capi_dynamic.h @@ -23,8 +23,6 @@ #ifndef mozilla_ovr_capi_dynamic_h_ #define mozilla_ovr_capi_dynamic_h_ -#define OVR_CAPI_LIMITED_MOZILLA 1 - #ifdef HAVE_64BIT_BUILD #define OVR_PTR_SIZE 8 #define OVR_ON64(x) x