зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1407423 - Ensure that any time we have loaded the Oculus runtime libary, we are polling ShouldQuit,r=daoshengmu
- Ensure ovr_GetSessionStatus is polled even when a VR presentation is not active. - When we fail to initialize an Oculus Session or detect VR hardware, immediately unload the Oculus Library as we can't poll for ShouldQuit without a valid Oculus session. - When we poll ovr_GetSessionStatus, we are now updating the mounted state in VRDisplayInfo::mIsMounted. - Added prefs to control enumeration throttling and timeout to release VR hardware when inactive. - Some refactoring to make frame loop more understandable and less brittle. - When throttling enumeration, we ensure that all other VR apis also throttle enumeration so that they don't pick up the same device during throttling. - Some long functions in VRManager have been broken up and had their inner-workings documented in more detail. MozReview-Commit-ID: CEYwwQ9mYd0 --HG-- extra : rebase_source : b82cd9f200e6311528d4bed469d1b8044e9fc7f2 extra : amend_source : e74f56f5ec95641fd478deb71d6c7ba5d2cba7b1
This commit is contained in:
Родитель
6e5bc11c14
Коммит
7e7cb086d3
|
@ -367,6 +367,9 @@ private:
|
||||||
DECL_GFX_PREF(Live, "dom.vr.oculus.quit.timeout", VROculusQuitTimeout, int32_t, 30000);
|
DECL_GFX_PREF(Live, "dom.vr.oculus.quit.timeout", VROculusQuitTimeout, int32_t, 30000);
|
||||||
DECL_GFX_PREF(Once, "dom.vr.openvr.enabled", VROpenVREnabled, bool, false);
|
DECL_GFX_PREF(Once, "dom.vr.openvr.enabled", VROpenVREnabled, bool, false);
|
||||||
DECL_GFX_PREF(Once, "dom.vr.osvr.enabled", VROSVREnabled, bool, false);
|
DECL_GFX_PREF(Once, "dom.vr.osvr.enabled", VROSVREnabled, bool, false);
|
||||||
|
DECL_GFX_PREF(Live, "dom.vr.controller.enumerate.interval", VRControllerEnumerateInterval, int32_t, 1000);
|
||||||
|
DECL_GFX_PREF(Live, "dom.vr.display.enumerate.interval", VRDisplayEnumerateInterval, int32_t, 5000);
|
||||||
|
DECL_GFX_PREF(Live, "dom.vr.inactive.timeout", VRInactiveTimeout, int32_t, 5000);
|
||||||
DECL_GFX_PREF(Live, "dom.vr.poseprediction.enabled", VRPosePredictionEnabled, bool, true);
|
DECL_GFX_PREF(Live, "dom.vr.poseprediction.enabled", VRPosePredictionEnabled, bool, true);
|
||||||
DECL_GFX_PREF(Live, "dom.vr.require-gesture", VRRequireGesture, bool, true);
|
DECL_GFX_PREF(Live, "dom.vr.require-gesture", VRRequireGesture, bool, true);
|
||||||
DECL_GFX_PREF(Live, "dom.vr.puppet.enabled", VRPuppetEnabled, bool, false);
|
DECL_GFX_PREF(Live, "dom.vr.puppet.enabled", VRPuppetEnabled, bool, false);
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
virtual void ZeroSensor() = 0;
|
virtual void ZeroSensor() = 0;
|
||||||
virtual void StartPresentation() = 0;
|
virtual void StartPresentation() = 0;
|
||||||
virtual void StopPresentation() = 0;
|
virtual void StopPresentation() = 0;
|
||||||
virtual void NotifyVSync();
|
void NotifyVSync();
|
||||||
|
|
||||||
void StartFrame();
|
void StartFrame();
|
||||||
void SubmitFrame(VRLayerParent* aLayer,
|
void SubmitFrame(VRLayerParent* aLayer,
|
||||||
|
|
|
@ -56,6 +56,8 @@ VRManager::ManagerInit()
|
||||||
VRManager::VRManager()
|
VRManager::VRManager()
|
||||||
: mInitialized(false)
|
: mInitialized(false)
|
||||||
, mVRTestSystemCreated(false)
|
, mVRTestSystemCreated(false)
|
||||||
|
, mVRDisplaysRequested(false)
|
||||||
|
, mVRControllersRequested(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(VRManager);
|
MOZ_COUNT_CTOR(VRManager);
|
||||||
MOZ_ASSERT(sVRManagerSingleton == nullptr);
|
MOZ_ASSERT(sVRManagerSingleton == nullptr);
|
||||||
|
@ -174,12 +176,8 @@ VRManager::RemoveVRManagerParent(VRManagerParent* aVRManagerParent)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
|
VRManager::UpdateRequestedDevices()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
|
|
||||||
const double kVRDisplayRefreshMaxDuration = 5000; // milliseconds
|
|
||||||
const double kVRDisplayInactiveMaxDuration = 30000; // milliseconds
|
|
||||||
|
|
||||||
bool bHaveEventListener = false;
|
bool bHaveEventListener = false;
|
||||||
bool bHaveControllerListener = false;
|
bool bHaveControllerListener = false;
|
||||||
|
|
||||||
|
@ -189,61 +187,55 @@ VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
|
||||||
bHaveControllerListener |= vmp->HaveControllerListener();
|
bHaveControllerListener |= vmp->HaveControllerListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
// VRDisplayHost::NotifyVSync may modify mVRDisplays, so we iterate
|
mVRDisplaysRequested = bHaveEventListener;
|
||||||
// through a local copy here.
|
// We only currently allow controllers to be used when
|
||||||
nsTArray<RefPtr<VRDisplayHost>> displays;
|
// also activating a VR display
|
||||||
for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
|
mVRControllersRequested = mVRDisplaysRequested && bHaveControllerListener;
|
||||||
displays.AppendElement(iter.UserData());
|
}
|
||||||
}
|
|
||||||
for (const auto& display: displays) {
|
/**
|
||||||
display->NotifyVSync();
|
* VRManager::NotifyVsync must be called on every 2d vsync (usually at 60hz).
|
||||||
|
* This must be called even when no WebVR site is active.
|
||||||
|
* If we don't have a 2d display attached to the system, we can call this
|
||||||
|
* at the VR display's native refresh rate.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
|
||||||
|
UpdateRequestedDevices();
|
||||||
|
|
||||||
|
for (const auto& manager : mManagers) {
|
||||||
|
manager->NotifyVSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bHaveEventListener) {
|
// We must continually refresh the VR display enumeration to check
|
||||||
// If content has set an EventHandler to be notified of VR display events
|
// for events that we must fire such as Window.onvrdisplayconnect
|
||||||
// we must continually refresh the VR display enumeration to check
|
// Note that enumeration itself may activate display hardware, such
|
||||||
// for events that we must fire such as Window.onvrdisplayconnect
|
// as Oculus, so we only do this when we know we are displaying content
|
||||||
// Note that enumeration itself may activate display hardware, such
|
// that is looking for VR displays.
|
||||||
// as Oculus, so we only do this when we know we are displaying content
|
RefreshVRDisplays();
|
||||||
// that is looking for VR displays.
|
|
||||||
if (mLastRefreshTime.IsNull()) {
|
|
||||||
// This is the first vsync, must refresh VR displays
|
|
||||||
RefreshVRDisplays();
|
|
||||||
if (bHaveControllerListener) {
|
|
||||||
RefreshVRControllers();
|
|
||||||
}
|
|
||||||
mLastRefreshTime = TimeStamp::Now();
|
|
||||||
} else {
|
|
||||||
// We don't have to do this every frame, so check if we
|
|
||||||
// have refreshed recently.
|
|
||||||
TimeDuration duration = TimeStamp::Now() - mLastRefreshTime;
|
|
||||||
if (duration.ToMilliseconds() > kVRDisplayRefreshMaxDuration) {
|
|
||||||
RefreshVRDisplays();
|
|
||||||
if (bHaveControllerListener) {
|
|
||||||
RefreshVRControllers();
|
|
||||||
}
|
|
||||||
mLastRefreshTime = TimeStamp::Now();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bHaveControllerListener) {
|
// Update state and enumeration of VR controllers
|
||||||
for (const auto& manager: mManagers) {
|
RefreshVRControllers();
|
||||||
if (!manager->GetIsPresenting()) {
|
|
||||||
manager->HandleInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
CheckForInactiveTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRManager::CheckForInactiveTimeout()
|
||||||
|
{
|
||||||
// Shut down the VR devices when not in use
|
// Shut down the VR devices when not in use
|
||||||
if (bHaveEventListener || bHaveControllerListener) {
|
if (mVRDisplaysRequested || mVRControllersRequested) {
|
||||||
// We are using a VR device, keep it alive
|
// We are using a VR device, keep it alive
|
||||||
mLastActiveTime = TimeStamp::Now();
|
mLastActiveTime = TimeStamp::Now();
|
||||||
} else if (mLastActiveTime.IsNull()) {
|
}
|
||||||
|
else if (mLastActiveTime.IsNull()) {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
TimeDuration duration = TimeStamp::Now() - mLastActiveTime;
|
TimeDuration duration = TimeStamp::Now() - mLastActiveTime;
|
||||||
if (duration.ToMilliseconds() > kVRDisplayInactiveMaxDuration) {
|
if (duration.ToMilliseconds() > gfxPrefs::VRInactiveTimeout()) {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,26 +259,80 @@ VRManager::NotifyVRVsync(const uint32_t& aDisplayID)
|
||||||
RefreshVRDisplays();
|
RefreshVRDisplays();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRManager::EnumerateVRDisplays()
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Throttle the rate of enumeration to the interval set in
|
||||||
|
* VRDisplayEnumerateInterval
|
||||||
|
*/
|
||||||
|
if (!mLastDisplayEnumerationTime.IsNull()) {
|
||||||
|
TimeDuration duration = TimeStamp::Now() - mLastDisplayEnumerationTime;
|
||||||
|
if (duration.ToMilliseconds() < gfxPrefs::VRDisplayEnumerateInterval()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any VRSystemManager instance may request that no enumeration
|
||||||
|
* should occur, including enumeration from other VRSystemManager
|
||||||
|
* instances.
|
||||||
|
*/
|
||||||
|
for (const auto& manager : mManagers) {
|
||||||
|
if (manager->ShouldInhibitEnumeration()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we get this far, don't try again until
|
||||||
|
* the VRDisplayEnumerateInterval elapses
|
||||||
|
*/
|
||||||
|
mLastDisplayEnumerationTime = TimeStamp::Now();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VRSystemManagers are inserted into mManagers in
|
||||||
|
* a strict order of priority. The managers for the
|
||||||
|
* most device-specialized API's will have a chance
|
||||||
|
* to enumerate devices before the more generic
|
||||||
|
* device-agnostic APIs.
|
||||||
|
*/
|
||||||
|
for (const auto& manager : mManagers) {
|
||||||
|
manager->Enumerate();
|
||||||
|
/**
|
||||||
|
* After a VRSystemManager::Enumerate is called, it may request
|
||||||
|
* that further enumeration should stop. This can be used to prevent
|
||||||
|
* erraneous redundant enumeration of the same HMD by multiple managers.
|
||||||
|
* XXX - Perhaps there will be a better way to detect duplicate displays
|
||||||
|
* in the future.
|
||||||
|
*/
|
||||||
|
if (manager->ShouldInhibitEnumeration()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VRManager::RefreshVRDisplays(bool aMustDispatch)
|
VRManager::RefreshVRDisplays(bool aMustDispatch)
|
||||||
{
|
{
|
||||||
nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
|
/**
|
||||||
|
* If we aren't viewing WebVR content, don't enumerate
|
||||||
|
* new hardware, as it will cause some devices to power on
|
||||||
|
* or interrupt other VR activities.
|
||||||
|
*/
|
||||||
|
if (mVRDisplaysRequested || aMustDispatch) {
|
||||||
|
EnumerateVRDisplays();
|
||||||
|
}
|
||||||
|
|
||||||
/** We don't wish to enumerate the same display from multiple managers,
|
/**
|
||||||
* so stop as soon as we get a display.
|
* VRSystemManager::GetHMDs will not activate new hardware
|
||||||
* It is still possible to get multiple displays from a single manager,
|
* or result in interruption of other VR activities.
|
||||||
* but do not wish to mix-and-match for risk of reporting a duplicate.
|
* We can call it even when suppressing enumeration to get
|
||||||
*
|
* the already-enumerated displays.
|
||||||
* XXX - Perhaps there will be a better way to detect duplicate displays
|
|
||||||
* in the future.
|
|
||||||
*/
|
*/
|
||||||
for (uint32_t i = 0; i < mManagers.Length() && displays.Length() == 0; ++i) {
|
nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
|
||||||
if (mManagers[i]->GetHMDs(displays)) {
|
for (const auto& manager: mManagers) {
|
||||||
// GetHMDs returns true to indicate that no further enumeration from
|
manager->GetHMDs(displays);
|
||||||
// other managers should be performed. This prevents erraneous
|
|
||||||
// redundant enumeration of the same HMD by multiple managers.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool displayInfoChanged = false;
|
bool displayInfoChanged = false;
|
||||||
|
@ -383,10 +429,10 @@ VRManager::GetVRControllerInfo(nsTArray<VRControllerInfo>& aControllerInfo)
|
||||||
void
|
void
|
||||||
VRManager::RefreshVRControllers()
|
VRManager::RefreshVRControllers()
|
||||||
{
|
{
|
||||||
nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
|
|
||||||
|
|
||||||
ScanForControllers();
|
ScanForControllers();
|
||||||
|
|
||||||
|
nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mManagers.Length()
|
for (uint32_t i = 0; i < mManagers.Length()
|
||||||
&& controllers.Length() == 0; ++i) {
|
&& controllers.Length() == 0; ++i) {
|
||||||
mManagers[i]->GetControllers(controllers);
|
mManagers[i]->GetControllers(controllers);
|
||||||
|
@ -419,9 +465,25 @@ VRManager::RefreshVRControllers()
|
||||||
void
|
void
|
||||||
VRManager::ScanForControllers()
|
VRManager::ScanForControllers()
|
||||||
{
|
{
|
||||||
|
// We don't have to do this every frame, so check if we
|
||||||
|
// have enumerated recently
|
||||||
|
if (!mLastControllerEnumerationTime.IsNull()) {
|
||||||
|
TimeDuration duration = TimeStamp::Now() - mLastControllerEnumerationTime;
|
||||||
|
if (duration.ToMilliseconds() < gfxPrefs::VRControllerEnumerateInterval()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only enumerate controllers once we need them
|
||||||
|
if (!mVRControllersRequested) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mManagers.Length(); ++i) {
|
for (uint32_t i = 0; i < mManagers.Length(); ++i) {
|
||||||
mManagers[i]->ScanForControllers();
|
mManagers[i]->ScanForControllers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLastControllerEnumerationTime = TimeStamp::Now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -64,6 +64,9 @@ private:
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void DispatchVRDisplayInfoUpdate();
|
void DispatchVRDisplayInfoUpdate();
|
||||||
|
void UpdateRequestedDevices();
|
||||||
|
void EnumerateVRDisplays();
|
||||||
|
void CheckForInactiveTimeout();
|
||||||
|
|
||||||
typedef nsTHashtable<nsRefPtrHashKey<VRManagerParent>> VRManagerParentSet;
|
typedef nsTHashtable<nsRefPtrHashKey<VRManagerParent>> VRManagerParentSet;
|
||||||
VRManagerParentSet mVRManagerParents;
|
VRManagerParentSet mVRManagerParents;
|
||||||
|
@ -79,9 +82,12 @@ private:
|
||||||
|
|
||||||
Atomic<bool> mInitialized;
|
Atomic<bool> mInitialized;
|
||||||
|
|
||||||
TimeStamp mLastRefreshTime;
|
TimeStamp mLastControllerEnumerationTime;
|
||||||
|
TimeStamp mLastDisplayEnumerationTime;
|
||||||
TimeStamp mLastActiveTime;
|
TimeStamp mLastActiveTime;
|
||||||
bool mVRTestSystemCreated;
|
bool mVRTestSystemCreated;
|
||||||
|
bool mVRDisplaysRequested;
|
||||||
|
bool mVRControllersRequested;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "gfxVR.h"
|
#include "gfxVR.h"
|
||||||
#include "mozilla/dom/GamepadEventTypes.h"
|
#include "mozilla/dom/GamepadEventTypes.h"
|
||||||
#include "mozilla/dom/GamepadBinding.h"
|
#include "mozilla/dom/GamepadBinding.h"
|
||||||
|
#include "VRDisplayHost.h"
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
# define M_PI 3.14159265358979323846
|
# define M_PI 3.14159265358979323846
|
||||||
|
@ -32,6 +33,58 @@ VRSystemManager::AllocateControllerID()
|
||||||
return ++sControllerBase;
|
return ++sControllerBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VRSystemManager::NotifyVsync must be called even when a WebVR site is
|
||||||
|
* not active, in order to poll for respond to VR Platform API requests.
|
||||||
|
* This should be called very often, ideally once per frame.
|
||||||
|
* VRSystemManager::Refresh will not activate VR hardware or
|
||||||
|
* initialize VR runtimes that have not already been activated.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
VRSystemManager::NotifyVSync()
|
||||||
|
{
|
||||||
|
// VRDisplayHost::NotifyVSync may modify mVRDisplays, so we iterate
|
||||||
|
// through a local copy here.
|
||||||
|
nsTArray<RefPtr<VRDisplayHost>> displays;
|
||||||
|
GetHMDs(displays);
|
||||||
|
for (const auto& display : displays) {
|
||||||
|
display->NotifyVSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the controller state is updated at least
|
||||||
|
// on every 2d display VSync when not in a VR presentation.
|
||||||
|
if (!GetIsPresenting()) {
|
||||||
|
HandleInput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VRSystemManager::GetHMDs must not be called unless
|
||||||
|
* VRSystemManager::ShouldInhibitEnumeration is called
|
||||||
|
* on all VRSystemManager instances and they all return
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* This is used to ensure that VR devices that can be
|
||||||
|
* enumerated by multiple API's are only enumerated by
|
||||||
|
* one API.
|
||||||
|
*
|
||||||
|
* GetHMDs is called for the most specific API
|
||||||
|
* (ie. Oculus SDK) first before calling GetHMDs on
|
||||||
|
* more generic api's (ie. OpenVR) to ensure that a device
|
||||||
|
* is accessed using the API most optimized for it.
|
||||||
|
*
|
||||||
|
* ShouldInhibitEnumeration may also be used to prevent
|
||||||
|
* devices from jumping to other API's when they are
|
||||||
|
* intentionally ignored, such as when responding to
|
||||||
|
* requests by the VR platform to unload the libraries
|
||||||
|
* for runtime software updates.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
VRSystemManager::ShouldInhibitEnumeration()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Matrix4x4
|
Matrix4x4
|
||||||
VRFieldOfView::ConstructProjectionMatrix(float zNear, float zFar,
|
VRFieldOfView::ConstructProjectionMatrix(float zNear, float zFar,
|
||||||
bool rightHanded) const
|
bool rightHanded) const
|
||||||
|
|
|
@ -347,7 +347,10 @@ public:
|
||||||
|
|
||||||
virtual void Destroy() = 0;
|
virtual void Destroy() = 0;
|
||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
virtual bool GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) = 0;
|
virtual void Enumerate() = 0;
|
||||||
|
virtual void NotifyVSync();
|
||||||
|
virtual bool ShouldInhibitEnumeration();
|
||||||
|
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) = 0;
|
||||||
virtual bool GetIsPresenting() = 0;
|
virtual bool GetIsPresenting() = 0;
|
||||||
virtual void HandleInput() = 0;
|
virtual void HandleInput() = 0;
|
||||||
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
|
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
|
||||||
|
|
|
@ -550,25 +550,51 @@ VRSystemManagerOSVR::Shutdown()
|
||||||
osvr_ClientShutdown(m_ctx);
|
osvr_ClientShutdown(m_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
VRSystemManagerOSVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
VRSystemManagerOSVR::NotifyVSync()
|
||||||
|
{
|
||||||
|
VRSystemManager::NotifyVSync();
|
||||||
|
|
||||||
|
// TODO - Check for device disconnection or other OSVR events
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRSystemManagerOSVR::Enumerate()
|
||||||
{
|
{
|
||||||
// make sure context, interface and display are initialized
|
// make sure context, interface and display are initialized
|
||||||
CheckOSVRStatus();
|
CheckOSVRStatus();
|
||||||
|
|
||||||
if (!Init()) {
|
if (!Init()) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mHMDInfo = new VRDisplayOSVR(&m_ctx, &m_iface, &m_display);
|
mHMDInfo = new VRDisplayOSVR(&m_ctx, &m_iface, &m_display);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
VRSystemManagerOSVR::ShouldInhibitEnumeration()
|
||||||
|
{
|
||||||
|
if (VRSystemManager::ShouldInhibitEnumeration()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (mHMDInfo) {
|
if (mHMDInfo) {
|
||||||
aHMDResult.AppendElement(mHMDInfo);
|
// When we find an a VR device, don't
|
||||||
|
// allow any further enumeration as it
|
||||||
|
// may get picked up redundantly by other
|
||||||
|
// API's.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRSystemManagerOSVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
||||||
|
{
|
||||||
|
if (mHMDInfo) {
|
||||||
|
aHMDResult.AppendElement(mHMDInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
VRSystemManagerOSVR::GetIsPresenting()
|
VRSystemManagerOSVR::GetIsPresenting()
|
||||||
{
|
{
|
||||||
|
|
|
@ -80,7 +80,10 @@ public:
|
||||||
static already_AddRefed<VRSystemManagerOSVR> Create();
|
static already_AddRefed<VRSystemManagerOSVR> Create();
|
||||||
virtual void Destroy() override;
|
virtual void Destroy() override;
|
||||||
virtual void Shutdown() override;
|
virtual void Shutdown() override;
|
||||||
virtual bool GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override;
|
virtual void NotifyVSync() override;
|
||||||
|
virtual void Enumerate() override;
|
||||||
|
virtual bool ShouldInhibitEnumeration() override;
|
||||||
|
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override;
|
||||||
virtual bool GetIsPresenting() override;
|
virtual bool GetIsPresenting() override;
|
||||||
virtual void HandleInput() override;
|
virtual void HandleInput() override;
|
||||||
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
|
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
|
||||||
|
|
|
@ -204,8 +204,11 @@ VROculusSession::VROculusSession()
|
||||||
, mSession(nullptr)
|
, mSession(nullptr)
|
||||||
, mInitFlags((ovrInitFlags)0)
|
, mInitFlags((ovrInitFlags)0)
|
||||||
, mTextureSet(nullptr)
|
, mTextureSet(nullptr)
|
||||||
, mPresenting(false)
|
, mRequestPresentation(false)
|
||||||
|
, mRequestTracking(false)
|
||||||
, mDrawBlack(false)
|
, mDrawBlack(false)
|
||||||
|
, mIsConnected(false)
|
||||||
|
, mIsMounted(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,26 +222,47 @@ VROculusSession::Get()
|
||||||
bool
|
bool
|
||||||
VROculusSession::IsTrackingReady() const
|
VROculusSession::IsTrackingReady() const
|
||||||
{
|
{
|
||||||
return mSession != nullptr;
|
// We should return true only if the HMD is connected and we
|
||||||
|
// are ready for tracking
|
||||||
|
MOZ_ASSERT(!mIsConnected || mSession);
|
||||||
|
return mIsConnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
VROculusSession::IsRenderReady() const
|
VROculusSession::IsPresentationReady() const
|
||||||
{
|
{
|
||||||
return !mRenderTargets.IsEmpty();
|
return !mRenderTargets.IsEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
VROculusSession::IsMounted() const
|
||||||
|
{
|
||||||
|
return mIsMounted;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VROculusSession::StopTracking()
|
VROculusSession::StopTracking()
|
||||||
{
|
{
|
||||||
Uninitialize(true);
|
if (mRequestTracking) {
|
||||||
|
mRequestTracking = false;
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VROculusSession::StartTracking()
|
||||||
|
{
|
||||||
|
if (!mRequestTracking) {
|
||||||
|
mRequestTracking = true;
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VROculusSession::StartPresentation(const IntSize& aSize)
|
VROculusSession::StartPresentation(const IntSize& aSize)
|
||||||
{
|
{
|
||||||
if (!mPresenting) {
|
if (!mRequestPresentation) {
|
||||||
mPresenting = true;
|
mRequestPresentation = true;
|
||||||
mTelemetry.Clear();
|
mTelemetry.Clear();
|
||||||
mTelemetry.mPresentationStart = TimeStamp::Now();
|
mTelemetry.mPresentationStart = TimeStamp::Now();
|
||||||
|
|
||||||
|
@ -258,9 +282,9 @@ VROculusSession::StartPresentation(const IntSize& aSize)
|
||||||
void
|
void
|
||||||
VROculusSession::StopPresentation()
|
VROculusSession::StopPresentation()
|
||||||
{
|
{
|
||||||
if (mPresenting) {
|
if (mRequestPresentation) {
|
||||||
mLastPresentationEnd = TimeStamp::Now();
|
mLastPresentationEnd = TimeStamp::Now();
|
||||||
mPresenting = false;
|
mRequestPresentation = false;
|
||||||
|
|
||||||
const TimeDuration duration = mLastPresentationEnd - mTelemetry.mPresentationStart;
|
const TimeDuration duration = mLastPresentationEnd - mTelemetry.mPresentationStart;
|
||||||
Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 1);
|
Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 1);
|
||||||
|
@ -315,6 +339,8 @@ VROculusSession::StopSession()
|
||||||
{
|
{
|
||||||
if (mSession) {
|
if (mSession) {
|
||||||
ovr_Destroy(mSession);
|
ovr_Destroy(mSession);
|
||||||
|
mIsConnected = false;
|
||||||
|
mIsMounted = false;
|
||||||
mSession = nullptr;
|
mSession = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,9 +363,14 @@ VROculusSession::Refresh(bool aForceRefresh)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mRequestTracking) {
|
||||||
|
Uninitialize(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ovrInitFlags flags = (ovrInitFlags)(ovrInit_RequestVersion | ovrInit_MixedRendering);
|
ovrInitFlags flags = (ovrInitFlags)(ovrInit_RequestVersion | ovrInit_MixedRendering);
|
||||||
bool bInvisible = true;
|
bool bInvisible = true;
|
||||||
if (mPresenting) {
|
if (mRequestPresentation) {
|
||||||
bInvisible = false;
|
bInvisible = false;
|
||||||
} else if (!mLastPresentationEnd.IsNull()) {
|
} else if (!mLastPresentationEnd.IsNull()) {
|
||||||
TimeDuration duration = TimeStamp::Now() - mLastPresentationEnd;
|
TimeDuration duration = TimeStamp::Now() - mLastPresentationEnd;
|
||||||
|
@ -384,15 +415,25 @@ VROculusSession::Refresh(bool aForceRefresh)
|
||||||
Uninitialize(false);
|
Uninitialize(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Initialize(flags);
|
if(!Initialize(flags)) {
|
||||||
|
// If we fail to initialize, ensure the Oculus libraries
|
||||||
|
// are unloaded, as we can't poll for ovrSessionStatus::ShouldQuit
|
||||||
|
// without an active ovrSession.
|
||||||
|
Uninitialize(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (mSession) {
|
if (mSession) {
|
||||||
ovrSessionStatus status;
|
ovrSessionStatus status;
|
||||||
if (OVR_SUCCESS(ovr_GetSessionStatus(mSession, &status))) {
|
if (OVR_SUCCESS(ovr_GetSessionStatus(mSession, &status))) {
|
||||||
|
mIsConnected = status.HmdPresent;
|
||||||
|
mIsMounted = status.HmdMounted;
|
||||||
if (status.ShouldQuit) {
|
if (status.ShouldQuit) {
|
||||||
mLastShouldQuit = TimeStamp::Now();
|
mLastShouldQuit = TimeStamp::Now();
|
||||||
Uninitialize(true);
|
Uninitialize(true);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
mIsConnected = false;
|
||||||
|
mIsMounted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,7 +478,7 @@ VROculusSession::Initialize(ovrInitFlags aFlags)
|
||||||
bool
|
bool
|
||||||
VROculusSession::StartRendering()
|
VROculusSession::StartRendering()
|
||||||
{
|
{
|
||||||
if (!mPresenting) {
|
if (!mRequestPresentation) {
|
||||||
// Nothing to do if we aren't presenting
|
// Nothing to do if we aren't presenting
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -973,7 +1014,7 @@ VRDisplayOculus::StartPresentation()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mSession->StartPresentation(IntSize(mDisplayInfo.mEyeResolution.width * 2, mDisplayInfo.mEyeResolution.height));
|
mSession->StartPresentation(IntSize(mDisplayInfo.mEyeResolution.width * 2, mDisplayInfo.mEyeResolution.height));
|
||||||
if (!mSession->IsRenderReady()) {
|
if (!mSession->IsPresentationReady()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1103,7 +1144,7 @@ VRDisplayOculus::SubmitFrame(ID3D11Texture2D* aSource,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mSession->IsRenderReady()) {
|
if (!mSession->IsPresentationReady()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1248,18 +1289,10 @@ VRDisplayOculus::SubmitFrame(ID3D11Texture2D* aSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VRDisplayOculus::NotifyVSync()
|
VRDisplayOculus::Refresh()
|
||||||
{
|
{
|
||||||
mSession->Refresh();
|
mDisplayInfo.mIsConnected = mSession->IsTrackingReady();
|
||||||
if (mSession->IsTrackingReady()) {
|
mDisplayInfo.mIsMounted = mSession->IsMounted();
|
||||||
ovrSessionStatus sessionStatus;
|
|
||||||
ovrResult ovr = ovr_GetSessionStatus(mSession->Get(), &sessionStatus);
|
|
||||||
mDisplayInfo.mIsConnected = (ovr == ovrSuccess && sessionStatus.HmdPresent);
|
|
||||||
} else {
|
|
||||||
mDisplayInfo.mIsConnected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
VRDisplayHost::NotifyVSync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VRControllerOculus::VRControllerOculus(dom::GamepadHand aHand, uint32_t aDisplayID)
|
VRControllerOculus::VRControllerOculus(dom::GamepadHand aHand, uint32_t aDisplayID)
|
||||||
|
@ -1517,37 +1550,66 @@ VRSystemManagerOculus::Shutdown()
|
||||||
mDisplay = nullptr;
|
mDisplay = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRSystemManagerOculus::NotifyVSync()
|
||||||
|
{
|
||||||
|
VRSystemManager::NotifyVSync();
|
||||||
|
if (!mSession) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mSession->Refresh();
|
||||||
|
if (mDisplay) {
|
||||||
|
mDisplay->Refresh();
|
||||||
|
}
|
||||||
|
// Detect disconnection
|
||||||
|
if (!mSession->IsTrackingReady()) {
|
||||||
|
// No HMD connected
|
||||||
|
mDisplay = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
VRSystemManagerOculus::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
VRSystemManagerOculus::ShouldInhibitEnumeration()
|
||||||
|
{
|
||||||
|
if (VRSystemManager::ShouldInhibitEnumeration()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mDisplay) {
|
||||||
|
// When we find an Oculus VR device, don't
|
||||||
|
// allow any further enumeration as it
|
||||||
|
// may get picked up redundantly by other
|
||||||
|
// API's such as OpenVR.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mSession && mSession->IsQuitTimeoutActive()) {
|
||||||
|
// When we are responding to ShouldQuit, we return true here
|
||||||
|
// to prevent further enumeration by other VRSystemManager's such as
|
||||||
|
// VRSystemManagerOpenVR which would also enumerate the connected Oculus
|
||||||
|
// HMD, resulting in interference with the Oculus runtime software updates.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRSystemManagerOculus::Enumerate()
|
||||||
{
|
{
|
||||||
if (!mSession) {
|
if (!mSession) {
|
||||||
mSession = new VROculusSession();
|
mSession = new VROculusSession();
|
||||||
}
|
}
|
||||||
mSession->Refresh();
|
mSession->StartTracking();
|
||||||
if (mSession->IsQuitTimeoutActive()) {
|
if (mDisplay == nullptr && mSession->IsTrackingReady()) {
|
||||||
// We have responded to a ShouldQuit flag set by the Oculus runtime
|
|
||||||
// and are waiting for a timeout duration to elapse before allowing
|
|
||||||
// re-initialization of the Oculus OVR lib. We return true in this case
|
|
||||||
// to prevent further enumeration by other VRSystemManager's such as
|
|
||||||
// VRSystemManagerOpenVR which would also enumerate the connected Oculus
|
|
||||||
// HMD, resulting in interference with the Oculus runtime software updates.
|
|
||||||
mDisplay = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mSession->IsTrackingReady()) {
|
|
||||||
// No HMD connected.
|
|
||||||
mDisplay = nullptr;
|
|
||||||
} else if (mDisplay == nullptr) {
|
|
||||||
// HMD Detected
|
// HMD Detected
|
||||||
mDisplay = new VRDisplayOculus(mSession);
|
mDisplay = new VRDisplayOculus(mSession);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRSystemManagerOculus::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
||||||
|
{
|
||||||
if (mDisplay) {
|
if (mDisplay) {
|
||||||
aHMDResult.AppendElement(mDisplay);
|
aHMDResult.AppendElement(mDisplay);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -42,12 +42,14 @@ class VROculusSession
|
||||||
public:
|
public:
|
||||||
VROculusSession();
|
VROculusSession();
|
||||||
void Refresh(bool aForceRefresh = false);
|
void Refresh(bool aForceRefresh = false);
|
||||||
|
void StartTracking();
|
||||||
|
void StopTracking();
|
||||||
bool IsTrackingReady() const;
|
bool IsTrackingReady() const;
|
||||||
bool IsRenderReady() const;
|
|
||||||
ovrSession Get();
|
|
||||||
void StartPresentation(const IntSize& aSize);
|
void StartPresentation(const IntSize& aSize);
|
||||||
void StopPresentation();
|
void StopPresentation();
|
||||||
void StopTracking();
|
bool IsPresentationReady() const;
|
||||||
|
bool IsMounted() const;
|
||||||
|
ovrSession Get();
|
||||||
bool IsQuitTimeoutActive();
|
bool IsQuitTimeoutActive();
|
||||||
already_AddRefed<layers::CompositingRenderTargetD3D11> GetNextRenderTarget();
|
already_AddRefed<layers::CompositingRenderTargetD3D11> GetNextRenderTarget();
|
||||||
ovrTextureSwapChain GetSwapChain();
|
ovrTextureSwapChain GetSwapChain();
|
||||||
|
@ -65,8 +67,12 @@ private:
|
||||||
// The timestamp of the last ending presentation
|
// The timestamp of the last ending presentation
|
||||||
TimeStamp mLastPresentationEnd;
|
TimeStamp mLastPresentationEnd;
|
||||||
VRTelemetry mTelemetry;
|
VRTelemetry mTelemetry;
|
||||||
bool mPresenting;
|
bool mRequestPresentation;
|
||||||
|
bool mRequestTracking;
|
||||||
|
bool mTracking;
|
||||||
bool mDrawBlack;
|
bool mDrawBlack;
|
||||||
|
bool mIsConnected;
|
||||||
|
bool mIsMounted;
|
||||||
|
|
||||||
~VROculusSession();
|
~VROculusSession();
|
||||||
void Uninitialize(bool aUnloadLib);
|
void Uninitialize(bool aUnloadLib);
|
||||||
|
@ -84,7 +90,6 @@ private:
|
||||||
class VRDisplayOculus : public VRDisplayHost
|
class VRDisplayOculus : public VRDisplayHost
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void NotifyVSync() override;
|
|
||||||
void ZeroSensor() override;
|
void ZeroSensor() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -100,6 +105,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
explicit VRDisplayOculus(VROculusSession* aSession);
|
explicit VRDisplayOculus(VROculusSession* aSession);
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
void Refresh();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~VRDisplayOculus();
|
virtual ~VRDisplayOculus();
|
||||||
|
@ -176,7 +182,10 @@ public:
|
||||||
static already_AddRefed<VRSystemManagerOculus> Create();
|
static already_AddRefed<VRSystemManagerOculus> Create();
|
||||||
virtual void Destroy() override;
|
virtual void Destroy() override;
|
||||||
virtual void Shutdown() override;
|
virtual void Shutdown() override;
|
||||||
virtual bool GetHMDs(nsTArray<RefPtr<VRDisplayHost> >& aHMDResult) override;
|
virtual void Enumerate() override;
|
||||||
|
virtual void NotifyVSync() override;
|
||||||
|
virtual bool ShouldInhibitEnumeration() override;
|
||||||
|
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost> >& aHMDResult) override;
|
||||||
virtual bool GetIsPresenting() override;
|
virtual bool GetIsPresenting() override;
|
||||||
virtual void HandleInput() override;
|
virtual void HandleInput() override;
|
||||||
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
|
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
|
||||||
|
|
|
@ -202,8 +202,10 @@ VRDisplayOpenVR::GetIsHmdPresent()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VRDisplayOpenVR::PollEvents()
|
VRDisplayOpenVR::Refresh()
|
||||||
{
|
{
|
||||||
|
mIsHmdPresent = ::vr::VR_IsHmdPresent();
|
||||||
|
|
||||||
::vr::VREvent_t event;
|
::vr::VREvent_t event;
|
||||||
while (mVRSystem && mVRSystem->PollNextEvent(&event, sizeof(event))) {
|
while (mVRSystem && mVRSystem->PollNextEvent(&event, sizeof(event))) {
|
||||||
switch (event.eventType) {
|
switch (event.eventType) {
|
||||||
|
@ -244,8 +246,6 @@ VRDisplayOpenVR::PollEvents()
|
||||||
VRHMDSensorState
|
VRHMDSensorState
|
||||||
VRDisplayOpenVR::GetSensorState()
|
VRDisplayOpenVR::GetSensorState()
|
||||||
{
|
{
|
||||||
PollEvents();
|
|
||||||
|
|
||||||
const uint32_t posesSize = ::vr::k_unTrackedDeviceIndex_Hmd + 1;
|
const uint32_t posesSize = ::vr::k_unTrackedDeviceIndex_Hmd + 1;
|
||||||
::vr::TrackedDevicePose_t poses[posesSize];
|
::vr::TrackedDevicePose_t poses[posesSize];
|
||||||
// Note: We *must* call WaitGetPoses in order for any rendering to happen at all.
|
// Note: We *must* call WaitGetPoses in order for any rendering to happen at all.
|
||||||
|
@ -422,17 +422,6 @@ VRDisplayOpenVR::SubmitFrame(MacIOSurface* aMacIOSurface,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
|
||||||
VRDisplayOpenVR::NotifyVSync()
|
|
||||||
{
|
|
||||||
// We check if HMD is available once per frame.
|
|
||||||
mIsHmdPresent = ::vr::VR_IsHmdPresent();
|
|
||||||
// Make sure we respond to OpenVR events even when not presenting
|
|
||||||
PollEvents();
|
|
||||||
|
|
||||||
VRDisplayHost::NotifyVSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
VRControllerOpenVR::VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aDisplayID,
|
VRControllerOpenVR::VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aDisplayID,
|
||||||
uint32_t aNumButtons, uint32_t aNumTriggers,
|
uint32_t aNumButtons, uint32_t aNumTriggers,
|
||||||
uint32_t aNumAxes, const nsCString& aId)
|
uint32_t aNumAxes, const nsCString& aId)
|
||||||
|
@ -633,50 +622,87 @@ VRSystemManagerOpenVR::Shutdown()
|
||||||
mVRSystem = nullptr;
|
mVRSystem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
VRSystemManagerOpenVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
VRSystemManagerOpenVR::NotifyVSync()
|
||||||
{
|
{
|
||||||
if (!::vr::VR_IsHmdPresent() ||
|
VRSystemManager::NotifyVSync();
|
||||||
(mOpenVRHMD && !mOpenVRHMD->GetIsHmdPresent())) {
|
|
||||||
// OpenVR runtime could be quit accidentally,
|
// Avoid doing anything unless we have already
|
||||||
// and we make it re-initialize.
|
// successfully enumerated and loaded the OpenVR
|
||||||
mOpenVRHMD = nullptr;
|
// runtime.
|
||||||
mVRSystem = nullptr;
|
if (mVRSystem == nullptr) {
|
||||||
} else if (mOpenVRHMD == nullptr) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mOpenVRHMD) {
|
||||||
|
mOpenVRHMD->Refresh();
|
||||||
|
if (!mOpenVRHMD->GetIsHmdPresent()) {
|
||||||
|
// OpenVR runtime could be quit accidentally
|
||||||
|
// or a device could be disconnected.
|
||||||
|
// We free up resources and must re-initialize
|
||||||
|
// if a device is detected again later.
|
||||||
|
mOpenVRHMD = nullptr;
|
||||||
|
mVRSystem = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRSystemManagerOpenVR::Enumerate()
|
||||||
|
{
|
||||||
|
if (mOpenVRHMD == nullptr && ::vr::VR_IsHmdPresent()) {
|
||||||
::vr::HmdError err;
|
::vr::HmdError err;
|
||||||
|
|
||||||
::vr::VR_Init(&err, ::vr::EVRApplicationType::VRApplication_Scene);
|
::vr::VR_Init(&err, ::vr::EVRApplicationType::VRApplication_Scene);
|
||||||
if (err) {
|
if (err) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
::vr::IVRSystem *system = (::vr::IVRSystem *)::vr::VR_GetGenericInterface(::vr::IVRSystem_Version, &err);
|
::vr::IVRSystem *system = (::vr::IVRSystem *)::vr::VR_GetGenericInterface(::vr::IVRSystem_Version, &err);
|
||||||
if (err || !system) {
|
if (err || !system) {
|
||||||
::vr::VR_Shutdown();
|
::vr::VR_Shutdown();
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
::vr::IVRChaperone *chaperone = (::vr::IVRChaperone *)::vr::VR_GetGenericInterface(::vr::IVRChaperone_Version, &err);
|
::vr::IVRChaperone *chaperone = (::vr::IVRChaperone *)::vr::VR_GetGenericInterface(::vr::IVRChaperone_Version, &err);
|
||||||
if (err || !chaperone) {
|
if (err || !chaperone) {
|
||||||
::vr::VR_Shutdown();
|
::vr::VR_Shutdown();
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
::vr::IVRCompositor *compositor = (::vr::IVRCompositor*)::vr::VR_GetGenericInterface(::vr::IVRCompositor_Version, &err);
|
::vr::IVRCompositor *compositor = (::vr::IVRCompositor*)::vr::VR_GetGenericInterface(::vr::IVRCompositor_Version, &err);
|
||||||
if (err || !compositor) {
|
if (err || !compositor) {
|
||||||
::vr::VR_Shutdown();
|
::vr::VR_Shutdown();
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mVRSystem = system;
|
mVRSystem = system;
|
||||||
mOpenVRHMD = new VRDisplayOpenVR(system, chaperone, compositor);
|
mOpenVRHMD = new VRDisplayOpenVR(system, chaperone, compositor);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
VRSystemManagerOpenVR::ShouldInhibitEnumeration()
|
||||||
|
{
|
||||||
|
if (VRSystemManager::ShouldInhibitEnumeration()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (mOpenVRHMD) {
|
if (mOpenVRHMD) {
|
||||||
aHMDResult.AppendElement(mOpenVRHMD);
|
// When we find an a VR device, don't
|
||||||
|
// allow any further enumeration as it
|
||||||
|
// may get picked up redundantly by other
|
||||||
|
// API's.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRSystemManagerOpenVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
||||||
|
{
|
||||||
|
if (mOpenVRHMD) {
|
||||||
|
aHMDResult.AppendElement(mOpenVRHMD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
VRSystemManagerOpenVR::GetIsPresenting()
|
VRSystemManagerOpenVR::GetIsPresenting()
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,6 @@ namespace impl {
|
||||||
class VRDisplayOpenVR : public VRDisplayHost
|
class VRDisplayOpenVR : public VRDisplayHost
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void NotifyVSync() override;
|
|
||||||
void ZeroSensor() override;
|
void ZeroSensor() override;
|
||||||
bool GetIsHmdPresent();
|
bool GetIsHmdPresent();
|
||||||
|
|
||||||
|
@ -54,7 +53,7 @@ public:
|
||||||
explicit VRDisplayOpenVR(::vr::IVRSystem *aVRSystem,
|
explicit VRDisplayOpenVR(::vr::IVRSystem *aVRSystem,
|
||||||
::vr::IVRChaperone *aVRChaperone,
|
::vr::IVRChaperone *aVRChaperone,
|
||||||
::vr::IVRCompositor *aVRCompositor);
|
::vr::IVRCompositor *aVRCompositor);
|
||||||
|
void Refresh();
|
||||||
protected:
|
protected:
|
||||||
virtual ~VRDisplayOpenVR();
|
virtual ~VRDisplayOpenVR();
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
@ -70,7 +69,6 @@ protected:
|
||||||
|
|
||||||
void UpdateStageParameters();
|
void UpdateStageParameters();
|
||||||
void UpdateEyeParameters(gfx::Matrix4x4* aHeadToEyeTransforms = nullptr);
|
void UpdateEyeParameters(gfx::Matrix4x4* aHeadToEyeTransforms = nullptr);
|
||||||
void PollEvents();
|
|
||||||
bool SubmitFrame(void* aTextureHandle,
|
bool SubmitFrame(void* aTextureHandle,
|
||||||
::vr::ETextureType aTextureType,
|
::vr::ETextureType aTextureType,
|
||||||
const IntSize& aSize,
|
const IntSize& aSize,
|
||||||
|
@ -127,7 +125,10 @@ public:
|
||||||
|
|
||||||
virtual void Destroy() override;
|
virtual void Destroy() override;
|
||||||
virtual void Shutdown() override;
|
virtual void Shutdown() override;
|
||||||
virtual bool GetHMDs(nsTArray<RefPtr<VRDisplayHost> >& aHMDResult) override;
|
virtual void NotifyVSync() override;
|
||||||
|
virtual void Enumerate() override;
|
||||||
|
virtual bool ShouldInhibitEnumeration() override;
|
||||||
|
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override;
|
||||||
virtual bool GetIsPresenting() override;
|
virtual bool GetIsPresenting() override;
|
||||||
virtual void HandleInput() override;
|
virtual void HandleInput() override;
|
||||||
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
|
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
|
||||||
|
|
|
@ -566,12 +566,10 @@ VRDisplayPuppet::SubmitFrame(const mozilla::layers::EGLImageDescriptor* aDescrip
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
VRDisplayPuppet::NotifyVSync()
|
VRDisplayPuppet::Refresh()
|
||||||
{
|
{
|
||||||
// We update mIsConneced once per frame.
|
// We update mIsConneced once per refresh.
|
||||||
mDisplayInfo.mIsConnected = true;
|
mDisplayInfo.mIsConnected = true;
|
||||||
|
|
||||||
VRDisplayHost::NotifyVSync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VRControllerPuppet::VRControllerPuppet(dom::GamepadHand aHand, uint32_t aDisplayID)
|
VRControllerPuppet::VRControllerPuppet(dom::GamepadHand aHand, uint32_t aDisplayID)
|
||||||
|
@ -703,14 +701,45 @@ VRSystemManagerPuppet::Shutdown()
|
||||||
mPuppetHMD = nullptr;
|
mPuppetHMD = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
VRSystemManagerPuppet::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
VRSystemManagerPuppet::NotifyVSync()
|
||||||
|
{
|
||||||
|
VRSystemManager::NotifyVSync();
|
||||||
|
if (mPuppetHMD) {
|
||||||
|
mPuppetHMD->Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRSystemManagerPuppet::Enumerate()
|
||||||
{
|
{
|
||||||
if (mPuppetHMD == nullptr) {
|
if (mPuppetHMD == nullptr) {
|
||||||
mPuppetHMD = new VRDisplayPuppet();
|
mPuppetHMD = new VRDisplayPuppet();
|
||||||
}
|
}
|
||||||
aHMDResult.AppendElement(mPuppetHMD);
|
}
|
||||||
return true;
|
|
||||||
|
bool
|
||||||
|
VRSystemManagerPuppet::ShouldInhibitEnumeration()
|
||||||
|
{
|
||||||
|
if (VRSystemManager::ShouldInhibitEnumeration()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mPuppetHMD) {
|
||||||
|
// When we find an a VR device, don't
|
||||||
|
// allow any further enumeration as it
|
||||||
|
// may get picked up redundantly by other
|
||||||
|
// API's.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VRSystemManagerPuppet::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
||||||
|
{
|
||||||
|
if (mPuppetHMD) {
|
||||||
|
aHMDResult.AppendElement(mPuppetHMD);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -24,7 +24,6 @@ class VRDisplayPuppet : public VRDisplayHost
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void SetDisplayInfo(const VRDisplayInfo& aDisplayInfo);
|
void SetDisplayInfo(const VRDisplayInfo& aDisplayInfo);
|
||||||
virtual void NotifyVSync() override;
|
|
||||||
void SetSensorState(const VRHMDSensorState& aSensorState);
|
void SetSensorState(const VRHMDSensorState& aSensorState);
|
||||||
void ZeroSensor() override;
|
void ZeroSensor() override;
|
||||||
|
|
||||||
|
@ -50,6 +49,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit VRDisplayPuppet();
|
explicit VRDisplayPuppet();
|
||||||
|
void Refresh();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~VRDisplayPuppet();
|
virtual ~VRDisplayPuppet();
|
||||||
|
@ -110,7 +110,9 @@ public:
|
||||||
|
|
||||||
virtual void Destroy() override;
|
virtual void Destroy() override;
|
||||||
virtual void Shutdown() override;
|
virtual void Shutdown() override;
|
||||||
virtual bool GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override;
|
virtual void Enumerate() override;
|
||||||
|
virtual bool ShouldInhibitEnumeration() override;
|
||||||
|
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override;
|
||||||
virtual bool GetIsPresenting() override;
|
virtual bool GetIsPresenting() override;
|
||||||
virtual void HandleInput() override;
|
virtual void HandleInput() override;
|
||||||
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
|
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
|
||||||
|
@ -123,6 +125,7 @@ public:
|
||||||
double aDuration,
|
double aDuration,
|
||||||
uint32_t aPromiseID) override;
|
uint32_t aPromiseID) override;
|
||||||
virtual void StopVibrateHaptic(uint32_t aControllerIdx) override;
|
virtual void StopVibrateHaptic(uint32_t aControllerIdx) override;
|
||||||
|
virtual void NotifyVSync() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
VRSystemManagerPuppet();
|
VRSystemManagerPuppet();
|
||||||
|
|
|
@ -5157,6 +5157,20 @@ pref("dom.vr.openvr.enabled", true);
|
||||||
// See Bug 1310663 (Linux)
|
// See Bug 1310663 (Linux)
|
||||||
pref("dom.vr.openvr.enabled", false);
|
pref("dom.vr.openvr.enabled", false);
|
||||||
#endif
|
#endif
|
||||||
|
// Minimum number of milliseconds that the browser will wait before
|
||||||
|
// attempting to poll again for connected VR controllers. The browser
|
||||||
|
// will not attempt to poll for VR controllers until it needs to use them.
|
||||||
|
pref("dom.vr.controller.enumerate.interval", 1000);
|
||||||
|
// Minimum number of milliseconds that the browser will wait before
|
||||||
|
// attempting to poll again for connected VR displays. The browser
|
||||||
|
// will not attempt to poll for VR displays until it needs to use
|
||||||
|
// them, such as when detecting a WebVR site.
|
||||||
|
pref("dom.vr.display.enumerate.interval", 5000);
|
||||||
|
// Minimum number of milliseconds that the VR session will be kept
|
||||||
|
// alive after the browser and content no longer are using the
|
||||||
|
// hardware. If a VR multitasking environment, this should be set
|
||||||
|
// very low or set to 0.
|
||||||
|
pref("dom.vr.inactive.timeout", 5000);
|
||||||
// Pose prediction reduces latency effects by returning future predicted HMD
|
// Pose prediction reduces latency effects by returning future predicted HMD
|
||||||
// poses to callers of the WebVR API. This currently only has an effect for
|
// poses to callers of the WebVR API. This currently only has an effect for
|
||||||
// Oculus Rift on SDK 0.8 or greater.
|
// Oculus Rift on SDK 0.8 or greater.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче