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