From fcc8fcf709c60327e7e1bbeabdc4c2578e0942eb Mon Sep 17 00:00:00 2001 From: "Kearwood \"Kip\" Gilbert" Date: Mon, 18 Sep 2017 16:19:49 -0700 Subject: [PATCH] Bug 1381085 - Submit VR frames with a separate ID3DDeviceContextState r=daoshengmu - Using a separate ID3DDeviceContextState ensures that the WebVR context does not stomp over the mirrored state used by the MLGPU "Advanced" Layers rendering. MozReview-Commit-ID: 99mfdsjFrMI --HG-- extra : rebase_source : fdcdcb55185048cfb54163f51aca70409a1aa74a --- gfx/vr/VRDisplayHost.cpp | 95 ++++++++++++++++++++++++++++++++++++++++ gfx/vr/VRDisplayHost.h | 29 ++++++++++++ gfx/vr/gfxVROculus.cpp | 30 ++++++------- gfx/vr/gfxVROculus.h | 2 - gfx/vr/gfxVRPuppet.cpp | 21 +++++---- gfx/vr/gfxVRPuppet.h | 2 - 6 files changed, 147 insertions(+), 32 deletions(-) diff --git a/gfx/vr/VRDisplayHost.cpp b/gfx/vr/VRDisplayHost.cpp index 2bf9526edeaa..045ad87b52f2 100644 --- a/gfx/vr/VRDisplayHost.cpp +++ b/gfx/vr/VRDisplayHost.cpp @@ -14,6 +14,7 @@ #include #include "gfxWindowsPlatform.h" #include "../layers/d3d11/CompositorD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/layers/TextureD3D11.h" #elif defined(XP_MACOSX) @@ -26,6 +27,37 @@ using namespace mozilla; using namespace mozilla::gfx; using namespace mozilla::layers; +VRDisplayHost::AutoRestoreRenderState::AutoRestoreRenderState(VRDisplayHost* aDisplay) + : mDisplay(aDisplay) + , mSuccess(true) +{ +#if defined(XP_WIN) + ID3D11DeviceContext1* context = mDisplay->GetD3DDeviceContext(); + ID3DDeviceContextState* state = mDisplay->GetD3DDeviceContextState(); + if (!context || !state) { + mSuccess = false; + return; + } + context->SwapDeviceContextState(state, getter_AddRefs(mPrevDeviceContextState)); +#endif +} + +VRDisplayHost::AutoRestoreRenderState::~AutoRestoreRenderState() +{ +#if defined(XP_WIN) + ID3D11DeviceContext1* context = mDisplay->GetD3DDeviceContext(); + if (context && mSuccess) { + context->SwapDeviceContextState(mPrevDeviceContextState, nullptr); + } +#endif +} + +bool +VRDisplayHost::AutoRestoreRenderState::IsSuccess() +{ + return mSuccess; +} + VRDisplayHost::VRDisplayHost(VRDeviceType aType) : mFrameStarted(false) { @@ -42,6 +74,69 @@ VRDisplayHost::~VRDisplayHost() MOZ_COUNT_DTOR(VRDisplayHost); } +#if defined(XP_WIN) +bool +VRDisplayHost::CreateD3DObjects() +{ + if (!mDevice) { + RefPtr device = gfx::DeviceManagerDx::Get()->GetCompositorDevice(); + if (!device) { + NS_WARNING("VRDisplayHost::CreateD3DObjects failed to get a D3D11Device"); + return false; + } + if (FAILED(device->QueryInterface(__uuidof(ID3D11Device1), getter_AddRefs(mDevice)))) { + NS_WARNING("VRDisplayHost::CreateD3DObjects failed to get a D3D11Device1"); + return false; + } + } + + if (!mContext) { + mDevice->GetImmediateContext1(getter_AddRefs(mContext)); + if (!mContext) { + NS_WARNING("VRDisplayHost::CreateD3DObjects failed to get an immediate context"); + return false; + } + } + if (!mDeviceContextState) { + D3D_FEATURE_LEVEL featureLevels[] { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0 + }; + mDevice->CreateDeviceContextState(0, + featureLevels, + 2, + D3D11_SDK_VERSION, + __uuidof(ID3D11Device1), + nullptr, + getter_AddRefs(mDeviceContextState)); + } + if (!mDeviceContextState) { + NS_WARNING("VRDisplayHost::CreateD3DObjects failed to get a D3D11DeviceContextState"); + return false; + } + return true; +} + +ID3D11Device1* +VRDisplayHost::GetD3DDevice() +{ + return mDevice; +} + +ID3D11DeviceContext1* +VRDisplayHost::GetD3DDeviceContext() +{ + return mContext; +} + +ID3DDeviceContextState* +VRDisplayHost::GetD3DDeviceContextState() +{ + return mDeviceContextState; +} + +#endif // defined(XP_WIN) + void VRDisplayHost::SetGroupMask(uint32_t aGroupMask) { diff --git a/gfx/vr/VRDisplayHost.h b/gfx/vr/VRDisplayHost.h index ed39732cbbc6..f28a5c2c7a6c 100644 --- a/gfx/vr/VRDisplayHost.h +++ b/gfx/vr/VRDisplayHost.h @@ -17,6 +17,9 @@ #include "mozilla/TimeStamp.h" #include "mozilla/TypedEnumBits.h" #include "mozilla/dom/GamepadPoseState.h" +#if defined(XP_WIN) +#include +#endif #if defined(XP_MACOSX) class MacIOSurface; @@ -56,6 +59,19 @@ public: void SetGroupMask(uint32_t aGroupMask); bool GetIsConnected(); + class AutoRestoreRenderState { + public: + explicit AutoRestoreRenderState(VRDisplayHost* aDisplay); + ~AutoRestoreRenderState(); + bool IsSuccess(); + private: + RefPtr mDisplay; +#if defined(XP_WIN) + RefPtr mPrevDeviceContextState; +#endif + bool mSuccess; + }; + protected: explicit VRDisplayHost(VRDeviceType aType); virtual ~VRDisplayHost(); @@ -89,6 +105,19 @@ private: VRDisplayInfo mLastUpdateDisplayInfo; TimeStamp mLastFrameStart; bool mFrameStarted; + +#if defined(XP_WIN) +protected: + bool CreateD3DObjects(); + RefPtr mDevice; + RefPtr mContext; + ID3D11Device1* GetD3DDevice(); + ID3D11DeviceContext1* GetD3DDeviceContext(); + ID3DDeviceContextState* GetD3DDeviceContextState(); + +private: + RefPtr mDeviceContextState; +#endif }; class VRControllerHost { diff --git a/gfx/vr/gfxVROculus.cpp b/gfx/vr/gfxVROculus.cpp index 8fe0bf1a07b0..4696e2a97bd6 100644 --- a/gfx/vr/gfxVROculus.cpp +++ b/gfx/vr/gfxVROculus.cpp @@ -910,27 +910,14 @@ VRDisplayOculus::GetSensorState(double absTime) void VRDisplayOculus::StartPresentation() { + if (!CreateD3DObjects()) { + return; + } mSession->StartPresentation(IntSize(mDisplayInfo.mEyeResolution.width * 2, mDisplayInfo.mEyeResolution.height)); if (!mSession->IsRenderReady()) { return; } - if (!mDevice) { - mDevice = gfx::DeviceManagerDx::Get()->GetCompositorDevice(); - if (!mDevice) { - NS_WARNING("Failed to get a D3D11Device for Oculus"); - return; - } - } - - if (!mContext) { - mDevice->GetImmediateContext(getter_AddRefs(mContext)); - if (!mContext) { - NS_WARNING("Failed to get immediate context for Oculus"); - return; - } - } - if (!mQuadVS) { if (FAILED(mDevice->CreateVertexShader(sLayerQuadVS.mData, sLayerQuadVS.mLength, nullptr, &mQuadVS))) { NS_WARNING("Failed to create vertex shader for Oculus"); @@ -1048,7 +1035,16 @@ VRDisplayOculus::SubmitFrame(TextureSourceD3D11* aSource, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) { - if (!mSession->IsRenderReady() || !mDevice || !mContext) { + if (!CreateD3DObjects()) { + return false; + } + + AutoRestoreRenderState restoreState(this); + if (!restoreState.IsSuccess()) { + return false; + } + + if (!mSession->IsRenderReady()) { return false; } /** diff --git a/gfx/vr/gfxVROculus.h b/gfx/vr/gfxVROculus.h index be7821296b53..e625820da354 100644 --- a/gfx/vr/gfxVROculus.h +++ b/gfx/vr/gfxVROculus.h @@ -108,8 +108,6 @@ protected: RefPtr mSession; ovrFovPort mFOVPort[2]; - RefPtr mDevice; - RefPtr mContext; ID3D11VertexShader* mQuadVS; ID3D11PixelShader* mQuadPS; RefPtr mLinearSamplerState; diff --git a/gfx/vr/gfxVRPuppet.cpp b/gfx/vr/gfxVRPuppet.cpp index ddae0d08796d..6480790994e6 100644 --- a/gfx/vr/gfxVRPuppet.cpp +++ b/gfx/vr/gfxVRPuppet.cpp @@ -166,17 +166,7 @@ VRDisplayPuppet::StartPresentation() mIsPresenting = true; #if defined(XP_WIN) - if (!mDevice) { - mDevice = gfx::DeviceManagerDx::Get()->GetCompositorDevice(); - if (!mDevice) { - NS_WARNING("Failed to get a D3D11Device for Puppet"); - return; - } - } - - mDevice->GetImmediateContext(getter_AddRefs(mContext)); - if (!mContext) { - NS_WARNING("Failed to get immediate context for Puppet"); + if (!CreateD3DObjects()) { return; } @@ -293,6 +283,15 @@ VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource, return false; } + if (!CreateD3DObjects()) { + return false; + } + + AutoRestoreRenderState restoreState(this); + if (!restoreState.IsSuccess()) { + return false; + } + VRManager *vm = VRManager::Get(); MOZ_ASSERT(vm); diff --git a/gfx/vr/gfxVRPuppet.h b/gfx/vr/gfxVRPuppet.h index d2c000a32fd4..790eb7e98798 100644 --- a/gfx/vr/gfxVRPuppet.h +++ b/gfx/vr/gfxVRPuppet.h @@ -56,8 +56,6 @@ private: #if defined(XP_WIN) bool UpdateConstantBuffers(); - RefPtr mDevice; - RefPtr mContext; ID3D11VertexShader* mQuadVS; ID3D11PixelShader* mQuadPS; RefPtr mLinearSamplerState;