Bug 1340359: Use IDXGIKeyedMutex for syncing DXVA D3D11 video textures. r=mattwoodrow draft
authorBas Schouten <bschouten@mozilla.com>
Fri, 17 Feb 2017 22:23:51 +0000
changeset 486430 c73004a90e2998c1e58537b9f2a34b99776edbed
parent 484686 828c1f39d71afcf09f04d624c67fb58e50991f3b
child 546235 3589b8d23ac4ab9ec7a719040628e6561c9ca90c
push id45973
push userbschouten@mozilla.com
push dateFri, 17 Feb 2017 22:25:16 +0000
reviewersmattwoodrow
bugs1340359
milestone54.0a1
Bug 1340359: Use IDXGIKeyedMutex for syncing DXVA D3D11 video textures. r=mattwoodrow MozReview-Commit-ID: 2EY1Yqql1wU
dom/media/platforms/wmf/DXVA2Manager.cpp
gfx/layers/D3D11ShareHandleImage.cpp
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -624,17 +624,16 @@ private:
   already_AddRefed<ID3D11VideoDecoder>
   CreateDecoder(const D3D11_VIDEO_DECODER_DESC& aDesc) const;
 
   RefPtr<ID3D11Device> mDevice;
   RefPtr<ID3D11DeviceContext> mContext;
   RefPtr<IMFDXGIDeviceManager> mDXGIDeviceManager;
   RefPtr<MFTDecoder> mTransform;
   RefPtr<D3D11RecycleAllocator> mTextureClientAllocator;
-  RefPtr<ID3D11Texture2D> mSyncSurface;
   RefPtr<ID3D11VideoDecoder> mDecoder;
   GUID mDecoderGUID;
   uint32_t mWidth = 0;
   uint32_t mHeight = 0;
   UINT mDeviceManagerToken = 0;
 };
 
 bool
@@ -786,32 +785,16 @@ D3D11DXVA2Manager::Init(layers::KnowsCom
     for (const auto& model : sAMDPreUVD4) {
       if (adapterDesc.DeviceId == model) {
         mIsAMDPreUVD4 = true;
         break;
       }
     }
   }
 
-  D3D11_TEXTURE2D_DESC desc;
-  desc.Width = kSyncSurfaceSize;
-  desc.Height = kSyncSurfaceSize;
-  desc.MipLevels = 1;
-  desc.ArraySize = 1;
-  desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
-  desc.SampleDesc.Count = 1;
-  desc.SampleDesc.Quality = 0;
-  desc.Usage = D3D11_USAGE_STAGING;
-  desc.BindFlags = 0;
-  desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
-  desc.MiscFlags = 0;
-
-  hr = mDevice->CreateTexture2D(&desc, NULL, getter_AddRefs(mSyncSurface));
-  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-
   if (layers::ImageBridgeChild::GetSingleton()) {
     // There's no proper KnowsCompositor for ImageBridge currently (and it
     // implements the interface), so just use that if it's available.
     mTextureClientAllocator = new D3D11RecycleAllocator(
       layers::ImageBridgeChild::GetSingleton().get(), mDevice);
   } else {
     mTextureClientAllocator =
       new D3D11RecycleAllocator(aKnowsCompositor, mDevice);
@@ -860,36 +843,28 @@ D3D11DXVA2Manager::CopyToImage(IMFSample
   RefPtr<D3D11ShareHandleImage> image =
     new D3D11ShareHandleImage(gfx::IntSize(mWidth, mHeight), aRegion);
   bool ok = image->AllocateTexture(mTextureClientAllocator, mDevice);
   NS_ENSURE_TRUE(ok, E_FAIL);
 
   HRESULT hr = mTransform->Input(aVideoSample);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
+  RefPtr<IDXGIKeyedMutex> mutex;
   RefPtr<IMFSample> sample;
   RefPtr<ID3D11Texture2D> texture = image->GetTexture();
+
+  texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
+
+  mutex->AcquireSync(0, INFINITE);
   hr = CreateOutputSample(sample, texture);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   hr = mTransform->Output(&sample);
-
-  RefPtr<ID3D11DeviceContext> ctx;
-  mDevice->GetImmediateContext(getter_AddRefs(ctx));
-
-  // Copy a small rect into our sync surface, and then map it
-  // to block until decoding/color conversion completes.
-  D3D11_BOX rect = { 0, 0, 0, kSyncSurfaceSize, kSyncSurfaceSize, 1 };
-  ctx->CopySubresourceRegion(mSyncSurface, 0, 0, 0, 0, texture, 0, &rect);
-
-  D3D11_MAPPED_SUBRESOURCE mapped;
-  hr = ctx->Map(mSyncSurface, 0, D3D11_MAP_READ, 0, &mapped);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-
-  ctx->Unmap(mSyncSurface, 0);
+  mutex->ReleaseSync(0);
 
   image.forget(aOutImage);
 
   return S_OK;
 }
 
 HRESULT ConfigureOutput(IMFMediaType* aOutput, void* aData)
 {
--- a/gfx/layers/D3D11ShareHandleImage.cpp
+++ b/gfx/layers/D3D11ShareHandleImage.cpp
@@ -91,17 +91,26 @@ D3D11ShareHandleImage::GetAsSourceSurfac
   }
 
   RefPtr<ID3D11DeviceContext> context;
   device->GetImmediateContext(getter_AddRefs(context));
   if (!context) {
     return nullptr;
   }
 
+  RefPtr<IDXGIKeyedMutex> mutex;
+  hr = texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
+
+  if (SUCCEEDED(hr) && mutex) {
+    mutex->AcquireSync(0, INFINITE);
+  }
   context->CopyResource(softTexture, texture);
+  if (SUCCEEDED(hr) && mutex) {
+    mutex->ReleaseSync(0);
+  }
 
   RefPtr<gfx::DataSourceSurface> surface =
     gfx::Factory::CreateDataSourceSurface(mSize, gfx::SurfaceFormat::B8G8R8A8);
   if (NS_WARN_IF(!surface)) {
     return nullptr;
   }
 
   gfx::DataSourceSurface::MappedSurface mappedSurface;
@@ -149,15 +158,15 @@ already_AddRefed<TextureClient>
 D3D11RecycleAllocator::CreateOrRecycleClient(gfx::SurfaceFormat aFormat,
                                              const gfx::IntSize& aSize)
 {
   RefPtr<TextureClient> textureClient =
     CreateOrRecycle(aFormat,
                     aSize,
                     BackendSelector::Content,
                     layers::TextureFlags::DEFAULT,
-                    TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION);
+                    TextureAllocationFlags::ALLOC_DEFAULT);
   return textureClient.forget();
 }
 
 
 } // namespace layers
 } // namespace mozilla