summaryrefslogtreecommitdiffstats
path: root/gfx/vr/VRManager.h
blob: c7a5bb5f0d18426a0342a003d69b8c169c8bd397 (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
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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_MANAGER_H
#define GFX_VR_MANAGER_H

#include "nsIObserver.h"
#include "nsTArray.h"
#include "nsTHashSet.h"
#include "nsThreadUtils.h"
#include "mozilla/Atomics.h"
#include "mozilla/dom/GamepadHandle.h"
#include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
#include "mozilla/Monitor.h"
#include "mozilla/TimeStamp.h"
#include "gfxVR.h"

class nsITimer;
namespace mozilla {
namespace gfx {
class VRLayerParent;
class VRManagerParent;
class VRServiceHost;
class VRThread;
class VRShMem;

enum class VRManagerState : uint32_t {
  Disabled,  // All VRManager activity is stopped
  Idle,  // No VR hardware has been activated, but background tasks are running
  RuntimeDetection,  // Waiting for detection of runtimes without starting up VR
                     // hardware
  Enumeration,       // Waiting for enumeration and startup of VR hardware
  Active,            // VR hardware is active
  Stopping,          // Waiting for the VRService to stop
};

class VRManager : nsIObserver {
 public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSIOBSERVER

  static void ManagerInit();
  static VRManager* Get();
  static VRManager* MaybeGet();

  void AddVRManagerParent(VRManagerParent* aVRManagerParent);
  void RemoveVRManagerParent(VRManagerParent* aVRManagerParent);

  void NotifyVsync(const TimeStamp& aVsyncTimestamp);

  void DetectRuntimes();
  void EnumerateDevices();
  void StopAllHaptics();

  void VibrateHaptic(mozilla::dom::GamepadHandle aGamepadHandle,
                     uint32_t aHapticIndex, double aIntensity, double aDuration,
                     const VRManagerPromise& aPromise);
  void StopVibrateHaptic(mozilla::dom::GamepadHandle aGamepadHandle);
  void NotifyVibrateHapticCompleted(const VRManagerPromise& aPromise);
  void StartVRNavigation(const uint32_t& aDisplayID);
  void StopVRNavigation(const uint32_t& aDisplayID,
                        const TimeDuration& aTimeout);
  void Shutdown();
  void ShutdownVRManagerParents();
#if !defined(MOZ_WIDGET_ANDROID)
  bool RunPuppet(const nsTArray<uint64_t>& aBuffer,
                 VRManagerParent* aManagerParent);
  void ResetPuppet(VRManagerParent* aManagerParent);
  void NotifyPuppetComplete();
#endif
  void AddLayer(VRLayerParent* aLayer);
  void RemoveLayer(VRLayerParent* aLayer);
  void SetGroupMask(uint32_t aGroupMask);
  void SubmitFrame(VRLayerParent* aLayer,
                   const layers::SurfaceDescriptor& aTexture, uint64_t aFrameId,
                   const gfx::Rect& aLeftEyeRect,
                   const gfx::Rect& aRightEyeRect);
  bool IsPresenting();

 private:
  VRManager();
  virtual ~VRManager();
  void Destroy();
  void StartTasks();
  void StopTasks();
  static void TaskTimerCallback(nsITimer* aTimer, void* aClosure);
  void RunTasks();
  void Run1msTasks(double aDeltaTime);
  void Run10msTasks();
  void Run100msTasks();
  uint32_t GetOptimalTaskInterval();
  void ProcessManagerState();
  void ProcessManagerState_Disabled();
  void ProcessManagerState_Idle();
  void ProcessManagerState_Idle_StartRuntimeDetection();
  void ProcessManagerState_Idle_StartEnumeration();
  void ProcessManagerState_DetectRuntimes();
  void ProcessManagerState_Enumeration();
  void ProcessManagerState_Active();
  void ProcessManagerState_Stopping();
  void PullState(const std::function<bool()>& aWaitCondition = nullptr);
  void PushState(const bool aNotifyCond = false);
  static uint32_t AllocateDisplayID();
  void DispatchVRDisplayInfoUpdate();
  void DispatchRuntimeCapabilitiesUpdate();
  void UpdateRequestedDevices();
  void CheckForInactiveTimeout();
#if !defined(MOZ_WIDGET_ANDROID)
  void CheckForPuppetCompletion();
#endif
  void CheckForShutdown();
  void CheckWatchDog();
  void ExpireNavigationTransition();
  void OpenShmem();
  void CloseShmem();
  void UpdateHaptics(double aDeltaTime);
  void ClearHapticSlot(size_t aSlot);
  void StartFrame();
  void ShutdownSubmitThread();
  void StartPresentation();
  void StopPresentation();
  void CancelCurrentSubmitTask();

  void SubmitFrameInternal(const layers::SurfaceDescriptor& aTexture,
                           uint64_t aFrameId, const gfx::Rect& aLeftEyeRect,
                           const gfx::Rect& aRightEyeRect);
  bool SubmitFrame(const layers::SurfaceDescriptor& aTexture, uint64_t aFrameId,
                   const gfx::Rect& aLeftEyeRect,
                   const gfx::Rect& aRightEyeRect);

  Atomic<VRManagerState> mState;
  typedef nsTHashSet<RefPtr<VRManagerParent>> VRManagerParentSet;
  VRManagerParentSet mVRManagerParents;
#if !defined(MOZ_WIDGET_ANDROID)
  VRManagerParentSet mManagerParentsWaitingForPuppetReset;
  RefPtr<VRManagerParent> mManagerParentRunningPuppet;
#endif
  // Weak reference to mLayers entries are cleared in
  // VRLayerParent destructor
  nsTArray<VRLayerParent*> mLayers;

  TimeStamp mLastDisplayEnumerationTime;
  TimeStamp mLastActiveTime;
  TimeStamp mLastTickTime;
  TimeStamp mEarliestRestartTime;
  TimeStamp mVRNavigationTransitionEnd;
  TimeStamp mLastFrameStart[kVRMaxLatencyFrames];
  double mAccumulator100ms;
  bool mRuntimeDetectionRequested;
  bool mRuntimeDetectionCompleted;
  bool mEnumerationRequested;
  bool mEnumerationCompleted;
  bool mVRDisplaysRequested;
  bool mVRDisplaysRequestedNonFocus;
  bool mVRControllersRequested;
  bool mFrameStarted;
  uint32_t mTaskInterval;
  RefPtr<nsITimer> mTaskTimer;
  mozilla::Monitor mCurrentSubmitTaskMonitor MOZ_UNANNOTATED;
  RefPtr<CancelableRunnable> mCurrentSubmitTask;
  uint64_t mLastSubmittedFrameId;
  uint64_t mLastStartedFrame;
  VRDisplayCapabilityFlags mRuntimeSupportFlags;
  bool mAppPaused;

  // Note: mShmem doesn't support RefPtr; thus, do not share this private
  // pointer so that its lifetime can still be controlled by VRManager
  VRShMem* mShmem;
  bool mVRProcessEnabled;

#if !defined(MOZ_WIDGET_ANDROID)
  RefPtr<VRServiceHost> mServiceHost;
#endif

  static Atomic<uint32_t> sDisplayBase;
  RefPtr<VRThread> mSubmitThread;
  VRTelemetry mTelemetry;
  nsTArray<UniquePtr<VRManagerPromise>> mHapticPromises;
  // Duration of haptic pulse time remaining (milliseconds)
  double mHapticPulseRemaining[kVRHapticsMaxCount];

  VRDisplayInfo mDisplayInfo;
  VRDisplayInfo mLastUpdateDisplayInfo;
  VRBrowserState mBrowserState;
  VRHMDSensorState mLastSensorState;
};

}  // namespace gfx
}  // namespace mozilla

#endif  // GFX_VR_MANAGER_H