diff --git a/dom/vr/test/mochitest/VRSimulationDriver.js b/dom/vr/test/mochitest/VRSimulationDriver.js
index f279d99953fb..6a1012df0067 100644
--- a/dom/vr/test/mochitest/VRSimulationDriver.js
+++ b/dom/vr/test/mochitest/VRSimulationDriver.js
@@ -6,10 +6,6 @@ var VRSimulationDriver = (function() {
"use strict";
var AttachWebVRDisplay = function() {
- if (vrMockDisplay) {
- // Avoid creating multiple displays
- return Promise.resolve(vrMockDisplay);
- }
var promise = VRServiceTest.attachVRDisplay("VRDisplayTest");
promise.then(function (display) {
assert_true(display != null, "AttachWebVRDisplay should success.");
diff --git a/dom/vr/test/mochitest/runVRTest.js b/dom/vr/test/mochitest/runVRTest.js
index afb76f89e9a9..438c9f3a316f 100644
--- a/dom/vr/test/mochitest/runVRTest.js
+++ b/dom/vr/test/mochitest/runVRTest.js
@@ -1,9 +1,7 @@
function runVRTest(callback) {
SpecialPowers.pushPrefEnv({"set" : [["dom.vr.puppet.enabled", true],
["dom.vr.require-gesture", false],
- ["dom.vr.test.enabled", true],
- ["dom.vr.display.enumerate.interval", 0],
- ["dom.vr.controller.enumerate.interval", 0]]},
+ ["dom.vr.test.enabled", true]]},
() => {
VRServiceTest = navigator.requestVRServiceTest();
callback();
diff --git a/dom/vr/test/mochitest/test_vrController_displayId.html b/dom/vr/test/mochitest/test_vrController_displayId.html
index 85f085057a0c..0f3e42d01845 100644
--- a/dom/vr/test/mochitest/test_vrController_displayId.html
+++ b/dom/vr/test/mochitest/test_vrController_displayId.html
@@ -38,14 +38,12 @@
function startTest() {
promise_test((test) => {
listenControllerEvents();
- return VRSimulationDriver.AttachWebVRDisplay().then(() => {
- return navigator.getVRDisplays().then((displays) => {
- vrDisplay = displays[0];
- assert_equals(displays.length, 1, "displays.length must be one after attach.");
- assert_equals(displays[0].displayId, 1, "displayId must be one.");
- addController();
- addController();
- });
+ return navigator.getVRDisplays().then((displays) => {
+ vrDisplay = displays[0];
+ assert_equals(displays.length, 1, "displays.length must be one after attach.");
+ assert_equals(displays[0].displayId, 1, "displayId must be one.");
+ addController();
+ addController();
});
}, "Finish to add VRDisplay.");
}
diff --git a/dom/vr/test/mochitest/test_vrDisplay_canvas2d.html b/dom/vr/test/mochitest/test_vrDisplay_canvas2d.html
index 2ebed1eef3d5..c4a5f5a07b84 100644
--- a/dom/vr/test/mochitest/test_vrDisplay_canvas2d.html
+++ b/dom/vr/test/mochitest/test_vrDisplay_canvas2d.html
@@ -6,7 +6,6 @@
-
@@ -36,14 +35,12 @@
var img = document.createElement('img');
img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACw=";
- return VRSimulationDriver.AttachWebVRDisplay().then(() => {
- return navigator.getVRDisplays().then((displays) => {
- assert_equals(displays.length, 1, "displays.length must be one after attach.");
- vrDisplay = displays[0];
- var frameData = new VRFrameData();
- return vrDisplay.requestPresent([{source: canvas}]).then(() => {
- requestPresentTest();
- });
+ return navigator.getVRDisplays().then((displays) => {
+ assert_equals(displays.length, 1, "displays.length must be one after attach.");
+ vrDisplay = displays[0];
+ var frameData = new VRFrameData();
+ return vrDisplay.requestPresent([{source: canvas}]).then(() => {
+ requestPresentTest();
});
});
}, "Finish running WebVR Canvas2D test.");
diff --git a/dom/vr/test/mochitest/test_vrDisplay_exitPresent.html b/dom/vr/test/mochitest/test_vrDisplay_exitPresent.html
index cdce7d79045e..3edb2f0cc9e8 100644
--- a/dom/vr/test/mochitest/test_vrDisplay_exitPresent.html
+++ b/dom/vr/test/mochitest/test_vrDisplay_exitPresent.html
@@ -6,7 +6,6 @@
-
@@ -18,29 +17,23 @@
});
}
var initVRPresentation = function(content) {
- return VRSimulationDriver.AttachWebVRDisplay().then(() => {
- return content.navigator.getVRDisplays().then((displays) => {
+ return content.navigator.getVRDisplays().then((displays) => {
content.vrDisplay = displays[0];
content.canvas = content.document.createElement("canvas");
content.canvas.id = "vrCanvas";
return content.vrDisplay.requestPresent([{source:content.canvas}]);
});
- });
}
function startTest() {
var ifr1 = document.getElementById("iframe1");
var ifr2 = document.getElementById("iframe2");
var frame1 = ifr1.contentWindow;
var frame2 = ifr2.contentWindow;
- promise_test((test) => {
- return VRSimulationDriver.AttachWebVRDisplay().then(() => {
- return initVRPresentation(frame1).then(() => {
- promise_test((test) => {
- return promise_rejects(test, null, testExitPresentOnOtherIframe(frame2));
- }, "We cannot exit VR presentation established by another content, this promise is expected to be rejected.")
- });
- });
- }, "Finish running WebVR exitPresent test.");
+ initVRPresentation(frame1).then(() => {
+ promise_test((test) => {
+ return promise_rejects(test, null, testExitPresentOnOtherIframe(frame2));
+ }, "We cannot exist VR presentation established by another content, this promise is expected to be rejected.")
+ });
}
runVRTest(startTest);
diff --git a/dom/vr/test/reftest/VRSimulationDriver.js b/dom/vr/test/reftest/VRSimulationDriver.js
index 971cdb8626fb..9ee139c0b2bf 100644
--- a/dom/vr/test/reftest/VRSimulationDriver.js
+++ b/dom/vr/test/reftest/VRSimulationDriver.js
@@ -6,10 +6,6 @@ var VRSimulationDriver = (function() {
"use strict";
var AttachWebVRDisplay = function() {
- if (vrMockDisplay) {
- // Avoid creating multiple displays
- return Promise.resolve(vrMockDisplay);
- }
var promise = VRServiceTest.attachVRDisplay("VRDisplayTest");
promise.then(function (display) {
vrMockDisplay = display;
diff --git a/dom/vr/test/reftest/reftest.list b/dom/vr/test/reftest/reftest.list
index 07a9325306dc..102da84300f9 100644
--- a/dom/vr/test/reftest/reftest.list
+++ b/dom/vr/test/reftest/reftest.list
@@ -1,6 +1,6 @@
# WebVR Reftests
# Please confirm there is no other VR display connected. Otherwise, VRPuppetDisplay can't be attached.
-default-preferences pref(dom.vr.puppet.enabled,true) pref(dom.vr.test.enabled,true) pref(dom.vr.require-gesture,false) pref(dom.vr.puppet.submitframe,1) pref(dom.vr.display.rafMaxDuration,200) pref(dom.vr.display.enumerate.interval,0) pref(dom.vr.controller.enumerate.interval,0)
+default-preferences pref(dom.vr.puppet.enabled,true) pref(dom.vr.test.enabled,true) pref(dom.vr.require-gesture,false) pref(dom.vr.puppet.submitframe,1) pref(dom.vr.display.rafMaxDuration,200)
# VR SubmitFrame is only implemented for D3D11.1 and MacOSX now.
# Our Windows 7 test machines don't support D3D11.1, so we run these tests on Windows 8+ only.
diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h
index 21df904ca774..793dd88a993e 100644
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -367,9 +367,6 @@ private:
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);
diff --git a/gfx/vr/VRDisplayHost.h b/gfx/vr/VRDisplayHost.h
index 63ff99c73f84..509c761c3140 100644
--- a/gfx/vr/VRDisplayHost.h
+++ b/gfx/vr/VRDisplayHost.h
@@ -41,7 +41,7 @@ public:
virtual void ZeroSensor() = 0;
virtual void StartPresentation() = 0;
virtual void StopPresentation() = 0;
- void NotifyVSync();
+ virtual void NotifyVSync();
void StartFrame();
void SubmitFrame(VRLayerParent* aLayer,
diff --git a/gfx/vr/VRManager.cpp b/gfx/vr/VRManager.cpp
index e22b63f81d05..123f65ce66d0 100644
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -55,8 +55,7 @@ VRManager::ManagerInit()
VRManager::VRManager()
: mInitialized(false)
- , mVRDisplaysRequested(false)
- , mVRControllersRequested(false)
+ , mVRTestSystemCreated(false)
{
MOZ_COUNT_CTOR(VRManager);
MOZ_ASSERT(sVRManagerSingleton == nullptr);
@@ -175,8 +174,12 @@ VRManager::RemoveVRManagerParent(VRManagerParent* aVRManagerParent)
}
void
-VRManager::UpdateRequestedDevices()
+VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
{
+ MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
+ const double kVRDisplayRefreshMaxDuration = 5000; // milliseconds
+ const double kVRDisplayInactiveMaxDuration = 30000; // milliseconds
+
bool bHaveEventListener = false;
bool bHaveControllerListener = false;
@@ -186,55 +189,61 @@ VRManager::UpdateRequestedDevices()
bHaveControllerListener |= vmp->HaveControllerListener();
}
- 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();
+ // VRDisplayHost::NotifyVSync may modify mVRDisplays, so we iterate
+ // through a local copy here.
+ nsTArray> displays;
+ for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
+ displays.AppendElement(iter.UserData());
+ }
+ for (const auto& display: displays) {
+ display->NotifyVSync();
}
- // 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 (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();
+ }
+ }
- // Update state and enumeration of VR controllers
- RefreshVRControllers();
+ if (bHaveControllerListener) {
+ for (const auto& manager: mManagers) {
+ if (!manager->GetIsPresenting()) {
+ manager->HandleInput();
+ }
+ }
+ }
+ }
- CheckForInactiveTimeout();
-}
-
-void
-VRManager::CheckForInactiveTimeout()
-{
// Shut down the VR devices when not in use
- if (mVRDisplaysRequested || mVRControllersRequested) {
+ if (bHaveEventListener || bHaveControllerListener) {
// 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() > gfxPrefs::VRInactiveTimeout()) {
+ if (duration.ToMilliseconds() > kVRDisplayInactiveMaxDuration) {
Shutdown();
}
}
@@ -258,80 +267,26 @@ VRManager::NotifyVRVsync(const uint32_t& aDisplayID)
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)
{
- /**
- * 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();
- }
-
- /**
- * 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.
- */
nsTArray > displays;
- for (const auto& manager: mManagers) {
- manager->GetHMDs(displays);
+
+ /** 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.
+ */
+ 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;
+ }
}
bool displayInfoChanged = false;
@@ -428,10 +383,10 @@ VRManager::GetVRControllerInfo(nsTArray& aControllerInfo)
void
VRManager::RefreshVRControllers()
{
- ScanForControllers();
-
nsTArray> controllers;
+ ScanForControllers();
+
for (uint32_t i = 0; i < mManagers.Length()
&& controllers.Length() == 0; ++i) {
mManagers[i]->GetControllers(controllers);
@@ -464,25 +419,9 @@ VRManager::RefreshVRControllers()
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
@@ -497,20 +436,15 @@ VRManager::RemoveControllers()
void
VRManager::CreateVRTestSystem()
{
- if (mPuppetManager) {
- mPuppetManager->ClearTestDisplays();
+ if (mVRTestSystemCreated) {
return;
}
- mPuppetManager = VRSystemManagerPuppet::Create();
- mManagers.AppendElement(mPuppetManager);
-}
-
-VRSystemManagerPuppet*
-VRManager::GetPuppetManager()
-{
- MOZ_ASSERT(mPuppetManager);
- return mPuppetManager;
+ RefPtr mgr = VRSystemManagerPuppet::Create();
+ if (mgr) {
+ mManagers.AppendElement(mgr);
+ mVRTestSystemCreated = true;
+ }
}
template
diff --git a/gfx/vr/VRManager.h b/gfx/vr/VRManager.h
index 062b46ca092c..7c79922ed442 100644
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -23,7 +23,6 @@ namespace gfx {
class VRLayerParent;
class VRManagerParent;
class VRDisplayHost;
-class VRSystemManagerPuppet;
class VRManager
{
@@ -48,8 +47,6 @@ public:
RefPtr GetController(const uint32_t& aControllerID);
void GetVRControllerInfo(nsTArray& aControllerInfo);
void CreateVRTestSystem();
- VRSystemManagerPuppet* GetPuppetManager();
-
void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
double aIntensity, double aDuration, uint32_t aPromiseID);
void StopVibrateHaptic(uint32_t aControllerIdx);
@@ -67,9 +64,6 @@ private:
void Shutdown();
void DispatchVRDisplayInfoUpdate();
- void UpdateRequestedDevices();
- void EnumerateVRDisplays();
- void CheckForInactiveTimeout();
typedef nsTHashtable> VRManagerParentSet;
VRManagerParentSet mVRManagerParents;
@@ -85,12 +79,9 @@ private:
Atomic mInitialized;
- TimeStamp mLastControllerEnumerationTime;
- TimeStamp mLastDisplayEnumerationTime;
+ TimeStamp mLastRefreshTime;
TimeStamp mLastActiveTime;
- RefPtr mPuppetManager;
- bool mVRDisplaysRequested;
- bool mVRControllersRequested;
+ bool mVRTestSystemCreated;
};
} // namespace gfx
diff --git a/gfx/vr/gfxVR.cpp b/gfx/vr/gfxVR.cpp
index da6054b591c8..849adc10ff62 100644
--- a/gfx/vr/gfxVR.cpp
+++ b/gfx/vr/gfxVR.cpp
@@ -9,7 +9,6 @@
#include "gfxVR.h"
#include "mozilla/dom/GamepadEventTypes.h"
#include "mozilla/dom/GamepadBinding.h"
-#include "VRDisplayHost.h"
#ifndef M_PI
# define M_PI 3.14159265358979323846
@@ -33,58 +32,6 @@ 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> 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
diff --git a/gfx/vr/gfxVR.h b/gfx/vr/gfxVR.h
index 48da76bc1461..7f71836ba0da 100644
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -347,10 +347,7 @@ public:
virtual void Destroy() = 0;
virtual void Shutdown() = 0;
- virtual void Enumerate() = 0;
- virtual void NotifyVSync();
- virtual bool ShouldInhibitEnumeration();
- virtual void GetHMDs(nsTArray>& aHMDResult) = 0;
+ virtual bool GetHMDs(nsTArray>& aHMDResult) = 0;
virtual bool GetIsPresenting() = 0;
virtual void HandleInput() = 0;
virtual void GetControllers(nsTArray>& aControllerResult) = 0;
diff --git a/gfx/vr/gfxVRGVR.cpp b/gfx/vr/gfxVRGVR.cpp
index 28f65214d749..a099947b03e9 100644
--- a/gfx/vr/gfxVRGVR.cpp
+++ b/gfx/vr/gfxVRGVR.cpp
@@ -340,6 +340,12 @@ VRDisplayGVR::SubmitFrame(const mozilla::layers::EGLImageDescriptor* aDescriptor
return true;
}
+void
+VRDisplayGVR::NotifyVSync()
+{
+ VRDisplayHost::NotifyVSync();
+}
+
static void
FillMatrix(gfx::Matrix4x4 &target, const gvr_mat4f& source)
{
@@ -706,40 +712,19 @@ VRSystemManagerGVR::Shutdown()
}
-void
-VRSystemManagerGVR::Enumerate()
+bool
+VRSystemManagerGVR::GetHMDs(nsTArray >& aHMDResult)
{
if (!GeckoVRManager::IsGVRPresent()) {
- return;
+ return false;
}
if (!mGVRHMD) {
mGVRHMD = new VRDisplayGVR();
}
-}
-bool
-VRSystemManagerGVR::ShouldInhibitEnumeration()
-{
- if (VRSystemManager::ShouldInhibitEnumeration()) {
- return true;
- }
- if (mGVRHMD) {
- // 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
-VRSystemManagerGVR::GetHMDs(nsTArray>& aHMDResult)
-{
- if (mGVRHMD) {
- aHMDResult.AppendElement(mGVRHMD);
- }
+ aHMDResult.AppendElement(mGVRHMD);
+ return true;
}
bool
diff --git a/gfx/vr/gfxVRGVR.h b/gfx/vr/gfxVRGVR.h
index eec3306909b2..175489db4857 100644
--- a/gfx/vr/gfxVRGVR.h
+++ b/gfx/vr/gfxVRGVR.h
@@ -60,6 +60,7 @@ public:
bool SubmitFrame(const mozilla::layers::EGLImageDescriptor* aDescriptor,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
+ void NotifyVSync() override;
protected:
virtual VRHMDSensorState GetSensorState() override;
// END VRDisplayHost interface
@@ -104,9 +105,7 @@ public:
void Destroy() override;
void Shutdown() override;
- void Enumerate() override;
- bool ShouldInhibitEnumeration() override;
- void GetHMDs(nsTArray>& aHMDResult) override;
+ bool GetHMDs(nsTArray >& aHMDResult) override;
bool GetIsPresenting() override;
void HandleInput() override;
void GetControllers(nsTArray>&
diff --git a/gfx/vr/gfxVROSVR.cpp b/gfx/vr/gfxVROSVR.cpp
index 053fc59f7480..c76a302c736b 100644
--- a/gfx/vr/gfxVROSVR.cpp
+++ b/gfx/vr/gfxVROSVR.cpp
@@ -550,51 +550,25 @@ VRSystemManagerOSVR::Shutdown()
osvr_ClientShutdown(m_ctx);
}
-void
-VRSystemManagerOSVR::NotifyVSync()
-{
- VRSystemManager::NotifyVSync();
-
- // TODO - Check for device disconnection or other OSVR events
-}
-
-void
-VRSystemManagerOSVR::Enumerate()
+bool
+VRSystemManagerOSVR::GetHMDs(nsTArray>& aHMDResult)
{
// make sure context, interface and display are initialized
CheckOSVRStatus();
if (!Init()) {
- return;
+ return false;
}
mHMDInfo = new VRDisplayOSVR(&m_ctx, &m_iface, &m_display);
-}
-bool
-VRSystemManagerOSVR::ShouldInhibitEnumeration()
-{
- if (VRSystemManager::ShouldInhibitEnumeration()) {
- return true;
- }
if (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.
+ aHMDResult.AppendElement(mHMDInfo);
return true;
}
return false;
}
-void
-VRSystemManagerOSVR::GetHMDs(nsTArray>& aHMDResult)
-{
- if (mHMDInfo) {
- aHMDResult.AppendElement(mHMDInfo);
- }
-}
-
bool
VRSystemManagerOSVR::GetIsPresenting()
{
diff --git a/gfx/vr/gfxVROSVR.h b/gfx/vr/gfxVROSVR.h
index a79d7e659733..3b70622aa39d 100644
--- a/gfx/vr/gfxVROSVR.h
+++ b/gfx/vr/gfxVROSVR.h
@@ -80,10 +80,7 @@ public:
static already_AddRefed Create();
virtual void Destroy() override;
virtual void Shutdown() override;
- virtual void NotifyVSync() override;
- virtual void Enumerate() override;
- virtual bool ShouldInhibitEnumeration() override;
- virtual void GetHMDs(nsTArray>& aHMDResult) override;
+ virtual bool GetHMDs(nsTArray>& aHMDResult) override;
virtual bool GetIsPresenting() override;
virtual void HandleInput() override;
virtual void GetControllers(nsTArray>&
diff --git a/gfx/vr/gfxVROculus.cpp b/gfx/vr/gfxVROculus.cpp
index 6f266d834bda..c9cdfb6563a3 100644
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -204,11 +204,8 @@ VROculusSession::VROculusSession()
, mSession(nullptr)
, mInitFlags((ovrInitFlags)0)
, mTextureSet(nullptr)
- , mRequestPresentation(false)
- , mRequestTracking(false)
+ , mPresenting(false)
, mDrawBlack(false)
- , mIsConnected(false)
- , mIsMounted(false)
{
}
@@ -222,47 +219,26 @@ VROculusSession::Get()
bool
VROculusSession::IsTrackingReady() const
{
- // We should return true only if the HMD is connected and we
- // are ready for tracking
- MOZ_ASSERT(!mIsConnected || mSession);
- return mIsConnected;
+ return mSession != nullptr;
}
bool
-VROculusSession::IsPresentationReady() const
+VROculusSession::IsRenderReady() const
{
return !mRenderTargets.IsEmpty();
}
-bool
-VROculusSession::IsMounted() const
-{
- return mIsMounted;
-}
-
void
VROculusSession::StopTracking()
{
- if (mRequestTracking) {
- mRequestTracking = false;
- Refresh();
- }
-}
-
-void
-VROculusSession::StartTracking()
-{
- if (!mRequestTracking) {
- mRequestTracking = true;
- Refresh();
- }
+ Uninitialize(true);
}
void
VROculusSession::StartPresentation(const IntSize& aSize)
{
- if (!mRequestPresentation) {
- mRequestPresentation = true;
+ if (!mPresenting) {
+ mPresenting = true;
mTelemetry.Clear();
mTelemetry.mPresentationStart = TimeStamp::Now();
@@ -282,9 +258,9 @@ VROculusSession::StartPresentation(const IntSize& aSize)
void
VROculusSession::StopPresentation()
{
- if (mRequestPresentation) {
+ if (mPresenting) {
mLastPresentationEnd = TimeStamp::Now();
- mRequestPresentation = false;
+ mPresenting = false;
const TimeDuration duration = mLastPresentationEnd - mTelemetry.mPresentationStart;
Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 1);
@@ -339,8 +315,6 @@ VROculusSession::StopSession()
{
if (mSession) {
ovr_Destroy(mSession);
- mIsConnected = false;
- mIsMounted = false;
mSession = nullptr;
}
}
@@ -363,14 +337,9 @@ VROculusSession::Refresh(bool aForceRefresh)
return;
}
- if (!mRequestTracking) {
- Uninitialize(true);
- return;
- }
-
ovrInitFlags flags = (ovrInitFlags)(ovrInit_RequestVersion | ovrInit_MixedRendering);
bool bInvisible = true;
- if (mRequestPresentation) {
+ if (mPresenting) {
bInvisible = false;
} else if (!mLastPresentationEnd.IsNull()) {
TimeDuration duration = TimeStamp::Now() - mLastPresentationEnd;
@@ -415,25 +384,15 @@ VROculusSession::Refresh(bool aForceRefresh)
Uninitialize(false);
}
- 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);
- }
+ Initialize(flags);
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;
}
}
}
@@ -478,7 +437,7 @@ VROculusSession::Initialize(ovrInitFlags aFlags)
bool
VROculusSession::StartRendering()
{
- if (!mRequestPresentation) {
+ if (!mPresenting) {
// Nothing to do if we aren't presenting
return true;
}
@@ -1014,7 +973,7 @@ VRDisplayOculus::StartPresentation()
return;
}
mSession->StartPresentation(IntSize(mDisplayInfo.mEyeResolution.width * 2, mDisplayInfo.mEyeResolution.height));
- if (!mSession->IsPresentationReady()) {
+ if (!mSession->IsRenderReady()) {
return;
}
@@ -1144,7 +1103,7 @@ VRDisplayOculus::SubmitFrame(ID3D11Texture2D* aSource,
return false;
}
- if (!mSession->IsPresentationReady()) {
+ if (!mSession->IsRenderReady()) {
return false;
}
/**
@@ -1289,10 +1248,18 @@ VRDisplayOculus::SubmitFrame(ID3D11Texture2D* aSource,
}
void
-VRDisplayOculus::Refresh()
+VRDisplayOculus::NotifyVSync()
{
- mDisplayInfo.mIsConnected = mSession->IsTrackingReady();
- mDisplayInfo.mIsMounted = mSession->IsMounted();
+ 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();
}
VRControllerOculus::VRControllerOculus(dom::GamepadHand aHand, uint32_t aDisplayID)
@@ -1550,66 +1517,37 @@ VRSystemManagerOculus::Shutdown()
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::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()
+VRSystemManagerOculus::GetHMDs(nsTArray>& aHMDResult)
{
if (!mSession) {
mSession = new VROculusSession();
}
- mSession->StartTracking();
- if (mDisplay == nullptr && mSession->IsTrackingReady()) {
+ 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) {
// HMD Detected
mDisplay = new VRDisplayOculus(mSession);
}
-}
-void
-VRSystemManagerOculus::GetHMDs(nsTArray>& aHMDResult)
-{
if (mDisplay) {
aHMDResult.AppendElement(mDisplay);
+ return true;
}
+ return false;
}
bool
diff --git a/gfx/vr/gfxVROculus.h b/gfx/vr/gfxVROculus.h
index e77e054ba359..8e3f0812a721 100644
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -42,14 +42,12 @@ class VROculusSession
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();
- bool IsPresentationReady() const;
- bool IsMounted() const;
- ovrSession Get();
+ void StopTracking();
bool IsQuitTimeoutActive();
already_AddRefed GetNextRenderTarget();
ovrTextureSwapChain GetSwapChain();
@@ -67,12 +65,8 @@ private:
// The timestamp of the last ending presentation
TimeStamp mLastPresentationEnd;
VRTelemetry mTelemetry;
- bool mRequestPresentation;
- bool mRequestTracking;
- bool mTracking;
+ bool mPresenting;
bool mDrawBlack;
- bool mIsConnected;
- bool mIsMounted;
~VROculusSession();
void Uninitialize(bool aUnloadLib);
@@ -90,6 +84,7 @@ private:
class VRDisplayOculus : public VRDisplayHost
{
public:
+ virtual void NotifyVSync() override;
void ZeroSensor() override;
protected:
@@ -105,7 +100,6 @@ protected:
public:
explicit VRDisplayOculus(VROculusSession* aSession);
void Destroy();
- void Refresh();
protected:
virtual ~VRDisplayOculus();
@@ -182,10 +176,7 @@ public:
static already_AddRefed Create();
virtual void Destroy() override;
virtual void Shutdown() override;
- virtual void Enumerate() override;
- virtual void NotifyVSync() override;
- virtual bool ShouldInhibitEnumeration() override;
- virtual void GetHMDs(nsTArray >& aHMDResult) override;
+ virtual bool GetHMDs(nsTArray >& aHMDResult) override;
virtual bool GetIsPresenting() override;
virtual void HandleInput() override;
virtual void GetControllers(nsTArray>&
diff --git a/gfx/vr/gfxVROpenVR.cpp b/gfx/vr/gfxVROpenVR.cpp
index 009504f93498..c7a43df1050b 100644
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -202,10 +202,8 @@ VRDisplayOpenVR::GetIsHmdPresent()
}
void
-VRDisplayOpenVR::Refresh()
+VRDisplayOpenVR::PollEvents()
{
- mIsHmdPresent = ::vr::VR_IsHmdPresent();
-
::vr::VREvent_t event;
while (mVRSystem && mVRSystem->PollNextEvent(&event, sizeof(event))) {
switch (event.eventType) {
@@ -246,6 +244,8 @@ VRDisplayOpenVR::Refresh()
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.
@@ -422,6 +422,17 @@ VRDisplayOpenVR::SubmitFrame(MacIOSurface* aMacIOSurface,
#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)
@@ -622,87 +633,50 @@ VRSystemManagerOpenVR::Shutdown()
mVRSystem = nullptr;
}
-void
-VRSystemManagerOpenVR::NotifyVSync()
+bool
+VRSystemManagerOpenVR::GetHMDs(nsTArray>& aHMDResult)
{
- 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()) {
+ 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) {
::vr::HmdError err;
::vr::VR_Init(&err, ::vr::EVRApplicationType::VRApplication_Scene);
if (err) {
- return;
+ return false;
}
::vr::IVRSystem *system = (::vr::IVRSystem *)::vr::VR_GetGenericInterface(::vr::IVRSystem_Version, &err);
if (err || !system) {
::vr::VR_Shutdown();
- return;
+ return false;
}
::vr::IVRChaperone *chaperone = (::vr::IVRChaperone *)::vr::VR_GetGenericInterface(::vr::IVRChaperone_Version, &err);
if (err || !chaperone) {
::vr::VR_Shutdown();
- return;
+ return false;
}
::vr::IVRCompositor *compositor = (::vr::IVRCompositor*)::vr::VR_GetGenericInterface(::vr::IVRCompositor_Version, &err);
if (err || !compositor) {
::vr::VR_Shutdown();
- return;
+ return false;
}
mVRSystem = system;
mOpenVRHMD = new VRDisplayOpenVR(system, chaperone, compositor);
}
-}
-bool
-VRSystemManagerOpenVR::ShouldInhibitEnumeration()
-{
- if (VRSystemManager::ShouldInhibitEnumeration()) {
- return true;
- }
if (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.
+ aHMDResult.AppendElement(mOpenVRHMD);
return true;
}
return false;
}
-void
-VRSystemManagerOpenVR::GetHMDs(nsTArray>& aHMDResult)
-{
- if (mOpenVRHMD) {
- aHMDResult.AppendElement(mOpenVRHMD);
- }
-}
-
bool
VRSystemManagerOpenVR::GetIsPresenting()
{
diff --git a/gfx/vr/gfxVROpenVR.h b/gfx/vr/gfxVROpenVR.h
index 2bb310a697ed..f632c4266852 100644
--- a/gfx/vr/gfxVROpenVR.h
+++ b/gfx/vr/gfxVROpenVR.h
@@ -30,6 +30,7 @@ namespace impl {
class VRDisplayOpenVR : public VRDisplayHost
{
public:
+ virtual void NotifyVSync() override;
void ZeroSensor() override;
bool GetIsHmdPresent();
@@ -53,7 +54,7 @@ public:
explicit VRDisplayOpenVR(::vr::IVRSystem *aVRSystem,
::vr::IVRChaperone *aVRChaperone,
::vr::IVRCompositor *aVRCompositor);
- void Refresh();
+
protected:
virtual ~VRDisplayOpenVR();
void Destroy();
@@ -69,6 +70,7 @@ protected:
void UpdateStageParameters();
void UpdateEyeParameters(gfx::Matrix4x4* aHeadToEyeTransforms = nullptr);
+ void PollEvents();
bool SubmitFrame(void* aTextureHandle,
::vr::ETextureType aTextureType,
const IntSize& aSize,
@@ -125,10 +127,7 @@ public:
virtual void Destroy() override;
virtual void Shutdown() override;
- virtual void NotifyVSync() override;
- virtual void Enumerate() override;
- virtual bool ShouldInhibitEnumeration() override;
- virtual void GetHMDs(nsTArray>& aHMDResult) override;
+ virtual bool GetHMDs(nsTArray >& aHMDResult) override;
virtual bool GetIsPresenting() override;
virtual void HandleInput() override;
virtual void GetControllers(nsTArray>&
diff --git a/gfx/vr/gfxVRPuppet.cpp b/gfx/vr/gfxVRPuppet.cpp
index 8d5a6bae0199..6404f2c0ec65 100644
--- a/gfx/vr/gfxVRPuppet.cpp
+++ b/gfx/vr/gfxVRPuppet.cpp
@@ -566,10 +566,12 @@ VRDisplayPuppet::SubmitFrame(const mozilla::layers::EGLImageDescriptor* aDescrip
#endif
void
-VRDisplayPuppet::Refresh()
+VRDisplayPuppet::NotifyVSync()
{
- // We update mIsConneced once per refresh.
+ // We update mIsConneced once per frame.
mDisplayInfo.mIsConnected = true;
+
+ VRDisplayHost::NotifyVSync();
}
VRControllerPuppet::VRControllerPuppet(dom::GamepadHand aHand, uint32_t aDisplayID)
@@ -675,9 +677,6 @@ VRControllerPuppet::SetAxisMove(uint32_t aAxis, float aValue)
}
VRSystemManagerPuppet::VRSystemManagerPuppet()
- : mPuppetDisplayCount(0)
- , mPuppetDisplayInfo{}
- , mPuppetDisplaySensorState{}
{
}
@@ -701,119 +700,27 @@ VRSystemManagerPuppet::Destroy()
void
VRSystemManagerPuppet::Shutdown()
{
- mPuppetHMDs.Clear();
+ mPuppetHMD = nullptr;
}
-void
-VRSystemManagerPuppet::NotifyVSync()
-{
- VRSystemManager::NotifyVSync();
-
- for (const auto& display: mPuppetHMDs) {
- display->Refresh();
- }
-}
-
-uint32_t
-VRSystemManagerPuppet::CreateTestDisplay()
-{
- if (mPuppetDisplayCount >= kMaxPuppetDisplays) {
- MOZ_ASSERT(false);
- return mPuppetDisplayCount;
- }
- return mPuppetDisplayCount++;
-}
-
-void
-VRSystemManagerPuppet::ClearTestDisplays()
-{
- mPuppetDisplayCount = 0;
-}
-
-void
-VRSystemManagerPuppet::Enumerate()
-{
- while (mPuppetHMDs.Length() < mPuppetDisplayCount) {
- VRDisplayPuppet* puppetDisplay = new VRDisplayPuppet();
- uint32_t deviceID = mPuppetHMDs.Length();
- puppetDisplay->SetDisplayInfo(mPuppetDisplayInfo[deviceID]);
- puppetDisplay->SetSensorState(mPuppetDisplaySensorState[deviceID]);
- mPuppetHMDs.AppendElement(puppetDisplay);
- }
- while (mPuppetHMDs.Length() > mPuppetDisplayCount) {
- mPuppetHMDs.RemoveElementAt(mPuppetHMDs.Length() - 1);
- }
-}
-
-void
-VRSystemManagerPuppet::SetPuppetDisplayInfo(const uint32_t& aDeviceID,
- const VRDisplayInfo& aDisplayInfo)
-{
- if (aDeviceID >= mPuppetDisplayCount) {
- MOZ_ASSERT(false);
- return;
- }
- /**
- * Even if mPuppetHMDs.Length() <= aDeviceID, we need to
- * update mPuppetDisplayInfo[aDeviceID]. In the case that
- * a puppet display is added and SetPuppetDisplayInfo is
- * immediately called, mPuppetHMDs may not be populated yet.
- * VRSystemManagerPuppet::Enumerate() will initialize
- * the VRDisplayPuppet later using mPuppetDisplayInfo.
- */
- mPuppetDisplayInfo[aDeviceID] = aDisplayInfo;
- if (mPuppetHMDs.Length() > aDeviceID) {
- /**
- * In the event that the VRDisplayPuppet has already been
- * created, we update it directly.
- */
- mPuppetHMDs[aDeviceID]->SetDisplayInfo(aDisplayInfo);
- }
-}
-
-void
-VRSystemManagerPuppet::SetPuppetDisplaySensorState(const uint32_t& aDeviceID,
- const VRHMDSensorState& aSensorState)
-{
- if (aDeviceID >= mPuppetDisplayCount) {
- MOZ_ASSERT(false);
- return;
- }
- /**
- * Even if mPuppetHMDs.Length() <= aDeviceID, we need to
- * update mPuppetDisplaySensorState[aDeviceID]. In the case that
- * a puppet display is added and SetPuppetDisplaySensorState is
- * immediately called, mPuppetHMDs may not be populated yet.
- * VRSystemManagerPuppet::Enumerate() will initialize
- * the VRDisplayPuppet later using mPuppetDisplaySensorState.
- */
- mPuppetDisplaySensorState[aDeviceID] = aSensorState;
- if (mPuppetHMDs.Length() > aDeviceID) {
- /**
- * In the event that the VRDisplayPuppet has already been
- * created, we update it directly.
- */
- mPuppetHMDs[aDeviceID]->SetSensorState(aSensorState);
- }
-}
-
-void
+bool
VRSystemManagerPuppet::GetHMDs(nsTArray>& aHMDResult)
{
- for (auto display: mPuppetHMDs) {
- aHMDResult.AppendElement(display);
+ if (mPuppetHMD == nullptr) {
+ mPuppetHMD = new VRDisplayPuppet();
}
+ aHMDResult.AppendElement(mPuppetHMD);
+ return true;
}
bool
VRSystemManagerPuppet::GetIsPresenting()
{
- for (const auto& display: mPuppetHMDs) {
- const VRDisplayInfo& displayInfo(display->GetDisplayInfo());
- if (displayInfo.GetPresentingGroups() != kVRGroupNone) {
- return true;
- }
+ if (mPuppetHMD) {
+ VRDisplayInfo displayInfo(mPuppetHMD->GetDisplayInfo());
+ return displayInfo.GetPresentingGroups() != kVRGroupNone;
}
+
return false;
}
@@ -915,27 +822,28 @@ VRSystemManagerPuppet::GetControllers(nsTArray>& aContr
void
VRSystemManagerPuppet::ScanForControllers()
{
- // We make sure VRSystemManagerPuppet has two controllers
- // for each display
- const uint32_t newControllerCount = mPuppetHMDs.Length() * 2;
+ // mPuppetHMD is available after VRDisplay is created
+ // at GetHMDs().
+ if (!mPuppetHMD) {
+ return;
+ }
+ // We make VRSystemManagerPuppet has two controllers always.
+ const uint32_t newControllerCount = 2;
if (newControllerCount != mControllerCount) {
RemoveControllers();
// Re-adding controllers to VRControllerManager.
- for (const auto& display: mPuppetHMDs) {
- uint32_t displayID = display->GetDisplayInfo().GetDisplayID();
- for (uint32_t i = 0; i < 2; i++) {
- dom::GamepadHand hand = (i % 2) ? dom::GamepadHand::Right :
- dom::GamepadHand::Left;
- RefPtr puppetController;
- puppetController = new VRControllerPuppet(hand, displayID);
- mPuppetController.AppendElement(puppetController);
+ for (uint32_t i = 0; i < newControllerCount; ++i) {
+ dom::GamepadHand hand = (i % 2) ? dom::GamepadHand::Right :
+ dom::GamepadHand::Left;
+ RefPtr puppetController = new VRControllerPuppet(hand,
+ mPuppetHMD->GetDisplayInfo().GetDisplayID());
+ mPuppetController.AppendElement(puppetController);
- // Not already present, add it.
- AddGamepad(puppetController->GetControllerInfo());
- ++mControllerCount;
- }
+ // Not already present, add it.
+ AddGamepad(puppetController->GetControllerInfo());
+ ++mControllerCount;
}
}
}
diff --git a/gfx/vr/gfxVRPuppet.h b/gfx/vr/gfxVRPuppet.h
index e2da9950bcae..39b4cdc4c610 100644
--- a/gfx/vr/gfxVRPuppet.h
+++ b/gfx/vr/gfxVRPuppet.h
@@ -9,7 +9,6 @@
#include "nsTArray.h"
#include "mozilla/RefPtr.h"
-#include "nsRefPtrHashtable.h"
#include "gfxVR.h"
#include "VRDisplayHost.h"
@@ -25,6 +24,7 @@ class VRDisplayPuppet : public VRDisplayHost
{
public:
void SetDisplayInfo(const VRDisplayInfo& aDisplayInfo);
+ virtual void NotifyVSync() override;
void SetSensorState(const VRHMDSensorState& aSensorState);
void ZeroSensor() override;
@@ -50,7 +50,6 @@ protected:
public:
explicit VRDisplayPuppet();
- void Refresh();
protected:
virtual ~VRDisplayPuppet();
@@ -108,17 +107,10 @@ class VRSystemManagerPuppet : public VRSystemManager
{
public:
static already_AddRefed Create();
- uint32_t CreateTestDisplay();
- void ClearTestDisplays();
- void SetPuppetDisplayInfo(const uint32_t& aDeviceID,
- const VRDisplayInfo& aDisplayInfo);
- void SetPuppetDisplaySensorState(const uint32_t& aDeviceID,
- const VRHMDSensorState& aSensorState);
virtual void Destroy() override;
virtual void Shutdown() override;
- virtual void Enumerate() override;
- virtual void GetHMDs(nsTArray>& aHMDResult) override;
+ virtual bool GetHMDs(nsTArray>& aHMDResult) override;
virtual bool GetIsPresenting() override;
virtual void HandleInput() override;
virtual void GetControllers(nsTArray>&
@@ -131,7 +123,6 @@ public:
double aDuration,
uint32_t aPromiseID) override;
virtual void StopVibrateHaptic(uint32_t aControllerIdx) override;
- virtual void NotifyVSync() override;
protected:
VRSystemManagerPuppet();
@@ -148,15 +139,9 @@ private:
const dom::GamepadPoseState& aPose,
VRControllerHost* aController);
- // Enumerated puppet hardware devices, as seen by Web APIs:
- nsTArray> mPuppetHMDs;
+ // there can only be one
+ RefPtr mPuppetHMD;
nsTArray> mPuppetController;
-
- // Emulated hardware state, persistent through VRSystemManager::Shutdown():
- static const uint32_t kMaxPuppetDisplays = 5;
- uint32_t mPuppetDisplayCount;
- VRDisplayInfo mPuppetDisplayInfo[kMaxPuppetDisplays];
- VRHMDSensorState mPuppetDisplaySensorState[kMaxPuppetDisplays];
};
} // namespace gfx
diff --git a/gfx/vr/ipc/VRManagerChild.cpp b/gfx/vr/ipc/VRManagerChild.cpp
index f6b549a5a71c..78dc67e478ea 100644
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -405,14 +405,7 @@ VRManagerChild::RecvReplyCreateVRServiceTestController(const nsCString& aID,
MOZ_CRASH("We should always have a promise.");
}
- if (aDeviceID == 0) {
- // A value of 0 indicates that the controller could not
- // be created. Most likely due to having no VR display
- // to associate it with.
- p->MaybeRejectWithUndefined();
- } else {
- p->MaybeResolve(new VRMockController(aID, aDeviceID));
- }
+ p->MaybeResolve(new VRMockController(aID, aDeviceID));
mPromiseList.Remove(aPromiseID);
return IPC_OK();
}
diff --git a/gfx/vr/ipc/VRManagerParent.cpp b/gfx/vr/ipc/VRManagerParent.cpp
index ec7e65de3d3c..c270299cce96 100644
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -20,7 +20,8 @@ using namespace layers;
namespace gfx {
VRManagerParent::VRManagerParent(ProcessId aChildProcessId, bool aIsContentChild)
- : mControllerTestID(1)
+ : mDisplayTestID(0)
+ , mControllerTestID(0)
, mHaveEventListener(false)
, mHaveControllerListener(false)
, mIsContentChild(aIsContentChild)
@@ -246,19 +247,37 @@ VRManagerParent::RecvCreateVRTestSystem()
{
VRManager* vm = VRManager::Get();
vm->CreateVRTestSystem();
- // The mControllerTestID is 1 based
- mControllerTestID = 1;
+ mDisplayTestID = 0;
+ mControllerTestID = 0;
return IPC_OK();
}
mozilla::ipc::IPCResult
VRManagerParent::RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint32_t& aPromiseID)
{
+ nsTArray displayInfoArray;
+ impl::VRDisplayPuppet* displayPuppet = nullptr;
VRManager* vm = VRManager::Get();
- VRSystemManagerPuppet* puppetManager = vm->GetPuppetManager();
- uint32_t deviceID = puppetManager->CreateTestDisplay();
+ vm->RefreshVRDisplays();
- if (SendReplyCreateVRServiceTestDisplay(aID, aPromiseID, deviceID)) {
+ // Get VRDisplayPuppet from VRManager
+ vm->GetVRDisplayInfo(displayInfoArray);
+ for (auto& displayInfo : displayInfoArray) {
+ if (displayInfo.GetType() == VRDeviceType::Puppet) {
+ displayPuppet = static_cast(
+ vm->GetDisplay(displayInfo.GetDisplayID()).get());
+ break;
+ }
+ }
+
+ MOZ_ASSERT(displayPuppet);
+ MOZ_ASSERT(!mDisplayTestID); // We have only one display in VRSystemManagerPuppet.
+
+ if (!mVRDisplayTests.Get(mDisplayTestID, nullptr)) {
+ mVRDisplayTests.Put(mDisplayTestID, displayPuppet);
+ }
+
+ if (SendReplyCreateVRServiceTestDisplay(aID, aPromiseID, mDisplayTestID)) {
return IPC_OK();
}
@@ -268,20 +287,14 @@ VRManagerParent::RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint
mozilla::ipc::IPCResult
VRManagerParent::RecvCreateVRServiceTestController(const nsCString& aID, const uint32_t& aPromiseID)
{
- uint32_t controllerIdx = 1; // ID's are 1 based
+ uint32_t controllerIdx = 0;
nsTArray controllerInfoArray;
impl::VRControllerPuppet* controllerPuppet = nullptr;
VRManager* vm = VRManager::Get();
- /**
- * When running headless mochitests on some of our automated test
- * infrastructure, 2d display vsyncs are not always generated.
- * In this case, the test controllers can't be created immediately
- * after the VR display was created as the state of the VR displays
- * are updated during vsync.
- * To workaround, we produce a vsync manually.
- */
- vm->NotifyVsync(TimeStamp::Now());
+ if (mHaveControllerListener) {
+ vm->RefreshVRControllers();
+ }
// Get VRControllerPuppet from VRManager
vm->GetVRControllerInfo(controllerInfoArray);
@@ -296,22 +309,16 @@ VRManagerParent::RecvCreateVRServiceTestController(const nsCString& aID, const u
}
}
- // We might not have a controllerPuppet if the test did
- // not create a VR display first.
- if (!controllerPuppet) {
- // We send a device ID of "0" to indicate failure
- if (SendReplyCreateVRServiceTestController(aID, aPromiseID, 0)) {
- return IPC_OK();
- }
- } else {
- if (!mVRControllerTests.Get(mControllerTestID, nullptr)) {
- mVRControllerTests.Put(mControllerTestID, controllerPuppet);
- }
+ MOZ_ASSERT(controllerPuppet);
+ MOZ_ASSERT(mControllerTestID < 2); // We have only two controllers in VRSystemManagerPuppet.
- if (SendReplyCreateVRServiceTestController(aID, aPromiseID, mControllerTestID)) {
- ++mControllerTestID;
- return IPC_OK();
- }
+ if (!mVRControllerTests.Get(mControllerTestID, nullptr)) {
+ mVRControllerTests.Put(mControllerTestID, controllerPuppet);
+ }
+
+ if (SendReplyCreateVRServiceTestController(aID, aPromiseID, mControllerTestID)) {
+ ++mControllerTestID;
+ return IPC_OK();
}
return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
@@ -321,9 +328,11 @@ mozilla::ipc::IPCResult
VRManagerParent::RecvSetDisplayInfoToMockDisplay(const uint32_t& aDeviceID,
const VRDisplayInfo& aDisplayInfo)
{
- VRManager* vm = VRManager::Get();
- VRSystemManagerPuppet* puppetManager = vm->GetPuppetManager();
- puppetManager->SetPuppetDisplayInfo(aDeviceID, aDisplayInfo);
+ RefPtr displayPuppet;
+ mVRDisplayTests.Get(aDeviceID,
+ getter_AddRefs(displayPuppet));
+ MOZ_ASSERT(displayPuppet);
+ displayPuppet->SetDisplayInfo(aDisplayInfo);
return IPC_OK();
}
@@ -331,33 +340,23 @@ mozilla::ipc::IPCResult
VRManagerParent::RecvSetSensorStateToMockDisplay(const uint32_t& aDeviceID,
const VRHMDSensorState& aSensorState)
{
- VRManager* vm = VRManager::Get();
- VRSystemManagerPuppet* puppetManager = vm->GetPuppetManager();
- puppetManager->SetPuppetDisplaySensorState(aDeviceID, aSensorState);
+ RefPtr displayPuppet;
+ mVRDisplayTests.Get(aDeviceID,
+ getter_AddRefs(displayPuppet));
+ MOZ_ASSERT(displayPuppet);
+ displayPuppet->SetSensorState(aSensorState);
return IPC_OK();
}
-already_AddRefed
-VRManagerParent::GetControllerPuppet(uint32_t aDeviceID)
-{
- // aDeviceID for controllers start at 1 and are
- // used as a key to mVRControllerTests
- MOZ_ASSERT(aDeviceID > 0);
- RefPtr controllerPuppet;
- mVRControllerTests.Get(aDeviceID,
- getter_AddRefs(controllerPuppet));
- MOZ_ASSERT(controllerPuppet);
- return controllerPuppet.forget();
-}
-
mozilla::ipc::IPCResult
VRManagerParent::RecvNewButtonEventToMockController(const uint32_t& aDeviceID, const long& aButton,
const bool& aPressed)
{
- RefPtr controllerPuppet = GetControllerPuppet(aDeviceID);
- if (controllerPuppet) {
- controllerPuppet->SetButtonPressState(aButton, aPressed);
- }
+ RefPtr controllerPuppet;
+ mVRControllerTests.Get(aDeviceID,
+ getter_AddRefs(controllerPuppet));
+ MOZ_ASSERT(controllerPuppet);
+ controllerPuppet->SetButtonPressState(aButton, aPressed);
return IPC_OK();
}
@@ -365,10 +364,11 @@ mozilla::ipc::IPCResult
VRManagerParent::RecvNewAxisMoveEventToMockController(const uint32_t& aDeviceID, const long& aAxis,
const double& aValue)
{
- RefPtr controllerPuppet = GetControllerPuppet(aDeviceID);
- if (controllerPuppet) {
- controllerPuppet->SetAxisMoveState(aAxis, aValue);
- }
+ RefPtr controllerPuppet;
+ mVRControllerTests.Get(aDeviceID,
+ getter_AddRefs(controllerPuppet));
+ MOZ_ASSERT(controllerPuppet);
+ controllerPuppet->SetAxisMoveState(aAxis, aValue);
return IPC_OK();
}
@@ -376,10 +376,11 @@ mozilla::ipc::IPCResult
VRManagerParent::RecvNewPoseMoveToMockController(const uint32_t& aDeviceID,
const GamepadPoseState& pose)
{
- RefPtr controllerPuppet = GetControllerPuppet(aDeviceID);
- if (controllerPuppet) {
- controllerPuppet->SetPoseMoveState(pose);
- }
+ RefPtr controllerPuppet;
+ mVRControllerTests.Get(aDeviceID,
+ getter_AddRefs(controllerPuppet));
+ MOZ_ASSERT(controllerPuppet);
+ controllerPuppet->SetPoseMoveState(pose);
return IPC_OK();
}
diff --git a/gfx/vr/ipc/VRManagerParent.h b/gfx/vr/ipc/VRManagerParent.h
index c5606371a55d..9129a3bbbef0 100644
--- a/gfx/vr/ipc/VRManagerParent.h
+++ b/gfx/vr/ipc/VRManagerParent.h
@@ -83,7 +83,6 @@ private:
static void RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager);
void DeferredDestroy();
- already_AddRefed GetControllerPuppet(uint32_t aDeviceID);
// This keeps us alive until ActorDestroy(), at which point we do a
// deferred destruction of ourselves.
@@ -92,7 +91,9 @@ private:
// Keep the VRManager alive, until we have destroyed ourselves.
RefPtr mVRManagerHolder;
+ nsRefPtrHashtable mVRDisplayTests;
nsRefPtrHashtable mVRControllerTests;
+ uint32_t mDisplayTestID;
uint32_t mControllerTestID;
bool mHaveEventListener;
bool mHaveControllerListener;
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 90ee3f9065ff..b86f4dfba2a1 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5157,20 +5157,6 @@ pref("dom.vr.openvr.enabled", true);
// 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.