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