Bug 1257013 - Part 2: Use readback to synchronize d3d11 video. r=cpearce, r=Bas

This commit is contained in:
Matt Woodrow 2016-03-21 18:49:59 +13:00
parent a4e47cb2a8
commit bb3b79e71e
5 changed files with 40 additions and 25 deletions

View File

@ -523,6 +523,7 @@ private:
RefPtr<IMFDXGIDeviceManager> mDXGIDeviceManager;
RefPtr<MFTDecoder> mTransform;
RefPtr<D3D11RecycleAllocator> mTextureClientAllocator;
RefPtr<ID3D11Texture2D> mSyncSurface;
GUID mDecoderGUID;
uint32_t mWidth;
uint32_t mHeight;
@ -702,6 +703,22 @@ D3D11DXVA2Manager::Init(nsACString& aFailureReason)
}
}
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);
mTextureClientAllocator = new D3D11RecycleAllocator(layers::ImageBridgeChild::GetSingleton(),
mDevice);
mTextureClientAllocator->SetMaxPoolSize(5);
@ -753,18 +770,22 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
hr = CreateOutputSample(sample, texture);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
RefPtr<IDXGIKeyedMutex> keyedMutex;
hr = texture->QueryInterface(static_cast<IDXGIKeyedMutex**>(getter_AddRefs(keyedMutex)));
NS_ENSURE_TRUE(SUCCEEDED(hr) && keyedMutex, hr);
hr = keyedMutex->AcquireSync(0, INFINITE);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
hr = mTransform->Output(&sample);
keyedMutex->ReleaseSync(0);
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);
image.forget(aOutImage);
return S_OK;

View File

@ -55,17 +55,6 @@ D3D11ShareHandleImage::GetAsSourceSurface()
RefPtr<ID3D11Device> device;
texture->GetDevice(getter_AddRefs(device));
RefPtr<IDXGIKeyedMutex> keyedMutex;
if (FAILED(texture->QueryInterface(static_cast<IDXGIKeyedMutex**>(getter_AddRefs(keyedMutex))))) {
NS_WARNING("Failed to QueryInterface for IDXGIKeyedMutex, strange.");
return nullptr;
}
if (FAILED(keyedMutex->AcquireSync(0, 0))) {
NS_WARNING("Failed to acquire sync for keyedMutex, plugin failed to release?");
return nullptr;
}
D3D11_TEXTURE2D_DESC desc;
texture->GetDesc(&desc);
@ -83,19 +72,16 @@ D3D11ShareHandleImage::GetAsSourceSurface()
if (FAILED(hr)) {
NS_WARNING("Failed to create 2D staging texture.");
keyedMutex->ReleaseSync(0);
return nullptr;
}
RefPtr<ID3D11DeviceContext> context;
device->GetImmediateContext(getter_AddRefs(context));
if (!context) {
keyedMutex->ReleaseSync(0);
return nullptr;
}
context->CopyResource(softTexture, texture);
keyedMutex->ReleaseSync(0);
RefPtr<gfx::DataSourceSurface> surface =
gfx::Factory::CreateDataSourceSurface(mSize, gfx::SurfaceFormat::B8G8R8X8);
@ -152,7 +138,8 @@ D3D11RecycleAllocator::CreateOrRecycleClient(gfx::SurfaceFormat aFormat,
CreateOrRecycle(aFormat,
aSize,
BackendSelector::Content,
layers::TextureFlags::DEFAULT);
layers::TextureFlags::DEFAULT,
TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION);
return textureClient.forget();
}

View File

@ -80,6 +80,10 @@ enum TextureAllocationFlags {
// TextureClientD3D11, which may otherwise choose D3D10 or non-KeyedMutex
// surfaces when used on the main thread.
ALLOC_FOR_OUT_OF_BAND_CONTENT = 1 << 5,
// Disable any cross-device synchronization. This is also for TextureClientD3D11,
// and creates a texture without KeyedMutex.
ALLOC_MANUAL_SYNCHRONIZATION = 1 << 6,
};
#ifdef XP_WIN

View File

@ -135,7 +135,8 @@ TextureClientRecycleAllocator::CreateOrRecycle(ITextureClientAllocationHelper& a
// This class does not handle ContentClient's TextureClient allocation.
MOZ_ASSERT(aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_DEFAULT ||
aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_DISALLOW_BUFFERTEXTURECLIENT ||
aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_FOR_OUT_OF_BAND_CONTENT);
aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_FOR_OUT_OF_BAND_CONTENT ||
aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION);
MOZ_ASSERT(aHelper.mTextureFlags & TextureFlags::RECYCLE);
RefPtr<TextureClientHolder> textureHolder;

View File

@ -362,7 +362,9 @@ D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocation
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
if (!NS_IsMainThread() || !!(aFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT)) {
// On the main thread we use the syncobject to handle synchronization.
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
if (!(aFlags & ALLOC_MANUAL_SYNCHRONIZATION)) {
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
}
}
HRESULT hr = d3d11device->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(texture11));