Bug 1364302 - Fix HoldExternalImage() handling r=nical
authorsotaro <sotaro.ikeda.g@gmail.com>
Mon, 15 May 2017 22:18:54 -0700
changeset 359317 67ca59cd3d03d9ded6dd30c7824572b6f3bb33d1
parent 359316 65542e1d8eaeff390e3481c1fd13e571230acca3
child 359318 4e3d5e3fb742da2ae8b95edc1626307cee1ef1d6
push id31852
push userkwierso@gmail.com
push dateFri, 19 May 2017 21:47:27 +0000
treeherdermozilla-central@979f11deabd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1364302
milestone55.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 1364302 - Fix HoldExternalImage() handling r=nical
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
gfx/layers/wr/WebRenderImageHost.cpp
gfx/layers/wr/WebRenderImageHost.h
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -465,26 +465,24 @@ WebRenderBridgeParent::ProcessWebRenderC
         if (wrTexture) {
           if (wrTexture->IsWrappingNativeHandle()) {
             // XXX only for MacIOSurface right now.
             // XXX remove the redundant codes for both native handle and yuv case.
             wr::ImageDescriptor descriptor(wrTexture->GetSize(), wrTexture->GetReadFormat());
             mApi->AddExternalImageHandle(key,
                                          descriptor,
                                          wrTexture->GetExternalImageKey());
-            mCompositableHolder->HoldExternalImage(mPipelineId, aEpoch, texture->AsWebRenderTextureHost());
           } else {
             // XXX handling YUV
             gfx::SurfaceFormat format =
               wrTexture->GetFormat() == SurfaceFormat::YUV ? SurfaceFormat::B8G8R8A8 : wrTexture->GetFormat();
             wr::ImageDescriptor descriptor(wrTexture->GetSize(), wrTexture->GetRGBStride(), format);
             mApi->AddExternalImageBuffer(key,
                                          descriptor,
                                          wrTexture->GetExternalImageKey());
-            mCompositableHolder->HoldExternalImage(mPipelineId, aEpoch, texture->AsWebRenderTextureHost());
           }
 
           break;
         }
         RefPtr<DataSourceSurface> dSurf = host->GetAsSurface();
         if (!dSurf) {
           break;
         }
@@ -622,17 +620,17 @@ WebRenderBridgeParent::RecvAddExternalIm
   }
   MOZ_ASSERT(host->AsWebRenderImageHost());
   WebRenderImageHost* wrHost = host->AsWebRenderImageHost();
   if (!wrHost) {
     NS_ERROR("Incompatible CompositableHost");
     return IPC_OK();
   }
 
-  wrHost->SetWrCompositableHolder(mCompositableHolder);
+  wrHost->SetWrBridge(this);
   mExternalImageIds.Put(wr::AsUint64(aImageId), wrHost);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvAddExternalImageIdForCompositable(const ExternalImageId& aImageId,
                                                              const CompositableHandle& aHandle)
@@ -645,32 +643,32 @@ WebRenderBridgeParent::RecvAddExternalIm
   RefPtr<CompositableHost> host = FindCompositable(aHandle);
   MOZ_ASSERT(host->AsWebRenderImageHost());
   WebRenderImageHost* wrHost = host->AsWebRenderImageHost();
   if (!wrHost) {
     NS_ERROR("Incompatible CompositableHost");
     return IPC_OK();
   }
 
-  wrHost->SetWrCompositableHolder(mCompositableHolder);
+  wrHost->SetWrBridge(this);
   mExternalImageIds.Put(wr::AsUint64(aImageId), wrHost);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvRemoveExternalImageId(const ExternalImageId& aImageId)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
   MOZ_ASSERT(mExternalImageIds.Get(wr::AsUint64(aImageId)).get());
   WebRenderImageHost* wrHost = mExternalImageIds.Get(wr::AsUint64(aImageId)).get();
   if (wrHost) {
-    wrHost->SetWrCompositableHolder(nullptr);
+    wrHost->SetWrBridge(nullptr);
   }
   mExternalImageIds.Remove(wr::AsUint64(aImageId));
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch)
@@ -873,21 +871,21 @@ WebRenderBridgeParent::ClearResources()
       iter.Remove();
     }
     if (!mKeysToDelete.empty()) {
       // XXX Sync wait.
       mApi->WaitFlushed();
       DeleteOldImages();
     }
   }
-  mCompositableHolder->RemovePipeline(mPipelineId);
   for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
-    iter.Data()->SetWrCompositableHolder(nullptr);
+    iter.Data()->SetWrBridge(nullptr);
   }
   mExternalImageIds.Clear();
+  mCompositableHolder->RemovePipeline(mPipelineId);
 
   if (mWidget && mCompositorScheduler) {
     mCompositorScheduler->Destroy();
   }
   mCompositorScheduler = nullptr;
   mApi = nullptr;
   mCompositorBridge = nullptr;
 }
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -48,16 +48,17 @@ public:
                         const wr::PipelineId& aPipelineId,
                         widget::CompositorWidget* aWidget,
                         CompositorVsyncScheduler* aScheduler,
                         RefPtr<wr::WebRenderAPI>&& aApi,
                         RefPtr<WebRenderCompositableHolder>&& aHolder);
 
   wr::PipelineId PipelineId() { return mPipelineId; }
   wr::WebRenderAPI* GetWebRenderAPI() { return mApi; }
+  wr::Epoch WrEpoch() { return wr::NewEpoch(mWrEpoch); }
   WebRenderCompositableHolder* CompositableHolder() { return mCompositableHolder; }
   CompositorVsyncScheduler* CompositorScheduler() { return mCompositorScheduler.get(); }
 
   mozilla::ipc::IPCResult RecvNewCompositable(const CompositableHandle& aHandle,
                                               const TextureInfo& aInfo) override;
   mozilla::ipc::IPCResult RecvReleaseCompositable(const CompositableHandle& aHandle) override;
 
   mozilla::ipc::IPCResult RecvInitReadLocks(ReadLockArray&& aReadLocks) override;
@@ -166,19 +167,22 @@ public:
   static uint32_t AllocIdNameSpace() {
     return ++sIdNameSpace;
   }
 
 private:
   virtual ~WebRenderBridgeParent();
 
   void DeleteOldImages();
-  void ProcessWebRenderCommands(const gfx::IntSize &aSize, InfallibleTArray<WebRenderParentCommand>& commands, const wr::Epoch& aEpoch,
-                                    const WrSize& aContentSize, const ByteBuffer& dl,
-                                    const WrBuiltDisplayListDescriptor& dlDesc);
+  void ProcessWebRenderCommands(const gfx::IntSize &aSize,
+                                InfallibleTArray<WebRenderParentCommand>& commands,
+                                const wr::Epoch& aEpoch,
+                                const WrSize& aContentSize,
+                                const ByteBuffer& dl,
+                                const WrBuiltDisplayListDescriptor& dlDesc);
   void ScheduleComposition();
   void ClearResources();
   uint64_t GetChildLayerObserverEpoch() const { return mChildLayerObserverEpoch; }
   bool ShouldParentObserveEpoch();
   void HandleDPEnd(const gfx::IntSize& aSize,
                    InfallibleTArray<WebRenderParentCommand>&& aCommands,
                    InfallibleTArray<OpDestroy>&& aToDestroy,
                    const uint64_t& aFwdTransactionId,
--- a/gfx/layers/wr/WebRenderImageHost.cpp
+++ b/gfx/layers/wr/WebRenderImageHost.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebRenderImageHost.h"
 
 #include "LayersLogging.h"
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/Effects.h"     // for TexturedEffect, Effect, etc
 #include "mozilla/layers/LayerManagerComposite.h"     // for TexturedEffect, Effect, etc
+#include "mozilla/layers/WebRenderBridgeParent.h"
 #include "mozilla/layers/WebRenderCompositableHolder.h"
 #include "nsAString.h"
 #include "nsDebug.h"                    // for NS_WARNING, NS_ASSERTION
 #include "nsPrintfCString.h"            // for nsPrintfCString
 #include "nsString.h"                   // for nsAutoCString
 
 namespace mozilla {
 
@@ -21,22 +22,22 @@ using namespace gfx;
 
 namespace layers {
 
 class ISurfaceAllocator;
 
 WebRenderImageHost::WebRenderImageHost(const TextureInfo& aTextureInfo)
   : CompositableHost(aTextureInfo)
   , ImageComposite()
-  , mWrCompositableHolder(nullptr)
+  , mWrBridge(nullptr)
 {}
 
 WebRenderImageHost::~WebRenderImageHost()
 {
-  MOZ_ASSERT(!mWrCompositableHolder);
+  MOZ_ASSERT(!mWrBridge);
 }
 
 void
 WebRenderImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
 {
   CompositableHost::UseTextureHost(aTextures);
   MOZ_ASSERT(aTextures.Length() >= 1);
 
@@ -65,22 +66,23 @@ WebRenderImageHost::UseTextureHost(const
 
   mImages.SwapElements(newImages);
   newImages.Clear();
 
   // Video producers generally send replacement images with the same frameID but
   // slightly different timestamps in order to sync with the audio clock. This
   // means that any CompositeUntil() call we made in Composite() may no longer
   // guarantee that we'll composite until the next frame is ready. Fix that here.
-  if (mWrCompositableHolder && mLastFrameID >= 0) {
+  if (mWrBridge && mLastFrameID >= 0) {
+    MOZ_ASSERT(mWrBridge->CompositableHolder());
     for (size_t i = 0; i < mImages.Length(); ++i) {
       bool frameComesAfter = mImages[i].mFrameID > mLastFrameID ||
                              mImages[i].mProducerID != mLastProducerID;
       if (frameComesAfter && !mImages[i].mTimeStamp.IsNull()) {
-        mWrCompositableHolder->CompositeUntil(mImages[i].mTimeStamp +
+        mWrBridge->CompositableHolder()->CompositeUntil(mImages[i].mTimeStamp +
                            TimeDuration::FromMilliseconds(BIAS_TIME_MS));
         break;
       }
     }
   }
 }
 
 void
@@ -91,16 +93,17 @@ WebRenderImageHost::UseComponentAlphaTex
 }
 
 void
 WebRenderImageHost::CleanupResources()
 {
   nsTArray<TimedImage> newImages;
   mImages.SwapElements(newImages);
   newImages.Clear();
+  SetCurrentTextureHost(nullptr);
 }
 
 void
 WebRenderImageHost::RemoveTextureHost(TextureHost* aTexture)
 {
   CompositableHost::RemoveTextureHost(aTexture);
 
   for (int32_t i = mImages.Length() - 1; i >= 0; --i) {
@@ -110,18 +113,19 @@ WebRenderImageHost::RemoveTextureHost(Te
     }
   }
 }
 
 TimeStamp
 WebRenderImageHost::GetCompositionTime() const
 {
   TimeStamp time;
-  if (mWrCompositableHolder) {
-    time = mWrCompositableHolder->GetCompositionTime();
+  if (mWrBridge) {
+    MOZ_ASSERT(mWrBridge->CompositableHolder());
+    time = mWrBridge->CompositableHolder()->GetCompositionTime();
   }
   return time;
 }
 
 TextureHost*
 WebRenderImageHost::GetAsTextureHost(IntRect* aPictureRect)
 {
   TimedImage* img = ChooseImage();
@@ -131,30 +135,56 @@ WebRenderImageHost::GetAsTextureHost(Int
   return nullptr;
 }
 
 TextureHost*
 WebRenderImageHost::GetAsTextureHostForComposite()
 {
   int imageIndex = ChooseImageIndex();
   if (imageIndex < 0) {
+    SetCurrentTextureHost(nullptr);
     return nullptr;
   }
 
-  if (mWrCompositableHolder && uint32_t(imageIndex) + 1 < mImages.Length()) {
-    mWrCompositableHolder->CompositeUntil(mImages[imageIndex + 1].mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS));
+  if (mWrBridge && uint32_t(imageIndex) + 1 < mImages.Length()) {
+    MOZ_ASSERT(mWrBridge->CompositableHolder());
+    mWrBridge->CompositableHolder()->CompositeUntil(mImages[imageIndex + 1].mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS));
   }
 
   TimedImage* img = &mImages[imageIndex];
 
   if (mLastFrameID != img->mFrameID || mLastProducerID != img->mProducerID) {
     mLastFrameID = img->mFrameID;
     mLastProducerID = img->mProducerID;
   }
-  return img->mTextureHost;
+  SetCurrentTextureHost(img->mTextureHost);
+  return mCurrentTextureHost;
+}
+
+void
+WebRenderImageHost::SetCurrentTextureHost(TextureHost* aTexture)
+{
+  if (aTexture == mCurrentTextureHost.get()) {
+    return;
+  }
+
+  if (mWrBridge &&
+      !!mCurrentTextureHost &&
+      mCurrentTextureHost != aTexture &&
+      mCurrentTextureHost->AsWebRenderTextureHost()) {
+    MOZ_ASSERT(mWrBridge->CompositableHolder());
+    wr::PipelineId piplineId = mWrBridge->PipelineId();
+    wr::Epoch epoch = mWrBridge->WrEpoch();
+    mWrBridge->CompositableHolder()->HoldExternalImage(
+      piplineId,
+      epoch,
+      mCurrentTextureHost->AsWebRenderTextureHost());
+  }
+
+  mCurrentTextureHost = aTexture;
 }
 
 void WebRenderImageHost::Attach(Layer* aLayer,
                        TextureSourceProvider* aProvider,
                        AttachFlags aFlags)
 {
   MOZ_ASSERT_UNREACHABLE("unexpected to be called");
 }
@@ -241,10 +271,17 @@ WebRenderImageHost::GetImageSize() const
 {
   const TimedImage* img = ChooseImage();
   if (img) {
     return IntSize(img->mPictureRect.width, img->mPictureRect.height);
   }
   return IntSize();
 }
 
+void
+WebRenderImageHost::SetWrBridge(WebRenderBridgeParent* aWrBridge)
+{
+  SetCurrentTextureHost(nullptr);
+  mWrBridge = aWrBridge;
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderImageHost.h
+++ b/gfx/layers/wr/WebRenderImageHost.h
@@ -7,17 +7,17 @@
 #define MOZILLA_GFX_WEBRENDERIMAGEHOST_H
 
 #include "CompositableHost.h"           // for CompositableHost
 #include "mozilla/layers/ImageComposite.h"  // for ImageComposite
 
 namespace mozilla {
 namespace layers {
 
-class WebRenderCompositableHolder;
+class WebRenderBridgeParent;
 
 /**
  * ImageHost. Works with ImageClientSingle and ImageClientBuffered
  */
 class WebRenderImageHost : public CompositableHost,
                            public ImageComposite
 {
 public:
@@ -64,24 +64,25 @@ public:
   virtual void Unlock() override;
 
   virtual void CleanupResources() override;
 
   virtual WebRenderImageHost* AsWebRenderImageHost() override { return this; }
 
   TextureHost* GetAsTextureHostForComposite();
 
-  void SetWrCompositableHolder(WebRenderCompositableHolder* aWrCompositableHolder)
-  {
-    mWrCompositableHolder = aWrCompositableHolder;
-  }
+  void SetWrBridge(WebRenderBridgeParent* aWrBridge);
 
 protected:
   // ImageComposite
   virtual TimeStamp GetCompositionTime() const override;
 
-  WebRenderCompositableHolder* MOZ_NON_OWNING_REF mWrCompositableHolder;
+  void SetCurrentTextureHost(TextureHost* aTexture);
+
+  WebRenderBridgeParent* MOZ_NON_OWNING_REF mWrBridge;
+
+  CompositableTextureHostRef mCurrentTextureHost;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // MOZILLA_GFX_WEBRENDERIMAGEHOST_H