author | Daosheng Mu <daoshengmu@gmail.com> |
Thu, 02 Mar 2017 00:04:12 +0800 | |
changeset 392142 | 0f9b03faff358ed78b951b0f67401f8bd108bf34 |
parent 392141 | 0fb088fb7d66147ff48d99596dfd3f67960d6426 |
child 392143 | 36bb16774744cba10efdfa1d33f4a5dd027f32ce |
push id | 7198 |
push user | jlorenzo@mozilla.com |
push date | Tue, 18 Apr 2017 12:07:49 +0000 |
treeherder | mozilla-beta@d57aa49c3948 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | kip |
bugs | 1229480 |
milestone | 54.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
gfx/thebes/gfxPrefs.h | file | annotate | diff | comparison | revisions | |
gfx/vr/VRManager.cpp | file | annotate | diff | comparison | revisions | |
gfx/vr/gfxVR.h | file | annotate | diff | comparison | revisions | |
gfx/vr/gfxVRPuppet.cpp | file | annotate | diff | comparison | revisions | |
gfx/vr/gfxVRPuppet.h | file | annotate | diff | comparison | revisions | |
gfx/vr/moz.build | file | annotate | diff | comparison | revisions |
--- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -320,16 +320,17 @@ private: DECL_GFX_PREF(Live, "dom.ipc.plugins.asyncdrawing.enabled", PluginAsyncDrawingEnabled, bool, false); DECL_GFX_PREF(Live, "dom.meta-viewport.enabled", MetaViewportEnabled, bool, false); DECL_GFX_PREF(Once, "dom.vr.enabled", VREnabled, bool, false); DECL_GFX_PREF(Once, "dom.vr.oculus.enabled", VROculusEnabled, bool, true); DECL_GFX_PREF(Once, "dom.vr.openvr.enabled", VROpenVREnabled, bool, false); DECL_GFX_PREF(Once, "dom.vr.osvr.enabled", VROSVREnabled, bool, false); DECL_GFX_PREF(Live, "dom.vr.poseprediction.enabled", VRPosePredictionEnabled, bool, false); + DECL_GFX_PREF(Once, "dom.vr.puppet.enabled", VRPuppetEnabled, bool, false); DECL_GFX_PREF(Live, "dom.w3c_pointer_events.enabled", PointerEventsEnabled, bool, false); DECL_GFX_PREF(Live, "dom.w3c_touch_events.enabled", TouchEventsEnabled, int32_t, 0); DECL_GFX_PREF(Live, "general.smoothScroll", SmoothScrollEnabled, bool, true); DECL_GFX_PREF(Live, "general.smoothScroll.currentVelocityWeighting", SmoothScrollCurrentVelocityWeighting, float, 0.25); DECL_GFX_PREF(Live, "general.smoothScroll.durationToIntervalRatio", SmoothScrollDurationToIntervalRatio, int32_t, 200);
--- a/gfx/vr/VRManager.cpp +++ b/gfx/vr/VRManager.cpp @@ -17,16 +17,17 @@ #include "gfxPrefs.h" #include "gfxVR.h" #if defined(XP_WIN) #include "gfxVROculus.h" #endif #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_LINUX) #include "gfxVROSVR.h" #endif +#include "gfxVRPuppet.h" #include "ipc/VRLayerParent.h" using namespace mozilla; using namespace mozilla::gfx; using namespace mozilla::layers; using namespace mozilla::gl; namespace mozilla { @@ -83,16 +84,20 @@ VRManager::VRManager() } // OSVR is cross platform compatible mgr = VRSystemManagerOSVR::Create(); if (mgr) { mManagers.AppendElement(mgr); } #endif + mgr = VRSystemManagerPuppet::Create(); + if (mgr) { + mManagers.AppendElement(mgr); + } // Enable gamepad extensions while VR is enabled. // Preference only can be set at the Parent process. if (XRE_IsParentProcess() && gfxPrefs::VREnabled()) { Preferences::SetBool("dom.gamepad.extensions.enabled", true); } } VRManager::~VRManager()
--- a/gfx/vr/gfxVR.h +++ b/gfx/vr/gfxVR.h @@ -29,16 +29,17 @@ namespace gfx { class VRLayerParent; class VRDisplayHost; class VRControllerHost; enum class VRDeviceType : uint16_t { Oculus, OpenVR, OSVR, + Puppet, NumVRDeviceTypes }; enum class VRDisplayCapabilityFlags : uint16_t { Cap_None = 0, /** * Cap_Position is set if the VRDisplay is capable of tracking its position. */
new file mode 100644 --- /dev/null +++ b/gfx/vr/gfxVRPuppet.cpp @@ -0,0 +1,459 @@ +/* -*- Mode: C++; tab-width: 20; 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/. */ + +#if defined(XP_WIN) +#include "CompositorD3D11.h" +#include "TextureD3D11.h" +#endif // XP_WIN + +#include "gfxVRPuppet.h" + +#include "mozilla/dom/GamepadEventTypes.h" +#include "mozilla/dom/GamepadBinding.h" + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::gfx::impl; +using namespace mozilla::layers; + + +// Reminder: changing the order of these buttons may break web content +static const uint64_t kPuppetButtonMask[] = { + 1, + 2, + 4, + 8 +}; + +static const uint32_t kNumPuppetButtonMask = sizeof(kPuppetButtonMask) / + sizeof(uint64_t); + +static const uint32_t kPuppetAxes[] = { + 0, + 1, + 2 +}; + +static const uint32_t kNumPuppetAxis = sizeof(kPuppetAxes) / + sizeof(uint32_t); + +VRDisplayPuppet::VRDisplayPuppet() + : VRDisplayHost(VRDeviceType::Puppet) + , mIsPresenting(false) +{ + MOZ_COUNT_CTOR_INHERITED(VRDisplayPuppet, VRDisplayHost); + + mDisplayInfo.mDisplayName.AssignLiteral("Puppet HMD"); + mDisplayInfo.mIsConnected = true; + mDisplayInfo.mIsMounted = false; + mDisplayInfo.mCapabilityFlags = VRDisplayCapabilityFlags::Cap_None | + VRDisplayCapabilityFlags::Cap_Orientation | + VRDisplayCapabilityFlags::Cap_Position | + VRDisplayCapabilityFlags::Cap_External | + VRDisplayCapabilityFlags::Cap_Present | + VRDisplayCapabilityFlags::Cap_StageParameters; + mDisplayInfo.mEyeResolution.width = 1836; // 1080 * 1.7 + mDisplayInfo.mEyeResolution.height = 2040; // 1200 * 1.7 + + // SteamVR gives the application a single FOV to use; it's not configurable as with Oculus + for (uint32_t eye = 0; eye < 2; ++eye) { + mDisplayInfo.mEyeTranslation[eye].x = 0.0f; + mDisplayInfo.mEyeTranslation[eye].y = 0.0f; + mDisplayInfo.mEyeTranslation[eye].z = 0.0f; + mDisplayInfo.mEyeFOV[eye] = VRFieldOfView(45.0, 45.0, 45.0, 45.0); + } + + // default: 1m x 1m space, 0.75m high in seated position + mDisplayInfo.mStageSize.width = 1.0f; + mDisplayInfo.mStageSize.height = 1.0f; + + mDisplayInfo.mSittingToStandingTransform._11 = 1.0f; + mDisplayInfo.mSittingToStandingTransform._12 = 0.0f; + mDisplayInfo.mSittingToStandingTransform._13 = 0.0f; + mDisplayInfo.mSittingToStandingTransform._14 = 0.0f; + + mDisplayInfo.mSittingToStandingTransform._21 = 0.0f; + mDisplayInfo.mSittingToStandingTransform._22 = 1.0f; + mDisplayInfo.mSittingToStandingTransform._23 = 0.0f; + mDisplayInfo.mSittingToStandingTransform._24 = 0.0f; + + mDisplayInfo.mSittingToStandingTransform._31 = 0.0f; + mDisplayInfo.mSittingToStandingTransform._32 = 0.0f; + mDisplayInfo.mSittingToStandingTransform._33 = 1.0f; + mDisplayInfo.mSittingToStandingTransform._34 = 0.0f; + + mDisplayInfo.mSittingToStandingTransform._41 = 0.0f; + mDisplayInfo.mSittingToStandingTransform._42 = 0.75f; + mDisplayInfo.mSittingToStandingTransform._43 = 0.0f; + + mSensorState.Clear(); + mSensorState.timestamp = PR_Now(); + + gfx::Quaternion rot; + + mSensorState.flags |= VRDisplayCapabilityFlags::Cap_Orientation; + mSensorState.orientation[0] = rot.x; + mSensorState.orientation[1] = rot.y; + mSensorState.orientation[2] = rot.z; + mSensorState.orientation[3] = rot.w; + mSensorState.angularVelocity[0] = 0.0f; + mSensorState.angularVelocity[1] = 0.0f; + mSensorState.angularVelocity[2] = 0.0f; + + mSensorState.flags |= VRDisplayCapabilityFlags::Cap_Position; + mSensorState.position[0] = 0.0f; + mSensorState.position[1] = 0.0f; + mSensorState.position[2] = 0.0f; + mSensorState.linearVelocity[0] = 0.0f; + mSensorState.linearVelocity[1] = 0.0f; + mSensorState.linearVelocity[2] = 0.0f; +} + +VRDisplayPuppet::~VRDisplayPuppet() +{ + MOZ_COUNT_DTOR_INHERITED(VRDisplayPuppet, VRDisplayHost); +} + +void +VRDisplayPuppet::SetDisplayInfo(const VRDisplayInfo& aDisplayInfo) +{ + mDisplayInfo = aDisplayInfo; +} + +void +VRDisplayPuppet::Destroy() +{ + StopPresentation(); +} + +void +VRDisplayPuppet::ZeroSensor() +{ +} + +VRHMDSensorState +VRDisplayPuppet::GetSensorState() +{ + return GetSensorState(0.0f); +} + +VRHMDSensorState +VRDisplayPuppet::GetImmediateSensorState() +{ + return GetSensorState(0.0f); +} + +VRHMDSensorState +VRDisplayPuppet::GetSensorState(double timeOffset) +{ + return mSensorState; +} + +void +VRDisplayPuppet::SetSensorState(const VRHMDSensorState& aSensorState) +{ + mSensorState = aSensorState; +} + +void +VRDisplayPuppet::StartPresentation() +{ + if (mIsPresenting) { + return; + } + mIsPresenting = true; +} + +void +VRDisplayPuppet::StopPresentation() +{ + if (!mIsPresenting) { + return; + } + + mIsPresenting = false; +} + +#if defined(XP_WIN) +void +VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource, + const IntSize& aSize, + const VRHMDSensorState& aSensorState, + const gfx::Rect& aLeftEyeRect, + const gfx::Rect& aRightEyeRect) +{ + if (!mIsPresenting) { + return; + } + + ID3D11Texture2D* tex = aSource->GetD3D11Texture(); + MOZ_ASSERT(tex); + + // TODO: Bug 1343730, Need to block until the next simulated + // vblank interval and capture frames for use in reftests. + + // Trigger the next VSync immediately + VRManager *vm = VRManager::Get(); + MOZ_ASSERT(vm); + vm->NotifyVRVsync(mDisplayInfo.mDisplayID); +} +#else +void +VRDisplayPuppet::SubmitFrame(TextureSourceOGL* aSource, + const IntSize& aSize, + const VRHMDSensorState& aSensorState, + const gfx::Rect& aLeftEyeRect, + const gfx::Rect& aRightEyeRect) +{ + if (!mIsPresenting) { + return; + } + + // TODO: Bug 1343730, Need to block until the next simulated + // vblank interval and capture frames for use in reftests. + + // Trigger the next VSync immediately + VRManager *vm = VRManager::Get(); + MOZ_ASSERT(vm); + vm->NotifyVRVsync(mDisplayInfo.mDisplayID); +} +#endif + +void +VRDisplayPuppet::NotifyVSync() +{ + // We update mIsConneced once per frame. + mDisplayInfo.mIsConnected = true; +} + +VRControllerPuppet::VRControllerPuppet(dom::GamepadHand aHand) + : VRControllerHost(VRDeviceType::Puppet) + , mButtonPressState(0) +{ + MOZ_COUNT_CTOR_INHERITED(VRControllerPuppet, VRControllerHost); + mControllerInfo.mControllerName.AssignLiteral("Puppet Gamepad"); + mControllerInfo.mMappingType = GamepadMappingType::_empty; + mControllerInfo.mHand = aHand; + mControllerInfo.mNumButtons = kNumPuppetButtonMask; + mControllerInfo.mNumAxes = kNumPuppetAxis; +} + +VRControllerPuppet::~VRControllerPuppet() +{ + MOZ_COUNT_DTOR_INHERITED(VRControllerPuppet, VRControllerHost); +} + +void +VRControllerPuppet::SetButtonPressState(uint32_t aButton, bool aPressed) +{ + const uint64_t buttonMask = kPuppetButtonMask[aButton]; + uint64_t pressedBit = GetButtonPressed(); + + if (aPressed) { + pressedBit |= kPuppetButtonMask[aButton]; + } else if (pressedBit & buttonMask) { + // this button was pressed but is released now. + uint64_t mask = 0xff ^ buttonMask; + pressedBit &= mask; + } + + mButtonPressState = pressedBit; +} + +uint64_t +VRControllerPuppet::GetButtonPressState() +{ + return mButtonPressState; +} + +void +VRControllerPuppet::SetAxisMoveState(uint32_t aAxis, double aValue) +{ + MOZ_ASSERT((sizeof(mAxisMoveState) / sizeof(float)) == kNumPuppetAxis); + MOZ_ASSERT(aAxis <= kNumPuppetAxis); + + mAxisMoveState[aAxis] = aValue; +} + +double +VRControllerPuppet::GetAxisMoveState(uint32_t aAxis) +{ + return mAxisMoveState[aAxis]; +} + +void +VRControllerPuppet::SetPoseMoveState(const dom::GamepadPoseState& aPose) +{ + mPoseState = aPose; +} + +const dom::GamepadPoseState& +VRControllerPuppet::GetPoseMoveState() +{ + return mPoseState; +} + +float +VRControllerPuppet::GetAxisMove(uint32_t aAxis) +{ + return mAxisMove[aAxis]; +} + +void +VRControllerPuppet::SetAxisMove(uint32_t aAxis, float aValue) +{ + mAxisMove[aAxis] = aValue; +} + +VRSystemManagerPuppet::VRSystemManagerPuppet() +{ +} + +/*static*/ already_AddRefed<VRSystemManagerPuppet> +VRSystemManagerPuppet::Create() +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (!gfxPrefs::VREnabled() || !gfxPrefs::VRPuppetEnabled()) { + return nullptr; + } + + RefPtr<VRSystemManagerPuppet> manager = new VRSystemManagerPuppet(); + return manager.forget(); +} + +bool +VRSystemManagerPuppet::Init() +{ + return true; +} + +void +VRSystemManagerPuppet::Destroy() +{ + mPuppetHMD = nullptr; +} + +void +VRSystemManagerPuppet::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) +{ + if (mPuppetHMD == nullptr) { + mPuppetHMD = new VRDisplayPuppet(); + } + aHMDResult.AppendElement(mPuppetHMD); +} + +void +VRSystemManagerPuppet::HandleInput() +{ + RefPtr<impl::VRControllerPuppet> controller; + for (uint32_t i = 0; i < mPuppetController.Length(); ++i) { + controller = mPuppetController[i]; + HandleButtonPress(i, controller->GetButtonPressState()); + + for (uint32_t j = 0; j < kNumPuppetAxis; ++j) { + HandleAxisMove(i, j, controller->GetAxisMoveState(j)); + } + HandlePoseTracking(i, controller->GetPoseMoveState(), controller); + } +} + +void +VRSystemManagerPuppet::HandleButtonPress(uint32_t aControllerIdx, + uint64_t aButtonPressed) +{ + uint64_t buttonMask = 0; + RefPtr<impl::VRControllerPuppet> controller(mPuppetController[aControllerIdx]); + MOZ_ASSERT(controller); + uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed); + + if (!diff) { + return; + } + + for (uint32_t i = 0; i < kNumPuppetButtonMask; ++i) { + buttonMask = kPuppetButtonMask[i]; + + if (diff & buttonMask) { + // diff & aButtonPressed would be true while a new button press + // event, otherwise it is an old press event and needs to notify + // the button has been released. + NewButtonEvent(aControllerIdx, i, diff & aButtonPressed); + } + } + + controller->SetButtonPressed(aButtonPressed); +} + +void +VRSystemManagerPuppet::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis, + float aValue) +{ + RefPtr<impl::VRControllerPuppet> controller(mPuppetController[aControllerIdx]); + MOZ_ASSERT(controller); + + if (controller->GetAxisMove(aAxis) != aValue) { + NewAxisMove(aControllerIdx, aAxis, aValue); + controller->SetAxisMove(aAxis, aValue); + } +} + +void +VRSystemManagerPuppet::HandlePoseTracking(uint32_t aControllerIdx, + const GamepadPoseState& aPose, + VRControllerHost* aController) +{ + MOZ_ASSERT(aController); + if (aPose != aController->GetPose()) { + aController->SetPose(aPose); + NewPoseState(aControllerIdx, aPose); + } +} + +void +VRSystemManagerPuppet::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) +{ + aControllerResult.Clear(); + for (uint32_t i = 0; i < mPuppetController.Length(); ++i) { + aControllerResult.AppendElement(mPuppetController[i]); + } +} + +void +VRSystemManagerPuppet::ScanForControllers() +{ + // We make VRSystemManagerPuppet has two controllers always. + const uint32_t newControllerCount = 2; + + if (newControllerCount != mControllerCount) { + // controller count is changed, removing the existing gamepads first. + for (uint32_t i = 0; i < mPuppetController.Length(); ++i) { + RemoveGamepad(i); + } + + mControllerCount = 0; + mPuppetController.Clear(); + + // Re-adding controllers to VRControllerManager. + for (uint32_t i = 0; i < newControllerCount; ++i) { + dom::GamepadHand hand = (i % 2) ? dom::GamepadHand::Right : + dom::GamepadHand::Left; + RefPtr<VRControllerPuppet> puppetController = new VRControllerPuppet(hand); + puppetController->SetIndex(mControllerCount); + mPuppetController.AppendElement(puppetController); + + // Not already present, add it. + AddGamepad(puppetController->GetControllerInfo()); + ++mControllerCount; + } + } +} + +void +VRSystemManagerPuppet::RemoveControllers() +{ + mPuppetController.Clear(); + mControllerCount = 0; +}
new file mode 100644 --- /dev/null +++ b/gfx/vr/gfxVRPuppet.h @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 20; 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/. */ + +#ifndef GFX_VR_PUPPET_H +#define GFX_VR_PUPPET_H + +#include "nsTArray.h" +#include "mozilla/RefPtr.h" + +#include "gfxVR.h" + +namespace mozilla { +namespace gfx { +namespace impl { + +class VRDisplayPuppet : public VRDisplayHost +{ +public: + void SetDisplayInfo(const VRDisplayInfo& aDisplayInfo); + virtual void NotifyVSync() override; + virtual VRHMDSensorState GetSensorState() override; + virtual VRHMDSensorState GetImmediateSensorState() override; + void SetSensorState(const VRHMDSensorState& aSensorState); + void ZeroSensor() override; + +protected: + virtual void StartPresentation() override; + virtual void StopPresentation() override; +#if defined(XP_WIN) + virtual void SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource, + const IntSize& aSize, + const VRHMDSensorState& aSensorState, + const gfx::Rect& aLeftEyeRect, + const gfx::Rect& aRightEyeRect) override; +#else + virtual void SubmitFrame(mozilla::layers::TextureSourceOGL* aSource, + const IntSize& aSize, + const VRHMDSensorState& aSensorState, + const gfx::Rect& aLeftEyeRect, + const gfx::Rect& aRightEyeRect); +#endif // XP_WIN + +public: + explicit VRDisplayPuppet(); + +protected: + virtual ~VRDisplayPuppet(); + void Destroy(); + + VRHMDSensorState GetSensorState(double timeOffset); + + bool mIsPresenting; + +private: + VRHMDSensorState mSensorState; +}; + +class VRControllerPuppet : public VRControllerHost +{ +public: + explicit VRControllerPuppet(dom::GamepadHand aHand); + void SetButtonPressState(uint32_t aButton, bool aPressed); + uint64_t GetButtonPressState(); + void SetAxisMoveState(uint32_t aAxis, double aValue); + double GetAxisMoveState(uint32_t aAxis); + void SetPoseMoveState(const dom::GamepadPoseState& aPose); + const dom::GamepadPoseState& GetPoseMoveState(); + float GetAxisMove(uint32_t aAxis); + void SetAxisMove(uint32_t aAxis, float aValue); + +protected: + virtual ~VRControllerPuppet(); + +private: + uint64_t mButtonPressState; + float mAxisMoveState[3]; + float mAxisMove[3]; + dom::GamepadPoseState mPoseState; +}; + +} // namespace impl + +class VRSystemManagerPuppet : public VRSystemManager +{ +public: + static already_AddRefed<VRSystemManagerPuppet> Create(); + + virtual bool Init() override; + virtual void Destroy() override; + virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override; + virtual void HandleInput() override; + virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& + aControllerResult) override; + virtual void ScanForControllers() override; + virtual void RemoveControllers() override; + +protected: + VRSystemManagerPuppet(); + +private: + virtual void HandleButtonPress(uint32_t aControllerIndex, + uint64_t aButtonPressed) override; + virtual void HandleAxisMove(uint32_t aControllerIndex, uint32_t aAxis, + float aValue) override; + virtual void HandlePoseTracking(uint32_t aControllerIndex, + const dom::GamepadPoseState& aPose, + VRControllerHost* aController) override; + + // there can only be one + RefPtr<impl::VRDisplayPuppet> mPuppetHMD; + nsTArray<RefPtr<impl::VRControllerPuppet>> mPuppetController; +}; + +} // namespace gfx +} // namespace mozilla + +#endif /* GFX_VR_PUPPET_H*/ \ No newline at end of file
--- a/gfx/vr/moz.build +++ b/gfx/vr/moz.build @@ -20,16 +20,17 @@ LOCAL_INCLUDES += [ '/gfx/layers/d3d11', '/gfx/thebes', ] UNIFIED_SOURCES += [ 'gfxVR.cpp', 'gfxVROpenVR.cpp', 'gfxVROSVR.cpp', + 'gfxVRPuppet.cpp', 'ipc/VRLayerChild.cpp', 'ipc/VRLayerParent.cpp', 'ipc/VRManagerChild.cpp', 'ipc/VRManagerParent.cpp', 'VRDisplayClient.cpp', 'VRDisplayHost.cpp', 'VRDisplayPresentation.cpp', 'VRManager.cpp',