LCOV - code coverage report
Current view: top level - gfx/vr - VRManager.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 52 217 24.0 %
Date: 2017-07-14 16:53:18 Functions: 7 32 21.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : 
       7             : #include "VRManager.h"
       8             : #include "VRManagerParent.h"
       9             : #include "gfxVR.h"
      10             : #include "mozilla/ClearOnShutdown.h"
      11             : #include "mozilla/dom/VRDisplay.h"
      12             : #include "mozilla/dom/GamepadEventTypes.h"
      13             : #include "mozilla/layers/TextureHost.h"
      14             : #include "mozilla/Unused.h"
      15             : 
      16             : #include "gfxPrefs.h"
      17             : #include "gfxVR.h"
      18             : #if defined(XP_WIN)
      19             : #include "gfxVROculus.h"
      20             : #endif
      21             : #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
      22             : #include "gfxVROpenVR.h"
      23             : #include "gfxVROSVR.h"
      24             : #endif
      25             : #include "gfxVRPuppet.h"
      26             : #include "ipc/VRLayerParent.h"
      27             : 
      28             : using namespace mozilla;
      29             : using namespace mozilla::gfx;
      30             : using namespace mozilla::layers;
      31             : using namespace mozilla::gl;
      32             : 
      33             : namespace mozilla {
      34             : namespace gfx {
      35             : 
      36           3 : static StaticRefPtr<VRManager> sVRManagerSingleton;
      37             : 
      38             : /*static*/ void
      39           3 : VRManager::ManagerInit()
      40             : {
      41           3 :   MOZ_ASSERT(NS_IsMainThread());
      42             : 
      43           3 :   if (sVRManagerSingleton == nullptr) {
      44           3 :     sVRManagerSingleton = new VRManager();
      45           3 :     ClearOnShutdown(&sVRManagerSingleton);
      46             :   }
      47           3 : }
      48             : 
      49           3 : VRManager::VRManager()
      50             :   : mInitialized(false)
      51           3 :   , mVRTestSystemCreated(false)
      52             : {
      53           3 :   MOZ_COUNT_CTOR(VRManager);
      54           3 :   MOZ_ASSERT(sVRManagerSingleton == nullptr);
      55             : 
      56           6 :   RefPtr<VRSystemManager> mgr;
      57             : 
      58             :   /**
      59             :    * We must add the VRDisplayManager's to mManagers in a careful order to
      60             :    * ensure that we don't detect the same VRDisplay from multiple API's.
      61             :    *
      62             :    * Oculus comes first, as it will only enumerate Oculus HMD's and is the
      63             :    * native interface for Oculus HMD's.
      64             :    *
      65             :    * OpenvR comes second, as it is the native interface for HTC Vive
      66             :    * which is the most common HMD at this time.
      67             :    *
      68             :    * OSVR will be used if Oculus SDK and OpenVR don't detect any HMDS,
      69             :    * to support everyone else.
      70             :    */
      71             : 
      72             : #if defined(XP_WIN)
      73             :   // The Oculus runtime is supported only on Windows
      74             :   mgr = VRSystemManagerOculus::Create();
      75             :   if (mgr) {
      76             :     mManagers.AppendElement(mgr);
      77             :   }
      78             : #endif
      79             : 
      80             : #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
      81             :   // OpenVR is cross platform compatible
      82           3 :   mgr = VRSystemManagerOpenVR::Create();
      83           3 :   if (mgr) {
      84           0 :     mManagers.AppendElement(mgr);
      85             :   }
      86             : 
      87             :   // OSVR is cross platform compatible
      88           3 :   mgr = VRSystemManagerOSVR::Create();
      89           3 :   if (mgr) {
      90           0 :       mManagers.AppendElement(mgr);
      91             :   }
      92             : #endif
      93             :   // Enable gamepad extensions while VR is enabled.
      94             :   // Preference only can be set at the Parent process.
      95           3 :   if (XRE_IsParentProcess() && gfxPrefs::VREnabled()) {
      96           1 :     Preferences::SetBool("dom.gamepad.extensions.enabled", true);
      97             :   }
      98           3 : }
      99             : 
     100           0 : VRManager::~VRManager()
     101             : {
     102           0 :   MOZ_ASSERT(NS_IsMainThread());
     103           0 :   MOZ_ASSERT(!mInitialized);
     104           0 :   MOZ_COUNT_DTOR(VRManager);
     105           0 : }
     106             : 
     107             : void
     108           0 : VRManager::Destroy()
     109             : {
     110           0 :   mVRDisplays.Clear();
     111           0 :   mVRControllers.Clear();
     112           0 :   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     113           0 :     mManagers[i]->Destroy();
     114             :   }
     115             : 
     116           0 :   mInitialized = false;
     117           0 : }
     118             : 
     119             : void
     120         151 : VRManager::Shutdown()
     121             : {
     122         151 :   mVRDisplays.Clear();
     123         151 :   mVRControllers.Clear();
     124         151 :   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     125           0 :     mManagers[i]->Shutdown();
     126             :   }
     127         151 : }
     128             : 
     129             : void
     130           1 : VRManager::Init()
     131             : {
     132           1 :   mInitialized = true;
     133           1 : }
     134             : 
     135             : /* static */VRManager*
     136         154 : VRManager::Get()
     137             : {
     138         154 :   MOZ_ASSERT(sVRManagerSingleton != nullptr);
     139             : 
     140         154 :   return sVRManagerSingleton;
     141             : }
     142             : 
     143             : void
     144           3 : VRManager::AddVRManagerParent(VRManagerParent* aVRManagerParent)
     145             : {
     146           3 :   if (mVRManagerParents.IsEmpty()) {
     147           1 :     Init();
     148             :   }
     149           3 :   mVRManagerParents.PutEntry(aVRManagerParent);
     150           3 : }
     151             : 
     152             : void
     153           0 : VRManager::RemoveVRManagerParent(VRManagerParent* aVRManagerParent)
     154             : {
     155           0 :   mVRManagerParents.RemoveEntry(aVRManagerParent);
     156           0 :   if (mVRManagerParents.IsEmpty()) {
     157           0 :     Destroy();
     158             :   }
     159           0 : }
     160             : 
     161             : void
     162         151 : VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
     163             : {
     164         151 :   const double kVRDisplayRefreshMaxDuration = 5000; // milliseconds
     165         151 :   const double kVRDisplayInactiveMaxDuration = 30000; // milliseconds
     166             : 
     167         151 :   bool bHaveEventListener = false;
     168         151 :   bool bHaveControllerListener = false;
     169             : 
     170         455 :   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     171         304 :     VRManagerParent *vmp = iter.Get()->GetKey();
     172         304 :     bHaveEventListener |= vmp->HaveEventListener();
     173         304 :     bHaveControllerListener |= vmp->HaveControllerListener();
     174             :   }
     175             : 
     176             :   // VRDisplayHost::NotifyVSync may modify mVRDisplays, so we iterate
     177             :   // through a local copy here.
     178         302 :   nsTArray<RefPtr<VRDisplayHost>> displays;
     179         151 :   for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
     180           0 :     displays.AppendElement(iter.UserData());
     181             :   }
     182         151 :   for (const auto& display: displays) {
     183           0 :     display->NotifyVSync();
     184             :   }
     185             : 
     186         151 :   if (bHaveEventListener) {
     187             :     // If content has set an EventHandler to be notified of VR display events
     188             :     // we must continually refresh the VR display enumeration to check
     189             :     // for events that we must fire such as Window.onvrdisplayconnect
     190             :     // Note that enumeration itself may activate display hardware, such
     191             :     // as Oculus, so we only do this when we know we are displaying content
     192             :     // that is looking for VR displays.
     193           0 :     if (mLastRefreshTime.IsNull()) {
     194             :       // This is the first vsync, must refresh VR displays
     195           0 :       RefreshVRDisplays();
     196           0 :       if (bHaveControllerListener) {
     197           0 :         RefreshVRControllers();
     198             :       }
     199           0 :       mLastRefreshTime = TimeStamp::Now();
     200             :     } else {
     201             :       // We don't have to do this every frame, so check if we
     202             :       // have refreshed recently.
     203           0 :       TimeDuration duration = TimeStamp::Now() - mLastRefreshTime;
     204           0 :       if (duration.ToMilliseconds() > kVRDisplayRefreshMaxDuration) {
     205           0 :         RefreshVRDisplays();
     206           0 :         if (bHaveControllerListener) {
     207           0 :           RefreshVRControllers();
     208             :         }
     209           0 :         mLastRefreshTime = TimeStamp::Now();
     210             :       }
     211             :     }
     212             : 
     213           0 :     if (bHaveControllerListener) {
     214           0 :       for (const auto& manager: mManagers) {
     215           0 :         if (!manager->GetIsPresenting()) {
     216           0 :           manager->HandleInput();
     217             :         }
     218             :       }
     219             :     }
     220             :   }
     221             : 
     222             :   // Shut down the VR devices when not in use
     223         151 :   if (bHaveEventListener || bHaveControllerListener) {
     224             :     // We are using a VR device, keep it alive
     225           0 :     mLastActiveTime = TimeStamp::Now();
     226         151 :   } else if (mLastActiveTime.IsNull()) {
     227         151 :     Shutdown();
     228             :   } else {
     229           0 :     TimeDuration duration = TimeStamp::Now() - mLastActiveTime;
     230           0 :     if (duration.ToMilliseconds() > kVRDisplayInactiveMaxDuration) {
     231           0 :       Shutdown();
     232             :     }
     233             :   }
     234         151 : }
     235             : 
     236             : void
     237           0 : VRManager::NotifyVRVsync(const uint32_t& aDisplayID)
     238             : {
     239           0 :   for (const auto& manager: mManagers) {
     240           0 :     if (manager->GetIsPresenting()) {
     241           0 :       manager->HandleInput();
     242             :     }
     243             :   }
     244             : 
     245           0 :   RefPtr<VRDisplayHost> display = GetDisplay(aDisplayID);
     246           0 :   if (display) {
     247           0 :     display->StartFrame();
     248             :   }
     249             : 
     250           0 :   RefreshVRDisplays();
     251           0 : }
     252             : 
     253             : void
     254           0 : VRManager::RefreshVRDisplays(bool aMustDispatch)
     255             : {
     256           0 :   nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
     257             : 
     258             :   /** We don't wish to enumerate the same display from multiple managers,
     259             :    * so stop as soon as we get a display.
     260             :    * It is still possible to get multiple displays from a single manager,
     261             :    * but do not wish to mix-and-match for risk of reporting a duplicate.
     262             :    *
     263             :    * XXX - Perhaps there will be a better way to detect duplicate displays
     264             :    *       in the future.
     265             :    */
     266           0 :   for (uint32_t i = 0; i < mManagers.Length() && displays.Length() == 0; ++i) {
     267           0 :     if (mManagers[i]->GetHMDs(displays)) {
     268             :       // GetHMDs returns true to indicate that no further enumeration from
     269             :       // other managers should be performed.  This prevents erraneous
     270             :       // redundant enumeration of the same HMD by multiple managers.
     271           0 :       break;
     272             :     }
     273             :   }
     274             : 
     275           0 :   bool displayInfoChanged = false;
     276           0 :   bool displaySetChanged = false;
     277             : 
     278           0 :   if (displays.Length() != mVRDisplays.Count()) {
     279             :     // Catch cases where a VR display has been removed
     280           0 :     displaySetChanged = true;
     281             :   }
     282             : 
     283           0 :   for (const auto& display: displays) {
     284           0 :     if (!GetDisplay(display->GetDisplayInfo().GetDisplayID())) {
     285             :       // This is a new display
     286           0 :       displaySetChanged = true;
     287           0 :       break;
     288             :     }
     289             : 
     290           0 :     if (display->CheckClearDisplayInfoDirty()) {
     291             :       // This display's info has changed
     292           0 :       displayInfoChanged = true;
     293           0 :       break;
     294             :     }
     295             :   }
     296             : 
     297             :   // Rebuild the HashMap if there are additions or removals
     298           0 :   if (displaySetChanged) {
     299           0 :     mVRDisplays.Clear();
     300           0 :     for (const auto& display: displays) {
     301           0 :       mVRDisplays.Put(display->GetDisplayInfo().GetDisplayID(), display);
     302             :     }
     303             :   }
     304             : 
     305           0 :   if (displayInfoChanged || displaySetChanged || aMustDispatch) {
     306           0 :     DispatchVRDisplayInfoUpdate();
     307             :   }
     308           0 : }
     309             : 
     310             : void
     311           0 : VRManager::DispatchVRDisplayInfoUpdate()
     312             : {
     313           0 :   nsTArray<VRDisplayInfo> update;
     314           0 :   GetVRDisplayInfo(update);
     315             : 
     316           0 :   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     317           0 :     Unused << iter.Get()->GetKey()->SendUpdateDisplayInfo(update);
     318             :   }
     319           0 : }
     320             : 
     321             : 
     322             : /**
     323             :  * Get any VR displays that have already been enumerated without
     324             :  * activating any new devices.
     325             :  */
     326             : void
     327           0 : VRManager::GetVRDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayInfo)
     328             : {
     329           0 :   aDisplayInfo.Clear();
     330           0 :   for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
     331           0 :     gfx::VRDisplayHost* display = iter.UserData();
     332           0 :     aDisplayInfo.AppendElement(VRDisplayInfo(display->GetDisplayInfo()));
     333             :   }
     334           0 : }
     335             : 
     336             : RefPtr<gfx::VRDisplayHost>
     337           0 : VRManager::GetDisplay(const uint32_t& aDisplayID)
     338             : {
     339           0 :   RefPtr<gfx::VRDisplayHost> display;
     340           0 :   if (mVRDisplays.Get(aDisplayID, getter_AddRefs(display))) {
     341           0 :     return display;
     342             :   }
     343           0 :   return nullptr;
     344             : }
     345             : 
     346             : void
     347           0 : VRManager::SubmitFrame(VRLayerParent* aLayer, layers::PTextureParent* aTexture,
     348             :                        const gfx::Rect& aLeftEyeRect,
     349             :                        const gfx::Rect& aRightEyeRect)
     350             : {
     351           0 :   TextureHost* th = TextureHost::AsTextureHost(aTexture);
     352           0 :   mLastFrame = th;
     353           0 :   RefPtr<VRDisplayHost> display = GetDisplay(aLayer->GetDisplayID());
     354           0 :   if (display) {
     355           0 :     display->SubmitFrame(aLayer, aTexture, aLeftEyeRect, aRightEyeRect);
     356             :   }
     357           0 : }
     358             : 
     359             : RefPtr<gfx::VRControllerHost>
     360           0 : VRManager::GetController(const uint32_t& aControllerID)
     361             : {
     362           0 :   RefPtr<gfx::VRControllerHost> controller;
     363           0 :   if (mVRControllers.Get(aControllerID, getter_AddRefs(controller))) {
     364           0 :     return controller;
     365             :   }
     366           0 :   return nullptr;
     367             : }
     368             : 
     369             : void
     370           0 : VRManager::GetVRControllerInfo(nsTArray<VRControllerInfo>& aControllerInfo)
     371             : {
     372           0 :   aControllerInfo.Clear();
     373           0 :   for (auto iter = mVRControllers.Iter(); !iter.Done(); iter.Next()) {
     374           0 :     gfx::VRControllerHost* controller = iter.UserData();
     375           0 :     aControllerInfo.AppendElement(VRControllerInfo(controller->GetControllerInfo()));
     376             :   }
     377           0 : }
     378             : 
     379             : void
     380           0 : VRManager::RefreshVRControllers()
     381             : {
     382           0 :   nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
     383             : 
     384           0 :   ScanForControllers();
     385             : 
     386           0 :   for (uint32_t i = 0; i < mManagers.Length()
     387           0 :       && controllers.Length() == 0; ++i) {
     388           0 :     mManagers[i]->GetControllers(controllers);
     389             :   }
     390             : 
     391           0 :   bool controllerInfoChanged = false;
     392             : 
     393           0 :   if (controllers.Length() != mVRControllers.Count()) {
     394             :     // Catch cases where VR controllers has been removed
     395           0 :     controllerInfoChanged = true;
     396             :   }
     397             : 
     398           0 :   for (const auto& controller: controllers) {
     399           0 :     if (!GetController(controller->GetControllerInfo().GetControllerID())) {
     400             :       // This is a new controller
     401           0 :       controllerInfoChanged = true;
     402           0 :       break;
     403             :     }
     404             :   }
     405             : 
     406           0 :   if (controllerInfoChanged) {
     407           0 :     mVRControllers.Clear();
     408           0 :     for (const auto& controller: controllers) {
     409           0 :       mVRControllers.Put(controller->GetControllerInfo().GetControllerID(),
     410           0 :                          controller);
     411             :     }
     412             :   }
     413           0 : }
     414             : 
     415             : void
     416           0 : VRManager::ScanForControllers()
     417             : {
     418           0 :   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     419           0 :     mManagers[i]->ScanForControllers();
     420             :   }
     421           0 : }
     422             : 
     423             : void
     424           0 : VRManager::RemoveControllers()
     425             : {
     426           0 :   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     427           0 :     mManagers[i]->RemoveControllers();
     428             :   }
     429           0 :   mVRControllers.Clear();
     430           0 : }
     431             : 
     432             : void
     433           0 : VRManager::CreateVRTestSystem()
     434             : {
     435           0 :   if (mVRTestSystemCreated) {
     436           0 :     return;
     437             :   }
     438             : 
     439           0 :   RefPtr<VRSystemManager> mgr = VRSystemManagerPuppet::Create();
     440           0 :   if (mgr) {
     441           0 :     mManagers.AppendElement(mgr);
     442           0 :     mVRTestSystemCreated = true;
     443             :   }
     444             : }
     445             : 
     446             : template<class T>
     447             : void
     448           0 : VRManager::NotifyGamepadChange(const T& aInfo)
     449             : {
     450           0 :   dom::GamepadChangeEvent e(aInfo);
     451             : 
     452           0 :   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     453           0 :     Unused << iter.Get()->GetKey()->SendGamepadUpdate(e);
     454             :   }
     455           0 : }
     456             : 
     457             : void
     458           0 : VRManager::VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
     459             :                          double aIntensity, double aDuration, uint32_t aPromiseID)
     460             : 
     461             : {
     462           0 :   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     463           0 :     mManagers[i]->VibrateHaptic(aControllerIdx, aHapticIndex,
     464           0 :                                 aIntensity, aDuration, aPromiseID);
     465             :   }
     466           0 : }
     467             : 
     468             : void
     469           0 : VRManager::StopVibrateHaptic(uint32_t aControllerIdx)
     470             : {
     471           0 :   for (const auto& manager: mManagers) {
     472           0 :     manager->StopVibrateHaptic(aControllerIdx);
     473             :   }
     474           0 : }
     475             : 
     476             : void
     477           0 : VRManager::NotifyVibrateHapticCompleted(uint32_t aPromiseID)
     478             : {
     479           0 :   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     480           0 :     Unused << iter.Get()->GetKey()->SendReplyGamepadVibrateHaptic(aPromiseID);
     481             :   }
     482           0 : }
     483             : 
     484             : void
     485           0 : VRManager::DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameResultInfo& aResult)
     486             : {
     487           0 :   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     488           0 :     Unused << iter.Get()->GetKey()->SendDispatchSubmitFrameResult(aDisplayID, aResult);
     489             :   }
     490           0 : }
     491             : 
     492             : } // namespace gfx
     493             : } // namespace mozilla

Generated by: LCOV version 1.13