VRDisplay.h (12409B)
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 #ifndef mozilla_dom_VRDisplay_h_ 8 #define mozilla_dom_VRDisplay_h_ 9 10 #include <stdint.h> 11 12 #include "gfxVR.h" 13 #include "mozilla/DOMEventTargetHelper.h" 14 #include "mozilla/TimeStamp.h" 15 #include "mozilla/dom/DOMPoint.h" 16 #include "mozilla/dom/DOMRect.h" 17 #include "mozilla/dom/Pose.h" 18 #include "mozilla/dom/TypedArray.h" 19 #include "mozilla/dom/VRDisplayBinding.h" 20 #include "nsCOMPtr.h" 21 #include "nsString.h" 22 #include "nsTArray.h" 23 24 namespace mozilla { 25 class ErrorResult; 26 27 namespace gfx { 28 class VRDisplayClient; 29 class VRDisplayPresentation; 30 struct VRFieldOfView; 31 enum class VRDisplayCapabilityFlags : uint16_t; 32 struct VRHMDSensorState; 33 } // namespace gfx 34 namespace dom { 35 class Navigator; 36 37 class VRFieldOfView final : public nsWrapperCache { 38 public: 39 VRFieldOfView(nsISupports* aParent, double aUpDegrees, double aRightDegrees, 40 double aDownDegrees, double aLeftDegrees); 41 VRFieldOfView(nsISupports* aParent, const gfx::VRFieldOfView& aSrc); 42 43 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRFieldOfView) 44 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(VRFieldOfView) 45 46 double UpDegrees() const { return mUpDegrees; } 47 double RightDegrees() const { return mRightDegrees; } 48 double DownDegrees() const { return mDownDegrees; } 49 double LeftDegrees() const { return mLeftDegrees; } 50 51 nsISupports* GetParentObject() const { return mParent; } 52 virtual JSObject* WrapObject(JSContext* aCx, 53 JS::Handle<JSObject*> aGivenProto) override; 54 55 protected: 56 virtual ~VRFieldOfView() = default; 57 58 nsCOMPtr<nsISupports> mParent; 59 60 double mUpDegrees; 61 double mRightDegrees; 62 double mDownDegrees; 63 double mLeftDegrees; 64 }; 65 66 class VRDisplayCapabilities final : public nsWrapperCache { 67 public: 68 VRDisplayCapabilities(nsISupports* aParent, 69 const gfx::VRDisplayCapabilityFlags& aFlags) 70 : mParent(aParent), mFlags(aFlags) {} 71 72 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRDisplayCapabilities) 73 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(VRDisplayCapabilities) 74 75 nsISupports* GetParentObject() const { return mParent; } 76 77 virtual JSObject* WrapObject(JSContext* aCx, 78 JS::Handle<JSObject*> aGivenProto) override; 79 80 bool HasPosition() const; 81 bool HasOrientation() const; 82 bool HasExternalDisplay() const; 83 bool CanPresent() const; 84 uint32_t MaxLayers() const; 85 86 protected: 87 ~VRDisplayCapabilities() = default; 88 nsCOMPtr<nsISupports> mParent; 89 gfx::VRDisplayCapabilityFlags mFlags; 90 }; 91 92 class VRPose final : public Pose { 93 public: 94 VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState); 95 explicit VRPose(nsISupports* aParent); 96 97 virtual void GetPosition(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval, 98 ErrorResult& aRv) override; 99 virtual void GetLinearVelocity(JSContext* aCx, 100 JS::MutableHandle<JSObject*> aRetval, 101 ErrorResult& aRv) override; 102 virtual void GetLinearAcceleration(JSContext* aCx, 103 JS::MutableHandle<JSObject*> aRetval, 104 ErrorResult& aRv) override; 105 virtual void GetOrientation(JSContext* aCx, 106 JS::MutableHandle<JSObject*> aRetval, 107 ErrorResult& aRv) override; 108 virtual void GetAngularVelocity(JSContext* aCx, 109 JS::MutableHandle<JSObject*> aRetval, 110 ErrorResult& aRv) override; 111 virtual void GetAngularAcceleration(JSContext* aCx, 112 JS::MutableHandle<JSObject*> aRetval, 113 ErrorResult& aRv) override; 114 115 virtual JSObject* WrapObject(JSContext* aCx, 116 JS::Handle<JSObject*> aGivenProto) override; 117 118 void Update(const gfx::VRHMDSensorState& aState); 119 120 protected: 121 ~VRPose(); 122 123 gfx::VRHMDSensorState mVRState; 124 }; 125 126 struct VRFrameInfo { 127 VRFrameInfo(); 128 129 void Update(const gfx::VRDisplayInfo& aInfo, 130 const gfx::VRHMDSensorState& aState, float aDepthNear, 131 float aDepthFar); 132 133 void Clear(); 134 bool IsDirty(); 135 136 gfx::VRHMDSensorState mVRState; 137 gfx::Matrix4x4 mLeftProjection; 138 gfx::Matrix4x4 mLeftView; 139 gfx::Matrix4x4 mRightProjection; 140 gfx::Matrix4x4 mRightView; 141 142 /** 143 * In order to avoid leaking information related to the duration of 144 * the user's VR session, we re-base timestamps. 145 * mTimeStampOffset is added to the actual timestamp returned by the 146 * underlying VR platform API when returned through WebVR API's. 147 */ 148 double mTimeStampOffset; 149 }; 150 151 class VRFrameData final : public nsWrapperCache { 152 public: 153 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRFrameData) 154 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRFrameData) 155 156 explicit VRFrameData(nsISupports* aParent); 157 static already_AddRefed<VRFrameData> Constructor(const GlobalObject& aGlobal); 158 159 void Update(const VRFrameInfo& aFrameInfo); 160 161 // WebIDL Members 162 double Timestamp() const; 163 void GetLeftProjectionMatrix(JSContext* aCx, 164 JS::MutableHandle<JSObject*> aRetval, 165 ErrorResult& aRv); 166 void GetLeftViewMatrix(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval, 167 ErrorResult& aRv); 168 void GetRightProjectionMatrix(JSContext* aCx, 169 JS::MutableHandle<JSObject*> aRetval, 170 ErrorResult& aRv); 171 void GetRightViewMatrix(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval, 172 ErrorResult& aRv); 173 174 VRPose* Pose(); 175 176 // WebIDL Boilerplate 177 nsISupports* GetParentObject() const { return mParent; } 178 virtual JSObject* WrapObject(JSContext* aCx, 179 JS::Handle<JSObject*> aGivenProto) override; 180 181 protected: 182 ~VRFrameData(); 183 nsCOMPtr<nsISupports> mParent; 184 185 VRFrameInfo mFrameInfo; 186 RefPtr<VRPose> mPose; 187 JS::Heap<JSObject*> mLeftProjectionMatrix; 188 JS::Heap<JSObject*> mLeftViewMatrix; 189 JS::Heap<JSObject*> mRightProjectionMatrix; 190 JS::Heap<JSObject*> mRightViewMatrix; 191 192 void LazyCreateMatrix(JS::Heap<JSObject*>& aArray, gfx::Matrix4x4& aMat, 193 JSContext* aCx, JS::MutableHandle<JSObject*> aRetval, 194 ErrorResult& aRv); 195 }; 196 197 class VRStageParameters final : public nsWrapperCache { 198 public: 199 VRStageParameters(nsISupports* aParent, 200 const gfx::Matrix4x4& aSittingToStandingTransform, 201 const gfx::Size& aSize); 202 203 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRStageParameters) 204 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRStageParameters) 205 206 void GetSittingToStandingTransform(JSContext* aCx, 207 JS::MutableHandle<JSObject*> aRetval, 208 ErrorResult& aRv); 209 float SizeX() const { return mSize.width; } 210 float SizeZ() const { return mSize.height; } 211 212 nsISupports* GetParentObject() const { return mParent; } 213 virtual JSObject* WrapObject(JSContext* aCx, 214 JS::Handle<JSObject*> aGivenProto) override; 215 216 protected: 217 ~VRStageParameters(); 218 219 nsCOMPtr<nsISupports> mParent; 220 221 gfx::Matrix4x4 mSittingToStandingTransform; 222 JS::Heap<JSObject*> mSittingToStandingTransformArray; 223 gfx::Size mSize; 224 }; 225 226 class VREyeParameters final : public nsWrapperCache { 227 public: 228 VREyeParameters(nsISupports* aParent, const gfx::Point3D& aEyeTranslation, 229 const gfx::VRFieldOfView& aFOV, 230 const gfx::IntSize& aRenderSize); 231 232 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VREyeParameters) 233 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VREyeParameters) 234 235 void GetOffset(JSContext* aCx, JS::MutableHandle<JSObject*> aRetVal, 236 ErrorResult& aRv); 237 238 VRFieldOfView* FieldOfView(); 239 240 uint32_t RenderWidth() const { return mRenderSize.width; } 241 uint32_t RenderHeight() const { return mRenderSize.height; } 242 243 nsISupports* GetParentObject() const { return mParent; } 244 virtual JSObject* WrapObject(JSContext* aCx, 245 JS::Handle<JSObject*> aGivenProto) override; 246 247 protected: 248 ~VREyeParameters(); 249 250 nsCOMPtr<nsISupports> mParent; 251 252 gfx::Point3D mEyeTranslation; 253 gfx::IntSize mRenderSize; 254 JS::Heap<JSObject*> mOffset; 255 RefPtr<VRFieldOfView> mFOV; 256 }; 257 258 class VRDisplay final : public DOMEventTargetHelper, public nsIObserver { 259 public: 260 NS_DECL_ISUPPORTS_INHERITED 261 NS_DECL_NSIOBSERVER 262 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(VRDisplay, DOMEventTargetHelper) 263 264 virtual JSObject* WrapObject(JSContext* aCx, 265 JS::Handle<JSObject*> aGivenProto) override; 266 267 uint32_t PresentingGroups() const; 268 uint32_t GroupMask() const; 269 void SetGroupMask(const uint32_t& aGroupMask); 270 bool IsAnyPresenting(uint32_t aGroupMask) const; 271 bool IsPresenting() const; 272 bool IsConnected() const; 273 274 VRDisplayCapabilities* Capabilities(); 275 VRStageParameters* GetStageParameters(); 276 277 uint32_t DisplayId() const; 278 void GetDisplayName(nsAString& aDisplayName) const; 279 // Replacing the old VRDisplayClient with the newest one to avoid 280 // JS needs to reload to recover VRDisplay when VRService is shutdown at the 281 // backend. 282 void UpdateDisplayClient(already_AddRefed<gfx::VRDisplayClient> aClient); 283 284 static bool RefreshVRDisplays(uint64_t aWindowId); 285 static void UpdateVRDisplays(nsTArray<RefPtr<VRDisplay> >& aDisplays, 286 nsPIDOMWindowInner* aWindow); 287 288 gfx::VRDisplayClient* GetClient() { return mClient; } 289 290 virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye); 291 292 bool GetFrameData(VRFrameData& aFrameData); 293 already_AddRefed<VRPose> GetPose(); 294 void ResetPose(); 295 296 double DepthNear() { return mDepthNear; } 297 298 double DepthFar() { return mDepthFar; } 299 300 void SetDepthNear(double aDepthNear) { 301 // XXX When we start sending depth buffers to VRLayer's we will want 302 // to communicate this with the VRDisplayHost 303 mDepthNear = aDepthNear; 304 } 305 306 void SetDepthFar(double aDepthFar) { 307 // XXX When we start sending depth buffers to VRLayer's we will want 308 // to communicate this with the VRDisplayHost 309 mDepthFar = aDepthFar; 310 } 311 312 already_AddRefed<Promise> RequestPresent(const nsTArray<VRLayer>& aLayers, 313 CallerType aCallerType, 314 ErrorResult& aRv); 315 already_AddRefed<Promise> ExitPresent(ErrorResult& aRv); 316 void GetLayers(nsTArray<VRLayer>& result); 317 void SubmitFrame(); 318 319 int32_t RequestAnimationFrame(mozilla::dom::FrameRequestCallback& aCallback, 320 mozilla::ErrorResult& aError); 321 void CancelAnimationFrame(int32_t aHandle, mozilla::ErrorResult& aError); 322 void StartVRNavigation(); 323 void StartHandlingVRNavigationEvent(); 324 void StopHandlingVRNavigationEvent(); 325 bool IsHandlingVRNavigationEvent(); 326 void OnPresentationGenerationChanged(); 327 328 protected: 329 VRDisplay(nsPIDOMWindowInner* aWindow, gfx::VRDisplayClient* aClient); 330 virtual ~VRDisplay(); 331 virtual void LastRelease() override; 332 333 void ExitPresentInternal(); 334 void Shutdown(); 335 void UpdateFrameInfo(); 336 337 RefPtr<gfx::VRDisplayClient> mClient; 338 339 RefPtr<VRDisplayCapabilities> mCapabilities; 340 RefPtr<VRStageParameters> mStageParameters; 341 342 double mDepthNear; 343 double mDepthFar; 344 345 RefPtr<gfx::VRDisplayPresentation> mPresentation; 346 347 /** 348 * The WebVR 1.1 spec Requires that VRDisplay.getPose and 349 * VRDisplay.getFrameData must return the same values until the next 350 * VRDisplay.submitFrame. mFrameInfo is updated only on the first call to 351 * either function within one frame. Subsequent calls before the next 352 * SubmitFrame or ExitPresent call will use these cached values. 353 */ 354 VRFrameInfo mFrameInfo; 355 356 // Time at which we began expecting VR navigation. 357 TimeStamp mHandlingVRNavigationEventStart; 358 int32_t mVRNavigationEventDepth; 359 bool mShutdown; 360 }; 361 362 } // namespace dom 363 } // namespace mozilla 364 365 #endif