Bug 1394561 - Ensure WebVR content can catch up when IPC messages are delayed draft
authorKearwood "Kip" Gilbert <kgilbert@mozilla.com>
Thu, 31 Aug 2017 16:29:14 -0700
changeset 663112 79eda7a6578b81db4f5f854127d60d1ceb68d580
parent 662980 b0e945eed81db8bf076daf64e381c514f70144f0
child 731099 2a0d2b2eb9a7cd5e0a3445a736ff36b39b451a25
push id79327
push userkgilbert@mozilla.com
push dateTue, 12 Sep 2017 17:15:21 +0000
bugs1394561
milestone57.0a1
Bug 1394561 - Ensure WebVR content can catch up when IPC messages are delayed MozReview-Commit-ID: F4NKtyaNwEo
gfx/vr/VRDisplayHost.cpp
gfx/vr/VRDisplayHost.h
gfx/vr/VRDisplayPresentation.cpp
gfx/vr/VRManager.cpp
gfx/vr/VRManager.h
gfx/vr/ipc/PVRLayer.ipdl
gfx/vr/ipc/VRLayerChild.cpp
gfx/vr/ipc/VRLayerChild.h
gfx/vr/ipc/VRLayerParent.cpp
gfx/vr/ipc/VRLayerParent.h
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -157,28 +157,29 @@ VRDisplayHost::NotifyVSync()
     VRManager *vm = VRManager::Get();
     MOZ_ASSERT(vm);
     vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
   }
 }
 
 void
 VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, PTextureParent* aTexture,
+                           uint64_t aFrameId,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect)
 {
   AutoProfilerTracing tracing("VR", "SubmitFrameAtVRDisplayHost");
 
   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) {
+  if (!mFrameStarted || aFrameId != mDisplayInfo.mFrameId) {
     return;
   }
   mFrameStarted = false;
 
 #if defined(XP_WIN)
 
   TextureHost* th = TextureHost::AsTextureHost(aTexture);
 
--- a/gfx/vr/VRDisplayHost.h
+++ b/gfx/vr/VRDisplayHost.h
@@ -43,16 +43,17 @@ public:
   virtual void ZeroSensor() = 0;
   virtual void StartPresentation() = 0;
   virtual void StopPresentation() = 0;
   virtual void NotifyVSync();
 
   void StartFrame();
   void SubmitFrame(VRLayerParent* aLayer,
                    mozilla::layers::PTextureParent* aTexture,
+                   uint64_t aFrameId,
                    const gfx::Rect& aLeftEyeRect,
                    const gfx::Rect& aRightEyeRect);
 
   bool CheckClearDisplayInfoDirty();
   void SetGroupMask(uint32_t aGroupMask);
   bool GetIsConnected();
 
 protected:
--- a/gfx/vr/VRDisplayPresentation.cpp
+++ b/gfx/vr/VRDisplayPresentation.cpp
@@ -122,12 +122,12 @@ VRDisplayPresentation::~VRDisplayPresent
 {
   DestroyLayers();
   mDisplayClient->PresentationDestroyed();
 }
 
 void VRDisplayPresentation::SubmitFrame()
 {
   for (VRLayerChild *layer : mLayers) {
-    layer->SubmitFrame();
+    layer->SubmitFrame(mDisplayClient->GetDisplayInfo().GetFrameId());
     break; // Currently only one layer supported, submit only the first
   }
 }
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -340,24 +340,25 @@ VRManager::GetDisplay(const uint32_t& aD
   if (mVRDisplays.Get(aDisplayID, getter_AddRefs(display))) {
     return display;
   }
   return nullptr;
 }
 
 void
 VRManager::SubmitFrame(VRLayerParent* aLayer, layers::PTextureParent* aTexture,
+                       uint64_t aFrameId,
                        const gfx::Rect& aLeftEyeRect,
                        const gfx::Rect& aRightEyeRect)
 {
   TextureHost* th = TextureHost::AsTextureHost(aTexture);
   mLastFrame = th;
   RefPtr<VRDisplayHost> display = GetDisplay(aLayer->GetDisplayID());
   if (display) {
-    display->SubmitFrame(aLayer, aTexture, aLeftEyeRect, aRightEyeRect);
+    display->SubmitFrame(aLayer, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect);
   }
 }
 
 RefPtr<gfx::VRControllerHost>
 VRManager::GetController(const uint32_t& aControllerID)
 {
   RefPtr<gfx::VRControllerHost> controller;
   if (mVRControllers.Get(aControllerID, getter_AddRefs(controller))) {
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -40,16 +40,17 @@ public:
   void RefreshVRControllers();
   void ScanForControllers();
   void RemoveControllers();
   template<class T> void NotifyGamepadChange(uint32_t aIndex, const T& aInfo);
   RefPtr<gfx::VRDisplayHost> GetDisplay(const uint32_t& aDisplayID);
   void GetVRDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayInfo);
 
   void SubmitFrame(VRLayerParent* aLayer, layers::PTextureParent* aTexture,
+                   uint64_t aFrameId,
                    const gfx::Rect& aLeftEyeRect,
                    const gfx::Rect& aRightEyeRect);
   RefPtr<gfx::VRControllerHost> GetController(const uint32_t& aControllerID);
   void GetVRControllerInfo(nsTArray<VRControllerInfo>& aControllerInfo);
   void CreateVRTestSystem();
   void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
                      double aIntensity, double aDuration, uint32_t aPromiseID);
   void StopVibrateHaptic(uint32_t aControllerIdx);
--- a/gfx/vr/ipc/PVRLayer.ipdl
+++ b/gfx/vr/ipc/PVRLayer.ipdl
@@ -11,17 +11,17 @@ include protocol PTexture;
 namespace mozilla {
 namespace gfx {
 
 async protocol PVRLayer
 {
   manager PVRManager;
 
 parent:
-  async SubmitFrame(PTexture aTexture);
+  async SubmitFrame(PTexture aTexture, uint64_t aFrameId);
   async Destroy();
 
 child:
   async __delete__();
 };
 
 } // gfx
 } // mozilla
--- a/gfx/vr/ipc/VRLayerChild.cpp
+++ b/gfx/vr/ipc/VRLayerChild.cpp
@@ -42,17 +42,17 @@ VRLayerChild::Initialize(dom::HTMLCanvas
   mCanvasElement = aCanvasElement;
   mCanvasElement->StartVRPresentation();
 
   VRManagerChild *vrmc = VRManagerChild::Get();
   vrmc->RunFrameRequestCallbacks();
 }
 
 void
-VRLayerChild::SubmitFrame()
+VRLayerChild::SubmitFrame(uint64_t aFrameId)
 {
   if (!mCanvasElement) {
     return;
   }
 
   mShSurfClient = mCanvasElement->GetVRFrame();
   if (!mShSurfClient) {
     return;
@@ -67,17 +67,17 @@ VRLayerChild::SubmitFrame()
   mFront = mShSurfClient;
   mShSurfClient = nullptr;
 
   mFront->SetAddedToCompositableClient();
   VRManagerChild* vrmc = VRManagerChild::Get();
   mFront->SyncWithObject(vrmc->GetSyncObject());
   MOZ_ALWAYS_TRUE(mFront->InitIPDLActor(vrmc));
 
-  SendSubmitFrame(mFront->GetIPDLActor());
+  SendSubmitFrame(mFront->GetIPDLActor(), aFrameId);
 }
 
 bool
 VRLayerChild::IsIPCOpen()
 {
   return mIPCOpen;
 }
 
--- a/gfx/vr/ipc/VRLayerChild.h
+++ b/gfx/vr/ipc/VRLayerChild.h
@@ -31,17 +31,17 @@ namespace gfx {
 class VRLayerChild : public PVRLayerChild {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRLayerChild)
 
 public:
   static PVRLayerChild* CreateIPDLActor();
   static bool DestroyIPDLActor(PVRLayerChild* actor);
 
   void Initialize(dom::HTMLCanvasElement* aCanvasElement);
-  void SubmitFrame();
+  void SubmitFrame(uint64_t aFrameId);
   bool IsIPCOpen();
 
 private:
   VRLayerChild();
   virtual ~VRLayerChild();
   void ClearSurfaces();
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
--- a/gfx/vr/ipc/VRLayerParent.cpp
+++ b/gfx/vr/ipc/VRLayerParent.cpp
@@ -52,21 +52,22 @@ VRLayerParent::Destroy()
   }
 
   if (mIPCOpen) {
     Unused << PVRLayerParent::Send__delete__(this);
   }
 }
 
 mozilla::ipc::IPCResult
-VRLayerParent::RecvSubmitFrame(PTextureParent* texture)
+VRLayerParent::RecvSubmitFrame(PTextureParent* texture,
+                               const uint64_t& aFrameId)
 {
   if (mVRDisplayID) {
     VRManager* vm = VRManager::Get();
-    vm->SubmitFrame(this, texture, mLeftEyeRect, mRightEyeRect);
+    vm->SubmitFrame(this, texture, aFrameId, mLeftEyeRect, mRightEyeRect);
   }
 
   return IPC_OK();
 }
 
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/vr/ipc/VRLayerParent.h
+++ b/gfx/vr/ipc/VRLayerParent.h
@@ -16,17 +16,18 @@ namespace mozilla {
 namespace gfx {
 
 class VRLayerParent : public PVRLayerParent {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRLayerParent)
 
 public:
   VRLayerParent(uint32_t aVRDisplayID, const Rect& aLeftEyeRect,
                 const Rect& aRightEyeRect, const uint32_t aGroup);
-  virtual mozilla::ipc::IPCResult RecvSubmitFrame(PTextureParent* texture) override;
+  virtual mozilla::ipc::IPCResult RecvSubmitFrame(PTextureParent* texture,
+                                                  const uint64_t& aFrameId) override;
   virtual mozilla::ipc::IPCResult RecvDestroy() override;
   uint32_t GetDisplayID() const { return mVRDisplayID; }
   uint32_t GetGroup() const { return mGroup; }
 protected:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   virtual ~VRLayerParent();
   void Destroy();