Bug 1288618 - Part 2: Allow allocating D3D9/11 Images when we don't have a recycling allocator available. r?nical
MozReview-Commit-ID: 5pYZbHJSSIc
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -423,19 +423,21 @@ D3D9DXVA2Manager::Init(nsACString& aFail
mDecoderService = decoderService;
mResetToken = resetToken;
mD3D9 = d3d9Ex;
mDevice = device;
mDeviceManager = deviceManager;
mSyncSurface = syncSurf;
- mTextureClientAllocator = new D3D9RecycleAllocator(layers::ImageBridgeChild::GetSingleton().get(),
- mDevice);
- mTextureClientAllocator->SetMaxPoolSize(5);
+ if (layers::ImageBridgeChild::GetSingleton()) {
+ mTextureClientAllocator = new D3D9RecycleAllocator(layers::ImageBridgeChild::GetSingleton().get(),
+ mDevice);
+ mTextureClientAllocator->SetMaxPoolSize(5);
+ }
Telemetry::Accumulate(Telemetry::MEDIA_DECODER_BACKEND_USED,
uint32_t(media::MediaDecoderBackend::WMFDXVA2D3D9));
reporter.SetSuccessful();
return S_OK;
}
@@ -747,19 +749,21 @@ D3D11DXVA2Manager::Init(nsACString& aFai
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().get(),
- mDevice);
- mTextureClientAllocator->SetMaxPoolSize(5);
+ if (layers::ImageBridgeChild::GetSingleton()) {
+ mTextureClientAllocator = new D3D11RecycleAllocator(layers::ImageBridgeChild::GetSingleton().get(),
+ mDevice);
+ mTextureClientAllocator->SetMaxPoolSize(5);
+ }
Telemetry::Accumulate(Telemetry::MEDIA_DECODER_BACKEND_USED,
uint32_t(media::MediaDecoderBackend::WMFDXVA2D3D11));
reporter.SetSuccessful();
return S_OK;
}
@@ -790,17 +794,17 @@ D3D11DXVA2Manager::CopyToImage(IMFSample
NS_ENSURE_TRUE(aOutImage, E_POINTER);
// Our video frame is stored in a non-sharable ID3D11Texture2D. We need
// to create a copy of that frame as a sharable resource, save its share
// handle, and put that handle into the rendering pipeline.
RefPtr<D3D11ShareHandleImage> image =
new D3D11ShareHandleImage(gfx::IntSize(mWidth, mHeight), aRegion);
- bool ok = image->AllocateTexture(mTextureClientAllocator);
+ bool ok = image->AllocateTexture(mTextureClientAllocator, mDevice);
NS_ENSURE_TRUE(ok, E_FAIL);
HRESULT hr = mTransform->Input(aVideoSample);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
RefPtr<IMFSample> sample;
RefPtr<ID3D11Texture2D> texture = image->GetTexture();
hr = CreateOutputSample(sample, texture);
--- a/gfx/layers/D3D11ShareHandleImage.cpp
+++ b/gfx/layers/D3D11ShareHandleImage.cpp
@@ -20,20 +20,35 @@ D3D11ShareHandleImage::D3D11ShareHandleI
const gfx::IntRect& aRect)
: Image(nullptr, ImageFormat::D3D11_SHARE_HANDLE_TEXTURE),
mSize(aSize),
mPictureRect(aRect)
{
}
bool
-D3D11ShareHandleImage::AllocateTexture(D3D11RecycleAllocator* aAllocator)
+D3D11ShareHandleImage::AllocateTexture(D3D11RecycleAllocator* aAllocator, ID3D11Device* aDevice)
{
- mTextureClient = aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::B8G8R8A8, mSize);
- return !!mTextureClient;
+ if (aAllocator) {
+ mTextureClient = aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::B8G8R8A8, mSize);
+ if (mTextureClient) {
+ mTexture = static_cast<D3D11TextureData*>(mTextureClient->GetInternalData())->GetD3D11Texture();
+ return true;
+ }
+ return false;
+ } else {
+ MOZ_ASSERT(aDevice);
+ CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
+ mSize.width, mSize.height, 1, 1,
+ D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
+ newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
+
+ HRESULT hr = aDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(mTexture));
+ return SUCCEEDED(hr);
+ }
}
gfx::IntSize
D3D11ShareHandleImage::GetSize()
{
return mSize;
}
@@ -110,17 +125,17 @@ D3D11ShareHandleImage::GetAsSourceSurfac
context->Unmap(softTexture, 0);
surface->Unmap();
return surface.forget();
}
ID3D11Texture2D*
D3D11ShareHandleImage::GetTexture() const {
- return static_cast<D3D11TextureData*>(mTextureClient->GetInternalData())->GetD3D11Texture();
+ return mTexture;
}
already_AddRefed<TextureClient>
D3D11RecycleAllocator::Allocate(gfx::SurfaceFormat aFormat,
gfx::IntSize aSize,
BackendSelector aSelector,
TextureFlags aTextureFlags,
TextureAllocationFlags aAllocFlags)
--- a/gfx/layers/D3D11ShareHandleImage.h
+++ b/gfx/layers/D3D11ShareHandleImage.h
@@ -45,27 +45,28 @@ protected:
// This class also manages the synchronization of the copy, to ensure the
// resource is ready to use.
class D3D11ShareHandleImage final : public Image {
public:
D3D11ShareHandleImage(const gfx::IntSize& aSize,
const gfx::IntRect& aRect);
~D3D11ShareHandleImage() override {}
- bool AllocateTexture(D3D11RecycleAllocator* aAllocator);
+ bool AllocateTexture(D3D11RecycleAllocator* aAllocator, ID3D11Device* aDevice);
gfx::IntSize GetSize() override;
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
virtual TextureClient* GetTextureClient(CompositableClient* aClient) override;
virtual gfx::IntRect GetPictureRect() override { return mPictureRect; }
ID3D11Texture2D* GetTexture() const;
private:
gfx::IntSize mSize;
gfx::IntRect mPictureRect;
RefPtr<TextureClient> mTextureClient;
+ RefPtr<ID3D11Texture2D> mTexture;
};
} // namepace layers
} // namespace mozilla
#endif // GFX_D3DSURFACEIMAGE_H
--- a/gfx/layers/D3D9SurfaceImage.cpp
+++ b/gfx/layers/D3D9SurfaceImage.cpp
@@ -13,16 +13,17 @@
namespace mozilla {
namespace layers {
D3D9SurfaceImage::D3D9SurfaceImage()
: Image(nullptr, ImageFormat::D3D9_RGB32_TEXTURE)
, mSize(0, 0)
+ , mShareHandle(0)
, mValid(true)
{}
D3D9SurfaceImage::~D3D9SurfaceImage()
{
}
HRESULT
@@ -50,49 +51,79 @@ D3D9SurfaceImage::AllocateAndCopy(D3D9Re
D3DDEVTYPE_HAL,
desc.Format,
D3DFMT_A8R8G8B8);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
// DXVA surfaces aren't created sharable, so we need to copy the surface
// to a sharable texture to that it's accessible to the layer manager's
// device.
- RefPtr<TextureClient> textureClient =
- aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::B8G8R8A8, aRegion.Size());
- if (!textureClient) {
- return E_FAIL;
+ if (aAllocator) {
+ mTextureClient =
+ aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::B8G8R8A8, aRegion.Size());
+ if (!mTextureClient) {
+ return E_FAIL;
+ }
+
+ DXGID3D9TextureData* texData =
+ static_cast<DXGID3D9TextureData*>(mTextureClient->GetInternalData());
+ mTexture = texData->GetD3D9Texture();
+ mShareHandle = texData->GetShareHandle();
+ mDesc = texData->GetDesc();
+ } else {
+ hr = device->CreateTexture(aRegion.Size().width, aRegion.Size().height,
+ 1,
+ D3DUSAGE_RENDERTARGET,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_DEFAULT,
+ getter_AddRefs(mTexture),
+ &mShareHandle);
+ if (FAILED(hr) || !mShareHandle) {
+ return E_FAIL;
+ }
+
+ hr = mTexture->GetLevelDesc(0, &mDesc);
+ if (FAILED(hr)) {
+ return E_FAIL;
+ }
}
// Copy the image onto the texture, preforming YUV -> RGB conversion if necessary.
- RefPtr<IDirect3DSurface9> textureSurface = static_cast<DXGID3D9TextureData*>(
- textureClient->GetInternalData())->GetD3D9Surface();
+ RefPtr<IDirect3DSurface9> textureSurface = GetD3D9Surface();
if (!textureSurface) {
return E_FAIL;
}
RECT src = { aRegion.x, aRegion.y, aRegion.x+aRegion.width, aRegion.y+aRegion.height };
hr = device->StretchRect(surface, &src, textureSurface, nullptr, D3DTEXF_NONE);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
- mTextureClient = textureClient;
mSize = aRegion.Size();
return S_OK;
}
already_AddRefed<IDirect3DSurface9>
D3D9SurfaceImage::GetD3D9Surface()
{
- return static_cast<DXGID3D9TextureData*>(
- mTextureClient->GetInternalData())->GetD3D9Surface();
+ RefPtr<IDirect3DSurface9> textureSurface;
+ HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(textureSurface));
+ NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+ return textureSurface.forget();
}
const D3DSURFACE_DESC&
D3D9SurfaceImage::GetDesc() const
{
- return static_cast<DXGID3D9TextureData*>(mTextureClient->GetInternalData())->GetDesc();
+ return mDesc;
+}
+
+HANDLE
+D3D9SurfaceImage::GetShareHandle() const
+{
+ return mShareHandle;
}
gfx::IntSize
D3D9SurfaceImage::GetSize()
{
return mSize;
}
@@ -102,38 +133,36 @@ D3D9SurfaceImage::GetTextureClient(Compo
MOZ_ASSERT(mTextureClient);
MOZ_ASSERT(mTextureClient->GetAllocator() == aClient->GetForwarder());
return mTextureClient;
}
already_AddRefed<gfx::SourceSurface>
D3D9SurfaceImage::GetAsSourceSurface()
{
- if (!mTextureClient) {
+ if (!mTexture) {
return nullptr;
}
HRESULT hr;
RefPtr<gfx::DataSourceSurface> surface = gfx::Factory::CreateDataSourceSurface(mSize, gfx::SurfaceFormat::B8G8R8X8);
if (NS_WARN_IF(!surface)) {
return nullptr;
}
- DXGID3D9TextureData* texData = static_cast<DXGID3D9TextureData*>(mTextureClient->GetInternalData());
// Readback the texture from GPU memory into system memory, so that
// we can copy it into the Cairo image. This is expensive.
- RefPtr<IDirect3DSurface9> textureSurface = texData->GetD3D9Surface();
+ RefPtr<IDirect3DSurface9> textureSurface = GetD3D9Surface();
if (!textureSurface) {
return nullptr;
}
- RefPtr<IDirect3DDevice9> device = texData->GetD3D9Device();
- if (!device) {
- return nullptr;
- }
+ RefPtr<IDirect3DDevice9> device;
+ hr = textureSurface->GetDevice(getter_AddRefs(device));
+ NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
RefPtr<IDirect3DSurface9> systemMemorySurface;
hr = device->CreateOffscreenPlainSurface(mSize.width,
mSize.height,
D3DFMT_A8R8G8B8,
D3DPOOL_SYSTEMMEM,
getter_AddRefs(systemMemorySurface),
0);
--- a/gfx/layers/D3D9SurfaceImage.h
+++ b/gfx/layers/D3D9SurfaceImage.h
@@ -59,23 +59,28 @@ public:
gfx::IntSize GetSize() override;
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
virtual TextureClient* GetTextureClient(CompositableClient* aClient) override;
already_AddRefed<IDirect3DSurface9> GetD3D9Surface();
+ HANDLE GetShareHandle() const;
+
virtual bool IsValid() override { return mValid; }
void Invalidate() { mValid = false; }
private:
gfx::IntSize mSize;
RefPtr<TextureClient> mTextureClient;
+ RefPtr<IDirect3DTexture9> mTexture;
+ HANDLE mShareHandle;
+ D3DSURFACE_DESC mDesc;
bool mValid;
};
} // namepace layers
} // namespace mozilla
#endif // GFX_D3DSURFACEIMAGE_H