Bug 1298058 - Use different lock/unlock function for WebVR composition path. r=milan
authorJerryShih <hshih@mozilla.com>
Mon, 05 Sep 2016 01:17:00 -0400
changeset 356286 d64ac5fa891449482807c9399b4bac86372b8e9d
parent 356285 8e8e90b93acf4759ac9f0cd2a0354f935841fa3a
child 356287 b00b37cb64ef7088a7fd83f59d9974dee2b29caf
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmilan
bugs1298058
milestone51.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 1298058 - Use different lock/unlock function for WebVR composition path. r=milan
gfx/layers/composite/TextureHost.h
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
gfx/vr/VRDisplayHost.cpp
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -389,21 +389,30 @@ public:
     ISurfaceAllocator* aDeallocator,
     LayersBackend aBackend,
     TextureFlags aFlags);
 
   /**
    * Lock the texture host for compositing.
    */
   virtual bool Lock() { return true; }
+  /**
+   * Unlock the texture host after compositing. Lock() and Unlock() should be
+   * called in pair.
+   */
+  virtual void Unlock() {}
 
   /**
-   * Unlock the texture host after compositing.
+   * Lock the texture host for compositing without using compositor.
    */
-  virtual void Unlock() {}
+  virtual bool LockWithoutCompositor() { return true; }
+  /**
+   * Similar to Unlock(), but it should be called with LockWithoutCompositor().
+   */
+  virtual void UnlockWithoutCompositor() {}
 
   /**
    * Note that the texture host format can be different from its corresponding
    * texture source's. For example a ShmemTextureHost can have the ycbcr
    * format and produce 3 "alpha" textures sources.
    */
   virtual gfx::SurfaceFormat GetFormat() const = 0;
   /**
@@ -806,16 +815,39 @@ public:
 
   bool Failed() { return mTexture && !mLocked; }
 
 private:
   RefPtr<TextureHost> mTexture;
   bool mLocked;
 };
 
+class MOZ_STACK_CLASS AutoLockTextureHostWithoutCompositor
+{
+public:
+  explicit AutoLockTextureHostWithoutCompositor(TextureHost* aTexture)
+    : mTexture(aTexture)
+  {
+    mLocked = mTexture ? mTexture->LockWithoutCompositor() : false;
+  }
+
+  ~AutoLockTextureHostWithoutCompositor()
+  {
+    if (mTexture && mLocked) {
+      mTexture->UnlockWithoutCompositor();
+    }
+  }
+
+  bool Failed() { return mTexture && !mLocked; }
+
+private:
+  RefPtr<TextureHost> mTexture;
+  bool mLocked;
+};
+
 /**
  * This can be used as an offscreen rendering target by the compositor, and
  * subsequently can be used as a source by the compositor.
  */
 class CompositingRenderTarget: public TextureSource
 {
 public:
 
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -728,21 +728,50 @@ Compositor*
 DXGITextureHostD3D11::GetCompositor()
 {
   return mCompositor;
 }
 
 bool
 DXGITextureHostD3D11::Lock()
 {
-  /**
-   * Note: This function may be called when mCompositor is null
-   *       such as during WebVR frame submission.
-   **/
+  if (!mCompositor) {
+    // Make an early return here if we call SetCompositor() with an incompatible
+    // compositor. This check tries to prevent the problem where we use that
+    // incompatible compositor to compose this texture.
+    return false;
+  }
+
+  return LockInternal();
+}
 
+bool
+DXGITextureHostD3D11::LockWithoutCompositor()
+{
+  // Unlike the normal Lock() function, this function may be called when
+  // mCompositor is nullptr such as during WebVR frame submission. So, there is
+  // no 'mCompositor' checking here.
+  return LockInternal();
+}
+
+void
+DXGITextureHostD3D11::Unlock()
+{
+  UnlockInternal();
+}
+
+void
+DXGITextureHostD3D11::UnlockWithoutCompositor()
+{
+  UnlockInternal();
+}
+
+bool
+DXGITextureHostD3D11::LockInternal()
+{
   if (!GetDevice()) {
     NS_WARNING("trying to lock a TextureHost without a D3D device");
     return false;
   }
 
   if (!mTextureSource) {
     if (!mTexture && !OpenSharedHandle()) {
       gfxWindowsPlatform::GetPlatform()->ForceDeviceReset(ForcedDeviceResetReason::OPENSHAREDHANDLE);
@@ -753,17 +782,17 @@ DXGITextureHostD3D11::Lock()
   }
 
   mIsLocked = LockD3DTexture(mTextureSource->GetD3D11Texture());
 
   return mIsLocked;
 }
 
 void
-DXGITextureHostD3D11::Unlock()
+DXGITextureHostD3D11::UnlockInternal()
 {
   UnlockD3DTexture(mTextureSource->GetD3D11Texture());
 }
 
 bool
 DXGITextureHostD3D11::BindTextureSource(CompositableTextureSourceRef& aTexture)
 {
   MOZ_ASSERT(mIsLocked);
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -291,27 +291,32 @@ public:
 
   virtual void SetCompositor(Compositor* aCompositor) override;
 
   virtual Compositor* GetCompositor() override;
 
   virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
 
   virtual bool Lock() override;
+  virtual void Unlock() override;
 
-  virtual void Unlock() override;
+  virtual bool LockWithoutCompositor() override;
+  virtual void UnlockWithoutCompositor() override;
 
   virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
   {
     return nullptr;
   }
 
 protected:
+  bool LockInternal();
+  void UnlockInternal();
+
   RefPtr<ID3D11Device> GetDevice();
 
   bool OpenSharedHandle();
 
   RefPtr<ID3D11Texture2D> mTexture;
   RefPtr<DataTextureSourceD3D11> mTextureSource;
   RefPtr<CompositorD3D11> mCompositor;
   gfx::IntSize mSize;
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -78,17 +78,19 @@ VRDisplayHost::SubmitFrame(VRLayerParent
   // It is possible to get a cache miss on mLastSensorState if latency is
   // longer than kMaxLatencyFrames.  An optimization would be to find a frame
   // that is closer than the one selected with the modulus.
   // If we hit this; however, latency is already so high that the site is
   // un-viewable and a more accurate pose prediction is not likely to
   // compensate.
 
   TextureHost* th = TextureHost::AsTextureHost(aTexture);
-  AutoLockTextureHost autoLock(th);
+  // 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;
   }
 
   CompositableTextureSourceRef source;
   if (!th->BindTextureSource(source)) {
     NS_WARNING("The TextureHost was successfully locked but can't provide a TextureSource");