2015-09-17 21:23:13 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
* vim: sw=2 ts=8 et :
|
|
|
|
*/
|
|
|
|
/* 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 "VRManagerChild.h"
|
|
|
|
#include "VRManagerParent.h"
|
2016-02-24 23:54:50 +00:00
|
|
|
#include "VRDisplayClient.h"
|
2016-10-04 08:30:04 +00:00
|
|
|
#include "nsGlobalWindow.h"
|
2015-09-17 21:23:13 +00:00
|
|
|
#include "mozilla/StaticPtr.h"
|
2016-05-16 06:39:30 +00:00
|
|
|
#include "mozilla/layers/CompositorThread.h" // for CompositorThread
|
2015-09-17 21:23:13 +00:00
|
|
|
#include "mozilla/dom/Navigator.h"
|
2016-07-04 22:46:49 +00:00
|
|
|
#include "mozilla/dom/VREventObserver.h"
|
2016-02-24 23:54:50 +00:00
|
|
|
#include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback
|
2016-10-04 08:31:27 +00:00
|
|
|
#include "mozilla/dom/ContentChild.h"
|
2016-02-24 23:54:50 +00:00
|
|
|
#include "mozilla/layers/TextureClient.h"
|
2016-07-04 22:46:49 +00:00
|
|
|
#include "nsContentUtils.h"
|
2016-11-04 07:53:01 +00:00
|
|
|
#include "mozilla/dom/GamepadManager.h"
|
2017-03-01 15:58:31 +00:00
|
|
|
#include "mozilla/dom/VRServiceTest.h"
|
2016-11-04 07:53:01 +00:00
|
|
|
|
2016-02-24 23:54:50 +00:00
|
|
|
using layers::TextureClient;
|
2015-09-17 21:23:13 +00:00
|
|
|
|
2016-07-04 22:46:49 +00:00
|
|
|
namespace {
|
|
|
|
const nsTArray<RefPtr<dom::VREventObserver>>::index_type kNoIndex =
|
|
|
|
nsTArray<RefPtr<dom::VREventObserver> >::NoIndex;
|
|
|
|
} // namespace
|
|
|
|
|
2015-09-17 21:23:13 +00:00
|
|
|
namespace mozilla {
|
|
|
|
namespace gfx {
|
|
|
|
|
|
|
|
static StaticRefPtr<VRManagerChild> sVRManagerChildSingleton;
|
|
|
|
static StaticRefPtr<VRManagerParent> sVRManagerParentSingleton;
|
|
|
|
|
|
|
|
void ReleaseVRManagerParentSingleton() {
|
|
|
|
sVRManagerParentSingleton = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
VRManagerChild::VRManagerChild()
|
2016-02-24 23:54:50 +00:00
|
|
|
: TextureForwarder()
|
2016-07-04 22:52:21 +00:00
|
|
|
, mDisplaysInitialized(false)
|
2016-02-24 23:54:50 +00:00
|
|
|
, mInputFrameID(-1)
|
|
|
|
, mMessageLoop(MessageLoop::current())
|
|
|
|
, mFrameRequestCallbackCounter(0)
|
|
|
|
, mBackend(layers::LayersBackend::LAYERS_NONE)
|
2017-03-01 15:58:31 +00:00
|
|
|
, mPromiseID(0)
|
2017-03-15 05:50:34 +00:00
|
|
|
, mVRMockDisplay(nullptr)
|
2015-09-17 21:23:13 +00:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2016-02-24 23:54:50 +00:00
|
|
|
|
|
|
|
mStartTimeStamp = TimeStamp::Now();
|
2015-09-17 21:23:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VRManagerChild::~VRManagerChild()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
}
|
|
|
|
|
2016-02-24 23:54:50 +00:00
|
|
|
/*static*/ void
|
|
|
|
VRManagerChild::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
|
|
|
|
{
|
|
|
|
if (sVRManagerChildSingleton) {
|
|
|
|
sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend;
|
|
|
|
sVRManagerChildSingleton->mSyncObject = SyncObject::CreateSyncObject(aIdentifier.mSyncHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
layers::LayersBackend
|
|
|
|
VRManagerChild::GetBackendType() const
|
|
|
|
{
|
|
|
|
return mBackend;
|
|
|
|
}
|
|
|
|
|
2015-09-17 21:23:13 +00:00
|
|
|
/*static*/ VRManagerChild*
|
|
|
|
VRManagerChild::Get()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(sVRManagerChildSingleton);
|
|
|
|
return sVRManagerChildSingleton;
|
|
|
|
}
|
|
|
|
|
2016-07-21 07:14:59 +00:00
|
|
|
/* static */ bool
|
|
|
|
VRManagerChild::IsCreated()
|
|
|
|
{
|
|
|
|
return !!sVRManagerChildSingleton;
|
|
|
|
}
|
|
|
|
|
2016-07-21 07:14:59 +00:00
|
|
|
/* static */ bool
|
|
|
|
VRManagerChild::InitForContent(Endpoint<PVRManagerChild>&& aEndpoint)
|
2015-09-17 21:23:13 +00:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(!sVRManagerChildSingleton);
|
|
|
|
|
|
|
|
RefPtr<VRManagerChild> child(new VRManagerChild());
|
2016-09-02 20:13:50 +00:00
|
|
|
if (!aEndpoint.Bind(child)) {
|
2015-09-17 21:23:13 +00:00
|
|
|
NS_RUNTIMEABORT("Couldn't Open() Compositor channel.");
|
2016-07-21 07:14:59 +00:00
|
|
|
return false;
|
2015-09-17 21:23:13 +00:00
|
|
|
}
|
|
|
|
sVRManagerChildSingleton = child;
|
2016-07-21 07:14:59 +00:00
|
|
|
return true;
|
2015-09-17 21:23:13 +00:00
|
|
|
}
|
|
|
|
|
2016-09-20 08:18:50 +00:00
|
|
|
/* static */ bool
|
|
|
|
VRManagerChild::ReinitForContent(Endpoint<PVRManagerChild>&& aEndpoint)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
ShutDown();
|
|
|
|
|
|
|
|
return InitForContent(Move(aEndpoint));
|
|
|
|
}
|
|
|
|
|
2015-09-17 21:23:13 +00:00
|
|
|
/*static*/ void
|
2016-07-21 07:14:59 +00:00
|
|
|
VRManagerChild::InitSameProcess()
|
2015-09-17 21:23:13 +00:00
|
|
|
{
|
2016-07-21 07:14:59 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(!sVRManagerChildSingleton);
|
2016-07-21 07:14:59 +00:00
|
|
|
|
|
|
|
sVRManagerChildSingleton = new VRManagerChild();
|
|
|
|
sVRManagerParentSingleton = VRManagerParent::CreateSameProcess();
|
|
|
|
sVRManagerChildSingleton->Open(sVRManagerParentSingleton->GetIPCChannel(),
|
|
|
|
mozilla::layers::CompositorThreadHolder::Loop(),
|
|
|
|
mozilla::ipc::ChildSide);
|
2015-09-17 21:23:13 +00:00
|
|
|
}
|
|
|
|
|
2016-07-21 07:14:59 +00:00
|
|
|
/* static */ void
|
|
|
|
VRManagerChild::InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(!sVRManagerChildSingleton);
|
|
|
|
|
|
|
|
sVRManagerChildSingleton = new VRManagerChild();
|
2016-09-02 20:13:50 +00:00
|
|
|
if (!aEndpoint.Bind(sVRManagerChildSingleton)) {
|
2016-07-21 07:14:59 +00:00
|
|
|
NS_RUNTIMEABORT("Couldn't Open() Compositor channel.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-17 21:23:13 +00:00
|
|
|
/*static*/ void
|
|
|
|
VRManagerChild::ShutDown()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
if (sVRManagerChildSingleton) {
|
|
|
|
sVRManagerChildSingleton->Destroy();
|
|
|
|
sVRManagerChildSingleton = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*static*/ void
|
|
|
|
VRManagerChild::DeferredDestroy(RefPtr<VRManagerChild> aVRManagerChild)
|
|
|
|
{
|
2016-02-24 23:54:50 +00:00
|
|
|
aVRManagerChild->Close();
|
2015-09-17 21:23:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
VRManagerChild::Destroy()
|
|
|
|
{
|
2016-02-24 23:54:50 +00:00
|
|
|
mTexturesWaitingRecycled.Clear();
|
2015-09-17 21:23:13 +00:00
|
|
|
|
|
|
|
// Keep ourselves alive until everything has been shut down
|
|
|
|
RefPtr<VRManagerChild> selfRef = this;
|
|
|
|
|
|
|
|
// The DeferredDestroyVRManager task takes ownership of
|
|
|
|
// the VRManagerChild and will release it when it runs.
|
2016-04-28 00:06:05 +00:00
|
|
|
MessageLoop::current()->PostTask(
|
2015-09-17 21:23:13 +00:00
|
|
|
NewRunnableFunction(DeferredDestroy, selfRef));
|
|
|
|
}
|
|
|
|
|
2016-02-24 23:54:50 +00:00
|
|
|
layers::PTextureChild*
|
|
|
|
VRManagerChild::AllocPTextureChild(const SurfaceDescriptor&,
|
|
|
|
const LayersBackend&,
|
|
|
|
const TextureFlags&,
|
|
|
|
const uint64_t&)
|
|
|
|
{
|
|
|
|
return TextureClient::CreateIPDLActor();
|
|
|
|
}
|
|
|
|
|
2015-09-17 21:23:13 +00:00
|
|
|
bool
|
2016-02-24 23:54:50 +00:00
|
|
|
VRManagerChild::DeallocPTextureChild(PTextureChild* actor)
|
2015-09-17 21:23:13 +00:00
|
|
|
{
|
2016-02-24 23:54:50 +00:00
|
|
|
return TextureClient::DestroyIPDLActor(actor);
|
|
|
|
}
|
|
|
|
|
|
|
|
PVRLayerChild*
|
|
|
|
VRManagerChild::AllocPVRLayerChild(const uint32_t& aDisplayID,
|
|
|
|
const float& aLeftEyeX,
|
|
|
|
const float& aLeftEyeY,
|
|
|
|
const float& aLeftEyeWidth,
|
|
|
|
const float& aLeftEyeHeight,
|
|
|
|
const float& aRightEyeX,
|
|
|
|
const float& aRightEyeY,
|
|
|
|
const float& aRightEyeWidth,
|
|
|
|
const float& aRightEyeHeight)
|
|
|
|
{
|
|
|
|
RefPtr<VRLayerChild> layer = new VRLayerChild(aDisplayID, this);
|
|
|
|
return layer.forget().take();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
VRManagerChild::DeallocPVRLayerChild(PVRLayerChild* actor)
|
|
|
|
{
|
|
|
|
delete actor;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-07-04 22:52:21 +00:00
|
|
|
void
|
|
|
|
VRManagerChild::UpdateDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayUpdates)
|
2016-02-24 23:54:50 +00:00
|
|
|
{
|
2017-02-14 19:21:09 +00:00
|
|
|
nsTArray<uint32_t> disconnectedDisplays;
|
|
|
|
nsTArray<uint32_t> connectedDisplays;
|
2016-02-24 23:54:50 +00:00
|
|
|
|
|
|
|
// Check if any displays have been disconnected
|
|
|
|
for (auto& display : mDisplays) {
|
|
|
|
bool found = false;
|
|
|
|
for (auto& displayUpdate : aDisplayUpdates) {
|
|
|
|
if (display->GetDisplayInfo().GetDisplayID() == displayUpdate.GetDisplayID()) {
|
|
|
|
found = true;
|
2015-09-17 21:23:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-02-24 23:54:50 +00:00
|
|
|
if (!found) {
|
|
|
|
display->NotifyDisconnected();
|
2017-02-14 19:21:09 +00:00
|
|
|
disconnectedDisplays.AppendElement(display->GetDisplayInfo().GetDisplayID());
|
2015-09-17 21:23:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-24 23:54:50 +00:00
|
|
|
// mDisplays could be a hashed container for more scalability, but not worth
|
|
|
|
// it now as we expect < 10 entries.
|
|
|
|
nsTArray<RefPtr<VRDisplayClient>> displays;
|
2016-07-04 22:52:21 +00:00
|
|
|
for (VRDisplayInfo& displayUpdate : aDisplayUpdates) {
|
2016-02-24 23:54:50 +00:00
|
|
|
bool isNewDisplay = true;
|
2016-07-04 22:52:21 +00:00
|
|
|
for (auto& display : mDisplays) {
|
2016-02-24 23:54:50 +00:00
|
|
|
const VRDisplayInfo& prevInfo = display->GetDisplayInfo();
|
|
|
|
if (prevInfo.GetDisplayID() == displayUpdate.GetDisplayID()) {
|
|
|
|
if (displayUpdate.GetIsConnected() && !prevInfo.GetIsConnected()) {
|
2017-02-14 19:21:09 +00:00
|
|
|
connectedDisplays.AppendElement(displayUpdate.GetDisplayID());
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
if (!displayUpdate.GetIsConnected() && prevInfo.GetIsConnected()) {
|
2017-02-14 19:21:09 +00:00
|
|
|
disconnectedDisplays.AppendElement(displayUpdate.GetDisplayID());
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
display->UpdateDisplayInfo(displayUpdate);
|
|
|
|
displays.AppendElement(display);
|
|
|
|
isNewDisplay = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isNewDisplay) {
|
|
|
|
displays.AppendElement(new VRDisplayClient(displayUpdate));
|
2017-02-14 19:21:09 +00:00
|
|
|
connectedDisplays.AppendElement(displayUpdate.GetDisplayID());
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
}
|
2015-09-17 21:23:13 +00:00
|
|
|
|
2016-02-24 23:54:50 +00:00
|
|
|
mDisplays = displays;
|
2015-09-17 21:23:13 +00:00
|
|
|
|
2017-02-14 19:21:09 +00:00
|
|
|
// We wish to fire the events only after mDisplays is updated
|
|
|
|
for (uint32_t displayID : disconnectedDisplays) {
|
|
|
|
FireDOMVRDisplayDisconnectEvent(displayID);
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
2017-02-14 19:21:09 +00:00
|
|
|
|
|
|
|
for (uint32_t displayID : connectedDisplays) {
|
|
|
|
FireDOMVRDisplayConnectEvent(displayID);
|
2015-09-17 21:23:13 +00:00
|
|
|
}
|
|
|
|
|
2016-07-04 22:52:21 +00:00
|
|
|
mDisplaysInitialized = true;
|
|
|
|
}
|
|
|
|
|
2016-11-15 03:26:00 +00:00
|
|
|
mozilla::ipc::IPCResult
|
2016-07-04 22:52:21 +00:00
|
|
|
VRManagerChild::RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates)
|
|
|
|
{
|
|
|
|
UpdateDisplayInfo(aDisplayUpdates);
|
2016-11-24 19:50:43 +00:00
|
|
|
for (auto& windowId : mNavigatorCallbacks) {
|
2016-07-04 22:52:21 +00:00
|
|
|
/** We must call NotifyVRDisplaysUpdated for every
|
2016-11-24 19:50:43 +00:00
|
|
|
* window's Navigator in mNavigatorCallbacks to ensure that
|
2016-07-04 22:52:21 +00:00
|
|
|
* the promise returned by Navigator.GetVRDevices
|
|
|
|
* can resolve. This must happen even if no changes
|
|
|
|
* to VRDisplays have been detected here.
|
|
|
|
*/
|
2016-11-24 19:50:43 +00:00
|
|
|
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(windowId);
|
|
|
|
if (!window) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ErrorResult result;
|
|
|
|
dom::Navigator* nav = window->GetNavigator(result);
|
|
|
|
if (NS_WARN_IF(result.Failed())) {
|
|
|
|
continue;
|
|
|
|
}
|
2016-07-04 22:52:21 +00:00
|
|
|
nav->NotifyVRDisplaysUpdated();
|
|
|
|
}
|
|
|
|
mNavigatorCallbacks.Clear();
|
2016-11-15 03:26:00 +00:00
|
|
|
return IPC_OK();
|
2015-09-17 21:23:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2016-02-24 23:54:50 +00:00
|
|
|
VRManagerChild::GetVRDisplays(nsTArray<RefPtr<VRDisplayClient>>& aDisplays)
|
2015-09-17 21:23:13 +00:00
|
|
|
{
|
2016-02-24 23:54:50 +00:00
|
|
|
aDisplays = mDisplays;
|
2015-09-17 21:23:13 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2016-11-24 19:50:43 +00:00
|
|
|
VRManagerChild::RefreshVRDisplaysWithCallback(uint64_t aWindowId)
|
2015-09-17 21:23:13 +00:00
|
|
|
{
|
2016-02-24 23:54:50 +00:00
|
|
|
bool success = SendRefreshDisplays();
|
2015-09-17 21:23:13 +00:00
|
|
|
if (success) {
|
2016-11-24 19:50:43 +00:00
|
|
|
mNavigatorCallbacks.AppendElement(aWindowId);
|
2015-09-17 21:23:13 +00:00
|
|
|
}
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2017-03-01 15:58:31 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-01-09 02:50:10 +00:00
|
|
|
int
|
|
|
|
VRManagerChild::GetInputFrameID()
|
|
|
|
{
|
|
|
|
return mInputFrameID;
|
|
|
|
}
|
|
|
|
|
2016-11-15 03:26:00 +00:00
|
|
|
mozilla::ipc::IPCResult
|
2016-02-24 23:54:50 +00:00
|
|
|
VRManagerChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages)
|
|
|
|
{
|
|
|
|
for (InfallibleTArray<AsyncParentMessageData>::index_type i = 0; i < aMessages.Length(); ++i) {
|
|
|
|
const AsyncParentMessageData& message = aMessages[i];
|
|
|
|
|
|
|
|
switch (message.type()) {
|
|
|
|
case AsyncParentMessageData::TOpNotifyNotUsed: {
|
|
|
|
const OpNotifyNotUsed& op = message.get_OpNotifyNotUsed();
|
|
|
|
NotifyNotUsed(op.TextureId(), op.fwdTransactionId());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
NS_ERROR("unknown AsyncParentMessageData type");
|
2016-11-15 03:26:00 +00:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
}
|
2016-11-15 03:26:00 +00:00
|
|
|
return IPC_OK();
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PTextureChild*
|
|
|
|
VRManagerChild::CreateTexture(const SurfaceDescriptor& aSharedData,
|
|
|
|
LayersBackend aLayersBackend,
|
|
|
|
TextureFlags aFlags,
|
|
|
|
uint64_t aSerial)
|
|
|
|
{
|
|
|
|
return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
VRManagerChild::CancelWaitForRecycle(uint64_t aTextureId)
|
|
|
|
{
|
|
|
|
RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
|
|
|
|
if (!client) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mTexturesWaitingRecycled.Remove(aTextureId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
VRManagerChild::NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId)
|
|
|
|
{
|
|
|
|
RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
|
|
|
|
if (!client) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mTexturesWaitingRecycled.Remove(aTextureId);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
VRManagerChild::AllocShmem(size_t aSize,
|
|
|
|
ipc::SharedMemory::SharedMemoryType aType,
|
|
|
|
ipc::Shmem* aShmem)
|
|
|
|
{
|
|
|
|
return PVRManagerChild::AllocShmem(aSize, aType, aShmem);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
VRManagerChild::AllocUnsafeShmem(size_t aSize,
|
|
|
|
ipc::SharedMemory::SharedMemoryType aType,
|
|
|
|
ipc::Shmem* aShmem)
|
|
|
|
{
|
|
|
|
return PVRManagerChild::AllocUnsafeShmem(aSize, aType, aShmem);
|
|
|
|
}
|
|
|
|
|
2016-11-04 00:28:28 +00:00
|
|
|
bool
|
2016-02-24 23:54:50 +00:00
|
|
|
VRManagerChild::DeallocShmem(ipc::Shmem& aShmem)
|
|
|
|
{
|
2016-11-04 00:28:28 +00:00
|
|
|
return PVRManagerChild::DeallocShmem(aShmem);
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PVRLayerChild*
|
2017-03-23 06:19:11 +00:00
|
|
|
VRManagerChild::CreateVRLayer(uint32_t aDisplayID,
|
|
|
|
const Rect& aLeftEyeRect,
|
|
|
|
const Rect& aRightEyeRect,
|
|
|
|
nsIEventTarget* aTarget)
|
|
|
|
{
|
|
|
|
PVRLayerChild* vrLayerChild = AllocPVRLayerChild(aDisplayID, aLeftEyeRect.x,
|
|
|
|
aLeftEyeRect.y, aLeftEyeRect.width,
|
|
|
|
aLeftEyeRect.height, aRightEyeRect.x,
|
|
|
|
aRightEyeRect.y, aRightEyeRect.width,
|
|
|
|
aRightEyeRect.height);
|
|
|
|
// Do the DOM labeling.
|
|
|
|
if (aTarget) {
|
|
|
|
SetEventTargetForActor(vrLayerChild, aTarget);
|
|
|
|
MOZ_ASSERT(vrLayerChild->GetActorEventTarget());
|
|
|
|
}
|
|
|
|
return SendPVRLayerConstructor(vrLayerChild, aDisplayID, aLeftEyeRect.x,
|
|
|
|
aLeftEyeRect.y, aLeftEyeRect.width,
|
|
|
|
aLeftEyeRect.height, aRightEyeRect.x,
|
|
|
|
aRightEyeRect.y, aRightEyeRect.width,
|
|
|
|
aRightEyeRect.height);
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// XXX TODO - VRManagerChild::FrameRequest is the same as nsIDocument::FrameRequest, should we consolodate these?
|
|
|
|
struct VRManagerChild::FrameRequest
|
|
|
|
{
|
|
|
|
FrameRequest(mozilla::dom::FrameRequestCallback& aCallback,
|
|
|
|
int32_t aHandle) :
|
|
|
|
mCallback(&aCallback),
|
|
|
|
mHandle(aHandle)
|
|
|
|
{}
|
|
|
|
|
|
|
|
// Conversion operator so that we can append these to a
|
|
|
|
// FrameRequestCallbackList
|
|
|
|
operator const RefPtr<mozilla::dom::FrameRequestCallback>& () const {
|
|
|
|
return mCallback;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Comparator operators to allow RemoveElementSorted with an
|
|
|
|
// integer argument on arrays of FrameRequest
|
|
|
|
bool operator==(int32_t aHandle) const {
|
|
|
|
return mHandle == aHandle;
|
|
|
|
}
|
|
|
|
bool operator<(int32_t aHandle) const {
|
|
|
|
return mHandle < aHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<mozilla::dom::FrameRequestCallback> mCallback;
|
|
|
|
int32_t mHandle;
|
|
|
|
};
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
VRManagerChild::ScheduleFrameRequestCallback(mozilla::dom::FrameRequestCallback& aCallback,
|
|
|
|
int32_t *aHandle)
|
|
|
|
{
|
|
|
|
if (mFrameRequestCallbackCounter == INT32_MAX) {
|
|
|
|
// Can't increment without overflowing; bail out
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
int32_t newHandle = ++mFrameRequestCallbackCounter;
|
|
|
|
|
|
|
|
DebugOnly<FrameRequest*> request =
|
|
|
|
mFrameRequestCallbacks.AppendElement(FrameRequest(aCallback, newHandle));
|
|
|
|
NS_ASSERTION(request, "This is supposed to be infallible!");
|
|
|
|
|
|
|
|
*aHandle = newHandle;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
VRManagerChild::CancelFrameRequestCallback(int32_t aHandle)
|
|
|
|
{
|
|
|
|
// mFrameRequestCallbacks is stored sorted by handle
|
|
|
|
mFrameRequestCallbacks.RemoveElementSorted(aHandle);
|
|
|
|
}
|
|
|
|
|
2016-11-15 03:26:00 +00:00
|
|
|
mozilla::ipc::IPCResult
|
2016-02-24 23:54:50 +00:00
|
|
|
VRManagerChild::RecvNotifyVSync()
|
|
|
|
{
|
|
|
|
for (auto& display : mDisplays) {
|
|
|
|
display->NotifyVsync();
|
|
|
|
}
|
|
|
|
|
2016-11-15 03:26:00 +00:00
|
|
|
return IPC_OK();
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
|
2016-11-15 03:26:00 +00:00
|
|
|
mozilla::ipc::IPCResult
|
2016-02-24 23:54:50 +00:00
|
|
|
VRManagerChild::RecvNotifyVRVSync(const uint32_t& aDisplayID)
|
|
|
|
{
|
|
|
|
for (auto& display : mDisplays) {
|
|
|
|
if (display->GetDisplayInfo().GetDisplayID() == aDisplayID) {
|
|
|
|
display->NotifyVRVsync();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-15 03:26:00 +00:00
|
|
|
return IPC_OK();
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
|
2016-11-15 03:26:00 +00:00
|
|
|
mozilla::ipc::IPCResult
|
2016-10-04 08:30:04 +00:00
|
|
|
VRManagerChild::RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
|
|
|
|
{
|
2016-10-11 02:45:25 +00:00
|
|
|
// VRManagerChild could be at other processes, but GamepadManager
|
2016-12-01 05:12:10 +00:00
|
|
|
// only exists at the content process or the same process
|
2016-10-11 02:45:25 +00:00
|
|
|
// in non-e10s mode.
|
2016-12-01 05:12:10 +00:00
|
|
|
MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess());
|
|
|
|
|
|
|
|
RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
|
|
|
|
if (gamepadManager) {
|
|
|
|
gamepadManager->Update(aGamepadEvent);
|
2016-10-04 08:30:04 +00:00
|
|
|
}
|
|
|
|
|
2016-11-15 03:26:00 +00:00
|
|
|
return IPC_OK();
|
2016-10-04 08:30:04 +00:00
|
|
|
}
|
|
|
|
|
2017-03-01 15:58:31 +00:00
|
|
|
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.");
|
|
|
|
}
|
|
|
|
|
2017-03-15 05:50:34 +00:00
|
|
|
// We only allow one VRMockDisplay in VR tests.
|
|
|
|
if (!mVRMockDisplay) {
|
|
|
|
mVRMockDisplay = new VRMockDisplay(aID, aDeviceID);
|
|
|
|
}
|
|
|
|
p->MaybeResolve(mVRMockDisplay);
|
2017-03-01 15:58:31 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2016-02-24 23:54:50 +00:00
|
|
|
void
|
|
|
|
VRManagerChild::RunFrameRequestCallbacks()
|
|
|
|
{
|
|
|
|
TimeStamp nowTime = TimeStamp::Now();
|
|
|
|
mozilla::TimeDuration duration = nowTime - mStartTimeStamp;
|
|
|
|
DOMHighResTimeStamp timeStamp = duration.ToMilliseconds();
|
|
|
|
|
|
|
|
|
|
|
|
nsTArray<FrameRequest> callbacks;
|
|
|
|
callbacks.AppendElements(mFrameRequestCallbacks);
|
|
|
|
mFrameRequestCallbacks.Clear();
|
|
|
|
for (auto& callback : callbacks) {
|
|
|
|
callback.mCallback->Call(timeStamp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-18 22:18:10 +00:00
|
|
|
void
|
|
|
|
VRManagerChild::FireDOMVRDisplayMountedEvent(uint32_t aDisplayID)
|
|
|
|
{
|
|
|
|
nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(this,
|
|
|
|
&VRManagerChild::FireDOMVRDisplayMountedEventInternal,
|
|
|
|
aDisplayID));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
VRManagerChild::FireDOMVRDisplayUnmountedEvent(uint32_t aDisplayID)
|
|
|
|
{
|
|
|
|
nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(this,
|
|
|
|
&VRManagerChild::FireDOMVRDisplayUnmountedEventInternal,
|
|
|
|
aDisplayID));
|
|
|
|
}
|
|
|
|
|
2016-02-24 23:54:50 +00:00
|
|
|
void
|
2017-02-14 19:21:09 +00:00
|
|
|
VRManagerChild::FireDOMVRDisplayConnectEvent(uint32_t aDisplayID)
|
2016-02-24 23:54:50 +00:00
|
|
|
{
|
2017-02-14 19:21:09 +00:00
|
|
|
nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(this,
|
|
|
|
&VRManagerChild::FireDOMVRDisplayConnectEventInternal,
|
|
|
|
aDisplayID));
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-02-14 19:21:09 +00:00
|
|
|
VRManagerChild::FireDOMVRDisplayDisconnectEvent(uint32_t aDisplayID)
|
2016-02-24 23:54:50 +00:00
|
|
|
{
|
2017-02-14 19:21:09 +00:00
|
|
|
nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(this,
|
|
|
|
&VRManagerChild::FireDOMVRDisplayDisconnectEventInternal,
|
|
|
|
aDisplayID));
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-02-14 19:21:09 +00:00
|
|
|
VRManagerChild::FireDOMVRDisplayPresentChangeEvent(uint32_t aDisplayID)
|
2016-02-24 23:54:50 +00:00
|
|
|
{
|
2017-02-14 19:21:09 +00:00
|
|
|
nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(this,
|
|
|
|
&VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal,
|
|
|
|
aDisplayID));
|
2016-07-04 22:46:49 +00:00
|
|
|
}
|
|
|
|
|
2016-10-18 22:18:10 +00:00
|
|
|
void
|
|
|
|
VRManagerChild::FireDOMVRDisplayMountedEventInternal(uint32_t aDisplayID)
|
|
|
|
{
|
2017-02-14 19:21:09 +00:00
|
|
|
// Iterate over a copy of mListeners, as dispatched events may modify it.
|
|
|
|
nsTArray<RefPtr<dom::VREventObserver>> listeners;
|
|
|
|
listeners = mListeners;
|
|
|
|
for (auto& listener : listeners) {
|
2016-10-18 22:18:10 +00:00
|
|
|
listener->NotifyVRDisplayMounted(aDisplayID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
VRManagerChild::FireDOMVRDisplayUnmountedEventInternal(uint32_t aDisplayID)
|
|
|
|
{
|
2017-02-14 19:21:09 +00:00
|
|
|
// Iterate over a copy of mListeners, as dispatched events may modify it.
|
|
|
|
nsTArray<RefPtr<dom::VREventObserver>> listeners;
|
|
|
|
listeners = mListeners;
|
|
|
|
for (auto& listener : listeners) {
|
2016-10-18 22:18:10 +00:00
|
|
|
listener->NotifyVRDisplayUnmounted(aDisplayID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-04 22:46:49 +00:00
|
|
|
void
|
2017-02-14 19:21:09 +00:00
|
|
|
VRManagerChild::FireDOMVRDisplayConnectEventInternal(uint32_t aDisplayID)
|
2016-07-04 22:46:49 +00:00
|
|
|
{
|
2017-02-14 19:21:09 +00:00
|
|
|
// Iterate over a copy of mListeners, as dispatched events may modify it.
|
|
|
|
nsTArray<RefPtr<dom::VREventObserver>> listeners;
|
|
|
|
listeners = mListeners;
|
|
|
|
for (auto& listener : listeners) {
|
|
|
|
listener->NotifyVRDisplayConnect(aDisplayID);
|
2016-07-04 22:46:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-02-14 19:21:09 +00:00
|
|
|
VRManagerChild::FireDOMVRDisplayDisconnectEventInternal(uint32_t aDisplayID)
|
2016-07-04 22:46:49 +00:00
|
|
|
{
|
2017-02-14 19:21:09 +00:00
|
|
|
// Iterate over a copy of mListeners, as dispatched events may modify it.
|
|
|
|
nsTArray<RefPtr<dom::VREventObserver>> listeners;
|
|
|
|
listeners = mListeners;
|
|
|
|
for (auto& listener : listeners) {
|
|
|
|
listener->NotifyVRDisplayDisconnect(aDisplayID);
|
2016-07-04 22:46:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-02-14 19:21:09 +00:00
|
|
|
VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal(uint32_t aDisplayID)
|
2016-07-04 22:46:49 +00:00
|
|
|
{
|
2017-02-14 19:21:09 +00:00
|
|
|
// Iterate over a copy of mListeners, as dispatched events may modify it.
|
|
|
|
nsTArray<RefPtr<dom::VREventObserver>> listeners;
|
|
|
|
listeners = mListeners;
|
|
|
|
for (auto& listener : listeners) {
|
|
|
|
listener->NotifyVRDisplayPresentChange(aDisplayID);
|
2016-07-04 22:46:49 +00:00
|
|
|
}
|
2016-02-24 23:54:50 +00:00
|
|
|
}
|
2016-07-04 22:46:49 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
VRManagerChild::AddListener(dom::VREventObserver* aObserver)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aObserver);
|
|
|
|
|
|
|
|
if (mListeners.IndexOf(aObserver) != kNoIndex) {
|
|
|
|
return; // already exists
|
|
|
|
}
|
|
|
|
|
|
|
|
mListeners.AppendElement(aObserver);
|
|
|
|
if (mListeners.Length() == 1) {
|
|
|
|
Unused << SendSetHaveEventListener(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
VRManagerChild::RemoveListener(dom::VREventObserver* aObserver)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aObserver);
|
|
|
|
|
|
|
|
mListeners.RemoveElement(aObserver);
|
|
|
|
if (mListeners.IsEmpty()) {
|
|
|
|
Unused << SendSetHaveEventListener(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-04 08:31:27 +00:00
|
|
|
void
|
2016-11-01 16:10:42 +00:00
|
|
|
VRManagerChild::HandleFatalError(const char* aName, const char* aMsg) const
|
2016-10-04 08:31:27 +00:00
|
|
|
{
|
|
|
|
dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
|
|
|
|
}
|
|
|
|
|
2017-02-02 06:59:44 +00:00
|
|
|
void
|
|
|
|
VRManagerChild::AddPromise(const uint32_t& aID, dom::Promise* aPromise)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!mGamepadPromiseList.Get(aID, nullptr));
|
|
|
|
mGamepadPromiseList.Put(aID, aPromise);
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
VRManagerChild::RecvReplyGamepadVibrateHaptic(const uint32_t& aPromiseID)
|
|
|
|
{
|
2017-03-07 02:17:57 +00:00
|
|
|
// VRManagerChild could be at other processes, but GamepadManager
|
|
|
|
// only exists at the content process or the same process
|
|
|
|
// in non-e10s mode.
|
|
|
|
MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess());
|
|
|
|
|
2017-02-02 06:59:44 +00:00
|
|
|
RefPtr<dom::Promise> p;
|
|
|
|
if (!mGamepadPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
|
|
|
|
MOZ_CRASH("We should always have a promise.");
|
|
|
|
}
|
|
|
|
|
|
|
|
p->MaybeResolve(true);
|
|
|
|
mGamepadPromiseList.Remove(aPromiseID);
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2015-09-17 21:23:13 +00:00
|
|
|
} // namespace gfx
|
|
|
|
} // namespace mozilla
|