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 429585 ced7ff6dd7cdf770d7781c8b4da9027d1471f04a
parent 429584 591e885716bf12cd4b0d1ea7282b8c75a5bff073
child 429586 73168a75363633f0042e8bf03ed23f553ddf953e
push id34368
push userdvarga@mozilla.com
push dateWed, 01 Aug 2018 22:08:36 +0000
treeherdermozilla-central@210796a7e6b4 [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;