tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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