Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/vr/ipc/VRManagerParent.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "VRManagerParent.h"
8
#include "ipc/VRLayerParent.h"
9
#include "mozilla/gfx/PVRManagerParent.h"
10
#include "mozilla/ipc/ProtocolTypes.h"
11
#include "mozilla/ipc/ProtocolUtils.h"       // for IToplevelProtocol
12
#include "mozilla/TimeStamp.h"               // for TimeStamp
13
#include "mozilla/Unused.h"
14
#include "VRManager.h"
15
#include "VRThread.h"
16
#include "gfxVRPuppet.h"
17
18
namespace mozilla {
19
using namespace layers;
20
namespace gfx {
21
22
VRManagerParent::VRManagerParent(ProcessId aChildProcessId, bool aIsContentChild)
23
  : mControllerTestID(1)
24
  , mHaveEventListener(false)
25
  , mHaveControllerListener(false)
26
  , mIsContentChild(aIsContentChild)
27
0
{
28
0
  MOZ_COUNT_CTOR(VRManagerParent);
29
0
  MOZ_ASSERT(NS_IsMainThread());
30
0
31
0
  SetOtherProcessId(aChildProcessId);
32
0
}
33
34
VRManagerParent::~VRManagerParent()
35
0
{
36
0
  MOZ_ASSERT(!mVRManagerHolder);
37
0
38
0
  MOZ_COUNT_DTOR(VRManagerParent);
39
0
}
40
41
PVRLayerParent*
42
VRManagerParent::AllocPVRLayerParent(const uint32_t& aDisplayID,
43
                                     const uint32_t& aGroup)
44
0
{
45
0
  RefPtr<VRLayerParent> layer;
46
0
  layer = new VRLayerParent(aDisplayID,
47
0
                            aGroup);
48
0
  VRManager* vm = VRManager::Get();
49
0
  RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(aDisplayID);
50
0
  if (display) {
51
0
    display->AddLayer(layer);
52
0
  }
53
0
  return layer.forget().take();
54
0
}
55
56
bool
57
VRManagerParent::DeallocPVRLayerParent(PVRLayerParent* actor)
58
0
{
59
0
  delete actor;
60
0
  return true;
61
0
}
62
63
bool
64
VRManagerParent::IsSameProcess() const
65
0
{
66
0
  return OtherPid() == base::GetCurrentProcId();
67
0
}
68
69
void
70
VRManagerParent::RegisterWithManager()
71
0
{
72
0
  VRManager* vm = VRManager::Get();
73
0
  vm->AddVRManagerParent(this);
74
0
  mVRManagerHolder = vm;
75
0
}
76
77
void
78
VRManagerParent::UnregisterFromManager()
79
0
{
80
0
  VRManager* vm = VRManager::Get();
81
0
  vm->RemoveVRManagerParent(this);
82
0
  mVRManagerHolder = nullptr;
83
0
}
84
85
/* static */ bool
86
VRManagerParent::CreateForContent(Endpoint<PVRManagerParent>&& aEndpoint)
87
0
{
88
0
  MessageLoop* loop = VRListenerThreadHolder::Loop();
89
0
90
0
  RefPtr<VRManagerParent> vmp = new VRManagerParent(aEndpoint.OtherPid(), true);
91
0
  loop->PostTask(NewRunnableMethod<Endpoint<PVRManagerParent>&&>(
92
0
    "gfx::VRManagerParent::Bind",
93
0
    vmp,
94
0
    &VRManagerParent::Bind,
95
0
    std::move(aEndpoint)));
96
0
97
0
  return true;
98
0
}
99
100
void
101
VRManagerParent::Bind(Endpoint<PVRManagerParent>&& aEndpoint)
102
0
{
103
0
  if (!aEndpoint.Bind(this)) {
104
0
    return;
105
0
  }
106
0
  mSelfRef = this;
107
0
108
0
  RegisterWithManager();
109
0
}
110
111
/*static*/ void
112
VRManagerParent::RegisterVRManagerInVRListenerThread(VRManagerParent* aVRManager)
113
0
{
114
0
  aVRManager->RegisterWithManager();
115
0
}
116
117
/*static*/ VRManagerParent*
118
VRManagerParent::CreateSameProcess()
119
0
{
120
0
  MessageLoop* loop = VRListenerThreadHolder::Loop();
121
0
  RefPtr<VRManagerParent> vmp = new VRManagerParent(base::GetCurrentProcId(), false);
122
0
  vmp->mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton();
123
0
  vmp->mSelfRef = vmp;
124
0
  loop->PostTask(NewRunnableFunction("RegisterVRManagerInVRListenerThreadRunnable",
125
0
                                     RegisterVRManagerInVRListenerThread, vmp.get()));
126
0
  return vmp.get();
127
0
}
128
129
bool
130
VRManagerParent::CreateForGPUProcess(Endpoint<PVRManagerParent>&& aEndpoint)
131
0
{
132
0
  MessageLoop* loop = VRListenerThreadHolder::Loop();
133
0
134
0
  RefPtr<VRManagerParent> vmp = new VRManagerParent(aEndpoint.OtherPid(), false);
135
0
  vmp->mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton();
136
0
  loop->PostTask(NewRunnableMethod<Endpoint<PVRManagerParent>&&>(
137
0
    "gfx::VRManagerParent::Bind",
138
0
    vmp,
139
0
    &VRManagerParent::Bind,
140
0
    std::move(aEndpoint)));
141
0
  return true;
142
0
}
143
144
void
145
VRManagerParent::DeferredDestroy()
146
0
{
147
0
  mVRListenerThreadHolder = nullptr;
148
0
  mSelfRef = nullptr;
149
0
}
150
151
void
152
VRManagerParent::ActorDestroy(ActorDestroyReason why)
153
0
{
154
0
  UnregisterFromManager();
155
0
  MessageLoop::current()->PostTask(
156
0
    NewRunnableMethod("gfx::VRManagerParent::DeferredDestroy",
157
0
                      this,
158
0
                      &VRManagerParent::DeferredDestroy));
159
0
}
160
161
void
162
VRManagerParent::OnChannelConnected(int32_t aPid)
163
0
{
164
0
  mVRListenerThreadHolder = VRListenerThreadHolder::GetSingleton();
165
0
}
166
167
mozilla::ipc::IPCResult
168
VRManagerParent::RecvRefreshDisplays()
169
0
{
170
0
  // TODO: Bug 1406327, Launch VR listener thread here.
171
0
  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
172
0
173
0
  // This is called to refresh the VR Displays for Navigator.GetVRDevices().
174
0
  // We must pass "true" to VRManager::RefreshVRDisplays()
175
0
  // to ensure that the promise returned by Navigator.GetVRDevices
176
0
  // can resolve even if there are no changes to the VR Displays.
177
0
  VRManager* vm = VRManager::Get();
178
0
  vm->RefreshVRDisplays(true);
179
0
180
0
  return IPC_OK();
181
0
}
182
183
mozilla::ipc::IPCResult
184
VRManagerParent::RecvResetSensor(const uint32_t& aDisplayID)
185
0
{
186
0
  VRManager* vm = VRManager::Get();
187
0
  RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(aDisplayID);
188
0
  if (display != nullptr) {
189
0
    display->ZeroSensor();
190
0
  }
191
0
192
0
  return IPC_OK();
193
0
}
194
195
mozilla::ipc::IPCResult
196
VRManagerParent::RecvSetGroupMask(const uint32_t& aDisplayID, const uint32_t& aGroupMask)
197
0
{
198
0
  VRManager* vm = VRManager::Get();
199
0
  RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(aDisplayID);
200
0
  if (display != nullptr) {
201
0
    display->SetGroupMask(aGroupMask);
202
0
  }
203
0
  return IPC_OK();
204
0
}
205
206
bool
207
VRManagerParent::HaveEventListener()
208
0
{
209
0
  return mHaveEventListener;
210
0
}
211
212
bool
213
VRManagerParent::HaveControllerListener()
214
0
{
215
0
  return mHaveControllerListener;
216
0
}
217
218
mozilla::ipc::IPCResult
219
VRManagerParent::RecvSetHaveEventListener(const bool& aHaveEventListener)
220
0
{
221
0
  mHaveEventListener = aHaveEventListener;
222
0
  return IPC_OK();
223
0
}
224
225
mozilla::ipc::IPCResult
226
VRManagerParent::RecvControllerListenerAdded()
227
0
{
228
0
  // Force update the available controllers for GamepadManager,
229
0
  // remove the existing controllers and sync them by NotifyVsync().
230
0
  VRManager* vm = VRManager::Get();
231
0
  vm->RemoveControllers();
232
0
  mHaveControllerListener = true;
233
0
  return IPC_OK();
234
0
}
235
236
mozilla::ipc::IPCResult
237
VRManagerParent::RecvControllerListenerRemoved()
238
0
{
239
0
  mHaveControllerListener = false;
240
0
  VRManager* vm = VRManager::Get();
241
0
  vm->RemoveControllers();
242
0
  return IPC_OK();
243
0
}
244
245
mozilla::ipc::IPCResult
246
VRManagerParent::RecvCreateVRTestSystem()
247
0
{
248
0
  VRManager* vm = VRManager::Get();
249
0
  vm->CreateVRTestSystem();
250
0
  // The mControllerTestID is 1 based
251
0
  mControllerTestID = 1;
252
0
  mVRControllerTests.Clear();
253
0
  return IPC_OK();
254
0
}
255
256
mozilla::ipc::IPCResult
257
VRManagerParent::RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint32_t& aPromiseID)
258
0
{
259
0
  VRManager* vm = VRManager::Get();
260
0
  VRSystemManagerPuppet* puppetManager = vm->GetPuppetManager();
261
0
  uint32_t deviceID = puppetManager->CreateTestDisplay();
262
0
263
0
  if (SendReplyCreateVRServiceTestDisplay(aID, aPromiseID, deviceID)) {
264
0
    return IPC_OK();
265
0
  }
266
0
267
0
  return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
268
0
}
269
270
mozilla::ipc::IPCResult
271
VRManagerParent::RecvCreateVRServiceTestController(const nsCString& aID, const uint32_t& aPromiseID)
272
0
{
273
0
  uint32_t controllerIdx = 1; // ID's are 1 based
274
0
  nsTArray<VRControllerInfo> controllerInfoArray;
275
0
  impl::VRControllerPuppet* controllerPuppet = nullptr;
276
0
  VRManager* vm = VRManager::Get();
277
0
278
0
  /**
279
0
   * When running headless mochitests on some of our automated test
280
0
   * infrastructure, 2d display vsyncs are not always generated.
281
0
   * In this case, the test controllers can't be created immediately
282
0
   * after the VR display was created as the state of the VR displays
283
0
   * are updated during vsync.
284
0
   * To workaround, we produce a vsync manually.
285
0
   */
286
0
  vm->NotifyVsync(TimeStamp::Now());
287
0
288
0
  // Get VRControllerPuppet from VRManager
289
0
  vm->GetVRControllerInfo(controllerInfoArray);
290
0
  for (auto& controllerInfo : controllerInfoArray) {
291
0
    if (controllerInfo.GetType() == VRDeviceType::Puppet) {
292
0
      if (controllerIdx == mControllerTestID) {
293
0
        controllerPuppet = static_cast<impl::VRControllerPuppet*>(
294
0
                           vm->GetController(controllerInfo.GetControllerID()).get());
295
0
        break;
296
0
      }
297
0
      ++controllerIdx;
298
0
    }
299
0
  }
300
0
301
0
  // We might not have a controllerPuppet if the test did
302
0
  // not create a VR display first.
303
0
  if (!controllerPuppet) {
304
0
    // We send a device ID of "0" to indicate failure
305
0
    if (SendReplyCreateVRServiceTestController(aID, aPromiseID, 0)) {
306
0
      return IPC_OK();
307
0
    }
308
0
  } else {
309
0
    if (!mVRControllerTests.Get(mControllerTestID, nullptr)) {
310
0
      mVRControllerTests.Put(mControllerTestID, controllerPuppet);
311
0
    }
312
0
313
0
    if (SendReplyCreateVRServiceTestController(aID, aPromiseID, mControllerTestID)) {
314
0
      ++mControllerTestID;
315
0
      return IPC_OK();
316
0
    }
317
0
  }
318
0
319
0
  return IPC_FAIL(this, "SendReplyCreateVRServiceTestController fail");
320
0
}
321
322
mozilla::ipc::IPCResult
323
VRManagerParent::RecvSetDisplayInfoToMockDisplay(const uint32_t& aDeviceID,
324
                                                 const VRDisplayInfo& aDisplayInfo)
325
0
{
326
0
  VRManager* vm = VRManager::Get();
327
0
  VRSystemManagerPuppet* puppetManager = vm->GetPuppetManager();
328
0
  puppetManager->SetPuppetDisplayInfo(aDeviceID, aDisplayInfo);
329
0
  return IPC_OK();
330
0
}
331
332
mozilla::ipc::IPCResult
333
VRManagerParent::RecvSetSensorStateToMockDisplay(const uint32_t& aDeviceID,
334
                                                 const VRHMDSensorState& aSensorState)
335
0
{
336
0
  VRManager* vm = VRManager::Get();
337
0
  VRSystemManagerPuppet* puppetManager = vm->GetPuppetManager();
338
0
  puppetManager->SetPuppetDisplaySensorState(aDeviceID, aSensorState);
339
0
  return IPC_OK();
340
0
}
341
342
already_AddRefed<impl::VRControllerPuppet>
343
VRManagerParent::GetControllerPuppet(uint32_t aDeviceID)
344
0
{
345
0
  // aDeviceID for controllers start at 1 and are
346
0
  // used as a key to mVRControllerTests
347
0
  MOZ_ASSERT(aDeviceID > 0);
348
0
  RefPtr<impl::VRControllerPuppet> controllerPuppet;
349
0
  mVRControllerTests.Get(aDeviceID,
350
0
                         getter_AddRefs(controllerPuppet));
351
0
  MOZ_ASSERT(controllerPuppet);
352
0
  return controllerPuppet.forget();
353
0
}
354
355
mozilla::ipc::IPCResult
356
VRManagerParent::RecvNewButtonEventToMockController(const uint32_t& aDeviceID, const long& aButton,
357
                                                    const bool& aPressed)
358
0
{
359
0
  RefPtr<impl::VRControllerPuppet> controllerPuppet = GetControllerPuppet(aDeviceID);
360
0
  if (controllerPuppet) {
361
0
    controllerPuppet->SetButtonPressState(aButton, aPressed);
362
0
  }
363
0
  return IPC_OK();
364
0
}
365
366
mozilla::ipc::IPCResult
367
VRManagerParent::RecvNewAxisMoveEventToMockController(const uint32_t& aDeviceID, const long& aAxis,
368
                                                      const double& aValue)
369
0
{
370
0
  RefPtr<impl::VRControllerPuppet> controllerPuppet = GetControllerPuppet(aDeviceID);
371
0
  if (controllerPuppet) {
372
0
    controllerPuppet->SetAxisMoveState(aAxis, aValue);
373
0
  }
374
0
  return IPC_OK();
375
0
}
376
377
mozilla::ipc::IPCResult
378
VRManagerParent::RecvNewPoseMoveToMockController(const uint32_t& aDeviceID,
379
                                                 const GamepadPoseState& pose)
380
0
{
381
0
  RefPtr<impl::VRControllerPuppet> controllerPuppet = GetControllerPuppet(aDeviceID);
382
0
  if (controllerPuppet) {
383
0
    controllerPuppet->SetPoseMoveState(pose);
384
0
  }
385
0
  return IPC_OK();
386
0
}
387
388
mozilla::ipc::IPCResult
389
VRManagerParent::RecvVibrateHaptic(const uint32_t& aControllerIdx,
390
                                   const uint32_t& aHapticIndex,
391
                                   const double& aIntensity,
392
                                   const double& aDuration,
393
                                   const uint32_t& aPromiseID)
394
0
{
395
0
  VRManager* vm = VRManager::Get();
396
0
  VRManagerPromise promise(this, aPromiseID);
397
0
398
0
  vm->VibrateHaptic(aControllerIdx, aHapticIndex, aIntensity,
399
0
                    aDuration, promise);
400
0
  return IPC_OK();
401
0
}
402
403
mozilla::ipc::IPCResult
404
VRManagerParent::RecvStopVibrateHaptic(const uint32_t& aControllerIdx)
405
0
{
406
0
  VRManager* vm = VRManager::Get();
407
0
  vm->StopVibrateHaptic(aControllerIdx);
408
0
  return IPC_OK();
409
0
}
410
411
bool
412
VRManagerParent::SendGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
413
0
{
414
0
  // GamepadManager only exists at the content process
415
0
  // or the same process in non-e10s mode.
416
0
  if (mHaveControllerListener &&
417
0
      (mIsContentChild || IsSameProcess())) {
418
0
    return PVRManagerParent::SendGamepadUpdate(aGamepadEvent);
419
0
  }
420
0
421
0
  return true;
422
0
}
423
424
bool
425
VRManagerParent::SendReplyGamepadVibrateHaptic(const uint32_t& aPromiseID)
426
0
{
427
0
  // GamepadManager only exists at the content process
428
0
  // or the same process in non-e10s mode.
429
0
  if (mHaveControllerListener &&
430
0
      (mIsContentChild || IsSameProcess())) {
431
0
    return PVRManagerParent::SendReplyGamepadVibrateHaptic(aPromiseID);
432
0
  }
433
0
434
0
  return true;
435
0
}
436
437
mozilla::ipc::IPCResult
438
VRManagerParent::RecvStartVRNavigation(const uint32_t& aDeviceID)
439
0
{
440
0
  VRManager* vm = VRManager::Get();
441
0
  vm->StartVRNavigation(aDeviceID);
442
0
  return IPC_OK();
443
0
}
444
445
mozilla::ipc::IPCResult
446
VRManagerParent::RecvStopVRNavigation(const uint32_t& aDeviceID, const TimeDuration& aTimeout)
447
0
{
448
0
  VRManager* vm = VRManager::Get();
449
0
  vm->StopVRNavigation(aDeviceID, aTimeout);
450
0
  return IPC_OK();
451
0
}
452
453
} // namespace gfx
454
} // namespace mozilla