问题
I try to use DirectX ChromaKey effect, but my function stucks on some step.
What I do:
- Create ID2D1Factory1
- Create ID3D11Device and ID3D11DeviceContext
- Obtain DXGIResource from received texture
- Obtain shared handle from DXGIResource
- Open DXGIResource as new ID3D11Texture2D using ID3D11Device
- Obtain D3D11_TEXTURE2D_DESC of new ID3D11Texture2D
- Create new ID3D11Texture2D using input ID3D11Texture2D and D3D11_TEXTURE2D_DESC
- Copy resource from obtained ID3D11Texture2D to created ID3D11Texture2D
- Obtain IDXGISurface from created ID3D11Texture2D
- Define D2D1_SIZE_U, D2D1_PIXEL_FORMAT, D2D1_BITMAP_PROPERTIES
- Obtain desktop DPI from ID2D1Factory1
- Create D2D1_RENDER_TARGET_PROPERTIES using obtained DPI
- Create ID2D1RenderTarget using ID2D1Factory1, IDXGISurface and D2D1_RENDER_TARGET_PROPERTIES
- Create shared ID2D1Bitmap using ID2D1RenderTarget, IDXGISurface and D2D1_BITMAP_PROPERTIES
- Obtain IDXGIDevice using ID3D11Device
- Create ID2D1Device using ID2D1Factory1 and IDXGIDevice
- Obtain ID2D1DeviceContext using ID2D1Device
- Create ChromaKey ID2D1Effect using ID2D1DeviceContext
- Define D2D1_VECTOR_3F basing on ChromaKey background
- Set parameters and D2D1_VECTOR_3F of ID2D1Effect
- Drow over ID2D1Bitmap using ID2D1DeviceContext, and ID2D1Effect
- Return new ID3D11Texture2D bound to ID2D1Bitmap
Here is a code.
Defines:
#define SIZEOF_ARRAY(arr) (sizeof(arr)/sizeof((arr)[0]))
#define RET_HR(_f) hr = _f; if (FAILED(hr)) return hr;
#define RET_HR_NULL( _f, _obj ) hr = _f; if (FAILED(hr) || !_obj) return FAILED(hr) ? hr : S_FALSE;
Device creation:
inline CComPtr<ID3D11Device> DX11_CreateDevice(IDXGIAdapter* _pAdapter, ID3D11DeviceContext** _ppD2D1DeviceContext = NULL)
{
DXGI_ADAPTER_DESC dxgiDesc = {};
CComQIPtr<IDXGIAdapter> qpDXGIAdapter(_pAdapter);
if (qpDXGIAdapter)
qpDXGIAdapter->GetDesc(&dxgiDesc);
CComPtr<ID3D11Device> cpD3D11Device;
D3D_FEATURE_LEVEL d3dFeature = (D3D_FEATURE_LEVEL)0;
D3D_FEATURE_LEVEL arrD3DFeatures[] = {
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1 };
HRESULT hr = S_OK;
RET_HR(D3D11CreateDevice(
qpDXGIAdapter,
qpDXGIAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE,
nullptr,
D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG,
arrD3DFeatures,
SIZEOF_ARRAY(arrD3DFeatures),
D3D11_SDK_VERSION,
&cpD3D11Device,
&d3dFeature,
_ppD2D1DeviceContext
));
CComQIPtr<ID3D10Multithread> qpMTProtect(cpD3D11Device);
ATLASSERT(qpMTProtect);
if (qpMTProtect)
qpMTProtect->SetMultithreadProtected(TRUE);
return cpD3D11Device;
}
ChromaKey code:
HRESULT DXV_ChromaKey(ID3D11Texture2D* _pTexIn, ID3D11Texture2D** _pTexOut)
{
// -----------------
HRESULT hr = S_OK;
CComPtr<ID2D1Factory1> cpD2DFactory;
RET_HR_NULL(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &cpD2DFactory), cpD2DFactory);
// Create the DX11 API device object, and get a corresponding context.
CComPtr<ID3D11DeviceContext> cpD3D11DeviceContext;
CComPtr<IDXGIAdapter> cpNVidiaAdpt = DXGI_AdapterByType(eGPU_NVidia);
CComPtr<ID3D11Device> cpD3D11Device = DX11_CreateDevice(cpNVidiaAdpt, &cpD3D11DeviceContext);
CComPtr<IDXGIResource> cpDXGIResource;
RET_HR_NULL(_pTexIn->QueryInterface(__uuidof(IDXGIResource), (void**)&cpDXGIResource), cpDXGIResource);
HANDLE sharedHandle;
cpDXGIResource->GetSharedHandle(&sharedHandle);
CComPtr<ID3D11Texture2D> cpTexIn;
cpD3D11Device->OpenSharedResource(sharedHandle, __uuidof(ID3D11Resource), (void**)(&cpTexIn));
D3D11_TEXTURE2D_DESC td;
cpTexIn->GetDesc(&td);
td.BindFlags = D3D11_BIND_SHADER_RESOURCE;
td.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
CComPtr<ID3D11Texture2D> cpNewTexture;
RET_HR_NULL(cpD3D11Device->CreateTexture2D(&td, NULL, &cpNewTexture), cpNewTexture);
cpD3D11DeviceContext->CopyResource(cpNewTexture, cpTexIn);
CComPtr<IDXGISurface> cpDXGISurface;
RET_HR_NULL(cpNewTexture->QueryInterface(&cpDXGISurface), cpDXGISurface);
// -----------------
D2D1_SIZE_U size = D2D1::SizeU(200, 200); // Adapt to your own size.
D2D1_PIXEL_FORMAT desc2d;
desc2d.format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc2d.alphaMode = D2D1_ALPHA_MODE_IGNORE; // Adapt to your needs.
D2D1_BITMAP_PROPERTIES bmpprops;
bmpprops.dpiX = 96.0f;
bmpprops.dpiY = 96.0f;
bmpprops.pixelFormat = desc2d;
FLOAT dpiX;
FLOAT dpiY;
cpD2DFactory->GetDesktopDpi(&dpiX, &dpiY);
D2D1_RENDER_TARGET_PROPERTIES d2d1RenderTargetProperties =
D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT,
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
dpiX,
dpiY
);
CComPtr<ID2D1RenderTarget> cpRenderTarget;
RET_HR_NULL(cpD2DFactory->CreateDxgiSurfaceRenderTarget(
cpDXGISurface,
&d2d1RenderTargetProperties,
&cpRenderTarget),
cpRenderTarget);
// -----------------
CComPtr<ID2D1Bitmap> cpBitmap;
cpRenderTarget->CreateSharedBitmap(__uuidof(IDXGISurface), cpDXGISurface, &bmpprops, &cpBitmap);
// -----------------
CComPtr<IDXGIDevice> cpDXGIDevice;
// Obtain the underlying DXGI device of the Direct3D11 device.
RET_HR_NULL(cpD3D11Device->QueryInterface(&cpDXGIDevice), cpDXGIDevice);
CComPtr<ID2D1Device> cpD2D1Device;
// Obtain the Direct2D device for 2-D rendering.
RET_HR_NULL(cpD2DFactory->CreateDevice(cpDXGIDevice, &cpD2D1Device), cpD2D1Device);
CComPtr<ID2D1DeviceContext> cpD2DContext;
// Get Direct2D device's corresponding device context object.
RET_HR_NULL(cpD2D1Device->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&cpD2DContext
), cpD2DContext);
CComPtr<ID2D1Effect> chromakeyEffect;
RET_HR_NULL(cpD2DContext->CreateEffect(CLSID_D2D1ChromaKey, &chromakeyEffect), chromakeyEffect);
D2D1_VECTOR_3F Vector3F;
Vector3F.x = .32f;
Vector3F.y = .99f;
Vector3F.z = .48f;
int nSize = sizeof(Vector3F);
BYTE* pData = (BYTE*)&Vector3F;
chromakeyEffect->SetInput(0, cpBitmap);
RET_HR(chromakeyEffect->SetValue(D2D1_CHROMAKEY_PROP_COLOR, pData, nSize));
RET_HR(chromakeyEffect->SetValue(D2D1_CHROMAKEY_PROP_TOLERANCE, 0.2f));
RET_HR(chromakeyEffect->SetValue(D2D1_CHROMAKEY_PROP_INVERT_ALPHA, false));
RET_HR(chromakeyEffect->SetValue(D2D1_CHROMAKEY_PROP_FEATHER, false));
cpD2DContext->BeginDraw();
cpD2DContext->DrawImage(chromakeyEffect);
RET_HR(cpD2DContext->EndDraw());
return cpNewTexture->QueryInterface(_pTexOut);
// -----------------
}
Entry point:
TEST_METHOD(UT_DXV_ChromaKey)
{
MTimeout timeOut(__FUNCTION__);
HRESULT hr = S_OK;
DX11Texture::TPtr apTexturePicOrg;
DX_TextureLoadFromFile(cbsChromaCat, &apTexturePicOrg);
Assert::IsTrue(apTexturePicOrg);
CComPtr<ID3D11Texture2D> cpD3D11Texture;
hr = m_arrVidProcessor[0]->DXV_ChromaKey(apTexturePicOrg, &cpD3D11Texture);
CComPtr<IMFFrame> cpMFFrameCnv;
MCreator::MFFrameCreateFromTexture(NULL, cpD3D11Texture, 0, NULL, &cpMFFrameCnv, NULL);
cpMFFrameCnv->MFVideoSaveToFile(L"C:\\temp\\Kosh.bmp");
}
The input picture:
Now, I'm stucking on 13th step:
- Create ID2D1RenderTarget using ID2D1Factory1, IDXGISurface and D2D1_RENDER_TARGET_PROPERTIES
RET_HR_NULL(cpD2DFactory->CreateDxgiSurfaceRenderTarget(
cpDXGISurface,
&d2d1RenderTargetProperties,
&cpRenderTarget),
cpRenderTarget);
Despite D3D11_CREATE_DEVICE_DEBUG
I get just follow error as HRESULT
of CreateDxgiSurfaceRenderTarget
:
E_INVALIDARG One or more arguments are invalid.
Here is content of td
and description of cpDXGISurface
:
td {Width=0x00000354 Height=0x000001e0 MipLevels=0x00000001 ...} D3D11_TEXTURE2D_DESC
Width 0x00000354 unsigned int
Height 0x000001e0 unsigned int
MipLevels 0x00000001 unsigned int
ArraySize 0x00000001 unsigned int
Format DXGI_FORMAT_B8G8R8A8_UNORM (0x00000057) DXGI_FORMAT
SampleDesc {Count=0x00000001 Quality=0x00000000 } DXGI_SAMPLE_DESC
Usage D3D11_USAGE_DEFAULT (0x00000000) D3D11_USAGE
BindFlags 0x00000008 unsigned int
CPUAccessFlags 0x00020000 unsigned int
MiscFlags 0x00000002 unsigned int
sd {Width=0x00000354 Height=0x000001e0 Format=DXGI_FORMAT_B8G8R8A8_UNORM (0x00000057) ...} DXGI_SURFACE_DESC
Width 0x00000354 unsigned int
Height 0x000001e0 unsigned int
Format DXGI_FORMAT_B8G8R8A8_UNORM (0x00000057) DXGI_FORMAT
SampleDesc {Count=0x00000001 Quality=0x00000000 } DXGI_SAMPLE_DESC
来源:https://stackoverflow.com/questions/60621606/clsid-d2d1chromakey-issues