Bug 1479424 - Fix VRManager NotifyVSync not called when compositor is paused on Android; r=kip,rbarker
authorImanol Fernandez <imanol@mozilla.com>
Mon, 30 Jul 2018 18:14:05 +0200
changeset 429601 ced7ff6dd7cdf770d7781c8b4da9027d1471f04a
parent 429600 591e885716bf12cd4b0d1ea7282b8c75a5bff073
child 429602 73168a75363633f0042e8bf03ed23f553ddf953e
push id67187
push userdluca@mozilla.com
push dateWed, 01 Aug 2018 15:43:10 +0000
treeherderautoland@ced7ff6dd7cd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskip, rbarker
bugs1479424
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1479424 - Fix VRManager NotifyVSync not called when compositor is paused on Android; r=kip,rbarker MozReview-Commit-ID: JY8xyCSKIgv
gfx/vr/gfxVRExternal.cpp
gfx/vr/gfxVRExternal.h
--- a/gfx/vr/gfxVRExternal.cpp
+++ b/gfx/vr/gfxVRExternal.cpp
@@ -112,21 +112,55 @@ VRDisplayExternal::StartPresentation()
   mTelemetry.Clear();
   mTelemetry.mPresentationStart = TimeStamp::Now();
 
   // Indicate that we are ready to start immersive mode
   mBrowserState.presentationActive = true;
   mBrowserState.layerState[0].type = VRLayerType::LayerType_Stereo_Immersive;
   PushState();
 
+#if defined(MOZ_WIDGET_ANDROID)
+  /**
+   * Android compositor is paused when presentation starts. That causes VRManager::NotifyVsync() not to be called.
+   * We post a VRTask to call VRManager::NotifyVsync() while the compositor is paused on Android.
+   * VRManager::NotifyVsync() should be called constinuosly while the compositor is paused because Gecko WebVR Architecture
+   * relies on that to act as a "watchdog" in order to avoid render loop stalls and recover from SubmitFrame call timeouts.
+   */
+  PostVRTask();
+#endif
   // TODO - Implement telemetry:
 
   // mTelemetry.mLastDroppedFrameCount = stats.m_nNumReprojectedFrames;
 }
 
+#if defined(MOZ_WIDGET_ANDROID)
+void
+VRDisplayExternal::PostVRTask() {
+  MessageLoop * vrLoop = VRListenerThreadHolder::Loop();
+  if (!vrLoop || !mBrowserState.presentationActive) {
+    return;
+  }
+  RefPtr<Runnable> task = NewRunnableMethod(
+    "VRDisplayExternal::RunVRTask",
+    this,
+    &VRDisplayExternal::RunVRTask);
+  VRListenerThreadHolder::Loop()->PostDelayedTask(task.forget(), 50);
+}
+
+void
+VRDisplayExternal::RunVRTask() {
+  if (mBrowserState.presentationActive) {
+    VRManager *vm = VRManager::Get();
+    vm->NotifyVsync(TimeStamp::Now());
+    PostVRTask();
+  }
+}
+
+#endif // defined(MOZ_WIDGET_ANDROID)
+
 void
 VRDisplayExternal::StopPresentation()
 {
   if (!mBrowserState.presentationActive) {
     return;
   }
   sPushIndex = 0;
 
--- a/gfx/vr/gfxVRExternal.h
+++ b/gfx/vr/gfxVRExternal.h
@@ -55,16 +55,18 @@ protected:
 
 private:
   bool PopulateLayerTexture(const layers::SurfaceDescriptor& aTexture,
                             VRLayerTextureType* aTextureType,
                             VRLayerTextureHandle* aTextureHandle);
   void PushState(bool aNotifyCond = false);
 #if defined(MOZ_WIDGET_ANDROID)
   bool PullState(const std::function<bool()>& aWaitCondition = nullptr);
+  void PostVRTask();
+  void RunVRTask();
 #else
   bool PullState();
 #endif
 
   VRTelemetry mTelemetry;
   TimeStamp mVRNavigationTransitionEnd;
   VRBrowserState mBrowserState;
   VRHMDSensorState mLastSensorState;