--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -362,16 +362,19 @@ private:
DECL_GFX_PREF(Live, "dom.vr.autoactivate.enabled", VRAutoActivateEnabled, bool, false);
DECL_GFX_PREF(Live, "dom.vr.controller_trigger_threshold", VRControllerTriggerThreshold, float, 0.1f);
DECL_GFX_PREF(Live, "dom.vr.navigation.timeout", VRNavigationTimeout, int32_t, 1000);
DECL_GFX_PREF(Once, "dom.vr.oculus.enabled", VROculusEnabled, bool, true);
DECL_GFX_PREF(Live, "dom.vr.oculus.present.timeout", VROculusPresentTimeout, int32_t, 10000);
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.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.require-gesture", VRRequireGesture, bool, true);
DECL_GFX_PREF(Live, "dom.vr.puppet.enabled", VRPuppetEnabled, bool, false);
DECL_GFX_PREF(Live, "dom.vr.puppet.submitframe", VRPuppetSubmitFrame, uint32_t, 0);
DECL_GFX_PREF(Live, "dom.vr.display.rafMaxDuration", VRDisplayRafMaxDuration, uint32_t, 50);
DECL_GFX_PREF(Live, "dom.w3c_pointer_events.enabled", PointerEventsEnabled, bool, false);
DECL_GFX_PREF(Live, "general.smoothScroll", SmoothScrollEnabled, bool, true);
--- a/gfx/vr/VRDisplayHost.h
+++ b/gfx/vr/VRDisplayHost.h
@@ -36,17 +36,17 @@ public:
const VRDisplayInfo& GetDisplayInfo() const { return mDisplayInfo; }
void AddLayer(VRLayerParent* aLayer);
void RemoveLayer(VRLayerParent* aLayer);
virtual void ZeroSensor() = 0;
virtual void StartPresentation() = 0;
virtual void StopPresentation() = 0;
- virtual void NotifyVSync();
+ void NotifyVSync();
void StartFrame();
void SubmitFrame(VRLayerParent* aLayer,
const layers::SurfaceDescriptor& aTexture,
uint64_t aFrameId,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect);
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -51,16 +51,18 @@ VRManager::ManagerInit()
sVRManagerSingleton = new VRManager();
ClearOnShutdown(&sVRManagerSingleton);
}
}
VRManager::VRManager()
: mInitialized(false)
, mVRTestSystemCreated(false)
+ , mVRDisplaysRequested(false)
+ , mVRControllersRequested(false)
{
MOZ_COUNT_CTOR(VRManager);
MOZ_ASSERT(sVRManagerSingleton == nullptr);
RefPtr<VRSystemManager> mgr;
/**
* We must add the VRDisplayManager's to mManagers in a careful order to
@@ -169,86 +171,76 @@ VRManager::RemoveVRManagerParent(VRManag
{
mVRManagerParents.RemoveEntry(aVRManagerParent);
if (mVRManagerParents.IsEmpty()) {
Destroy();
}
}
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 bHaveControllerListener = false;
for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
VRManagerParent *vmp = iter.Get()->GetKey();
bHaveEventListener |= vmp->HaveEventListener();
bHaveControllerListener |= vmp->HaveControllerListener();
}
- // VRDisplayHost::NotifyVSync may modify mVRDisplays, so we iterate
- // through a local copy here.
- nsTArray<RefPtr<VRDisplayHost>> displays;
- for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
- displays.AppendElement(iter.UserData());
- }
- for (const auto& display: displays) {
- display->NotifyVSync();
+ mVRDisplaysRequested = bHaveEventListener;
+ // We only currently allow controllers to be used when
+ // also activating a VR display
+ mVRControllersRequested = mVRDisplaysRequested && bHaveControllerListener;
+}
+
+/**
+ * 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) {
- // If content has set an EventHandler to be notified of VR display events
- // 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
- // as Oculus, so we only do this when we know we are displaying content
- // 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();
- }
- }
+ // 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
+ // as Oculus, so we only do this when we know we are displaying content
+ // that is looking for VR displays.
+ RefreshVRDisplays();
- if (bHaveControllerListener) {
- for (const auto& manager: mManagers) {
- if (!manager->GetIsPresenting()) {
- manager->HandleInput();
- }
- }
- }
- }
+ // Update state and enumeration of VR controllers
+ RefreshVRControllers();
+
+ CheckForInactiveTimeout();
+}
+void
+VRManager::CheckForInactiveTimeout()
+{
// Shut down the VR devices when not in use
- if (bHaveEventListener || bHaveControllerListener) {
+ if (mVRDisplaysRequested || mVRControllersRequested) {
// We are using a VR device, keep it alive
mLastActiveTime = TimeStamp::Now();
- } else if (mLastActiveTime.IsNull()) {
+ }
+ else if (mLastActiveTime.IsNull()) {
Shutdown();
- } else {
+ }
+ else {
TimeDuration duration = TimeStamp::Now() - mLastActiveTime;
- if (duration.ToMilliseconds() > kVRDisplayInactiveMaxDuration) {
+ if (duration.ToMilliseconds() > gfxPrefs::VRInactiveTimeout()) {
Shutdown();
}
}
}
void
VRManager::NotifyVRVsync(const uint32_t& aDisplayID)
{
@@ -263,35 +255,89 @@ VRManager::NotifyVRVsync(const uint32_t&
if (display) {
display->StartFrame();
}
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
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.
- * It is still possible to get multiple displays from a single manager,
- * but do not wish to mix-and-match for risk of reporting a duplicate.
- *
- * XXX - Perhaps there will be a better way to detect duplicate displays
- * in the future.
+ /**
+ * VRSystemManager::GetHMDs will not activate new hardware
+ * or result in interruption of other VR activities.
+ * We can call it even when suppressing enumeration to get
+ * the already-enumerated displays.
*/
- for (uint32_t i = 0; i < mManagers.Length() && displays.Length() == 0; ++i) {
- if (mManagers[i]->GetHMDs(displays)) {
- // GetHMDs returns true to indicate that no further enumeration from
- // other managers should be performed. This prevents erraneous
- // redundant enumeration of the same HMD by multiple managers.
- break;
- }
+ nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
+ for (const auto& manager: mManagers) {
+ manager->GetHMDs(displays);
}
bool displayInfoChanged = false;
bool displaySetChanged = false;
if (displays.Length() != mVRDisplays.Count()) {
// Catch cases where a VR display has been removed
displaySetChanged = true;
@@ -378,19 +424,19 @@ VRManager::GetVRControllerInfo(nsTArray<
gfx::VRControllerHost* controller = iter.UserData();
aControllerInfo.AppendElement(VRControllerInfo(controller->GetControllerInfo()));
}
}
void
VRManager::RefreshVRControllers()
{
- nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
+ ScanForControllers();
- ScanForControllers();
+ nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
for (uint32_t i = 0; i < mManagers.Length()
&& controllers.Length() == 0; ++i) {
mManagers[i]->GetControllers(controllers);
}
bool controllerInfoChanged = false;
@@ -414,19 +460,35 @@ VRManager::RefreshVRControllers()
controller);
}
}
}
void
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) {
mManagers[i]->ScanForControllers();
}
+
+ mLastControllerEnumerationTime = TimeStamp::Now();
}
void
VRManager::RemoveControllers()
{
for (uint32_t i = 0; i < mManagers.Length(); ++i) {
mManagers[i]->RemoveControllers();
}
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -59,32 +59,38 @@ protected:
private:
void Init();
void Destroy();
void Shutdown();
void DispatchVRDisplayInfoUpdate();
+ void UpdateRequestedDevices();
+ void EnumerateVRDisplays();
+ void CheckForInactiveTimeout();
typedef nsTHashtable<nsRefPtrHashKey<VRManagerParent>> VRManagerParentSet;
VRManagerParentSet mVRManagerParents;
typedef nsTArray<RefPtr<VRSystemManager>> VRSystemManagerArray;
VRSystemManagerArray mManagers;
typedef nsRefPtrHashtable<nsUint32HashKey, gfx::VRDisplayHost> VRDisplayHostHashMap;
VRDisplayHostHashMap mVRDisplays;
typedef nsRefPtrHashtable<nsUint32HashKey, gfx::VRControllerHost> VRControllerHostHashMap;
VRControllerHostHashMap mVRControllers;
Atomic<bool> mInitialized;
- TimeStamp mLastRefreshTime;
+ TimeStamp mLastControllerEnumerationTime;
+ TimeStamp mLastDisplayEnumerationTime;
TimeStamp mLastActiveTime;
bool mVRTestSystemCreated;
+ bool mVRDisplaysRequested;
+ bool mVRControllersRequested;
};
} // namespace gfx
} // namespace mozilla
#endif // GFX_VR_MANAGER_H
--- a/gfx/vr/gfxVR.cpp
+++ b/gfx/vr/gfxVR.cpp
@@ -4,16 +4,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <math.h>
#include "gfxVR.h"
#include "mozilla/dom/GamepadEventTypes.h"
#include "mozilla/dom/GamepadBinding.h"
+#include "VRDisplayHost.h"
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
using namespace mozilla;
using namespace mozilla::gfx;
@@ -27,16 +28,68 @@ VRSystemManager::AllocateDisplayID()
}
/* static */ uint32_t
VRSystemManager::AllocateControllerID()
{
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
VRFieldOfView::ConstructProjectionMatrix(float zNear, float zFar,
bool rightHanded) const
{
float upTan = tan(upDegrees * M_PI / 180.0);
float downTan = tan(downDegrees * M_PI / 180.0);
float leftTan = tan(leftDegrees * M_PI / 180.0);
float rightTan = tan(rightDegrees * M_PI / 180.0);
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -343,17 +343,20 @@ protected:
static Atomic<uint32_t> sDisplayBase;
static Atomic<uint32_t> sControllerBase;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRSystemManager)
virtual void Destroy() = 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 void HandleInput() = 0;
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
virtual void ScanForControllers() = 0;
virtual void RemoveControllers() = 0;
virtual void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
double aIntensity, double aDuration, const VRManagerPromise& aPromise) = 0;
virtual void StopVibrateHaptic(uint32_t aControllerIdx) = 0;
--- a/gfx/vr/gfxVROSVR.cpp
+++ b/gfx/vr/gfxVROSVR.cpp
@@ -545,35 +545,61 @@ VRSystemManagerOSVR::Shutdown()
if (m_ctx) {
osvr_ClientFreeDisplay(m_display);
}
// osvr checks that m_ctx or m_iface are not null
osvr_ClientFreeInterface(m_ctx, m_iface);
osvr_ClientShutdown(m_ctx);
}
-bool
-VRSystemManagerOSVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
+void
+VRSystemManagerOSVR::NotifyVSync()
+{
+ VRSystemManager::NotifyVSync();
+
+ // TODO - Check for device disconnection or other OSVR events
+}
+
+void
+VRSystemManagerOSVR::Enumerate()
{
// make sure context, interface and display are initialized
CheckOSVRStatus();
if (!Init()) {
- return false;
+ return;
}
mHMDInfo = new VRDisplayOSVR(&m_ctx, &m_iface, &m_display);
+}
+bool
+VRSystemManagerOSVR::ShouldInhibitEnumeration()
+{
+ if (VRSystemManager::ShouldInhibitEnumeration()) {
+ return true;
+ }
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 false;
}
+void
+VRSystemManagerOSVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
+{
+ if (mHMDInfo) {
+ aHMDResult.AppendElement(mHMDInfo);
+ }
+}
+
bool
VRSystemManagerOSVR::GetIsPresenting()
{
if (mHMDInfo) {
VRDisplayInfo displayInfo(mHMDInfo->GetDisplayInfo());
return displayInfo.GetPresentingGroups() != kVRGroupNone;
}
--- a/gfx/vr/gfxVROSVR.h
+++ b/gfx/vr/gfxVROSVR.h
@@ -75,17 +75,20 @@ protected:
} // namespace impl
class VRSystemManagerOSVR : public VRSystemManager
{
public:
static already_AddRefed<VRSystemManagerOSVR> Create();
virtual void Destroy() 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 void HandleInput() override;
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
aControllerResult) override;
virtual void ScanForControllers() override;
virtual void RemoveControllers() override;
virtual void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
double aIntensity, double aDuration,
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -200,51 +200,75 @@ FromFovPort(const ovrFovPort& aFOV)
} // namespace
VROculusSession::VROculusSession()
: mOvrLib(nullptr)
, mSession(nullptr)
, mInitFlags((ovrInitFlags)0)
, mTextureSet(nullptr)
- , mPresenting(false)
+ , mRequestPresentation(false)
+ , mRequestTracking(false)
, mDrawBlack(false)
+ , mIsConnected(false)
+ , mIsMounted(false)
{
}
ovrSession
VROculusSession::Get()
{
MOZ_ASSERT(mSession);
return mSession;
}
bool
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
-VROculusSession::IsRenderReady() const
+VROculusSession::IsPresentationReady() const
{
return !mRenderTargets.IsEmpty();
}
+bool
+VROculusSession::IsMounted() const
+{
+ return mIsMounted;
+}
+
void
VROculusSession::StopTracking()
{
- Uninitialize(true);
+ if (mRequestTracking) {
+ mRequestTracking = false;
+ Refresh();
+ }
+}
+
+void
+VROculusSession::StartTracking()
+{
+ if (!mRequestTracking) {
+ mRequestTracking = true;
+ Refresh();
+ }
}
void
VROculusSession::StartPresentation(const IntSize& aSize)
{
- if (!mPresenting) {
- mPresenting = true;
+ if (!mRequestPresentation) {
+ mRequestPresentation = true;
mTelemetry.Clear();
mTelemetry.mPresentationStart = TimeStamp::Now();
ovrPerfStats perfStats;
if (ovr_GetPerfStats(mSession, &perfStats) == ovrSuccess) {
if (perfStats.FrameStatsCount) {
mTelemetry.mLastDroppedFrameCount = perfStats.FrameStats[0].AppDroppedFrameCount;
}
@@ -254,19 +278,19 @@ VROculusSession::StartPresentation(const
// Update the size, even when we are already presenting.
mPresentationSize = aSize;
Refresh();
}
void
VROculusSession::StopPresentation()
{
- if (mPresenting) {
+ if (mRequestPresentation) {
mLastPresentationEnd = TimeStamp::Now();
- mPresenting = false;
+ mRequestPresentation = false;
const TimeDuration duration = mLastPresentationEnd - mTelemetry.mPresentationStart;
Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 1);
Telemetry::Accumulate(Telemetry::WEBVR_TIME_SPENT_VIEWING_IN_OCULUS,
duration.ToMilliseconds());
if (mTelemetry.IsLastDroppedFrameValid() && duration.ToSeconds()) {
ovrPerfStats perfStats;
@@ -311,16 +335,18 @@ VROculusSession::StopRendering()
mDevice = nullptr;
}
void
VROculusSession::StopSession()
{
if (mSession) {
ovr_Destroy(mSession);
+ mIsConnected = false;
+ mIsMounted = false;
mSession = nullptr;
}
}
void
VROculusSession::StopLib()
{
if (mInitFlags) {
@@ -333,19 +359,24 @@ void
VROculusSession::Refresh(bool aForceRefresh)
{
// We are waiting for drawing the black layer command for
// Compositor thread. Ignore Refresh() calls from other threads.
if (mDrawBlack && !aForceRefresh) {
return;
}
+ if (!mRequestTracking) {
+ Uninitialize(true);
+ return;
+ }
+
ovrInitFlags flags = (ovrInitFlags)(ovrInit_RequestVersion | ovrInit_MixedRendering);
bool bInvisible = true;
- if (mPresenting) {
+ if (mRequestPresentation) {
bInvisible = false;
} else if (!mLastPresentationEnd.IsNull()) {
TimeDuration duration = TimeStamp::Now() - mLastPresentationEnd;
TimeDuration timeout = TimeDuration::FromMilliseconds(gfxPrefs::VROculusPresentTimeout());
if (timeout > TimeDuration(0) && duration < timeout) {
// Do not immediately re-initialize with an invisible session after
// the end of a VR presentation. Waiting for the configured duraction
// ensures that the user will not drop to Oculus Home during VR link
@@ -380,25 +411,35 @@ VROculusSession::Refresh(bool aForceRefr
if (bInvisible) {
flags = (ovrInitFlags)(flags | ovrInit_Invisible);
}
if (mInitFlags != flags) {
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) {
ovrSessionStatus status;
if (OVR_SUCCESS(ovr_GetSessionStatus(mSession, &status))) {
+ mIsConnected = status.HmdPresent;
+ mIsMounted = status.HmdMounted;
if (status.ShouldQuit) {
mLastShouldQuit = TimeStamp::Now();
Uninitialize(true);
}
+ } else {
+ mIsConnected = false;
+ mIsMounted = false;
}
}
}
bool
VROculusSession::IsQuitTimeoutActive()
{
// If Oculus asked us to quit our session, do not try to initialize again
@@ -433,17 +474,17 @@ VROculusSession::Initialize(ovrInitFlags
return false;
}
return true;
}
bool
VROculusSession::StartRendering()
{
- if (!mPresenting) {
+ if (!mRequestPresentation) {
// Nothing to do if we aren't presenting
return true;
}
if (!mDevice) {
mDevice = gfx::DeviceManagerDx::Get()->GetVRDevice();
if (!mDevice) {
NS_WARNING("Failed to get a D3D11Device for Oculus");
return false;
@@ -969,17 +1010,17 @@ VRDisplayOculus::GetSensorState(double a
void
VRDisplayOculus::StartPresentation()
{
if (!CreateD3DObjects()) {
return;
}
mSession->StartPresentation(IntSize(mDisplayInfo.mEyeResolution.width * 2, mDisplayInfo.mEyeResolution.height));
- if (!mSession->IsRenderReady()) {
+ if (!mSession->IsPresentationReady()) {
return;
}
if (!mQuadVS) {
if (FAILED(mDevice->CreateVertexShader(sLayerQuadVS.mData, sLayerQuadVS.mLength, nullptr, &mQuadVS))) {
NS_WARNING("Failed to create vertex shader for Oculus");
return;
}
@@ -1099,17 +1140,17 @@ VRDisplayOculus::SubmitFrame(ID3D11Textu
return false;
}
AutoRestoreRenderState restoreState(this);
if (!restoreState.IsSuccess()) {
return false;
}
- if (!mSession->IsRenderReady()) {
+ if (!mSession->IsPresentationReady()) {
return false;
}
/**
* XXX - We should resolve fail the promise returned by
* VRDisplay.requestPresent() when the DX11 resources fail allocation
* in VRDisplayOculus::StartPresentation().
* Bailing out here prevents the crash but content should be aware
* that frames are not being presented.
@@ -1244,28 +1285,20 @@ VRDisplayOculus::SubmitFrame(ID3D11Textu
*/
return false;
}
return true;
}
void
-VRDisplayOculus::NotifyVSync()
+VRDisplayOculus::Refresh()
{
- mSession->Refresh();
- if (mSession->IsTrackingReady()) {
- ovrSessionStatus sessionStatus;
- ovrResult ovr = ovr_GetSessionStatus(mSession->Get(), &sessionStatus);
- mDisplayInfo.mIsConnected = (ovr == ovrSuccess && sessionStatus.HmdPresent);
- } else {
- mDisplayInfo.mIsConnected = false;
- }
-
- VRDisplayHost::NotifyVSync();
+ mDisplayInfo.mIsConnected = mSession->IsTrackingReady();
+ mDisplayInfo.mIsMounted = mSession->IsMounted();
}
VRControllerOculus::VRControllerOculus(dom::GamepadHand aHand, uint32_t aDisplayID)
: VRControllerHost(VRDeviceType::Oculus, aHand, aDisplayID)
, mIndexTrigger(0.0f)
, mHandTrigger(0.0f)
, mVibrateThread(nullptr)
, mIsVibrateStopped(false)
@@ -1516,47 +1549,76 @@ VRSystemManagerOculus::Shutdown()
}
RemoveControllers();
if (mDisplay) {
mDisplay->Destroy();
}
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
-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) {
mSession = new VROculusSession();
}
- mSession->Refresh();
- if (mSession->IsQuitTimeoutActive()) {
- // 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) {
+ mSession->StartTracking();
+ if (mDisplay == nullptr && mSession->IsTrackingReady()) {
// HMD Detected
mDisplay = new VRDisplayOculus(mSession);
}
+}
+void
+VRSystemManagerOculus::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
+{
if (mDisplay) {
aHMDResult.AppendElement(mDisplay);
- return true;
}
- return false;
}
bool
VRSystemManagerOculus::GetIsPresenting()
{
if (mDisplay) {
VRDisplayInfo displayInfo(mDisplay->GetDisplayInfo());
return displayInfo.GetPresentingGroups() != 0;
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -37,22 +37,24 @@ enum class OculusControllerAxisType : ui
class VROculusSession
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VROculusSession);
friend class VRDisplayOculus;
public:
VROculusSession();
void Refresh(bool aForceRefresh = false);
+ void StartTracking();
+ void StopTracking();
bool IsTrackingReady() const;
- bool IsRenderReady() const;
- ovrSession Get();
void StartPresentation(const IntSize& aSize);
void StopPresentation();
- void StopTracking();
+ bool IsPresentationReady() const;
+ bool IsMounted() const;
+ ovrSession Get();
bool IsQuitTimeoutActive();
already_AddRefed<layers::CompositingRenderTargetD3D11> GetNextRenderTarget();
ovrTextureSwapChain GetSwapChain();
private:
PRLibrary* mOvrLib;
ovrSession mSession;
ovrInitFlags mInitFlags;
@@ -60,18 +62,22 @@ private:
nsTArray<RefPtr<layers::CompositingRenderTargetD3D11>> mRenderTargets;
IntSize mPresentationSize;
RefPtr<ID3D11Device> mDevice;
// The timestamp of the last time Oculus set ShouldQuit to true.
TimeStamp mLastShouldQuit;
// The timestamp of the last ending presentation
TimeStamp mLastPresentationEnd;
VRTelemetry mTelemetry;
- bool mPresenting;
+ bool mRequestPresentation;
+ bool mRequestTracking;
+ bool mTracking;
bool mDrawBlack;
+ bool mIsConnected;
+ bool mIsMounted;
~VROculusSession();
void Uninitialize(bool aUnloadLib);
bool Initialize(ovrInitFlags aFlags);
bool LoadOvrLib();
void UnloadOvrLib();
bool StartSession();
void StopSession();
@@ -79,32 +85,32 @@ private:
void StopLib();
bool StartRendering();
void StopRendering();
};
class VRDisplayOculus : public VRDisplayHost
{
public:
- virtual void NotifyVSync() override;
void ZeroSensor() override;
protected:
virtual VRHMDSensorState GetSensorState() override;
virtual void StartPresentation() override;
virtual void StopPresentation() override;
virtual bool SubmitFrame(ID3D11Texture2D* aSource,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
void UpdateStageParameters();
public:
explicit VRDisplayOculus(VROculusSession* aSession);
void Destroy();
+ void Refresh();
protected:
virtual ~VRDisplayOculus();
VRHMDSensorState GetSensorState(double absTime);
ovrHmdDesc mDesc;
RefPtr<VROculusSession> mSession;
@@ -171,17 +177,20 @@ private:
} // namespace impl
class VRSystemManagerOculus : public VRSystemManager
{
public:
static already_AddRefed<VRSystemManagerOculus> Create();
virtual void Destroy() 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 void HandleInput() override;
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
aControllerResult) override;
virtual void ScanForControllers() override;
virtual void RemoveControllers() override;
virtual void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
double aIntensity, double aDuration, const VRManagerPromise& aPromise) override;
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -198,18 +198,20 @@ VRDisplayOpenVR::ZeroSensor()
bool
VRDisplayOpenVR::GetIsHmdPresent()
{
return mIsHmdPresent;
}
void
-VRDisplayOpenVR::PollEvents()
+VRDisplayOpenVR::Refresh()
{
+ mIsHmdPresent = ::vr::VR_IsHmdPresent();
+
::vr::VREvent_t event;
while (mVRSystem && mVRSystem->PollNextEvent(&event, sizeof(event))) {
switch (event.eventType) {
case ::vr::VREvent_TrackedDeviceUserInteractionStarted:
if (event.trackedDeviceIndex == ::vr::k_unTrackedDeviceIndex_Hmd) {
mDisplayInfo.mIsMounted = true;
}
break;
@@ -240,18 +242,16 @@ VRDisplayOpenVR::PollEvents()
break;
}
}
}
VRHMDSensorState
VRDisplayOpenVR::GetSensorState()
{
- PollEvents();
-
const uint32_t posesSize = ::vr::k_unTrackedDeviceIndex_Hmd + 1;
::vr::TrackedDevicePose_t poses[posesSize];
// Note: We *must* call WaitGetPoses in order for any rendering to happen at all.
mVRCompositor->WaitGetPoses(nullptr, 0, poses, posesSize);
gfx::Matrix4x4 headToEyeTransforms[2];
UpdateEyeParameters(headToEyeTransforms);
VRHMDSensorState result{};
@@ -418,27 +418,16 @@ VRDisplayOpenVR::SubmitFrame(MacIOSurfac
::vr::ETextureType::TextureType_IOSurface,
aSize, aLeftEyeRect, aRightEyeRect);
}
return result;
}
#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,
uint32_t aNumButtons, uint32_t aNumTriggers,
uint32_t aNumAxes, const nsCString& aId)
: VRControllerHost(VRDeviceType::OpenVR, aHand, aDisplayID)
, mTrigger(aNumTriggers)
, mAxisMove(aNumAxes)
, mVibrateThread(nullptr)
, mIsVibrateStopped(false)
@@ -632,60 +621,97 @@ VRSystemManagerOpenVR::Shutdown()
{
if (mOpenVRHMD) {
mOpenVRHMD = nullptr;
}
RemoveControllers();
mVRSystem = nullptr;
}
-bool
-VRSystemManagerOpenVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
+void
+VRSystemManagerOpenVR::NotifyVSync()
{
- if (!::vr::VR_IsHmdPresent() ||
- (mOpenVRHMD && !mOpenVRHMD->GetIsHmdPresent())) {
- // OpenVR runtime could be quit accidentally,
- // and we make it re-initialize.
- mOpenVRHMD = nullptr;
- mVRSystem = nullptr;
- } else if (mOpenVRHMD == nullptr) {
+ VRSystemManager::NotifyVSync();
+
+ // Avoid doing anything unless we have already
+ // successfully enumerated and loaded the OpenVR
+ // runtime.
+ if (mVRSystem == 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::VR_Init(&err, ::vr::EVRApplicationType::VRApplication_Scene);
if (err) {
- return false;
+ return;
}
::vr::IVRSystem *system = (::vr::IVRSystem *)::vr::VR_GetGenericInterface(::vr::IVRSystem_Version, &err);
if (err || !system) {
::vr::VR_Shutdown();
- return false;
+ return;
}
::vr::IVRChaperone *chaperone = (::vr::IVRChaperone *)::vr::VR_GetGenericInterface(::vr::IVRChaperone_Version, &err);
if (err || !chaperone) {
::vr::VR_Shutdown();
- return false;
+ return;
}
::vr::IVRCompositor *compositor = (::vr::IVRCompositor*)::vr::VR_GetGenericInterface(::vr::IVRCompositor_Version, &err);
if (err || !compositor) {
::vr::VR_Shutdown();
- return false;
+ return;
}
mVRSystem = system;
mOpenVRHMD = new VRDisplayOpenVR(system, chaperone, compositor);
}
+}
+bool
+VRSystemManagerOpenVR::ShouldInhibitEnumeration()
+{
+ if (VRSystemManager::ShouldInhibitEnumeration()) {
+ return true;
+ }
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 false;
}
+void
+VRSystemManagerOpenVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
+{
+ if (mOpenVRHMD) {
+ aHMDResult.AppendElement(mOpenVRHMD);
+ }
+}
+
bool
VRSystemManagerOpenVR::GetIsPresenting()
{
if (mOpenVRHMD) {
VRDisplayInfo displayInfo(mOpenVRHMD->GetDisplayInfo());
return displayInfo.GetPresentingGroups() != kVRGroupNone;
}
--- a/gfx/vr/gfxVROpenVR.h
+++ b/gfx/vr/gfxVROpenVR.h
@@ -25,17 +25,16 @@ class MacIOSurface;
#endif
namespace mozilla {
namespace gfx {
namespace impl {
class VRDisplayOpenVR : public VRDisplayHost
{
public:
- virtual void NotifyVSync() override;
void ZeroSensor() override;
bool GetIsHmdPresent();
protected:
virtual VRHMDSensorState GetSensorState() override;
virtual void StartPresentation() override;
virtual void StopPresentation() override;
#if defined(XP_WIN)
@@ -49,33 +48,32 @@ protected:
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
#endif
public:
explicit VRDisplayOpenVR(::vr::IVRSystem *aVRSystem,
::vr::IVRChaperone *aVRChaperone,
::vr::IVRCompositor *aVRCompositor);
-
+ void Refresh();
protected:
virtual ~VRDisplayOpenVR();
void Destroy();
// not owned by us; global from OpenVR
::vr::IVRSystem *mVRSystem;
::vr::IVRChaperone *mVRChaperone;
::vr::IVRCompositor *mVRCompositor;
VRTelemetry mTelemetry;
bool mIsPresenting;
bool mIsHmdPresent;
void UpdateStageParameters();
void UpdateEyeParameters(gfx::Matrix4x4* aHeadToEyeTransforms = nullptr);
- void PollEvents();
bool SubmitFrame(void* aTextureHandle,
::vr::ETextureType aTextureType,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect);
};
class VRControllerOpenVR : public VRControllerHost
@@ -122,17 +120,20 @@ private:
class VRSystemManagerOpenVR : public VRSystemManager
{
public:
static already_AddRefed<VRSystemManagerOpenVR> Create();
virtual void Destroy() 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 void HandleInput() override;
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
aControllerResult) override;
virtual void ScanForControllers() override;
virtual void RemoveControllers() override;
virtual void VibrateHaptic(uint32_t aControllerIdx,
uint32_t aHapticIndex,
--- a/gfx/vr/gfxVRPuppet.cpp
+++ b/gfx/vr/gfxVRPuppet.cpp
@@ -561,22 +561,20 @@ VRDisplayPuppet::SubmitFrame(const mozil
const gfx::Rect& aRightEyeRect) {
return false;
}
#endif
void
-VRDisplayPuppet::NotifyVSync()
+VRDisplayPuppet::Refresh()
{
- // We update mIsConneced once per frame.
+ // We update mIsConneced once per refresh.
mDisplayInfo.mIsConnected = true;
-
- VRDisplayHost::NotifyVSync();
}
VRControllerPuppet::VRControllerPuppet(dom::GamepadHand aHand, uint32_t aDisplayID)
: VRControllerHost(VRDeviceType::Puppet, aHand, aDisplayID)
, mButtonPressState(0)
, mButtonTouchState(0)
{
MOZ_COUNT_CTOR_INHERITED(VRControllerPuppet, VRControllerHost);
@@ -698,24 +696,55 @@ VRSystemManagerPuppet::Destroy()
}
void
VRSystemManagerPuppet::Shutdown()
{
mPuppetHMD = nullptr;
}
-bool
-VRSystemManagerPuppet::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
+void
+VRSystemManagerPuppet::NotifyVSync()
+{
+ VRSystemManager::NotifyVSync();
+ if (mPuppetHMD) {
+ mPuppetHMD->Refresh();
+ }
+}
+
+void
+VRSystemManagerPuppet::Enumerate()
{
if (mPuppetHMD == nullptr) {
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
VRSystemManagerPuppet::GetIsPresenting()
{
if (mPuppetHMD) {
VRDisplayInfo displayInfo(mPuppetHMD->GetDisplayInfo());
return displayInfo.GetPresentingGroups() != kVRGroupNone;
--- a/gfx/vr/gfxVRPuppet.h
+++ b/gfx/vr/gfxVRPuppet.h
@@ -19,17 +19,16 @@ class MacIOSurface;
namespace mozilla {
namespace gfx {
namespace impl {
class VRDisplayPuppet : public VRDisplayHost
{
public:
void SetDisplayInfo(const VRDisplayInfo& aDisplayInfo);
- virtual void NotifyVSync() override;
void SetSensorState(const VRHMDSensorState& aSensorState);
void ZeroSensor() override;
protected:
virtual VRHMDSensorState GetSensorState() override;
virtual void StartPresentation() override;
virtual void StopPresentation() override;
#if defined(XP_WIN)
@@ -45,16 +44,17 @@ protected:
#elif defined(MOZ_ANDROID_GOOGLE_VR)
virtual bool SubmitFrame(const mozilla::layers::EGLImageDescriptor* aDescriptor,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
#endif
public:
explicit VRDisplayPuppet();
+ void Refresh();
protected:
virtual ~VRDisplayPuppet();
void Destroy();
bool mIsPresenting;
private:
@@ -105,29 +105,32 @@ private:
class VRSystemManagerPuppet : public VRSystemManager
{
public:
static already_AddRefed<VRSystemManagerPuppet> Create();
virtual void Destroy() 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 void HandleInput() override;
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
aControllerResult) override;
virtual void ScanForControllers() override;
virtual void RemoveControllers() override;
virtual void VibrateHaptic(uint32_t aControllerIdx,
uint32_t aHapticIndex,
double aIntensity,
double aDuration,
const VRManagerPromise& aPromise) override;
virtual void StopVibrateHaptic(uint32_t aControllerIdx) override;
+ virtual void NotifyVSync() override;
protected:
VRSystemManagerPuppet();
private:
void HandleButtonPress(uint32_t aControllerIdx,
uint32_t aButton,
uint64_t aButtonMask,
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5226,16 +5226,30 @@ pref("dom.vr.osvr.enabled", false);
pref("dom.vr.openvr.enabled", false);
#elif defined(XP_WIN) || defined(XP_MACOSX)
// We enable WebVR by default for Windows and macOS
pref("dom.vr.openvr.enabled", true);
#else
// See Bug 1310663 (Linux)
pref("dom.vr.openvr.enabled", false);
#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
// poses to callers of the WebVR API. This currently only has an effect for
// Oculus Rift on SDK 0.8 or greater.
pref("dom.vr.poseprediction.enabled", true);
// Starting VR presentation is only allowed within a user gesture or event such
// as VRDisplayActivate triggered by the system. dom.vr.require-gesture allows
// this requirement to be disabled for special cases such as during automated
// tests or in a headless kiosk system.