diff options
Diffstat (limited to 'dom/vr/VRServiceTest.cpp')
-rw-r--r-- | dom/vr/VRServiceTest.cpp | 740 |
1 files changed, 740 insertions, 0 deletions
diff --git a/dom/vr/VRServiceTest.cpp b/dom/vr/VRServiceTest.cpp new file mode 100644 index 0000000000..06720328c2 --- /dev/null +++ b/dom/vr/VRServiceTest.cpp @@ -0,0 +1,740 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 "mozilla/dom/VRServiceTest.h" +#include "mozilla/dom/VRServiceTestBinding.h" +#include "mozilla/dom/GamepadPoseState.h" +#include "mozilla/dom/Promise.h" +#include "VRManagerChild.h" +#include "VRPuppetCommandBuffer.h" +#include <type_traits> + +namespace mozilla { +using namespace gfx; +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_INHERITED(VRMockDisplay, DOMEventTargetHelper, + mVRServiceTest) + +NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(VRMockDisplay, + DOMEventTargetHelper) + +namespace { +template <class T> +bool ReadFloat32Array(T& aDestination, const Float32Array& aSource, + ErrorResult& aRv) { + constexpr size_t length = std::extent<T>::value; + aSource.ComputeState(); + if (aSource.Length() != length) { + aRv.Throw(NS_ERROR_INVALID_ARG); + // We don't want to MOZ_ASSERT here, as that would cause the + // browser to crash, making it difficult to debug the problem + // in JS code calling this API. + return false; + } + for (size_t i = 0; i < length; i++) { + aDestination[i] = aSource.Data()[i]; + } + return true; +} +}; // anonymous namespace + +VRMockDisplay::VRMockDisplay(VRServiceTest* aVRServiceTest) + : DOMEventTargetHelper(aVRServiceTest->GetOwner()), + mVRServiceTest(aVRServiceTest) {} + +JSObject* VRMockDisplay::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return VRMockDisplay_Binding::Wrap(aCx, this, aGivenProto); +} + +VRHMDSensorState& VRMockDisplay::SensorState() const { + return mVRServiceTest->SystemState().sensorState; +} + +VRDisplayState& VRMockDisplay::DisplayState() const { + return mVRServiceTest->SystemState().displayState; +} + +void VRMockDisplay::Clear() { + VRDisplayState& displayState = DisplayState(); + displayState.Clear(); + VRHMDSensorState& sensorState = SensorState(); + sensorState.Clear(); +} + +void VRMockDisplay::Create() { + Clear(); + VRDisplayState& state = DisplayState(); + + strncpy(state.displayName, "Puppet HMD", kVRDisplayNameMaxLen); + state.eightCC = GFX_VR_EIGHTCC('P', 'u', 'p', 'p', 'e', 't', ' ', ' '); + state.isConnected = true; + state.isMounted = false; + state.capabilityFlags = VRDisplayCapabilityFlags::Cap_None | + VRDisplayCapabilityFlags::Cap_Orientation | + VRDisplayCapabilityFlags::Cap_Position | + VRDisplayCapabilityFlags::Cap_External | + VRDisplayCapabilityFlags::Cap_Present | + VRDisplayCapabilityFlags::Cap_StageParameters | + VRDisplayCapabilityFlags::Cap_MountDetection | + VRDisplayCapabilityFlags::Cap_ImmersiveVR; + state.blendMode = VRDisplayBlendMode::Opaque; + + // 1836 x 2040 resolution is arbitrary and can be overridden. + // This default resolution was chosen to be within range of a + // typical VR eye buffer size. This value is derived by + // scaling a 1080x1200 per-eye panel resolution by the + // commonly used pre-lens-distortion pass scaling factor of 1.7x. + // 1.7x is commonly used in HMD's employing fresnel lenses to ensure + // a sufficient fragment shading rate in the peripheral area of the + // post-warp eye buffers. + state.eyeResolution.width = 1836; // 1080 * 1.7 + state.eyeResolution.height = 2040; // 1200 * 1.7 + + for (uint32_t eye = 0; eye < VRDisplayState::NumEyes; ++eye) { + state.eyeTranslation[eye].x = 0.0f; + state.eyeTranslation[eye].y = 0.0f; + state.eyeTranslation[eye].z = 0.0f; + state.eyeFOV[eye] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0); + } + + // default: 1m x 1m space, 0.75m high in seated position + state.stageSize.width = 1.0f; + state.stageSize.height = 1.0f; + + state.sittingToStandingTransform[0] = 1.0f; + state.sittingToStandingTransform[1] = 0.0f; + state.sittingToStandingTransform[2] = 0.0f; + state.sittingToStandingTransform[3] = 0.0f; + + state.sittingToStandingTransform[4] = 0.0f; + state.sittingToStandingTransform[5] = 1.0f; + state.sittingToStandingTransform[6] = 0.0f; + state.sittingToStandingTransform[7] = 0.0f; + + state.sittingToStandingTransform[8] = 0.0f; + state.sittingToStandingTransform[9] = 0.0f; + state.sittingToStandingTransform[10] = 1.0f; + state.sittingToStandingTransform[11] = 0.0f; + + state.sittingToStandingTransform[12] = 0.0f; + state.sittingToStandingTransform[13] = 0.75f; + state.sittingToStandingTransform[14] = 0.0f; + state.sittingToStandingTransform[15] = 1.0f; + + VRHMDSensorState& sensorState = SensorState(); + gfx::Quaternion rot; + sensorState.flags |= VRDisplayCapabilityFlags::Cap_Orientation; + sensorState.pose.orientation[0] = rot.x; + sensorState.pose.orientation[1] = rot.y; + sensorState.pose.orientation[2] = rot.z; + sensorState.pose.orientation[3] = rot.w; + sensorState.pose.angularVelocity[0] = 0.0f; + sensorState.pose.angularVelocity[1] = 0.0f; + sensorState.pose.angularVelocity[2] = 0.0f; + + sensorState.flags |= VRDisplayCapabilityFlags::Cap_Position; + sensorState.pose.position[0] = 0.0f; + sensorState.pose.position[1] = 0.0f; + sensorState.pose.position[2] = 0.0f; + sensorState.pose.linearVelocity[0] = 0.0f; + sensorState.pose.linearVelocity[1] = 0.0f; + sensorState.pose.linearVelocity[2] = 0.0f; +} + +void VRMockDisplay::SetConnected(bool aConnected) { + DisplayState().isConnected = aConnected; +} +bool VRMockDisplay::Connected() const { return DisplayState().isConnected; } + +void VRMockDisplay::SetMounted(bool aMounted) { + DisplayState().isMounted = aMounted; +} + +bool VRMockDisplay::Mounted() const { return DisplayState().isMounted; } + +void VRMockDisplay::SetCapFlag(VRDisplayCapabilityFlags aFlag, bool aEnabled) { + if (aEnabled) { + DisplayState().capabilityFlags |= aFlag; + } else { + DisplayState().capabilityFlags &= ~aFlag; + } +} +bool VRMockDisplay::GetCapFlag(VRDisplayCapabilityFlags aFlag) const { + return ((DisplayState().capabilityFlags & aFlag) != + VRDisplayCapabilityFlags::Cap_None); +} + +void VRMockDisplay::SetCapPosition(bool aEnabled) { + SetCapFlag(VRDisplayCapabilityFlags::Cap_Position, aEnabled); +} + +void VRMockDisplay::SetCapOrientation(bool aEnabled) { + SetCapFlag(VRDisplayCapabilityFlags::Cap_Orientation, aEnabled); +} + +void VRMockDisplay::SetCapPresent(bool aEnabled) { + SetCapFlag(VRDisplayCapabilityFlags::Cap_Present, aEnabled); +} + +void VRMockDisplay::SetCapExternal(bool aEnabled) { + SetCapFlag(VRDisplayCapabilityFlags::Cap_External, aEnabled); +} + +void VRMockDisplay::SetCapAngularAcceleration(bool aEnabled) { + SetCapFlag(VRDisplayCapabilityFlags::Cap_AngularAcceleration, aEnabled); +} + +void VRMockDisplay::SetCapLinearAcceleration(bool aEnabled) { + SetCapFlag(VRDisplayCapabilityFlags::Cap_LinearAcceleration, aEnabled); +} + +void VRMockDisplay::SetCapStageParameters(bool aEnabled) { + SetCapFlag(VRDisplayCapabilityFlags::Cap_StageParameters, aEnabled); +} + +void VRMockDisplay::SetCapMountDetection(bool aEnabled) { + SetCapFlag(VRDisplayCapabilityFlags::Cap_MountDetection, aEnabled); +} + +void VRMockDisplay::SetCapPositionEmulated(bool aEnabled) { + SetCapFlag(VRDisplayCapabilityFlags::Cap_PositionEmulated, aEnabled); +} + +void VRMockDisplay::SetEyeFOV(VREye aEye, double aUpDegree, double aRightDegree, + double aDownDegree, double aLeftDegree) { + gfx::VRDisplayState::Eye eye = aEye == VREye::Left + ? gfx::VRDisplayState::Eye_Left + : gfx::VRDisplayState::Eye_Right; + VRDisplayState& state = DisplayState(); + state.eyeFOV[eye] = + gfx::VRFieldOfView(aUpDegree, aRightDegree, aDownDegree, aLeftDegree); +} + +void VRMockDisplay::SetEyeOffset(VREye aEye, double aOffsetX, double aOffsetY, + double aOffsetZ) { + gfx::VRDisplayState::Eye eye = aEye == VREye::Left + ? gfx::VRDisplayState::Eye_Left + : gfx::VRDisplayState::Eye_Right; + VRDisplayState& state = DisplayState(); + state.eyeTranslation[eye].x = (float)aOffsetX; + state.eyeTranslation[eye].y = (float)aOffsetY; + state.eyeTranslation[eye].z = (float)aOffsetZ; +} + +bool VRMockDisplay::CapPosition() const { + return GetCapFlag(VRDisplayCapabilityFlags::Cap_Position); +} + +bool VRMockDisplay::CapOrientation() const { + return GetCapFlag(VRDisplayCapabilityFlags::Cap_Orientation); +} + +bool VRMockDisplay::CapPresent() const { + return GetCapFlag(VRDisplayCapabilityFlags::Cap_Present); +} + +bool VRMockDisplay::CapExternal() const { + return GetCapFlag(VRDisplayCapabilityFlags::Cap_External); +} + +bool VRMockDisplay::CapAngularAcceleration() const { + return GetCapFlag(VRDisplayCapabilityFlags::Cap_AngularAcceleration); +} + +bool VRMockDisplay::CapLinearAcceleration() const { + return GetCapFlag(VRDisplayCapabilityFlags::Cap_LinearAcceleration); +} + +bool VRMockDisplay::CapStageParameters() const { + return GetCapFlag(VRDisplayCapabilityFlags::Cap_StageParameters); +} + +bool VRMockDisplay::CapMountDetection() const { + return GetCapFlag(VRDisplayCapabilityFlags::Cap_MountDetection); +} + +bool VRMockDisplay::CapPositionEmulated() const { + return GetCapFlag(VRDisplayCapabilityFlags::Cap_PositionEmulated); +} + +void VRMockDisplay::SetEyeResolution(uint32_t aRenderWidth, + uint32_t aRenderHeight) { + DisplayState().eyeResolution.width = aRenderWidth; + DisplayState().eyeResolution.height = aRenderHeight; +} + +void VRMockDisplay::SetStageSize(double aWidth, double aHeight) { + VRDisplayState& displayState = DisplayState(); + displayState.stageSize.width = (float)aWidth; + displayState.stageSize.height = (float)aHeight; +} + +void VRMockDisplay::SetSittingToStandingTransform( + const Float32Array& aTransform, ErrorResult& aRv) { + Unused << ReadFloat32Array(DisplayState().sittingToStandingTransform, + aTransform, aRv); +} + +void VRMockDisplay::SetPose(const Nullable<Float32Array>& aPosition, + const Nullable<Float32Array>& aLinearVelocity, + const Nullable<Float32Array>& aLinearAcceleration, + const Nullable<Float32Array>& aOrientation, + const Nullable<Float32Array>& aAngularVelocity, + const Nullable<Float32Array>& aAngularAcceleration, + ErrorResult& aRv) { + VRHMDSensorState& sensorState = mVRServiceTest->SystemState().sensorState; + sensorState.Clear(); + sensorState.flags = VRDisplayCapabilityFlags::Cap_None; + // sensorState.timestamp will be set automatically during + // puppet script execution + + if (!aOrientation.IsNull()) { + if (!ReadFloat32Array(sensorState.pose.orientation, aOrientation.Value(), + aRv)) { + return; + } + sensorState.flags |= VRDisplayCapabilityFlags::Cap_Orientation; + } + if (!aAngularVelocity.IsNull()) { + if (!ReadFloat32Array(sensorState.pose.angularVelocity, + aAngularVelocity.Value(), aRv)) { + return; + } + sensorState.flags |= VRDisplayCapabilityFlags::Cap_AngularAcceleration; + } + if (!aAngularAcceleration.IsNull()) { + if (!ReadFloat32Array(sensorState.pose.angularAcceleration, + aAngularAcceleration.Value(), aRv)) { + return; + } + sensorState.flags |= VRDisplayCapabilityFlags::Cap_AngularAcceleration; + } + if (!aPosition.IsNull()) { + if (!ReadFloat32Array(sensorState.pose.position, aPosition.Value(), aRv)) { + return; + } + sensorState.flags |= VRDisplayCapabilityFlags::Cap_Position; + } + if (!aLinearVelocity.IsNull()) { + if (!ReadFloat32Array(sensorState.pose.linearVelocity, + aLinearVelocity.Value(), aRv)) { + return; + } + sensorState.flags |= VRDisplayCapabilityFlags::Cap_LinearAcceleration; + } + if (!aLinearAcceleration.IsNull()) { + if (!ReadFloat32Array(sensorState.pose.linearAcceleration, + aLinearAcceleration.Value(), aRv)) { + return; + } + sensorState.flags |= VRDisplayCapabilityFlags::Cap_LinearAcceleration; + } +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(VRMockController, DOMEventTargetHelper, + mVRServiceTest) + +NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(VRMockController, + DOMEventTargetHelper) + +VRMockController::VRMockController(VRServiceTest* aVRServiceTest, + uint32_t aControllerIdx) + : DOMEventTargetHelper(aVRServiceTest->GetOwner()), + mVRServiceTest(aVRServiceTest), + mControllerIdx(aControllerIdx) { + MOZ_ASSERT(aControllerIdx < kVRControllerMaxCount); +} + +JSObject* VRMockController::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return VRMockController_Binding::Wrap(aCx, this, aGivenProto); +} + +VRControllerState& VRMockController::ControllerState() const { + return mVRServiceTest->SystemState().controllerState[mControllerIdx]; +} + +void VRMockController::Create() { + // Initialize with a 6dof, left-handed gamepad with one haptic actuator + // Tests are expected to modify the controller before it is sent to the + // puppet. + Clear(); + VRControllerState& state = ControllerState(); + strncpy(state.controllerName, "Puppet Gamepad", kVRControllerNameMaxLen); + state.hand = GamepadHand::Left; + state.flags = GamepadCapabilityFlags::Cap_Position | + GamepadCapabilityFlags::Cap_Orientation; + state.numButtons = 1; + state.numHaptics = 1; + state.triggerValue[0] = 0.0f; +} + +void VRMockController::Clear() { + mVRServiceTest->ClearController(mControllerIdx); +} + +void VRMockController::SetCapFlag(GamepadCapabilityFlags aFlag, bool aEnabled) { + if (aEnabled) { + ControllerState().flags |= aFlag; + } else { + ControllerState().flags &= ~aFlag; + } +} +bool VRMockController::GetCapFlag(GamepadCapabilityFlags aFlag) const { + return (ControllerState().flags & aFlag) != GamepadCapabilityFlags::Cap_None; +} + +void VRMockController::SetHand(GamepadHand aHand) { + ControllerState().hand = aHand; +} + +GamepadHand VRMockController::Hand() const { return ControllerState().hand; } + +void VRMockController::SetCapPosition(bool aEnabled) { + SetCapFlag(GamepadCapabilityFlags::Cap_Position, aEnabled); +} + +bool VRMockController::CapPosition() const { + return GetCapFlag(GamepadCapabilityFlags::Cap_Position); +} + +void VRMockController::SetCapOrientation(bool aEnabled) { + SetCapFlag(GamepadCapabilityFlags::Cap_Orientation, aEnabled); +} + +bool VRMockController::CapOrientation() const { + return GetCapFlag(GamepadCapabilityFlags::Cap_Orientation); +} + +void VRMockController::SetCapAngularAcceleration(bool aEnabled) { + SetCapFlag(GamepadCapabilityFlags::Cap_AngularAcceleration, aEnabled); +} + +bool VRMockController::CapAngularAcceleration() const { + return GetCapFlag(GamepadCapabilityFlags::Cap_AngularAcceleration); +} + +void VRMockController::SetCapLinearAcceleration(bool aEnabled) { + SetCapFlag(GamepadCapabilityFlags::Cap_LinearAcceleration, aEnabled); +} + +bool VRMockController::CapLinearAcceleration() const { + return GetCapFlag(GamepadCapabilityFlags::Cap_LinearAcceleration); +} + +void VRMockController::SetAxisCount(uint32_t aCount) { + MOZ_ASSERT(aCount <= kVRControllerMaxAxis); + ControllerState().numAxes = aCount; +} + +uint32_t VRMockController::AxisCount() const { + return ControllerState().numAxes; +} + +void VRMockController::SetButtonCount(uint32_t aCount) { + MOZ_ASSERT(aCount <= kVRControllerMaxButtons); + ControllerState().numButtons = aCount; +} + +uint32_t VRMockController::ButtonCount() const { + return ControllerState().numButtons; +} + +void VRMockController::SetHapticCount(uint32_t aCount) { + ControllerState().numHaptics = aCount; +} + +uint32_t VRMockController::HapticCount() const { + return ControllerState().numHaptics; +} + +void VRMockController::SetButtonPressed(uint32_t aButtonIdx, bool aPressed) { + MOZ_ASSERT(aButtonIdx < kVRControllerMaxButtons); + if (aPressed) { + ControllerState().buttonPressed |= (1 << aButtonIdx); + } else { + ControllerState().buttonPressed &= ~(1 << aButtonIdx); + } +} + +void VRMockController::SetButtonTouched(uint32_t aButtonIdx, bool aTouched) { + MOZ_ASSERT(aButtonIdx < kVRControllerMaxButtons); + if (aTouched) { + ControllerState().buttonTouched |= (1 << aButtonIdx); + } else { + ControllerState().buttonTouched &= ~(1 << aButtonIdx); + } +} + +void VRMockController::SetButtonTrigger(uint32_t aButtonIdx, double aTrigger) { + MOZ_ASSERT(aButtonIdx < kVRControllerMaxButtons); + + ControllerState().triggerValue[aButtonIdx] = (float)aTrigger; +} + +void VRMockController::SetAxisValue(uint32_t aAxisIdx, double aValue) { + MOZ_ASSERT(aAxisIdx < kVRControllerMaxAxis); + ControllerState().axisValue[aAxisIdx] = (float)aValue; +} + +void VRMockController::SetPose( + const Nullable<Float32Array>& aPosition, + const Nullable<Float32Array>& aLinearVelocity, + const Nullable<Float32Array>& aLinearAcceleration, + const Nullable<Float32Array>& aOrientation, + const Nullable<Float32Array>& aAngularVelocity, + const Nullable<Float32Array>& aAngularAcceleration, ErrorResult& aRv) { + VRControllerState& controllerState = ControllerState(); + controllerState.flags = GamepadCapabilityFlags::Cap_None; + + if (!aOrientation.IsNull()) { + if (!ReadFloat32Array(controllerState.pose.orientation, + aOrientation.Value(), aRv)) { + return; + } + controllerState.flags |= GamepadCapabilityFlags::Cap_Orientation; + } + if (!aAngularVelocity.IsNull()) { + if (!ReadFloat32Array(controllerState.pose.angularVelocity, + aAngularVelocity.Value(), aRv)) { + return; + } + controllerState.flags |= GamepadCapabilityFlags::Cap_AngularAcceleration; + } + if (!aAngularAcceleration.IsNull()) { + if (!ReadFloat32Array(controllerState.pose.angularAcceleration, + aAngularAcceleration.Value(), aRv)) { + return; + } + controllerState.flags |= GamepadCapabilityFlags::Cap_AngularAcceleration; + } + if (!aPosition.IsNull()) { + if (!ReadFloat32Array(controllerState.pose.position, aPosition.Value(), + aRv)) { + return; + } + controllerState.flags |= GamepadCapabilityFlags::Cap_Position; + } + if (!aLinearVelocity.IsNull()) { + if (!ReadFloat32Array(controllerState.pose.linearVelocity, + aLinearVelocity.Value(), aRv)) { + return; + } + controllerState.flags |= GamepadCapabilityFlags::Cap_LinearAcceleration; + } + if (!aLinearAcceleration.IsNull()) { + if (!ReadFloat32Array(controllerState.pose.linearAcceleration, + aLinearAcceleration.Value(), aRv)) { + return; + } + controllerState.flags |= GamepadCapabilityFlags::Cap_LinearAcceleration; + } +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(VRServiceTest, DOMEventTargetHelper, + mDisplay, mControllers, mWindow) + +NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(VRServiceTest, + DOMEventTargetHelper) + +JSObject* VRServiceTest::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return VRServiceTest_Binding::Wrap(aCx, this, aGivenProto); +} + +// static +already_AddRefed<VRServiceTest> VRServiceTest::CreateTestService( + nsPIDOMWindowInner* aWindow) { + MOZ_ASSERT(aWindow); + RefPtr<VRServiceTest> service = new VRServiceTest(aWindow); + return service.forget(); +} + +VRServiceTest::VRServiceTest(nsPIDOMWindowInner* aWindow) + : mWindow(aWindow), mPendingState{}, mEncodedState{}, mShuttingDown(false) { + mDisplay = new VRMockDisplay(this); + for (int i = 0; i < kVRControllerMaxCount; i++) { + mControllers.AppendElement(new VRMockController(this, i)); + } + ClearAll(); +} + +gfx::VRSystemState& VRServiceTest::SystemState() { return mPendingState; } + +VRMockDisplay* VRServiceTest::GetVRDisplay() { return mDisplay; } + +VRMockController* VRServiceTest::GetVRController(uint32_t aControllerIdx, + ErrorResult& aRv) { + if (aControllerIdx >= kVRControllerMaxCount) { + aRv.Throw(NS_ERROR_INVALID_ARG); + return nullptr; + } + return mControllers[aControllerIdx]; +} + +void VRServiceTest::Shutdown() { + MOZ_ASSERT(!mShuttingDown); + mShuttingDown = true; + mWindow = nullptr; +} + +void VRServiceTest::AddCommand(uint64_t aCommand) { + EncodeData(); + mCommandBuffer.AppendElement(aCommand); +} + +void VRServiceTest::End() { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_End); +} + +void VRServiceTest::ClearAll() { + memset(&mPendingState, 0, sizeof(VRSystemState)); + memset(&mEncodedState, 0, sizeof(VRSystemState)); + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_ClearAll); +} + +void VRServiceTest::ClearController(uint32_t aControllerIdx) { + MOZ_ASSERT(aControllerIdx < kVRControllerMaxCount); + mPendingState.controllerState[aControllerIdx].Clear(); + mEncodedState.controllerState[aControllerIdx].Clear(); + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_ClearController | + (uint64_t)aControllerIdx); +} + +void VRServiceTest::Timeout(uint32_t aDuration) { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_Timeout | + (uint64_t)aDuration); +} + +void VRServiceTest::Wait(uint32_t aDuration) { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_Wait | (uint64_t)aDuration); +} + +void VRServiceTest::WaitHapticIntensity(uint32_t aControllerIdx, + uint32_t aHapticIdx, double aIntensity, + ErrorResult& aRv) { + if (aControllerIdx >= kVRControllerMaxCount) { + aRv.Throw(NS_ERROR_INVALID_ARG); + return; + } + if (aHapticIdx >= kVRHapticsMaxCount) { + aRv.Throw(NS_ERROR_INVALID_ARG); + return; + } + // convert to 16.16 fixed point. This must match conversion in + // VRPuppetCommandBuffer::RunCommand + uint64_t iIntensity = round((float)aIntensity * (1 << 16)); + if (iIntensity > 0xffffffff) { + iIntensity = 0xffffffff; + } + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_WaitHapticIntensity | + ((uint64_t)aControllerIdx << 40) | ((uint64_t)aHapticIdx << 32) | + iIntensity); +} + +void VRServiceTest::WaitSubmit() { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_WaitSubmit); +} + +void VRServiceTest::WaitPresentationStart() { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_WaitPresentationStart); +} +void VRServiceTest::WaitPresentationEnd() { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_WaitPresentationEnd); +} + +void VRServiceTest::EncodeData() { + VRPuppetCommandBuffer::EncodeStruct( + mCommandBuffer, (uint8_t*)&mPendingState.displayState, + (uint8_t*)&mEncodedState.displayState, sizeof(VRDisplayState), + VRPuppet_Command::VRPuppet_UpdateDisplay); + VRPuppetCommandBuffer::EncodeStruct( + mCommandBuffer, (uint8_t*)&mPendingState.sensorState, + (uint8_t*)&mEncodedState.sensorState, sizeof(VRHMDSensorState), + VRPuppet_Command::VRPuppet_UpdateSensor); + VRPuppetCommandBuffer::EncodeStruct( + mCommandBuffer, (uint8_t*)&mPendingState.controllerState, + (uint8_t*)&mEncodedState.controllerState, + sizeof(VRControllerState) * kVRControllerMaxCount, + VRPuppet_Command::VRPuppet_UpdateControllers); +} + +void VRServiceTest::CaptureFrame() { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_CaptureFrame); +} + +void VRServiceTest::AcknowledgeFrame() { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_AcknowledgeFrame); +} + +void VRServiceTest::RejectFrame() { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_RejectFrame); +} + +void VRServiceTest::StartTimer() { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_StartTimer); +} + +void VRServiceTest::StopTimer() { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_StopTimer); +} + +void VRServiceTest::Commit() { + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_Commit); +} + +already_AddRefed<Promise> VRServiceTest::Run(ErrorResult& aRv) { + if (mShuttingDown) { + return nullptr; + } + + AddCommand((uint64_t)VRPuppet_Command::VRPuppet_End); + + RefPtr<dom::Promise> runPuppetPromise = + Promise::Create(mWindow->AsGlobal(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + gfx::VRManagerChild* vm = gfx::VRManagerChild::Get(); + vm->RunPuppet(mCommandBuffer, runPuppetPromise, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + mCommandBuffer.Clear(); + + return runPuppetPromise.forget(); +} + +already_AddRefed<Promise> VRServiceTest::Reset(ErrorResult& aRv) { + if (mShuttingDown) { + return nullptr; + } + + RefPtr<dom::Promise> resetPuppetPromise = + Promise::Create(mWindow->AsGlobal(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + gfx::VRManagerChild* vm = gfx::VRManagerChild::Get(); + vm->ResetPuppet(resetPuppetPromise, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + memset(&mPendingState, 0, sizeof(VRSystemState)); + memset(&mEncodedState, 0, sizeof(VRSystemState)); + mCommandBuffer.Clear(); + + return resetPuppetPromise.forget(); +} + +} // namespace dom +} // namespace mozilla |