What factors determine DXGI_FORMAT?

Viewed 1612

I am not familiar with directx, but I ran into a problem in a small project, part of which involves capturing directx data. I hope, below I make some sense.

General question:

I would like to know what factors determine the DXGI_FORMAT of a texture in the backbuffer (hardware?, OS?, application?, directx version?). And more importantly, when capturing a texture from the backbuffer, is it possible to receive a texture in the desired format by supplying the format as a parameter, having the format automatically converted if necessary.

Specifics about my problem :

I capture screens from games using Open Broadcaster Software(OBS) and process them using a specific library(OpenCV) prior to streaming. I noticed that, following updates to both Windows and OBS, I get 'DXGI_FORMAT_R10G10B10A2_UNORM' as the DXGI_FORMAT. This is a problem for me, because as far as I know OpenCV does not provide a convenient way for building an OpenCV object when colors are 10bits. Below are a few relevant lines from the modified OBS source file.

d3d11_copy_texture(data.texture, backbuffer);
...
hlog(toStr(data.format));  // prints 24 = DXGI_FORMAT_R10G10B10A2_UNORM
...
ID3D11Texture2D* tex;
bool success = create_d3d11_stage_surface(&tex);
if (success) {
    ...
    HRESULT hr = data.context->Map(tex, subresource, D3D11_MAP_READ, 0, &mappedTex);
    ...
    Mat frame(data.cy, data.cx, CV_8UC4, mappedTex.pData, (int)mappedTex.RowPitch); //This creates an OpenCV Mat object.
                                               //No support for 10-bit coors. Expects 8-bit colors (CV_8UC4 argument).
                                               //When the resulting Mat is viewed, colours are jumbled (Probably because 10-bits did not fit into 8-bits).

Before the updates (when I was working on this a year ago), I was probably receiving DXGI_FORMAT = DXGI_FORMAT_B8G8R8A8_UNORM, because the code above used to work.

Now I wonder what changed, and whether I can modify the source code of OBS to receive data with the desired DXGI_FORMAT.

'create_d3d11_stage_surface' method called above sets the DXGI_FORMAT, but I am not sure if it means 'give me data with this DXGI_FORMAT' or 'I know you work with this format, give me what you have'.

static bool create_d3d11_stage_surface(ID3D11Texture2D **tex)
{
    HRESULT hr;

    D3D11_TEXTURE2D_DESC desc      = {};
    desc.Width                     = data.cx;
    desc.Height                    = data.cy;
    desc.Format = data.format;
    ...

I hoped that, overriding the desc.Format with DXGI_FORMAT_B8G8R8A8_UNORM would result in that format being passed as argument in the ID3D11DeviceContext::Map call above, and I would get data with specified format. But that did not work.

2 Answers
Related