LCOV - code coverage report
Current view: top level - gfx/vr - VRManager.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 52 218 23.9 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
       8             : #include "VRManager.h"
       9             : #include "VRManagerParent.h"
      10             : #include "VRThread.h"
      11             : #include "gfxVR.h"
      12             : #include "mozilla/ClearOnShutdown.h"
      13             : #include "mozilla/dom/VRDisplay.h"
      14             : #include "mozilla/dom/GamepadEventTypes.h"
      15             : #include "mozilla/layers/TextureHost.h"
      16             : #include "mozilla/layers/CompositorThread.h"
      17             : #include "mozilla/Unused.h"
      18             : 
      19             : #include "gfxPrefs.h"
      20             : #include "gfxVR.h"
      21             : #include "gfxVRExternal.h"
      22             : #if defined(XP_WIN)
      23             : #include "gfxVROculus.h"
      24             : #endif
      25             : #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
      26             : #include "gfxVROpenVR.h"
      27             : #include "gfxVROSVR.h"
      28             : #endif
      29             : 
      30             : #include "gfxVRPuppet.h"
      31             : #include "ipc/VRLayerParent.h"
      32             : 
      33             : using namespace mozilla;
      34             : using namespace mozilla::gfx;
      35             : using namespace mozilla::layers;
      36             : using namespace mozilla::gl;
      37             : 
      38             : namespace mozilla {
      39             : namespace gfx {
      40             : 
      41           1 : static StaticRefPtr<VRManager> sVRManagerSingleton;
      42             : 
      43             : /*static*/ void
      44           0 : VRManager::ManagerInit()
      45             : {
      46           1 :   MOZ_ASSERT(NS_IsMainThread());
      47             : 
      48           2 :   if (sVRManagerSingleton == nullptr) {
      49           0 :     sVRManagerSingleton = new VRManager();
      50           1 :     ClearOnShutdown(&sVRManagerSingleton);
      51             :   }
      52           0 : }
      53             : 
      54           1 : VRManager::VRManager()
      55             :   : mInitialized(false)
      56             :   , mVRDisplaysRequested(false)
      57           0 :   , mVRControllersRequested(false)
      58             : {
      59           1 :   MOZ_COUNT_CTOR(VRManager);
      60           0 :   MOZ_ASSERT(sVRManagerSingleton == nullptr);
      61             : 
      62           0 :   RefPtr<VRSystemManager> mgr;
      63             : 
      64             :   /**
      65             :    * We must add the VRDisplayManager's to mManagers in a careful order to
      66             :    * ensure that we don't detect the same VRDisplay from multiple API's.
      67             :    *
      68             :    * Oculus comes first, as it will only enumerate Oculus HMD's and is the
      69             :    * native interface for Oculus HMD's.
      70             :    *
      71             :    * OpenvR comes second, as it is the native interface for HTC Vive
      72             :    * which is the most common HMD at this time.
      73             :    *
      74             :    * OSVR will be used if Oculus SDK and OpenVR don't detect any HMDS,
      75             :    * to support everyone else.
      76             :    */
      77           1 :   mExternalManager = VRSystemManagerExternal::Create();
      78           2 :   if (mExternalManager) {
      79           0 :       mManagers.AppendElement(mExternalManager);
      80             :   }
      81             : 
      82             : #if defined(XP_WIN)
      83             :   // The Oculus runtime is supported only on Windows
      84             :   mgr = VRSystemManagerOculus::Create();
      85             :   if (mgr) {
      86             :     mManagers.AppendElement(mgr);
      87             :   }
      88             : #endif
      89             : 
      90             : #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
      91             :   // OpenVR is cross platform compatible
      92           1 :   mgr = VRSystemManagerOpenVR::Create();
      93           1 :   if (mgr) {
      94           0 :     mManagers.AppendElement(mgr);
      95             :   }
      96             : 
      97             :   // OSVR is cross platform compatible
      98           1 :   mgr = VRSystemManagerOSVR::Create();
      99           1 :   if (mgr) {
     100           0 :       mManagers.AppendElement(mgr);
     101             :   }
     102             : #endif
     103             : 
     104             :   // Enable gamepad extensions while VR is enabled.
     105             :   // Preference only can be set at the Parent process.
     106           1 :   if (XRE_IsParentProcess() && gfxPrefs::VREnabled()) {
     107           1 :     Preferences::SetBool("dom.gamepad.extensions.enabled", true);
     108             :   }
     109           1 : }
     110             : 
     111           0 : VRManager::~VRManager()
     112             : {
     113           0 :   MOZ_ASSERT(NS_IsMainThread());
     114           0 :   MOZ_ASSERT(!mInitialized);
     115           0 :   MOZ_COUNT_DTOR(VRManager);
     116           0 : }
     117             : 
     118             : void
     119           0 : VRManager::Destroy()
     120             : {
     121           0 :   mVRDisplays.Clear();
     122           0 :   mVRControllers.Clear();
     123           0 :   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     124           0 :     mManagers[i]->Destroy();
     125             :   }
     126             : 
     127           0 :   mInitialized = false;
     128           0 : }
     129             : 
     130             : void
     131           0 : VRManager::Shutdown()
     132             : {
     133           0 :   mVRDisplays.Clear();
     134           0 :   mVRControllers.Clear();
     135         160 :   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     136           0 :     mManagers[i]->Shutdown();
     137             :   }
     138           0 : }
     139             : 
     140             : void
     141           0 : VRManager::Init()
     142             : {
     143           0 :   mInitialized = true;
     144           0 : }
     145             : 
     146             : /* static */VRManager*
     147          82 : VRManager::Get()
     148             : {
     149         164 :   MOZ_ASSERT(sVRManagerSingleton != nullptr);
     150             : 
     151           0 :   return sVRManagerSingleton;
     152             : }
     153             : 
     154             : void
     155           2 : VRManager::AddVRManagerParent(VRManagerParent* aVRManagerParent)
     156             : {
     157           0 :   if (mVRManagerParents.IsEmpty()) {
     158           1 :     Init();
     159             :   }
     160           2 :   mVRManagerParents.PutEntry(aVRManagerParent);
     161           0 : }
     162             : 
     163             : void
     164           0 : VRManager::RemoveVRManagerParent(VRManagerParent* aVRManagerParent)
     165             : {
     166           0 :   mVRManagerParents.RemoveEntry(aVRManagerParent);
     167           0 :   if (mVRManagerParents.IsEmpty()) {
     168           0 :     Destroy();
     169             :   }
     170           0 : }
     171             : 
     172             : void
     173          80 : VRManager::UpdateRequestedDevices()
     174             : {
     175          80 :   bool bHaveEventListener = false;
     176           0 :   bool bHaveControllerListener = false;
     177             : 
     178           0 :   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     179         320 :     VRManagerParent *vmp = iter.Get()->GetKey();
     180           0 :     bHaveEventListener |= vmp->HaveEventListener();
     181         160 :     bHaveControllerListener |= vmp->HaveControllerListener();
     182             :   }
     183             : 
     184          80 :   mVRDisplaysRequested = bHaveEventListener;
     185             :   // We only currently allow controllers to be used when
     186             :   // also activating a VR display
     187          80 :   mVRControllersRequested = mVRDisplaysRequested && bHaveControllerListener;
     188           0 : }
     189             : 
     190             : /**
     191             :  * VRManager::NotifyVsync must be called on every 2d vsync (usually at 60hz).
     192             :  * This must be called even when no WebVR site is active.
     193             :  * If we don't have a 2d display attached to the system, we can call this
     194             :  * at the VR display's native refresh rate.
     195             :  **/
     196             : void
     197           0 : VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
     198             : {
     199          80 :   MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
     200          80 :   UpdateRequestedDevices();
     201             : 
     202         240 :   for (const auto& manager : mManagers) {
     203           0 :     manager->NotifyVSync();
     204             :   }
     205             : 
     206             :   // We must continually refresh the VR display enumeration to check
     207             :   // for events that we must fire such as Window.onvrdisplayconnect
     208             :   // Note that enumeration itself may activate display hardware, such
     209             :   // as Oculus, so we only do this when we know we are displaying content
     210             :   // that is looking for VR displays.
     211          80 :   RefreshVRDisplays();
     212             : 
     213             :   // Update state and enumeration of VR controllers
     214          80 :   RefreshVRControllers();
     215             : 
     216          80 :   CheckForInactiveTimeout();
     217          80 : }
     218             : 
     219             : void
     220          80 : VRManager::CheckForInactiveTimeout()
     221             : {
     222             :   // Shut down the VR devices when not in use
     223          80 :   if (mVRDisplaysRequested || mVRControllersRequested) {
     224             :     // We are using a VR device, keep it alive
     225           0 :     mLastActiveTime = TimeStamp::Now();
     226             :   }
     227           0 :   else if (mLastActiveTime.IsNull()) {
     228          80 :     Shutdown();
     229             :   }
     230             :   else {
     231           0 :     TimeDuration duration = TimeStamp::Now() - mLastActiveTime;
     232           0 :     if (duration.ToMilliseconds() > gfxPrefs::VRInactiveTimeout()) {
     233           0 :       Shutdown();
     234             :     }
     235             :   }
     236          80 : }
     237             : 
     238             : void
     239           0 : VRManager::NotifyVRVsync(const uint32_t& aDisplayID)
     240             : {
     241           0 :   MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
     242           0 :   for (const auto& manager: mManagers) {
     243           0 :     if (manager->GetIsPresenting()) {
     244           0 :       manager->HandleInput();
     245             :     }
     246             :   }
     247             : 
     248           0 :   RefPtr<VRDisplayHost> display = GetDisplay(aDisplayID);
     249           0 :   if (display) {
     250           0 :     display->StartFrame();
     251             :   }
     252             : 
     253           0 :   RefreshVRDisplays();
     254           0 : }
     255             : 
     256             : void
     257           0 : VRManager::EnumerateVRDisplays()
     258             : {
     259             :   /**
     260             :    * Throttle the rate of enumeration to the interval set in
     261             :    * VRDisplayEnumerateInterval
     262             :    */
     263           0 :   if (!mLastDisplayEnumerationTime.IsNull()) {
     264           0 :     TimeDuration duration = TimeStamp::Now() - mLastDisplayEnumerationTime;
     265           0 :     if (duration.ToMilliseconds() < gfxPrefs::VRDisplayEnumerateInterval()) {
     266           0 :       return;
     267             :     }
     268             :   }
     269             : 
     270             :   /**
     271             :    * Any VRSystemManager instance may request that no enumeration
     272             :    * should occur, including enumeration from other VRSystemManager
     273             :    * instances.
     274             :    */
     275           0 :   for (const auto& manager : mManagers) {
     276           0 :     if (manager->ShouldInhibitEnumeration()) {
     277           0 :       return;
     278             :     }
     279             :   }
     280             : 
     281             :   /**
     282             :    * If we get this far, don't try again until
     283             :    * the VRDisplayEnumerateInterval elapses
     284             :    */
     285           0 :   mLastDisplayEnumerationTime = TimeStamp::Now();
     286             : 
     287             :   /**
     288             :    * VRSystemManagers are inserted into mManagers in
     289             :    * a strict order of priority.  The managers for the
     290             :    * most device-specialized API's will have a chance
     291             :    * to enumerate devices before the more generic
     292             :    * device-agnostic APIs.
     293             :    */
     294           0 :   for (const auto& manager : mManagers) {
     295           0 :     manager->Enumerate();
     296             :     /**
     297             :      * After a VRSystemManager::Enumerate is called, it may request
     298             :      * that further enumeration should stop.  This can be used to prevent
     299             :      * erraneous redundant enumeration of the same HMD by multiple managers.
     300             :      * XXX - Perhaps there will be a better way to detect duplicate displays
     301             :      * in the future.
     302             :      */
     303           0 :     if (manager->ShouldInhibitEnumeration()) {
     304           0 :       return;
     305             :     }
     306             :   }
     307             : }
     308             : 
     309             : void
     310          80 : VRManager::RefreshVRDisplays(bool aMustDispatch)
     311             : {
     312             :   /**
     313             :   * If we aren't viewing WebVR content, don't enumerate
     314             :   * new hardware, as it will cause some devices to power on
     315             :   * or interrupt other VR activities.
     316             :   */
     317          80 :   if (mVRDisplaysRequested || aMustDispatch) {
     318           0 :     EnumerateVRDisplays();
     319             :   }
     320             : 
     321             :   /**
     322             :    * VRSystemManager::GetHMDs will not activate new hardware
     323             :    * or result in interruption of other VR activities.
     324             :    * We can call it even when suppressing enumeration to get
     325             :    * the already-enumerated displays.
     326             :    */
     327           0 :   nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
     328           0 :   for (const auto& manager: mManagers) {
     329           0 :     manager->GetHMDs(displays);
     330             :   }
     331             : 
     332          80 :   bool displayInfoChanged = false;
     333          80 :   bool displaySetChanged = false;
     334             : 
     335         160 :   if (displays.Length() != mVRDisplays.Count()) {
     336             :     // Catch cases where a VR display has been removed
     337           0 :     displaySetChanged = true;
     338             :   }
     339             : 
     340         240 :   for (const auto& display: displays) {
     341           0 :     if (!GetDisplay(display->GetDisplayInfo().GetDisplayID())) {
     342             :       // This is a new display
     343             :       displaySetChanged = true;
     344             :       break;
     345             :     }
     346             : 
     347           0 :     if (display->CheckClearDisplayInfoDirty()) {
     348             :       // This display's info has changed
     349             :       displayInfoChanged = true;
     350             :       break;
     351             :     }
     352             :   }
     353             : 
     354             :   // Rebuild the HashMap if there are additions or removals
     355          80 :   if (displaySetChanged) {
     356           0 :     mVRDisplays.Clear();
     357           0 :     for (const auto& display: displays) {
     358           0 :       mVRDisplays.Put(display->GetDisplayInfo().GetDisplayID(), display);
     359             :     }
     360             :   }
     361             : 
     362          80 :   if (displayInfoChanged || displaySetChanged || aMustDispatch) {
     363           0 :     DispatchVRDisplayInfoUpdate();
     364             :   }
     365           0 : }
     366             : 
     367             : void
     368           0 : VRManager::DispatchVRDisplayInfoUpdate()
     369             : {
     370           0 :   nsTArray<VRDisplayInfo> update;
     371           0 :   GetVRDisplayInfo(update);
     372             : 
     373           0 :   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     374           0 :     Unused << iter.Get()->GetKey()->SendUpdateDisplayInfo(update);
     375             :   }
     376           0 : }
     377             : 
     378             : 
     379             : /**
     380             :  * Get any VR displays that have already been enumerated without
     381             :  * activating any new devices.
     382             :  */
     383             : void
     384           0 : VRManager::GetVRDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayInfo)
     385             : {
     386           0 :   aDisplayInfo.Clear();
     387           0 :   for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
     388           0 :     gfx::VRDisplayHost* display = iter.UserData();
     389           0 :     aDisplayInfo.AppendElement(VRDisplayInfo(display->GetDisplayInfo()));
     390             :   }
     391           0 : }
     392             : 
     393             : RefPtr<gfx::VRDisplayHost>
     394           0 : VRManager::GetDisplay(const uint32_t& aDisplayID)
     395             : {
     396           0 :   RefPtr<gfx::VRDisplayHost> display;
     397           0 :   if (mVRDisplays.Get(aDisplayID, getter_AddRefs(display))) {
     398             :     return display;
     399             :   }
     400             :   return nullptr;
     401             : }
     402             : 
     403             : RefPtr<gfx::VRControllerHost>
     404           0 : VRManager::GetController(const uint32_t& aControllerID)
     405             : {
     406           0 :   RefPtr<gfx::VRControllerHost> controller;
     407           0 :   if (mVRControllers.Get(aControllerID, getter_AddRefs(controller))) {
     408             :     return controller;
     409             :   }
     410             :   return nullptr;
     411             : }
     412             : 
     413             : void
     414           0 : VRManager::GetVRControllerInfo(nsTArray<VRControllerInfo>& aControllerInfo)
     415             : {
     416           0 :   aControllerInfo.Clear();
     417           0 :   for (auto iter = mVRControllers.Iter(); !iter.Done(); iter.Next()) {
     418           0 :     gfx::VRControllerHost* controller = iter.UserData();
     419           0 :     aControllerInfo.AppendElement(VRControllerInfo(controller->GetControllerInfo()));
     420             :   }
     421           0 : }
     422             : 
     423             : void
     424           0 : VRManager::RefreshVRControllers()
     425             : {
     426           0 :   ScanForControllers();
     427             : 
     428           0 :   nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
     429             : 
     430         240 :   for (uint32_t i = 0; i < mManagers.Length()
     431           0 :       && controllers.Length() == 0; ++i) {
     432           0 :     mManagers[i]->GetControllers(controllers);
     433             :   }
     434             : 
     435          80 :   bool controllerInfoChanged = false;
     436             : 
     437         160 :   if (controllers.Length() != mVRControllers.Count()) {
     438             :     // Catch cases where VR controllers has been removed
     439           0 :     controllerInfoChanged = true;
     440             :   }
     441             : 
     442           0 :   for (const auto& controller: controllers) {
     443           0 :     if (!GetController(controller->GetControllerInfo().GetControllerID())) {
     444             :       // This is a new controller
     445             :       controllerInfoChanged = true;
     446             :       break;
     447             :     }
     448             :   }
     449             : 
     450          80 :   if (controllerInfoChanged) {
     451           0 :     mVRControllers.Clear();
     452           0 :     for (const auto& controller: controllers) {
     453           0 :       mVRControllers.Put(controller->GetControllerInfo().GetControllerID(),
     454           0 :                          controller);
     455             :     }
     456             :   }
     457          80 : }
     458             : 
     459             : void
     460           0 : VRManager::ScanForControllers()
     461             : {
     462             :   // We don't have to do this every frame, so check if we
     463             :   // have enumerated recently
     464           0 :   if (!mLastControllerEnumerationTime.IsNull()) {
     465           0 :     TimeDuration duration = TimeStamp::Now() - mLastControllerEnumerationTime;
     466           0 :     if (duration.ToMilliseconds() < gfxPrefs::VRControllerEnumerateInterval()) {
     467           0 :       return;
     468             :     }
     469             :   }
     470             : 
     471             :   // Only enumerate controllers once we need them
     472          80 :   if (!mVRControllersRequested) {
     473             :     return;
     474             :   }
     475             : 
     476           0 :   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     477           0 :     mManagers[i]->ScanForControllers();
     478             :   }
     479             : 
     480           0 :   mLastControllerEnumerationTime = TimeStamp::Now();
     481             : }
     482             : 
     483             : void
     484           0 : VRManager::RemoveControllers()
     485             : {
     486           0 :   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     487           0 :     mManagers[i]->RemoveControllers();
     488             :   }
     489           0 :   mVRControllers.Clear();
     490           0 : }
     491             : 
     492             : void
     493           0 : VRManager::CreateVRTestSystem()
     494             : {
     495           0 :   if (mPuppetManager) {
     496           0 :     mPuppetManager->ClearTestDisplays();
     497           0 :     return;
     498             :   }
     499             : 
     500           0 :   mPuppetManager = VRSystemManagerPuppet::Create();
     501           0 :   mManagers.AppendElement(mPuppetManager);
     502             : }
     503             : 
     504             : VRSystemManagerPuppet*
     505           0 : VRManager::GetPuppetManager()
     506             : {
     507           0 :   MOZ_ASSERT(mPuppetManager);
     508           0 :   return mPuppetManager;
     509             : }
     510             : 
     511             : VRSystemManagerExternal*
     512           0 : VRManager::GetExternalManager()
     513             : {
     514           0 :   MOZ_ASSERT(mExternalManager);
     515           0 :   return mExternalManager;
     516             : }
     517             : 
     518             : template<class T>
     519             : void
     520           0 : VRManager::NotifyGamepadChange(uint32_t aIndex, const T& aInfo)
     521             : {
     522           0 :   dom::GamepadChangeEventBody body(aInfo);
     523           0 :   dom::GamepadChangeEvent e(aIndex, dom::GamepadServiceType::VR, body);
     524             : 
     525           0 :   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     526           0 :     Unused << iter.Get()->GetKey()->SendGamepadUpdate(e);
     527             :   }
     528           0 : }
     529             : 
     530             : void
     531           0 : VRManager::VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
     532             :                          double aIntensity, double aDuration,
     533             :                          const VRManagerPromise& aPromise)
     534             : 
     535             : {
     536           0 :   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     537           0 :     mManagers[i]->VibrateHaptic(aControllerIdx, aHapticIndex,
     538           0 :                                 aIntensity, aDuration, aPromise);
     539             :   }
     540           0 : }
     541             : 
     542             : void
     543           0 : VRManager::StopVibrateHaptic(uint32_t aControllerIdx)
     544             : {
     545           0 :   for (const auto& manager: mManagers) {
     546           0 :     manager->StopVibrateHaptic(aControllerIdx);
     547             :   }
     548           0 : }
     549             : 
     550             : void
     551           0 : VRManager::NotifyVibrateHapticCompleted(const VRManagerPromise& aPromise)
     552             : {
     553           0 :   aPromise.mParent->SendReplyGamepadVibrateHaptic(aPromise.mPromiseID);
     554           0 : }
     555             : 
     556             : void
     557           0 : VRManager::DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameResultInfo& aResult)
     558             : {
     559           0 :   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     560           0 :     Unused << iter.Get()->GetKey()->SendDispatchSubmitFrameResult(aDisplayID, aResult);
     561             :   }
     562           0 : }
     563             : 
     564             : } // namespace gfx
     565             : } // namespace mozilla

Generated by: LCOV version 1.13-14-ga5dd952