Bug 1384279 - Oculus Rift Core 2.0 Adjustments draft
authorKearwood "Kip" Gilbert <kgilbert@mozilla.com>
Thu, 07 Dec 2017 15:27:03 -0800
changeset 709415 99bdc0389f543d88e4061b0366c05e7397a69efd
parent 709267 8c84a3550f7adfc529b8568d9c559e7fd58946c3
child 743413 42430044fdfe199bd0c31e320e80b1c6cdd118c3
push id92635
push userkgilbert@mozilla.com
push dateFri, 08 Dec 2017 01:13:10 +0000
bugs1384279
milestone59.0a1
Bug 1384279 - Oculus Rift Core 2.0 Adjustments - Add pref to enable the ovrInit_Invisible flag for Oculus sessions, enabled by default. - Ensure that the Oculus library is unloaded every time it is uninitialized, improving reliability of exiting and returning to WebVR. MozReview-Commit-ID: 6VCugCJ2dUz
gfx/thebes/gfxPrefs.h
gfx/vr/gfxVROculus.cpp
gfx/vr/gfxVROculus.h
modules/libpref/init/all.js
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -358,18 +358,19 @@ private:
 
   DECL_GFX_PREF(Live, "dom.ipc.plugins.asyncdrawing.enabled",  PluginAsyncDrawingEnabled, bool, false);
   DECL_GFX_PREF(Live, "dom.meta-viewport.enabled",             MetaViewportEnabled, bool, false);
   DECL_GFX_PREF(Once, "dom.vr.enabled",                        VREnabled, bool, false);
   DECL_GFX_PREF(Live, "dom.vr.autoactivate.enabled",           VRAutoActivateEnabled, bool, false);
   DECL_GFX_PREF(Live, "dom.vr.controller_trigger_threshold",   VRControllerTriggerThreshold, float, 0.1f);
   DECL_GFX_PREF(Live, "dom.vr.navigation.timeout",             VRNavigationTimeout, int32_t, 1000);
   DECL_GFX_PREF(Once, "dom.vr.oculus.enabled",                 VROculusEnabled, bool, true);
-  DECL_GFX_PREF(Live, "dom.vr.oculus.present.timeout",         VROculusPresentTimeout, int32_t, 10000);
-  DECL_GFX_PREF(Live, "dom.vr.oculus.quit.timeout",            VROculusQuitTimeout, int32_t, 30000);
+  DECL_GFX_PREF(Live, "dom.vr.oculus.invisible.enabled",       VROculusInvisibleEnabled, bool, true);
+  DECL_GFX_PREF(Live, "dom.vr.oculus.present.timeout",         VROculusPresentTimeout, int32_t, 500);
+  DECL_GFX_PREF(Live, "dom.vr.oculus.quit.timeout",            VROculusQuitTimeout, int32_t, 10000);
   DECL_GFX_PREF(Once, "dom.vr.openvr.enabled",                 VROpenVREnabled, bool, false);
   DECL_GFX_PREF(Once, "dom.vr.osvr.enabled",                   VROSVREnabled, bool, false);
   DECL_GFX_PREF(Live, "dom.vr.controller.enumerate.interval",  VRControllerEnumerateInterval, int32_t, 1000);
   DECL_GFX_PREF(Live, "dom.vr.display.enumerate.interval",     VRDisplayEnumerateInterval, int32_t, 5000);
   DECL_GFX_PREF(Live, "dom.vr.inactive.timeout",               VRInactiveTimeout, int32_t, 5000);
   DECL_GFX_PREF(Live, "dom.vr.poseprediction.enabled",         VRPosePredictionEnabled, bool, true);
   DECL_GFX_PREF(Live, "dom.vr.require-gesture",                VRRequireGesture, bool, true);
   DECL_GFX_PREF(Live, "dom.vr.puppet.enabled",                 VRPuppetEnabled, bool, false);
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -304,28 +304,26 @@ VROculusSession::StopPresentation()
     }
     Refresh();
   }
 }
 
 VROculusSession::~VROculusSession()
 {
   mSubmitThread = nullptr;
-  Uninitialize(true);
+  Uninitialize();
 }
 
 void
-VROculusSession::Uninitialize(bool aUnloadLib)
+VROculusSession::Uninitialize()
 {
   StopRendering();
   StopSession();
   StopLib();
-  if (aUnloadLib) {
-    UnloadOvrLib();
-  }
+  UnloadOvrLib();
 }
 
 void
 VROculusSession::StopRendering()
 {
   if (!mRenderTargets.IsEmpty()) {
     mRenderTargets.Clear();
   }
@@ -361,22 +359,25 @@ VROculusSession::Refresh(bool aForceRefr
 {
   // We are waiting for drawing the black layer command for
   // Compositor thread. Ignore Refresh() calls from other threads.
   if (mDrawBlack && !aForceRefresh) {
     return;
   }
 
   if (!mRequestTracking) {
-    Uninitialize(true);
+    Uninitialize();
     return;
   }
 
   ovrInitFlags flags = (ovrInitFlags)(ovrInit_RequestVersion | ovrInit_MixedRendering);
   bool bInvisible = true;
+  if (!gfxPrefs::VROculusInvisibleEnabled()) {
+    bInvisible = false;
+  }
   if (mRequestPresentation) {
     bInvisible = false;
   } else if (!mLastPresentationEnd.IsNull()) {
     TimeDuration duration = TimeStamp::Now() - mLastPresentationEnd;
     TimeDuration timeout = TimeDuration::FromMilliseconds(gfxPrefs::VROculusPresentTimeout());
     if (timeout > TimeDuration(0) && duration < timeout) {
       // Do not immediately re-initialize with an invisible session after
       // the end of a VR presentation.  Waiting for the configured duraction
@@ -412,34 +413,34 @@ VROculusSession::Refresh(bool aForceRefr
       }
     }
   }
   if (bInvisible) {
     flags = (ovrInitFlags)(flags | ovrInit_Invisible);
   }
 
   if (mInitFlags != flags) {
-    Uninitialize(false);
+    Uninitialize();
   }
 
   if(!Initialize(flags)) {
     // If we fail to initialize, ensure the Oculus libraries
     // are unloaded, as we can't poll for ovrSessionStatus::ShouldQuit
     // without an active ovrSession.
-    Uninitialize(true);
+    Uninitialize();
   }
 
   if (mSession) {
     ovrSessionStatus status;
     if (OVR_SUCCESS(ovr_GetSessionStatus(mSession, &status))) {
       mIsConnected = status.HmdPresent;
       mIsMounted = status.HmdMounted;
       if (status.ShouldQuit) {
         mLastShouldQuit = TimeStamp::Now();
-        Uninitialize(true);
+        Uninitialize();
       }
     } else {
       mIsConnected = false;
       mIsMounted = false;
     }
   }
 }
 
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -73,17 +73,17 @@ private:
   bool mRequestPresentation;
   bool mRequestTracking;
   bool mTracking;
   bool mDrawBlack;
   bool mIsConnected;
   bool mIsMounted;
 
   ~VROculusSession();
-  void Uninitialize(bool aUnloadLib);
+  void Uninitialize();
   bool Initialize(ovrInitFlags aFlags);
   bool LoadOvrLib();
   void UnloadOvrLib();
   bool StartSession();
   void StopSession();
   bool StartLib(ovrInitFlags aFlags);
   void StopLib();
   bool StartRendering();
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5203,24 +5203,31 @@ pref("dom.vr.oculus.enabled", false);
 // Minimum number of milliseconds after content has stopped VR presentation
 // before the Oculus session is re-initialized to an invisible / tracking
 // only mode.  If this value is too high, users will need to wait longer
 // after stopping WebVR presentation before automatically returning to the
 // Oculus home interface.  (They can immediately return to the Oculus Home
 // interface through the Oculus HUD without waiting this duration)
 // If this value is too low, the Oculus Home interface may be visible
 // momentarily during VR link navigation.
-pref("dom.vr.oculus.present.timeout", 10000);
+pref("dom.vr.oculus.present.timeout", 500);
 // Minimum number of milliseconds that the browser will wait before
 // reloading the Oculus OVR library after seeing a "ShouldQuit" flag set.
 // Oculus requests that we shut down and unload the OVR library, by setting
 // a "ShouldQuit" flag.  To ensure that we don't interfere with
 // Oculus software auto-updates, we will not attempt to re-load the
 // OVR library until this timeout has elapsed.
-pref("dom.vr.oculus.quit.timeout", 30000);
+pref("dom.vr.oculus.quit.timeout", 10000);
+// When enabled, Oculus sessions may be created with the ovrInit_Invisible
+// flag if a page is using tracking but not presenting.  When a page
+// begins presenting VR frames, the session will be re-initialized without
+// the flag.  This eliminates the "Firefox not responding" warnings in
+// the headset, but might not be compatible with all versions of the Oculus
+// runtime.
+pref("dom.vr.oculus.invisible.enabled", true);
 // OSVR device
 pref("dom.vr.osvr.enabled", false);
 // OpenVR device
 #if !defined(HAVE_64BIT_BUILD)
 // We are only enabling WebVR by default on 64-bit builds (Bug 1384459)
 pref("dom.vr.openvr.enabled", false);
 #elif defined(XP_WIN) || defined(XP_MACOSX)
 // We enable WebVR by default for Windows and macOS