【问题标题】:Get GDI DC from ID3D11Texture2D for drawing从 ID3D11Texture2D 获取 GDI DC 进行绘图
【发布时间】:2019-01-28 11:08:32
【问题描述】:

我在 directx9 中有一个实现,我使用 GDI DC 来渲染绘图。 但是directx11中的类似代码并没有得到GDI DC而是抛出了无效调用异常。

在directx9中的实现:

IF_DX9ERR_THROW_HR(m_spIDevice->CreateTexture(UINT(cSizeOverlay.cx), UINT(cSizeOverlay.cy), 1, D3DUSAGE_DYNAMIC,  D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_spIOverlay, nullptr));
m_spIOverlaySurface = nullptr;
IF_DX9ERR_THROW_HR(m_spIOverlay->GetSurfaceLevel(0, &m_spIOverlaySurface));
D3DSURFACE_DESC descOverlay;
::ZeroMemory(&descOverlay, sizeof(descOverlay));
IF_DX9ERR_THROW_HR(m_spIOverlaySurface->GetDesc(&descOverlay));
// fill the texture with the color key
CRect cRect(0, 0, descOverlay.Width, descOverlay.Height);
HDC hDC = nullptr;
IF_DX9ERR_THROW_HR(m_spIOverlaySurface->GetDC(&hDC));
::SetBkColor(hDC, colKey);
::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, cRect, nullptr, 0, nullptr);
IF_DX9ERR_THROW_HR(m_spIOverlaySurface->ReleaseDC(hDC));

在directx11中的实现:

D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = gsl::narrow_cast<UINT>(width);
desc.Height = gsl::narrow_cast<UINT>(height);
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_B8G8R8X8_UNORM;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MipLevels = 1;
desc.SampleDesc.Count = 1;
desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;

ID3D11DevicePtr device = renderer->Device();
ID3D11Texture2DPtr  texture2D;
IF_FAILED_THROW_HR(device->CreateTexture2D(&desc, nullptr, &texture2D));    
// get texture surface
IDXGISurface1Ptr dxgiSurface1 = tex2D;

IF_FAILED_THROW_HR(dxgiSurface1->GetDC(FALSE, &m_overlayDC));
//Draw on the DC using GDI
if (!m_overlayDC) // we have lost the device
    THROW_PE(IDS_ERR_NO_VIDEO_HARDWARE);
::SetBkColor(m_overlayDC, m_effectConstants.m_keyColor);
::ExtTextOut(m_overlayDC, 0, 0, ETO_OPAQUE, overlayRect, nullptr, 0, nullptr);
//When finish drawing release the DC
dxgiSurface1->ReleaseDC(nullptr);

m_overlayDC = nullptr;

编辑:我已经改变了 D3D11_TEXTURE2D_DESC 如下:

    CD3D11_TEXTURE2D_DESC texDesc(DXGI_FORMAT_B8G8R8X8_UNORM
    , gsl::narrow_cast<UINT>(targetSize.width), gsl::narrow_cast<UINT>(targetSize.height), 1U, 1, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);

ID3D11DevicePtr device = renderer->Device();
ID3D11Texture2DPtr  texture2D;
IF_FAILED_THROW_HR(device->CreateTexture2D(&texDesc, nullptr, &texture2D));

// get texture surface
IDXGISurface1Ptr dxgiSurface1 = texture2D;

IF_FAILED_THROW_HR(dxgiSurface1->GetDC(FALSE, &m_overlayDC));
//Draw on the DC using GDI
if (!m_overlayDC) // we have lost the device
    THROW_PE(IDS_ERR_NO_VIDEO_HARDWARE);
::SetBkColor(m_overlayDC, m_effectConstants.m_keyColor);
::ExtTextOut(m_overlayDC, 0, 0, ETO_OPAQUE, overlayRect, nullptr, 0, nullptr);
//When finish drawing release the DC
dxgiSurface1->ReleaseDC(nullptr);

m_overlayDC = nullptr;

现在 GetDC() 抛出异常:应用程序进行了无效的调用。调用的参数或某些对象的状态不正确。 启用 D3D 调试层以通过调试消息查看详细信息。 HResult:0x887A0001,设施:2170,代码:1

【问题讨论】:

  • 哪一行有错误,Direct3D调试输出是什么?
  • 执行 CreateTexture2D() 并调试输出如下:无效参数错误。 HResult:0x80070057,设施:7(WIN32),代码:87
  • 这完全合乎逻辑,因为您没有遵循Microsoft Docs 上列出的D3D11_RESOURCE_MISC_GDI_COMPATIBLE 的限制。它必须有D3D11_BIND_RENDER_TARGET 和格式DXGI_FORMAT_B8G8R8A8_UNORM

标签: c++11 gdi directx-11 directx-9 texture2d


【解决方案1】:

您选择的格式、用法和绑定标志的组合与D3D11_RESOURCE_MISC_GDI_COMPATIBLE 不兼容。

如果您启用Direct3D Debug Device,您将获得调试输出以通知您此限制。 Direct3D 调试设备是找出您收到E_INVALIDARG 原因的理想方式。

D3D11 错误:ID3D11Device::CreateTexture2D: D3D11_RESOURCE_MISC_GDI_COMPATIBLE 要求设置 D3D11_BIND_RENDER_TARGET 标志。 [STATE_CREATION 错误 #103:CREATETEXTURE2D_INVALIDMISCFLAGS]

然后在修复它之后,你会得到:

D3D11 错误:ID3D11Device::CreateTexture2D:D3D11_RESOURCE_MISC_GDI_COMPATIBLE 需要 D3D11_USAGE_DEFAULT。 [状态创建错误#103:CREATETEXTURE2D_INVALIDMISCFLAGS]``。

最后:

D3D11 错误:ID3D11Device::CreateTexture2D: D3D11_RESOURCE_MISC_GDI_COMPATIBLE 需要 B8G8R8A8 格式。 [STATE_CREATION 错误 #103:CREATETEXTURE2D_INVALIDMISCFLAGS]

所以把这一切放在一起,这是可行的:

D3D11_TEXTURE2D_DESC desc = {};
desc.Width = ...
desc.Height = ...
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
desc.MipLevels = 1;
desc.SampleDesc.Count = 1;
desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;

Microsoft::WRL::ComPtr<ID3D11Texture2D> texture2D;
DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D(&desc, nullptr, &texture2D));

限制都写在Microsoft Docs

【讨论】:

    猜你喜欢
    • 2019-08-05
    • 2013-05-23
    • 1970-01-01
    • 2011-11-10
    • 2015-05-04
    • 2015-12-29
    • 2018-05-18
    • 2021-08-03
    • 2018-01-15
    相关资源
    最近更新 更多