From c5a2279e204b82dcd561adc76b12c27a426549c9 Mon Sep 17 00:00:00 2001 From: "Kearwood \"Kip\" Gilbert" Date: Fri, 21 Jul 2017 17:30:34 -0700 Subject: [PATCH] Bug 1400457 - Isolate VR Rendering from Compositor r=daoshengmu,jgilbert - WebVR is no longer dependent on PTexture, TextureParent, TextureHost, and TextureChild. It continues to use TextureClient for pooling and coordinating locks with other Gecko code. - PreserveDrawingBuffer now behaving correctly for 2d display mirroring - Preparation for separating to VR process MozReview-Commit-ID: 2RGOulCInSu --HG-- extra : rebase_source : 3542b804c3def36fa74541be32d0e7cbc9698641 --- dom/canvas/WebGLContext.cpp | 83 +++++------------------ dom/canvas/WebGLContext.h | 1 - dom/html/HTMLCanvasElement.cpp | 29 +------- dom/html/HTMLCanvasElement.h | 3 - gfx/vr/VRDisplayHost.cpp | 117 +++++++++++++++++++-------------- gfx/vr/VRDisplayHost.h | 16 ++--- gfx/vr/VRManager.cpp | 14 ---- gfx/vr/VRManager.h | 6 -- gfx/vr/gfxVROSVR.cpp | 2 +- gfx/vr/gfxVROSVR.h | 2 +- gfx/vr/gfxVROculus.cpp | 21 +++--- gfx/vr/gfxVROculus.h | 2 +- gfx/vr/gfxVROpenVR.cpp | 4 +- gfx/vr/gfxVROpenVR.h | 2 +- gfx/vr/gfxVRPuppet.cpp | 24 +++---- gfx/vr/gfxVRPuppet.h | 2 +- gfx/vr/ipc/PVRLayer.ipdl | 4 +- gfx/vr/ipc/VRLayerChild.cpp | 53 ++++++++------- gfx/vr/ipc/VRLayerChild.h | 7 +- gfx/vr/ipc/VRLayerParent.cpp | 9 ++- gfx/vr/ipc/VRLayerParent.h | 2 +- 21 files changed, 166 insertions(+), 237 deletions(-) diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp index 5e4051138254..a0cb3950b202 100644 --- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -2333,80 +2333,27 @@ WebGLContext::GetUnpackSize(bool isFunc3D, uint32_t width, uint32_t height, already_AddRefed WebGLContext::GetVRFrame() { - if (!mLayerIsMirror) { - /** - * Do not allow VR frame submission until a mirroring canvas layer has - * been returned by GetCanvasLayer - */ - return nullptr; - } + /** + * Swap buffers as though composition has occurred. + * We will then share the resulting front buffer to be submitted to the VR + * compositor. + */ + BeginComposition(); + EndComposition(); - VRManagerChild* vrmc = VRManagerChild::Get(); - if (!vrmc) { - return nullptr; - } + gl::GLScreenBuffer* screen = gl->Screen(); + if (!screen) { + return nullptr; + } - /** - * Swap buffers as though composition has occurred. - * We will then share the resulting front buffer to be submitted to the VR - * compositor. - */ - BeginComposition(); - EndComposition(); - - gl::GLScreenBuffer* screen = gl->Screen(); - if (!screen) { - return nullptr; - } - - RefPtr sharedSurface = screen->Front(); - if (!sharedSurface) { - return nullptr; - } - - if (sharedSurface && sharedSurface->GetAllocator() != vrmc) { - RefPtr dest = - screen->Factory()->NewTexClient(sharedSurface->GetSize(), vrmc); - if (!dest) { - return nullptr; - } - gl::SharedSurface* destSurf = dest->Surf(); - destSurf->ProducerAcquire(); - SharedSurface::ProdCopy(sharedSurface->Surf(), dest->Surf(), - screen->Factory()); - destSurf->ProducerRelease(); - - return dest.forget(); - } + RefPtr sharedSurface = screen->Front(); + if (!sharedSurface) { + return nullptr; + } return sharedSurface.forget(); } -bool -WebGLContext::StartVRPresentation() -{ - VRManagerChild* vrmc = VRManagerChild::Get(); - if (!vrmc) { - return false; - } - gl::GLScreenBuffer* screen = gl->Screen(); - if (!screen) { - return false; - } - gl::SurfaceCaps caps = screen->mCaps; - - UniquePtr factory = - gl::GLScreenBuffer::CreateFactory(gl, - caps, - vrmc, - TextureFlags::ORIGIN_BOTTOM_LEFT); - - if (factory) { - screen->Morph(Move(factory)); - } - return true; -} - //////////////////////////////////////////////////////////////////////////////// static inline size_t diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index da7de1342781..51f022e4a5e0 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -642,7 +642,6 @@ public: void PolygonOffset(GLfloat factor, GLfloat units); already_AddRefed GetVRFrame(); - bool StartVRPresentation(); //// diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index fc4f206426d3..68f2d29872ca 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -378,7 +378,6 @@ NS_IMPL_ISUPPORTS(HTMLCanvasElementObserver, nsIObserver) HTMLCanvasElement::HTMLCanvasElement(already_AddRefed& aNodeInfo) : nsGenericHTMLElement(aNodeInfo), mResetLayer(true) , - mVRPresentationActive(false), mWriteOnly(false) {} @@ -1160,7 +1159,7 @@ HTMLCanvasElement::GetCanvasLayer(nsDisplayListBuilder* aBuilder, static uint8_t sOffscreenCanvasLayerUserDataDummy = 0; if (mCurrentContext) { - return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager, mVRPresentationActive); + return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager); } if (mOffscreenCanvas) { @@ -1503,32 +1502,6 @@ HTMLCanvasElement::InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRende element->InvalidateCanvasContent(nullptr); } -void -HTMLCanvasElement::StartVRPresentation() -{ - if (GetCurrentContextType() != CanvasContextType::WebGL1 && - GetCurrentContextType() != CanvasContextType::WebGL2) { - return; - } - - WebGLContext* webgl = static_cast(GetContextAtIndex(0)); - if (!webgl) { - return; - } - - if (!webgl->StartVRPresentation()) { - return; - } - - mVRPresentationActive = true; -} - -void -HTMLCanvasElement::StopVRPresentation() -{ - mVRPresentationActive = false; -} - already_AddRefed HTMLCanvasElement::GetVRFrame() { diff --git a/dom/html/HTMLCanvasElement.h b/dom/html/HTMLCanvasElement.h index 366683e6def0..a3e3556c87c9 100644 --- a/dom/html/HTMLCanvasElement.h +++ b/dom/html/HTMLCanvasElement.h @@ -341,8 +341,6 @@ public: static void SetAttrFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer); static void InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer); - void StartVRPresentation(); - void StopVRPresentation(); already_AddRefed GetVRFrame(); protected: @@ -386,7 +384,6 @@ protected: RefPtr mAsyncCanvasRenderer; RefPtr mOffscreenCanvas; RefPtr mContextObserver; - bool mVRPresentationActive; public: // Record whether this canvas should be write-only or not. diff --git a/gfx/vr/VRDisplayHost.cpp b/gfx/vr/VRDisplayHost.cpp index 8d98e46159b1..9e5088a28016 100644 --- a/gfx/vr/VRDisplayHost.cpp +++ b/gfx/vr/VRDisplayHost.cpp @@ -255,7 +255,8 @@ VRDisplayHost::NotifyVSync() } void -VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, PTextureParent* aTexture, +VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, + const layers::SurfaceDescriptor &aTexture, uint64_t aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) @@ -273,59 +274,75 @@ VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, PTextureParent* aTexture, } mFrameStarted = false; + switch (aTexture.type()) { + #if defined(XP_WIN) + case SurfaceDescriptor::TSurfaceDescriptorD3D10: { + if (!CreateD3DObjects()) { + return; + } + const SurfaceDescriptorD3D10& surf = aTexture.get_SurfaceDescriptorD3D10(); + RefPtr dxTexture; + HRESULT hr = mDevice->OpenSharedResource((HANDLE)surf.handle(), + __uuidof(ID3D11Texture2D), + (void**)(ID3D11Texture2D**)getter_AddRefs(dxTexture)); + if (FAILED(hr) || !dxTexture) { + NS_WARNING("Failed to open shared texture"); + return; + } - 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("VRDisplayHost::SubmitFrame failed to get a TextureSourceD3D11"); - return; - } - - if (!SubmitFrame(sourceD3D11, texSize, aLeftEyeRect, aRightEyeRect)) { - return; - } - + // Similar to LockD3DTexture in TextureD3D11.cpp + RefPtr mutex; + dxTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex)); + if (mutex) { + HRESULT hr = mutex->AcquireSync(0, 1000); + if (hr == WAIT_TIMEOUT) { + gfxDevCrash(LogReason::D3DLockTimeout) << "D3D lock mutex timeout"; + } + else if (hr == WAIT_ABANDONED) { + gfxCriticalNote << "GFX: D3D11 lock mutex abandoned"; + } + if (FAILED(hr)) { + NS_WARNING("Failed to lock the texture"); + return; + } + } + bool success = SubmitFrame(dxTexture, surf.size(), + aLeftEyeRect, aRightEyeRect); + if (mutex) { + HRESULT hr = mutex->ReleaseSync(0); + if (FAILED(hr)) { + NS_WARNING("Failed to unlock the texture"); + } + } + if (!success) { + return; + } + break; + } #elif defined(XP_MACOSX) - - TextureHost* th = TextureHost::AsTextureHost(aTexture); - - MacIOSurface* surf = th->GetMacIOSurface(); - if (!surf) { - NS_WARNING("VRDisplayHost::SubmitFrame failed to get a MacIOSurface"); - return; - } - - IntSize texSize = gfx::IntSize(surf->GetDevicePixelWidth(), - surf->GetDevicePixelHeight()); - - if (!SubmitFrame(surf, texSize, aLeftEyeRect, aRightEyeRect)) { - return; - } - -#else - - NS_WARNING("WebVR is not supported on this platform."); - return; + case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: { + const auto& desc = aTexture.get_SurfaceDescriptorMacIOSurface(); + RefPtr surf = MacIOSurface::LookupSurface(desc.surfaceId(), + desc.scaleFactor(), + !desc.isOpaque()); + if (!surf) { + NS_WARNING("VRDisplayHost::SubmitFrame failed to get a MacIOSurface"); + return; + } + IntSize texSize = gfx::IntSize(surf->GetDevicePixelWidth(), + surf->GetDevicePixelHeight()); + if (!SubmitFrame(surf, texSize, aLeftEyeRect, aRightEyeRect)) { + return; + } + break; + } #endif + default: { + NS_WARNING("Unsupported SurfaceDescriptor type for VR layer texture"); + return; + } + } #if defined(XP_WIN) || defined(XP_MACOSX) diff --git a/gfx/vr/VRDisplayHost.h b/gfx/vr/VRDisplayHost.h index f28a5c2c7a6c..b87cd5af6a0f 100644 --- a/gfx/vr/VRDisplayHost.h +++ b/gfx/vr/VRDisplayHost.h @@ -17,20 +17,14 @@ #include "mozilla/TimeStamp.h" #include "mozilla/TypedEnumBits.h" #include "mozilla/dom/GamepadPoseState.h" +#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor + #if defined(XP_WIN) #include -#endif - -#if defined(XP_MACOSX) +#elif defined(XP_MACOSX) class MacIOSurface; #endif namespace mozilla { -namespace layers { -class PTextureParent; -#if defined(XP_WIN) -class TextureSourceD3D11; -#endif -} // namespace layers namespace gfx { class VRLayerParent; @@ -50,7 +44,7 @@ public: void StartFrame(); void SubmitFrame(VRLayerParent* aLayer, - mozilla::layers::PTextureParent* aTexture, + const layers::SurfaceDescriptor& aTexture, uint64_t aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect); @@ -81,7 +75,7 @@ protected: // Returns true if the SubmitFrame call will block as necessary // to control timing of the next frame and throttle the render loop // for the needed framerate. - virtual bool SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource, + virtual bool SubmitFrame(ID3D11Texture2D* aSource, const IntSize& aSize, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) = 0; diff --git a/gfx/vr/VRManager.cpp b/gfx/vr/VRManager.cpp index 8c82875771a8..1916dc212e78 100644 --- a/gfx/vr/VRManager.cpp +++ b/gfx/vr/VRManager.cpp @@ -343,20 +343,6 @@ VRManager::GetDisplay(const uint32_t& aDisplayID) return nullptr; } -void -VRManager::SubmitFrame(VRLayerParent* aLayer, layers::PTextureParent* aTexture, - uint64_t aFrameId, - const gfx::Rect& aLeftEyeRect, - const gfx::Rect& aRightEyeRect) -{ - TextureHost* th = TextureHost::AsTextureHost(aTexture); - mLastFrame = th; - RefPtr display = GetDisplay(aLayer->GetDisplayID()); - if (display) { - display->SubmitFrame(aLayer, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect); - } -} - RefPtr VRManager::GetController(const uint32_t& aControllerID) { diff --git a/gfx/vr/VRManager.h b/gfx/vr/VRManager.h index 4e7035857351..5a467cea22ba 100644 --- a/gfx/vr/VRManager.h +++ b/gfx/vr/VRManager.h @@ -43,11 +43,6 @@ public: template void NotifyGamepadChange(uint32_t aIndex, const T& aInfo); RefPtr GetDisplay(const uint32_t& aDisplayID); void GetVRDisplayInfo(nsTArray& aDisplayInfo); - - void SubmitFrame(VRLayerParent* aLayer, layers::PTextureParent* aTexture, - uint64_t aFrameId, - const gfx::Rect& aLeftEyeRect, - const gfx::Rect& aRightEyeRect); RefPtr GetController(const uint32_t& aControllerID); void GetVRControllerInfo(nsTArray& aControllerInfo); void CreateVRTestSystem(); @@ -62,7 +57,6 @@ protected: ~VRManager(); private: - RefPtr mLastFrame; void Init(); void Destroy(); diff --git a/gfx/vr/gfxVROSVR.cpp b/gfx/vr/gfxVROSVR.cpp index 7ed8c5b361f5..42741c50eddd 100644 --- a/gfx/vr/gfxVROSVR.cpp +++ b/gfx/vr/gfxVROSVR.cpp @@ -321,7 +321,7 @@ VRDisplayOSVR::GetSensorState() #if defined(XP_WIN) bool -VRDisplayOSVR::SubmitFrame(TextureSourceD3D11* aSource, +VRDisplayOSVR::SubmitFrame(ID3D11Texture2D* aSource, const IntSize& aSize, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) diff --git a/gfx/vr/gfxVROSVR.h b/gfx/vr/gfxVROSVR.h index 31d6a09cb125..2b4bbdfa7869 100644 --- a/gfx/vr/gfxVROSVR.h +++ b/gfx/vr/gfxVROSVR.h @@ -36,7 +36,7 @@ protected: virtual void StopPresentation() override; #if defined(XP_WIN) - virtual bool SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource, + virtual bool SubmitFrame(ID3D11Texture2D* aSource, const IntSize& aSize, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) override; diff --git a/gfx/vr/gfxVROculus.cpp b/gfx/vr/gfxVROculus.cpp index e4946c4c5eb3..5fe03bb29372 100644 --- a/gfx/vr/gfxVROculus.cpp +++ b/gfx/vr/gfxVROculus.cpp @@ -1032,10 +1032,10 @@ VRDisplayOculus::UpdateConstantBuffers() } bool -VRDisplayOculus::SubmitFrame(TextureSourceD3D11* aSource, - const IntSize& aSize, - const gfx::Rect& aLeftEyeRect, - const gfx::Rect& aRightEyeRect) +VRDisplayOculus::SubmitFrame(ID3D11Texture2D* aSource, + const IntSize& aSize, + const gfx::Rect& aLeftEyeRect, + const gfx::Rect& aRightEyeRect) { if (!CreateD3DObjects()) { return false; @@ -1105,12 +1105,15 @@ VRDisplayOculus::SubmitFrame(TextureSourceD3D11* aSource, mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); mContext->VSSetShader(mQuadVS, nullptr, 0); mContext->PSSetShader(mQuadPS, nullptr, 0); - ID3D11ShaderResourceView* srView = aSource->GetShaderResourceView(); - if (!srView) { - NS_WARNING("Failed to get SRV for Oculus"); - return false; + + RefPtr srView; + HRESULT hr = mDevice->CreateShaderResourceView(aSource, nullptr, getter_AddRefs(srView)); + if (FAILED(hr)) { + gfxWarning() << "Could not create shader resource view for Oculus: " << hexa(hr); + return nullptr; } - mContext->PSSetShaderResources(0 /* 0 == TexSlot::RGB */, 1, &srView); + ID3D11ShaderResourceView* viewPtr = srView.get(); + mContext->PSSetShaderResources(0 /* 0 == TexSlot::RGB */, 1, &viewPtr); // XXX Use Constant from TexSlot in CompositorD3D11.cpp? ID3D11SamplerState *sampler = mLinearSamplerState; diff --git a/gfx/vr/gfxVROculus.h b/gfx/vr/gfxVROculus.h index e625820da354..77ca663c7d5e 100644 --- a/gfx/vr/gfxVROculus.h +++ b/gfx/vr/gfxVROculus.h @@ -89,7 +89,7 @@ protected: virtual VRHMDSensorState GetSensorState() override; virtual void StartPresentation() override; virtual void StopPresentation() override; - virtual bool SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource, + virtual bool SubmitFrame(ID3D11Texture2D* aSource, const IntSize& aSize, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) override; diff --git a/gfx/vr/gfxVROpenVR.cpp b/gfx/vr/gfxVROpenVR.cpp index 6c4c421aaa8b..9ab7b2b960ce 100644 --- a/gfx/vr/gfxVROpenVR.cpp +++ b/gfx/vr/gfxVROpenVR.cpp @@ -364,12 +364,12 @@ VRDisplayOpenVR::SubmitFrame(void* aTextureHandle, #if defined(XP_WIN) bool -VRDisplayOpenVR::SubmitFrame(TextureSourceD3D11* aSource, +VRDisplayOpenVR::SubmitFrame(ID3D11Texture2D* aSource, const IntSize& aSize, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) { - return SubmitFrame((void *)aSource->GetD3D11Texture(), + return SubmitFrame((void *)aSource, ::vr::ETextureType::TextureType_DirectX, aSize, aLeftEyeRect, aRightEyeRect); } diff --git a/gfx/vr/gfxVROpenVR.h b/gfx/vr/gfxVROpenVR.h index e68cbd34adc9..5840abaa76cc 100644 --- a/gfx/vr/gfxVROpenVR.h +++ b/gfx/vr/gfxVROpenVR.h @@ -38,7 +38,7 @@ protected: virtual void StartPresentation() override; virtual void StopPresentation() override; #if defined(XP_WIN) - virtual bool SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource, + virtual bool SubmitFrame(ID3D11Texture2D* aSource, const IntSize& aSize, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) override; diff --git a/gfx/vr/gfxVRPuppet.cpp b/gfx/vr/gfxVRPuppet.cpp index 4e2d0744b306..5ec1780cafd5 100644 --- a/gfx/vr/gfxVRPuppet.cpp +++ b/gfx/vr/gfxVRPuppet.cpp @@ -274,7 +274,7 @@ VRDisplayPuppet::UpdateConstantBuffers() } bool -VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource, +VRDisplayPuppet::SubmitFrame(ID3D11Texture2D* aSource, const IntSize& aSize, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) @@ -303,14 +303,13 @@ VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource, // The frames are submitted to VR compositor are decoded // into a base64Image and dispatched to the DOM side. D3D11_TEXTURE2D_DESC desc; - ID3D11Texture2D* texture = aSource->GetD3D11Texture(); - texture->GetDesc(&desc); + aSource->GetDesc(&desc); MOZ_ASSERT(desc.Format == DXGI_FORMAT_B8G8R8A8_UNORM, "Only support B8G8R8A8_UNORM format."); // Map the staging resource ID3D11Texture2D* mappedTexture = nullptr; D3D11_MAPPED_SUBRESOURCE mapInfo; - HRESULT hr = mContext->Map(texture, + HRESULT hr = mContext->Map(aSource, 0, // Subsource D3D11_MAP_READ, 0, // MapFlags @@ -338,7 +337,7 @@ VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource, return false; } // Copy the texture to a staging resource - mContext->CopyResource(stagingTexture, texture); + mContext->CopyResource(stagingTexture, aSource); // Map the staging resource hr = mContext->Map(stagingTexture, 0, // Subsource @@ -354,7 +353,7 @@ VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource, return false; } } else { - mappedTexture = texture; + mappedTexture = aSource; } // Ideally, we should convert the srcData to a PNG image and decode it // to a Base64 string here, but the GPU process does not have the privilege to @@ -429,12 +428,15 @@ VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource, mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); mContext->VSSetShader(mQuadVS, nullptr, 0); mContext->PSSetShader(mQuadPS, nullptr, 0); - ID3D11ShaderResourceView* srView = aSource->GetShaderResourceView(); - if (!srView) { - NS_WARNING("Failed to get SRV for Puppet"); - return false; + + RefPtr srView; + HRESULT hr = mDevice->CreateShaderResourceView(aSource, nullptr, getter_AddRefs(srView)); + if (FAILED(hr) || !srView) { + gfxWarning() << "Could not create shader resource view for Puppet: " << hexa(hr); + return nullptr; } - mContext->PSSetShaderResources(0 /* 0 == TexSlot::RGB */, 1, &srView); + ID3D11ShaderResourceView* viewPtr = srView.get(); + mContext->PSSetShaderResources(0 /* 0 == TexSlot::RGB */, 1, &viewPtr); // XXX Use Constant from TexSlot in CompositorD3D11.cpp? ID3D11SamplerState *sampler = mLinearSamplerState; diff --git a/gfx/vr/gfxVRPuppet.h b/gfx/vr/gfxVRPuppet.h index 790eb7e98798..59348050c8d8 100644 --- a/gfx/vr/gfxVRPuppet.h +++ b/gfx/vr/gfxVRPuppet.h @@ -32,7 +32,7 @@ protected: virtual void StartPresentation() override; virtual void StopPresentation() override; #if defined(XP_WIN) - virtual bool SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource, + virtual bool SubmitFrame(ID3D11Texture2D* aSource, const IntSize& aSize, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) override; diff --git a/gfx/vr/ipc/PVRLayer.ipdl b/gfx/vr/ipc/PVRLayer.ipdl index 42ebde764e38..5c73ccff2cba 100644 --- a/gfx/vr/ipc/PVRLayer.ipdl +++ b/gfx/vr/ipc/PVRLayer.ipdl @@ -5,8 +5,8 @@ * 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 LayersSurfaces; include protocol PVRManager; -include protocol PTexture; using mozilla::gfx::Rect from "mozilla/gfx/Rect.h"; @@ -18,7 +18,7 @@ async protocol PVRLayer manager PVRManager; parent: - async SubmitFrame(PTexture aTexture, uint64_t aFrameId, + async SubmitFrame(SurfaceDescriptor aTexture, uint64_t aFrameId, Rect aLeftEyeRect, Rect aRightEyeRect); async Destroy(); diff --git a/gfx/vr/ipc/VRLayerChild.cpp b/gfx/vr/ipc/VRLayerChild.cpp index 29b513c3020c..c5509c27a6c3 100644 --- a/gfx/vr/ipc/VRLayerChild.cpp +++ b/gfx/vr/ipc/VRLayerChild.cpp @@ -11,25 +11,21 @@ #include "mozilla/layers/LayersMessages.h" // for TimedTexture #include "nsICanvasRenderingContextInternal.h" #include "mozilla/dom/HTMLCanvasElement.h" +#include "mozilla/layers/SyncObject.h" // for SyncObjectClient namespace mozilla { namespace gfx { VRLayerChild::VRLayerChild() : mCanvasElement(nullptr) - , mShSurfClient(nullptr) - , mFront(nullptr) , mIPCOpen(false) + , mLastSubmittedFrameId(0) { MOZ_COUNT_CTOR(VRLayerChild); } VRLayerChild::~VRLayerChild() { - if (mCanvasElement) { - mCanvasElement->StopVRPresentation(); - } - ClearSurfaces(); MOZ_COUNT_DTOR(VRLayerChild); @@ -40,7 +36,6 @@ VRLayerChild::Initialize(dom::HTMLCanvasElement* aCanvasElement, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) { MOZ_ASSERT(aCanvasElement); - aCanvasElement->StartVRPresentation(); mLeftEyeRect = aLeftEyeRect; mRightEyeRect = aRightEyeRect; if (mCanvasElement == nullptr) { @@ -55,31 +50,45 @@ VRLayerChild::Initialize(dom::HTMLCanvasElement* aCanvasElement, void VRLayerChild::SubmitFrame(uint64_t aFrameId) { - if (!mCanvasElement) { + // aFrameId will not increment unless the previuosly submitted + // frame was received by the VR thread and submitted to the VR + // compositor. We early-exit here in the event that SubmitFrame + // was called twice for the same aFrameId. + if (!mCanvasElement || aFrameId == mLastSubmittedFrameId) { return; } + mLastSubmittedFrameId = aFrameId; - mShSurfClient = mCanvasElement->GetVRFrame(); - if (!mShSurfClient) { + // Keep the SharedSurfaceTextureClient alive long enough for + // 1 extra frame, accomodating overlapped asynchronous rendering. + mLastFrameTexture = mThisFrameTexture; + + mThisFrameTexture = mCanvasElement->GetVRFrame(); + if (!mThisFrameTexture) { return; } + VRManagerChild* vrmc = VRManagerChild::Get(); + layers::SyncObjectClient* syncObject = vrmc->GetSyncObject(); + mThisFrameTexture->SyncWithObject(syncObject); + if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { + if (syncObject && syncObject->IsSyncObjectValid()) { + syncObject->Synchronize(); + } + } - gl::SharedSurface* surf = mShSurfClient->Surf(); + gl::SharedSurface* surf = mThisFrameTexture->Surf(); if (surf->mType == gl::SharedSurfaceType::Basic) { gfxCriticalError() << "SharedSurfaceType::Basic not supported for WebVR"; return; } - mFront = mShSurfClient; - mShSurfClient = nullptr; + layers::SurfaceDescriptor desc; + if (!surf->ToSurfaceDescriptor(&desc)) { + gfxCriticalError() << "SharedSurface::ToSurfaceDescriptor failed in VRLayerChild::SubmitFrame"; + return; + } - mFront->SetAddedToCompositableClient(); - VRManagerChild* vrmc = VRManagerChild::Get(); - mFront->SyncWithObject(vrmc->GetSyncObject()); - MOZ_ALWAYS_TRUE(mFront->InitIPDLActor(vrmc)); - - SendSubmitFrame(mFront->GetIPDLActor(), aFrameId, - mLeftEyeRect, mRightEyeRect); + SendSubmitFrame(desc, aFrameId, mLeftEyeRect, mRightEyeRect); } bool @@ -91,8 +100,8 @@ VRLayerChild::IsIPCOpen() void VRLayerChild::ClearSurfaces() { - mFront = nullptr; - mShSurfClient = nullptr; + mThisFrameTexture = nullptr; + mLastFrameTexture = nullptr; } void diff --git a/gfx/vr/ipc/VRLayerChild.h b/gfx/vr/ipc/VRLayerChild.h index a4a1e6f3b5bf..f0d430f3fb02 100644 --- a/gfx/vr/ipc/VRLayerChild.h +++ b/gfx/vr/ipc/VRLayerChild.h @@ -47,8 +47,6 @@ private: virtual void ActorDestroy(ActorDestroyReason aWhy) override; RefPtr mCanvasElement; - RefPtr mShSurfClient; - RefPtr mFront; bool mIPCOpen; // AddIPDLReference and ReleaseIPDLReference are only to be called by CreateIPDLActor @@ -60,6 +58,11 @@ private: gfx::Rect mLeftEyeRect; gfx::Rect mRightEyeRect; + + RefPtr mThisFrameTexture; + RefPtr mLastFrameTexture; + + uint64_t mLastSubmittedFrameId; }; } // namespace gfx diff --git a/gfx/vr/ipc/VRLayerParent.cpp b/gfx/vr/ipc/VRLayerParent.cpp index 3992d4cf65dc..919781d064ec 100644 --- a/gfx/vr/ipc/VRLayerParent.cpp +++ b/gfx/vr/ipc/VRLayerParent.cpp @@ -6,6 +6,7 @@ #include "VRLayerParent.h" #include "mozilla/Unused.h" +#include "VRDisplayHost.h" namespace mozilla { namespace gfx { @@ -55,14 +56,18 @@ VRLayerParent::Destroy() } mozilla::ipc::IPCResult -VRLayerParent::RecvSubmitFrame(PTextureParent* texture, +VRLayerParent::RecvSubmitFrame(const layers::SurfaceDescriptor &aTexture, const uint64_t& aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) { if (mVRDisplayID) { VRManager* vm = VRManager::Get(); - vm->SubmitFrame(this, texture, aFrameId, aLeftEyeRect, aRightEyeRect); + RefPtr display = vm->GetDisplay(mVRDisplayID); + if (display) { + display->SubmitFrame(this, aTexture, aFrameId, + aLeftEyeRect, aRightEyeRect); + } } return IPC_OK(); diff --git a/gfx/vr/ipc/VRLayerParent.h b/gfx/vr/ipc/VRLayerParent.h index cfcb1463efa4..d11d787682e6 100644 --- a/gfx/vr/ipc/VRLayerParent.h +++ b/gfx/vr/ipc/VRLayerParent.h @@ -20,7 +20,7 @@ class VRLayerParent : public PVRLayerParent { public: VRLayerParent(uint32_t aVRDisplayID, const uint32_t aGroup); - virtual mozilla::ipc::IPCResult RecvSubmitFrame(PTextureParent* texture, + virtual mozilla::ipc::IPCResult RecvSubmitFrame(const layers::SurfaceDescriptor &aTexture, const uint64_t& aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) override;