Bug 1469967 - Implement immersive mode for gfxVRExternal r=rbarker

- The VR External interface/shmem and gfxVRExternal are
  updated to enable entering VR, exiting VR, and submitting
  frames.
- You can now construct gfxVRExternal using a pointer to
  the VR External API shmem, if it is created elsewhere.

MozReview-Commit-ID: LZuoLvoEmKO

--HG--
extra : rebase_source : ab38ae4c34f9ac5cdd69e7222f12b1c758307057
This commit is contained in:
Kearwood "Kip" Gilbert 2018-05-08 11:31:28 -07:00
parent 742cfdad99
commit 89b524f028
18 changed files with 422 additions and 211 deletions

View File

@ -273,83 +273,8 @@ VRDisplayHost::SubmitFrameInternal(const layers::SurfaceDescriptor &aTexture,
#endif // !defined(MOZ_WIDGET_ANDROID) #endif // !defined(MOZ_WIDGET_ANDROID)
AUTO_PROFILER_TRACING("VR", "SubmitFrameAtVRDisplayHost"); AUTO_PROFILER_TRACING("VR", "SubmitFrameAtVRDisplayHost");
mFrameStarted = false; if (!SubmitFrame(aTexture, aFrameId, aLeftEyeRect, aRightEyeRect)) {
switch (aTexture.type()) { 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;
}
// 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)
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;
}
#elif defined(MOZ_WIDGET_ANDROID)
case SurfaceDescriptor::TSurfaceTextureDescriptor: {
const SurfaceTextureDescriptor& desc = aTexture.get_SurfaceTextureDescriptor();
if (!SubmitFrame(desc, aLeftEyeRect, aRightEyeRect)) {
return;
}
break;
}
#endif
default: {
NS_WARNING("Unsupported SurfaceDescriptor type for VR layer texture");
return;
}
} }
#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) #if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID)
@ -381,12 +306,6 @@ VRDisplayHost::SubmitFrame(VRLayerParent* aLayer,
const gfx::Rect& aLeftEyeRect, const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) const gfx::Rect& aRightEyeRect)
{ {
#if !defined(MOZ_WIDGET_ANDROID)
if (!mSubmitThread) {
mSubmitThread = new VRThread(NS_LITERAL_CSTRING("VR_SubmitFrame"));
}
#endif // !defined(MOZ_WIDGET_ANDROID)
if ((mDisplayInfo.mGroupMask & aLayer->GetGroup()) == 0) { if ((mDisplayInfo.mGroupMask & aLayer->GetGroup()) == 0) {
// Suppress layers hidden by the group mask // Suppress layers hidden by the group mask
return; return;
@ -397,12 +316,18 @@ VRDisplayHost::SubmitFrame(VRLayerParent* aLayer,
return; return;
} }
mFrameStarted = false;
RefPtr<Runnable> submit = RefPtr<Runnable> submit =
NewRunnableMethod<StoreCopyPassByConstLRef<layers::SurfaceDescriptor>, uint64_t, NewRunnableMethod<StoreCopyPassByConstLRef<layers::SurfaceDescriptor>, uint64_t,
StoreCopyPassByConstLRef<gfx::Rect>, StoreCopyPassByConstLRef<gfx::Rect>>( StoreCopyPassByConstLRef<gfx::Rect>, StoreCopyPassByConstLRef<gfx::Rect>>(
"gfx::VRDisplayHost::SubmitFrameInternal", this, &VRDisplayHost::SubmitFrameInternal, "gfx::VRDisplayHost::SubmitFrameInternal", this, &VRDisplayHost::SubmitFrameInternal,
aTexture, aFrameId, aLeftEyeRect, aRightEyeRect); aTexture, aFrameId, aLeftEyeRect, aRightEyeRect);
#if !defined(MOZ_WIDGET_ANDROID) #if !defined(MOZ_WIDGET_ANDROID)
if (!mSubmitThread) {
mSubmitThread = new VRThread(NS_LITERAL_CSTRING("VR_SubmitFrame"));
}
mSubmitThread->Start(); mSubmitThread->Start();
mSubmitThread->PostTask(submit.forget()); mSubmitThread->PostTask(submit.forget());
#else #else

View File

@ -72,25 +72,13 @@ protected:
explicit VRDisplayHost(VRDeviceType aType); explicit VRDisplayHost(VRDeviceType aType);
virtual ~VRDisplayHost(); virtual ~VRDisplayHost();
#if defined(XP_WIN) // This SubmitFrame() must be overridden by children and block until
// Subclasses should override this SubmitFrame function. // the next frame is ready to start and the resources in aTexture can
// Returns true if the SubmitFrame call will block as necessary // safely be released.
// to control timing of the next frame and throttle the render loop virtual bool SubmitFrame(const layers::SurfaceDescriptor& aTexture,
// for the needed framerate. uint64_t aFrameId,
virtual bool SubmitFrame(ID3D11Texture2D* aSource,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect, const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) = 0; 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;
#elif defined(MOZ_WIDGET_ANDROID)
virtual bool SubmitFrame(const mozilla::layers::SurfaceTextureDescriptor& aSurface,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) = 0;
#endif
VRDisplayInfo mDisplayInfo; VRDisplayInfo mDisplayInfo;

132
gfx/vr/VRDisplayLocal.cpp Normal file
View File

@ -0,0 +1,132 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "VRDisplayLocal.h"
#include "gfxPrefs.h"
#include "gfxVR.h"
#include "ipc/VRLayerParent.h"
#include "mozilla/layers/TextureHost.h"
#include "mozilla/dom/GamepadBinding.h" // For GamepadMappingType
#include "VRThread.h"
#if defined(XP_WIN)
#include <d3d11.h>
#include "gfxWindowsPlatform.h"
#include "../layers/d3d11/CompositorD3D11.h"
#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/layers/TextureD3D11.h"
#elif defined(XP_MACOSX)
#include "mozilla/gfx/MacIOSurface.h"
#endif
#if defined(MOZ_WIDGET_ANDROID)
#include "mozilla/layers/CompositorThread.h"
#endif // defined(MOZ_WIDGET_ANDROID)
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::layers;
VRDisplayLocal::VRDisplayLocal(VRDeviceType aType)
: VRDisplayHost(aType)
{
MOZ_COUNT_CTOR_INHERITED(VRDisplayLocal, VRDisplayHost);
}
VRDisplayLocal::~VRDisplayLocal()
{
MOZ_COUNT_DTOR_INHERITED(VRDisplayLocal, VRDisplayHost);
}
bool
VRDisplayLocal::SubmitFrame(const layers::SurfaceDescriptor &aTexture,
uint64_t aFrameId,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
#if !defined(MOZ_WIDGET_ANDROID)
MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
#endif // !defined(MOZ_WIDGET_ANDROID)
switch (aTexture.type()) {
#if defined(XP_WIN)
case SurfaceDescriptor::TSurfaceDescriptorD3D10: {
if (!CreateD3DObjects()) {
return false;
}
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 false;
}
// 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 false;
}
}
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");
}
}
return success;
}
#elif defined(XP_MACOSX)
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 false;
}
IntSize texSize = gfx::IntSize(surf->GetDevicePixelWidth(),
surf->GetDevicePixelHeight());
if (!SubmitFrame(surf, texSize, aLeftEyeRect, aRightEyeRect)) {
return false;
}
return true;
}
#elif defined(MOZ_WIDGET_ANDROID)
case SurfaceDescriptor::TSurfaceTextureDescriptor: {
const SurfaceTextureDescriptor& desc = aTexture.get_SurfaceTextureDescriptor();
if (!SubmitFrame(desc, aLeftEyeRect, aRightEyeRect)) {
return false;
}
return true;
}
#endif
default: {
NS_WARNING("Unsupported SurfaceDescriptor type for VR layer texture");
return false;
}
}
}

61
gfx/vr/VRDisplayLocal.h Normal file
View File

@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef GFX_VR_DISPLAY_LOCAL_H
#define GFX_VR_DISPLAY_LOCAL_H
#include "gfxVR.h"
#include "VRDisplayHost.h"
#if defined(XP_WIN)
#include <d3d11_1.h>
#elif defined(XP_MACOSX)
class MacIOSurface;
#endif
namespace mozilla {
namespace gfx {
class VRThread;
class VRDisplayLocal : public VRDisplayHost
{
public:
#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(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;
#elif defined(MOZ_WIDGET_ANDROID)
virtual bool SubmitFrame(const mozilla::layers::SurfaceTextureDescriptor& aSurface,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) = 0;
#endif
protected:
explicit VRDisplayLocal(VRDeviceType aType);
virtual ~VRDisplayLocal();
private:
bool SubmitFrame(const layers::SurfaceDescriptor& aTexture,
uint64_t aFrameId,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) final;
};
} // namespace gfx
} // namespace mozilla
#endif // GFX_VR_DISPLAY_LOCAL_H

View File

@ -231,6 +231,12 @@ VRManager::CheckForInactiveTimeout()
TimeDuration duration = TimeStamp::Now() - mLastActiveTime; TimeDuration duration = TimeStamp::Now() - mLastActiveTime;
if (duration.ToMilliseconds() > gfxPrefs::VRInactiveTimeout()) { if (duration.ToMilliseconds() > gfxPrefs::VRInactiveTimeout()) {
Shutdown(); Shutdown();
// We must not throttle the next enumeration request
// after an idle timeout, as it may result in the
// user needing to refresh the browser to detect
// VR hardware when leaving and returning to a VR
// site.
mLastDisplayEnumerationTime = TimeStamp();
} }
} }
} }

View File

@ -235,6 +235,8 @@ struct VRDisplayState
FloatSize_POD mStageSize; FloatSize_POD mStageSize;
// We can't use a Matrix4x4 here unless we ensure it's a POD type // We can't use a Matrix4x4 here unless we ensure it's a POD type
float mSittingToStandingTransform[16]; float mSittingToStandingTransform[16];
uint64_t mLastSubmittedFrameId;
bool mLastSubmittedFrameSuccessful;
uint32_t mPresentingGeneration; uint32_t mPresentingGeneration;
}; };
@ -274,9 +276,8 @@ enum class VRLayerType : uint16_t {
enum class VRLayerTextureType : uint16_t { enum class VRLayerTextureType : uint16_t {
LayerTextureType_None = 0, LayerTextureType_None = 0,
LayerTextureType_DirectX = 1, LayerTextureType_D3D10SurfaceDescriptor = 1,
LayerTextureType_OpenGL = 2, LayerTextureType_MacIOSurface = 2
LayerTextureType_Vulkan = 3
}; };
struct VRLayer_2D_Content struct VRLayer_2D_Content
@ -291,6 +292,7 @@ struct VRLayer_Stereo_Immersive
void* mTextureHandle; void* mTextureHandle;
VRLayerTextureType mTextureType; VRLayerTextureType mTextureType;
uint64_t mFrameId; uint64_t mFrameId;
uint64_t mInputFrameId;
VRLayerEyeRect mLeftEyeRect; VRLayerEyeRect mLeftEyeRect;
VRLayerEyeRect mRightEyeRect; VRLayerEyeRect mRightEyeRect;
}; };
@ -315,6 +317,7 @@ struct VRBrowserState
struct VRSystemState struct VRSystemState
{ {
uint32_t presentingGeneration; uint32_t presentingGeneration;
bool enumerationCompleted;
VRDisplayState displayState; VRDisplayState displayState;
VRHMDSensorState sensorState; VRHMDSensorState sensorState;
VRControllerState controllerState[kVRControllerMaxCount]; VRControllerState controllerState[kVRControllerMaxCount];

View File

@ -102,8 +102,6 @@ VRDisplayExternal::GetSensorState()
manager->PullState(&mDisplayInfo.mDisplayState, &mLastSensorState); manager->PullState(&mDisplayInfo.mDisplayState, &mLastSensorState);
// result.CalcViewMatrices(headToEyeTransforms);
mLastSensorState.inputFrameID = mDisplayInfo.mFrameId;
return mLastSensorState; return mLastSensorState;
} }
@ -117,7 +115,15 @@ VRDisplayExternal::StartPresentation()
mTelemetry.Clear(); mTelemetry.Clear();
mTelemetry.mPresentationStart = TimeStamp::Now(); mTelemetry.mPresentationStart = TimeStamp::Now();
// TODO - Implement this // Indicate that we are ready to start immersive mode
VRBrowserState state;
memset(&state, 0, sizeof(VRBrowserState));
state.layerState[0].type = VRLayerType::LayerType_Stereo_Immersive;
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
manager->PushState(&state);
// TODO - Implement telemetry:
// mTelemetry.mLastDroppedFrameCount = stats.m_nNumReprojectedFrames; // mTelemetry.mLastDroppedFrameCount = stats.m_nNumReprojectedFrames;
} }
@ -128,11 +134,18 @@ VRDisplayExternal::StopPresentation()
if (!mIsPresenting) { if (!mIsPresenting) {
return; return;
} }
mIsPresenting = false;
// TODO - Implement this // Indicate that we have stopped immersive mode
VRBrowserState state;
memset(&state, 0, sizeof(VRBrowserState));
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
manager->PushState(&state);
// TODO - Implement telemetry:
/* /*
mIsPresenting = false;
const TimeDuration duration = TimeStamp::Now() - mTelemetry.mPresentationStart; const TimeDuration duration = TimeStamp::Now() - mTelemetry.mPresentationStart;
Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 2); Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 2);
Telemetry::Accumulate(Telemetry::WEBVR_TIME_SPENT_VIEWING_IN_OPENVR, Telemetry::Accumulate(Telemetry::WEBVR_TIME_SPENT_VIEWING_IN_OPENVR,
@ -146,47 +159,88 @@ VRDisplayExternal::StopPresentation()
*/ */
} }
bool
VRDisplayExternal::PopulateLayerTexture(const layers::SurfaceDescriptor& aTexture,
VRLayerTextureType* aTextureType,
void** aTextureHandle)
{
switch (aTexture.type()) {
#if defined(XP_WIN) #if defined(XP_WIN)
case SurfaceDescriptor::TSurfaceDescriptorD3D10: {
bool const SurfaceDescriptorD3D10& surf = aTexture.get_SurfaceDescriptorD3D10();
VRDisplayExternal::SubmitFrame(ID3D11Texture2D* aSource, *aTextureType = VRLayerTextureType::LayerTextureType_D3D10SurfaceDescriptor;
const IntSize& aSize, *aTextureHandle = (void *)surf.handle();
const gfx::Rect& aLeftEyeRect, return true;
const gfx::Rect& aRightEyeRect) }
{
// FINDME! Implement this
return false;
}
#elif defined(XP_MACOSX) #elif defined(XP_MACOSX)
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
bool const auto& desc = aTexture.get_SurfaceDescriptorMacIOSurface();
VRDisplayExternal::SubmitFrame(MacIOSurface* aMacIOSurface, RefPtr<MacIOSurface> surf = MacIOSurface::LookupSurface(desc.surfaceId(),
const IntSize& aSize, desc.scaleFactor(),
const gfx::Rect& aLeftEyeRect, !desc.isOpaque());
const gfx::Rect& aRightEyeRect) if (!surf) {
{ NS_WARNING("VRDisplayHost::SubmitFrame failed to get a MacIOSurface");
const void* ioSurface = aMacIOSurface->GetIOSurfacePtr(); return false;
bool result = false; }
if (ioSurface == nullptr) { *aTextureType = VRLayerTextureType::LayerTextureType_MacIOSurface;
NS_WARNING("VRDisplayExternal::SubmitFrame() could not get an IOSurface"); *aTextureHandle = (void *)surf->GetIOSurfacePtr();
} else { return true;
// FINDME! Implement this }
}
return result;
}
#elif defined(MOZ_WIDGET_ANDROID)
bool
VRDisplayExternal::SubmitFrame(const layers::SurfaceTextureDescriptor& aSurface,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) {
return false;
}
#endif #endif
default: {
MOZ_ASSERT(false);
return false;
}
}
}
bool
VRDisplayExternal::SubmitFrame(const layers::SurfaceDescriptor& aTexture,
uint64_t aFrameId,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
VRBrowserState state;
memset(&state, 0, sizeof(VRBrowserState));
state.layerState[0].type = VRLayerType::LayerType_Stereo_Immersive;
VRLayer_Stereo_Immersive& layer = state.layerState[0].layer_stereo_immersive;
if (!PopulateLayerTexture(aTexture, &layer.mTextureType, &layer.mTextureHandle)) {
return false;
}
layer.mFrameId = aFrameId;
layer.mInputFrameId = mDisplayInfo.mLastSensorState[mDisplayInfo.mFrameId % kVRMaxLatencyFrames].inputFrameID;
layer.mLeftEyeRect.x = aLeftEyeRect.x;
layer.mLeftEyeRect.y = aLeftEyeRect.y;
layer.mLeftEyeRect.width = aLeftEyeRect.width;
layer.mLeftEyeRect.height = aLeftEyeRect.height;
layer.mRightEyeRect.x = aRightEyeRect.x;
layer.mRightEyeRect.y = aRightEyeRect.y;
layer.mRightEyeRect.width = aRightEyeRect.width;
layer.mRightEyeRect.height = aRightEyeRect.height;
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
manager->PushState(&state);
VRDisplayState displayState;
memset(&displayState, 0, sizeof(VRDisplayState));
while (displayState.mLastSubmittedFrameId < aFrameId) {
if (manager->PullState(&displayState)) {
if (!displayState.mIsConnected) {
// Service has shut down or hardware has been disconnected
return false;
}
}
#ifdef XP_WIN
Sleep(0);
#else
sleep(0);
#endif
}
return displayState.mLastSubmittedFrameSuccessful;
}
VRControllerExternal::VRControllerExternal(dom::GamepadHand aHand, uint32_t aDisplayID, VRControllerExternal::VRControllerExternal(dom::GamepadHand aHand, uint32_t aDisplayID,
uint32_t aNumButtons, uint32_t aNumTriggers, uint32_t aNumButtons, uint32_t aNumTriggers,
@ -208,8 +262,9 @@ VRControllerExternal::~VRControllerExternal()
MOZ_COUNT_DTOR_INHERITED(VRControllerExternal, VRControllerHost); MOZ_COUNT_DTOR_INHERITED(VRControllerExternal, VRControllerHost);
} }
VRSystemManagerExternal::VRSystemManagerExternal() VRSystemManagerExternal::VRSystemManagerExternal(VRExternalShmem* aAPIShmem /* = nullptr*/)
: mExternalShmem(nullptr) : mExternalShmem(aAPIShmem)
, mSameProcess(aAPIShmem != nullptr)
{ {
#if defined(XP_MACOSX) #if defined(XP_MACOSX)
mShmemFD = 0; mShmemFD = 0;
@ -323,6 +378,9 @@ VRSystemManagerExternal::CheckForShutdown()
void void
VRSystemManagerExternal::CloseShmem() VRSystemManagerExternal::CloseShmem()
{ {
if (mSameProcess) {
return;
}
#if defined(XP_MACOSX) #if defined(XP_MACOSX)
if (mExternalShmem) { if (mExternalShmem) {
munmap((void *)mExternalShmem, sizeof(VRExternalShmem)); munmap((void *)mExternalShmem, sizeof(VRExternalShmem));
@ -347,15 +405,19 @@ VRSystemManagerExternal::CloseShmem()
} }
/*static*/ already_AddRefed<VRSystemManagerExternal> /*static*/ already_AddRefed<VRSystemManagerExternal>
VRSystemManagerExternal::Create() VRSystemManagerExternal::Create(VRExternalShmem* aAPIShmem /* = nullptr*/)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (!gfxPrefs::VREnabled() || !gfxPrefs::VRExternalEnabled()) { if (!gfxPrefs::VREnabled()) {
return nullptr; return nullptr;
} }
RefPtr<VRSystemManagerExternal> manager = new VRSystemManagerExternal(); if (!gfxPrefs::VRExternalEnabled() && aAPIShmem == nullptr) {
return nullptr;
}
RefPtr<VRSystemManagerExternal> manager = new VRSystemManagerExternal(aAPIShmem);
return manager.forget(); return manager.forget();
} }
@ -397,7 +459,17 @@ VRSystemManagerExternal::Enumerate()
OpenShmem(); OpenShmem();
if (mExternalShmem) { if (mExternalShmem) {
VRDisplayState displayState; VRDisplayState displayState;
PullState(&displayState); memset(&displayState, 0, sizeof(VRDisplayState));
// We must block until enumeration has completed in order
// to signal that the WebVR promise should be resolved at the
// right time.
while (!PullState(&displayState)) {
#ifdef XP_WIN
Sleep(0);
#else
sleep(0);
#endif
}
if (displayState.mIsConnected) { if (displayState.mIsConnected) {
mDisplay = new VRDisplayExternal(displayState); mDisplay = new VRDisplayExternal(displayState);
} }
@ -488,9 +560,10 @@ VRSystemManagerExternal::RemoveControllers()
mControllerCount = 0; mControllerCount = 0;
} }
void bool
VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState, VRHMDSensorState* aSensorState /* = nullptr */) VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState, VRHMDSensorState* aSensorState /* = nullptr */)
{ {
bool success = false;
MOZ_ASSERT(mExternalShmem); MOZ_ASSERT(mExternalShmem);
if (mExternalShmem) { if (mExternalShmem) {
#if defined(MOZ_WIDGET_ANDROID) #if defined(MOZ_WIDGET_ANDROID)
@ -501,16 +574,39 @@ VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState, VRHMDSensorSta
} }
pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->systemMutex)); pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->systemMutex));
mDoShutdown = aDisplayState->shutdown; mDoShutdown = aDisplayState->shutdown;
success = mExternalShmem->state.enumerationCompleted;
} }
#else #else
VRExternalShmem tmp; VRExternalShmem tmp;
memcpy(&tmp, (void *)mExternalShmem, sizeof(VRExternalShmem)); memcpy(&tmp, (void *)mExternalShmem, sizeof(VRExternalShmem));
if (tmp.generationA == tmp.generationB && tmp.generationA != 0 && tmp.generationA != -1) { if (tmp.generationA == tmp.generationB && tmp.generationA != 0 && tmp.generationA != -1 && tmp.state.enumerationCompleted) {
memcpy(aDisplayState, &tmp.state.displayState, sizeof(VRDisplayState)); memcpy(aDisplayState, &tmp.state.displayState, sizeof(VRDisplayState));
if (aSensorState) { if (aSensorState) {
memcpy(aSensorState, &tmp.state.sensorState, sizeof(VRHMDSensorState)); memcpy(aSensorState, &tmp.state.sensorState, sizeof(VRHMDSensorState));
} }
success = true;
} }
#endif // defined(MOZ_WIDGET_ANDROID)
}
return success;
}
void
VRSystemManagerExternal::PushState(VRBrowserState* aBrowserState)
{
MOZ_ASSERT(aBrowserState);
MOZ_ASSERT(mExternalShmem);
if (mExternalShmem) {
#if defined(MOZ_WIDGET_ANDROID)
if (pthread_mutex_lock((pthread_mutex_t*)&(mExternalShmem->browserMutex)) == 0) {
memcpy((void *)&(mExternalShmem->browserState), aBrowserState, sizeof(VRBrowserState));
pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->browserMutex));
}
#else
mExternalShmem->browserGenerationA++;
memcpy((void *)&(mExternalShmem->browserState), (void *)aBrowserState, sizeof(VRBrowserState));
mExternalShmem->browserGenerationB++;
#endif // defined(MOZ_WIDGET_ANDROID) #endif // defined(MOZ_WIDGET_ANDROID)
} }
} }

View File

@ -33,24 +33,14 @@ public:
void ZeroSensor() override; void ZeroSensor() override;
protected: protected:
virtual VRHMDSensorState GetSensorState() override; VRHMDSensorState GetSensorState() override;
virtual void StartPresentation() override; void StartPresentation() override;
virtual void StopPresentation() override; void StopPresentation() override;
#if defined(XP_WIN)
virtual bool SubmitFrame(ID3D11Texture2D* aSource, bool SubmitFrame(const layers::SurfaceDescriptor& aTexture,
const IntSize& aSize, uint64_t aFrameId,
const gfx::Rect& aLeftEyeRect, const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override; 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;
#elif defined(MOZ_WIDGET_ANDROID)
bool SubmitFrame(const layers::SurfaceTextureDescriptor& aSurface,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
#endif
public: public:
explicit VRDisplayExternal(const VRDisplayState& aDisplayState); explicit VRDisplayExternal(const VRDisplayState& aDisplayState);
@ -59,6 +49,11 @@ protected:
virtual ~VRDisplayExternal(); virtual ~VRDisplayExternal();
void Destroy(); void Destroy();
private:
bool PopulateLayerTexture(const layers::SurfaceDescriptor& aTexture,
VRLayerTextureType* aTextureType,
void** aTextureHandle);
VRTelemetry mTelemetry; VRTelemetry mTelemetry;
bool mIsPresenting; bool mIsPresenting;
VRHMDSensorState mLastSensorState; VRHMDSensorState mLastSensorState;
@ -80,7 +75,7 @@ protected:
class VRSystemManagerExternal : public VRSystemManager class VRSystemManagerExternal : public VRSystemManager
{ {
public: public:
static already_AddRefed<VRSystemManagerExternal> Create(); static already_AddRefed<VRSystemManagerExternal> Create(VRExternalShmem* aAPIShmem = nullptr);
virtual void Destroy() override; virtual void Destroy() override;
virtual void Shutdown() override; virtual void Shutdown() override;
@ -100,10 +95,11 @@ public:
double aDuration, double aDuration,
const VRManagerPromise& aPromise) override; const VRManagerPromise& aPromise) override;
virtual void StopVibrateHaptic(uint32_t aControllerIdx) override; virtual void StopVibrateHaptic(uint32_t aControllerIdx) override;
void PullState(VRDisplayState* aDisplayState, VRHMDSensorState* aSensorState = nullptr); bool PullState(VRDisplayState* aDisplayState, VRHMDSensorState* aSensorState = nullptr);
void PushState(VRBrowserState* aBrowserState);
protected: protected:
VRSystemManagerExternal(); explicit VRSystemManagerExternal(VRExternalShmem* aAPIShmem = nullptr);
virtual ~VRSystemManagerExternal(); virtual ~VRSystemManagerExternal();
private: private:
@ -120,6 +116,7 @@ private:
#endif #endif
volatile VRExternalShmem* mExternalShmem; volatile VRExternalShmem* mExternalShmem;
bool mSameProcess;
void OpenShmem(); void OpenShmem();
void CloseShmem(); void CloseShmem();

View File

@ -211,13 +211,13 @@ SetFromTanRadians(double left, double right, double bottom, double top)
VRDisplayOSVR::VRDisplayOSVR(OSVR_ClientContext* context, VRDisplayOSVR::VRDisplayOSVR(OSVR_ClientContext* context,
OSVR_ClientInterface* iface, OSVR_ClientInterface* iface,
OSVR_DisplayConfig* display) OSVR_DisplayConfig* display)
: VRDisplayHost(VRDeviceType::OSVR) : VRDisplayLocal(VRDeviceType::OSVR)
, m_ctx(context) , m_ctx(context)
, m_iface(iface) , m_iface(iface)
, m_display(display) , m_display(display)
{ {
MOZ_COUNT_CTOR_INHERITED(VRDisplayOSVR, VRDisplayHost); MOZ_COUNT_CTOR_INHERITED(VRDisplayOSVR, VRDisplayLocal);
VRDisplayState& state = mDisplayInfo.mDisplayState; VRDisplayState& state = mDisplayInfo.mDisplayState;
state.mIsConnected = true; state.mIsConnected = true;

View File

@ -14,7 +14,7 @@
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/EnumeratedArray.h" #include "mozilla/EnumeratedArray.h"
#include "VRDisplayHost.h" #include "VRDisplayLocal.h"
#include <osvr/ClientKit/ClientKitC.h> #include <osvr/ClientKit/ClientKitC.h>
#include <osvr/ClientKit/DisplayC.h> #include <osvr/ClientKit/DisplayC.h>
@ -26,7 +26,7 @@ namespace mozilla {
namespace gfx { namespace gfx {
namespace impl { namespace impl {
class VRDisplayOSVR : public VRDisplayHost class VRDisplayOSVR : public VRDisplayLocal
{ {
public: public:
void ZeroSensor() override; void ZeroSensor() override;
@ -57,7 +57,7 @@ protected:
virtual ~VRDisplayOSVR() virtual ~VRDisplayOSVR()
{ {
Destroy(); Destroy();
MOZ_COUNT_DTOR_INHERITED(VRDisplayOSVR, VRDisplayHost); MOZ_COUNT_DTOR_INHERITED(VRDisplayOSVR, VRDisplayLocal);
} }
void Destroy(); void Destroy();

View File

@ -795,7 +795,7 @@ VROculusSession::UnloadOvrLib()
} }
VRDisplayOculus::VRDisplayOculus(VROculusSession* aSession) VRDisplayOculus::VRDisplayOculus(VROculusSession* aSession)
: VRDisplayHost(VRDeviceType::Oculus) : VRDisplayLocal(VRDeviceType::Oculus)
, mSession(aSession) , mSession(aSession)
, mQuadVS(nullptr) , mQuadVS(nullptr)
, mQuadPS(nullptr) , mQuadPS(nullptr)
@ -806,7 +806,7 @@ VRDisplayOculus::VRDisplayOculus(VROculusSession* aSession)
, mInputLayout(nullptr) , mInputLayout(nullptr)
, mEyeHeight(OVR_DEFAULT_EYE_HEIGHT) , mEyeHeight(OVR_DEFAULT_EYE_HEIGHT)
{ {
MOZ_COUNT_CTOR_INHERITED(VRDisplayOculus, VRDisplayHost); MOZ_COUNT_CTOR_INHERITED(VRDisplayOculus, VRDisplayLocal);
VRDisplayState& state = mDisplayInfo.mDisplayState; VRDisplayState& state = mDisplayInfo.mDisplayState;
strncpy(state.mDisplayName, "Oculus VR HMD", kVRDisplayNameMaxLen); strncpy(state.mDisplayName, "Oculus VR HMD", kVRDisplayNameMaxLen);
state.mIsConnected = true; state.mIsConnected = true;
@ -852,7 +852,7 @@ VRDisplayOculus::VRDisplayOculus(VROculusSession* aSession)
VRDisplayOculus::~VRDisplayOculus() { VRDisplayOculus::~VRDisplayOculus() {
Destroy(); Destroy();
MOZ_COUNT_DTOR_INHERITED(VRDisplayOculus, VRDisplayHost); MOZ_COUNT_DTOR_INHERITED(VRDisplayOculus, VRDisplayLocal);
} }
void void

View File

@ -15,7 +15,7 @@
#include "mozilla/EnumeratedArray.h" #include "mozilla/EnumeratedArray.h"
#include "gfxVR.h" #include "gfxVR.h"
#include "VRDisplayHost.h" #include "VRDisplayLocal.h"
#include "ovr_capi_dynamic.h" #include "ovr_capi_dynamic.h"
struct ID3D11Device; struct ID3D11Device;
@ -90,7 +90,7 @@ private:
void StopRendering(); void StopRendering();
}; };
class VRDisplayOculus : public VRDisplayHost class VRDisplayOculus : public VRDisplayLocal
{ {
public: public:
void ZeroSensor() override; void ZeroSensor() override;

View File

@ -50,13 +50,13 @@ static const uint32_t kNumOpenVRHaptcs = 1;
VRDisplayOpenVR::VRDisplayOpenVR(::vr::IVRSystem *aVRSystem, VRDisplayOpenVR::VRDisplayOpenVR(::vr::IVRSystem *aVRSystem,
::vr::IVRChaperone *aVRChaperone, ::vr::IVRChaperone *aVRChaperone,
::vr::IVRCompositor *aVRCompositor) ::vr::IVRCompositor *aVRCompositor)
: VRDisplayHost(VRDeviceType::OpenVR) : VRDisplayLocal(VRDeviceType::OpenVR)
, mVRSystem(aVRSystem) , mVRSystem(aVRSystem)
, mVRChaperone(aVRChaperone) , mVRChaperone(aVRChaperone)
, mVRCompositor(aVRCompositor) , mVRCompositor(aVRCompositor)
, mIsPresenting(false) , mIsPresenting(false)
{ {
MOZ_COUNT_CTOR_INHERITED(VRDisplayOpenVR, VRDisplayHost); MOZ_COUNT_CTOR_INHERITED(VRDisplayOpenVR, VRDisplayLocal);
VRDisplayState& state = mDisplayInfo.mDisplayState; VRDisplayState& state = mDisplayInfo.mDisplayState;
@ -98,7 +98,7 @@ VRDisplayOpenVR::VRDisplayOpenVR(::vr::IVRSystem *aVRSystem,
VRDisplayOpenVR::~VRDisplayOpenVR() VRDisplayOpenVR::~VRDisplayOpenVR()
{ {
Destroy(); Destroy();
MOZ_COUNT_DTOR_INHERITED(VRDisplayOpenVR, VRDisplayHost); MOZ_COUNT_DTOR_INHERITED(VRDisplayOpenVR, VRDisplayLocal);
} }
void void
@ -350,11 +350,11 @@ VRDisplayOpenVR::StopPresentation()
} }
bool bool
VRDisplayOpenVR::SubmitFrame(void* aTextureHandle, VRDisplayOpenVR::SubmitFrameOpenVRHandle(void* aTextureHandle,
::vr::ETextureType aTextureType, ::vr::ETextureType aTextureType,
const IntSize& aSize, const IntSize& aSize,
const gfx::Rect& aLeftEyeRect, const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) const gfx::Rect& aRightEyeRect)
{ {
MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread()); MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
if (!mIsPresenting) { if (!mIsPresenting) {
@ -400,9 +400,9 @@ VRDisplayOpenVR::SubmitFrame(ID3D11Texture2D* aSource,
const gfx::Rect& aLeftEyeRect, const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) const gfx::Rect& aRightEyeRect)
{ {
return SubmitFrame((void *)aSource, return SubmitFrameOpenVRHandle((void *)aSource,
::vr::ETextureType::TextureType_DirectX, ::vr::ETextureType::TextureType_DirectX,
aSize, aLeftEyeRect, aRightEyeRect); aSize, aLeftEyeRect, aRightEyeRect);
} }
#elif defined(XP_MACOSX) #elif defined(XP_MACOSX)
@ -418,9 +418,9 @@ VRDisplayOpenVR::SubmitFrame(MacIOSurface* aMacIOSurface,
if (ioSurface == nullptr) { if (ioSurface == nullptr) {
NS_WARNING("VRDisplayOpenVR::SubmitFrame() could not get an IOSurface"); NS_WARNING("VRDisplayOpenVR::SubmitFrame() could not get an IOSurface");
} else { } else {
result = SubmitFrame((void *)ioSurface, result = SubmitFrameOpenVRHandle((void *)ioSurface,
::vr::ETextureType::TextureType_IOSurface, ::vr::ETextureType::TextureType_IOSurface,
aSize, aLeftEyeRect, aRightEyeRect); aSize, aLeftEyeRect, aRightEyeRect);
} }
return result; return result;
} }

View File

@ -17,7 +17,7 @@
#include "openvr.h" #include "openvr.h"
#include "gfxVR.h" #include "gfxVR.h"
#include "VRDisplayHost.h" #include "VRDisplayLocal.h"
#if defined(XP_MACOSX) #if defined(XP_MACOSX)
class MacIOSurface; class MacIOSurface;
@ -28,7 +28,7 @@ class VRThread;
namespace impl { namespace impl {
class VRDisplayOpenVR : public VRDisplayHost class VRDisplayOpenVR : public VRDisplayLocal
{ {
public: public:
void ZeroSensor() override; void ZeroSensor() override;
@ -70,11 +70,11 @@ protected:
void UpdateStageParameters(); void UpdateStageParameters();
void UpdateEyeParameters(gfx::Matrix4x4* aHeadToEyeTransforms = nullptr); void UpdateEyeParameters(gfx::Matrix4x4* aHeadToEyeTransforms = nullptr);
bool SubmitFrame(void* aTextureHandle, bool SubmitFrameOpenVRHandle(void* aTextureHandle,
::vr::ETextureType aTextureType, ::vr::ETextureType aTextureType,
const IntSize& aSize, const IntSize& aSize,
const gfx::Rect& aLeftEyeRect, const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect); const gfx::Rect& aRightEyeRect);
}; };
class VRControllerOpenVR : public VRControllerHost class VRControllerOpenVR : public VRControllerHost

View File

@ -50,11 +50,11 @@ static const uint32_t kNumPuppetAxis = 3;
static const uint32_t kNumPuppetHaptcs = 1; static const uint32_t kNumPuppetHaptcs = 1;
VRDisplayPuppet::VRDisplayPuppet() VRDisplayPuppet::VRDisplayPuppet()
: VRDisplayHost(VRDeviceType::Puppet) : VRDisplayLocal(VRDeviceType::Puppet)
, mIsPresenting(false) , mIsPresenting(false)
, mSensorState{} , mSensorState{}
{ {
MOZ_COUNT_CTOR_INHERITED(VRDisplayPuppet, VRDisplayHost); MOZ_COUNT_CTOR_INHERITED(VRDisplayPuppet, VRDisplayLocal);
VRDisplayState& state = mDisplayInfo.mDisplayState; VRDisplayState& state = mDisplayInfo.mDisplayState;
strncpy(state.mDisplayName, "Puppet HMD", kVRDisplayNameMaxLen); strncpy(state.mDisplayName, "Puppet HMD", kVRDisplayNameMaxLen);
@ -123,7 +123,7 @@ VRDisplayPuppet::VRDisplayPuppet()
VRDisplayPuppet::~VRDisplayPuppet() VRDisplayPuppet::~VRDisplayPuppet()
{ {
MOZ_COUNT_DTOR_INHERITED(VRDisplayPuppet, VRDisplayHost); MOZ_COUNT_DTOR_INHERITED(VRDisplayPuppet, VRDisplayLocal);
} }
void void

View File

@ -12,7 +12,7 @@
#include "nsRefPtrHashtable.h" #include "nsRefPtrHashtable.h"
#include "gfxVR.h" #include "gfxVR.h"
#include "VRDisplayHost.h" #include "VRDisplayLocal.h"
#if defined(XP_MACOSX) #if defined(XP_MACOSX)
class MacIOSurface; class MacIOSurface;
@ -21,7 +21,7 @@ namespace mozilla {
namespace gfx { namespace gfx {
namespace impl { namespace impl {
class VRDisplayPuppet : public VRDisplayHost class VRDisplayPuppet : public VRDisplayLocal
{ {
public: public:
void SetDisplayInfo(const VRDisplayInfo& aDisplayInfo); void SetDisplayInfo(const VRDisplayInfo& aDisplayInfo);

View File

@ -47,6 +47,7 @@ struct ParamTraits<mozilla::gfx::VRDisplayState>
WriteParam(aMsg, aParam.mIsMounted); WriteParam(aMsg, aParam.mIsMounted);
WriteParam(aMsg, aParam.mStageSize.width); WriteParam(aMsg, aParam.mStageSize.width);
WriteParam(aMsg, aParam.mStageSize.height); WriteParam(aMsg, aParam.mStageSize.height);
WriteParam(aMsg, aParam.mLastSubmittedFrameId);
WriteParam(aMsg, aParam.mPresentingGeneration); WriteParam(aMsg, aParam.mPresentingGeneration);
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
// TODO - Should probably memcpy the whole array or // TODO - Should probably memcpy the whole array or
@ -73,6 +74,7 @@ struct ParamTraits<mozilla::gfx::VRDisplayState>
!ReadParam(aMsg, aIter, &(aResult->mIsMounted)) || !ReadParam(aMsg, aIter, &(aResult->mIsMounted)) ||
!ReadParam(aMsg, aIter, &(aResult->mStageSize.width)) || !ReadParam(aMsg, aIter, &(aResult->mStageSize.width)) ||
!ReadParam(aMsg, aIter, &(aResult->mStageSize.height)) || !ReadParam(aMsg, aIter, &(aResult->mStageSize.height)) ||
!ReadParam(aMsg, aIter, &(aResult->mLastSubmittedFrameId)) ||
!ReadParam(aMsg, aIter, &(aResult->mPresentingGeneration))) { !ReadParam(aMsg, aIter, &(aResult->mPresentingGeneration))) {
return false; return false;
} }

View File

@ -47,6 +47,7 @@ SOURCES += [
'gfxVRExternal.cpp', 'gfxVRExternal.cpp',
'gfxVRPuppet.cpp', 'gfxVRPuppet.cpp',
'VRDisplayHost.cpp', 'VRDisplayHost.cpp',
'VRDisplayLocal.cpp',
] ]
# Build OpenVR on Windows, Linux, and macOS desktop targets # Build OpenVR on Windows, Linux, and macOS desktop targets