--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -352,16 +352,17 @@ private:
DECL_GFX_PREF(Live, "dom.vr.controller_trigger_threshold", VRControllerTriggerThreshold, float, 0.1f);
DECL_GFX_PREF(Live, "dom.vr.navigation.timeout", VRNavigationTimeout, int32_t, 1000);
DECL_GFX_PREF(Once, "dom.vr.oculus.enabled", VROculusEnabled, bool, true);
DECL_GFX_PREF(Once, "dom.vr.openvr.enabled", VROpenVREnabled, bool, false);
DECL_GFX_PREF(Once, "dom.vr.osvr.enabled", VROSVREnabled, bool, false);
DECL_GFX_PREF(Live, "dom.vr.poseprediction.enabled", VRPosePredictionEnabled, bool, true);
DECL_GFX_PREF(Live, "dom.vr.require-gesture", VRRequireGesture, bool, true);
DECL_GFX_PREF(Live, "dom.vr.puppet.enabled", VRPuppetEnabled, bool, false);
+ DECL_GFX_PREF(Live, "dom.vr.puppet.submitframe", VRPuppetSubmitFrame, uint32_t, 0);
DECL_GFX_PREF(Live, "dom.w3c_pointer_events.enabled", PointerEventsEnabled, bool, false);
DECL_GFX_PREF(Live, "dom.w3c_touch_events.enabled", TouchEventsEnabled, int32_t, 0);
DECL_GFX_PREF(Live, "general.smoothScroll", SmoothScrollEnabled, bool, true);
DECL_GFX_PREF(Live, "general.smoothScroll.currentVelocityWeighting",
SmoothScrollCurrentVelocityWeighting, float, 0.25);
DECL_GFX_PREF(Live, "general.smoothScroll.durationToIntervalRatio",
SmoothScrollDurationToIntervalRatio, int32_t, 200);
--- a/gfx/vr/VRDisplayClient.cpp
+++ b/gfx/vr/VRDisplayClient.cpp
@@ -143,8 +143,20 @@ VRDisplayClient::GetIsPresenting() const
return mDisplayInfo.GetIsPresenting();
}
void
VRDisplayClient::NotifyDisconnected()
{
mDisplayInfo.mIsConnected = false;
}
+
+void
+VRDisplayClient::UpdateSubmitFrameResult(const VRSubmitFrameResultInfo& aResult)
+{
+ mSubmitFrameResult = aResult;
+}
+
+void
+VRDisplayClient::GetSubmitFrameResult(VRSubmitFrameResultInfo& aResult)
+{
+ aResult = mSubmitFrameResult;
+}
\ No newline at end of file
--- a/gfx/vr/VRDisplayClient.h
+++ b/gfx/vr/VRDisplayClient.h
@@ -21,19 +21,21 @@ class VRManagerChild;
class VRDisplayClient
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRDisplayClient)
explicit VRDisplayClient(const VRDisplayInfo& aDisplayInfo);
void UpdateDisplayInfo(const VRDisplayInfo& aDisplayInfo);
+ void UpdateSubmitFrameResult(const VRSubmitFrameResultInfo& aResult);
const VRDisplayInfo& GetDisplayInfo() const { return mDisplayInfo; }
virtual VRHMDSensorState GetSensorState();
+ void GetSubmitFrameResult(VRSubmitFrameResultInfo& aResult);
virtual void ZeroSensor();
already_AddRefed<VRDisplayPresentation> BeginPresentation(const nsTArray<dom::VRLayer>& aLayers);
void PresentationDestroyed();
void NotifyVsync();
void NotifyVRVsync();
@@ -48,14 +50,17 @@ protected:
VRDisplayInfo mDisplayInfo;
bool bLastEventWasMounted;
bool bLastEventWasPresenting;
TimeStamp mLastVSyncTime;
int mPresentationCount;
+
+private:
+ VRSubmitFrameResultInfo mSubmitFrameResult;
};
} // namespace gfx
} // namespace mozilla
#endif /* GFX_VR_DISPLAY_CLIENT_H */
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -463,10 +463,18 @@ VRManager::StopVibrateHaptic(uint32_t aC
void
VRManager::NotifyVibrateHapticCompleted(uint32_t aPromiseID)
{
for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
Unused << iter.Get()->GetKey()->SendReplyGamepadVibrateHaptic(aPromiseID);
}
}
+void
+VRManager::DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameResultInfo& aResult)
+{
+ for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
+ Unused << iter.Get()->GetKey()->SendDispatchSubmitFrameResult(aDisplayID, aResult);
+ }
+}
+
} // namespace gfx
} // namespace mozilla
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -48,16 +48,17 @@ public:
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;
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -204,16 +204,31 @@ struct VRHMDSensorState {
float linearVelocity[3];
float linearAcceleration[3];
void Clear() {
memset(this, 0, sizeof(VRHMDSensorState));
}
};
+struct VRSubmitFrameResultInfo
+{
+ VRSubmitFrameResultInfo()
+ : mFrameNum(0),
+ mWidth(0),
+ mHeight(0)
+ {}
+
+ nsCString mBase64Image;
+ SurfaceFormat mFormat;
+ uint32_t mFrameNum;
+ uint32_t mWidth;
+ uint32_t mHeight;
+};
+
struct VRControllerInfo
{
VRDeviceType GetType() const { return mType; }
uint32_t GetControllerID() const { return mControllerID; }
const nsCString& GetControllerName() const { return mControllerName; }
dom::GamepadMappingType GetMappingType() const { return mMappingType; }
dom::GamepadHand GetHand() const { return mHand; }
uint32_t GetNumButtons() const { return mNumButtons; }
--- a/gfx/vr/gfxVRPuppet.cpp
+++ b/gfx/vr/gfxVRPuppet.cpp
@@ -1,29 +1,41 @@
/* -*- Mode: C++; tab-width: 20; 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/. */
#if defined(XP_WIN)
#include "CompositorD3D11.h"
#include "TextureD3D11.h"
+#include "mozilla/gfx/DeviceManagerDx.h"
#endif // XP_WIN
+#include "mozilla/Base64.h"
+#include "mozilla/gfx/DataSurfaceHelpers.h"
+#include "gfxUtils.h"
#include "gfxVRPuppet.h"
#include "mozilla/dom/GamepadEventTypes.h"
#include "mozilla/dom/GamepadBinding.h"
+// See CompositorD3D11Shaders.h
+namespace mozilla {
+namespace layers {
+struct ShaderBytes { const void* mData; size_t mLength; };
+extern ShaderBytes sRGBShader;
+extern ShaderBytes sLayerQuadVS;
+} // namespace layers
+} // namespace mozilla
+
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::gfx::impl;
using namespace mozilla::layers;
-
// Reminder: changing the order of these buttons may break web content
static const uint64_t kPuppetButtonMask[] = {
1,
2,
4,
8
};
@@ -39,16 +51,17 @@ static const uint32_t kPuppetAxes[] = {
static const uint32_t kNumPuppetAxis = sizeof(kPuppetAxes) /
sizeof(uint32_t);
static const uint32_t kNumPuppetHaptcs = 1;
VRDisplayPuppet::VRDisplayPuppet()
: VRDisplayHost(VRDeviceType::Puppet)
, mIsPresenting(false)
+ , mFrameNum(0)
{
MOZ_COUNT_CTOR_INHERITED(VRDisplayPuppet, VRDisplayHost);
mDisplayInfo.mDisplayName.AssignLiteral("Puppet HMD");
mDisplayInfo.mIsConnected = true;
mDisplayInfo.mIsMounted = false;
mDisplayInfo.mCapabilityFlags = VRDisplayCapabilityFlags::Cap_None |
VRDisplayCapabilityFlags::Cap_Orientation |
@@ -158,50 +171,300 @@ VRDisplayPuppet::SetSensorState(const VR
void
VRDisplayPuppet::StartPresentation()
{
if (mIsPresenting) {
return;
}
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");
+ return;
+ }
+
+ if (FAILED(mDevice->CreateVertexShader(sLayerQuadVS.mData,
+ sLayerQuadVS.mLength, nullptr, &mQuadVS))) {
+ NS_WARNING("Failed to create vertex shader for Puppet");
+ return;
+ }
+
+ if (FAILED(mDevice->CreatePixelShader(sRGBShader.mData,
+ sRGBShader.mLength, nullptr, &mQuadPS))) {
+ NS_WARNING("Failed to create pixel shader for Puppet");
+ return;
+ }
+
+ CD3D11_BUFFER_DESC cBufferDesc(sizeof(layers::VertexShaderConstants),
+ D3D11_BIND_CONSTANT_BUFFER,
+ D3D11_USAGE_DYNAMIC,
+ D3D11_CPU_ACCESS_WRITE);
+
+ if (FAILED(mDevice->CreateBuffer(&cBufferDesc, nullptr, getter_AddRefs(mVSConstantBuffer)))) {
+ NS_WARNING("Failed to vertex shader constant buffer for Puppet");
+ return;
+ }
+
+ cBufferDesc.ByteWidth = sizeof(layers::PixelShaderConstants);
+ if (FAILED(mDevice->CreateBuffer(&cBufferDesc, nullptr, getter_AddRefs(mPSConstantBuffer)))) {
+ NS_WARNING("Failed to pixel shader constant buffer for Puppet");
+ return;
+ }
+
+ CD3D11_SAMPLER_DESC samplerDesc(D3D11_DEFAULT);
+ if (FAILED(mDevice->CreateSamplerState(&samplerDesc, getter_AddRefs(mLinearSamplerState)))) {
+ NS_WARNING("Failed to create sampler state for Puppet");
+ return;
+ }
+
+ D3D11_INPUT_ELEMENT_DESC layout[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+
+ if (FAILED(mDevice->CreateInputLayout(layout,
+ sizeof(layout) / sizeof(D3D11_INPUT_ELEMENT_DESC),
+ sLayerQuadVS.mData,
+ sLayerQuadVS.mLength,
+ getter_AddRefs(mInputLayout)))) {
+ NS_WARNING("Failed to create input layout for Puppet");
+ return;
+ }
+
+ Vertex vertices[] = { { { 0.0, 0.0 } },{ { 1.0, 0.0 } },{ { 0.0, 1.0 } },{ { 1.0, 1.0 } } };
+ CD3D11_BUFFER_DESC bufferDesc(sizeof(vertices), D3D11_BIND_VERTEX_BUFFER);
+ D3D11_SUBRESOURCE_DATA data;
+ data.pSysMem = (void*)vertices;
+
+ if (FAILED(mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mVertexBuffer)))) {
+ NS_WARNING("Failed to create vertex buffer for Puppet");
+ return;
+ }
+
+ memset(&mVSConstants, 0, sizeof(mVSConstants));
+ memset(&mPSConstants, 0, sizeof(mPSConstants));
+#endif // XP_WIN
}
void
VRDisplayPuppet::StopPresentation()
{
if (!mIsPresenting) {
return;
}
mIsPresenting = false;
}
#if defined(XP_WIN)
+bool
+VRDisplayPuppet::UpdateConstantBuffers()
+{
+ HRESULT hr;
+ D3D11_MAPPED_SUBRESOURCE resource;
+ resource.pData = nullptr;
+
+ hr = mContext->Map(mVSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
+ if (FAILED(hr) || !resource.pData) {
+ return false;
+ }
+ *(VertexShaderConstants*)resource.pData = mVSConstants;
+ mContext->Unmap(mVSConstantBuffer, 0);
+ resource.pData = nullptr;
+
+ hr = mContext->Map(mPSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
+ if (FAILED(hr) || !resource.pData) {
+ return false;
+ }
+ *(PixelShaderConstants*)resource.pData = mPSConstants;
+ mContext->Unmap(mPSConstantBuffer, 0);
+
+ ID3D11Buffer *buffer = mVSConstantBuffer;
+ mContext->VSSetConstantBuffers(0, 1, &buffer);
+ buffer = mPSConstantBuffer;
+ mContext->PSSetConstantBuffers(0, 1, &buffer);
+ return true;
+}
+
void
VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource,
const IntSize& aSize,
const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
if (!mIsPresenting) {
return;
}
- ID3D11Texture2D* tex = aSource->GetD3D11Texture();
- MOZ_ASSERT(tex);
+ VRManager *vm = VRManager::Get();
+ MOZ_ASSERT(vm);
+
+ switch (gfxPrefs::VRPuppetSubmitFrame()) {
+ 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);
+ DXGI_FORMAT format = desc.Format;
+ // Map the staging resource
+ ID3D11Texture2D* mappedTexture = nullptr;
+ D3D11_MAPPED_SUBRESOURCE mapInfo;
+ HRESULT hr = mContext->Map(texture,
+ 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) {
+ D3D11_TEXTURE2D_DESC desc2;
+ desc2.Width = desc.Width;
+ desc2.Height = desc.Height;
+ desc2.MipLevels = desc.MipLevels;
+ desc2.ArraySize = desc.ArraySize;
+ desc2.Format = desc.Format;
+ desc2.SampleDesc = desc.SampleDesc;
+ desc2.Usage = D3D11_USAGE_STAGING;
+ desc2.BindFlags = 0;
+ desc2.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ desc2.MiscFlags = 0;
- // TODO: Bug 1343730, Need to block until the next simulated
- // vblank interval and capture frames for use in reftests.
+ ID3D11Texture2D* stagingTexture = nullptr;
+ hr = mDevice->CreateTexture2D(&desc2, nullptr, &stagingTexture);
+ if (FAILED(hr)) {
+ MOZ_ASSERT(false, "Failed to create a staging texture");
+ return;
+ }
+ // Copy the texture to a staging resource
+ mContext->CopyResource(stagingTexture, texture);
+ // 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;
+ }
+ } else {
+ mappedTexture = texture;
+ }
+ // 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;
+ result.mFormat = SurfaceFormat::B8G8R8A8;
+ result.mWidth = desc.Width;
+ result.mHeight = desc.Height;
+ result.mFrameNum = mFrameNum;
+ nsCString rawString(Substring((char*)srcData, mapInfo.RowPitch * desc.Height));
+
+ if (Base64Encode(rawString, result.mBase64Image) != NS_OK) {
+ MOZ_ASSERT(false, "Failed to encode base64 images.");
+ }
+ mContext->Unmap(mappedTexture, 0);
+ // Dispatch the base64 encoded string to the DOM side, and it will be decoded
+ // and convert to a PNG image there.
+ vm->DispatchSubmitFrameResult(mDisplayInfo.mDisplayID, result);
+ break;
+ }
+ case 2:
+ {
+ // The VR compositor sumbmit frame to the screen window,
+ // the current coordinate is at (0, 0, width, height).
+ Matrix viewMatrix = Matrix::Translation(-1.0, 1.0);
+ viewMatrix.PreScale(2.0f / float(aSize.width), 2.0f / float(aSize.height));
+ viewMatrix.PreScale(1.0f, -1.0f);
+ Matrix4x4 projection = Matrix4x4::From2D(viewMatrix);
+ projection._33 = 0.0f;
+
+ Matrix transform2d;
+ gfx::Matrix4x4 transform = gfx::Matrix4x4::From2D(transform2d);
+
+ const float posX = 0.0f, posY = 0.0f;
+ D3D11_VIEWPORT viewport;
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ viewport.Width = aSize.width;
+ viewport.Height = aSize.height;
+ viewport.TopLeftX = posX;
+ viewport.TopLeftY = posY;
+
+ D3D11_RECT scissor;
+ scissor.left = posX;
+ scissor.right = aSize.width + posX;
+ scissor.top = posY;
+ scissor.bottom = aSize.height + posY;
+
+ memcpy(&mVSConstants.layerTransform, &transform._11, sizeof(mVSConstants.layerTransform));
+ memcpy(&mVSConstants.projection, &projection._11, sizeof(mVSConstants.projection));
+ mVSConstants.renderTargetOffset[0] = 0.0f;
+ mVSConstants.renderTargetOffset[1] = 0.0f;
+ mVSConstants.layerQuad = Rect(0.0f, 0.0f, aSize.width, aSize.height);
+ mVSConstants.textureCoords = Rect(0.0f, 1.0f, 1.0f, -1.0f);
+
+ mPSConstants.layerOpacity[0] = 1.0f;
+
+ ID3D11Buffer* vbuffer = mVertexBuffer;
+ UINT vsize = sizeof(Vertex);
+ UINT voffset = 0;
+ 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();
+ mContext->PSSetShaderResources(0 /* 0 == TexSlot::RGB */, 1, &srView);
+ // 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;
+ }
+ mContext->Draw(4, 0);
+ break;
+ }
+ }
// Trigger the next VSync immediately
- VRManager *vm = VRManager::Get();
- MOZ_ASSERT(vm);
vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
+ ++mFrameNum;
}
#else
void
VRDisplayPuppet::SubmitFrame(TextureSourceOGL* aSource,
const IntSize& aSize,
const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
@@ -212,16 +475,17 @@ VRDisplayPuppet::SubmitFrame(TextureSour
// TODO: Bug 1343730, Need to block until the next simulated
// vblank interval and capture frames for use in reftests.
// Trigger the next VSync immediately
VRManager *vm = VRManager::Get();
MOZ_ASSERT(vm);
vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
+ ++mFrameNum;
}
#endif
void
VRDisplayPuppet::NotifyVSync()
{
// We update mIsConneced once per frame.
mDisplayInfo.mIsConnected = true;
--- a/gfx/vr/gfxVRPuppet.h
+++ b/gfx/vr/gfxVRPuppet.h
@@ -48,17 +48,34 @@ protected:
virtual ~VRDisplayPuppet();
void Destroy();
VRHMDSensorState GetSensorState(double timeOffset);
bool mIsPresenting;
private:
+#if defined(XP_WIN)
+ bool UpdateConstantBuffers();
+
+ RefPtr<ID3D11Device> mDevice;
+ RefPtr<ID3D11DeviceContext> mContext;
+ ID3D11VertexShader* mQuadVS;
+ ID3D11PixelShader* mQuadPS;
+ RefPtr<ID3D11SamplerState> mLinearSamplerState;
+ layers::VertexShaderConstants mVSConstants;
+ layers::PixelShaderConstants mPSConstants;
+ RefPtr<ID3D11Buffer> mVSConstantBuffer;
+ RefPtr<ID3D11Buffer> mPSConstantBuffer;
+ RefPtr<ID3D11Buffer> mVertexBuffer;
+ RefPtr<ID3D11InputLayout> mInputLayout;
+#endif
+
VRHMDSensorState mSensorState;
+ uint32_t mFrameNum;
};
class VRControllerPuppet : public VRControllerHost
{
public:
explicit VRControllerPuppet(dom::GamepadHand aHand);
void SetButtonPressState(uint32_t aButton, bool aPressed);
uint64_t GetButtonPressState();
--- a/gfx/vr/ipc/PVRManager.ipdl
+++ b/gfx/vr/ipc/PVRManager.ipdl
@@ -13,16 +13,17 @@ include GamepadEventTypes;
include "VRMessageUtils.h";
using struct mozilla::gfx::VRFieldOfView from "gfxVR.h";
using struct mozilla::gfx::VRDisplayInfo from "gfxVR.h";
using struct mozilla::gfx::VRSensorUpdate from "gfxVR.h";
using struct mozilla::gfx::VRHMDSensorState from "gfxVR.h";
using struct mozilla::gfx::VRControllerInfo from "gfxVR.h";
+using struct mozilla::gfx::VRSubmitFrameResultInfo from "gfxVR.h";
using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
namespace mozilla {
namespace gfx {
/**
@@ -77,16 +78,17 @@ child:
// Notify children of updated VR display enumeration and details. This will
// be sent to all children when the parent receives RefreshDisplays, even
// if no changes have been detected. This ensures that Promises exposed
// through DOM calls are always resolved.
async UpdateDisplayInfo(VRDisplayInfo[] aDisplayUpdates);
async NotifyVSync();
async NotifyVRVSync(uint32_t aDisplayID);
+ async DispatchSubmitFrameResult(uint32_t aDisplayID, VRSubmitFrameResultInfo aResult);
async GamepadUpdate(GamepadChangeEvent aGamepadEvent);
async ReplyGamepadVibrateHaptic(uint32_t aPromiseID);
async ReplyCreateVRServiceTestDisplay(nsCString aID, uint32_t aPromiseID,
uint32_t aDeviceID);
async ReplyCreateVRServiceTestController(nsCString aID, uint32_t aPromiseID,
uint32_t aDeviceID);
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -713,10 +713,23 @@ VRManagerChild::RecvReplyGamepadVibrateH
MOZ_CRASH("We should always have a promise.");
}
p->MaybeResolve(true);
mGamepadPromiseList.Remove(aPromiseID);
return IPC_OK();
}
+mozilla::ipc::IPCResult
+VRManagerChild::RecvDispatchSubmitFrameResult(const uint32_t& aDisplayID,
+ const VRSubmitFrameResultInfo& aResult)
+{
+ for (auto& display : mDisplays) {
+ if (display->GetDisplayInfo().GetDisplayID() == aDisplayID) {
+ display->UpdateSubmitFrameResult(aResult);
+ }
+ }
+
+ return IPC_OK();
+}
+
} // namespace gfx
} // namespace mozilla
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -123,16 +123,17 @@ protected:
virtual bool DeallocPVRLayerChild(PVRLayerChild* actor) override;
virtual mozilla::ipc::IPCResult RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates) override;
virtual mozilla::ipc::IPCResult RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
virtual mozilla::ipc::IPCResult RecvNotifyVSync() override;
virtual mozilla::ipc::IPCResult RecvNotifyVRVSync(const uint32_t& aDisplayID) override;
+ virtual mozilla::ipc::IPCResult RecvDispatchSubmitFrameResult(const uint32_t& aDisplayID, const VRSubmitFrameResultInfo& aResult) override;
virtual mozilla::ipc::IPCResult RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override;
virtual mozilla::ipc::IPCResult RecvReplyGamepadVibrateHaptic(const uint32_t& aPromiseID) override;
virtual mozilla::ipc::IPCResult RecvReplyCreateVRServiceTestDisplay(const nsCString& aID,
const uint32_t& aPromiseID,
const uint32_t& aDeviceID) override;
virtual mozilla::ipc::IPCResult RecvReplyCreateVRServiceTestController(const nsCString& aID,
const uint32_t& aPromiseID,
--- a/gfx/vr/ipc/VRMessageUtils.h
+++ b/gfx/vr/ipc/VRMessageUtils.h
@@ -185,11 +185,40 @@ struct ParamTraits<mozilla::gfx::VRContr
!ReadParam(aMsg, aIter, &(aResult->mNumButtons)) ||
!ReadParam(aMsg, aIter, &(aResult->mNumAxes))) {
return false;
}
return true;
}
};
+
+template <>
+struct ParamTraits<mozilla::gfx::VRSubmitFrameResultInfo>
+{
+ typedef mozilla::gfx::VRSubmitFrameResultInfo paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, aParam.mBase64Image);
+ WriteParam(aMsg, aParam.mFormat);
+ WriteParam(aMsg, aParam.mWidth);
+ WriteParam(aMsg, aParam.mHeight);
+ WriteParam(aMsg, aParam.mFrameNum);
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ if (!ReadParam(aMsg, aIter, &(aResult->mBase64Image)) ||
+ !ReadParam(aMsg, aIter, &(aResult->mFormat)) ||
+ !ReadParam(aMsg, aIter, &(aResult->mWidth)) ||
+ !ReadParam(aMsg, aIter, &(aResult->mHeight)) ||
+ !ReadParam(aMsg, aIter, &(aResult->mFrameNum))) {
+ return false;
+ }
+
+ return true;
+ }
+};
+
} // namespace IPC
#endif // mozilla_gfx_vr_VRMessageUtils_h
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5128,16 +5128,20 @@ pref("dom.vr.poseprediction.enabled", tr
pref("dom.vr.require-gesture", true);
// path to OSVR DLLs
pref("gfx.vr.osvr.utilLibPath", "");
pref("gfx.vr.osvr.commonLibPath", "");
pref("gfx.vr.osvr.clientLibPath", "");
pref("gfx.vr.osvr.clientKitLibPath", "");
// Puppet device, used for simulating VR hardware within tests and dev tools
pref("dom.vr.puppet.enabled", false);
+// Allow displaying the result of vr submitframe (0: disable, 1: store the
+// result as a base64 image, 2: show it on the screen).
+pref("dom.vr.puppet.submitframe", 0);
+// VR test system.
pref("dom.vr.test.enabled", false);
// MMS UA Profile settings
pref("wap.UAProf.url", "");
pref("wap.UAProf.tagname", "x-wap-profile");
// MMS version 1.1 = 0x11 (or decimal 17)
// MMS version 1.3 = 0x13 (or decimal 19)
// @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.34