tor-browser

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

moz_external_vr.h (24989B)


      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
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef GFX_VR_EXTERNAL_API_H
      8 #define GFX_VR_EXTERNAL_API_H
      9 
     10 #define GFX_VR_EIGHTCC(c1, c2, c3, c4, c5, c6, c7, c8)                  \
     11  ((uint64_t)(c1) << 56 | (uint64_t)(c2) << 48 | (uint64_t)(c3) << 40 | \
     12   (uint64_t)(c4) << 32 | (uint64_t)(c5) << 24 | (uint64_t)(c6) << 16 | \
     13   (uint64_t)(c7) << 8 | (uint64_t)(c8))
     14 
     15 #ifdef MOZILLA_INTERNAL_API
     16 
     17 // __STDC_WANT_LIB_EXT1__ required for memcpy_s
     18 #  ifndef __STDC_WANT_LIB_EXT1__
     19 #    define __STDC_WANT_LIB_EXT1__ 1
     20 #  endif  // __STDC_WANT_LIB_EXT1__
     21 
     22 static_assert(__STDC_WANT_LIB_EXT1__ == 1,
     23              "__STDC_WANT_LIB_EXT1__ must be set");
     24 
     25 #  include <stdlib.h>
     26 #  include <string.h>
     27 #  include "mozilla/TiedFields.h"
     28 #  include "mozilla/TypedEnumBits.h"
     29 #  include "mozilla/gfx/2D.h"
     30 #  include <stddef.h>
     31 #  include <stdint.h>
     32 #endif  // MOZILLA_INTERNAL_API
     33 
     34 #if defined(__ANDROID__)
     35 #  include <pthread.h>
     36 #endif  // defined(__ANDROID__)
     37 
     38 #include <array>
     39 #include <cstdint>
     40 #include <type_traits>
     41 
     42 namespace mozilla {
     43 #ifdef MOZILLA_INTERNAL_API
     44 namespace dom {
     45 enum class GamepadHand : uint8_t;
     46 enum class GamepadCapabilityFlags : uint16_t;
     47 }  // namespace dom
     48 #endif  //  MOZILLA_INTERNAL_API
     49 namespace gfx {
     50 
     51 // If there is any change of "SHMEM_VERSION" or "kVRExternalVersion",
     52 // we need to change both of them at the same time.
     53 
     54 // TODO: we might need to use different names for the mutexes
     55 // and mapped files if we have both release and nightlies
     56 // running at the same time? Or...what if we have multiple
     57 // release builds running on same machine? (Bug 1563232)
     58 #define SHMEM_VERSION "0.0.12"
     59 static const int32_t kVRExternalVersion = 19;
     60 
     61 // We assign VR presentations to groups with a bitmask.
     62 // Currently, we will only display either content or chrome.
     63 // Later, we will have more groups to support VR home spaces and
     64 // multitasking environments.
     65 // These values are not exposed to regular content and only affect
     66 // chrome-only API's.  They may be changed at any time.
     67 static const uint32_t kVRGroupNone = 0;
     68 static const uint32_t kVRGroupContent = 1 << 0;
     69 static const uint32_t kVRGroupChrome = 1 << 1;
     70 static const uint32_t kVRGroupAll = 0xffffffff;
     71 
     72 static const int kVRDisplayNameMaxLen = 256;
     73 static const int kVRControllerNameMaxLen = 256;
     74 static const int kVRControllerMaxCount = 16;
     75 static const int kVRControllerMaxButtons = 64;
     76 static const int kVRControllerMaxAxis = 16;
     77 static const int kVRLayerMaxCount = 8;
     78 static const int kVRHapticsMaxCount = 32;
     79 
     80 #if defined(__ANDROID__)
     81 typedef uint64_t VRLayerTextureHandle;
     82 #elif defined(XP_MACOSX)
     83 typedef uint32_t VRLayerTextureHandle;
     84 #else
     85 typedef void* VRLayerTextureHandle;
     86 #endif
     87 
     88 struct Point3D_POD {
     89  float x;
     90  float y;
     91  float z;
     92 
     93 #ifdef MOZILLA_INTERNAL_API
     94  auto MutTiedFields() { return std::tie(x, y, z); }
     95 
     96  bool operator==(const Point3D_POD& other) const {
     97    return TiedFields(*this) == TiedFields(other);
     98  }
     99 #endif
    100 };
    101 
    102 struct IntSize_POD {
    103  int32_t width;
    104  int32_t height;
    105 
    106 #ifdef MOZILLA_INTERNAL_API
    107  auto MutTiedFields() { return std::tie(width, height); }
    108 
    109  bool operator==(const IntSize_POD& other) const {
    110    return TiedFields(*this) == TiedFields(other);
    111  }
    112 #endif
    113 };
    114 
    115 struct FloatSize_POD {
    116  float width;
    117  float height;
    118 
    119 #ifdef MOZILLA_INTERNAL_API
    120  auto MutTiedFields() { return std::tie(width, height); }
    121 
    122  bool operator==(const FloatSize_POD& other) const {
    123    return TiedFields(*this) == TiedFields(other);
    124  }
    125 #endif
    126 };
    127 
    128 #ifndef MOZILLA_INTERNAL_API
    129 
    130 enum class ControllerHand : uint8_t { _empty, Left, Right, EndGuard_ };
    131 
    132 enum class ControllerCapabilityFlags : uint16_t {
    133  Cap_None = 0,
    134  /**
    135   * Cap_Position is set if the Gamepad is capable of tracking its position.
    136   */
    137  Cap_Position = 1 << 1,
    138  /**
    139   * Cap_Orientation is set if the Gamepad is capable of tracking its
    140   * orientation.
    141   */
    142  Cap_Orientation = 1 << 2,
    143  /**
    144   * Cap_AngularAcceleration is set if the Gamepad is capable of tracking its
    145   * angular acceleration.
    146   */
    147  Cap_AngularAcceleration = 1 << 3,
    148  /**
    149   * Cap_LinearAcceleration is set if the Gamepad is capable of tracking its
    150   * linear acceleration.
    151   */
    152  Cap_LinearAcceleration = 1 << 4,
    153  /**
    154   * Cap_TargetRaySpacePosition is set if the Gamepad has a grip space position.
    155   */
    156  Cap_GripSpacePosition = 1 << 5,
    157  /**
    158   * Cap_PositionEmulated is set if the XRInputSoruce is capable of setting a
    159   * emulated position (e.g. neck model) even if still doesn't support 6DOF
    160   * tracking.
    161   */
    162  Cap_PositionEmulated = 1 << 6,
    163  /**
    164   * Cap_All used for validity checking during IPC serialization
    165   */
    166  Cap_All = (1 << 7) - 1
    167 };
    168 
    169 #endif  // ifndef MOZILLA_INTERNAL_API
    170 
    171 enum class VRControllerType : uint8_t {
    172  _empty,
    173  HTCVive,
    174  HTCViveCosmos,
    175  HTCViveFocus,
    176  HTCViveFocusPlus,
    177  MSMR,
    178  ValveIndex,
    179  OculusGo,
    180  OculusTouch,
    181  OculusTouch2,
    182  OculusTouch3,
    183  PicoGaze,
    184  PicoG2,
    185  PicoNeo2,
    186  _end
    187 };
    188 
    189 }  // namespace gfx
    190 
    191 template <class T>
    192 bool IsEnumCase(T);
    193 
    194 template <>
    195 inline constexpr bool IsEnumCase<gfx::VRControllerType>(
    196    const gfx::VRControllerType raw) {
    197  switch (raw) {
    198    case gfx::VRControllerType::_empty:
    199    case gfx::VRControllerType::HTCVive:
    200    case gfx::VRControllerType::HTCViveCosmos:
    201    case gfx::VRControllerType::HTCViveFocus:
    202    case gfx::VRControllerType::HTCViveFocusPlus:
    203    case gfx::VRControllerType::MSMR:
    204    case gfx::VRControllerType::ValveIndex:
    205    case gfx::VRControllerType::OculusGo:
    206    case gfx::VRControllerType::OculusTouch:
    207    case gfx::VRControllerType::OculusTouch2:
    208    case gfx::VRControllerType::OculusTouch3:
    209    case gfx::VRControllerType::PicoGaze:
    210    case gfx::VRControllerType::PicoG2:
    211    case gfx::VRControllerType::PicoNeo2:
    212    case gfx::VRControllerType::_end:
    213      return true;
    214  }
    215  return false;
    216 }
    217 namespace gfx {
    218 
    219 // -
    220 
    221 enum class TargetRayMode : uint8_t { Gaze, TrackedPointer, Screen };
    222 
    223 }  // namespace gfx
    224 template <>
    225 inline constexpr bool IsEnumCase<gfx::TargetRayMode>(
    226    const gfx::TargetRayMode raw) {
    227  switch (raw) {
    228    case gfx::TargetRayMode::Gaze:
    229    case gfx::TargetRayMode::TrackedPointer:
    230    case gfx::TargetRayMode::Screen:
    231      return true;
    232  }
    233  return false;
    234 }
    235 namespace gfx {
    236 
    237 // -
    238 
    239 enum class GamepadMappingType : uint8_t { _empty, Standard, XRStandard };
    240 
    241 }  // namespace gfx
    242 template <>
    243 inline constexpr bool IsEnumCase<gfx::GamepadMappingType>(
    244    const gfx::GamepadMappingType raw) {
    245  switch (raw) {
    246    case gfx::GamepadMappingType::_empty:
    247    case gfx::GamepadMappingType::Standard:
    248    case gfx::GamepadMappingType::XRStandard:
    249      return true;
    250  }
    251  return false;
    252 }
    253 namespace gfx {
    254 
    255 // -
    256 
    257 enum class VRDisplayBlendMode : uint8_t { Opaque, Additive, AlphaBlend };
    258 
    259 }  // namespace gfx
    260 template <>
    261 inline constexpr bool IsEnumCase<gfx::VRDisplayBlendMode>(
    262    const gfx::VRDisplayBlendMode raw) {
    263  switch (raw) {
    264    case gfx::VRDisplayBlendMode::Opaque:
    265    case gfx::VRDisplayBlendMode::Additive:
    266    case gfx::VRDisplayBlendMode::AlphaBlend:
    267      return true;
    268  }
    269  return false;
    270 }
    271 namespace gfx {
    272 
    273 // -
    274 
    275 enum class VRDisplayCapabilityFlags : uint16_t {
    276  Cap_None = 0,
    277  /**
    278   * Cap_Position is set if the VRDisplay is capable of tracking its position.
    279   */
    280  Cap_Position = 1 << 1,
    281  /**
    282   * Cap_Orientation is set if the VRDisplay is capable of tracking its
    283   * orientation.
    284   */
    285  Cap_Orientation = 1 << 2,
    286  /**
    287   * Cap_Present is set if the VRDisplay is capable of presenting content to an
    288   * HMD or similar device.  Can be used to indicate "magic window" devices that
    289   * are capable of 6DoF tracking but for which requestPresent is not
    290   * meaningful. If false then calls to requestPresent should always fail, and
    291   * getEyeParameters should return null.
    292   */
    293  Cap_Present = 1 << 3,
    294  /**
    295   * Cap_External is set if the VRDisplay is separate from the device's
    296   * primary display. If presenting VR content will obscure
    297   * other content on the device, this should be un-set. When
    298   * un-set, the application should not attempt to mirror VR content
    299   * or update non-VR UI because that content will not be visible.
    300   */
    301  Cap_External = 1 << 4,
    302  /**
    303   * Cap_AngularAcceleration is set if the VRDisplay is capable of tracking its
    304   * angular acceleration.
    305   */
    306  Cap_AngularAcceleration = 1 << 5,
    307  /**
    308   * Cap_LinearAcceleration is set if the VRDisplay is capable of tracking its
    309   * linear acceleration.
    310   */
    311  Cap_LinearAcceleration = 1 << 6,
    312  /**
    313   * Cap_StageParameters is set if the VRDisplay is capable of room scale VR
    314   * and can report the StageParameters to describe the space.
    315   */
    316  Cap_StageParameters = 1 << 7,
    317  /**
    318   * Cap_MountDetection is set if the VRDisplay is capable of sensing when the
    319   * user is wearing the device.
    320   */
    321  Cap_MountDetection = 1 << 8,
    322  /**
    323   * Cap_PositionEmulated is set if the VRDisplay is capable of setting a
    324   * emulated position (e.g. neck model) even if still doesn't support 6DOF
    325   * tracking.
    326   */
    327  Cap_PositionEmulated = 1 << 9,
    328  /**
    329   * Cap_Inline is set if the device can be used for WebXR inline sessions
    330   * where the content is displayed within an element on the page.
    331   */
    332  Cap_Inline = 1 << 10,
    333  /**
    334   * Cap_ImmersiveVR is set if the device can give exclusive access to the
    335   * XR device display and that content is not intended to be integrated
    336   * with the user's environment
    337   */
    338  Cap_ImmersiveVR = 1 << 11,
    339  /**
    340   * Cap_ImmersiveAR is set if the device can give exclusive access to the
    341   * XR device display and that content is intended to be integrated with
    342   * the user's environment.
    343   */
    344  Cap_ImmersiveAR = 1 << 12,
    345  /**
    346   * Cap_UseDepthValues is set if the device will use the depth values of the
    347   * submitted frames if provided.  How the depth values are used is determined
    348   * by the VR runtime.  Often the depth is used for occlusion of system UI
    349   * or to enable more effective asynchronous reprojection of frames.
    350   */
    351  Cap_UseDepthValues = 1 << 13,
    352  /**
    353   * Cap_All used for validity checking during IPC serialization
    354   */
    355  Cap_All = (1 << 14) - 1
    356 };
    357 
    358 #ifdef MOZILLA_INTERNAL_API
    359 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRDisplayCapabilityFlags)
    360 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRDisplayBlendMode)
    361 #endif  // MOZILLA_INTERNAL_API
    362 
    363 struct VRPose {
    364  std::array<float, 4> orientation;
    365  std::array<float, 3> position;
    366  std::array<float, 3> angularVelocity;
    367  std::array<float, 3> angularAcceleration;
    368  std::array<float, 3> linearVelocity;
    369  std::array<float, 3> linearAcceleration;
    370 
    371 #ifdef MOZILLA_INTERNAL_API
    372  auto MutTiedFields() {
    373    return std::tie(orientation, position, angularVelocity, angularAcceleration,
    374                    linearVelocity, linearAcceleration);
    375  }
    376 
    377  bool operator==(const VRPose& other) const {
    378    return TiedFields(*this) == TiedFields(other);
    379  }
    380 #endif  // MOZILLA_INTERNAL_API
    381 };
    382 
    383 struct VRHMDSensorState {
    384  uint64_t inputFrameID;
    385  double timestamp;
    386  VRDisplayCapabilityFlags flags;
    387  uint16_t _padding;
    388 
    389  // These members will only change with inputFrameID:
    390  VRPose pose;
    391  std::array<float, 16> leftViewMatrix;
    392  std::array<float, 16> rightViewMatrix;
    393 
    394 #ifdef MOZILLA_INTERNAL_API
    395 
    396  auto MutTiedFields() {
    397    return std::tie(inputFrameID, timestamp, flags, _padding, pose,
    398                    leftViewMatrix, rightViewMatrix);
    399  }
    400 
    401  void Clear() { memset(this, 0, sizeof(VRHMDSensorState)); }
    402 
    403  bool operator==(const VRHMDSensorState& other) const {
    404    return inputFrameID == other.inputFrameID && timestamp == other.timestamp;
    405  }
    406 
    407  bool operator!=(const VRHMDSensorState& other) const {
    408    return !(*this == other);
    409  }
    410 
    411  void CalcViewMatrices(const gfx::Matrix4x4* aHeadToEyeTransforms);
    412 
    413 #endif  // MOZILLA_INTERNAL_API
    414 };
    415 
    416 struct VRFieldOfView {
    417  double upDegrees;
    418  double rightDegrees;
    419  double downDegrees;
    420  double leftDegrees;
    421 
    422 #ifdef MOZILLA_INTERNAL_API
    423  auto MutTiedFields() {
    424    return std::tie(upDegrees, rightDegrees, downDegrees, leftDegrees);
    425  }
    426 
    427  bool operator==(const VRFieldOfView& other) const {
    428    return TiedFields(*this) == TiedFields(other);
    429  }
    430 
    431  VRFieldOfView() = default;
    432  VRFieldOfView(double up, double right, double down, double left)
    433      : upDegrees(up),
    434        rightDegrees(right),
    435        downDegrees(down),
    436        leftDegrees(left) {}
    437 
    438  void SetFromTanRadians(double up, double right, double down, double left) {
    439    upDegrees = atan(up) * 180.0 / M_PI;
    440    rightDegrees = atan(right) * 180.0 / M_PI;
    441    downDegrees = atan(down) * 180.0 / M_PI;
    442    leftDegrees = atan(left) * 180.0 / M_PI;
    443  }
    444 
    445  bool operator!=(const VRFieldOfView& other) const {
    446    return !(*this == other);
    447  }
    448 
    449  bool IsZero() const {
    450    return upDegrees == 0.0 || rightDegrees == 0.0 || downDegrees == 0.0 ||
    451           leftDegrees == 0.0;
    452  }
    453 
    454  Matrix4x4 ConstructProjectionMatrix(float zNear, float zFar,
    455                                      bool rightHanded) const;
    456 
    457 #endif  // MOZILLA_INTERNAL_API
    458 };
    459 
    460 struct VRDisplayState {
    461  enum Eye { Eye_Left, Eye_Right, NumEyes };
    462 
    463  // When true, indicates that the VR service has shut down
    464  bool shutdown;
    465  std::array<uint8_t, 3> _padding1;
    466  // Minimum number of milliseconds to wait before attempting
    467  // to start the VR service again
    468  uint32_t minRestartInterval;
    469  std::array<char, kVRDisplayNameMaxLen> displayName;
    470  // eight byte character code identifier
    471  // LSB first, so "ABCDEFGH" -> ('H'<<56) + ('G'<<48) + ('F'<<40) +
    472  //                             ('E'<<32) + ('D'<<24) + ('C'<<16) +
    473  //                             ('B'<<8) + 'A').
    474  uint64_t eightCC;
    475  VRDisplayCapabilityFlags capabilityFlags;
    476  VRDisplayBlendMode blendMode;
    477  std::array<uint8_t, 5> _padding2;
    478  std::array<VRFieldOfView, VRDisplayState::NumEyes> eyeFOV;
    479  static_assert(std::is_trivial_v<VRFieldOfView>);
    480  std::array<Point3D_POD, VRDisplayState::NumEyes> eyeTranslation;
    481  static_assert(std::is_trivial_v<Point3D_POD>);
    482  IntSize_POD eyeResolution;
    483  static_assert(std::is_trivial_v<IntSize_POD>);
    484  float nativeFramebufferScaleFactor;
    485  bool suppressFrames;
    486  bool isConnected;
    487  bool isMounted;
    488  uint8_t _padding3;
    489  FloatSize_POD stageSize;
    490  static_assert(std::is_trivial_v<FloatSize_POD>);
    491  // We can't use a Matrix4x4 here unless we ensure it's a POD type
    492  std::array<float, 16> sittingToStandingTransform;
    493  uint64_t lastSubmittedFrameId;
    494  bool lastSubmittedFrameSuccessful;
    495  std::array<uint8_t, 3> _padding4;
    496  uint32_t presentingGeneration;
    497  // Telemetry
    498  bool reportsDroppedFrames;
    499  std::array<uint8_t, 7> _padding5;
    500  uint64_t droppedFrameCount;
    501 
    502 #ifdef MOZILLA_INTERNAL_API
    503  auto MutTiedFields() {
    504    return std::tie(shutdown, _padding1, minRestartInterval, displayName,
    505                    eightCC, capabilityFlags, blendMode, _padding2, eyeFOV,
    506                    eyeTranslation, eyeResolution, nativeFramebufferScaleFactor,
    507                    suppressFrames, isConnected, isMounted, _padding3,
    508                    stageSize, sittingToStandingTransform, lastSubmittedFrameId,
    509                    lastSubmittedFrameSuccessful, _padding4,
    510                    presentingGeneration, reportsDroppedFrames, _padding5,
    511                    droppedFrameCount);
    512  }
    513 
    514  bool operator==(const VRDisplayState& other) const {
    515    return TiedFields(*this) == TiedFields(other);
    516  }
    517 
    518  void Clear() { memset(this, 0, sizeof(VRDisplayState)); }
    519 #endif
    520 };
    521 static_assert(std::is_trivial_v<VRDisplayState>);
    522 
    523 struct VRControllerState {
    524  std::array<char, kVRControllerNameMaxLen> controllerName;
    525 #ifdef MOZILLA_INTERNAL_API
    526  dom::GamepadHand hand;
    527 #else
    528  ControllerHand hand;
    529 #endif
    530  // For WebXR->WebVR mapping conversion, once we remove WebVR,
    531  // we can remove this item.
    532  VRControllerType type;
    533  // https://immersive-web.github.io/webxr/#enumdef-xrtargetraymode
    534  TargetRayMode targetRayMode;
    535 
    536  // https://immersive-web.github.io/webxr-gamepads-module/#enumdef-gamepadmappingtype
    537  GamepadMappingType mappingType;
    538 
    539  uint32_t _padding1;
    540 
    541  // Start frame ID of the most recent primary select
    542  // action, or 0 if the select action has never occurred.
    543  uint64_t selectActionStartFrameId;
    544  // End frame Id of the most recent primary select
    545  // action, or 0 if action never occurred.
    546  // If selectActionStopFrameId is less than
    547  // selectActionStartFrameId, then the select
    548  // action has not ended yet.
    549  uint64_t selectActionStopFrameId;
    550 
    551  // start frame Id of the most recent primary squeeze
    552  // action, or 0 if the squeeze action has never occurred.
    553  uint64_t squeezeActionStartFrameId;
    554  // End frame Id of the most recent primary squeeze
    555  // action, or 0 if action never occurred.
    556  // If squeezeActionStopFrameId is less than
    557  // squeezeActionStartFrameId, then the squeeze
    558  // action has not ended yet.
    559  uint64_t squeezeActionStopFrameId;
    560 
    561  uint32_t numButtons;
    562  uint32_t numAxes;
    563  uint32_t numHaptics;
    564  uint32_t _padding2;
    565  // The current button pressed bit of button mask.
    566  uint64_t buttonPressed;
    567  // The current button touched bit of button mask.
    568  uint64_t buttonTouched;
    569  std::array<float, kVRControllerMaxButtons> triggerValue;
    570  std::array<float, kVRControllerMaxAxis> axisValue;
    571 
    572 #ifdef MOZILLA_INTERNAL_API
    573  dom::GamepadCapabilityFlags flags;
    574 #else
    575  ControllerCapabilityFlags flags;
    576 #endif
    577 
    578  uint16_t _padding3;
    579 
    580  // When Cap_Position is set in flags, pose corresponds
    581  // to the controllers' pose in grip space:
    582  // https://immersive-web.github.io/webxr/#dom-xrinputsource-gripspace
    583  VRPose pose;
    584 
    585  // When Cap_TargetRaySpacePosition is set in flags, targetRayPose corresponds
    586  // to the controllers' pose in target ray space:
    587  // https://immersive-web.github.io/webxr/#dom-xrinputsource-targetrayspace
    588  VRPose targetRayPose;
    589 
    590  bool isPositionValid;
    591  bool isOrientationValid;
    592  uint16_t _padding4;
    593 
    594 #ifdef MOZILLA_INTERNAL_API
    595  auto MutTiedFields() {
    596    return std::tie(controllerName, hand, type, targetRayMode, mappingType,
    597                    _padding1, selectActionStartFrameId,
    598                    selectActionStopFrameId, squeezeActionStartFrameId,
    599                    squeezeActionStopFrameId, numButtons, numAxes, numHaptics,
    600                    _padding2, buttonPressed, buttonTouched, triggerValue,
    601                    axisValue, flags, _padding3, pose, targetRayPose,
    602                    isPositionValid, isOrientationValid, _padding4);
    603  }
    604 
    605  bool operator==(const VRControllerState& other) const {
    606    return TiedFields(*this) == TiedFields(other);
    607  }
    608 
    609  void Clear() { memset(this, 0, sizeof(VRControllerState)); }
    610 #endif
    611 };
    612 
    613 struct VRLayerEyeRect {
    614  float x;
    615  float y;
    616  float width;
    617  float height;
    618 };
    619 
    620 enum class VRLayerType : uint16_t {
    621  LayerType_None = 0,
    622  LayerType_2D_Content = 1,
    623  LayerType_Stereo_Immersive = 2
    624 };
    625 
    626 enum class VRLayerTextureType : uint16_t {
    627  LayerTextureType_None = 0,
    628  LayerTextureType_D3D10SurfaceDescriptor = 1,
    629  LayerTextureType_MacIOSurface = 2,
    630  LayerTextureType_GeckoSurfaceTexture = 3
    631 };
    632 
    633 struct VRLayer_2D_Content {
    634  VRLayerTextureHandle textureHandle;
    635  VRLayerTextureType textureType;
    636  uint64_t frameId;
    637 };
    638 
    639 struct VRLayer_Stereo_Immersive {
    640  VRLayerTextureHandle textureHandle;
    641  VRLayerTextureType textureType;
    642  uint64_t frameId;
    643  uint64_t inputFrameId;
    644  VRLayerEyeRect leftEyeRect;
    645  VRLayerEyeRect rightEyeRect;
    646  IntSize_POD textureSize;
    647 };
    648 
    649 struct VRLayerState {
    650  VRLayerType type;
    651  union {
    652    VRLayer_2D_Content layer_2d_content;
    653    VRLayer_Stereo_Immersive layer_stereo_immersive;
    654  };
    655 };
    656 
    657 struct VRHapticState {
    658  // Reference frame for timing.
    659  // When 0, this does not represent an active haptic pulse.
    660  uint64_t inputFrameID;
    661  // Index within VRSystemState.controllerState identifying the controller
    662  // to emit the haptic pulse
    663  uint32_t controllerIndex;
    664  // 0-based index indicating which haptic actuator within the controller
    665  uint32_t hapticIndex;
    666  // Start time of the haptic feedback pulse, relative to the start of
    667  // inputFrameID, in seconds
    668  float pulseStart;
    669  // Duration of the haptic feedback pulse, in seconds
    670  float pulseDuration;
    671  // Intensity of the haptic feedback pulse, from 0.0f to 1.0f
    672  float pulseIntensity;
    673 };
    674 
    675 struct VRBrowserState {
    676 #if defined(__ANDROID__)
    677  bool shutdown;
    678 #endif  // defined(__ANDROID__)
    679  /**
    680   * In order to support WebXR's navigator.xr.IsSessionSupported call without
    681   * displaying any permission dialogue, it is necessary to have a safe way to
    682   * detect the capability of running a VR or AR session without activating XR
    683   * runtimes or powering on hardware.
    684   *
    685   * API's such as OpenVR make no guarantee that hardware and software won't be
    686   * left activated after enumerating devices, so each backend in gfx/vr/service
    687   * must allow for more granular detection of capabilities.
    688   *
    689   * When detectRuntimesOnly is true, the initialization exits early after
    690   * reporting the presence of XR runtime software.
    691   *
    692   * The result of the runtime detection is reported with the Cap_ImmersiveVR
    693   * and Cap_ImmersiveAR bits in VRDisplayState.flags.
    694   */
    695  bool detectRuntimesOnly;
    696  bool presentationActive;
    697  bool navigationTransitionActive;
    698  VRLayerState layerState[kVRLayerMaxCount];
    699  VRHapticState hapticState[kVRHapticsMaxCount];
    700 
    701 #ifdef MOZILLA_INTERNAL_API
    702  void Clear() { memset(this, 0, sizeof(VRBrowserState)); }
    703 #endif
    704 };
    705 
    706 struct VRSystemState {
    707  bool enumerationCompleted;
    708  VRDisplayState displayState;
    709  VRHMDSensorState sensorState;
    710  std::array<VRControllerState, kVRControllerMaxCount> controllerState;
    711 };
    712 static_assert(std::is_trivial_v<VRDisplayState>);
    713 static_assert(std::is_trivial_v<VRHMDSensorState>);
    714 static_assert(std::is_trivial_v<VRControllerState>);
    715 static_assert(std::is_trivial_v<VRSystemState>);
    716 
    717 enum class VRFxEventType : uint8_t {
    718  NONE = 0,
    719  IME,
    720  SHUTDOWN,
    721  FULLSCREEN,
    722  TOTAL
    723 };
    724 
    725 enum class VRFxEventState : uint8_t {
    726  NONE = 0,
    727  BLUR,
    728  FOCUS,
    729  FULLSCREEN_ENTER,
    730  FULLSCREEN_EXIT,
    731  TOTAL
    732 };
    733 
    734 // Data shared via shmem for running Firefox in a VR windowed environment
    735 struct VRWindowState {
    736  // State from Firefox
    737  uint64_t hwndFx;
    738  uint32_t widthFx;
    739  uint32_t heightFx;
    740  VRLayerTextureHandle textureFx;
    741  uint32_t windowID;
    742  VRFxEventType eventType;
    743  VRFxEventState eventState;
    744 
    745  // State from VRHost
    746  uint32_t dxgiAdapterHost;
    747  uint32_t widthHost;
    748  uint32_t heightHost;
    749 
    750  // Name of synchronization primitive to signal change to this struct
    751  char signalName[32];
    752 };
    753 
    754 enum class VRTelemetryId : uint8_t {
    755  NONE = 0,
    756  INSTALLED_FROM = 1,
    757  ENTRY_METHOD = 2,
    758  FIRST_RUN = 3,
    759  TOTAL = 4,
    760 };
    761 
    762 enum class VRTelemetryInstallFrom : uint8_t {
    763  User = 0,
    764  FxR = 1,
    765  HTC = 2,
    766  Valve = 3,
    767  TOTAL = 4,
    768 };
    769 
    770 enum class VRTelemetryEntryMethod : uint8_t {
    771  SystemBtn = 0,
    772  Library = 1,
    773  Gaze = 2,
    774  TOTAL = 3,
    775 };
    776 
    777 struct VRTelemetryState {
    778  uint32_t uid;
    779 
    780  bool installedFrom : 1;
    781  bool entryMethod : 1;
    782  bool firstRun : 1;
    783 
    784  uint8_t installedFromValue : 3;
    785  uint8_t entryMethodValue : 3;
    786  bool firstRunValue : 1;
    787 };
    788 
    789 struct VRExternalShmem {
    790  int32_t version;
    791  int32_t size;
    792 #if defined(__ANDROID__)
    793  pthread_mutex_t systemMutex;
    794  pthread_mutex_t geckoMutex;
    795  pthread_mutex_t servoMutex;
    796  pthread_cond_t systemCond;
    797  pthread_cond_t geckoCond;
    798  pthread_cond_t servoCond;
    799 #else
    800  int64_t generationA;
    801 #endif  // defined(__ANDROID__)
    802  VRSystemState state;
    803 #if !defined(__ANDROID__)
    804  int64_t generationB;
    805  int64_t geckoGenerationA;
    806  int64_t servoGenerationA;
    807 #endif  // !defined(__ANDROID__)
    808  VRBrowserState geckoState;
    809  VRBrowserState servoState;
    810 #if !defined(__ANDROID__)
    811  int64_t geckoGenerationB;
    812  int64_t servoGenerationB;
    813 #endif  // !defined(__ANDROID__)
    814 #if defined(XP_WIN)
    815  VRWindowState windowState;
    816  VRTelemetryState telemetryState;
    817 #endif
    818 #ifdef MOZILLA_INTERNAL_API
    819  void Clear() volatile {
    820 /**
    821 * When possible we do a memset_s, which is explicitly safe for
    822 * the volatile, POD struct.  A memset may be optimized out by
    823 * the compiler and will fail to compile due to volatile keyword
    824 * propagation.
    825 *
    826 * A loop-based fallback is provided in case the toolchain does
    827 * not include STDC_LIB_EXT1 for memset_s.
    828 */
    829 #  ifdef __STDC_LIB_EXT1__
    830    memset_s((void*)this, sizeof(VRExternalShmem), 0, sizeof(VRExternalShmem));
    831 #  else
    832    size_t remaining = sizeof(VRExternalShmem);
    833    volatile unsigned char* d = (volatile unsigned char*)this;
    834    while (remaining--) {
    835      *d++ = 0;
    836    }
    837 #  endif
    838  }
    839 #endif
    840 };
    841 
    842 // As we are memcpy'ing VRExternalShmem and its members around, it must be a POD
    843 // type
    844 static_assert(std::is_trivial_v<VRSystemState>);
    845 static_assert(std::is_trivial_v<VRBrowserState>);
    846 static_assert(std::is_trivial_v<VRWindowState>);
    847 static_assert(std::is_trivial_v<VRTelemetryState>);
    848 static_assert(std::is_trivial_v<VRExternalShmem>,
    849              "VRExternalShmem must be a trivial type.");
    850 
    851 }  // namespace gfx
    852 }  // namespace mozilla
    853 
    854 #endif /* GFX_VR_EXTERNAL_API_H */