Bug 1322746 - Expose DXGI HANDLEs for GPU_VIDEO. - r=mattwoodrow draft
authorJeff Gilbert <jgilbert@mozilla.com>
Tue, 11 Apr 2017 22:58:47 -0700
changeset 656200 ac5d7eaaa8e219c74232beb4319f2d22fb456cf1
parent 655774 ab2d700fda2b4934d24227216972dce9fac19b74
child 656201 3f8b8603ed7908a4855280f38afb04b4717b6528
push id77113
push userbmo:jgilbert@mozilla.com
push dateWed, 30 Aug 2017 20:41:02 +0000
reviewersmattwoodrow
bugs1322746
milestone57.0a1
Bug 1322746 - Expose DXGI HANDLEs for GPU_VIDEO. - r=mattwoodrow MozReview-Commit-ID: Aea0xGesaQi
dom/media/ipc/VideoDecoderManagerParent.cpp
dom/media/ipc/VideoDecoderParent.cpp
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
gfx/layers/ipc/LayersSurfaces.ipdlh
--- a/dom/media/ipc/VideoDecoderManagerParent.cpp
+++ b/dom/media/ipc/VideoDecoderManagerParent.cpp
@@ -28,19 +28,22 @@ namespace dom {
 
 using namespace ipc;
 using namespace layers;
 using namespace gfx;
 
 SurfaceDescriptorGPUVideo
 VideoDecoderManagerParent::StoreImage(Image* aImage, TextureClient* aTexture)
 {
-  mImageMap[aTexture->GetSerial()] = aImage;
-  mTextureMap[aTexture->GetSerial()] = aTexture;
-  return SurfaceDescriptorGPUVideo(aTexture->GetSerial());
+  SurfaceDescriptorGPUVideo ret;
+  aTexture->GPUVideoDesc(&ret);
+
+  mImageMap[ret.handle()] = aImage;
+  mTextureMap[ret.handle()] = aTexture;
+  return Move(ret);
 }
 
 StaticRefPtr<nsIThread> sVideoDecoderManagerThread;
 StaticRefPtr<TaskQueue> sManagerTaskQueue;
 
 class VideoDecoderManagerThreadHolder
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderManagerThreadHolder)
--- a/dom/media/ipc/VideoDecoderParent.cpp
+++ b/dom/media/ipc/VideoDecoderParent.cpp
@@ -194,17 +194,17 @@ VideoDecoderParent::ProcessDecodedData(
     VideoDataIPDL output(
       MediaDataIPDL(data->mOffset, data->mTime.ToMicroseconds(),
                     data->mTimecode.ToMicroseconds(),
                     data->mDuration.ToMicroseconds(),
                     data->mFrames, data->mKeyframe),
       video->mDisplay,
       texture ? texture->GetSize() : IntSize(),
       texture ? mParent->StoreImage(video->mImage, texture)
-              : SurfaceDescriptorGPUVideo(0),
+              : SurfaceDescriptorGPUVideo(0, null_t()),
       video->mFrameID);
     Unused << SendOutput(output);
   }
 }
 
 mozilla::ipc::IPCResult
 VideoDecoderParent::RecvFlush()
 {
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -157,17 +157,17 @@ private:
   // The locking pattern of TextureClient may in some case upset deadlock detection
   // tools such as TSan.
   // Typically our tile rendering code will lock all of its tiles, render into them
   // and unlock them all right after that, which looks something like:
   //
   // Lock tile A
   // Lock tile B
   // Lock tile C
-  // Apply drawing commands to tiles A, B and C 
+  // Apply drawing commands to tiles A, B and C
   // Unlock tile A
   // Unlock tile B
   // Unlock tile C
   //
   // And later, we may end up rendering a tile buffer that has the same tiles,
   // in a different order, for example:
   //
   // Lock tile B
@@ -1397,16 +1397,28 @@ TextureClient::PrintInfo(std::stringstre
     RefPtr<gfx::DataSourceSurface> dSurf = GetAsSurface();
     if (dSurf) {
       aStream << gfxUtils::GetAsLZ4Base64Str(dSurf).get();
     }
   }
 #endif
 }
 
+void
+TextureClient::GPUVideoDesc(SurfaceDescriptorGPUVideo* const aOutDesc)
+{
+  const auto handle = GetSerial();
+
+  GPUVideoSubDescriptor subDesc = null_t();
+  MOZ_RELEASE_ASSERT(mData);
+  mData->GetSubDescriptor(&subDesc);
+
+  *aOutDesc = SurfaceDescriptorGPUVideo(handle, Move(subDesc));
+}
+
 class MemoryTextureReadLock : public NonBlockingTextureReadLock {
 public:
   MemoryTextureReadLock();
 
   ~MemoryTextureReadLock();
 
   virtual bool ReadLock() override;
 
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -261,16 +261,17 @@ public:
   virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; }
 
   virtual void Deallocate(LayersIPCChannel* aAllocator) = 0;
 
   /// Depending on the texture's flags either Deallocate or Forget is called.
   virtual void Forget(LayersIPCChannel* aAllocator) {}
 
   virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0;
+  virtual void GetSubDescriptor(GPUVideoSubDescriptor* aOutDesc) { }
 
   virtual TextureData*
   CreateSimilar(LayersIPCChannel* aAllocator,
                 LayersBackend aLayersBackend,
                 TextureFlags aFlags = TextureFlags::DEFAULT,
                 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const { return nullptr; }
 
   virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) { return false; };
@@ -593,22 +594,23 @@ public:
   ITextureClientRecycleAllocator* GetRecycleAllocator() { return mRecycleAllocator; }
   void SetRecycleAllocator(ITextureClientRecycleAllocator* aAllocator);
 
   /// If you add new code that uses this method, you are probably doing something wrong.
   TextureData* GetInternalData() { return mData; }
   const TextureData* GetInternalData() const { return mData; }
 
   uint64_t GetSerial() const { return mSerial; }
+  void GPUVideoDesc(SurfaceDescriptorGPUVideo* aOutDesc);
 
   void CancelWaitForRecycle();
 
   /**
    * Set last transaction id of CompositableForwarder.
-   * 
+   *
    * Called when TextureClient has TextureFlags::RECYCLE flag.
    * When CompositableForwarder forwards the TextureClient with
    * TextureFlags::RECYCLE, it holds TextureClient's ref until host side
    * releases it. The host side sends TextureClient release message.
    * The id is used to check if the message is for the last TextureClient
    * forwarding.
    */
   void SetLastFwdTransactionId(uint64_t aTransactionId)
@@ -637,32 +639,32 @@ public:
   void AddPaintThreadRef();
 
   // Mark that the TextureClient is no longer in use by the PaintThread. This
   // must only be called from the PaintThread.
   void DropPaintThreadRef();
 
 private:
   static void TextureClientRecycleCallback(TextureClient* aClient, void* aClosure);
- 
+
   // Internal helpers for creating texture clients using the actual forwarder instead
   // of KnowsCompositor. TextureClientPool uses these to let it cache texture clients
   // per-process instead of per ShadowLayerForwarder, but everyone else should
   // use the public functions instead.
   friend class TextureClientPool;
   static already_AddRefed<TextureClient>
   CreateForDrawing(TextureForwarder* aAllocator,
                    gfx::SurfaceFormat aFormat,
                    gfx::IntSize aSize,
                    LayersBackend aLayersBackend,
                    int32_t aMaxTextureSize,
                    BackendSelector aSelector,
                    TextureFlags aTextureFlags,
                    TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT);
-  
+
   static already_AddRefed<TextureClient>
   CreateForRawBufferAccess(LayersIPCChannel* aAllocator,
                            gfx::SurfaceFormat aFormat,
                            gfx::IntSize aSize,
                            gfx::BackendType aMoz2dBackend,
                            LayersBackend aLayersBackend,
                            TextureFlags aTextureFlags,
                            TextureAllocationFlags flags = ALLOC_DEFAULT);
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -368,34 +368,55 @@ D3D11TextureData::SyncWithObject(SyncObj
   }
 
   MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObjectClient::SyncType::D3D11);
   SyncObjectD3D11Client* sync = static_cast<SyncObjectD3D11Client*>(aSyncObject);
   sync->RegisterTexture(mTexture);
 }
 
 bool
-DXGITextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
+DXGITextureData::SerializeSpecific(SurfaceDescriptorD3D10* const aOutDesc)
 {
   RefPtr<IDXGIResource> resource;
   GetDXGIResource((IDXGIResource**)getter_AddRefs(resource));
   if (!resource) {
     return false;
   }
   HANDLE sharedHandle;
   HRESULT hr = resource->GetSharedHandle(&sharedHandle);
   if (FAILED(hr)) {
     LOGD3D11("Error getting shared handle for texture.");
     return false;
   }
 
-  aOutDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mFormat, mSize);
+  *aOutDesc = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mFormat, mSize);
   return true;
 }
 
+bool
+DXGITextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
+{
+  SurfaceDescriptorD3D10 desc;
+  if (!SerializeSpecific(&desc))
+    return false;
+
+  aOutDescriptor = Move(desc);
+  return true;
+}
+
+void
+DXGITextureData::GetSubDescriptor(GPUVideoSubDescriptor* const aOutDesc)
+{
+  SurfaceDescriptorD3D10 ret;
+  if (!SerializeSpecific(&ret))
+    return;
+
+  *aOutDesc = Move(ret);
+}
+
 DXGITextureData*
 DXGITextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocationFlags aFlags)
 {
   if (aFormat == SurfaceFormat::A8) {
     // Currently we don't support A8 surfaces. Fallback.
     return nullptr;
   }
 
@@ -654,27 +675,45 @@ DXGIYCbCrTextureData::FillInfo(TextureDa
 {
   aInfo.size = mSize;
   aInfo.format = gfx::SurfaceFormat::YUV;
   aInfo.supportsMoz2D = false;
   aInfo.hasIntermediateBuffer = false;
   aInfo.hasSynchronization = false;
 }
 
+void
+DXGIYCbCrTextureData::SerializeSpecific(SurfaceDescriptorDXGIYCbCr* const aOutDesc)
+{
+  *aOutDesc = SurfaceDescriptorDXGIYCbCr(
+    (WindowsHandle)mHandles[0], (WindowsHandle)mHandles[1], (WindowsHandle)mHandles[2],
+    mSize, mSizeY, mSizeCbCr
+  );
+}
+
 bool
 DXGIYCbCrTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
 {
-  aOutDescriptor = SurfaceDescriptorDXGIYCbCr(
-    (WindowsHandle)mHandles[0], (WindowsHandle)mHandles[1], (WindowsHandle)mHandles[2],
-    mSize, mSizeY, mSizeCbCr
-  );
+  SurfaceDescriptorDXGIYCbCr desc;
+  SerializeSpecific(&desc);
+
+  aOutDescriptor = Move(desc);
   return true;
 }
 
 void
+DXGIYCbCrTextureData::GetSubDescriptor(GPUVideoSubDescriptor* const aOutDesc)
+{
+  SurfaceDescriptorDXGIYCbCr desc;
+  SerializeSpecific(&desc);
+
+  *aOutDesc = Move(desc);
+}
+
+void
 DXGIYCbCrTextureData::Deallocate(LayersIPCChannel*)
 {
   mD3D9Textures[0] = nullptr;
   mD3D9Textures[1] = nullptr;
   mD3D9Textures[2] = nullptr;
   mD3D11Textures[0] = nullptr;
   mD3D11Textures[1] = nullptr;
   mD3D11Textures[2] = nullptr;
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -34,17 +34,19 @@ private:
 
 class CompositorD3D11;
 
 class DXGITextureData : public TextureData
 {
 public:
   virtual void FillInfo(TextureData::Info& aInfo) const override;
 
+  bool SerializeSpecific(SurfaceDescriptorD3D10* aOutDesc);
   virtual bool Serialize(SurfaceDescriptor& aOutDescrptor) override;
+  virtual void GetSubDescriptor(GPUVideoSubDescriptor* aOutDesc) override;
 
   static DXGITextureData*
   Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aFlags);
 
 protected:
   bool PrepareDrawTargetInLock(OpenMode aMode);
 
   DXGITextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
@@ -147,17 +149,19 @@ public:
          const gfx::IntSize& aSizeCbCr);
 
   virtual bool Lock(OpenMode) override { return true; }
 
   virtual void Unlock() override {}
 
   virtual void FillInfo(TextureData::Info& aInfo) const override;
 
+  void SerializeSpecific(SurfaceDescriptorDXGIYCbCr* aOutDesc);
   virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
+  virtual void GetSubDescriptor(GPUVideoSubDescriptor* aOutDesc) override;
 
   virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override { return nullptr; }
 
   virtual void Deallocate(LayersIPCChannel* aAllocator) override;
 
   virtual bool UpdateFromSurface(gfx::SourceSurface*) override { return false; }
 
   virtual TextureFlags GetTextureFlags() const override
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -75,18 +75,26 @@ struct EGLImageDescriptor {
 struct SurfaceDescriptorSharedGLTexture {
   uint32_t texture;
   uint32_t target;
   uintptr_t fence;
   IntSize size;
   bool hasAlpha;
 };
 
+
+union GPUVideoSubDescriptor {
+  SurfaceDescriptorD3D10;
+  SurfaceDescriptorDXGIYCbCr;
+  null_t;
+};
+
 struct SurfaceDescriptorGPUVideo {
   uint64_t handle;
+  GPUVideoSubDescriptor desc;
 };
 
 struct RGBDescriptor {
   IntSize size;
   SurfaceFormat format;
   bool hasIntermediateBuffer;
 };