Bug 1407423 - Part 3: Update Puppet Device Implementation
- Update prefs to accomodate tests, disabling
enumeration throttling
- Updated Puppet display and controller implementation
to act more like the actual devices.
- Updated tests to ensure that they explicitly
create a VR mock display and don't create duplicate
mock displays.
MozReview-Commit-ID: 7GSoYVxmqgM
--- a/dom/vr/test/mochitest/VRSimulationDriver.js
+++ b/dom/vr/test/mochitest/VRSimulationDriver.js
@@ -1,16 +1,20 @@
var VRServiceTest;
var vrMockDisplay;
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.");
vrMockDisplay = display;
});
return promise;
};
--- a/dom/vr/test/mochitest/runVRTest.js
+++ b/dom/vr/test/mochitest/runVRTest.js
@@ -1,9 +1,11 @@
function runVRTest(callback) {
SpecialPowers.pushPrefEnv({"set" : [["dom.vr.puppet.enabled", true],
["dom.vr.require-gesture", false],
- ["dom.vr.test.enabled", true]]},
+ ["dom.vr.test.enabled", true],
+ ["dom.vr.display.enumerate.interval", 0],
+ ["dom.vr.controller.enumerate.interval", 0]]},
() => {
VRServiceTest = navigator.requestVRServiceTest();
callback();
});
}
\ No newline at end of file
--- a/dom/vr/test/mochitest/test_vrController_displayId.html
+++ b/dom/vr/test/mochitest/test_vrController_displayId.html
@@ -33,22 +33,24 @@
}
});
}, "Finish to verify VRController.displayId.");
}
function startTest() {
promise_test((test) => {
listenControllerEvents();
- 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 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();
+ });
});
}, "Finish to add VRDisplay.");
}
runVRTest(startTest);
</script>
</body>
</html>
\ No newline at end of file
--- a/dom/vr/test/mochitest/test_vrDisplay_canvas2d.html
+++ b/dom/vr/test/mochitest/test_vrDisplay_canvas2d.html
@@ -1,16 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<title>VRDisplay Canvas2D</title>
<meta name="timeout" content="long"/>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
+ <script src="VRSimulationDriver.js"></script>
<script src="runVRTest.js"></script>
</head>
<body>
<script>
"use strict";
var vrDisplay;
function requestPresentTest() {
@@ -30,22 +31,24 @@
function startTest() {
promise_test((test) => {
var canvas = document.createElement('canvas');
(document.body || document.documentElement).appendChild(canvas);
var context = canvas.getContext('2d');
var img = document.createElement('img');
img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACw=";
- 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 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();
+ });
});
});
}, "Finish running WebVR Canvas2D test.");
}
runVRTest(startTest);
</script>
</body>
--- a/dom/vr/test/mochitest/test_vrDisplay_exitPresent.html
+++ b/dom/vr/test/mochitest/test_vrDisplay_exitPresent.html
@@ -1,44 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<title>VRDisplay ExitPresent</title>
<meta name="timeout" content="long"/>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
+ <script src="VRSimulationDriver.js"></script>
<script src="runVRTest.js"></script>
</head>
<body>
<script>
function testExitPresentOnOtherIframe(content) {
return content.navigator.getVRDisplays().then((displays) => {
content.vrDisplay = displays[0];
return content.vrDisplay.exitPresent();
});
}
var initVRPresentation = function(content) {
- return content.navigator.getVRDisplays().then((displays) => {
+ return VRSimulationDriver.AttachWebVRDisplay().then(() => {
+ 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;
- 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.")
- });
+ 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.");
}
runVRTest(startTest);
</script>
<iframe id="iframe1"></iframe>
<iframe id="iframe2"></iframe>
</body>
</html>
\ No newline at end of file
--- a/dom/vr/test/reftest/VRSimulationDriver.js
+++ b/dom/vr/test/reftest/VRSimulationDriver.js
@@ -1,16 +1,20 @@
var VRServiceTest;
var vrMockDisplay;
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;
});
return promise;
};
--- a/dom/vr/test/reftest/reftest.list
+++ b/dom/vr/test/reftest/reftest.list
@@ -1,10 +1,10 @@
# 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)
+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)
# 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.
skip-if((!winWidget&&release_or_beta)||Android||gtkWidget||!layersGPUAccelerated||/^Windows\x20NT\x206\.1/.test(http.oscpu)) == draw_rect.html wrapper.html?draw_rect.png
# On MacOSX platform, getting different color interpolation result.
# For lower resolution Mac hardware, we need to adjust it to fuzzy-if(cocoaWidget,1,1200).
fuzzy-if(cocoaWidget,1,600) skip-if((!winWidget&&release_or_beta)||Android||gtkWidget||!layersGPUAccelerated||/^Windows\x20NT\x206\.1/.test(http.oscpu)) == change_size.html wrapper.html?change_size.png
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -50,17 +50,16 @@ VRManager::ManagerInit()
if (sVRManagerSingleton == nullptr) {
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;
@@ -493,25 +492,30 @@ VRManager::RemoveControllers()
mManagers[i]->RemoveControllers();
}
mVRControllers.Clear();
}
void
VRManager::CreateVRTestSystem()
{
- if (mVRTestSystemCreated) {
+ if (mPuppetManager) {
+ mPuppetManager->ClearTestDisplays();
return;
}
- RefPtr<VRSystemManager> mgr = VRSystemManagerPuppet::Create();
- if (mgr) {
- mManagers.AppendElement(mgr);
- mVRTestSystemCreated = true;
- }
+ mPuppetManager = VRSystemManagerPuppet::Create();
+ mManagers.AppendElement(mPuppetManager);
+}
+
+VRSystemManagerPuppet*
+VRManager::GetPuppetManager()
+{
+ MOZ_ASSERT(mPuppetManager);
+ return mPuppetManager;
}
template<class T>
void
VRManager::NotifyGamepadChange(uint32_t aIndex, const T& aInfo)
{
dom::GamepadChangeEventBody body(aInfo);
dom::GamepadChangeEvent e(aIndex, dom::GamepadServiceType::VR, body);
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -18,16 +18,17 @@ namespace mozilla {
namespace layers {
class TextureHost;
}
namespace gfx {
class VRLayerParent;
class VRManagerParent;
class VRDisplayHost;
+class VRSystemManagerPuppet;
class VRManager
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::gfx::VRManager)
public:
static void ManagerInit();
static VRManager* Get();
@@ -42,16 +43,18 @@ public:
void ScanForControllers();
void RemoveControllers();
template<class T> void NotifyGamepadChange(uint32_t aIndex, const T& aInfo);
RefPtr<gfx::VRDisplayHost> GetDisplay(const uint32_t& aDisplayID);
void GetVRDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayInfo);
RefPtr<gfx::VRControllerHost> GetController(const uint32_t& aControllerID);
void GetVRControllerInfo(nsTArray<VRControllerInfo>& 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);
void NotifyVibrateHapticCompleted(uint32_t aPromiseID);
void DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameResultInfo& aResult);
protected:
VRManager();
@@ -80,17 +83,17 @@ private:
typedef nsRefPtrHashtable<nsUint32HashKey, gfx::VRControllerHost> VRControllerHostHashMap;
VRControllerHostHashMap mVRControllers;
Atomic<bool> mInitialized;
TimeStamp mLastControllerEnumerationTime;
TimeStamp mLastDisplayEnumerationTime;
TimeStamp mLastActiveTime;
- bool mVRTestSystemCreated;
+ RefPtr<VRSystemManagerPuppet> mPuppetManager;
bool mVRDisplaysRequested;
bool mVRControllersRequested;
};
} // namespace gfx
} // namespace mozilla
#endif // GFX_VR_MANAGER_H
--- a/gfx/vr/gfxVRPuppet.cpp
+++ b/gfx/vr/gfxVRPuppet.cpp
@@ -670,16 +670,19 @@ VRControllerPuppet::GetAxisMove(uint32_t
void
VRControllerPuppet::SetAxisMove(uint32_t aAxis, float aValue)
{
mAxisMove[aAxis] = aValue;
}
VRSystemManagerPuppet::VRSystemManagerPuppet()
+ : mPuppetDisplayCount(0)
+ , mPuppetDisplayInfo{}
+ , mPuppetDisplaySensorState{}
{
}
/*static*/ already_AddRefed<VRSystemManagerPuppet>
VRSystemManagerPuppet::Create()
{
if (!gfxPrefs::VREnabled() || !gfxPrefs::VRPuppetEnabled()) {
return nullptr;
@@ -693,68 +696,105 @@ void
VRSystemManagerPuppet::Destroy()
{
Shutdown();
}
void
VRSystemManagerPuppet::Shutdown()
{
- mPuppetHMD = nullptr;
+ mPuppetHMDs.Clear();
}
void
VRSystemManagerPuppet::NotifyVSync()
{
VRSystemManager::NotifyVSync();
- if (mPuppetHMD) {
- mPuppetHMD->Refresh();
+
+ 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()
{
- if (mPuppetHMD == nullptr) {
- mPuppetHMD = new VRDisplayPuppet();
+ 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);
}
}
-bool
-VRSystemManagerPuppet::ShouldInhibitEnumeration()
+void
+VRSystemManagerPuppet::SetPuppetDisplayInfo(const uint32_t& aDeviceID,
+ const VRDisplayInfo& aDisplayInfo)
{
- if (VRSystemManager::ShouldInhibitEnumeration()) {
- return true;
+ if (aDeviceID >= mPuppetDisplayCount) {
+ MOZ_ASSERT(false);
+ return;
+ }
+ mPuppetDisplayInfo[aDeviceID] = aDisplayInfo;
+ if (mPuppetHMDs.Length() > aDeviceID) {
+ mPuppetHMDs[aDeviceID]->SetDisplayInfo(aDisplayInfo);
}
- 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;
+}
+
+void
+VRSystemManagerPuppet::SetPuppetDisplaySensorState(const uint32_t& aDeviceID,
+ const VRHMDSensorState& aSensorState)
+{
+ if (aDeviceID >= mPuppetDisplayCount) {
+ MOZ_ASSERT(false);
+ return;
}
- return false;
+ mPuppetDisplaySensorState[aDeviceID] = aSensorState;
+ if (mPuppetHMDs.Length() > aDeviceID) {
+ mPuppetHMDs[aDeviceID]->SetSensorState(aSensorState);
+ }
}
void
VRSystemManagerPuppet::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
{
- if (mPuppetHMD) {
- aHMDResult.AppendElement(mPuppetHMD);
+ for (auto display: mPuppetHMDs) {
+ aHMDResult.AppendElement(display);
}
}
bool
VRSystemManagerPuppet::GetIsPresenting()
{
- if (mPuppetHMD) {
- VRDisplayInfo displayInfo(mPuppetHMD->GetDisplayInfo());
- return displayInfo.GetPresentingGroups() != kVRGroupNone;
+ for (const auto& display: mPuppetHMDs) {
+ const VRDisplayInfo& displayInfo(display->GetDisplayInfo());
+ if (displayInfo.GetPresentingGroups() != kVRGroupNone) {
+ return true;
+ }
}
-
return false;
}
void
VRSystemManagerPuppet::HandleInput()
{
RefPtr<impl::VRControllerPuppet> controller;
for (uint32_t i = 0; i < mPuppetController.Length(); ++i) {
@@ -846,38 +886,37 @@ VRSystemManagerPuppet::GetControllers(ns
for (uint32_t i = 0; i < mPuppetController.Length(); ++i) {
aControllerResult.AppendElement(mPuppetController[i]);
}
}
void
VRSystemManagerPuppet::ScanForControllers()
{
- // mPuppetHMD is available after VRDisplay is created
- // at GetHMDs().
- if (!mPuppetHMD) {
- return;
- }
- // We make VRSystemManagerPuppet has two controllers always.
- const uint32_t newControllerCount = 2;
+ // We make sure VRSystemManagerPuppet has two controllers
+ // for each display
+ const uint32_t newControllerCount = mPuppetHMDs.Length() * 2;
if (newControllerCount != mControllerCount) {
RemoveControllers();
// Re-adding controllers to VRControllerManager.
- for (uint32_t i = 0; i < newControllerCount; ++i) {
- dom::GamepadHand hand = (i % 2) ? dom::GamepadHand::Right :
- dom::GamepadHand::Left;
- RefPtr<VRControllerPuppet> puppetController = new VRControllerPuppet(hand,
- mPuppetHMD->GetDisplayInfo().GetDisplayID());
- mPuppetController.AppendElement(puppetController);
+ 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<VRControllerPuppet> puppetController;
+ puppetController = new VRControllerPuppet(hand, displayID);
+ mPuppetController.AppendElement(puppetController);
- // Not already present, add it.
- AddGamepad(puppetController->GetControllerInfo());
- ++mControllerCount;
+ // Not already present, add it.
+ AddGamepad(puppetController->GetControllerInfo());
+ ++mControllerCount;
+ }
}
}
}
void
VRSystemManagerPuppet::RemoveControllers()
{
// controller count is changed, removing the existing gamepads first.
--- a/gfx/vr/gfxVRPuppet.h
+++ b/gfx/vr/gfxVRPuppet.h
@@ -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/. */
#ifndef GFX_VR_PUPPET_H
#define GFX_VR_PUPPET_H
#include "nsTArray.h"
#include "mozilla/RefPtr.h"
+#include "nsRefPtrHashtable.h"
#include "gfxVR.h"
#include "VRDisplayHost.h"
#if defined(XP_MACOSX)
class MacIOSurface;
#endif
namespace mozilla {
@@ -102,21 +103,26 @@ private:
};
} // namespace impl
class VRSystemManagerPuppet : public VRSystemManager
{
public:
static already_AddRefed<VRSystemManagerPuppet> 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 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,
@@ -137,17 +143,23 @@ private:
uint64_t aButtonPressed,
uint64_t aButtonTouched);
void HandleAxisMove(uint32_t aControllerIndex, uint32_t aAxis,
float aValue);
void HandlePoseTracking(uint32_t aControllerIndex,
const dom::GamepadPoseState& aPose,
VRControllerHost* aController);
- // there can only be one
- RefPtr<impl::VRDisplayPuppet> mPuppetHMD;
+ // Enumerated puppet hardware devices, as seen by Web APIs:
+ nsTArray<RefPtr<impl::VRDisplayPuppet>> mPuppetHMDs;
nsTArray<RefPtr<impl::VRControllerPuppet>> 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
} // namespace mozilla
#endif /* GFX_VR_PUPPET_H*/
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -400,17 +400,24 @@ VRManagerChild::RecvReplyCreateVRService
const uint32_t& aPromiseID,
const uint32_t& aDeviceID)
{
RefPtr<dom::Promise> p;
if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
MOZ_CRASH("We should always have a promise.");
}
- p->MaybeResolve(new VRMockController(aID, aDeviceID));
+ 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));
+ }
mPromiseList.Remove(aPromiseID);
return IPC_OK();
}
void
VRManagerChild::RunFrameRequestCallbacks()
{
AUTO_PROFILER_TRACING("VR", "RunFrameRequestCallbacks");
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -15,18 +15,17 @@
#include "VRThread.h"
#include "gfxVRPuppet.h"
namespace mozilla {
using namespace layers;
namespace gfx {
VRManagerParent::VRManagerParent(ProcessId aChildProcessId, bool aIsContentChild)
- : mDisplayTestID(0)
- , mControllerTestID(0)
+ : mControllerTestID(1)
, mHaveEventListener(false)
, mHaveControllerListener(false)
, mIsContentChild(aIsContentChild)
{
MOZ_COUNT_CTOR(VRManagerParent);
MOZ_ASSERT(NS_IsMainThread());
SetOtherProcessId(aChildProcessId);
@@ -242,150 +241,150 @@ VRManagerParent::RecvControllerListenerR
return IPC_OK();
}
mozilla::ipc::IPCResult
VRManagerParent::RecvCreateVRTestSystem()
{
VRManager* vm = VRManager::Get();
vm->CreateVRTestSystem();
- mDisplayTestID = 0;
- mControllerTestID = 0;
+ // The mControllerTestID is 1 based
+ mControllerTestID = 1;
return IPC_OK();
}
mozilla::ipc::IPCResult
VRManagerParent::RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint32_t& aPromiseID)
{
- nsTArray<VRDisplayInfo> displayInfoArray;
- impl::VRDisplayPuppet* displayPuppet = nullptr;
VRManager* vm = VRManager::Get();
- vm->RefreshVRDisplays();
+ VRSystemManagerPuppet* puppetManager = vm->GetPuppetManager();
+ uint32_t deviceID = puppetManager->CreateTestDisplay();
- // Get VRDisplayPuppet from VRManager
- vm->GetVRDisplayInfo(displayInfoArray);
- for (auto& displayInfo : displayInfoArray) {
- if (displayInfo.GetType() == VRDeviceType::Puppet) {
- displayPuppet = static_cast<impl::VRDisplayPuppet*>(
- 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)) {
+ if (SendReplyCreateVRServiceTestDisplay(aID, aPromiseID, deviceID)) {
return IPC_OK();
}
return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
}
mozilla::ipc::IPCResult
VRManagerParent::RecvCreateVRServiceTestController(const nsCString& aID, const uint32_t& aPromiseID)
{
- uint32_t controllerIdx = 0;
+ uint32_t controllerIdx = 1; // ID's are 1 based
nsTArray<VRControllerInfo> controllerInfoArray;
impl::VRControllerPuppet* controllerPuppet = nullptr;
VRManager* vm = VRManager::Get();
- if (mHaveControllerListener) {
- vm->RefreshVRControllers();
- }
+ /**
+ * 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());
// Get VRControllerPuppet from VRManager
vm->GetVRControllerInfo(controllerInfoArray);
for (auto& controllerInfo : controllerInfoArray) {
if (controllerInfo.GetType() == VRDeviceType::Puppet) {
if (controllerIdx == mControllerTestID) {
controllerPuppet = static_cast<impl::VRControllerPuppet*>(
vm->GetController(controllerInfo.GetControllerID()).get());
break;
}
++controllerIdx;
}
}
- MOZ_ASSERT(controllerPuppet);
- MOZ_ASSERT(mControllerTestID < 2); // We have only two controllers in VRSystemManagerPuppet.
+
+ // 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);
+ }
- if (!mVRControllerTests.Get(mControllerTestID, nullptr)) {
- mVRControllerTests.Put(mControllerTestID, controllerPuppet);
- }
-
- if (SendReplyCreateVRServiceTestController(aID, aPromiseID, mControllerTestID)) {
- ++mControllerTestID;
- return IPC_OK();
+ if (SendReplyCreateVRServiceTestController(aID, aPromiseID, mControllerTestID)) {
+ ++mControllerTestID;
+ return IPC_OK();
+ }
}
return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
}
mozilla::ipc::IPCResult
VRManagerParent::RecvSetDisplayInfoToMockDisplay(const uint32_t& aDeviceID,
const VRDisplayInfo& aDisplayInfo)
{
- RefPtr<impl::VRDisplayPuppet> displayPuppet;
- mVRDisplayTests.Get(aDeviceID,
- getter_AddRefs(displayPuppet));
- MOZ_ASSERT(displayPuppet);
- displayPuppet->SetDisplayInfo(aDisplayInfo);
+ VRManager* vm = VRManager::Get();
+ VRSystemManagerPuppet* puppetManager = vm->GetPuppetManager();
+ puppetManager->SetPuppetDisplayInfo(aDeviceID, aDisplayInfo);
return IPC_OK();
}
mozilla::ipc::IPCResult
VRManagerParent::RecvSetSensorStateToMockDisplay(const uint32_t& aDeviceID,
const VRHMDSensorState& aSensorState)
{
- RefPtr<impl::VRDisplayPuppet> displayPuppet;
- mVRDisplayTests.Get(aDeviceID,
- getter_AddRefs(displayPuppet));
- MOZ_ASSERT(displayPuppet);
- displayPuppet->SetSensorState(aSensorState);
+ VRManager* vm = VRManager::Get();
+ VRSystemManagerPuppet* puppetManager = vm->GetPuppetManager();
+ puppetManager->SetPuppetDisplaySensorState(aDeviceID, aSensorState);
return IPC_OK();
}
+already_AddRefed<impl::VRControllerPuppet>
+VRManagerParent::GetControllerPuppet(uint32_t aDeviceID)
+{
+ // aDeviceID for controllers start at 1 and are
+ // used as a key to mVRControllerTests
+ RefPtr<impl::VRControllerPuppet> 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<impl::VRControllerPuppet> controllerPuppet;
- mVRControllerTests.Get(aDeviceID,
- getter_AddRefs(controllerPuppet));
- MOZ_ASSERT(controllerPuppet);
- controllerPuppet->SetButtonPressState(aButton, aPressed);
+ RefPtr<impl::VRControllerPuppet> controllerPuppet = GetControllerPuppet(aDeviceID);
+ if (controllerPuppet) {
+ controllerPuppet->SetButtonPressState(aButton, aPressed);
+ }
return IPC_OK();
}
mozilla::ipc::IPCResult
VRManagerParent::RecvNewAxisMoveEventToMockController(const uint32_t& aDeviceID, const long& aAxis,
const double& aValue)
{
- RefPtr<impl::VRControllerPuppet> controllerPuppet;
- mVRControllerTests.Get(aDeviceID,
- getter_AddRefs(controllerPuppet));
- MOZ_ASSERT(controllerPuppet);
- controllerPuppet->SetAxisMoveState(aAxis, aValue);
+ RefPtr<impl::VRControllerPuppet> controllerPuppet = GetControllerPuppet(aDeviceID);
+ if (controllerPuppet) {
+ controllerPuppet->SetAxisMoveState(aAxis, aValue);
+ }
return IPC_OK();
}
mozilla::ipc::IPCResult
VRManagerParent::RecvNewPoseMoveToMockController(const uint32_t& aDeviceID,
const GamepadPoseState& pose)
{
- RefPtr<impl::VRControllerPuppet> controllerPuppet;
- mVRControllerTests.Get(aDeviceID,
- getter_AddRefs(controllerPuppet));
- MOZ_ASSERT(controllerPuppet);
- controllerPuppet->SetPoseMoveState(pose);
+ RefPtr<impl::VRControllerPuppet> controllerPuppet = GetControllerPuppet(aDeviceID);
+ if (controllerPuppet) {
+ controllerPuppet->SetPoseMoveState(pose);
+ }
return IPC_OK();
}
mozilla::ipc::IPCResult
VRManagerParent::RecvVibrateHaptic(const uint32_t& aControllerIdx,
const uint32_t& aHapticIndex,
const double& aIntensity,
const double& aDuration,
--- a/gfx/vr/ipc/VRManagerParent.h
+++ b/gfx/vr/ipc/VRManagerParent.h
@@ -78,27 +78,26 @@ private:
void RegisterWithManager();
void UnregisterFromManager();
void Bind(Endpoint<PVRManagerParent>&& aEndpoint);
static void RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager);
void DeferredDestroy();
+ already_AddRefed<impl::VRControllerPuppet> GetControllerPuppet(uint32_t aDeviceID);
// This keeps us alive until ActorDestroy(), at which point we do a
// deferred destruction of ourselves.
RefPtr<VRManagerParent> mSelfRef;
RefPtr<VRListenerThreadHolder> mVRListenerThreadHolder;
// Keep the VRManager alive, until we have destroyed ourselves.
RefPtr<VRManager> mVRManagerHolder;
- nsRefPtrHashtable<nsUint32HashKey, impl::VRDisplayPuppet> mVRDisplayTests;
nsRefPtrHashtable<nsUint32HashKey, impl::VRControllerPuppet> mVRControllerTests;
- uint32_t mDisplayTestID;
uint32_t mControllerTestID;
bool mHaveEventListener;
bool mHaveControllerListener;
bool mIsContentChild;
};
} // namespace mozilla
} // namespace gfx