summaryrefslogtreecommitdiff
path: root/dom/vr
diff options
context:
space:
mode:
authorPale Moon <git-repo@palemoon.org>2016-09-01 13:39:08 +0200
committerPale Moon <git-repo@palemoon.org>2016-09-01 13:39:08 +0200
commit3d8ce1a11a7347cc94a937719c4bc8df46fb8d14 (patch)
tree8c26ca375a6312751c00a27e1653fb6f189f0463 /dom/vr
parente449bdb1ec3a82f204bffdd9c3c54069d086eee3 (diff)
downloadpalemoon-gre-3d8ce1a11a7347cc94a937719c4bc8df46fb8d14.tar.gz
Base import of Tycho code (warning: huge commit)
Diffstat (limited to 'dom/vr')
-rw-r--r--dom/vr/VRDevice.cpp311
-rw-r--r--dom/vr/VRDevice.h226
-rw-r--r--dom/vr/moz.build22
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'
+]