summaryrefslogtreecommitdiffstats
path: root/gfx/vr/VRDisplayHost.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/vr/VRDisplayHost.cpp')
-rw-r--r--gfx/vr/VRDisplayHost.cpp201
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;
+}
+