Bug 1323328 - Part 2: Implement VRServiceTest backend at VRManager; r?kip
MozReview-Commit-ID: EpW7BqeICLo
--- a/gfx/vr/ipc/PVRManager.ipdl
+++ b/gfx/vr/ipc/PVRManager.ipdl
@@ -57,29 +57,42 @@ parent:
sync GetImmediateSensorState(uint32_t aDisplayID) returns(VRHMDSensorState aState);
sync SetHaveEventListener(bool aHaveEventListener);
async ControllerListenerAdded();
async ControllerListenerRemoved();
// GetControllers synchronously returns the VR controllers that have already been
// enumerated by RefreshVRControllers() but does not enumerate new ones.
sync GetControllers() returns(VRControllerInfo[] aControllerInfo);
+ async CreateVRServiceTestDisplay(nsCString aID, uint32_t aPromiseID);
+ async CreateVRServiceTestController(nsCString aID, uint32_t aPromiseID);
+ async SetDisplayInfoToMockDisplay(uint32_t aDeviceID, VRDisplayInfo aDisplayInfo);
+ async SetSensorStateToMockDisplay(uint32_t aDeviceID, VRHMDSensorState aSensorState);
+ async NewButtonEventToMockController(uint32_t aDeviceID, long aButton,
+ bool aPressed);
+ async NewAxisMoveEventToMockController(uint32_t aDeviceID, long aAxis,
+ double aValue);
+ async NewPoseMoveToMockController(uint32_t aDeviceID, GamepadPoseState aPose);
child:
async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
// 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 GamepadUpdate(GamepadChangeEvent aGamepadEvent);
+ async ReplyCreateVRServiceTestDisplay(nsCString aID, uint32_t aPromiseID,
+ uint32_t aDeviceID);
+ async ReplyCreateVRServiceTestController(nsCString aID, uint32_t aPromiseID,
+ uint32_t aDeviceID);
async __delete__();
};
} // gfx
} // mozilla
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -13,16 +13,17 @@
#include "mozilla/layers/CompositorThread.h" // for CompositorThread
#include "mozilla/dom/Navigator.h"
#include "mozilla/dom/VREventObserver.h"
#include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback
#include "mozilla/dom/ContentChild.h"
#include "mozilla/layers/TextureClient.h"
#include "nsContentUtils.h"
#include "mozilla/dom/GamepadManager.h"
+#include "mozilla/dom/VRServiceTest.h"
using layers::TextureClient;
namespace {
const nsTArray<RefPtr<dom::VREventObserver>>::index_type kNoIndex =
nsTArray<RefPtr<dom::VREventObserver> >::NoIndex;
} // namespace
@@ -38,16 +39,17 @@ void ReleaseVRManagerParentSingleton() {
VRManagerChild::VRManagerChild()
: TextureForwarder()
, mDisplaysInitialized(false)
, mInputFrameID(-1)
, mMessageLoop(MessageLoop::current())
, mFrameRequestCallbackCounter(0)
, mBackend(layers::LayersBackend::LAYERS_NONE)
+ , mPromiseID(0)
{
MOZ_ASSERT(NS_IsMainThread());
mStartTimeStamp = TimeStamp::Now();
}
VRManagerChild::~VRManagerChild()
{
@@ -309,16 +311,32 @@ VRManagerChild::RefreshVRDisplaysWithCal
{
bool success = SendRefreshDisplays();
if (success) {
mNavigatorCallbacks.AppendElement(aWindowId);
}
return success;
}
+void
+VRManagerChild::CreateVRServiceTestDisplay(const nsCString& aID, dom::Promise* aPromise)
+{
+ SendCreateVRServiceTestDisplay(aID, mPromiseID);
+ mPromiseList.Put(mPromiseID, aPromise);
+ ++mPromiseID;
+}
+
+void
+VRManagerChild::CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise)
+{
+ SendCreateVRServiceTestController(aID, mPromiseID);
+ mPromiseList.Put(mPromiseID, aPromise);
+ ++mPromiseID;
+}
+
int
VRManagerChild::GetInputFrameID()
{
return mInputFrameID;
}
mozilla::ipc::IPCResult
VRManagerChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages)
@@ -486,16 +504,46 @@ VRManagerChild::RecvGamepadUpdate(const
RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
if (gamepadManager) {
gamepadManager->Update(aGamepadEvent);
}
return IPC_OK();
}
+mozilla::ipc::IPCResult
+VRManagerChild::RecvReplyCreateVRServiceTestDisplay(const nsCString& aID,
+ const uint32_t& aPromiseID,
+ const uint32_t& aDeviceID)
+{
+ RefPtr<dom::Promise> p;
+ if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
+ MOZ_CRASH("We should always have a promise.");
+ }
+
+ p->MaybeResolve(new VRMockDisplay(aID, aDeviceID));
+ mPromiseList.Remove(aPromiseID);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerChild::RecvReplyCreateVRServiceTestController(const nsCString& aID,
+ const uint32_t& aPromiseID,
+ const uint32_t& aDeviceID)
+{
+ RefPtr<dom::Promise> p;
+ if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
+ MOZ_CRASH("We should always have a promise.");
+ }
+
+ p->MaybeResolve(new VRMockController(aID, aDeviceID));
+ mPromiseList.Remove(aPromiseID);
+ return IPC_OK();
+}
+
void
VRManagerChild::RunFrameRequestCallbacks()
{
TimeStamp nowTime = TimeStamp::Now();
mozilla::TimeDuration duration = nowTime - mStartTimeStamp;
DOMHighResTimeStamp timeStamp = duration.ToMilliseconds();
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -44,16 +44,18 @@ public:
// Indicate that an observer wants to receive VR events.
void AddListener(dom::VREventObserver* aObserver);
// Indicate that an observer should no longer receive VR events.
void RemoveListener(dom::VREventObserver* aObserver);
int GetInputFrameID();
bool GetVRDisplays(nsTArray<RefPtr<VRDisplayClient> >& aDisplays);
bool RefreshVRDisplaysWithCallback(uint64_t aWindowId);
+ void CreateVRServiceTestDisplay(const nsCString& aID, dom::Promise* aPromise);
+ void CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise);
static void InitSameProcess();
static void InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint);
static bool InitForContent(Endpoint<PVRManagerChild>&& aEndpoint);
static bool ReinitForContent(Endpoint<PVRManagerChild>&& aEndpoint);
static void ShutDown();
static bool IsCreated();
@@ -112,16 +114,22 @@ protected:
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 RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) 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,
+ const uint32_t& aDeviceID) override;
// ShmemAllocator
virtual bool AllocShmem(size_t aSize,
ipc::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aShmem) override;
virtual bool AllocUnsafeShmem(size_t aSize,
@@ -172,16 +180,18 @@ private:
/**
* Hold TextureClients refs until end of their usages on host side.
* It defer calling of TextureClient recycle callback.
*/
nsDataHashtable<nsUint64HashKey, RefPtr<layers::TextureClient> > mTexturesWaitingRecycled;
layers::LayersBackend mBackend;
RefPtr<layers::SyncObject> mSyncObject;
+ uint32_t mPromiseID;
+ nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList;
DISALLOW_COPY_AND_ASSIGN(VRManagerChild);
};
} // namespace mozilla
} // namespace gfx
#endif // MOZILLA_GFX_VR_VRMANAGERCHILD_H
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -9,23 +9,26 @@
#include "ipc/VRLayerParent.h"
#include "mozilla/gfx/PVRManagerParent.h"
#include "mozilla/ipc/ProtocolTypes.h"
#include "mozilla/ipc/ProtocolUtils.h" // for IToplevelProtocol
#include "mozilla/TimeStamp.h" // for TimeStamp
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/Unused.h"
#include "VRManager.h"
+#include "gfxVRPuppet.h"
namespace mozilla {
using namespace layers;
namespace gfx {
VRManagerParent::VRManagerParent(ProcessId aChildProcessId, bool aIsContentChild)
: HostIPCAllocator()
+ , mDisplayTestID(0)
+ , mControllerTestID(0)
, mHaveEventListener(false)
, mHaveControllerListener(false)
, mIsContentChild(aIsContentChild)
{
MOZ_COUNT_CTOR(VRManagerParent);
MOZ_ASSERT(NS_IsMainThread());
SetOtherProcessId(aChildProcessId);
@@ -321,16 +324,139 @@ VRManagerParent::RecvControllerListenerR
mozilla::ipc::IPCResult
VRManagerParent::RecvGetControllers(nsTArray<VRControllerInfo> *aControllers)
{
VRManager* vm = VRManager::Get();
vm->GetVRControllerInfo(*aControllers);
return IPC_OK();
}
+mozilla::ipc::IPCResult
+VRManagerParent::RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint32_t& aPromiseID)
+{
+ nsTArray<VRDisplayInfo> displayInfoArray;
+ impl::VRDisplayPuppet* displayPuppet = nullptr;
+ VRManager* vm = VRManager::Get();
+ vm->RefreshVRDisplays();
+
+ // Get VRDisplayPuppet from VRManager
+ vm->GetVRDisplayInfo(displayInfoArray);
+ for (auto& displayInfo : displayInfoArray) {
+ if (displayInfo.GetType() == VRDeviceType::Puppet) {
+ displayPuppet = static_cast<impl::VRDisplayPuppet*>(
+ vm->GetDisplay(displayInfo.GetDisplayID()).get());
+ break;
+ }
+ }
+
+ MOZ_ASSERT(displayPuppet);
+ MOZ_ASSERT(!mDisplayTestID); // We have only one display in VRSystemManagerPuppet.
+
+ if (!mVRDisplayTests.Get(mDisplayTestID, nullptr)) {
+ mVRDisplayTests.Put(mDisplayTestID, displayPuppet);
+ }
+
+ if (SendReplyCreateVRServiceTestDisplay(aID, aPromiseID, mDisplayTestID)) {
+ return IPC_OK();
+ }
+
+ return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvCreateVRServiceTestController(const nsCString& aID, const uint32_t& aPromiseID)
+{
+ uint32_t controllerIdx = 0;
+ nsTArray<VRControllerInfo> controllerInfoArray;
+ impl::VRControllerPuppet* controllerPuppet = nullptr;
+ VRManager* vm = VRManager::Get();
+
+ // Get VRControllerPuppet from VRManager
+ vm->GetVRControllerInfo(controllerInfoArray);
+ for (auto& controllerInfo : controllerInfoArray) {
+ if (controllerInfo.GetType() == VRDeviceType::Puppet) {
+ if (controllerIdx == mControllerTestID) {
+ controllerPuppet = static_cast<impl::VRControllerPuppet*>(
+ vm->GetController(controllerInfo.GetControllerID()).get());
+ break;
+ }
+ ++controllerIdx;
+ }
+ }
+
+ MOZ_ASSERT(controllerPuppet);
+ MOZ_ASSERT(mControllerTestID < 2); // We have only two controllers in VRSystemManagerPuppet.
+
+ if (!mVRControllerTests.Get(mControllerTestID, nullptr)) {
+ mVRControllerTests.Put(mControllerTestID, controllerPuppet);
+ }
+
+ if (SendReplyCreateVRServiceTestController(aID, aPromiseID, mControllerTestID)) {
+ ++mControllerTestID;
+ return IPC_OK();
+ }
+
+ return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvSetDisplayInfoToMockDisplay(const uint32_t& aDeviceID,
+ const VRDisplayInfo& aDisplayInfo)
+{
+ RefPtr<impl::VRDisplayPuppet> displayPuppet;
+ MOZ_ASSERT(mVRDisplayTests.Get(mDisplayTestID,
+ getter_AddRefs(displayPuppet)));
+ displayPuppet->SetDisplayInfo(aDisplayInfo);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvSetSensorStateToMockDisplay(const uint32_t& aDeviceID,
+ const VRHMDSensorState& aSensorState)
+{
+ RefPtr<impl::VRDisplayPuppet> displayPuppet;
+ MOZ_ASSERT(mVRDisplayTests.Get(mControllerTestID,
+ getter_AddRefs(displayPuppet)));
+ displayPuppet->SetSensorState(aSensorState);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvNewButtonEventToMockController(const uint32_t& aDeviceID, const long& aButton,
+ const bool& aPressed)
+{
+ RefPtr<impl::VRControllerPuppet> controllerPuppet;
+ MOZ_ASSERT(mVRControllerTests.Get(mControllerTestID,
+ getter_AddRefs(controllerPuppet)));
+ controllerPuppet->SetButtonPressState(aButton, aPressed);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvNewAxisMoveEventToMockController(const uint32_t& aDeviceID, const long& aAxis,
+ const double& aValue)
+{
+ RefPtr<impl::VRControllerPuppet> controllerPuppet;
+ MOZ_ASSERT(mVRControllerTests.Get(mControllerTestID,
+ getter_AddRefs(controllerPuppet)));
+ controllerPuppet->SetAxisMoveState(aAxis, aValue);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvNewPoseMoveToMockController(const uint32_t& aDeviceID,
+ const GamepadPoseState& pose)
+{
+ RefPtr<impl::VRControllerPuppet> controllerPuppet;
+ MOZ_ASSERT(mVRControllerTests.Get(mControllerTestID,
+ getter_AddRefs(controllerPuppet)));
+ controllerPuppet->SetPoseMoveState(pose);
+ return IPC_OK();
+}
+
bool
VRManagerParent::SendGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
{
// GamepadManager only exists at the content process
// or the same process in non-e10s mode.
if (mIsContentChild || IsSameProcess()) {
return PVRManagerParent::SendGamepadUpdate(aGamepadEvent);
} else {
--- a/gfx/vr/ipc/VRManagerParent.h
+++ b/gfx/vr/ipc/VRManagerParent.h
@@ -17,16 +17,21 @@
#include "gfxVR.h" // for VRFieldOfView
namespace mozilla {
using namespace layers;
namespace gfx {
class VRManager;
+namespace impl {
+class VRDisplayPuppet;
+class VRControllerPuppet;
+} // namespace impl
+
class VRManagerParent final : public PVRManagerParent
, public HostIPCAllocator
, public ShmemAllocator
{
public:
explicit VRManagerParent(ProcessId aChildProcessId, bool aIsContentChild);
static VRManagerParent* CreateSameProcess();
@@ -84,16 +89,27 @@ protected:
virtual mozilla::ipc::IPCResult RecvGetDisplays(nsTArray<VRDisplayInfo> *aDisplays) override;
virtual mozilla::ipc::IPCResult RecvResetSensor(const uint32_t& aDisplayID) override;
virtual mozilla::ipc::IPCResult RecvGetSensorState(const uint32_t& aDisplayID, VRHMDSensorState* aState) override;
virtual mozilla::ipc::IPCResult RecvGetImmediateSensorState(const uint32_t& aDisplayID, VRHMDSensorState* aState) override;
virtual mozilla::ipc::IPCResult RecvSetHaveEventListener(const bool& aHaveEventListener) override;
virtual mozilla::ipc::IPCResult RecvControllerListenerAdded() override;
virtual mozilla::ipc::IPCResult RecvControllerListenerRemoved() override;
virtual mozilla::ipc::IPCResult RecvGetControllers(nsTArray<VRControllerInfo> *aControllers) override;
+ virtual mozilla::ipc::IPCResult RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint32_t& aPromiseID) override;
+ virtual mozilla::ipc::IPCResult RecvCreateVRServiceTestController(const nsCString& aID, const uint32_t& aPromiseID) override;
+ virtual mozilla::ipc::IPCResult RecvSetDisplayInfoToMockDisplay(const uint32_t& aDeviceID,
+ const VRDisplayInfo& aDisplayInfo) override;
+ virtual mozilla::ipc::IPCResult RecvSetSensorStateToMockDisplay(const uint32_t& aDeviceID,
+ const VRHMDSensorState& aSensorState) override;
+ virtual mozilla::ipc::IPCResult RecvNewButtonEventToMockController(const uint32_t& aDeviceID, const long& aButton,
+ const bool& aPressed) override;
+ virtual mozilla::ipc::IPCResult RecvNewAxisMoveEventToMockController(const uint32_t& aDeviceID, const long& aAxis,
+ const double& aValue) override;
+ virtual mozilla::ipc::IPCResult RecvNewPoseMoveToMockController(const uint32_t& aDeviceID, const GamepadPoseState& pose) override;
private:
void RegisterWithManager();
void UnregisterFromManager();
void Bind(Endpoint<PVRManagerParent>&& aEndpoint);
static void RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager);
@@ -104,16 +120,20 @@ private:
// deferred destruction of ourselves.
RefPtr<VRManagerParent> mSelfRef;
// Keep the compositor thread alive, until we have destroyed ourselves.
RefPtr<layers::CompositorThreadHolder> mCompositorThreadHolder;
// Keep the VRManager alive, until we have destroyed ourselves.
RefPtr<VRManager> mVRManagerHolder;
+ nsRefPtrHashtable<nsUint32HashKey, impl::VRDisplayPuppet> mVRDisplayTests;
+ nsRefPtrHashtable<nsUint32HashKey, impl::VRControllerPuppet> mVRControllerTests;
+ uint32_t mDisplayTestID;
+ uint32_t mControllerTestID;
bool mHaveEventListener;
bool mHaveControllerListener;
bool mIsContentChild;
};
} // namespace mozilla
} // namespace gfx