Bug 1570128:Part 1 - Present VR output to VR Host r=kip,jrmuizel,handyman,sotaro

This change introduces plumbing for communicating with the GPU process through
VRShMem while bootstrapping Firefox for creating a window with Firefox Reality.
Test impact shows a fabricated value returned for the texture handle in VRShMem.

Differential Revision: https://phabricator.services.mozilla.com/D41383

--HG--
extra : moz-landing-system : lando
This commit is contained in:
thomasmo 2019-09-04 19:58:51 +00:00
parent 0aa770f849
commit a7ea9dae63
13 changed files with 119 additions and 11 deletions

View File

@ -534,6 +534,15 @@ mozilla::ipc::IPCResult CompositorBridgeParent::RecvPause() {
return IPC_OK();
}
mozilla::ipc::IPCResult CompositorBridgeParent::RecvRequestFxrOutput() {
#ifdef XP_WIN
// Continue forwarding the request to the Widget + SwapChain
mWidget->AsWindows()->RequestFxrOutput();
#endif
return IPC_OK();
}
mozilla::ipc::IPCResult CompositorBridgeParent::RecvResume() {
ResumeComposition();
return IPC_OK();

View File

@ -253,6 +253,7 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
FrameUniformityData* data) = 0;
virtual mozilla::ipc::IPCResult RecvWillClose() = 0;
virtual mozilla::ipc::IPCResult RecvPause() = 0;
virtual mozilla::ipc::IPCResult RecvRequestFxrOutput() = 0;
virtual mozilla::ipc::IPCResult RecvResume() = 0;
virtual mozilla::ipc::IPCResult RecvResumeAsync() = 0;
virtual mozilla::ipc::IPCResult RecvNotifyChildCreated(
@ -320,6 +321,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
FrameUniformityData* aOutData) override;
mozilla::ipc::IPCResult RecvWillClose() override;
mozilla::ipc::IPCResult RecvPause() override;
mozilla::ipc::IPCResult RecvRequestFxrOutput() override;
mozilla::ipc::IPCResult RecvResume() override;
mozilla::ipc::IPCResult RecvResumeAsync() override;
mozilla::ipc::IPCResult RecvNotifyChildCreated(

View File

@ -42,6 +42,9 @@ class ContentCompositorBridgeParent final : public CompositorBridgeParentBase {
}
mozilla::ipc::IPCResult RecvWillClose() override { return IPC_OK(); }
mozilla::ipc::IPCResult RecvPause() override { return IPC_OK(); }
mozilla::ipc::IPCResult RecvRequestFxrOutput() override {
return IPC_FAIL_NO_REASON(this);
}
mozilla::ipc::IPCResult RecvResume() override { return IPC_OK(); }
mozilla::ipc::IPCResult RecvResumeAsync() override { return IPC_OK(); }
mozilla::ipc::IPCResult RecvNotifyChildCreated(

View File

@ -273,6 +273,9 @@ parent:
sync EndRecording()
returns (bool success);
// To set up sharing the composited output to Firefox Reality on Desktop
async RequestFxrOutput();
child:
// Send back Compositor Frame Metrics from APZCs so tiled layers can
// update progressively.

View File

@ -23,6 +23,7 @@ EXPORTS += [
'VRDisplayPresentation.h',
'VRManager.h',
'VRPuppetCommandBuffer.h',
'VRShMem.h',
'VRThread.h',
]

View File

@ -22,11 +22,39 @@
#include "nsCOMPtr.h"
#include "windows.h"
#include "WinUtils.h"
#include "VRShMem.h"
NS_IMPL_ISUPPORTS(nsFxrCommandLineHandler, nsICommandLineHandler)
// nsFxrCommandLineHandler acts in the middle of bootstrapping Firefox
// Reality with desktop Firefox. Details of the processes involved are
// described below:
//
// Host
// (vrhost!CreateVRWindow) Fx Main Fx GPU
// | + +
// VRShMem creates shared + +
// memory in OS + +
// | + +
// Launch firefox.exe + +
// with --fxr + +
// | | +
// Wait for Signal... nsFxrCLH handles param +
// | joins VRShMem +
// | creates new window |
// | sets .hwndFx in VRShMem |
// | | |
// | | After compositor and
// | | swapchain created,
// | | share texture handle to
// | | VRShMem and set signal
// CreateVRWindow returns | |
// to host | |
// | | |
//
NS_IMETHODIMP
nsFxrCommandLineHandler::Handle(nsICommandLine* aCmdLine) {
bool handleFlagRetVal = false;
@ -60,24 +88,17 @@ nsFxrCommandLineHandler::Handle(nsICommandLine* aCmdLine) {
nsPIDOMWindowOuter::From(newWindow));
HWND hwndWidget = (HWND)newWidget->GetNativeData(NS_NATIVE_WINDOW);
// The CLH should have populated this first
// The CLH should populate these members first
MOZ_ASSERT(windowState.hwndFx == 0);
MOZ_ASSERT(windowState.textureFx == nullptr);
windowState.hwndFx = (uint64_t)hwndWidget;
shmem.PushWindowState(windowState);
// Notify the waiting process that the data is now available
HANDLE hSignal = ::OpenEventA(EVENT_ALL_ACCESS, // dwDesiredAccess
FALSE, // bInheritHandle
windowState.signalName // lpName
);
::SetEvent(hSignal);
shmem.LeaveShMem();
::CloseHandle(hSignal);
// The GPU process will notify the host that window creation is complete
// after output data is set in VRShMem
newWidget->RequestFxrOutput();
} else {
MOZ_CRASH("failed to start with --fxr");
}

View File

@ -120,6 +120,8 @@ DWORD StartFirefoxThreadProc(_In_ LPVOID lpParameter) {
// This export is responsible for starting up a new VR window in Firefox and
// returning data related to its creation back to the caller.
// See nsFxrCommandLineHandler::Handle for more details about the bootstrapping
// process with Firefox.
void CreateVRWindow(char* firefoxFolderPath, char* firefoxProfilePath,
uint32_t dxgiAdapterID, uint32_t widthHost,
uint32_t heightHost, uint32_t* windowId, void** hTex,

View File

@ -2067,6 +2067,10 @@ class nsIWidget : public nsISupports {
const nsTArray<mozilla::FontRange>& aFontRangeArray,
const bool aIsVertical, const LayoutDeviceIntPoint& aPoint) {}
virtual void RequestFxrOutput() {
MOZ_ASSERT(false, "This function should only execute in Windows");
}
#if defined(MOZ_WIDGET_ANDROID)
/**
* RecvToolbarAnimatorMessageFromCompositor receive message from compositor

View File

@ -13,6 +13,7 @@
#include "nsWindow.h"
#include "VsyncDispatcher.h"
#include "WinCompositorWindowThread.h"
#include "VRShMem.h"
#include <ddraw.h>
@ -337,5 +338,34 @@ void WinCompositorWidget::UpdateCompositorWndSizeIfNecessary() {
mLastCompositorWndSize = size;
}
// TODO: Bug 1570128 - Forward request to swapchain
// For now, this simply validates that data can be passed to Firefox Reality
// host from the GPU process
void WinCompositorWidget::RequestFxrOutput() {
mozilla::gfx::VRShMem shmem(nullptr, true /*aRequiresMutex*/);
if (shmem.JoinShMem()) {
mozilla::gfx::VRWindowState windowState = {0};
shmem.PullWindowState(windowState);
// The CLH should have populated hwndFx first
MOZ_ASSERT(windowState.hwndFx != 0);
MOZ_ASSERT(windowState.textureFx == nullptr);
windowState.textureFx = (HANDLE)0xFFFFFFFF;
shmem.PushWindowState(windowState);
shmem.LeaveShMem();
// Notify the waiting host process that the data is now available
HANDLE hSignal = ::OpenEventA(EVENT_ALL_ACCESS, // dwDesiredAccess
FALSE, // bInheritHandle
windowState.signalName // lpName
);
::SetEvent(hSignal);
::CloseHandle(hSignal);
}
}
} // namespace widget
} // namespace mozilla

View File

@ -104,6 +104,8 @@ class WinCompositorWidget : public CompositorWidget,
return mTransparentSurfaceLock;
}
void RequestFxrOutput();
protected:
private:
HDC GetWindowSurface();

View File

@ -657,6 +657,8 @@ nsWindow::nsWindow(bool aIsChildWindow)
mSizeConstraintsScale = GetDefaultScale().scale;
mRequestFxrOutputPending = false;
sInstanceCount++;
}

View File

@ -533,6 +533,9 @@ class nsWindow final : public nsWindowBase {
already_AddRefed<SourceSurface> GetFallbackScrollSnapshot(
const RECT& aRequiredClip);
void CreateCompositor() override;
void RequestFxrOutput();
protected:
nsCOMPtr<nsIWidget> mParent;
nsIntSize mLastSize;
@ -692,6 +695,10 @@ class nsWindow final : public nsWindowBase {
WinPointerEvents mPointerEvents;
ScreenPoint mLastPanGestureFocus;
// When true, used to indicate an async call to RequestFxrOutput to the GPU
// process after the Compositor is created
bool mRequestFxrOutputPending;
};
#endif // Window_h__

View File

@ -418,6 +418,28 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) {
return result;
}
// This override of CreateCompositor is to add support for sending the IPC
// call for RequesetFxrOutput as soon as the compositor for this widget is
// available.
void nsWindow::CreateCompositor() {
// there's no super??
nsWindowBase::CreateCompositor();
if (mRequestFxrOutputPending) {
GetRemoteRenderer()->SendRequestFxrOutput();
}
}
void nsWindow::RequestFxrOutput() {
if (GetRemoteRenderer() != nullptr) {
MOZ_CRASH("RequestFxrOutput should happen before Compositor is created.");
} else {
// The compositor isn't ready, so indicate to make the IPC call when
// it is available.
mRequestFxrOutputPending = true;
}
}
LayoutDeviceIntSize nsWindowGfx::GetIconMetrics(IconSizeType aSizeType) {
int32_t width = ::GetSystemMetrics(sIconMetrics[aSizeType].xMetric);
int32_t height = ::GetSystemMetrics(sIconMetrics[aSizeType].yMetric);