Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef GFX_VR_H
7 : #define GFX_VR_H
8 :
9 : #include "nsTArray.h"
10 : #include "nsString.h"
11 : #include "nsCOMPtr.h"
12 : #include "mozilla/RefPtr.h"
13 : #include "mozilla/gfx/2D.h"
14 : #include "mozilla/Atomics.h"
15 : #include "mozilla/EnumeratedArray.h"
16 : #include "mozilla/TimeStamp.h"
17 : #include "mozilla/TypedEnumBits.h"
18 :
19 : namespace mozilla {
20 : namespace layers {
21 : class PTextureParent;
22 : }
23 : namespace dom {
24 : enum class GamepadMappingType : uint8_t;
25 : enum class GamepadHand : uint8_t;
26 : struct GamepadPoseState;
27 : }
28 : namespace gfx {
29 : class VRLayerParent;
30 : class VRDisplayHost;
31 : class VRControllerHost;
32 :
33 : enum class VRDeviceType : uint16_t {
34 : Oculus,
35 : OpenVR,
36 : OSVR,
37 : Puppet,
38 : NumVRDeviceTypes
39 : };
40 :
41 : enum class VRDisplayCapabilityFlags : uint16_t {
42 : Cap_None = 0,
43 : /**
44 : * Cap_Position is set if the VRDisplay is capable of tracking its position.
45 : */
46 : Cap_Position = 1 << 1,
47 : /**
48 : * Cap_Orientation is set if the VRDisplay is capable of tracking its orientation.
49 : */
50 : Cap_Orientation = 1 << 2,
51 : /**
52 : * Cap_Present is set if the VRDisplay is capable of presenting content to an
53 : * HMD or similar device. Can be used to indicate "magic window" devices that
54 : * are capable of 6DoF tracking but for which requestPresent is not meaningful.
55 : * If false then calls to requestPresent should always fail, and
56 : * getEyeParameters should return null.
57 : */
58 : Cap_Present = 1 << 3,
59 : /**
60 : * Cap_External is set if the VRDisplay is separate from the device's
61 : * primary display. If presenting VR content will obscure
62 : * other content on the device, this should be un-set. When
63 : * un-set, the application should not attempt to mirror VR content
64 : * or update non-VR UI because that content will not be visible.
65 : */
66 : Cap_External = 1 << 4,
67 : /**
68 : * Cap_AngularAcceleration is set if the VRDisplay is capable of tracking its
69 : * angular acceleration.
70 : */
71 : Cap_AngularAcceleration = 1 << 5,
72 : /**
73 : * Cap_LinearAcceleration is set if the VRDisplay is capable of tracking its
74 : * linear acceleration.
75 : */
76 : Cap_LinearAcceleration = 1 << 6,
77 : /**
78 : * Cap_StageParameters is set if the VRDisplay is capable of room scale VR
79 : * and can report the StageParameters to describe the space.
80 : */
81 : Cap_StageParameters = 1 << 7,
82 : /**
83 : * Cap_MountDetection is set if the VRDisplay is capable of sensing when the
84 : * user is wearing the device.
85 : */
86 : Cap_MountDetection = 1 << 8,
87 : /**
88 : * Cap_All used for validity checking during IPC serialization
89 : */
90 : Cap_All = (1 << 9) - 1
91 : };
92 :
93 0 : MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRDisplayCapabilityFlags)
94 :
95 : struct VRFieldOfView {
96 0 : VRFieldOfView() {}
97 0 : VRFieldOfView(double up, double right, double down, double left)
98 0 : : upDegrees(up), rightDegrees(right), downDegrees(down), leftDegrees(left)
99 0 : {}
100 :
101 0 : void SetFromTanRadians(double up, double right, double down, double left)
102 : {
103 0 : upDegrees = atan(up) * 180.0 / M_PI;
104 0 : rightDegrees = atan(right) * 180.0 / M_PI;
105 0 : downDegrees = atan(down) * 180.0 / M_PI;
106 0 : leftDegrees = atan(left) * 180.0 / M_PI;
107 0 : }
108 :
109 0 : bool operator==(const VRFieldOfView& other) const {
110 0 : return other.upDegrees == upDegrees &&
111 0 : other.downDegrees == downDegrees &&
112 0 : other.rightDegrees == rightDegrees &&
113 0 : other.leftDegrees == leftDegrees;
114 : }
115 :
116 : bool operator!=(const VRFieldOfView& other) const {
117 : return !(*this == other);
118 : }
119 :
120 : bool IsZero() const {
121 : return upDegrees == 0.0 ||
122 : rightDegrees == 0.0 ||
123 : downDegrees == 0.0 ||
124 : leftDegrees == 0.0;
125 : }
126 :
127 : Matrix4x4 ConstructProjectionMatrix(float zNear, float zFar, bool rightHanded) const;
128 :
129 : double upDegrees;
130 : double rightDegrees;
131 : double downDegrees;
132 : double leftDegrees;
133 : };
134 :
135 : struct VRHMDSensorState {
136 0 : VRHMDSensorState()
137 0 : {
138 0 : Clear();
139 0 : }
140 : int32_t inputFrameID;
141 : double timestamp;
142 : VRDisplayCapabilityFlags flags;
143 :
144 : // These members will only change with inputFrameID:
145 : float orientation[4];
146 : float position[3];
147 : float angularVelocity[3];
148 : float angularAcceleration[3];
149 : float linearVelocity[3];
150 : float linearAcceleration[3];
151 :
152 0 : void Clear() {
153 0 : memset(this, 0, sizeof(VRHMDSensorState));
154 0 : }
155 :
156 0 : bool operator==(const VRHMDSensorState& other) const {
157 0 : return inputFrameID == other.inputFrameID &&
158 0 : timestamp == other.timestamp;
159 : }
160 :
161 0 : bool operator!=(const VRHMDSensorState& other) const {
162 0 : return !(*this == other);
163 : }
164 : };
165 :
166 : // The maximum number of frames of latency that we would expect before we
167 : // should give up applying pose prediction.
168 : // If latency is greater than one second, then the experience is not likely
169 : // to be corrected by pose prediction. Setting this value too
170 : // high may result in unnecessary memory allocation.
171 : // As the current fastest refresh rate is 90hz, 100 is selected as a
172 : // conservative value.
173 : static const int kVRMaxLatencyFrames = 100;
174 :
175 : // We assign VR presentations to groups with a bitmask.
176 : // Currently, we will only display either content or chrome.
177 : // Later, we will have more groups to support VR home spaces and
178 : // multitasking environments.
179 : // These values are not exposed to regular content and only affect
180 : // chrome-only API's. They may be changed at any time.
181 : static const uint32_t kVRGroupNone = 0;
182 : static const uint32_t kVRGroupContent = 1 << 0;
183 : static const uint32_t kVRGroupChrome = 1 << 1;
184 : static const uint32_t kVRGroupAll = 0xffffffff;
185 :
186 0 : struct VRDisplayInfo
187 : {
188 0 : VRDeviceType GetType() const { return mType; }
189 0 : uint32_t GetDisplayID() const { return mDisplayID; }
190 0 : const nsCString& GetDisplayName() const { return mDisplayName; }
191 0 : VRDisplayCapabilityFlags GetCapabilities() const { return mCapabilityFlags; }
192 :
193 0 : const IntSize& SuggestedEyeResolution() const { return mEyeResolution; }
194 0 : const Point3D& GetEyeTranslation(uint32_t whichEye) const { return mEyeTranslation[whichEye]; }
195 0 : const VRFieldOfView& GetEyeFOV(uint32_t whichEye) const { return mEyeFOV[whichEye]; }
196 0 : bool GetIsConnected() const { return mIsConnected; }
197 : bool GetIsMounted() const { return mIsMounted; }
198 0 : uint32_t GetPresentingGroups() const { return mPresentingGroups; }
199 0 : uint32_t GetGroupMask() const { return mGroupMask; }
200 0 : const Size& GetStageSize() const { return mStageSize; }
201 0 : const Matrix4x4& GetSittingToStandingTransform() const { return mSittingToStandingTransform; }
202 : uint32_t GetFrameId() const { return mFrameId; }
203 :
204 : enum Eye {
205 : Eye_Left,
206 : Eye_Right,
207 : NumEyes
208 : };
209 :
210 : uint32_t mDisplayID;
211 : VRDeviceType mType;
212 : nsCString mDisplayName;
213 : VRDisplayCapabilityFlags mCapabilityFlags;
214 : VRFieldOfView mEyeFOV[VRDisplayInfo::NumEyes];
215 : Point3D mEyeTranslation[VRDisplayInfo::NumEyes];
216 : IntSize mEyeResolution;
217 : bool mIsConnected;
218 : bool mIsMounted;
219 : uint32_t mPresentingGroups;
220 : uint32_t mGroupMask;
221 : Size mStageSize;
222 : Matrix4x4 mSittingToStandingTransform;
223 : uint32_t mFrameId;
224 : VRHMDSensorState mLastSensorState[kVRMaxLatencyFrames];
225 :
226 0 : bool operator==(const VRDisplayInfo& other) const {
227 0 : for (size_t i = 0; i < kVRMaxLatencyFrames; i++) {
228 0 : if (mLastSensorState[i] != other.mLastSensorState[i]) {
229 0 : return false;
230 : }
231 : }
232 0 : return mType == other.mType &&
233 0 : mDisplayID == other.mDisplayID &&
234 0 : mDisplayName == other.mDisplayName &&
235 0 : mCapabilityFlags == other.mCapabilityFlags &&
236 0 : mEyeResolution == other.mEyeResolution &&
237 0 : mIsConnected == other.mIsConnected &&
238 0 : mIsMounted == other.mIsMounted &&
239 0 : mPresentingGroups == other.mPresentingGroups &&
240 0 : mGroupMask == other.mGroupMask &&
241 0 : mEyeFOV[0] == other.mEyeFOV[0] &&
242 0 : mEyeFOV[1] == other.mEyeFOV[1] &&
243 0 : mEyeTranslation[0] == other.mEyeTranslation[0] &&
244 0 : mEyeTranslation[1] == other.mEyeTranslation[1] &&
245 0 : mStageSize == other.mStageSize &&
246 0 : mSittingToStandingTransform == other.mSittingToStandingTransform &&
247 0 : mFrameId == other.mFrameId;
248 : }
249 :
250 : bool operator!=(const VRDisplayInfo& other) const {
251 : return !(*this == other);
252 : }
253 :
254 0 : const VRHMDSensorState& GetSensorState() const
255 : {
256 0 : return mLastSensorState[mFrameId % kVRMaxLatencyFrames];
257 : }
258 : };
259 :
260 0 : struct VRSubmitFrameResultInfo
261 : {
262 0 : VRSubmitFrameResultInfo()
263 0 : : mFrameNum(0),
264 : mWidth(0),
265 0 : mHeight(0)
266 0 : {}
267 :
268 : nsCString mBase64Image;
269 : SurfaceFormat mFormat;
270 : uint32_t mFrameNum;
271 : uint32_t mWidth;
272 : uint32_t mHeight;
273 : };
274 :
275 0 : struct VRControllerInfo
276 : {
277 0 : VRDeviceType GetType() const { return mType; }
278 0 : uint32_t GetControllerID() const { return mControllerID; }
279 0 : const nsCString& GetControllerName() const { return mControllerName; }
280 0 : dom::GamepadMappingType GetMappingType() const { return mMappingType; }
281 0 : dom::GamepadHand GetHand() const { return mHand; }
282 0 : uint32_t GetNumButtons() const { return mNumButtons; }
283 0 : uint32_t GetNumAxes() const { return mNumAxes; }
284 0 : uint32_t GetNumHaptics() const { return mNumHaptics; }
285 :
286 : uint32_t mControllerID;
287 : VRDeviceType mType;
288 : nsCString mControllerName;
289 : dom::GamepadMappingType mMappingType;
290 : dom::GamepadHand mHand;
291 : uint32_t mNumButtons;
292 : uint32_t mNumAxes;
293 : uint32_t mNumHaptics;
294 :
295 : bool operator==(const VRControllerInfo& other) const {
296 : return mType == other.mType &&
297 : mControllerID == other.mControllerID &&
298 : mControllerName == other.mControllerName &&
299 : mMappingType == other.mMappingType &&
300 : mHand == other.mHand &&
301 : mNumButtons == other.mNumButtons &&
302 : mNumAxes == other.mNumAxes &&
303 : mNumHaptics == other.mNumHaptics;
304 : }
305 :
306 : bool operator!=(const VRControllerInfo& other) const {
307 : return !(*this == other);
308 : }
309 : };
310 :
311 : class VRSystemManager {
312 : public:
313 : static uint32_t AllocateDisplayID();
314 :
315 : protected:
316 : static Atomic<uint32_t> sDisplayBase;
317 :
318 : public:
319 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRSystemManager)
320 :
321 : virtual void Destroy() = 0;
322 : virtual void Shutdown() = 0;
323 : virtual bool GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) = 0;
324 : virtual bool GetIsPresenting() = 0;
325 : virtual void HandleInput() = 0;
326 : virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
327 : virtual void ScanForControllers() = 0;
328 : virtual void RemoveControllers() = 0;
329 : virtual void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
330 : double aIntensity, double aDuration, uint32_t aPromiseID) = 0;
331 : virtual void StopVibrateHaptic(uint32_t aControllerIdx) = 0;
332 : void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, bool aTouched,
333 : double aValue);
334 : void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue);
335 : void NewPoseState(uint32_t aIndex, const dom::GamepadPoseState& aPose);
336 : void NewHandChangeEvent(uint32_t aIndex, const dom::GamepadHand aHand);
337 : void AddGamepad(const VRControllerInfo& controllerInfo);
338 : void RemoveGamepad(uint32_t aIndex);
339 :
340 : protected:
341 0 : VRSystemManager() : mControllerCount(0) { }
342 0 : virtual ~VRSystemManager() { }
343 :
344 : uint32_t mControllerCount;
345 : };
346 :
347 : } // namespace gfx
348 : } // namespace mozilla
349 :
350 : #endif /* GFX_VR_H */
|