diff options
author | Pale Moon <git-repo@palemoon.org> | 2016-09-01 13:39:08 +0200 |
---|---|---|
committer | Pale Moon <git-repo@palemoon.org> | 2016-09-01 13:39:08 +0200 |
commit | 3d8ce1a11a7347cc94a937719c4bc8df46fb8d14 (patch) | |
tree | 8c26ca375a6312751c00a27e1653fb6f189f0463 /dom/vr | |
parent | e449bdb1ec3a82f204bffdd9c3c54069d086eee3 (diff) | |
download | palemoon-gre-3d8ce1a11a7347cc94a937719c4bc8df46fb8d14.tar.gz |
Base import of Tycho code (warning: huge commit)
Diffstat (limited to 'dom/vr')
-rw-r--r-- | dom/vr/VRDevice.cpp | 311 | ||||
-rw-r--r-- | dom/vr/VRDevice.h | 226 | ||||
-rw-r--r-- | dom/vr/moz.build | 22 |
3 files changed, 559 insertions, 0 deletions
diff --git a/dom/vr/VRDevice.cpp b/dom/vr/VRDevice.cpp new file mode 100644 index 000000000..f265adc36 --- /dev/null +++ b/dom/vr/VRDevice.cpp @@ -0,0 +1,311 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* 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/. */ + +#include "nsWrapperCache.h" + +#include "mozilla/dom/Element.h" +#include "mozilla/dom/VRDeviceBinding.h" +#include "mozilla/dom/ElementBinding.h" +#include "mozilla/dom/VRDevice.h" +#include "gfxVR.h" +#include "nsIFrame.h" + +using namespace mozilla::gfx; + +namespace mozilla { +namespace dom { + +VRFieldOfView* +VRFieldOfView::Constructor(const GlobalObject& aGlobal, const VRFieldOfViewInit& aParams, + ErrorResult& aRV) +{ + return new VRFieldOfView(aParams.mUpDegrees, aParams.mRightDegrees, + aParams.mDownDegrees, aParams.mLeftDegrees); +} + +VRFieldOfView* +VRFieldOfView::Constructor(const GlobalObject& aGlobal, + double aUpDegrees, double aRightDegrees, + double aDownDegrees, double aLeftDegrees, + ErrorResult& aRV) +{ + return new VRFieldOfView(aUpDegrees, aRightDegrees, aDownDegrees, + aLeftDegrees); +} + +bool +VRFieldOfView::WrapObject(JSContext* aCx, + JS::MutableHandle<JSObject*> aReflector) +{ + return VRFieldOfViewBinding::Wrap(aCx, this, aReflector); +} + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRPositionState, mParent) +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRPositionState, AddRef) +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRPositionState, Release) + +VRPositionState::VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState) + : mParent(aParent) + , mVRState(aState) +{ + mTimeStamp = aState.timestamp; + + if (aState.flags & gfx::VRHMDInfo::State_Position) { + mPosition = new DOMPoint(mParent, aState.position[0], aState.position[1], aState.position[2], 0.0); + } + + if (aState.flags & gfx::VRHMDInfo::State_Orientation) { + mOrientation = new DOMPoint(mParent, aState.orientation[0], aState.orientation[1], aState.orientation[2], aState.orientation[3]); + } +} + +DOMPoint* +VRPositionState::GetLinearVelocity() +{ + if (!mLinearVelocity) { + mLinearVelocity = new DOMPoint(mParent, mVRState.linearVelocity[0], mVRState.linearVelocity[1], mVRState.linearVelocity[2], 0.0); + } + return mLinearVelocity; +} + +DOMPoint* +VRPositionState::GetLinearAcceleration() +{ + if (!mLinearAcceleration) { + mLinearAcceleration = new DOMPoint(mParent, mVRState.linearAcceleration[0], mVRState.linearAcceleration[1], mVRState.linearAcceleration[2], 0.0); + } + return mLinearAcceleration; +} + +DOMPoint* +VRPositionState::GetAngularVelocity() +{ + if (!mAngularVelocity) { + mAngularVelocity = new DOMPoint(mParent, mVRState.angularVelocity[0], mVRState.angularVelocity[1], mVRState.angularVelocity[2], 0.0); + } + return mAngularVelocity; +} + +DOMPoint* +VRPositionState::GetAngularAcceleration() +{ + if (!mAngularAcceleration) { + mAngularAcceleration = new DOMPoint(mParent, mVRState.angularAcceleration[0], mVRState.angularAcceleration[1], mVRState.angularAcceleration[2], 0.0); + } + return mAngularAcceleration; +} + +JSObject* +VRPositionState::WrapObject(JSContext* aCx) +{ + return VRPositionStateBinding::Wrap(aCx, this); +} + +NS_IMPL_CYCLE_COLLECTING_ADDREF(VRDevice) +NS_IMPL_CYCLE_COLLECTING_RELEASE(VRDevice) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(VRDevice) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRDevice, mParent) + +/* virtual */ JSObject* +HMDVRDevice::WrapObject(JSContext* aCx) +{ + return HMDVRDeviceBinding::Wrap(aCx, this); +} + +/* virtual */ JSObject* +PositionSensorVRDevice::WrapObject(JSContext* aCx) +{ + return PositionSensorVRDeviceBinding::Wrap(aCx, this); +} + +static void +ReleaseHMDInfoRef(void *, nsIAtom*, void *aPropertyValue, void *) +{ + if (aPropertyValue) { + static_cast<VRHMDInfo*>(aPropertyValue)->Release(); + } +} + +void +HMDVRDevice::XxxToggleElementVR(Element& aElement) +{ + VRHMDInfo* hmdPtr = static_cast<VRHMDInfo*>(aElement.GetProperty(nsGkAtoms::vr_state)); + if (hmdPtr) { + aElement.DeleteProperty(nsGkAtoms::vr_state); + return; + } + + nsRefPtr<VRHMDInfo> hmdRef = mHMD; + aElement.SetProperty(nsGkAtoms::vr_state, hmdRef.forget().take(), + ReleaseHMDInfoRef, + true); +} + +namespace { + +gfx::VRHMDInfo::Eye +EyeToEye(const VREye& aEye) +{ + return aEye == VREye::Left ? gfx::VRHMDInfo::Eye_Left : gfx::VRHMDInfo::Eye_Right; +} + +class HMDInfoVRDevice : public HMDVRDevice +{ +public: + HMDInfoVRDevice(nsISupports* aParent, gfx::VRHMDInfo* aHMD) + : HMDVRDevice(aParent, aHMD) + { + // XXX TODO use real names/IDs + mHWID.AppendPrintf("HMDInfo-0x%llx", aHMD); + mDeviceId.AssignLiteral("somedevid"); + mDeviceName.AssignLiteral("HMD Device"); + + mValid = true; + } + + virtual ~HMDInfoVRDevice() { } + + /* If a field of view that is set to all 0's is passed in, + * the recommended field of view for that eye is used. + */ + virtual void SetFieldOfView(const VRFieldOfViewInit& aLeftFOV, + const VRFieldOfViewInit& aRightFOV, + double zNear, double zFar) override + { + gfx::VRFieldOfView left = gfx::VRFieldOfView(aLeftFOV.mUpDegrees, aLeftFOV.mRightDegrees, + aLeftFOV.mDownDegrees, aLeftFOV.mLeftDegrees); + gfx::VRFieldOfView right = gfx::VRFieldOfView(aRightFOV.mUpDegrees, aRightFOV.mRightDegrees, + aRightFOV.mDownDegrees, aRightFOV.mLeftDegrees); + + if (left.IsZero()) + left = mHMD->GetRecommendedEyeFOV(VRHMDInfo::Eye_Left); + if (right.IsZero()) + right = mHMD->GetRecommendedEyeFOV(VRHMDInfo::Eye_Right); + + mHMD->SetFOV(left, right, zNear, zFar); + } + + virtual already_AddRefed<DOMPoint> GetEyeTranslation(VREye aEye) override + { + gfx::Point3D p = mHMD->GetEyeTranslation(EyeToEye(aEye)); + + nsRefPtr<DOMPoint> obj = new DOMPoint(mParent, p.x, p.y, p.z, 0.0); + return obj.forget(); + } + + virtual VRFieldOfView* GetCurrentEyeFieldOfView(VREye aEye) override + { + return CopyFieldOfView(mHMD->GetEyeFOV(EyeToEye(aEye))); + } + + virtual VRFieldOfView* GetRecommendedEyeFieldOfView(VREye aEye) override + { + return CopyFieldOfView(mHMD->GetRecommendedEyeFOV(EyeToEye(aEye))); + } + + virtual VRFieldOfView* GetMaximumEyeFieldOfView(VREye aEye) override + { + return CopyFieldOfView(mHMD->GetMaximumEyeFOV(EyeToEye(aEye))); + } + + virtual already_AddRefed<DOMRect> GetRecommendedEyeRenderRect(VREye aEye) override + { + const IntSize& a(mHMD->SuggestedEyeResolution()); + nsRefPtr<DOMRect> obj = + new DOMRect(mParent, + (aEye == VREye::Left) ? 0 : a.width, 0, + a.width, a.height); + return obj.forget(); + } + +protected: + VRFieldOfView* + CopyFieldOfView(const gfx::VRFieldOfView& aSrc) + { + return new VRFieldOfView(aSrc.upDegrees, aSrc.rightDegrees, + aSrc.downDegrees, aSrc.leftDegrees); + } +}; + +class HMDPositionVRDevice : public PositionSensorVRDevice +{ +public: + HMDPositionVRDevice(nsISupports* aParent, gfx::VRHMDInfo* aHMD) + : PositionSensorVRDevice(aParent) + , mHMD(aHMD) + , mTracking(false) + { + // XXX TODO use real names/IDs + mHWID.AppendPrintf("HMDInfo-0x%llx", aHMD); + mDeviceId.AssignLiteral("somedevid"); + mDeviceName.AssignLiteral("HMD Position Device"); + + mValid = true; + } + + ~HMDPositionVRDevice() + { + if (mTracking) { + mHMD->StopSensorTracking(); + } + } + + virtual already_AddRefed<VRPositionState> GetState(double timeOffset) override + { + if (!mTracking) { + mHMD->StartSensorTracking(); + mTracking = true; + } + + gfx::VRHMDSensorState state = mHMD->GetSensorState(timeOffset); + nsRefPtr<VRPositionState> obj = new VRPositionState(mParent, state); + + return obj.forget(); + } + + virtual void ZeroSensor() override + { + mHMD->ZeroSensor(); + } + +protected: + nsRefPtr<gfx::VRHMDInfo> mHMD; + bool mTracking; +}; + +} // namespace + +bool +VRDevice::CreateAllKnownVRDevices(nsISupports *aParent, nsTArray<nsRefPtr<VRDevice>>& aDevices) +{ + if (!gfx::VRHMDManagerOculus::Init()) { + NS_WARNING("Failed to initialize Oculus HMD Manager"); + return false; + } + + nsTArray<nsRefPtr<gfx::VRHMDInfo>> hmds; + gfx::VRHMDManagerOculus::GetOculusHMDs(hmds); + + for (size_t i = 0; i < hmds.Length(); ++i) { + uint32_t sensorBits = hmds[i]->GetSupportedSensorStateBits(); + aDevices.AppendElement(new HMDInfoVRDevice(aParent, hmds[i])); + + if (sensorBits & + (gfx::VRHMDInfo::State_Position | gfx::VRHMDInfo::State_Orientation)) + { + aDevices.AppendElement(new HMDPositionVRDevice(aParent, hmds[i])); + } + } + + return true; +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/vr/VRDevice.h b/dom/vr/VRDevice.h new file mode 100644 index 000000000..a637e23eb --- /dev/null +++ b/dom/vr/VRDevice.h @@ -0,0 +1,226 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* 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 mozilla_dom_VRDevice_h_ +#define mozilla_dom_VRDevice_h_ + +#include <stdint.h> + +#include "mozilla/ErrorResult.h" +#include "mozilla/dom/TypedArray.h" +#include "mozilla/dom/VRDeviceBinding.h" +#include "mozilla/dom/DOMPoint.h" +#include "mozilla/dom/DOMRect.h" + +#include "nsCOMPtr.h" +#include "nsString.h" +#include "nsTArray.h" +#include "nsWrapperCache.h" + +#include "gfxVR.h" + +namespace mozilla { +namespace dom { + +class Element; + +class VRFieldOfViewReadOnly : public NonRefcountedDOMObject +{ +public: + VRFieldOfViewReadOnly(double aUpDegrees, double aRightDegrees, + double aDownDegrees, double aLeftDegrees) + : mUpDegrees(aUpDegrees) + , mRightDegrees(aRightDegrees) + , mDownDegrees(aDownDegrees) + , mLeftDegrees(aLeftDegrees) + { + } + + double UpDegrees() const { return mUpDegrees; } + double RightDegrees() const { return mRightDegrees; } + double DownDegrees() const { return mDownDegrees; } + double LeftDegrees() const { return mLeftDegrees; } + +protected: + double mUpDegrees; + double mRightDegrees; + double mDownDegrees; + double mLeftDegrees; +}; + +class VRFieldOfView final : public VRFieldOfViewReadOnly +{ +public: + explicit VRFieldOfView(double aUpDegrees = 0.0, double aRightDegrees = 0.0, + double aDownDegrees = 0.0, double aLeftDegrees = 0.0) + : VRFieldOfViewReadOnly(aUpDegrees, aRightDegrees, aDownDegrees, aLeftDegrees) + {} + + static VRFieldOfView* + Constructor(const GlobalObject& aGlobal, const VRFieldOfViewInit& aParams, + ErrorResult& aRv); + + static VRFieldOfView* + Constructor(const GlobalObject& aGlobal, + double aUpDegrees, double aRightDegrees, + double aDownDegrees, double aLeftDegrees, + ErrorResult& aRv); + + bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector); + + void SetUpDegrees(double aVal) { mUpDegrees = aVal; } + void SetRightDegrees(double aVal) { mRightDegrees = aVal; } + void SetDownDegrees(double aVal) { mDownDegrees = aVal; } + void SetLeftDegrees(double aVal) { mLeftDegrees = aVal; } +}; + +class VRPositionState final : public nsWrapperCache +{ + ~VRPositionState() {} +public: + explicit VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState); + + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRPositionState) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRPositionState) + + double TimeStamp() const { return mTimeStamp; } + + bool HasPosition() const { return mPosition != nullptr; } + DOMPoint* GetPosition() const { return mPosition; } + + bool HasOrientation() const { return mOrientation != nullptr; } + DOMPoint* GetOrientation() const { return mOrientation; } + + // these are created lazily + DOMPoint* GetLinearVelocity(); + DOMPoint* GetLinearAcceleration(); + DOMPoint* GetAngularVelocity(); + DOMPoint* GetAngularAcceleration(); + + nsISupports* GetParentObject() const { return mParent; } + virtual JSObject* WrapObject(JSContext* aCx) override; + +protected: + nsCOMPtr<nsISupports> mParent; + + double mTimeStamp; + gfx::VRHMDSensorState mVRState; + + nsRefPtr<DOMPoint> mPosition; + nsRefPtr<DOMPoint> mLinearVelocity; + nsRefPtr<DOMPoint> mLinearAcceleration; + + nsRefPtr<DOMPoint> mOrientation; + nsRefPtr<DOMPoint> mAngularVelocity; + nsRefPtr<DOMPoint> mAngularAcceleration; +}; + +class VRDevice : public nsISupports, + public nsWrapperCache +{ +public: + // create new VRDevice objects for all known underlying gfx::vr devices + static bool CreateAllKnownVRDevices(nsISupports *aParent, nsTArray<nsRefPtr<VRDevice>>& aDevices); + +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(VRDevice) + + void GetHardwareUnitId(nsAString& aHWID) const { aHWID = mHWID; } + void GetDeviceId(nsAString& aDeviceId) const { aDeviceId = mDeviceId; } + void GetDeviceName(nsAString& aDeviceName) const { aDeviceName = mDeviceName; } + + bool IsValid() { return mValid; } + + virtual void Shutdown() { } + + nsISupports* GetParentObject() const + { + return mParent; + } + + enum VRDeviceType { + HMD, + PositionSensor + }; + + VRDeviceType GetType() const { return mType; } + +protected: + VRDevice(nsISupports* aParent, VRDeviceType aType) + : mParent(aParent) + , mType(aType) + , mValid(false) + { + mHWID.AssignLiteral("uknown"); + mDeviceId.AssignLiteral("unknown"); + mDeviceName.AssignLiteral("unknown"); + } + + virtual ~VRDevice() { + Shutdown(); + } + + nsCOMPtr<nsISupports> mParent; + nsString mHWID; + nsString mDeviceId; + nsString mDeviceName; + + VRDeviceType mType; + + bool mValid; +}; + +class HMDVRDevice : public VRDevice +{ +public: + virtual already_AddRefed<DOMPoint> GetEyeTranslation(VREye aEye) = 0; + + virtual void SetFieldOfView(const VRFieldOfViewInit& aLeftFOV, + const VRFieldOfViewInit& aRightFOV, + double zNear, double zFar) = 0; + virtual VRFieldOfView* GetCurrentEyeFieldOfView(VREye aEye) = 0; + virtual VRFieldOfView* GetRecommendedEyeFieldOfView(VREye aEye) = 0; + virtual VRFieldOfView* GetMaximumEyeFieldOfView(VREye aEye) = 0; + virtual already_AddRefed<DOMRect> GetRecommendedEyeRenderRect(VREye aEye) = 0; + + virtual JSObject* WrapObject(JSContext* aCx) override; + + void XxxToggleElementVR(Element& aElement); + + gfx::VRHMDInfo *GetHMD() { return mHMD.get(); } + +protected: + HMDVRDevice(nsISupports* aParent, gfx::VRHMDInfo* aHMD) + : VRDevice(aParent, VRDevice::HMD) + , mHMD(aHMD) + { } + + virtual ~HMDVRDevice() { } + + nsRefPtr<gfx::VRHMDInfo> mHMD; +}; + +class PositionSensorVRDevice : public VRDevice +{ +public: + virtual already_AddRefed<VRPositionState> GetState(double timeOffset) = 0; + + virtual void ZeroSensor() = 0; + + virtual JSObject* WrapObject(JSContext* aCx) override; + +protected: + explicit PositionSensorVRDevice(nsISupports* aParent) + : VRDevice(aParent, VRDevice::PositionSensor) + { } + + virtual ~PositionSensorVRDevice() { } +}; + +} // namespace dom +} // namespace mozilla + +#endif diff --git a/dom/vr/moz.build b/dom/vr/moz.build new file mode 100644 index 000000000..0b23ecffe --- /dev/null +++ b/dom/vr/moz.build @@ -0,0 +1,22 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +EXPORTS.mozilla.dom += [ + 'VRDevice.h', + ] + +UNIFIED_SOURCES = [ + 'VRDevice.cpp', + ] + +FAIL_ON_WARNINGS = True + +include('/ipc/chromium/chromium-config.mozbuild') + +FINAL_LIBRARY = 'xul' +LOCAL_INCLUDES += [ + '/dom/base' +] |