1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "mozilla/dom/VRServiceTest.h"
8 #include "mozilla/dom/VRServiceTestBinding.h"
9 #include "mozilla/dom/GamepadPoseState.h"
10 #include "mozilla/dom/Promise.h"
11 #include "VRManagerChild.h"
12 #include "VRPuppetCommandBuffer.h"
13 #include <type_traits>
14
15 namespace mozilla {
16 using namespace gfx;
17 namespace dom {
18
19 NS_IMPL_CYCLE_COLLECTION_INHERITED(VRMockDisplay, DOMEventTargetHelper,
20 mVRServiceTest)
21
22 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(VRMockDisplay,
23 DOMEventTargetHelper)
24
25 namespace {
26 template <class T>
ReadFloat32Array(T & aDestination,const Float32Array & aSource,ErrorResult & aRv)27 bool ReadFloat32Array(T& aDestination, const Float32Array& aSource,
28 ErrorResult& aRv) {
29 constexpr size_t length = std::extent<T>::value;
30 aSource.ComputeState();
31 if (aSource.Length() != length) {
32 aRv.Throw(NS_ERROR_INVALID_ARG);
33 // We don't want to MOZ_ASSERT here, as that would cause the
34 // browser to crash, making it difficult to debug the problem
35 // in JS code calling this API.
36 return false;
37 }
38 for (size_t i = 0; i < length; i++) {
39 aDestination[i] = aSource.Data()[i];
40 }
41 return true;
42 }
43 }; // anonymous namespace
44
VRMockDisplay(VRServiceTest * aVRServiceTest)45 VRMockDisplay::VRMockDisplay(VRServiceTest* aVRServiceTest)
46 : DOMEventTargetHelper(aVRServiceTest->GetOwner()),
47 mVRServiceTest(aVRServiceTest) {}
48
WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)49 JSObject* VRMockDisplay::WrapObject(JSContext* aCx,
50 JS::Handle<JSObject*> aGivenProto) {
51 return VRMockDisplay_Binding::Wrap(aCx, this, aGivenProto);
52 }
53
SensorState() const54 VRHMDSensorState& VRMockDisplay::SensorState() const {
55 return mVRServiceTest->SystemState().sensorState;
56 }
57
DisplayState() const58 VRDisplayState& VRMockDisplay::DisplayState() const {
59 return mVRServiceTest->SystemState().displayState;
60 }
61
Clear()62 void VRMockDisplay::Clear() {
63 VRDisplayState& displayState = DisplayState();
64 displayState.Clear();
65 VRHMDSensorState& sensorState = SensorState();
66 sensorState.Clear();
67 }
68
Create()69 void VRMockDisplay::Create() {
70 Clear();
71 VRDisplayState& state = DisplayState();
72
73 strncpy(state.displayName, "Puppet HMD", kVRDisplayNameMaxLen);
74 state.eightCC = GFX_VR_EIGHTCC('P', 'u', 'p', 'p', 'e', 't', ' ', ' ');
75 state.isConnected = true;
76 state.isMounted = false;
77 state.capabilityFlags = VRDisplayCapabilityFlags::Cap_None |
78 VRDisplayCapabilityFlags::Cap_Orientation |
79 VRDisplayCapabilityFlags::Cap_Position |
80 VRDisplayCapabilityFlags::Cap_External |
81 VRDisplayCapabilityFlags::Cap_Present |
82 VRDisplayCapabilityFlags::Cap_StageParameters |
83 VRDisplayCapabilityFlags::Cap_MountDetection |
84 VRDisplayCapabilityFlags::Cap_ImmersiveVR;
85 state.blendMode = VRDisplayBlendMode::Opaque;
86
87 // 1836 x 2040 resolution is arbitrary and can be overridden.
88 // This default resolution was chosen to be within range of a
89 // typical VR eye buffer size. This value is derived by
90 // scaling a 1080x1200 per-eye panel resolution by the
91 // commonly used pre-lens-distortion pass scaling factor of 1.7x.
92 // 1.7x is commonly used in HMD's employing fresnel lenses to ensure
93 // a sufficient fragment shading rate in the peripheral area of the
94 // post-warp eye buffers.
95 state.eyeResolution.width = 1836; // 1080 * 1.7
96 state.eyeResolution.height = 2040; // 1200 * 1.7
97
98 for (uint32_t eye = 0; eye < VRDisplayState::NumEyes; ++eye) {
99 state.eyeTranslation[eye].x = 0.0f;
100 state.eyeTranslation[eye].y = 0.0f;
101 state.eyeTranslation[eye].z = 0.0f;
102 state.eyeFOV[eye] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0);
103 }
104
105 // default: 1m x 1m space, 0.75m high in seated position
106 state.stageSize.width = 1.0f;
107 state.stageSize.height = 1.0f;
108
109 state.sittingToStandingTransform[0] = 1.0f;
110 state.sittingToStandingTransform[1] = 0.0f;
111 state.sittingToStandingTransform[2] = 0.0f;
112 state.sittingToStandingTransform[3] = 0.0f;
113
114 state.sittingToStandingTransform[4] = 0.0f;
115 state.sittingToStandingTransform[5] = 1.0f;
116 state.sittingToStandingTransform[6] = 0.0f;
117 state.sittingToStandingTransform[7] = 0.0f;
118
119 state.sittingToStandingTransform[8] = 0.0f;
120 state.sittingToStandingTransform[9] = 0.0f;
121 state.sittingToStandingTransform[10] = 1.0f;
122 state.sittingToStandingTransform[11] = 0.0f;
123
124 state.sittingToStandingTransform[12] = 0.0f;
125 state.sittingToStandingTransform[13] = 0.75f;
126 state.sittingToStandingTransform[14] = 0.0f;
127 state.sittingToStandingTransform[15] = 1.0f;
128
129 VRHMDSensorState& sensorState = SensorState();
130 gfx::Quaternion rot;
131 sensorState.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
132 sensorState.pose.orientation[0] = rot.x;
133 sensorState.pose.orientation[1] = rot.y;
134 sensorState.pose.orientation[2] = rot.z;
135 sensorState.pose.orientation[3] = rot.w;
136 sensorState.pose.angularVelocity[0] = 0.0f;
137 sensorState.pose.angularVelocity[1] = 0.0f;
138 sensorState.pose.angularVelocity[2] = 0.0f;
139
140 sensorState.flags |= VRDisplayCapabilityFlags::Cap_Position;
141 sensorState.pose.position[0] = 0.0f;
142 sensorState.pose.position[1] = 0.0f;
143 sensorState.pose.position[2] = 0.0f;
144 sensorState.pose.linearVelocity[0] = 0.0f;
145 sensorState.pose.linearVelocity[1] = 0.0f;
146 sensorState.pose.linearVelocity[2] = 0.0f;
147 }
148
SetConnected(bool aConnected)149 void VRMockDisplay::SetConnected(bool aConnected) {
150 DisplayState().isConnected = aConnected;
151 }
Connected() const152 bool VRMockDisplay::Connected() const { return DisplayState().isConnected; }
153
SetMounted(bool aMounted)154 void VRMockDisplay::SetMounted(bool aMounted) {
155 DisplayState().isMounted = aMounted;
156 }
157
Mounted() const158 bool VRMockDisplay::Mounted() const { return DisplayState().isMounted; }
159
SetCapFlag(VRDisplayCapabilityFlags aFlag,bool aEnabled)160 void VRMockDisplay::SetCapFlag(VRDisplayCapabilityFlags aFlag, bool aEnabled) {
161 if (aEnabled) {
162 DisplayState().capabilityFlags |= aFlag;
163 } else {
164 DisplayState().capabilityFlags &= ~aFlag;
165 }
166 }
GetCapFlag(VRDisplayCapabilityFlags aFlag) const167 bool VRMockDisplay::GetCapFlag(VRDisplayCapabilityFlags aFlag) const {
168 return ((DisplayState().capabilityFlags & aFlag) !=
169 VRDisplayCapabilityFlags::Cap_None);
170 }
171
SetCapPosition(bool aEnabled)172 void VRMockDisplay::SetCapPosition(bool aEnabled) {
173 SetCapFlag(VRDisplayCapabilityFlags::Cap_Position, aEnabled);
174 }
175
SetCapOrientation(bool aEnabled)176 void VRMockDisplay::SetCapOrientation(bool aEnabled) {
177 SetCapFlag(VRDisplayCapabilityFlags::Cap_Orientation, aEnabled);
178 }
179
SetCapPresent(bool aEnabled)180 void VRMockDisplay::SetCapPresent(bool aEnabled) {
181 SetCapFlag(VRDisplayCapabilityFlags::Cap_Present, aEnabled);
182 }
183
SetCapExternal(bool aEnabled)184 void VRMockDisplay::SetCapExternal(bool aEnabled) {
185 SetCapFlag(VRDisplayCapabilityFlags::Cap_External, aEnabled);
186 }
187
SetCapAngularAcceleration(bool aEnabled)188 void VRMockDisplay::SetCapAngularAcceleration(bool aEnabled) {
189 SetCapFlag(VRDisplayCapabilityFlags::Cap_AngularAcceleration, aEnabled);
190 }
191
SetCapLinearAcceleration(bool aEnabled)192 void VRMockDisplay::SetCapLinearAcceleration(bool aEnabled) {
193 SetCapFlag(VRDisplayCapabilityFlags::Cap_LinearAcceleration, aEnabled);
194 }
195
SetCapStageParameters(bool aEnabled)196 void VRMockDisplay::SetCapStageParameters(bool aEnabled) {
197 SetCapFlag(VRDisplayCapabilityFlags::Cap_StageParameters, aEnabled);
198 }
199
SetCapMountDetection(bool aEnabled)200 void VRMockDisplay::SetCapMountDetection(bool aEnabled) {
201 SetCapFlag(VRDisplayCapabilityFlags::Cap_MountDetection, aEnabled);
202 }
203
SetCapPositionEmulated(bool aEnabled)204 void VRMockDisplay::SetCapPositionEmulated(bool aEnabled) {
205 SetCapFlag(VRDisplayCapabilityFlags::Cap_PositionEmulated, aEnabled);
206 }
207
SetEyeFOV(VREye aEye,double aUpDegree,double aRightDegree,double aDownDegree,double aLeftDegree)208 void VRMockDisplay::SetEyeFOV(VREye aEye, double aUpDegree, double aRightDegree,
209 double aDownDegree, double aLeftDegree) {
210 gfx::VRDisplayState::Eye eye = aEye == VREye::Left
211 ? gfx::VRDisplayState::Eye_Left
212 : gfx::VRDisplayState::Eye_Right;
213 VRDisplayState& state = DisplayState();
214 state.eyeFOV[eye] =
215 gfx::VRFieldOfView(aUpDegree, aRightDegree, aDownDegree, aLeftDegree);
216 }
217
SetEyeOffset(VREye aEye,double aOffsetX,double aOffsetY,double aOffsetZ)218 void VRMockDisplay::SetEyeOffset(VREye aEye, double aOffsetX, double aOffsetY,
219 double aOffsetZ) {
220 gfx::VRDisplayState::Eye eye = aEye == VREye::Left
221 ? gfx::VRDisplayState::Eye_Left
222 : gfx::VRDisplayState::Eye_Right;
223 VRDisplayState& state = DisplayState();
224 state.eyeTranslation[eye].x = (float)aOffsetX;
225 state.eyeTranslation[eye].y = (float)aOffsetY;
226 state.eyeTranslation[eye].z = (float)aOffsetZ;
227 }
228
CapPosition() const229 bool VRMockDisplay::CapPosition() const {
230 return GetCapFlag(VRDisplayCapabilityFlags::Cap_Position);
231 }
232
CapOrientation() const233 bool VRMockDisplay::CapOrientation() const {
234 return GetCapFlag(VRDisplayCapabilityFlags::Cap_Orientation);
235 }
236
CapPresent() const237 bool VRMockDisplay::CapPresent() const {
238 return GetCapFlag(VRDisplayCapabilityFlags::Cap_Present);
239 }
240
CapExternal() const241 bool VRMockDisplay::CapExternal() const {
242 return GetCapFlag(VRDisplayCapabilityFlags::Cap_External);
243 }
244
CapAngularAcceleration() const245 bool VRMockDisplay::CapAngularAcceleration() const {
246 return GetCapFlag(VRDisplayCapabilityFlags::Cap_AngularAcceleration);
247 }
248
CapLinearAcceleration() const249 bool VRMockDisplay::CapLinearAcceleration() const {
250 return GetCapFlag(VRDisplayCapabilityFlags::Cap_LinearAcceleration);
251 }
252
CapStageParameters() const253 bool VRMockDisplay::CapStageParameters() const {
254 return GetCapFlag(VRDisplayCapabilityFlags::Cap_StageParameters);
255 }
256
CapMountDetection() const257 bool VRMockDisplay::CapMountDetection() const {
258 return GetCapFlag(VRDisplayCapabilityFlags::Cap_MountDetection);
259 }
260
CapPositionEmulated() const261 bool VRMockDisplay::CapPositionEmulated() const {
262 return GetCapFlag(VRDisplayCapabilityFlags::Cap_PositionEmulated);
263 }
264
SetEyeResolution(uint32_t aRenderWidth,uint32_t aRenderHeight)265 void VRMockDisplay::SetEyeResolution(uint32_t aRenderWidth,
266 uint32_t aRenderHeight) {
267 DisplayState().eyeResolution.width = aRenderWidth;
268 DisplayState().eyeResolution.height = aRenderHeight;
269 }
270
SetStageSize(double aWidth,double aHeight)271 void VRMockDisplay::SetStageSize(double aWidth, double aHeight) {
272 VRDisplayState& displayState = DisplayState();
273 displayState.stageSize.width = (float)aWidth;
274 displayState.stageSize.height = (float)aHeight;
275 }
276
SetSittingToStandingTransform(const Float32Array & aTransform,ErrorResult & aRv)277 void VRMockDisplay::SetSittingToStandingTransform(
278 const Float32Array& aTransform, ErrorResult& aRv) {
279 Unused << ReadFloat32Array(DisplayState().sittingToStandingTransform,
280 aTransform, aRv);
281 }
282
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)283 void VRMockDisplay::SetPose(const Nullable<Float32Array>& aPosition,
284 const Nullable<Float32Array>& aLinearVelocity,
285 const Nullable<Float32Array>& aLinearAcceleration,
286 const Nullable<Float32Array>& aOrientation,
287 const Nullable<Float32Array>& aAngularVelocity,
288 const Nullable<Float32Array>& aAngularAcceleration,
289 ErrorResult& aRv) {
290 VRHMDSensorState& sensorState = mVRServiceTest->SystemState().sensorState;
291 sensorState.Clear();
292 sensorState.flags = VRDisplayCapabilityFlags::Cap_None;
293 // sensorState.timestamp will be set automatically during
294 // puppet script execution
295
296 if (!aOrientation.IsNull()) {
297 if (!ReadFloat32Array(sensorState.pose.orientation, aOrientation.Value(),
298 aRv)) {
299 return;
300 }
301 sensorState.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
302 }
303 if (!aAngularVelocity.IsNull()) {
304 if (!ReadFloat32Array(sensorState.pose.angularVelocity,
305 aAngularVelocity.Value(), aRv)) {
306 return;
307 }
308 sensorState.flags |= VRDisplayCapabilityFlags::Cap_AngularAcceleration;
309 }
310 if (!aAngularAcceleration.IsNull()) {
311 if (!ReadFloat32Array(sensorState.pose.angularAcceleration,
312 aAngularAcceleration.Value(), aRv)) {
313 return;
314 }
315 sensorState.flags |= VRDisplayCapabilityFlags::Cap_AngularAcceleration;
316 }
317 if (!aPosition.IsNull()) {
318 if (!ReadFloat32Array(sensorState.pose.position, aPosition.Value(), aRv)) {
319 return;
320 }
321 sensorState.flags |= VRDisplayCapabilityFlags::Cap_Position;
322 }
323 if (!aLinearVelocity.IsNull()) {
324 if (!ReadFloat32Array(sensorState.pose.linearVelocity,
325 aLinearVelocity.Value(), aRv)) {
326 return;
327 }
328 sensorState.flags |= VRDisplayCapabilityFlags::Cap_LinearAcceleration;
329 }
330 if (!aLinearAcceleration.IsNull()) {
331 if (!ReadFloat32Array(sensorState.pose.linearAcceleration,
332 aLinearAcceleration.Value(), aRv)) {
333 return;
334 }
335 sensorState.flags |= VRDisplayCapabilityFlags::Cap_LinearAcceleration;
336 }
337 }
338
NS_IMPL_CYCLE_COLLECTION_INHERITED(VRMockController,DOMEventTargetHelper,mVRServiceTest)339 NS_IMPL_CYCLE_COLLECTION_INHERITED(VRMockController, DOMEventTargetHelper,
340 mVRServiceTest)
341
342 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(VRMockController,
343 DOMEventTargetHelper)
344
345 VRMockController::VRMockController(VRServiceTest* aVRServiceTest,
346 uint32_t aControllerIdx)
347 : DOMEventTargetHelper(aVRServiceTest->GetOwner()),
348 mVRServiceTest(aVRServiceTest),
349 mControllerIdx(aControllerIdx) {
350 MOZ_ASSERT(aControllerIdx < kVRControllerMaxCount);
351 }
352
WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)353 JSObject* VRMockController::WrapObject(JSContext* aCx,
354 JS::Handle<JSObject*> aGivenProto) {
355 return VRMockController_Binding::Wrap(aCx, this, aGivenProto);
356 }
357
ControllerState() const358 VRControllerState& VRMockController::ControllerState() const {
359 return mVRServiceTest->SystemState().controllerState[mControllerIdx];
360 }
361
Create()362 void VRMockController::Create() {
363 // Initialize with a 6dof, left-handed gamepad with one haptic actuator
364 // Tests are expected to modify the controller before it is sent to the
365 // puppet.
366 Clear();
367 VRControllerState& state = ControllerState();
368 strncpy(state.controllerName, "Puppet Gamepad", kVRControllerNameMaxLen);
369 state.hand = GamepadHand::Left;
370 state.flags = GamepadCapabilityFlags::Cap_Position |
371 GamepadCapabilityFlags::Cap_Orientation;
372 state.numButtons = 1;
373 state.numHaptics = 1;
374 state.triggerValue[0] = 0.0f;
375 }
376
Clear()377 void VRMockController::Clear() {
378 mVRServiceTest->ClearController(mControllerIdx);
379 }
380
SetCapFlag(GamepadCapabilityFlags aFlag,bool aEnabled)381 void VRMockController::SetCapFlag(GamepadCapabilityFlags aFlag, bool aEnabled) {
382 if (aEnabled) {
383 ControllerState().flags |= aFlag;
384 } else {
385 ControllerState().flags &= ~aFlag;
386 }
387 }
GetCapFlag(GamepadCapabilityFlags aFlag) const388 bool VRMockController::GetCapFlag(GamepadCapabilityFlags aFlag) const {
389 return (ControllerState().flags & aFlag) != GamepadCapabilityFlags::Cap_None;
390 }
391
SetHand(GamepadHand aHand)392 void VRMockController::SetHand(GamepadHand aHand) {
393 ControllerState().hand = aHand;
394 }
395
Hand() const396 GamepadHand VRMockController::Hand() const { return ControllerState().hand; }
397
SetCapPosition(bool aEnabled)398 void VRMockController::SetCapPosition(bool aEnabled) {
399 SetCapFlag(GamepadCapabilityFlags::Cap_Position, aEnabled);
400 }
401
CapPosition() const402 bool VRMockController::CapPosition() const {
403 return GetCapFlag(GamepadCapabilityFlags::Cap_Position);
404 }
405
SetCapOrientation(bool aEnabled)406 void VRMockController::SetCapOrientation(bool aEnabled) {
407 SetCapFlag(GamepadCapabilityFlags::Cap_Orientation, aEnabled);
408 }
409
CapOrientation() const410 bool VRMockController::CapOrientation() const {
411 return GetCapFlag(GamepadCapabilityFlags::Cap_Orientation);
412 }
413
SetCapAngularAcceleration(bool aEnabled)414 void VRMockController::SetCapAngularAcceleration(bool aEnabled) {
415 SetCapFlag(GamepadCapabilityFlags::Cap_AngularAcceleration, aEnabled);
416 }
417
CapAngularAcceleration() const418 bool VRMockController::CapAngularAcceleration() const {
419 return GetCapFlag(GamepadCapabilityFlags::Cap_AngularAcceleration);
420 }
421
SetCapLinearAcceleration(bool aEnabled)422 void VRMockController::SetCapLinearAcceleration(bool aEnabled) {
423 SetCapFlag(GamepadCapabilityFlags::Cap_LinearAcceleration, aEnabled);
424 }
425
CapLinearAcceleration() const426 bool VRMockController::CapLinearAcceleration() const {
427 return GetCapFlag(GamepadCapabilityFlags::Cap_LinearAcceleration);
428 }
429
SetAxisCount(uint32_t aCount)430 void VRMockController::SetAxisCount(uint32_t aCount) {
431 MOZ_ASSERT(aCount <= kVRControllerMaxAxis);
432 ControllerState().numAxes = aCount;
433 }
434
AxisCount() const435 uint32_t VRMockController::AxisCount() const {
436 return ControllerState().numAxes;
437 }
438
SetButtonCount(uint32_t aCount)439 void VRMockController::SetButtonCount(uint32_t aCount) {
440 MOZ_ASSERT(aCount <= kVRControllerMaxButtons);
441 ControllerState().numButtons = aCount;
442 }
443
ButtonCount() const444 uint32_t VRMockController::ButtonCount() const {
445 return ControllerState().numButtons;
446 }
447
SetHapticCount(uint32_t aCount)448 void VRMockController::SetHapticCount(uint32_t aCount) {
449 ControllerState().numHaptics = aCount;
450 }
451
HapticCount() const452 uint32_t VRMockController::HapticCount() const {
453 return ControllerState().numHaptics;
454 }
455
SetButtonPressed(uint32_t aButtonIdx,bool aPressed)456 void VRMockController::SetButtonPressed(uint32_t aButtonIdx, bool aPressed) {
457 MOZ_ASSERT(aButtonIdx < kVRControllerMaxButtons);
458 if (aPressed) {
459 ControllerState().buttonPressed |= (1 << aButtonIdx);
460 } else {
461 ControllerState().buttonPressed &= ~(1 << aButtonIdx);
462 }
463 }
464
SetButtonTouched(uint32_t aButtonIdx,bool aTouched)465 void VRMockController::SetButtonTouched(uint32_t aButtonIdx, bool aTouched) {
466 MOZ_ASSERT(aButtonIdx < kVRControllerMaxButtons);
467 if (aTouched) {
468 ControllerState().buttonTouched |= (1 << aButtonIdx);
469 } else {
470 ControllerState().buttonTouched &= ~(1 << aButtonIdx);
471 }
472 }
473
SetButtonTrigger(uint32_t aButtonIdx,double aTrigger)474 void VRMockController::SetButtonTrigger(uint32_t aButtonIdx, double aTrigger) {
475 MOZ_ASSERT(aButtonIdx < kVRControllerMaxButtons);
476
477 ControllerState().triggerValue[aButtonIdx] = (float)aTrigger;
478 }
479
SetAxisValue(uint32_t aAxisIdx,double aValue)480 void VRMockController::SetAxisValue(uint32_t aAxisIdx, double aValue) {
481 MOZ_ASSERT(aAxisIdx < kVRControllerMaxAxis);
482 ControllerState().axisValue[aAxisIdx] = (float)aValue;
483 }
484
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)485 void VRMockController::SetPose(
486 const Nullable<Float32Array>& aPosition,
487 const Nullable<Float32Array>& aLinearVelocity,
488 const Nullable<Float32Array>& aLinearAcceleration,
489 const Nullable<Float32Array>& aOrientation,
490 const Nullable<Float32Array>& aAngularVelocity,
491 const Nullable<Float32Array>& aAngularAcceleration, ErrorResult& aRv) {
492 VRControllerState& controllerState = ControllerState();
493 controllerState.flags = GamepadCapabilityFlags::Cap_None;
494
495 if (!aOrientation.IsNull()) {
496 if (!ReadFloat32Array(controllerState.pose.orientation,
497 aOrientation.Value(), aRv)) {
498 return;
499 }
500 controllerState.flags |= GamepadCapabilityFlags::Cap_Orientation;
501 }
502 if (!aAngularVelocity.IsNull()) {
503 if (!ReadFloat32Array(controllerState.pose.angularVelocity,
504 aAngularVelocity.Value(), aRv)) {
505 return;
506 }
507 controllerState.flags |= GamepadCapabilityFlags::Cap_AngularAcceleration;
508 }
509 if (!aAngularAcceleration.IsNull()) {
510 if (!ReadFloat32Array(controllerState.pose.angularAcceleration,
511 aAngularAcceleration.Value(), aRv)) {
512 return;
513 }
514 controllerState.flags |= GamepadCapabilityFlags::Cap_AngularAcceleration;
515 }
516 if (!aPosition.IsNull()) {
517 if (!ReadFloat32Array(controllerState.pose.position, aPosition.Value(),
518 aRv)) {
519 return;
520 }
521 controllerState.flags |= GamepadCapabilityFlags::Cap_Position;
522 }
523 if (!aLinearVelocity.IsNull()) {
524 if (!ReadFloat32Array(controllerState.pose.linearVelocity,
525 aLinearVelocity.Value(), aRv)) {
526 return;
527 }
528 controllerState.flags |= GamepadCapabilityFlags::Cap_LinearAcceleration;
529 }
530 if (!aLinearAcceleration.IsNull()) {
531 if (!ReadFloat32Array(controllerState.pose.linearAcceleration,
532 aLinearAcceleration.Value(), aRv)) {
533 return;
534 }
535 controllerState.flags |= GamepadCapabilityFlags::Cap_LinearAcceleration;
536 }
537 }
538
NS_IMPL_CYCLE_COLLECTION_INHERITED(VRServiceTest,DOMEventTargetHelper,mDisplay,mControllers,mWindow)539 NS_IMPL_CYCLE_COLLECTION_INHERITED(VRServiceTest, DOMEventTargetHelper,
540 mDisplay, mControllers, mWindow)
541
542 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(VRServiceTest,
543 DOMEventTargetHelper)
544
545 JSObject* VRServiceTest::WrapObject(JSContext* aCx,
546 JS::Handle<JSObject*> aGivenProto) {
547 return VRServiceTest_Binding::Wrap(aCx, this, aGivenProto);
548 }
549
550 // static
CreateTestService(nsPIDOMWindowInner * aWindow)551 already_AddRefed<VRServiceTest> VRServiceTest::CreateTestService(
552 nsPIDOMWindowInner* aWindow) {
553 MOZ_ASSERT(aWindow);
554 RefPtr<VRServiceTest> service = new VRServiceTest(aWindow);
555 return service.forget();
556 }
557
VRServiceTest(nsPIDOMWindowInner * aWindow)558 VRServiceTest::VRServiceTest(nsPIDOMWindowInner* aWindow)
559 : mWindow(aWindow), mPendingState{}, mEncodedState{}, mShuttingDown(false) {
560 mDisplay = new VRMockDisplay(this);
561 for (int i = 0; i < kVRControllerMaxCount; i++) {
562 mControllers.AppendElement(new VRMockController(this, i));
563 }
564 ClearAll();
565 }
566
SystemState()567 gfx::VRSystemState& VRServiceTest::SystemState() { return mPendingState; }
568
GetVRDisplay()569 VRMockDisplay* VRServiceTest::GetVRDisplay() { return mDisplay; }
570
GetVRController(uint32_t aControllerIdx,ErrorResult & aRv)571 VRMockController* VRServiceTest::GetVRController(uint32_t aControllerIdx,
572 ErrorResult& aRv) {
573 if (aControllerIdx >= kVRControllerMaxCount) {
574 aRv.Throw(NS_ERROR_INVALID_ARG);
575 return nullptr;
576 }
577 return mControllers[aControllerIdx];
578 }
579
Shutdown()580 void VRServiceTest::Shutdown() {
581 MOZ_ASSERT(!mShuttingDown);
582 mShuttingDown = true;
583 mWindow = nullptr;
584 }
585
AddCommand(uint64_t aCommand)586 void VRServiceTest::AddCommand(uint64_t aCommand) {
587 EncodeData();
588 mCommandBuffer.AppendElement(aCommand);
589 }
590
End()591 void VRServiceTest::End() {
592 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_End);
593 }
594
ClearAll()595 void VRServiceTest::ClearAll() {
596 memset(&mPendingState, 0, sizeof(VRSystemState));
597 memset(&mEncodedState, 0, sizeof(VRSystemState));
598 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_ClearAll);
599 }
600
ClearController(uint32_t aControllerIdx)601 void VRServiceTest::ClearController(uint32_t aControllerIdx) {
602 MOZ_ASSERT(aControllerIdx < kVRControllerMaxCount);
603 mPendingState.controllerState[aControllerIdx].Clear();
604 mEncodedState.controllerState[aControllerIdx].Clear();
605 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_ClearController |
606 (uint64_t)aControllerIdx);
607 }
608
Timeout(uint32_t aDuration)609 void VRServiceTest::Timeout(uint32_t aDuration) {
610 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_Timeout |
611 (uint64_t)aDuration);
612 }
613
Wait(uint32_t aDuration)614 void VRServiceTest::Wait(uint32_t aDuration) {
615 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_Wait | (uint64_t)aDuration);
616 }
617
WaitHapticIntensity(uint32_t aControllerIdx,uint32_t aHapticIdx,double aIntensity,ErrorResult & aRv)618 void VRServiceTest::WaitHapticIntensity(uint32_t aControllerIdx,
619 uint32_t aHapticIdx, double aIntensity,
620 ErrorResult& aRv) {
621 if (aControllerIdx >= kVRControllerMaxCount) {
622 aRv.Throw(NS_ERROR_INVALID_ARG);
623 return;
624 }
625 if (aHapticIdx >= kVRHapticsMaxCount) {
626 aRv.Throw(NS_ERROR_INVALID_ARG);
627 return;
628 }
629 // convert to 16.16 fixed point. This must match conversion in
630 // VRPuppetCommandBuffer::RunCommand
631 uint64_t iIntensity = round((float)aIntensity * (1 << 16));
632 if (iIntensity > 0xffffffff) {
633 iIntensity = 0xffffffff;
634 }
635 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_WaitHapticIntensity |
636 ((uint64_t)aControllerIdx << 40) | ((uint64_t)aHapticIdx << 32) |
637 iIntensity);
638 }
639
WaitSubmit()640 void VRServiceTest::WaitSubmit() {
641 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_WaitSubmit);
642 }
643
WaitPresentationStart()644 void VRServiceTest::WaitPresentationStart() {
645 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_WaitPresentationStart);
646 }
WaitPresentationEnd()647 void VRServiceTest::WaitPresentationEnd() {
648 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_WaitPresentationEnd);
649 }
650
EncodeData()651 void VRServiceTest::EncodeData() {
652 VRPuppetCommandBuffer::EncodeStruct(
653 mCommandBuffer, (uint8_t*)&mPendingState.displayState,
654 (uint8_t*)&mEncodedState.displayState, sizeof(VRDisplayState),
655 VRPuppet_Command::VRPuppet_UpdateDisplay);
656 VRPuppetCommandBuffer::EncodeStruct(
657 mCommandBuffer, (uint8_t*)&mPendingState.sensorState,
658 (uint8_t*)&mEncodedState.sensorState, sizeof(VRHMDSensorState),
659 VRPuppet_Command::VRPuppet_UpdateSensor);
660 VRPuppetCommandBuffer::EncodeStruct(
661 mCommandBuffer, (uint8_t*)&mPendingState.controllerState,
662 (uint8_t*)&mEncodedState.controllerState,
663 sizeof(VRControllerState) * kVRControllerMaxCount,
664 VRPuppet_Command::VRPuppet_UpdateControllers);
665 }
666
CaptureFrame()667 void VRServiceTest::CaptureFrame() {
668 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_CaptureFrame);
669 }
670
AcknowledgeFrame()671 void VRServiceTest::AcknowledgeFrame() {
672 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_AcknowledgeFrame);
673 }
674
RejectFrame()675 void VRServiceTest::RejectFrame() {
676 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_RejectFrame);
677 }
678
StartTimer()679 void VRServiceTest::StartTimer() {
680 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_StartTimer);
681 }
682
StopTimer()683 void VRServiceTest::StopTimer() {
684 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_StopTimer);
685 }
686
Commit()687 void VRServiceTest::Commit() {
688 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_Commit);
689 }
690
Run(ErrorResult & aRv)691 already_AddRefed<Promise> VRServiceTest::Run(ErrorResult& aRv) {
692 if (mShuttingDown) {
693 return nullptr;
694 }
695
696 AddCommand((uint64_t)VRPuppet_Command::VRPuppet_End);
697
698 RefPtr<dom::Promise> runPuppetPromise =
699 Promise::Create(mWindow->AsGlobal(), aRv);
700 if (NS_WARN_IF(aRv.Failed())) {
701 return nullptr;
702 }
703
704 gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
705 vm->RunPuppet(mCommandBuffer, runPuppetPromise, aRv);
706 if (NS_WARN_IF(aRv.Failed())) {
707 return nullptr;
708 }
709
710 mCommandBuffer.Clear();
711
712 return runPuppetPromise.forget();
713 }
714
Reset(ErrorResult & aRv)715 already_AddRefed<Promise> VRServiceTest::Reset(ErrorResult& aRv) {
716 if (mShuttingDown) {
717 return nullptr;
718 }
719
720 RefPtr<dom::Promise> resetPuppetPromise =
721 Promise::Create(mWindow->AsGlobal(), aRv);
722 if (NS_WARN_IF(aRv.Failed())) {
723 return nullptr;
724 }
725
726 gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
727 vm->ResetPuppet(resetPuppetPromise, aRv);
728 if (NS_WARN_IF(aRv.Failed())) {
729 return nullptr;
730 }
731
732 memset(&mPendingState, 0, sizeof(VRSystemState));
733 memset(&mEncodedState, 0, sizeof(VRSystemState));
734 mCommandBuffer.Clear();
735
736 return resetPuppetPromise.forget();
737 }
738
739 } // namespace dom
740 } // namespace mozilla
741