summaryrefslogtreecommitdiff
path: root/gfx/vr/gfxVR.h
blob: b468757413857171bb2ddb127a506db863dc6dfe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef GFX_VR_H
#define GFX_VR_H

#include "nsTArray.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/Atomics.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/TypedEnumBits.h"

namespace mozilla {
namespace layers {
class PTextureParent;
}
namespace dom {
enum class GamepadMappingType : uint32_t;
struct GamepadPoseState;
}
namespace gfx {
class VRLayerParent;
class VRDisplayHost;
class VRControllerHost;

enum class VRDeviceType : uint16_t {
  Oculus,
  OpenVR,
  OSVR,
  NumVRDeviceTypes
};

enum class VRDisplayCapabilityFlags : uint16_t {
  Cap_None = 0,
  /**
   * Cap_Position is set if the VRDisplay is capable of tracking its position.
   */
  Cap_Position = 1 << 1,
  /**
    * Cap_Orientation is set if the VRDisplay is capable of tracking its orientation.
    */
  Cap_Orientation = 1 << 2,
  /**
   * Cap_Present is set if the VRDisplay is capable of presenting content to an
   * HMD or similar device.  Can be used to indicate "magic window" devices that
   * are capable of 6DoF tracking but for which requestPresent is not meaningful.
   * If false then calls to requestPresent should always fail, and
   * getEyeParameters should return null.
   */
  Cap_Present = 1 << 3,
  /**
   * Cap_External is set if the VRDisplay is separate from the device's
   * primary display. If presenting VR content will obscure
   * other content on the device, this should be un-set. When
   * un-set, the application should not attempt to mirror VR content
   * or update non-VR UI because that content will not be visible.
   */
  Cap_External = 1 << 4,
  /**
   * Cap_AngularAcceleration is set if the VRDisplay is capable of tracking its
   * angular acceleration.
   */
  Cap_AngularAcceleration = 1 << 5,
  /**
   * Cap_LinearAcceleration is set if the VRDisplay is capable of tracking its
   * linear acceleration.
   */
  Cap_LinearAcceleration = 1 << 6,
  /**
   * Cap_StageParameters is set if the VRDisplay is capable of room scale VR
   * and can report the StageParameters to describe the space.
   */
  Cap_StageParameters = 1 << 7,
  /**
   * Cap_All used for validity checking during IPC serialization
   */
  Cap_All = (1 << 8) - 1
};

MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRDisplayCapabilityFlags)

struct VRFieldOfView {
  VRFieldOfView() {}
  VRFieldOfView(double up, double right, double down, double left)
    : upDegrees(up), rightDegrees(right), downDegrees(down), leftDegrees(left)
  {}

  void SetFromTanRadians(double up, double right, double down, double left)
  {
    upDegrees = atan(up) * 180.0 / M_PI;
    rightDegrees = atan(right) * 180.0 / M_PI;
    downDegrees = atan(down) * 180.0 / M_PI;
    leftDegrees = atan(left) * 180.0 / M_PI;
  }

  bool operator==(const VRFieldOfView& other) const {
    return other.upDegrees == upDegrees &&
           other.downDegrees == downDegrees &&
           other.rightDegrees == rightDegrees &&
           other.leftDegrees == leftDegrees;
  }

  bool operator!=(const VRFieldOfView& other) const {
    return !(*this == other);
  }

  bool IsZero() const {
    return upDegrees == 0.0 ||
      rightDegrees == 0.0 ||
      downDegrees == 0.0 ||
      leftDegrees == 0.0;
  }

  Matrix4x4 ConstructProjectionMatrix(float zNear, float zFar, bool rightHanded) const;

  double upDegrees;
  double rightDegrees;
  double downDegrees;
  double leftDegrees;
};

struct VRDisplayInfo
{
  VRDeviceType GetType() const { return mType; }
  uint32_t GetDisplayID() const { return mDisplayID; }
  const nsCString& GetDisplayName() const { return mDisplayName; }
  VRDisplayCapabilityFlags GetCapabilities() const { return mCapabilityFlags; }

  const IntSize& SuggestedEyeResolution() const { return mEyeResolution; }
  const Point3D& GetEyeTranslation(uint32_t whichEye) const { return mEyeTranslation[whichEye]; }
  const VRFieldOfView& GetEyeFOV(uint32_t whichEye) const { return mEyeFOV[whichEye]; }
  bool GetIsConnected() const { return mIsConnected; }
  bool GetIsPresenting() const { return mIsPresenting; }
  const Size& GetStageSize() const { return mStageSize; }
  const Matrix4x4& GetSittingToStandingTransform() const { return mSittingToStandingTransform; }

  enum Eye {
    Eye_Left,
    Eye_Right,
    NumEyes
  };

  uint32_t mDisplayID;
  VRDeviceType mType;
  nsCString mDisplayName;
  VRDisplayCapabilityFlags mCapabilityFlags;
  VRFieldOfView mEyeFOV[VRDisplayInfo::NumEyes];
  Point3D mEyeTranslation[VRDisplayInfo::NumEyes];
  IntSize mEyeResolution;
  bool mIsConnected;
  bool mIsPresenting;
  Size mStageSize;
  Matrix4x4 mSittingToStandingTransform;

  bool operator==(const VRDisplayInfo& other) const {
    return mType == other.mType &&
           mDisplayID == other.mDisplayID &&
           mDisplayName == other.mDisplayName &&
           mCapabilityFlags == other.mCapabilityFlags &&
           mEyeResolution == other.mEyeResolution &&
           mIsConnected == other.mIsConnected &&
           mIsPresenting == other.mIsPresenting &&
           mEyeFOV[0] == other.mEyeFOV[0] &&
           mEyeFOV[1] == other.mEyeFOV[1] &&
           mEyeTranslation[0] == other.mEyeTranslation[0] &&
           mEyeTranslation[1] == other.mEyeTranslation[1] &&
           mStageSize == other.mStageSize &&
           mSittingToStandingTransform == other.mSittingToStandingTransform;
  }

  bool operator!=(const VRDisplayInfo& other) const {
    return !(*this == other);
  }
};

struct VRHMDSensorState {
  double timestamp;
  int32_t inputFrameID;
  VRDisplayCapabilityFlags flags;
  float orientation[4];
  float position[3];
  float angularVelocity[3];
  float angularAcceleration[3];
  float linearVelocity[3];
  float linearAcceleration[3];

  void Clear() {
    memset(this, 0, sizeof(VRHMDSensorState));
  }
};

class VRDisplayManager {
public:
  static uint32_t AllocateDisplayID();

protected:
  static Atomic<uint32_t> sDisplayBase;

public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRDisplayManager)

  virtual bool Init() = 0;
  virtual void Destroy() = 0;
  virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) = 0;

protected:
  VRDisplayManager() { }
  virtual ~VRDisplayManager() { }
};

struct VRControllerInfo
{
  VRDeviceType GetType() const { return mType; }
  uint32_t GetControllerID() const { return mControllerID; }
  const nsCString& GetControllerName() const { return mControllerName; }
  uint32_t GetMappingType() const { return mMappingType; }
  uint32_t GetNumButtons() const { return mNumButtons; }
  uint32_t GetNumAxes() const { return mNumAxes; }

  uint32_t mControllerID;
  VRDeviceType mType;
  nsCString mControllerName;
  uint32_t mMappingType;
  uint32_t mNumButtons;
  uint32_t mNumAxes;

  bool operator==(const VRControllerInfo& other) const {
  return mType == other.mType &&
         mControllerID == other.mControllerID &&
         mControllerName == other.mControllerName &&
         mMappingType == other.mMappingType &&
         mNumButtons == other.mNumButtons &&
         mNumAxes == other.mNumAxes;
  }

  bool operator!=(const VRControllerInfo& other) const {
    return !(*this == other);
  }
};

class VRControllerManager {
public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRControllerManager)

  static uint32_t AllocateControllerID();
  virtual bool Init() = 0;
  virtual void Destroy() = 0;
  virtual void HandleInput() = 0;
  virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
  virtual void ScanForDevices() = 0;
  void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
  void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue);
  void NewPoseState(uint32_t aIndex, const dom::GamepadPoseState& aPose);
  void AddGamepad(const char* aID, uint32_t aMapping,
                  uint32_t aNumButtons, uint32_t aNumAxes);
  void RemoveGamepad(uint32_t aIndex);

protected:
  VRControllerManager() : mInstalled(false), mControllerCount(0) {}
  virtual ~VRControllerManager() {}

  bool mInstalled;
  uint32_t mControllerCount;
  static Atomic<uint32_t> sControllerBase;

private:
  virtual void HandleButtonPress(uint32_t aControllerIdx,
                                 uint64_t aButtonPressed) = 0;
  virtual void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
                              float aValue) = 0;
  virtual void HandlePoseTracking(uint32_t aControllerIdx,
                                  const dom::GamepadPoseState& aPose,
                                  VRControllerHost* aController) = 0;
};

} // namespace gfx
} // namespace mozilla

#endif /* GFX_VR_H */