--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -2328,90 +2328,37 @@ WebGLContext::GetUnpackSize(bool isFunc3
totalBytes += usedBytesPerRow;
return totalBytes;
}
already_AddRefed<layers::SharedSurfaceTextureClient>
WebGLContext::GetVRFrame()
{
- if (!mLayerIsMirror) {
- /**
- * Do not allow VR frame submission until a mirroring canvas layer has
- * been returned by GetCanvasLayer
- */
- return nullptr;
- }
-
- VRManagerChild* vrmc = VRManagerChild::Get();
- if (!vrmc) {
- 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<SharedSurfaceTextureClient> sharedSurface = screen->Front();
- if (!sharedSurface) {
- return nullptr;
- }
-
- if (sharedSurface && sharedSurface->GetAllocator() != vrmc) {
- RefPtr<SharedSurfaceTextureClient> 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();
- }
+ /**
+ * 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<SharedSurfaceTextureClient> 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<gl::SurfaceFactory> factory =
- gl::GLScreenBuffer::CreateFactory(gl,
- caps,
- vrmc,
- TextureFlags::ORIGIN_BOTTOM_LEFT);
-
- if (factory) {
- screen->Morph(Move(factory));
- }
- return true;
-}
-
////////////////////////////////////////////////////////////////////////////////
static inline size_t
SizeOfViewElem(const dom::ArrayBufferView& view)
{
const auto& elemType = view.Type();
if (elemType == js::Scalar::MaxTypedArrayViewType) // DataViews.
return 1;
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -637,17 +637,16 @@ public:
bool IsShader(const WebGLShader* shader);
bool IsVertexArray(const WebGLVertexArray* vao);
void LineWidth(GLfloat width);
void LinkProgram(WebGLProgram& prog);
void PixelStorei(GLenum pname, GLint param);
void PolygonOffset(GLfloat factor, GLfloat units);
already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
- bool StartVRPresentation();
////
webgl::PackingInfo
ValidImplementationColorReadPI(const webgl::FormatUsageInfo* usage) const;
protected:
bool ReadPixels_SharedPrecheck(dom::CallerType aCallerType,
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -373,17 +373,16 @@ HTMLCanvasElementObserver::HandleEvent(n
NS_IMPL_ISUPPORTS(HTMLCanvasElementObserver, nsIObserver)
// ---------------------------------------------------------------------------
HTMLCanvasElement::HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsGenericHTMLElement(aNodeInfo),
mResetLayer(true) ,
- mVRPresentationActive(false),
mWriteOnly(false)
{}
HTMLCanvasElement::~HTMLCanvasElement()
{
if (mContextObserver) {
mContextObserver->Destroy();
mContextObserver = nullptr;
@@ -1155,17 +1154,17 @@ HTMLCanvasElement::GetCanvasLayer(nsDisp
{
// The address of sOffscreenCanvasLayerUserDataDummy is used as the user
// data key for retained LayerManagers managed by FrameLayerBuilder.
// We don't much care about what value in it, so just assign a dummy
// value for it.
static uint8_t sOffscreenCanvasLayerUserDataDummy = 0;
if (mCurrentContext) {
- return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager, mVRPresentationActive);
+ return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager);
}
if (mOffscreenCanvas) {
if (!mResetLayer &&
aOldLayer && aOldLayer->HasUserData(&sOffscreenCanvasLayerUserDataDummy)) {
RefPtr<Layer> ret = aOldLayer;
return ret.forget();
}
@@ -1498,42 +1497,16 @@ HTMLCanvasElement::InvalidateFromAsyncCa
HTMLCanvasElement *element = aRenderer->mHTMLCanvasElement;
if (!element) {
return;
}
element->InvalidateCanvasContent(nullptr);
}
-void
-HTMLCanvasElement::StartVRPresentation()
-{
- if (GetCurrentContextType() != CanvasContextType::WebGL1 &&
- GetCurrentContextType() != CanvasContextType::WebGL2) {
- return;
- }
-
- WebGLContext* webgl = static_cast<WebGLContext*>(GetContextAtIndex(0));
- if (!webgl) {
- return;
- }
-
- if (!webgl->StartVRPresentation()) {
- return;
- }
-
- mVRPresentationActive = true;
-}
-
-void
-HTMLCanvasElement::StopVRPresentation()
-{
- mVRPresentationActive = false;
-}
-
already_AddRefed<layers::SharedSurfaceTextureClient>
HTMLCanvasElement::GetVRFrame()
{
if (GetCurrentContextType() != CanvasContextType::WebGL1 &&
GetCurrentContextType() != CanvasContextType::WebGL2) {
return nullptr;
}
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -336,18 +336,16 @@ public:
void OnVisibilityChange();
void OnMemoryPressure();
static void SetAttrFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
static void InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
- void StartVRPresentation();
- void StopVRPresentation();
already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
protected:
virtual ~HTMLCanvasElement();
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
virtual nsIntSize GetWidthHeight() override;
@@ -381,17 +379,16 @@ protected:
RefPtr<HTMLCanvasElement> mOriginalCanvas;
RefPtr<PrintCallback> mPrintCallback;
RefPtr<HTMLCanvasPrintState> mPrintState;
nsTArray<WeakPtr<FrameCaptureListener>> mRequestedFrameListeners;
RefPtr<RequestedFrameRefreshObserver> mRequestedFrameRefreshObserver;
RefPtr<AsyncCanvasRenderer> mAsyncCanvasRenderer;
RefPtr<OffscreenCanvas> mOffscreenCanvas;
RefPtr<HTMLCanvasElementObserver> mContextObserver;
- bool mVRPresentationActive;
public:
// Record whether this canvas should be write-only or not.
// We set this when script paints an image from a different origin.
// We also transitively set it when script paints a canvas which
// is itself write-only.
bool mWriteOnly;
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -250,17 +250,18 @@ VRDisplayHost::NotifyVSync()
if (bShouldStartFrame) {
VRManager *vm = VRManager::Get();
MOZ_ASSERT(vm);
vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
}
}
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)
{
AutoProfilerTracing tracing("VR", "SubmitFrameAtVRDisplayHost");
if ((mDisplayInfo.mGroupMask & aLayer->GetGroup()) == 0) {
// Suppress layers hidden by the group mask
@@ -268,70 +269,86 @@ VRDisplayHost::SubmitFrame(VRLayerParent
}
// Ensure that we only accept the first SubmitFrame call per RAF cycle.
if (!mFrameStarted || aFrameId != mDisplayInfo.mFrameId) {
return;
}
mFrameStarted = false;
-#if defined(XP_WIN)
-
- 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;
- }
+ switch (aTexture.type()) {
- 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 defined(XP_WIN)
+ case SurfaceDescriptor::TSurfaceDescriptorD3D10: {
+ if (!CreateD3DObjects()) {
+ return;
+ }
+ const SurfaceDescriptorD3D10& surf = aTexture.get_SurfaceDescriptorD3D10();
+ RefPtr<ID3D11Texture2D> 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;
+ }
- if (!SubmitFrame(sourceD3D11, texSize, aLeftEyeRect, aRightEyeRect)) {
- return;
- }
-
+ // Similar to LockD3DTexture in TextureD3D11.cpp
+ RefPtr<IDXGIKeyedMutex> 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;
+ case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
+ const auto& desc = aTexture.get_SurfaceDescriptorMacIOSurface();
+ RefPtr<MacIOSurface> 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;
+ }
}
- 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;
-#endif
-
#if defined(XP_WIN) || defined(XP_MACOSX)
/**
* Trigger the next VSync immediately after we are successfully
* submitting frames. As SubmitFrame is responsible for throttling
* the render loop, if we don't successfully call it, we shouldn't trigger
* NotifyVRVsync immediately, as it will run unbounded.
* If NotifyVRVsync is not called here due to SubmitFrame failing, the
--- a/gfx/vr/VRDisplayHost.h
+++ b/gfx/vr/VRDisplayHost.h
@@ -12,30 +12,24 @@
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/Atomics.h"
#include "mozilla/EnumeratedArray.h"
#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 <d3d11_1.h>
-#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;
class VRDisplayHost {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRDisplayHost)
const VRDisplayInfo& GetDisplayInfo() const { return mDisplayInfo; }
@@ -45,17 +39,17 @@ public:
virtual void ZeroSensor() = 0;
virtual void StartPresentation() = 0;
virtual void StopPresentation() = 0;
virtual void NotifyVSync();
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);
bool CheckClearDisplayInfoDirty();
void SetGroupMask(uint32_t aGroupMask);
bool GetIsConnected();
@@ -76,17 +70,17 @@ protected:
explicit VRDisplayHost(VRDeviceType aType);
virtual ~VRDisplayHost();
#if defined(XP_WIN)
// Subclasses should override this SubmitFrame function.
// 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;
#elif defined(XP_MACOSX)
virtual bool SubmitFrame(MacIOSurface* aMacIOSurface,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) = 0;
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -338,30 +338,16 @@ VRManager::GetDisplay(const uint32_t& aD
{
RefPtr<gfx::VRDisplayHost> display;
if (mVRDisplays.Get(aDisplayID, getter_AddRefs(display))) {
return display;
}
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<VRDisplayHost> display = GetDisplay(aLayer->GetDisplayID());
- if (display) {
- display->SubmitFrame(aLayer, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect);
- }
-}
-
RefPtr<gfx::VRControllerHost>
VRManager::GetController(const uint32_t& aControllerID)
{
RefPtr<gfx::VRControllerHost> controller;
if (mVRControllers.Get(aControllerID, getter_AddRefs(controller))) {
return controller;
}
return nullptr;
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -38,36 +38,30 @@ public:
void NotifyVRVsync(const uint32_t& aDisplayID);
void RefreshVRDisplays(bool aMustDispatch = false);
void RefreshVRControllers();
void ScanForControllers();
void RemoveControllers();
template<class T> void NotifyGamepadChange(uint32_t aIndex, const T& aInfo);
RefPtr<gfx::VRDisplayHost> GetDisplay(const uint32_t& aDisplayID);
void GetVRDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayInfo);
-
- void SubmitFrame(VRLayerParent* aLayer, layers::PTextureParent* aTexture,
- uint64_t aFrameId,
- const gfx::Rect& aLeftEyeRect,
- const gfx::Rect& aRightEyeRect);
RefPtr<gfx::VRControllerHost> GetController(const uint32_t& aControllerID);
void GetVRControllerInfo(nsTArray<VRControllerInfo>& aControllerInfo);
void CreateVRTestSystem();
void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
double aIntensity, double aDuration, uint32_t aPromiseID);
void StopVibrateHaptic(uint32_t aControllerIdx);
void NotifyVibrateHapticCompleted(uint32_t aPromiseID);
void DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameResultInfo& aResult);
protected:
VRManager();
~VRManager();
private:
- RefPtr<layers::TextureHost> mLastFrame;
void Init();
void Destroy();
void Shutdown();
void DispatchVRDisplayInfoUpdate();
typedef nsTHashtable<nsRefPtrHashKey<VRManagerParent>> VRManagerParentSet;
--- a/gfx/vr/gfxVROSVR.cpp
+++ b/gfx/vr/gfxVROSVR.cpp
@@ -316,17 +316,17 @@ VRDisplayOSVR::GetSensorState()
}
return result;
}
#if defined(XP_WIN)
bool
-VRDisplayOSVR::SubmitFrame(TextureSourceD3D11* aSource,
+VRDisplayOSVR::SubmitFrame(ID3D11Texture2D* aSource,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
// XXX Add code to submit frame
return false;
}
--- a/gfx/vr/gfxVROSVR.h
+++ b/gfx/vr/gfxVROSVR.h
@@ -31,17 +31,17 @@ public:
void ZeroSensor() override;
protected:
VRHMDSensorState GetSensorState() override;
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;
#elif defined(XP_MACOSX)
virtual bool SubmitFrame(MacIOSurface* aMacIOSurface,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -1027,20 +1027,20 @@ VRDisplayOculus::UpdateConstantBuffers()
ID3D11Buffer *buffer = mVSConstantBuffer;
mContext->VSSetConstantBuffers(0, 1, &buffer);
buffer = mPSConstantBuffer;
mContext->PSSetConstantBuffers(0, 1, &buffer);
return true;
}
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;
}
AutoRestoreRenderState restoreState(this);
if (!restoreState.IsSuccess()) {
return false;
@@ -1100,22 +1100,25 @@ VRDisplayOculus::SubmitFrame(TextureSour
mContext->IASetVertexBuffers(0, 1, &vbuffer, &vsize, &voffset);
mContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0);
mContext->IASetInputLayout(mInputLayout);
mContext->RSSetViewports(1, &viewport);
mContext->RSSetScissorRects(1, &scissor);
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<ID3D11ShaderResourceView> 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;
mContext->PSSetSamplers(0, 1, &sampler);
if (!UpdateConstantBuffers()) {
NS_WARNING("Failed to update constant buffers for Oculus");
return false;
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -84,17 +84,17 @@ class VRDisplayOculus : public VRDisplay
public:
virtual void NotifyVSync() override;
void ZeroSensor() override;
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;
void UpdateStageParameters();
public:
explicit VRDisplayOculus(VROculusSession* aSession);
void Destroy();
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -359,22 +359,22 @@ VRDisplayOpenVR::SubmitFrame(void* aText
mVRCompositor->PostPresentHandoff();
return true;
}
#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);
}
#elif defined(XP_MACOSX)
bool
VRDisplayOpenVR::SubmitFrame(MacIOSurface* aMacIOSurface,
--- a/gfx/vr/gfxVROpenVR.h
+++ b/gfx/vr/gfxVROpenVR.h
@@ -33,17 +33,17 @@ public:
void ZeroSensor() override;
bool GetIsHmdPresent();
protected:
virtual VRHMDSensorState GetSensorState() override;
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;
#elif defined(XP_MACOSX)
virtual bool SubmitFrame(MacIOSurface* aMacIOSurface,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
--- a/gfx/vr/gfxVRPuppet.cpp
+++ b/gfx/vr/gfxVRPuppet.cpp
@@ -269,17 +269,17 @@ VRDisplayPuppet::UpdateConstantBuffers()
ID3D11Buffer *buffer = mVSConstantBuffer;
mContext->VSSetConstantBuffers(0, 1, &buffer);
buffer = mPSConstantBuffer;
mContext->PSSetConstantBuffers(0, 1, &buffer);
return true;
}
bool
-VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource,
+VRDisplayPuppet::SubmitFrame(ID3D11Texture2D* aSource,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
if (!mIsPresenting) {
return false;
}
@@ -298,24 +298,23 @@ VRDisplayPuppet::SubmitFrame(TextureSour
case 0:
// The VR frame is not displayed.
break;
case 1:
{
// 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
&mapInfo);
if (FAILED(hr)) {
// If we can't map this texture, copy it to a staging resource.
if (hr == E_INVALIDARG) {
@@ -333,33 +332,33 @@ VRDisplayPuppet::SubmitFrame(TextureSour
ID3D11Texture2D* stagingTexture = nullptr;
hr = mDevice->CreateTexture2D(&desc2, nullptr, &stagingTexture);
if (FAILED(hr)) {
MOZ_ASSERT(false, "Failed to create a staging texture");
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
D3D11_MAP_READ,
0, // MapFlags
&mapInfo);
if (FAILED(hr)) {
MOZ_ASSERT(false, "Failed to map staging texture");
}
mappedTexture = stagingTexture;
} else {
MOZ_ASSERT(false, "Failed to map staging texture");
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
// access the image library. So, we have to convert the RAW image data
// to a base64 string and forward it to let the content process to
// do the image conversion.
char* srcData = static_cast<char*>(mapInfo.pData);
VRSubmitFrameResultInfo result;
@@ -424,22 +423,25 @@ VRDisplayPuppet::SubmitFrame(TextureSour
mContext->IASetVertexBuffers(0, 1, &vbuffer, &vsize, &voffset);
mContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0);
mContext->IASetInputLayout(mInputLayout);
mContext->RSSetViewports(1, &viewport);
mContext->RSSetScissorRects(1, &scissor);
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<ID3D11ShaderResourceView> 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;
mContext->PSSetSamplers(0, 1, &sampler);
if (!UpdateConstantBuffers()) {
NS_WARNING("Failed to update constant buffers for Puppet");
return false;
--- a/gfx/vr/gfxVRPuppet.h
+++ b/gfx/vr/gfxVRPuppet.h
@@ -27,17 +27,17 @@ public:
void SetSensorState(const VRHMDSensorState& aSensorState);
void ZeroSensor() override;
protected:
virtual VRHMDSensorState GetSensorState() override;
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;
#elif defined(XP_MACOSX)
virtual bool SubmitFrame(MacIOSurface* aMacIOSurface,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
--- a/gfx/vr/ipc/PVRLayer.ipdl
+++ b/gfx/vr/ipc/PVRLayer.ipdl
@@ -1,29 +1,29 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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 LayersSurfaces;
include protocol PVRManager;
-include protocol PTexture;
using mozilla::gfx::Rect from "mozilla/gfx/Rect.h";
namespace mozilla {
namespace gfx {
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();
child:
async __delete__();
};
--- a/gfx/vr/ipc/VRLayerChild.cpp
+++ b/gfx/vr/ipc/VRLayerChild.cpp
@@ -6,98 +6,107 @@
#include "VRLayerChild.h"
#include "GLScreenBuffer.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#include "SharedSurface.h" // for SharedSurface
#include "SharedSurfaceGL.h" // for SharedSurface
#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);
}
void
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) {
mCanvasElement = aCanvasElement;
VRManagerChild *vrmc = VRManagerChild::Get();
vrmc->RunFrameRequestCallbacks();
} else {
mCanvasElement = 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;
+
+ // 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();
+ }
+ }
- mShSurfClient = mCanvasElement->GetVRFrame();
- if (!mShSurfClient) {
- return;
- }
-
- 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
VRLayerChild::IsIPCOpen()
{
return mIPCOpen;
}
void
VRLayerChild::ClearSurfaces()
{
- mFront = nullptr;
- mShSurfClient = nullptr;
+ mThisFrameTexture = nullptr;
+ mLastFrameTexture = nullptr;
}
void
VRLayerChild::ActorDestroy(ActorDestroyReason aWhy)
{
mIPCOpen = false;
}
--- a/gfx/vr/ipc/VRLayerChild.h
+++ b/gfx/vr/ipc/VRLayerChild.h
@@ -42,27 +42,30 @@ public:
private:
VRLayerChild();
virtual ~VRLayerChild();
void ClearSurfaces();
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
RefPtr<dom::HTMLCanvasElement> mCanvasElement;
- RefPtr<layers::SharedSurfaceTextureClient> mShSurfClient;
- RefPtr<layers::TextureClient> mFront;
bool mIPCOpen;
// AddIPDLReference and ReleaseIPDLReference are only to be called by CreateIPDLActor
// and DestroyIPDLActor, respectively. We intentionally make them private to prevent misuse.
// The purpose of these methods is to be aware of when the IPC system around this
// actor goes down: mIPCOpen is then set to false.
void AddIPDLReference();
void ReleaseIPDLReference();
gfx::Rect mLeftEyeRect;
gfx::Rect mRightEyeRect;
+
+ RefPtr<layers::SharedSurfaceTextureClient> mThisFrameTexture;
+ RefPtr<layers::SharedSurfaceTextureClient> mLastFrameTexture;
+
+ uint64_t mLastSubmittedFrameId;
};
} // namespace gfx
} // namespace mozilla
#endif
--- a/gfx/vr/ipc/VRLayerParent.cpp
+++ b/gfx/vr/ipc/VRLayerParent.cpp
@@ -1,16 +1,17 @@
/* -*- 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 "VRLayerParent.h"
#include "mozilla/Unused.h"
+#include "VRDisplayHost.h"
namespace mozilla {
namespace gfx {
VRLayerParent::VRLayerParent(uint32_t aVRDisplayID, const uint32_t aGroup)
: mIPCOpen(true)
, mVRDisplayID(aVRDisplayID)
, mGroup(aGroup)
@@ -50,24 +51,28 @@ VRLayerParent::Destroy()
}
if (mIPCOpen) {
Unused << PVRLayerParent::Send__delete__(this);
}
}
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<VRDisplayHost> display = vm->GetDisplay(mVRDisplayID);
+ if (display) {
+ display->SubmitFrame(this, aTexture, aFrameId,
+ aLeftEyeRect, aRightEyeRect);
+ }
}
return IPC_OK();
}
} // namespace gfx
} // namespace mozilla
--- a/gfx/vr/ipc/VRLayerParent.h
+++ b/gfx/vr/ipc/VRLayerParent.h
@@ -15,17 +15,17 @@
namespace mozilla {
namespace gfx {
class VRLayerParent : public PVRLayerParent {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRLayerParent)
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;
virtual mozilla::ipc::IPCResult RecvDestroy() override;
uint32_t GetDisplayID() const { return mVRDisplayID; }
uint32_t GetGroup() const { return mGroup; }
protected:
virtual void ActorDestroy(ActorDestroyReason aWhy) override;