缩放DXGI捕抓的屏幕画面

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

你可能感兴趣的:(缩放DXGI捕抓的屏幕画面)