diff options
Diffstat (limited to 'gfx/vr/VRDisplayHost.cpp')
-rw-r--r-- | gfx/vr/VRDisplayHost.cpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/gfx/vr/VRDisplayHost.cpp b/gfx/vr/VRDisplayHost.cpp new file mode 100644 index 000000000..fd2fd6d6a --- /dev/null +++ b/gfx/vr/VRDisplayHost.cpp @@ -0,0 +1,201 @@ +/* -*- Mode: C++; 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/. */ + +#include "VRDisplayHost.h" +#include "gfxVR.h" + +#if defined(XP_WIN) + +#include <d3d11.h> +#include "gfxWindowsPlatform.h" +#include "../layers/d3d11/CompositorD3D11.h" +#include "mozilla/layers/TextureD3D11.h" + +#endif + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::layers; + +VRDisplayHost::VRDisplayHost(VRDeviceType aType) + : mInputFrameID(0) +{ + MOZ_COUNT_CTOR(VRDisplayHost); + mDisplayInfo.mType = aType; + mDisplayInfo.mDisplayID = VRDisplayManager::AllocateDisplayID(); + mDisplayInfo.mIsPresenting = false; + + for (int i = 0; i < kMaxLatencyFrames; i++) { + mLastSensorState[i].Clear(); + } +} + +VRDisplayHost::~VRDisplayHost() +{ + MOZ_COUNT_DTOR(VRDisplayHost); +} + +void +VRDisplayHost::AddLayer(VRLayerParent *aLayer) +{ + mLayers.AppendElement(aLayer); + if (mLayers.Length() == 1) { + StartPresentation(); + } + mDisplayInfo.mIsPresenting = mLayers.Length() > 0; + + // Ensure that the content process receives the change immediately + VRManager* vm = VRManager::Get(); + vm->RefreshVRDisplays(); +} + +void +VRDisplayHost::RemoveLayer(VRLayerParent *aLayer) +{ + mLayers.RemoveElement(aLayer); + if (mLayers.Length() == 0) { + StopPresentation(); + } + mDisplayInfo.mIsPresenting = mLayers.Length() > 0; + + // Ensure that the content process receives the change immediately + VRManager* vm = VRManager::Get(); + vm->RefreshVRDisplays(); +} + +#if defined(XP_WIN) + +void +VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, const int32_t& aInputFrameID, + PTextureParent* aTexture, const gfx::Rect& aLeftEyeRect, + const gfx::Rect& aRightEyeRect) +{ + // aInputFrameID is no longer controlled by content with the WebVR 1.1 API + // update; however, we will later use this code to enable asynchronous + // submission of multiple layers to be composited. This will enable + // us to build browser UX that remains responsive even when content does + // not consistently submit frames. + + int32_t inputFrameID = aInputFrameID; + if (inputFrameID == 0) { + inputFrameID = mInputFrameID; + } + if (inputFrameID < 0) { + // Sanity check to prevent invalid memory access on builds with assertions + // disabled. + inputFrameID = 0; + } + + VRHMDSensorState sensorState = mLastSensorState[inputFrameID % kMaxLatencyFrames]; + // It is possible to get a cache miss on mLastSensorState if latency is + // longer than kMaxLatencyFrames. An optimization would be to find a frame + // that is closer than the one selected with the modulus. + // If we hit this; however, latency is already so high that the site is + // un-viewable and a more accurate pose prediction is not likely to + // compensate. + + TextureHost* th = TextureHost::AsTextureHost(aTexture); + // WebVR doesn't use the compositor to compose the frame, so use + // AutoLockTextureHostWithoutCompositor here. + AutoLockTextureHostWithoutCompositor autoLock(th); + if (autoLock.Failed()) { + NS_WARNING("Failed to lock the VR layer texture"); + return; + } + + CompositableTextureSourceRef source; + if (!th->BindTextureSource(source)) { + NS_WARNING("The TextureHost was successfully locked but can't provide a TextureSource"); + return; + } + MOZ_ASSERT(source); + + IntSize texSize = source->GetSize(); + + TextureSourceD3D11* sourceD3D11 = source->AsSourceD3D11(); + if (!sourceD3D11) { + NS_WARNING("WebVR support currently only implemented for D3D11"); + return; + } + + SubmitFrame(sourceD3D11, texSize, sensorState, aLeftEyeRect, aRightEyeRect); +} + +#else + +void +VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, const int32_t& aInputFrameID, + PTextureParent* aTexture, const gfx::Rect& aLeftEyeRect, + const gfx::Rect& aRightEyeRect) +{ + NS_WARNING("WebVR only supported in Windows."); +} + +#endif + +bool +VRDisplayHost::CheckClearDisplayInfoDirty() +{ + if (mDisplayInfo == mLastUpdateDisplayInfo) { + return false; + } + mLastUpdateDisplayInfo = mDisplayInfo; + return true; +} + +VRControllerHost::VRControllerHost(VRDeviceType aType) +{ + MOZ_COUNT_CTOR(VRControllerHost); + mControllerInfo.mType = aType; + mControllerInfo.mControllerID = VRDisplayManager::AllocateDisplayID(); +} + +VRControllerHost::~VRControllerHost() +{ + MOZ_COUNT_DTOR(VRControllerHost); +} + +const VRControllerInfo& +VRControllerHost::GetControllerInfo() const +{ + return mControllerInfo; +} + +void +VRControllerHost::SetIndex(uint32_t aIndex) +{ + mIndex = aIndex; +} + +uint32_t +VRControllerHost::GetIndex() +{ + return mIndex; +} + +void +VRControllerHost::SetButtonPressed(uint64_t aBit) +{ + mButtonPressed = aBit; +} + +uint64_t +VRControllerHost::GetButtonPressed() +{ + return mButtonPressed; +} + +void +VRControllerHost::SetPose(const dom::GamepadPoseState& aPose) +{ + mPose = aPose; +} + +const dom::GamepadPoseState& +VRControllerHost::GetPose() +{ + return mPose; +} + |