2

问题

我在从 DXGI 表面创建 Direct2D 图像源时遇到问题。我正在 Visual Studio 2017 中创建一个 Windows 10 UWP 应用程序,其中部分处理用 C++ 编写的 Direct2D/3D 图形。

基本上,我从 YUV 图像中得到一个亮度值的数组,我现在想将其绘制为黑白图像。这些值在流中每帧出现一次,因此我想使用交换链来有效地呈现数据。在交换链示例的帮助下,我设法建立了一个交换链,当我使用其他数据进行测试时,我可以绘制该交换链。

创建图像源的代码是这样的:

void D2DPanel::DrawBackground(int32 dataPtr, int width, int height)
{
    D3D11_TEXTURE2D_DESC _d3d_texture_desc;
    _d3d_texture_desc.Width = width;
    _d3d_texture_desc.Height = height;
    _d3d_texture_desc.MipLevels = 1;
    _d3d_texture_desc.ArraySize = 1;
    _d3d_texture_desc.Format = DXGI_FORMAT::DXGI_FORMAT_R8_UNORM;    
    _d3d_texture_desc.Usage = D3D11_USAGE::D3D11_USAGE_DYNAMIC;
    _d3d_texture_desc.SampleDesc.Count = 1;
    _d3d_texture_desc.SampleDesc.Quality = 0;
    _d3d_texture_desc.BindFlags = 
    D3D11_BIND_FLAG::D3D11_BIND_SHADER_RESOURCE;
    _d3d_texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_FLAG::D3D11_CPU_ACCESS_WRITE;
    _d3d_texture_desc.MiscFlags = 0;

    D3D11_SUBRESOURCE_DATA _d3d_texture_data;
    _d3d_texture_data.pSysMem = (void*)IntPtr(dataPtr);
    _d3d_texture_data.SysMemPitch = width;

    ComPtr<ID3D11Texture2D> _d3d_texture;   
    DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D(&_d3d_texture_desc, &_d3d_texture_data, &_d3d_texture)); 
    ComPtr<IDXGISurface> _dxgi_surface;
    DX::ThrowIfFailed(_d3d_texture.As(&_dxgi_surface));    
    IDXGISurface* surfaces[1] = { _dxgi_surface.Get() };                

    ComPtr<ID2D1ImageSource> d2d_image_source;

    //The following method call results in an exception
    //m_d2d_context2 is an ID2D1DeviceContext2
    DX::ThrowIfFailed(m_d2d_context2->CreateImageSourceFromDxgi(surfaces, 1,
        DXGI_COLOR_SPACE_TYPE::DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709,
        D2D1_IMAGE_SOURCE_FROM_DXGI_OPTIONS::D2D1_IMAGE_SOURCE_FROM_DXGI_OPTIONS_LOW_QUALITY_PRIMARY_CONVERSION,
        &d2d_image_source));

    //….drawing, etc
}

当我使用上面的参数调用CreateImageSourceFromDXGI时,我得到一个异常,并显示以下错误消息(错误消息描述):

D2D DEBUG ERROR - The combination of alpha mode and DXGI format supplied
are not compatible with one another.

我可以通过调用访问连接到 ID2D1DeviceContext2 的 alpha 模式,例如auto foo = m_d2d_context2->GetPixelFormat();我已经尝试设置从交换链缓冲区创建的渲染目标位图的 alpha 模式 D2D1_ALPHA_MODE_PREMULTIPLIED(在我的代码所基于的示例代码中)和D2D1_ALPHA_MODE_IGNORE. D2D1_ALPHA_MODE_STRAIGHT当我尝试创建渲染目标位图时导致错误。我可以看到 alpha 模式确实是通过m_d2d_context2->GetPixelFormat(). 没有任何帮助,我仍然收到相同的错误消息。创建交换链时,alpha 设置为DXGI_ALPHA_MODE_UNSPECIFIED,格式为DXGI_FORMAT_B8G8R8A8_UNORM.

在尝试创建黑白图像之前,我成功地从 YUV 数据创建和渲染图像源,在调用 CreateImageSourceFromDxgi 时,我使用 DXGI 格式DXGI_FORMAT_NV12创建D3D11_TEXTURE2D和参数。DXGI_COLOR_SPACE_TYPE::DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601D2D1_IMAGE_SOURCE_FROM_DXGI_OPTIONS::D2D1_IMAGE_SOURCE_FROM_DXGI_OPTIONS_LOW_QUALITY_PRIMARY_CONVERSION

我的问题

  • 问题是我使用的是不兼容的 alpha 模式DXGI_FORMAT_R8_UNORM吗?如果是这样,哪些兼容,哪些不兼容?
  • 有谁知道还有什么可以阻止我创建图像源?
  • 有谁知道有人试图从像素数据数组中渲染 Direct2D 中的单通道图像的示例?

编辑:

我做了一个解决方法并创建了一个位图而不是图像源。

//create texture etc, see code from original question...

//access _dxgi_surface connected to texture
ComPtr<IDXGISurface> _dxgi_surface;
DX::ThrowIfFailed(_d3d_texture.As(&_dxgi_surface)); 

//create bitmap from texture with y channel values
D2D1_BITMAP_PROPERTIES1 YPlaneBitmapProp =
    BitmapProperties1(
        D2D1_BITMAP_OPTIONS_NONE,
        PixelFormat(DXGI_FORMAT_R8_UNORM, D2D1_ALPHA_MODE_IGNORE),
        width, height
    );
ComPtr<ID2D1Bitmap1> YPlaneBitmap;
DX::ThrowIfFailed(m_d2d_context2->CreateBitmapFromDxgiSurface(_dxgi_surface.Get(), &YPlaneBitmapProp, YPlaneBitmap.GetAddressOf()));    

//create empty rgb bitmap 
D2D1_BITMAP_PROPERTIES RGBBitmapProp =
    BitmapProperties(PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE), 96.0f, 96.0f);
ComPtr<ID2D1Bitmap> RGBBitmap;
DX::ThrowIfFailed(m_d2dContext->CreateBitmap(D2D1::SizeU(width, height), RGBBitmapProp, RGBBitmap.GetAddressOf())); 

//Draw Y plane values from YPlaneBitmap on RGBBitmap using a custom effect/pixel shader
m_backgroundEffect->SetInput(0, RGBBitmap.Get());
m_backgroundEffect->SetInput(1, YPlaneBitmap.Get());    

//Scale up image to size of render target
m_scaleEffect->SetInputEffect(0, m_backgroundEffect.Get()); 
m_scaleEffect->SetValue(D2D1_SCALE_PROP_SCALE, D2D1::Vector2F(((float)m_renderTargetWidth / width), (float)m_renderTargetHeight / height));

//Draw image
m_d2dContext->DrawImage(m_scaleEffect.Get());

我仍然不知道创建图像源的代码有什么问题。

4

0 回答 0