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
This commit is contained in:
Kearwood Gilbert 2017-03-30 09:35:49 -04:00
Родитель d8ee3acbe9
Коммит 043d85c921
13 изменённых файлов: 139 добавлений и 161 удалений

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

@ -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);
}

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

@ -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<VRSystemManager> mgr = VRSystemManagerPuppet::Create();
if (mgr) {
mgr->Init();
mManagers.AppendElement(mgr);
mVRTestSystemCreated = true;
}

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

@ -63,6 +63,7 @@ private:
void Init();
void Destroy();
void Shutdown();
void DispatchVRDisplayInfoUpdate();
void RefreshVRControllers();

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

@ -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<RefPtr<VRDisplayHost>>& aHMDResult) = 0;
virtual bool GetIsPresenting() = 0;
virtual void HandleInput() = 0;

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

@ -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<RefPtr<VRDisplayHost>>& aHMDResult)
// make sure context, interface and display are initialized
CheckOSVRStatus();
if (!mOSVRInitialized) {
if (!Init()) {
return;
}

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

@ -64,8 +64,8 @@ class VRSystemManagerOSVR : public VRSystemManager
{
public:
static already_AddRefed<VRSystemManagerOSVR> Create();
virtual bool Init() override;
virtual void Destroy() override;
virtual void Shutdown() override;
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override;
virtual bool GetIsPresenting() override;
virtual void HandleInput() override;
@ -89,6 +89,8 @@ protected:
{
}
bool Init();
RefPtr<impl::VRDisplayOSVR> mHMDInfo;
bool mOSVRInitialized;
bool mClientContextInitialized;

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

@ -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<uint32_t>
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<nsCString> 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 <OVR_Version.h>
// 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<VRSystemManagerOculus> manager = new VRSystemManagerOculus();
return manager.forget();
}
bool
VRSystemManagerOculus::Init()
VRSystemManagerOculus::Startup()
{
if (!mOculusInitialized) {
nsIThread* thread = nullptr;
NS_GetCurrentThread(&thread);
mOculusThread = already_AddRefed<nsIThread>(thread);
ovrInitParams params;
memset(&params, 0, sizeof(params));
params.Flags = ovrInit_RequestVersion;
params.RequestedMinorVersion = OVR_MINOR_VERSION;
params.LogCallback = nullptr;
params.ConnectionTimeoutMS = 0;
ovrResult orv = ovr_Initialize(&params);
if (orv == ovrSuccess) {
mOculusInitialized = true;
}
if (mStarted) {
return true;
}
return mOculusInitialized;
if (!LoadOvrLib()) {
return false;
}
nsIThread* thread = nullptr;
NS_GetCurrentThread(&thread);
mOculusThread = already_AddRefed<nsIThread>(thread);
ovrInitParams params;
memset(&params, 0, sizeof(params));
params.Flags = ovrInit_RequestVersion;
params.RequestedMinorVersion = OVR_MINOR_VERSION;
params.LogCallback = nullptr;
params.ConnectionTimeoutMS = 0;
ovrResult orv = ovr_Initialize(&params);
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<RefPtr<VRDisplayHost>>& aHMDResult)
{
if (!mOculusInitialized) {
if (!Startup()) {
return;
}
@ -1437,10 +1406,6 @@ void
VRSystemManagerOculus::GetControllers(nsTArray<RefPtr<VRControllerHost>>&
aControllerResult)
{
if (!mOculusInitialized) {
return;
}
aControllerResult.Clear();
for (uint32_t i = 0; i < mOculusController.Length(); ++i) {
aControllerResult.AppendElement(mOculusController[i]);

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

@ -136,8 +136,8 @@ class VRSystemManagerOculus : public VRSystemManager
{
public:
static already_AddRefed<VRSystemManagerOculus> Create();
virtual bool Init() override;
virtual void Destroy() override;
virtual void Shutdown() override;
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost> >& 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<impl::VRDisplayOculus> mHMDInfo;
nsTArray<RefPtr<impl::VRControllerOculus>> mOculusController;
RefPtr<nsIThread> mOculusThread;
ovrSession mSession;
bool mOculusInitialized;
bool mStarted;
};
} // namespace gfx

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

@ -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<VRSystemManagerOpenVR> 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<RefPtr<VRDisplayHost>>& aHMDResult)
{
if (!mOpenVRInstalled) {
return;
}
if (!vr_IsHmdPresent()) {
if (mOpenVRHMD) {
mOpenVRHMD = nullptr;
@ -909,10 +898,6 @@ VRSystemManagerOpenVR::StopVibrateHaptic(uint32_t aControllerIdx)
void
VRSystemManagerOpenVR::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
{
if (!mOpenVRInstalled) {
return;
}
aControllerResult.Clear();
for (uint32_t i = 0; i < mOpenVRController.Length(); ++i) {
aControllerResult.AppendElement(mOpenVRController[i]);

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

@ -111,8 +111,8 @@ class VRSystemManagerOpenVR : public VRSystemManager
public:
static already_AddRefed<VRSystemManagerOpenVR> Create();
virtual bool Init() override;
virtual void Destroy() override;
virtual void Shutdown() override;
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost> >& aHMDResult) override;
virtual bool GetIsPresenting() override;
virtual void HandleInput() override;
@ -152,7 +152,6 @@ private:
RefPtr<impl::VRDisplayOpenVR> mOpenVRHMD;
nsTArray<RefPtr<impl::VRControllerOpenVR>> mOpenVRController;
vr::IVRSystem *mVRSystem;
bool mOpenVRInstalled;
};
} // namespace gfx

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

@ -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;
}

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

@ -89,8 +89,8 @@ class VRSystemManagerPuppet : public VRSystemManager
public:
static already_AddRefed<VRSystemManagerPuppet> Create();
virtual bool Init() override;
virtual void Destroy() override;
virtual void Shutdown() override;
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override;
virtual bool GetIsPresenting() override;
virtual void HandleInput() override;

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

@ -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