Bug 1364922 - Create individual imageKey for each channel in the textureClient. v2. r=nical
authorJerryShih <hshih@mozilla.com>
Fri, 19 May 2017 00:25:42 +0800
changeset 359349 f5be98afef66e3b83e3e369822b44077cda34afa
parent 359348 6a240376afe79df182fdd7a302f2c1c6eddea6e1
child 359350 9157ff3fa189f74ca96df6661570bdd879b1f979
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
bugs1364922
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 1364922 - Create individual imageKey for each channel in the textureClient. v2. r=nical WebRenderImageLayer will create the proper number of imageKey for different video format. Then, send the imageKey to The WebRenderBridgeParent. MozReview-Commit-ID: HMp4KWCCFqU
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderImageLayer.cpp
gfx/layers/wr/WebRenderImageLayer.h
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -438,51 +438,96 @@ WebRenderBridgeParent::ProcessWebRenderC
 {
   mCompositableHolder->SetCompositionTime(TimeStamp::Now());
 
   for (InfallibleTArray<WebRenderParentCommand>::index_type i = 0; i < aCommands.Length(); ++i) {
     const WebRenderParentCommand& cmd = aCommands[i];
     switch (cmd.type()) {
       case WebRenderParentCommand::TOpAddExternalImage: {
         const OpAddExternalImage& op = cmd.get_OpAddExternalImage();
-        wr::ImageKey key = op.key();
+        Range<const wr::ImageKey> keys(&op.key(), 1);
         MOZ_ASSERT(mExternalImageIds.Get(wr::AsUint64(op.externalImageId())).get());
-        MOZ_ASSERT(!mActiveKeys.Get(wr::AsUint64(key), nullptr));
-        mActiveKeys.Put(wr::AsUint64(key), key);
+        MOZ_ASSERT(!mActiveKeys.Get(wr::AsUint64(keys[0]), nullptr));
+        mActiveKeys.Put(wr::AsUint64(keys[0]), keys[0]);
 
         RefPtr<WebRenderImageHost> host = mExternalImageIds.Get(wr::AsUint64(op.externalImageId()));
         if (!host) {
           NS_ERROR("CompositableHost does not exist");
           break;
         }
         // XXX select Texture for video in CompositeToTarget().
         TextureHost* texture = host->GetAsTextureHostForComposite();
         if (!texture) {
           NS_ERROR("TextureHost does not exist");
           break;
         }
         WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost();
         if (wrTexture) {
-          wrTexture->AddWRImage(mApi, key, wrTexture->GetExternalImageKey());
+          wrTexture->AddWRImage(mApi, keys, wrTexture->GetExternalImageKey());
           break;
         }
         RefPtr<DataSourceSurface> dSurf = host->GetAsSurface();
         if (!dSurf) {
           break;
         }
 
         DataSourceSurface::MappedSurface map;
         if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
           break;
         }
 
         IntSize size = dSurf->GetSize();
         wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
         auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
-        mApi->AddImage(key, descriptor, slice);
+        mApi->AddImage(keys[0], descriptor, slice);
+
+        dSurf->Unmap();
+        break;
+      }
+      case WebRenderParentCommand::TOpAddExternalVideoImage: {
+        const OpAddExternalVideoImage& op = cmd.get_OpAddExternalVideoImage();
+        MOZ_ASSERT(mExternalImageIds.Get(wr::AsUint64(op.externalImageId())).get());
+        MOZ_ASSERT(op.keys().Length() > 0);
+        Range<const wr::ImageKey> keys(&(op.keys())[0], op.keys().Length());
+        for (auto key : keys) {
+          MOZ_ASSERT(!mActiveKeys.Get(wr::AsUint64(key), nullptr));
+          mActiveKeys.Put(wr::AsUint64(key), key);
+        }
+
+        RefPtr<WebRenderImageHost> host = mExternalImageIds.Get(wr::AsUint64(op.externalImageId()));
+        if (!host) {
+          NS_ERROR("CompositableHost does not exist");
+          break;
+        }
+        // XXX select Texture for video in CompositeToTarget().
+        TextureHost* texture = host->GetAsTextureHostForComposite();
+        if (!texture) {
+          NS_ERROR("TextureHost does not exist");
+          break;
+        }
+        WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost();
+        if (wrTexture) {
+          wrTexture->AddWRImage(mApi, keys, wrTexture->GetExternalImageKey());
+          break;
+        }
+
+        MOZ_ASSERT(keys.length() == 1);
+        RefPtr<DataSourceSurface> dSurf = host->GetAsSurface();
+        if (!dSurf) {
+          break;
+        }
+        DataSourceSurface::MappedSurface map;
+        if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
+          break;
+        }
+
+        IntSize size = dSurf->GetSize();
+        wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
+        auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
+        mApi->AddImage(keys[0], descriptor, slice);
 
         dSurf->Unmap();
         break;
       }
       case WebRenderParentCommand::TCompositableOperation: {
         if (!ReceiveCompositableUpdate(cmd.get_CompositableOperation())) {
           NS_ERROR("ReceiveCompositableUpdate failed");
         }
--- a/gfx/layers/wr/WebRenderImageLayer.cpp
+++ b/gfx/layers/wr/WebRenderImageLayer.cpp
@@ -27,19 +27,24 @@ WebRenderImageLayer::WebRenderImageLayer
 {
   MOZ_COUNT_CTOR(WebRenderImageLayer);
 }
 
 WebRenderImageLayer::~WebRenderImageLayer()
 {
   MOZ_COUNT_DTOR(WebRenderImageLayer);
   mPipelineIdRequest.DisconnectIfExists();
+
+  for (auto key : mVideoKeys) {
+    WrManager()->AddImageKeyForDiscard(key);
+  }
   if (mKey.isSome()) {
     WrManager()->AddImageKeyForDiscard(mKey.value());
   }
+
   if (mExternalImageId.isSome()) {
     WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
   }
 }
 
 CompositableType
 WebRenderImageLayer::GetImageClientType()
 {
@@ -81,16 +86,27 @@ void
 WebRenderImageLayer::ClearCachedResources()
 {
   if (mImageClient) {
     mImageClient->ClearCachedResources();
   }
 }
 
 void
+WebRenderImageLayer::AddWRVideoImage(size_t aChannelNumber)
+{
+  for (size_t i = 0; i < aChannelNumber; ++i) {
+    WrImageKey key = GetImageKey();
+    WrManager()->AddImageKeyForDiscard(key);
+    mVideoKeys.AppendElement(key);
+  }
+  WrBridge()->AddWebRenderParentCommand(OpAddExternalVideoImage(mExternalImageId.value(), mVideoKeys));
+}
+
+void
 WebRenderImageLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
                                  const StackingContextHelper& aSc)
 {
   if (!mContainer) {
      return;
   }
 
   CompositableType type = GetImageClientType();
@@ -143,33 +159,50 @@ WebRenderImageLayer::RenderLayer(wr::Dis
   // XXX Not good for async ImageContainer case.
   AutoLockImage autoLock(mContainer);
   Image* image = autoLock.GetImage();
   if (!image) {
     return;
   }
   gfx::IntSize size = image->GetSize();
 
-  if (GetImageClientType() == CompositableType::IMAGE_BRIDGE) {
-    // Always allocate key
-    WrImageKey key = GetImageKey();
-    WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId.value(), key));
-    WrManager()->AddImageKeyForDiscard(key);
-    mKey = Some(key);
-  } else {
+  if (GetImageClientType() != CompositableType::IMAGE_BRIDGE) {
     // Handle CompositableType::IMAGE case
     MOZ_ASSERT(mImageClient->AsImageClientSingle());
     mKey = UpdateImageKey(mImageClient->AsImageClientSingle(),
                           mContainer,
                           mKey,
                           mExternalImageId.ref());
-  }
+    if (mKey.isNothing()) {
+      return;
+    }
+  } else {
+    // Always allocate key.
+    mVideoKeys.Clear();
 
-  if (mKey.isNothing()) {
-    return;
+    // XXX (Jerry): Remove the hardcode image format setting.
+#if defined(XP_WIN)
+    // Use libyuv to convert the buffer to rgba format. So, use 1 image key here.
+    AddWRVideoImage(1);
+#elif defined(XP_MACOSX)
+    if (gfx::gfxVars::CanUseHardwareVideoDecoding()) {
+      // Use the hardware MacIOSurface with YCbCr interleaved format. It uses 1
+      // image key.
+      AddWRVideoImage(1);
+    } else {
+      // Use libyuv.
+      AddWRVideoImage(1);
+    }
+#elif defined(MOZ_WIDGET_GTK)
+    // Use libyuv.
+    AddWRVideoImage(1);
+#elif defined(ANDROID)
+    // Use libyuv.
+    AddWRVideoImage(1);
+#endif
   }
 
   ScrollingLayersHelper scroller(this, aBuilder, aSc);
   StackingContextHelper sc(aSc, aBuilder, this);
 
   LayerRect rect(0, 0, size.width, size.height);
   if (mScaleMode != ScaleMode::SCALE_NONE) {
     NS_ASSERTION(mScaleMode == ScaleMode::STRETCH,
@@ -195,31 +228,36 @@ WebRenderImageLayer::RenderLayer(wr::Dis
   if (GetImageClientType() != CompositableType::IMAGE_BRIDGE) {
     aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mKey.value());
   } else {
     // XXX (Jerry): Remove the hardcode image format setting. The format of
     // textureClient could change from time to time. So, we just set the most
     // usable format here.
 #if defined(XP_WIN)
     // Use libyuv to convert the buffer to rgba format.
-    aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mKey.value());
+    MOZ_ASSERT(mVideoKeys.Length() == 1);
+    aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mVideoKeys[0]);
 #elif defined(XP_MACOSX)
     if (gfx::gfxVars::CanUseHardwareVideoDecoding()) {
       // Use the hardware MacIOSurface with YCbCr interleaved format.
-      aBuilder.PushYCbCrInterleavedImage(sc.ToRelativeWrRect(rect), clip, mKey.value(), WrYuvColorSpace::Rec601);
+      MOZ_ASSERT(mVideoKeys.Length() == 1);
+      aBuilder.PushYCbCrInterleavedImage(sc.ToRelativeWrRect(rect), clip, mVideoKeys[0], WrYuvColorSpace::Rec601);
     } else {
       // Use libyuv to convert the buffer to rgba format.
-      aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mKey.value());
+      MOZ_ASSERT(mVideoKeys.Length() == 1);
+      aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mVideoKeys[0]);
     }
 #elif defined(MOZ_WIDGET_GTK)
     // Use libyuv to convert the buffer to rgba format.
-    aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mKey.value());
+    MOZ_ASSERT(mVideoKeys.Length() == 1);
+    aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mVideoKeys[0]);
 #elif defined(ANDROID)
     // Use libyuv to convert the buffer to rgba format.
-    aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mKey.value());
+    MOZ_ASSERT(mVideoKeys.Length() == 1);
+    aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, filter, mVideoKeys[0]);
 #endif
   }
 }
 
 Maybe<WrImageMask>
 WebRenderImageLayer::RenderMaskLayer(const gfx::Matrix4x4& aTransform)
 {
   if (!mContainer) {
--- a/gfx/layers/wr/WebRenderImageLayer.h
+++ b/gfx/layers/wr/WebRenderImageLayer.h
@@ -31,27 +31,32 @@ public:
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
                    const StackingContextHelper& aSc) override;
   Maybe<WrImageMask> RenderMaskLayer(const gfx::Matrix4x4& aTransform) override;
 
 protected:
   CompositableType GetImageClientType();
 
+  void AddWRVideoImage(size_t aChannelNumber);
+
   class Holder {
   public:
     explicit Holder(WebRenderImageLayer* aLayer)
       : mLayer(aLayer)
     {}
     WebRenderImageLayer* operator ->() const { return mLayer; }
   private:
     WebRenderImageLayer* mLayer;
   };
 
   wr::MaybeExternalImageId mExternalImageId;
+  // Some video image format contains multiple channel data.
+  nsTArray<wr::ImageKey> mVideoKeys;
+  // The regular single channel image.
   Maybe<wr::ImageKey> mKey;
   RefPtr<ImageClient> mImageClient;
   CompositableType mImageClientTypeContainer;
   Maybe<wr::PipelineId> mPipelineId;
   MozPromiseRequestHolder<PipelineIdPromise> mPipelineIdRequest;
 };
 
 } // namespace layers