From 7168326772bda9701fe8f704f0b3dee9126c5bb7 Mon Sep 17 00:00:00 2001 From: Daosheng Mu Date: Mon, 24 Oct 2016 18:04:41 +0800 Subject: [PATCH] Bug 1299932 - Part 1: Implement gamepadPose attribute in Gamepad API; r=kip,qdot MozReview-Commit-ID: DiJadVc2TyE --HG-- extra : rebase_source : f4571090518a084b6d4b1e6fccf951510b227fbd --- dom/base/Pose.cpp | 94 ++++++++++++++ dom/base/Pose.h | 67 ++++++++++ dom/base/Timeout.cpp | 1 - dom/base/Timeout.h | 2 + dom/base/moz.build | 2 + dom/gamepad/Gamepad.cpp | 18 ++- dom/gamepad/Gamepad.h | 8 ++ dom/gamepad/GamepadPose.cpp | 120 ++++++++++++++++++ dom/gamepad/GamepadPose.h | 58 +++++++++ dom/gamepad/GamepadPoseState.h | 88 +++++++++++++ dom/gamepad/ipc/GamepadMessageUtils.h | 1 + dom/gamepad/moz.build | 3 + .../mochitest/general/test_interfaces.html | 4 + dom/vr/VRDisplay.cpp | 120 +++--------------- dom/vr/VRDisplay.h | 51 +++----- dom/webidl/Gamepad.webidl | 6 + dom/webidl/GamepadPose.webidl | 13 ++ dom/webidl/Pose.webidl | 23 ++++ dom/webidl/VRDisplay.webidl | 16 +-- dom/webidl/moz.build | 2 + modules/libpref/init/all.js | 1 + 21 files changed, 551 insertions(+), 147 deletions(-) create mode 100644 dom/base/Pose.cpp create mode 100644 dom/base/Pose.h create mode 100644 dom/gamepad/GamepadPose.cpp create mode 100644 dom/gamepad/GamepadPose.h create mode 100644 dom/gamepad/GamepadPoseState.h create mode 100644 dom/webidl/GamepadPose.webidl create mode 100644 dom/webidl/Pose.webidl diff --git a/dom/base/Pose.cpp b/dom/base/Pose.cpp new file mode 100644 index 000000000000..218b29cdc700 --- /dev/null +++ b/dom/base/Pose.cpp @@ -0,0 +1,94 @@ +/* -*- 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/. */ + +#include "mozilla/HoldDropJSObjects.h" +#include "mozilla/dom/TypedArray.h" +#include "mozilla/dom/PoseBinding.h" +#include "mozilla/dom/Pose.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_CLASS(Pose) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Pose) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent) + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER + tmp->mPosition = nullptr; + tmp->mLinearVelocity = nullptr; + tmp->mLinearAcceleration = nullptr; + tmp->mOrientation = nullptr; + tmp->mAngularVelocity = nullptr; + tmp->mAngularAcceleration = nullptr; +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Pose) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Pose) + NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPosition) + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLinearVelocity) + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLinearAcceleration) + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mOrientation) + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAngularVelocity) + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAngularAcceleration) +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(Pose, AddRef) +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(Pose, Release) + + +Pose::Pose(nsISupports* aParent) + : mParent(aParent), + mPosition(nullptr), + mLinearVelocity(nullptr), + mLinearAcceleration(nullptr), + mOrientation(nullptr), + mAngularVelocity(nullptr), + mAngularAcceleration(nullptr) +{ + mozilla::HoldJSObjects(this); +} + +Pose::~Pose() +{ + mozilla::DropJSObjects(this); +} + +nsISupports* +Pose::GetParentObject() const +{ + return mParent; +} + +void +Pose::SetFloat32Array(JSContext* aJSContext, JS::MutableHandle aRetVal, + JS::Heap& aObj, float* aVal, uint32_t sizeOfVal, + bool bCreate, ErrorResult& aRv) +{ + if (bCreate) { + aObj = Float32Array::Create(aJSContext, this, + sizeOfVal, aVal); + if (!aObj) { + aRv.NoteJSContextException(aJSContext); + return; + } + } + + aRetVal.set(aObj); +} + +/* virtual */ JSObject* +Pose::WrapObject(JSContext* aJSContext, JS::Handle aGivenProto) +{ + return PoseBinding::Wrap(aJSContext, this, aGivenProto); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/base/Pose.h b/dom/base/Pose.h new file mode 100644 index 000000000000..1d3539672bfb --- /dev/null +++ b/dom/base/Pose.h @@ -0,0 +1,67 @@ +/* -*- 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 mozilla_dom_Pose_h +#define mozilla_dom_Pose_h + +#include "nsWrapperCache.h" + +namespace mozilla { +namespace dom { + +class Pose : public nsWrapperCache +{ +public: + explicit Pose(nsISupports* aParent); + + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Pose) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(Pose) + + nsISupports* GetParentObject() const; + + virtual void GetPosition(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) = 0; + virtual void GetLinearVelocity(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) = 0; + virtual void GetLinearAcceleration(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) = 0; + virtual void GetOrientation(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) = 0; + virtual void GetAngularVelocity(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) = 0; + virtual void GetAngularAcceleration(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) = 0; + + virtual JSObject* WrapObject(JSContext* aJSContext, + JS::Handle aGivenProto) override; + +protected: + virtual ~Pose(); + + void SetFloat32Array(JSContext* aJSContext, JS::MutableHandle aRetVal, + JS::Heap& aObj, float* aVal, uint32_t sizeOfVal, + bool bCreate, ErrorResult& aRv); + + nsCOMPtr mParent; + + JS::Heap mPosition; + JS::Heap mLinearVelocity; + JS::Heap mLinearAcceleration; + JS::Heap mOrientation; + JS::Heap mAngularVelocity; + JS::Heap mAngularAcceleration; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_Pose_h diff --git a/dom/base/Timeout.cpp b/dom/base/Timeout.cpp index ebad378e7aca..35971a151ec6 100644 --- a/dom/base/Timeout.cpp +++ b/dom/base/Timeout.cpp @@ -9,7 +9,6 @@ #include "nsGlobalWindow.h" #include "nsITimeoutHandler.h" #include "nsITimer.h" -#include "nsPIDOMWindow.h" namespace mozilla { namespace dom { diff --git a/dom/base/Timeout.h b/dom/base/Timeout.h index 9a392cb43145..e929f3dd134e 100644 --- a/dom/base/Timeout.h +++ b/dom/base/Timeout.h @@ -11,11 +11,13 @@ #include "mozilla/TimeStamp.h" #include "nsCOMPtr.h" #include "nsCycleCollectionParticipant.h" +#include "nsPIDOMWindow.h" class nsGlobalWindow; class nsIPrincipal; class nsITimeoutHandler; class nsITimer; +class nsIEventTarget; namespace mozilla { namespace dom { diff --git a/dom/base/moz.build b/dom/base/moz.build index ef1a5a17771a..870a5d277130 100644 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -201,6 +201,7 @@ EXPORTS.mozilla.dom += [ 'NodeInfoInlines.h', 'NodeIterator.h', 'PartialSHistory.h', + 'Pose.h', 'ProcessGlobal.h', 'ResponsiveImageSelector.h', 'SameProcessMessageQueue.h', @@ -345,6 +346,7 @@ UNIFIED_SOURCES += [ 'nsXMLContentSerializer.cpp', 'nsXMLNameSpaceMap.cpp', 'PartialSHistory.cpp', + 'Pose.cpp', 'PostMessageEvent.cpp', 'ProcessGlobal.cpp', 'ResponsiveImageSelector.cpp', diff --git a/dom/gamepad/Gamepad.cpp b/dom/gamepad/Gamepad.cpp index 69409cf415ca..0c59b190e077 100644 --- a/dom/gamepad/Gamepad.cpp +++ b/dom/gamepad/Gamepad.cpp @@ -21,7 +21,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Gamepad) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Gamepad, mParent, mButtons) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Gamepad, mParent, mButtons, mPose) void Gamepad::UpdateTimestamp() @@ -52,6 +52,7 @@ Gamepad::Gamepad(nsISupports* aParent, mButtons.InsertElementAt(i, new GamepadButton(mParent)); } mAxes.InsertElementsAt(0, aNumAxes, 0.0f); + mPose = new GamepadPose(aParent); UpdateTimestamp(); } @@ -87,9 +88,17 @@ Gamepad::SetAxis(uint32_t aAxis, double aValue) UpdateTimestamp(); } +void +Gamepad::SetPose(const GamepadPoseState& aPose) +{ + mPose->SetPoseState(aPose); +} + void Gamepad::SyncState(Gamepad* aOther) { + const char* kGamepadExtEnabledPref = "dom.gamepad.extensions.enabled"; + if (mButtons.Length() != aOther->mButtons.Length() || mAxes.Length() != aOther->mAxes.Length()) { return; @@ -100,6 +109,7 @@ Gamepad::SyncState(Gamepad* aOther) mButtons[i]->SetPressed(aOther->mButtons[i]->Pressed()); mButtons[i]->SetValue(aOther->mButtons[i]->Value()); } + bool changed = false; for (uint32_t i = 0; i < mAxes.Length(); ++i) { changed = changed || (mAxes[i] != aOther->mAxes[i]); @@ -108,6 +118,12 @@ Gamepad::SyncState(Gamepad* aOther) if (changed) { GamepadBinding::ClearCachedAxesValue(this); } + + if (Preferences::GetBool(kGamepadExtEnabledPref)) { + MOZ_ASSERT(aOther->GetPose()); + mPose->SetPoseState(aOther->GetPose()->GetPoseState()); + } + UpdateTimestamp(); } diff --git a/dom/gamepad/Gamepad.h b/dom/gamepad/Gamepad.h index 38265ac34c59..e388348f0fcf 100644 --- a/dom/gamepad/Gamepad.h +++ b/dom/gamepad/Gamepad.h @@ -10,6 +10,7 @@ #include "mozilla/ErrorResult.h" #include "mozilla/dom/GamepadBinding.h" #include "mozilla/dom/GamepadButton.h" +#include "mozilla/dom/GamepadPose.h" #include "mozilla/dom/Performance.h" #include #include "nsCOMPtr.h" @@ -49,6 +50,7 @@ public: void SetButton(uint32_t aButton, bool aPressed, double aValue); void SetAxis(uint32_t aAxis, double aValue); void SetIndex(uint32_t aIndex); + void SetPose(const GamepadPoseState& aPose); // Make the state of this gamepad equivalent to other. void SyncState(Gamepad* aOther); @@ -99,6 +101,11 @@ public: aAxes = mAxes; } + GamepadPose* GetPose() const + { + return mPose; + } + private: virtual ~Gamepad() {} void UpdateTimestamp(); @@ -118,6 +125,7 @@ protected: nsTArray> mButtons; nsTArray mAxes; DOMHighResTimeStamp mTimestamp; + RefPtr mPose; }; } // namespace dom diff --git a/dom/gamepad/GamepadPose.cpp b/dom/gamepad/GamepadPose.cpp new file mode 100644 index 000000000000..25d157b8b38d --- /dev/null +++ b/dom/gamepad/GamepadPose.cpp @@ -0,0 +1,120 @@ +/* -*- 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/. */ + +#include "nsWrapperCache.h" + +#include "mozilla/HoldDropJSObjects.h" +#include "mozilla/dom/GamepadPoseBinding.h" +#include "mozilla/dom/GamepadPose.h" + +namespace mozilla { +namespace dom { + +GamepadPose::GamepadPose(nsISupports* aParent, const GamepadPoseState& aState) + : Pose(aParent), + mPoseState(aState) +{ + mozilla::HoldJSObjects(this); +} + +GamepadPose::GamepadPose(nsISupports* aParent) + : Pose(aParent) +{ + mozilla::HoldJSObjects(this); + mPoseState.Clear(); +} + +GamepadPose::~GamepadPose() +{ + mozilla::DropJSObjects(this); +} + +/* virtual */ JSObject* +GamepadPose::WrapObject(JSContext* aJSContext, JS::Handle aGivenProto) +{ + return GamepadPoseBinding::Wrap(aJSContext, this, aGivenProto); +} + +bool +GamepadPose::HasOrientation() const +{ + return bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Position); +} + +bool +GamepadPose::HasPosition() const +{ + return bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Orientation); +} + +void +GamepadPose::GetPosition(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) +{ + SetFloat32Array(aJSContext, aRetval, mPosition, mPoseState.position, 3, + bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Position), aRv); +} + +void +GamepadPose::GetLinearVelocity(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) +{ + SetFloat32Array(aJSContext, aRetval, mLinearVelocity, mPoseState.linearVelocity, 3, + bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Position), aRv); +} + +void +GamepadPose::GetLinearAcceleration(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) +{ + SetFloat32Array(aJSContext, aRetval, mLinearAcceleration, mPoseState.linearAcceleration, 3, + bool(mPoseState.flags & GamepadCapabilityFlags::Cap_LinearAcceleration), aRv); +} + +void +GamepadPose::GetOrientation(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) +{ + SetFloat32Array(aJSContext, aRetval, mOrientation, mPoseState.orientation, 4, + bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Orientation), aRv); +} + +void +GamepadPose::GetAngularVelocity(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) +{ + SetFloat32Array(aJSContext, aRetval, mAngularVelocity, mPoseState.angularVelocity, 3, + bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Orientation), aRv); +} + +void +GamepadPose::GetAngularAcceleration(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) +{ + SetFloat32Array(aJSContext, aRetval, mAngularAcceleration, mPoseState.angularAcceleration, 3, + bool(mPoseState.flags & GamepadCapabilityFlags::Cap_AngularAcceleration), aRv); +} + +void +GamepadPose::SetPoseState(const GamepadPoseState& aPose) +{ + mPoseState = aPose; +} + +const GamepadPoseState& +GamepadPose::GetPoseState() +{ + return mPoseState; +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/gamepad/GamepadPose.h b/dom/gamepad/GamepadPose.h new file mode 100644 index 000000000000..fa32df3fcede --- /dev/null +++ b/dom/gamepad/GamepadPose.h @@ -0,0 +1,58 @@ +/* -*- 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 mozilla_dom_gamepad_GamepadPose_h +#define mozilla_dom_gamepad_GamepadPose_h + +#include "mozilla/TypedEnumBits.h" +#include "mozilla/dom/Pose.h" +#include "mozilla/dom/GamepadPoseState.h" + +namespace mozilla { +namespace dom { + +class GamepadPose final : public Pose +{ +public: + GamepadPose(nsISupports* aParent, const GamepadPoseState& aState); + explicit GamepadPose(nsISupports* aParent); + + virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + + bool HasOrientation() const; + bool HasPosition() const; + virtual void GetPosition(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; + virtual void GetLinearVelocity(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; + virtual void GetLinearAcceleration(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; + virtual void GetOrientation(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; + virtual void GetAngularVelocity(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; + virtual void GetAngularAcceleration(JSContext* aJSContext, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; + void SetPoseState(const GamepadPoseState& aPose); + const GamepadPoseState& GetPoseState(); + +private: + virtual ~GamepadPose(); + + nsCOMPtr mParent; + GamepadPoseState mPoseState; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_gamepad_GamepadPose_h diff --git a/dom/gamepad/GamepadPoseState.h b/dom/gamepad/GamepadPoseState.h new file mode 100644 index 000000000000..958b26139fda --- /dev/null +++ b/dom/gamepad/GamepadPoseState.h @@ -0,0 +1,88 @@ + +#ifndef mozilla_dom_gamepad_GamepadPoseState_h_ +#define mozilla_dom_gamepad_GamepadPoseState_h_ + +namespace mozilla{ +namespace dom{ + +enum class GamepadCapabilityFlags : uint16_t { + Cap_None = 0, + /** + * Cap_Position is set if the Gamepad is capable of tracking its position. + */ + Cap_Position = 1 << 1, + /** + * Cap_Orientation is set if the Gamepad is capable of tracking its orientation. + */ + Cap_Orientation = 1 << 2, + /** + * Cap_AngularAcceleration is set if the Gamepad is capable of tracking its + * angular acceleration. + */ + Cap_AngularAcceleration = 1 << 3, + /** + * Cap_LinearAcceleration is set if the Gamepad is capable of tracking its + * linear acceleration. + */ + Cap_LinearAcceleration = 1 << 4, + /** + * Cap_All used for validity checking during IPC serialization + */ + Cap_All = (1 << 5) - 1 +}; + +MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(GamepadCapabilityFlags) + +struct GamepadPoseState +{ + GamepadCapabilityFlags flags; + float orientation[4]; + float position[3]; + float angularVelocity[3]; + float angularAcceleration[3]; + float linearVelocity[3]; + float linearAcceleration[3]; + + GamepadPoseState() + { + Clear(); + } + + bool operator==(const GamepadPoseState& aPose) const + { + return flags == aPose.flags + && orientation[0] == aPose.orientation[0] + && orientation[1] == aPose.orientation[1] + && orientation[2] == aPose.orientation[2] + && orientation[3] == aPose.orientation[3] + && position[0] == aPose.position[0] + && position[1] == aPose.position[1] + && position[2] == aPose.position[2] + && angularVelocity[0] == aPose.angularVelocity[0] + && angularVelocity[1] == aPose.angularVelocity[1] + && angularVelocity[2] == aPose.angularVelocity[2] + && angularAcceleration[0] == aPose.angularAcceleration[0] + && angularAcceleration[1] == aPose.angularAcceleration[1] + && angularAcceleration[2] == aPose.angularAcceleration[2] + && linearVelocity[0] == aPose.linearVelocity[0] + && linearVelocity[1] == aPose.linearVelocity[1] + && linearVelocity[2] == aPose.linearVelocity[2] + && linearAcceleration[0] == aPose.linearAcceleration[0] + && linearAcceleration[1] == aPose.linearAcceleration[1] + && linearAcceleration[2] == aPose.linearAcceleration[2]; + } + + bool operator!=(const GamepadPoseState& aPose) const + { + return !(*this == aPose); + } + + void Clear() { + memset(this, 0, sizeof(GamepadPoseState)); + } +}; + +}// namespace dom +}// namespace mozilla + +#endif // mozilla_dom_gamepad_GamepadPoseState_h_ \ No newline at end of file diff --git a/dom/gamepad/ipc/GamepadMessageUtils.h b/dom/gamepad/ipc/GamepadMessageUtils.h index f26a8d51fa39..cc8cba97b5d2 100644 --- a/dom/gamepad/ipc/GamepadMessageUtils.h +++ b/dom/gamepad/ipc/GamepadMessageUtils.h @@ -4,6 +4,7 @@ #include "ipc/IPCMessageUtils.h" #include "mozilla/dom/GamepadServiceType.h" +#include "mozilla/dom/GamepadPoseState.h" namespace IPC { diff --git a/dom/gamepad/moz.build b/dom/gamepad/moz.build index 99ec38655088..a809d1ebaa04 100644 --- a/dom/gamepad/moz.build +++ b/dom/gamepad/moz.build @@ -11,6 +11,7 @@ IPDL_SOURCES += [ ] EXPORTS.mozilla.dom += [ + 'GamepadPoseState.h', 'ipc/GamepadMessageUtils.h', 'ipc/GamepadServiceType.h' ] @@ -22,6 +23,7 @@ if CONFIG['MOZ_GAMEPAD']: 'GamepadManager.h', 'GamepadMonitoring.h', 'GamepadPlatformService.h', + 'GamepadPose.h', 'GamepadServiceTest.h', 'ipc/GamepadEventChannelChild.h', 'ipc/GamepadEventChannelParent.h', @@ -35,6 +37,7 @@ if CONFIG['MOZ_GAMEPAD']: 'GamepadManager.cpp', 'GamepadMonitoring.cpp', 'GamepadPlatformService.cpp', + 'GamepadPose.cpp', 'GamepadServiceTest.cpp', 'ipc/GamepadEventChannelChild.cpp', 'ipc/GamepadEventChannelParent.cpp', diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index 043181a3cae8..e349666042e0 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -404,6 +404,8 @@ var interfaceNamesInGlobalScope = "GamepadButton", // IMPORTANT: Do not change this list without review from a DOM peer! "GamepadEvent", +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "GamepadPose", release: false}, // IMPORTANT: Do not change this list without review from a DOM peer! "HashChangeEvent", // IMPORTANT: Do not change this list without review from a DOM peer! @@ -774,6 +776,8 @@ var interfaceNamesInGlobalScope = "PopupBlockedEvent", // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PopupBoxObject", xbl: true}, +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "Pose", release: false}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PresentationDeviceInfoManager", disabled: true}, diff --git a/dom/vr/VRDisplay.cpp b/dom/vr/VRDisplay.cpp index ee0ff4083b59..11113cd99301 100644 --- a/dom/vr/VRDisplay.cpp +++ b/dom/vr/VRDisplay.cpp @@ -256,59 +256,16 @@ VRDisplayCapabilities::WrapObject(JSContext* aCx, JS::Handle aGivenPr return VRDisplayCapabilitiesBinding::Wrap(aCx, this, aGivenProto); } -NS_IMPL_CYCLE_COLLECTION_CLASS(VRPose) - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(VRPose) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent) - NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER - tmp->mPosition = nullptr; - tmp->mLinearVelocity = nullptr; - tmp->mLinearAcceleration = nullptr; - tmp->mOrientation = nullptr; - tmp->mAngularVelocity = nullptr; - tmp->mAngularAcceleration = nullptr; -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(VRPose) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(VRPose) - NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPosition) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLinearVelocity) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLinearAcceleration) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mOrientation) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAngularVelocity) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAngularAcceleration) -NS_IMPL_CYCLE_COLLECTION_TRACE_END - -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRPose, AddRef) -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRPose, Release) - VRPose::VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState) - : mParent(aParent) + : Pose(aParent) , mVRState(aState) - , mPosition(nullptr) - , mLinearVelocity(nullptr) - , mLinearAcceleration(nullptr) - , mOrientation(nullptr) - , mAngularVelocity(nullptr) - , mAngularAcceleration(nullptr) { mFrameId = aState.inputFrameID; mozilla::HoldJSObjects(this); } VRPose::VRPose(nsISupports* aParent) - : mParent(aParent) - , mPosition(nullptr) - , mLinearVelocity(nullptr) - , mLinearAcceleration(nullptr) - , mOrientation(nullptr) - , mAngularVelocity(nullptr) - , mAngularAcceleration(nullptr) + : Pose(aParent) { mFrameId = 0; mVRState.Clear(); @@ -325,15 +282,9 @@ VRPose::GetPosition(JSContext* aCx, JS::MutableHandle aRetval, ErrorResult& aRv) { - if (!mPosition && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) { - // Lazily create the Float32Array - mPosition = dom::Float32Array::Create(aCx, this, 3, mVRState.position); - if (!mPosition) { - aRv.NoteJSContextException(aCx); - return; - } - } - aRetval.set(mPosition); + SetFloat32Array(aCx, aRetval, mPosition, mVRState.position, 3, + !mPosition && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position), + aRv); } void @@ -341,15 +292,9 @@ VRPose::GetLinearVelocity(JSContext* aCx, JS::MutableHandle aRetval, ErrorResult& aRv) { - if (!mLinearVelocity && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) { - // Lazily create the Float32Array - mLinearVelocity = dom::Float32Array::Create(aCx, this, 3, mVRState.linearVelocity); - if (!mLinearVelocity) { - aRv.NoteJSContextException(aCx); - return; - } - } - aRetval.set(mLinearVelocity); + SetFloat32Array(aCx, aRetval, mLinearVelocity, mVRState.linearVelocity, 3, + !mLinearVelocity && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position), + aRv); } void @@ -357,15 +302,10 @@ VRPose::GetLinearAcceleration(JSContext* aCx, JS::MutableHandle aRetval, ErrorResult& aRv) { - if (!mLinearAcceleration && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_LinearAcceleration) { - // Lazily create the Float32Array - mLinearAcceleration = dom::Float32Array::Create(aCx, this, 3, mVRState.linearAcceleration); - if (!mLinearAcceleration) { - aRv.NoteJSContextException(aCx); - return; - } - } - aRetval.set(mLinearAcceleration); + SetFloat32Array(aCx, aRetval, mLinearAcceleration, mVRState.linearAcceleration, 3, + !mLinearAcceleration && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_LinearAcceleration), + aRv); + } void @@ -373,15 +313,9 @@ VRPose::GetOrientation(JSContext* aCx, JS::MutableHandle aRetval, ErrorResult& aRv) { - if (!mOrientation && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) { - // Lazily create the Float32Array - mOrientation = dom::Float32Array::Create(aCx, this, 4, mVRState.orientation); - if (!mOrientation) { - aRv.NoteJSContextException(aCx); - return; - } - } - aRetval.set(mOrientation); + SetFloat32Array(aCx, aRetval, mOrientation, mVRState.orientation, 4, + !mOrientation && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation), + aRv); } void @@ -389,15 +323,9 @@ VRPose::GetAngularVelocity(JSContext* aCx, JS::MutableHandle aRetval, ErrorResult& aRv) { - if (!mAngularVelocity && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) { - // Lazily create the Float32Array - mAngularVelocity = dom::Float32Array::Create(aCx, this, 3, mVRState.angularVelocity); - if (!mAngularVelocity) { - aRv.NoteJSContextException(aCx); - return; - } - } - aRetval.set(mAngularVelocity); + SetFloat32Array(aCx, aRetval, mAngularVelocity, mVRState.angularVelocity, 3, + !mAngularVelocity && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation), + aRv); } void @@ -405,15 +333,9 @@ VRPose::GetAngularAcceleration(JSContext* aCx, JS::MutableHandle aRetval, ErrorResult& aRv) { - if (!mAngularAcceleration && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_AngularAcceleration) { - // Lazily create the Float32Array - mAngularAcceleration = dom::Float32Array::Create(aCx, this, 3, mVRState.angularAcceleration); - if (!mAngularAcceleration) { - aRv.NoteJSContextException(aCx); - return; - } - } - aRetval.set(mAngularAcceleration); + SetFloat32Array(aCx, aRetval, mAngularAcceleration, mVRState.angularAcceleration, 3, + !mAngularAcceleration && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_AngularAcceleration), + aRv); } JSObject* diff --git a/dom/vr/VRDisplay.h b/dom/vr/VRDisplay.h index dc8df7c3b5a8..378efc98ed1d 100644 --- a/dom/vr/VRDisplay.h +++ b/dom/vr/VRDisplay.h @@ -15,11 +15,11 @@ #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/dom/DOMPoint.h" #include "mozilla/dom/DOMRect.h" +#include "mozilla/dom/Pose.h" #include "nsCOMPtr.h" #include "nsString.h" #include "nsTArray.h" -#include "nsWrapperCache.h" #include "gfxVR.h" @@ -95,54 +95,41 @@ protected: gfx::VRDisplayCapabilityFlags mFlags; }; -class VRPose final : public nsWrapperCache +class VRPose final : public Pose { public: VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState); explicit VRPose(nsISupports* aParent); - NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRPose) - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRPose) - uint32_t FrameID() const { return mFrameId; } - void GetPosition(JSContext* aCx, - JS::MutableHandle aRetval, - ErrorResult& aRv); - void GetLinearVelocity(JSContext* aCx, - JS::MutableHandle aRetval, - ErrorResult& aRv); - void GetLinearAcceleration(JSContext* aCx, - JS::MutableHandle aRetval, - ErrorResult& aRv); - void GetOrientation(JSContext* aCx, - JS::MutableHandle aRetval, - ErrorResult& aRv); - void GetAngularVelocity(JSContext* aCx, - JS::MutableHandle aRetval, - ErrorResult& aRv); - void GetAngularAcceleration(JSContext* aCx, + virtual void GetPosition(JSContext* aCx, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; + virtual void GetLinearVelocity(JSContext* aCx, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; + virtual void GetLinearAcceleration(JSContext* aCx, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; + virtual void GetOrientation(JSContext* aCx, JS::MutableHandle aRetval, - ErrorResult& aRv); + ErrorResult& aRv) override; + virtual void GetAngularVelocity(JSContext* aCx, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; + virtual void GetAngularAcceleration(JSContext* aCx, + JS::MutableHandle aRetval, + ErrorResult& aRv) override; - nsISupports* GetParentObject() const { return mParent; } virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; protected: ~VRPose(); - nsCOMPtr mParent; uint32_t mFrameId; gfx::VRHMDSensorState mVRState; - - JS::Heap mPosition; - JS::Heap mLinearVelocity; - JS::Heap mLinearAcceleration; - JS::Heap mOrientation; - JS::Heap mAngularVelocity; - JS::Heap mAngularAcceleration; - }; struct VRFrameInfo diff --git a/dom/webidl/Gamepad.webidl b/dom/webidl/Gamepad.webidl index 9779c71b85b5..d36df735d06f 100644 --- a/dom/webidl/Gamepad.webidl +++ b/dom/webidl/Gamepad.webidl @@ -56,4 +56,10 @@ interface Gamepad { * Timestamp from when the data of this device was last updated. */ readonly attribute DOMHighResTimeStamp timestamp; + + /** + * The current pose of the device, a GamepadPose. + */ + [Pref="dom.gamepad.extensions.enabled"] + readonly attribute GamepadPose? pose; }; diff --git a/dom/webidl/GamepadPose.webidl b/dom/webidl/GamepadPose.webidl new file mode 100644 index 000000000000..254ea81a5965 --- /dev/null +++ b/dom/webidl/GamepadPose.webidl @@ -0,0 +1,13 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Pref="dom.gamepad.extensions.enabled", + HeaderFile="mozilla/dom/GamepadPose.h"] +interface GamepadPose : Pose +{ + readonly attribute boolean hasOrientation; + readonly attribute boolean hasPosition; +}; diff --git a/dom/webidl/Pose.webidl b/dom/webidl/Pose.webidl new file mode 100644 index 000000000000..8c71dd797b7d --- /dev/null +++ b/dom/webidl/Pose.webidl @@ -0,0 +1,23 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +interface Pose +{ + /** + * position, linearVelocity, and linearAcceleration are 3-component vectors. + * position is relative to a sitting space. Transforming this point with + * VRStageParameters.sittingToStandingTransform converts this to standing space. + */ + [Constant, Throws] readonly attribute Float32Array? position; + [Constant, Throws] readonly attribute Float32Array? linearVelocity; + [Constant, Throws] readonly attribute Float32Array? linearAcceleration; + + /* orientation is a 4-entry array representing the components of a quaternion. */ + [Constant, Throws] readonly attribute Float32Array? orientation; + /* angularVelocity and angularAcceleration are the components of 3-dimensional vectors. */ + [Constant, Throws] readonly attribute Float32Array? angularVelocity; + [Constant, Throws] readonly attribute Float32Array? angularAcceleration; +}; diff --git a/dom/webidl/VRDisplay.webidl b/dom/webidl/VRDisplay.webidl index f5ae848922d0..0979123f5a08 100644 --- a/dom/webidl/VRDisplay.webidl +++ b/dom/webidl/VRDisplay.webidl @@ -116,21 +116,9 @@ interface VRStageParameters { [Pref="dom.vr.enabled", HeaderFile="mozilla/dom/VRDisplay.h"] -interface VRPose { - /** - * position, linearVelocity, and linearAcceleration are 3-component vectors. - * position is relative to a sitting space. Transforming this point with - * VRStageParameters.sittingToStandingTransform converts this to standing space. - */ - [Constant, Throws] readonly attribute Float32Array? position; - [Constant, Throws] readonly attribute Float32Array? linearVelocity; - [Constant, Throws] readonly attribute Float32Array? linearAcceleration; +interface VRPose : Pose +{ - /* orientation is a 4-entry array representing the components of a quaternion. */ - [Constant, Throws] readonly attribute Float32Array? orientation; - /* angularVelocity and angularAcceleration are the components of 3-dimensional vectors. */ - [Constant, Throws] readonly attribute Float32Array? angularVelocity; - [Constant, Throws] readonly attribute Float32Array? angularAcceleration; }; [Constructor, diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 67338894a380..cf4f8e981034 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -367,6 +367,7 @@ WEBIDL_FILES = [ 'PluginArray.webidl', 'PointerEvent.webidl', 'PopupBoxObject.webidl', + 'Pose.webidl', 'Position.webidl', 'PositionError.webidl', 'Presentation.webidl', @@ -647,6 +648,7 @@ if CONFIG['MOZ_WEBSPEECH']: if CONFIG['MOZ_GAMEPAD']: WEBIDL_FILES += [ 'Gamepad.webidl', + 'GamepadPose.webidl', 'GamepadServiceTest.webidl' ] diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 35700b4d52fa..0d6054c20c07 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -203,6 +203,7 @@ pref("dom.gamepad.non_standard_events.enabled", false); #else pref("dom.gamepad.non_standard_events.enabled", true); #endif +pref("dom.gamepad.extensions.enabled", false); // Whether the KeyboardEvent.code is enabled pref("dom.keyboardevent.code.enabled", true);