Bug 1392217 - Part 2: Spawn a VR submit thread in VRDisplayHost; r?kip
MozReview-Commit-ID: 5xvTepEFxe0
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -72,16 +72,20 @@ VRDisplayHost::VRDisplayHost(VRDeviceTyp
mDisplayInfo.mPresentingGroups = 0;
mDisplayInfo.mGroupMask = kVRGroupContent;
mDisplayInfo.mFrameId = 0;
mDisplayInfo.mPresentingGeneration = 0;
}
VRDisplayHost::~VRDisplayHost()
{
+ if (mSubmitThread) {
+ mSubmitThread->Shutdown();
+ mSubmitThread = nullptr;
+ }
MOZ_COUNT_DTOR(VRDisplayHost);
}
#if defined(XP_WIN)
bool
VRDisplayHost::CreateD3DObjects()
{
if (!mDevice) {
@@ -248,33 +252,24 @@ VRDisplayHost::NotifyVSync()
if (bShouldStartFrame) {
VRManager *vm = VRManager::Get();
MOZ_ASSERT(vm);
vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
}
}
void
-VRDisplayHost::SubmitFrame(VRLayerParent* aLayer,
- const layers::SurfaceDescriptor &aTexture,
- uint64_t aFrameId,
- const gfx::Rect& aLeftEyeRect,
- const gfx::Rect& aRightEyeRect)
+VRDisplayHost::SubmitFrameInternal(const layers::SurfaceDescriptor &aTexture,
+ uint64_t aFrameId,
+ const gfx::Rect& aLeftEyeRect,
+ const gfx::Rect& aRightEyeRect)
{
+ MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
AUTO_PROFILER_TRACING("VR", "SubmitFrameAtVRDisplayHost");
- if ((mDisplayInfo.mGroupMask & aLayer->GetGroup()) == 0) {
- // Suppress layers hidden by the group mask
- return;
- }
-
- // Ensure that we only accept the first SubmitFrame call per RAF cycle.
- if (!mFrameStarted || aFrameId != mDisplayInfo.mFrameId) {
- return;
- }
mFrameStarted = false;
switch (aTexture.type()) {
#if defined(XP_WIN)
case SurfaceDescriptor::TSurfaceDescriptorD3D10: {
if (!CreateD3DObjects()) {
return;
}
@@ -331,21 +326,21 @@ VRDisplayHost::SubmitFrame(VRLayerParent
surf->GetDevicePixelHeight());
if (!SubmitFrame(surf, texSize, aLeftEyeRect, aRightEyeRect)) {
return;
}
break;
}
#elif defined(MOZ_ANDROID_GOOGLE_VR)
case SurfaceDescriptor::TEGLImageDescriptor: {
- const EGLImageDescriptor& desc = aTexture.get_EGLImageDescriptor();
- if (!SubmitFrame(&desc, aLeftEyeRect, aRightEyeRect)) {
- return;
- }
- break;
+ const EGLImageDescriptor& desc = aTexture.get_EGLImageDescriptor();
+ if (!SubmitFrame(&desc, aLeftEyeRect, aRightEyeRect)) {
+ return;
+ }
+ break;
}
#endif
default: {
NS_WARNING("Unsupported SurfaceDescriptor type for VR layer texture");
return;
}
}
@@ -366,16 +361,45 @@ VRDisplayHost::SubmitFrame(VRLayerParent
loop->PostTask(NewRunnableMethod<const uint32_t>(
"gfx::VRManager::NotifyVRVsync",
vm, &VRManager::NotifyVRVsync, mDisplayInfo.mDisplayID
));
#endif
}
+void
+VRDisplayHost::SubmitFrame(VRLayerParent* aLayer,
+ const layers::SurfaceDescriptor &aTexture,
+ uint64_t aFrameId,
+ const gfx::Rect& aLeftEyeRect,
+ const gfx::Rect& aRightEyeRect)
+{
+ if (!mSubmitThread) {
+ mSubmitThread = new VRThread(NS_LITERAL_CSTRING("VR_SubmitFrame"));
+ }
+
+ if ((mDisplayInfo.mGroupMask & aLayer->GetGroup()) == 0) {
+ // Suppress layers hidden by the group mask
+ return;
+ }
+
+ // Ensure that we only accept the first SubmitFrame call per RAF cycle.
+ if (!mFrameStarted || aFrameId != mDisplayInfo.mFrameId) {
+ return;
+ }
+
+ mSubmitThread->Start();
+ mSubmitThread->PostTask(
+ NewRunnableMethod<StoreCopyPassByConstLRef<layers::SurfaceDescriptor>, uint64_t,
+ StoreCopyPassByConstLRef<gfx::Rect>, StoreCopyPassByConstLRef<gfx::Rect>>(
+ "gfx::VRDisplayHost::SubmitFrameInternal", this, &VRDisplayHost::SubmitFrameInternal,
+ aTexture, aFrameId, aLeftEyeRect, aRightEyeRect));
+}
+
bool
VRDisplayHost::CheckClearDisplayInfoDirty()
{
if (mDisplayInfo == mLastUpdateDisplayInfo) {
return false;
}
mLastUpdateDisplayInfo = mDisplayInfo;
return true;
--- a/gfx/vr/VRDisplayHost.h
+++ b/gfx/vr/VRDisplayHost.h
@@ -22,16 +22,17 @@
#if defined(XP_WIN)
#include <d3d11_1.h>
#elif defined(XP_MACOSX)
class MacIOSurface;
#endif
namespace mozilla {
namespace gfx {
+class VRThread;
class VRLayerParent;
class VRDisplayHost {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRDisplayHost)
const VRDisplayInfo& GetDisplayInfo() const { return mDisplayInfo; }
@@ -95,17 +96,23 @@ protected:
nsTArray<VRLayerParent *> mLayers;
// Weak reference to mLayers entries are cleared in
// VRLayerParent destructor
protected:
virtual VRHMDSensorState GetSensorState() = 0;
+ RefPtr<VRThread> mSubmitThread;
private:
+ void SubmitFrameInternal(const layers::SurfaceDescriptor& aTexture,
+ uint64_t aFrameId,
+ const gfx::Rect& aLeftEyeRect,
+ const gfx::Rect& aRightEyeRect);
+
VRDisplayInfo mLastUpdateDisplayInfo;
TimeStamp mLastFrameStart;
bool mFrameStarted;
#if defined(XP_WIN)
protected:
bool CreateD3DObjects();
RefPtr<ID3D11Device1> mDevice;
--- a/gfx/vr/gfxVROSVR.cpp
+++ b/gfx/vr/gfxVROSVR.cpp
@@ -349,27 +349,29 @@ VRDisplayOSVR::SubmitFrame(ID3D11Texture
bool
VRDisplayOSVR::SubmitFrame(MacIOSurface* aMacIOSurface,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
// XXX Add code to submit frame
+ MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
return false;
}
#elif defined(MOZ_ANDROID_GOOGLE_VR)
bool
VRDisplayOSVR::SubmitFrame(const mozilla::layers::EGLImageDescriptor*,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
// XXX Add code to submit frame
+ MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
return false;
}
#endif
void
VRDisplayOSVR::StartPresentation()
{
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -279,16 +279,17 @@ VROculusSession::StopPresentation()
}
}
Refresh();
}
}
VROculusSession::~VROculusSession()
{
+ mSubmitThread = nullptr;
Uninitialize(true);
}
void
VROculusSession::Uninitialize(bool aUnloadLib)
{
StopRendering();
StopSession();
@@ -351,26 +352,29 @@ VROculusSession::Refresh(bool aForceRefr
// ensures that the user will not drop to Oculus Home during VR link
// traversal.
bInvisible = false;
// While we are waiting for either the timeout or a new presentation,
// fill the HMD with black / no layers.
if (mSession && mTextureSet) {
if (!aForceRefresh) {
- // ovr_SubmitFrame is only allowed been run at Compositor thread,
- // so we post this task to Compositor thread and let it determine
- // if reloading library.
+ // VROculusSession didn't start submitting frames yet.
+ if (!mSubmitThread) {
+ return;
+ }
+ // ovr_SubmitFrame is running at VR Submit thread,
+ // so we post this task to VR Submit thread and let it paint
+ // a black frame.
mDrawBlack = true;
- MessageLoop* loop = layers::CompositorThreadHolder::Loop();
- loop->PostTask(NewRunnableMethod<bool>(
+ MOZ_ASSERT(mSubmitThread->IsActive());
+ mSubmitThread->PostTask(NewRunnableMethod<bool>(
"gfx::VROculusSession::Refresh",
this,
&VROculusSession::Refresh, true));
-
return;
}
ovrLayerEyeFov layer;
memset(&layer, 0, sizeof(layer));
layer.Header.Type = ovrLayerType_Disabled;
ovrLayerHeader *layers = &layer.Header;
ovr_SubmitFrame(mSession, 0, nullptr, &layers, 1);
mDrawBlack = false;
@@ -1090,16 +1094,17 @@ VRDisplayOculus::UpdateConstantBuffers()
}
bool
VRDisplayOculus::SubmitFrame(ID3D11Texture2D* aSource,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
+ MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
if (!CreateD3DObjects()) {
return false;
}
AutoRestoreRenderState restoreState(this);
if (!restoreState.IsSuccess()) {
return false;
}
@@ -1240,16 +1245,17 @@ VRDisplayOculus::SubmitFrame(ID3D11Textu
* "health and safety warning", orv will be > 0 (OVR_SUCCESS but not
* OVR_UNQUALIFIED_SUCCESS) and ovr_SubmitFrame will not block.
* In this case, returning true would have resulted in an unthrottled
* render loop hiting excessive frame rates and consuming resources.
*/
return false;
}
+ mSession->mSubmitThread = mSubmitThread;
return true;
}
void
VRDisplayOculus::NotifyVSync()
{
mSession->Refresh();
if (mSession->IsTrackingReady()) {
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -57,16 +57,17 @@ public:
private:
PRLibrary* mOvrLib;
ovrSession mSession;
ovrInitFlags mInitFlags;
ovrTextureSwapChain mTextureSet;
nsTArray<RefPtr<layers::CompositingRenderTargetD3D11>> mRenderTargets;
IntSize mPresentationSize;
RefPtr<ID3D11Device> mDevice;
+ RefPtr<VRThread> mSubmitThread;
// The timestamp of the last time Oculus set ShouldQuit to true.
TimeStamp mLastShouldQuit;
// The timestamp of the last ending presentation
TimeStamp mLastPresentationEnd;
VRTelemetry mTelemetry;
bool mPresenting;
bool mDrawBlack;
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -348,16 +348,17 @@ VRDisplayOpenVR::StopPresentation()
bool
VRDisplayOpenVR::SubmitFrame(void* aTextureHandle,
::vr::ETextureType aTextureType,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
+ MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
if (!mIsPresenting) {
return false;
}
::vr::Texture_t tex;
tex.handle = aTextureHandle;
tex.eType = aTextureType;
tex.eColorSpace = ::vr::EColorSpace::ColorSpace_Auto;
--- a/gfx/vr/gfxVRPuppet.cpp
+++ b/gfx/vr/gfxVRPuppet.cpp
@@ -284,16 +284,17 @@ VRDisplayPuppet::UpdateConstantBuffers()
}
bool
VRDisplayPuppet::SubmitFrame(ID3D11Texture2D* aSource,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
+ MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
if (!mIsPresenting) {
return false;
}
if (!CreateD3DObjects()) {
return false;
}
AutoRestoreRenderState restoreState(this);
@@ -480,16 +481,17 @@ VRDisplayPuppet::SubmitFrame(ID3D11Textu
#elif defined(XP_MACOSX)
bool
VRDisplayPuppet::SubmitFrame(MacIOSurface* aMacIOSurface,
const IntSize& aSize,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
+ MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
if (!mIsPresenting || !aMacIOSurface) {
return false;
}
VRManager* vm = VRManager::Get();
MOZ_ASSERT(vm);
switch (gfxPrefs::VRPuppetSubmitFrame()) {
@@ -553,18 +555,19 @@ VRDisplayPuppet::SubmitFrame(MacIOSurfac
return false;
}
#elif defined(MOZ_ANDROID_GOOGLE_VR)
bool
VRDisplayPuppet::SubmitFrame(const mozilla::layers::EGLImageDescriptor* aDescriptor,
const gfx::Rect& aLeftEyeRect,
- const gfx::Rect& aRightEyeRect) {
-
+ const gfx::Rect& aRightEyeRect)
+{
+ MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
return false;
}
#endif
void
VRDisplayPuppet::NotifyVSync()
{
--- a/gfx/vr/ipc/VRLayerParent.cpp
+++ b/gfx/vr/ipc/VRLayerParent.cpp
@@ -60,36 +60,20 @@ VRLayerParent::Destroy()
mozilla::ipc::IPCResult
VRLayerParent::RecvSubmitFrame(const layers::SurfaceDescriptor &aTexture,
const uint64_t& aFrameId,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
if (mVRDisplayID) {
- MessageLoop* loop = layers::CompositorThreadHolder::Loop();
VRManager* vm = VRManager::Get();
RefPtr<VRDisplayHost> display = vm->GetDisplay(mVRDisplayID);
if (display) {
- // Because VR compositor still shares the same graphics device with Compositor thread.
- // We have to post sumbit frame tasks to Compositor thread.
- // TODO: Move SubmitFrame to Bug 1392217.
- loop->PostTask(NewRunnableMethod<VRDisplayHost*, const layers::SurfaceDescriptor, uint64_t,
- const gfx::Rect&, const gfx::Rect&>(
- "gfx::VRLayerParent::SubmitFrame",
- this,
- &VRLayerParent::SubmitFrame, display, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect));
+ display->SubmitFrame(this, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect);
}
}
return IPC_OK();
}
-void
-VRLayerParent::SubmitFrame(VRDisplayHost* aDisplay, const layers::SurfaceDescriptor& aTexture,
- uint64_t aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect)
-{
- aDisplay->SubmitFrame(this, aTexture, aFrameId,
- aLeftEyeRect, aRightEyeRect);
-}
-
} // namespace gfx
} // namespace mozilla
--- a/gfx/vr/ipc/VRLayerParent.h
+++ b/gfx/vr/ipc/VRLayerParent.h
@@ -35,18 +35,14 @@ protected:
void Destroy();
bool mIPCOpen;
uint32_t mVRDisplayID;
gfx::Rect mLeftEyeRect;
gfx::Rect mRightEyeRect;
uint32_t mGroup;
-
-private:
- void SubmitFrame(VRDisplayHost* aDisplay, const layers::SurfaceDescriptor& aTexture,
- uint64_t aFrameId, const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect);
};
} // namespace gfx
} // namespace mozilla
#endif