如何在Win7上支持GDI,D3D11互操作性?

问题描述

我创建了一个D3D11设备,可以执行诸如平滑渲染图片的操作,但是为了也支持GDI,我尝试了几种方法:

  1. 通过交换链-> GetBuffer(ID3D11Texture2D)-> CreateDxgiSurfaceRenderTarget-> ID2D1GdiInteropRenderTarget-> GetDC,最后获得DC。它可以在Win10上正常运行,但是在Win7上运行GetDC时出现异常报告:_com_error。
  2. 通过交换链-> GetBuffer(IDXGISurface1)-> GetDC,与1相同。

我怀疑GetBuffer在Win7上获得的ID3D11Texture2D / IDXGISurface1在使用GDI方面会受到一些限制,因此我更改为自己动态创建新的ID3D11Texture2D,现在单独使用DC / D3D11绘图界面就可以了,但是如果我进行互操作,我会发现gdi操作是在自定义创建的ID3D11Texture2D上绘制的,而不是swapchain的back_buffer上绘制的:

_d3d->Clear();
_d3d->DrawImage();
HDC hdc = _d3d->GetDC();
DrawRectangleByGDI(hdc);
_d3d->ReleaseDC();
_d3d->Present();

那么该怎么做:无论是绘制D3D还是DC方法,它们都位于同一ID3D11Texture2D上?这样,对我的CopyResource也很方便。

HRESULT CGraphRender::Resize(const UINT32& width,const UINT32& height)
{
_back_texture2d = nullptr;
_back_rendertarget_view = nullptr;
_dc_texture2d = nullptr;
_dc_render_target = nullptr;

float dpi = GetDpiFromD2DFactory(_d2d_factory);

//Backbuffer
HRESULT hr = _swap_chain->ResizeBuffers(2,width,height,DXGI_FORMAT_B8G8R8A8_UNORM,_is_gdi_compatible ? DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE : 0);
RETURN_ON_FAIL(hr);

hr = _swap_chain->GetBuffer(0,__uuidof(ID3D11Texture2D),(void**)&_back_texture2d);
RETURN_ON_FAIL(hr);

hr = CreateD3D11Texture2D(_d3d_device,&_dc_texture2d);
RETURN_ON_FAIL(hr);

D3D11_RENDER_TARGET_VIEW_DESC rtv;
rtv.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
rtv.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtv.Texture2D.MipSlice = 0;
hr = _d3d_device->CreateRenderTargetView(_back_texture2d,&rtv,&_back_rendertarget_view);
RETURN_ON_FAIL(hr);
 
...
}

HRESULT CGraphRender::Clear(float color[])
{
CComPtr<ID3D11DeviceContext> immediate_context;
_d3d_device->GetImmediateContext(&immediate_context);
if (!immediate_context)
{
    return E_UNEXPECTED;
}
ID3D11RenderTargetView* ref_renderTargetView = _back_rendertarget_view;
immediate_context->OMSetRenderTargets(1,&ref_renderTargetView,nullptr);
immediate_context->ClearRenderTargetView(_back_rendertarget_view,color);

return S_OK;
}

HDC     CGraphRender::GetDC()
{
if (_is_gdi_compatible)
{
    CComPtr<IDXGISurface1>  gdi_surface;
    HRESULT hr = _dc_texture2d->QueryInterface(__uuidof(IDXGISurface1),(void**)&gdi_surface);
    if (SUCCEEDED(hr))
    {
        HDC hdc = nullptr;
        hr = gdi_surface->GetDC(TRUE,&hdc);
        if (SUCCEEDED(hr))
        {
            return hdc;
        }
    }
}
return nullptr;
}

HRESULT CGraphRender::CopyTexture(ID3D11Texture2D* dst_texture,ID3D11Texture2D* src_texture,POINT* dst_topleft/* = nullptr*/,POINT* src_topleft/* = nullptr*/)
{
if (!dst_texture && !src_texture)
{
    return E_INVALIDARG;
}
CComPtr<ID3D11DeviceContext> immediate_context;
_d3d_device->GetImmediateContext(&immediate_context);
if (!immediate_context)
{
    return E_UNEXPECTED;
}

ID3D11Texture2D* dst_texture_real = dst_texture ? dst_texture : _dc_texture2d;
POINT dst_topleft_real = dst_topleft ? (*dst_topleft) : POINT{ 0,0 };
ID3D11Texture2D* src_texture_real = src_texture ? src_texture : _dc_texture2d;
POINT src_topleft_real = src_topleft ? (*src_topleft) : POINT{ 0,0 };

D3D11_TEXTURE2D_DESC src_desc = { 0 };
src_texture_real->GetDesc(&src_desc);
D3D11_TEXTURE2D_DESC dst_desc = { 0 };
dst_texture_real->GetDesc(&dst_desc);

if (!dst_topleft_real.x && !src_topleft_real.x && !dst_topleft_real.y && !src_topleft_real.y && dst_desc.Width == src_desc.Width && dst_desc.Height == src_desc.Height)
{
    immediate_context->CopyResource(dst_texture_real,src_texture_real);
}
else
{
    D3D11_BOX   src_box;
    src_box.left = min((UINT)src_topleft_real.x,(UINT)dst_topleft_real.x + dst_desc.Width);
    src_box.top = min((UINT)src_topleft_real.y,(UINT)dst_topleft_real.y + dst_desc.Height);
    src_box.right = min((UINT)src_box.left + src_desc.Width,(UINT)dst_topleft_real.x + dst_desc.Width);
    src_box.bottom = min((UINT)src_box.top + src_desc.Height,(UINT)dst_topleft_real.y + dst_desc.Height);
    src_box.front = 0;
    src_box.back = 1;

    ATLASSERT(src_box.left < src_box.right);
    ATLASSERT(src_box.top < src_box.bottom);

    immediate_context->CopySubresourceRegion(dst_texture_real,dst_topleft_real.x,dst_topleft_real.y,src_texture_real,&src_box);
}

return S_OK;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)