Bug 1381165 - Ensure that only the first VRDisplay.submitFrame call per VRDisplay RAF callback renders and kicks off the next VR RAF callback. draft
authorKearwood "Kip" Gilbert <kgilbert@mozilla.com>
Fri, 14 Jul 2017 16:08:49 -0700
changeset 609166 65278e1dceaf6f147c5769682518308a7dfbf9e5
parent 609112 2908b6171cb8df85fc1f0985e2bf94ce3b04a522
child 637525 527a96d0074010490bb3d1c4ccc928bbce9dbccf
push id68528
push userkgilbert@mozilla.com
push dateFri, 14 Jul 2017 23:12:34 +0000
bugs1381165
milestone56.0a1
Bug 1381165 - Ensure that only the first VRDisplay.submitFrame call per VRDisplay RAF callback renders and kicks off the next VR RAF callback. MozReview-Commit-ID: L9qPfr1Jf9o
gfx/vr/VRDisplayHost.cpp
gfx/vr/VRDisplayHost.h
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -16,16 +16,17 @@
 
 #endif
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
 VRDisplayHost::VRDisplayHost(VRDeviceType aType)
+ : mFrameStarted(false)
 {
   MOZ_COUNT_CTOR(VRDisplayHost);
   mDisplayInfo.mType = aType;
   mDisplayInfo.mDisplayID = VRSystemManager::AllocateDisplayID();
   mDisplayInfo.mPresentingGroups = 0;
   mDisplayInfo.mGroupMask = kVRGroupContent;
   mDisplayInfo.mFrameId = 0;
 }
@@ -79,16 +80,17 @@ VRDisplayHost::RemoveLayer(VRLayerParent
 }
 
 void
 VRDisplayHost::StartFrame()
 {
   mLastFrameStart = TimeStamp::Now();
   ++mDisplayInfo.mFrameId;
   mDisplayInfo.mLastSensorState[mDisplayInfo.mFrameId % kVRMaxLatencyFrames] = GetSensorState();
+  mFrameStarted = true;
 }
 
 void
 VRDisplayHost::NotifyVSync()
 {
   /**
    * We will trigger a new frame immediately after a successful frame texture
    * submission.  If content fails to call VRDisplay.submitFrame after
@@ -157,16 +159,22 @@ VRDisplayHost::SubmitFrame(VRLayerParent
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect)
 {
   if ((mDisplayInfo.mGroupMask & aLayer->GetGroup()) == 0) {
     // Suppress layers hidden by the group mask
     return;
   }
 
+  // Ensure that we only accept the first SubmitFrame call per RAF cycle.
+  if (!mFrameStarted) {
+    return;
+  }
+  mFrameStarted = false;
+
   TextureHost* th = TextureHost::AsTextureHost(aTexture);
   // WebVR doesn't use the compositor to compose the frame, so use
   // AutoLockTextureHostWithoutCompositor here.
   AutoLockTextureHostWithoutCompositor autoLock(th);
   if (autoLock.Failed()) {
     NS_WARNING("Failed to lock the VR layer texture");
     return;
   }
--- a/gfx/vr/VRDisplayHost.h
+++ b/gfx/vr/VRDisplayHost.h
@@ -74,16 +74,17 @@ protected:
   // VRLayerParent destructor
 
 protected:
   virtual VRHMDSensorState GetSensorState() = 0;
 
 private:
   VRDisplayInfo mLastUpdateDisplayInfo;
   TimeStamp mLastFrameStart;
+  bool mFrameStarted;
 };
 
 class VRControllerHost {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRControllerHost)
 
   const VRControllerInfo& GetControllerInfo() const;
   void SetButtonPressed(uint64_t aBit);