https://stackoverflow.com/questions/24064837/resizing-a-dxgi-resource-or-texture2d-in-sharpdx
准备采用Direct2D的方案,因为它灵活性更好,可以缩放任意比例。但是答案只是给了个大概,并没有实现的细节。在模仿实现的时候,遇到的问题:
一、ID2D1DeviceContext::EndDraw()报错
0x88990024 : 无法将图像设置为目标,原因是它是一种效果或是未设置 D2D1_BITMAP_OPTIONS_TARGET 标志的位图。
意思是 ID2D1DeviceContext::SetTarget 中传入的ID2D1Bitmap1,没有D2D1_BITMAP_OPTIONS_TARGET 标志。而ID2D1Bitmap1,是通过 CreateBitmapFromDxgiSurface 从 ID3D11Texture2D 创建的。这款 ID3D11Texture2D 创建时的属性为
// Create CPU access texture
desc.Width = output_dup_desc_.ModeDesc.Width;
desc.Height = output_dup_desc_.ModeDesc.Height;
desc.Format = output_dup_desc_.ModeDesc.Format;
desc.ArraySize = 1;
desc.BindFlags = 0;
desc.MiscFlags = 0;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.MipLevels = 1;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.Usage = D3D11_USAGE_STAGING;
hr = d3d11_dev_->CreateTexture2D(&desc, NULL, &dest_image_);
这片纹理是需要从gpu读回cpu的,需要支持 ID3D11DeviceContext::Map 操作。因此 Usage 需要设置为D3D11_CPU_ACCESS_READ,BindFlags设置为空。从这片纹理创建出的ID2D1Bitmap1,无法设置 D2D1_BITMAP_OPTIONS_TARGET
解决办法:用于Direct2D绘制(即被SetTarget)的ID2D1Bitmap1,对应的那块 ID3D11Texture2D ,必须Usage = D3D11_USAGE_DEFAULT,BindFlags = D3D11_BIND_RENDER_TARGET
二、ID2D1DeviceContext::EndDraw()报错
0x88990021 : 无法使用带 D2D1_BITMAP_OPTIONS_CANNOT_DRAW 选项的位图进行绘制。
这个错误实际应该是 ID2D1DeviceContext::DrawBitmap 带来的。只是绘制的函数全部没有HResult返回,错误只能在EndDraw()里面报告了。传入DrawBitmap的源 ID2D1Bitmap1,对应的ID3D11Texture2D 创建属性为
desc.Width = output_dup_desc_.ModeDesc.Width;
desc.Height = output_dup_desc_.ModeDesc.Height;
desc.Format = output_dup_desc_.ModeDesc.Format;
desc.ArraySize = 1;
desc.BindFlags = D3D11_BIND_FLAG::D3D11_BIND_RENDER_TARGET;
desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.MipLevels = 1;
desc.CPUAccessFlags = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
hr = d3d11_dev_->CreateTexture2D(&desc, NULL, &gdi_image_);
这样的ID3D11Texture2D ,对应的bitmapOptions只能是 D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_TARGET。
解决办法:用于 DrawBitmap 的源ID2D1Bitmap1,对应的那块 ID3D11Texture2D,使用 BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE
参考资料
https://www.codeproject.com/Tips/1116253/Desktop-Screen-Capture-on-Windows-via-Windows-Desk
https://stackoverflow.com/questions/54400679/get-gdi-dc-from-id3d11texture2d-for-drawing
https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/Direct2D/devices-and-device-contexts.md
https://learn.microsoft.com/en-us/windows/win32/direct2d/how-to-draw-a-bitmap
网友评论