Bug 1340359: Use IDXGIKeyedMutex for syncing DXVA D3D11 video textures. r=mattwoodrow
MozReview-Commit-ID: 2EY1Yqql1wU
--- 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