0

I am trying to make a desktop recorder, but all i get, is black screen, i have no clue why at all. I tried with dx9, but same thing when i use backbuffer, front buffer method does work, and it can capture the frames correctly, but it's too slow (33ms per frame, and all because of GetFrontBuffer).

So i decided to try with dx11, there are no errors from return, no errors when creating swapchain and device, everything is fine, and in fact the frames are captured(i measure the time and fps, and something is going on), but they are all black, like it's not coming from the desktop, but from somewhere else.

This is the capture method

    if(contains_errors()){return;}

    m_swap_chain->GetBuffer(0, __uuidof(ID3D11Resource), (void**)&m_back_buffer_ptr);
    return_if_null(m_back_buffer_ptr);

    HRESULT hr = m_back_buffer_ptr->QueryInterface(__uuidof(ID3D11Resource),  (void**)&m_back_buffer_data);
    return_if_failed(hr);

    hr = m_swap_chain->GetDevice(__uuidof(ID3D11Device), (void**)&m_device);
    return_if_failed(hr);

    hr = m_swap_chain->GetDesc(&m_desc);
    return_if_failed(hr);

    ID3D11Texture2D* texture = nullptr;
    hr = m_device->CreateTexture2D(&m_tex_desc, 0, &texture);
    return_if_failed(hr);

    ID3D11DeviceContext* context = nullptr;
    m_device->GetImmediateContext(&context);
    return_if_null(context);

    context->CopyResource(texture, m_back_buffer_data);
    D3D11_MAPPED_SUBRESOURCE map_subres = {0, 0, 0};

    hr = context->Map(texture, 0, D3D11_MAP_READ, 0, &map_subres);
    return_if_failed(hr);

    if(m_current_frame == 0)
    {
        m_current_frame = new BYTE[map_subres.DepthPitch];
    }

    memcpy(m_current_frame, map_subres.pData, map_subres.DepthPitch);
    texture->Release();
    m_device->Release();

This is the texture desc setup

    ZeroMemory(&m_tex_desc, sizeof(m_tex_desc));
    m_tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    m_tex_desc.Width = m_desc.BufferDesc.Width;
    m_tex_desc.Height = m_desc.BufferDesc.Height;
    m_tex_desc.MipLevels = 1;
    m_tex_desc.ArraySize = 1;
    m_tex_desc.SampleDesc.Count = 1;
    m_tex_desc.Usage = D3D11_USAGE_STAGING;
    m_tex_desc.BindFlags = 0;
    m_tex_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    m_tex_desc.MiscFlags = 0;

This is swapchain desc

    m_desc.BufferDesc.Width = 1366;
    m_desc.BufferDesc.Height = 768;
    m_desc.BufferDesc.RefreshRate.Numerator = 1;
    m_desc.BufferDesc.RefreshRate.Denominator = 60;
    m_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

    m_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    m_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    m_desc.SampleDesc.Count = 2;
    m_desc.SampleDesc.Quality = 0;
    m_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    m_desc.BufferCount = 1;
    m_desc.OutputWindow = (HWND)m_dx_win->winId();
    m_desc.Windowed = true;
    m_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    m_desc.Flags = 0;

Class members

private:
    IDXGISwapChain* m_swap_chain = 0;
    ID3D11DeviceContext* m_context = 0;
    Dx_Output_Window* m_dx_win = 0;

    IDXGIResource* m_back_buffer_ptr = 0;
    ID3D11Resource* m_back_buffer_data = 0;
    ID3D11Device* m_device = 0;

    D3D_FEATURE_LEVEL m_selected_feature;
    DXGI_SWAP_CHAIN_DESC m_desc;
    D3D11_TEXTURE2D_DESC m_tex_desc = {};

I look up basically all the resources i could, but i could not find any info why it does work, but the image is all black. I was thinking maybe there is something up with the display, but no, i took the raw data, and display the value, and all the pixel or whatever it was is, was exactly 0, which is black color.

In the "m_desc.OutputWindow = (HWND)m_dx_win->winId();" i tried to also use GetDesktopWindow(), but it doesn't change anything, in fact i got some warnings instead.

  • You can't capture the desktop like that, you must use the DXGI Output Duplication API: https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/desktop-dup-api – Simon Mourier Oct 20 '21 at 15:55
  • @Simon Mourier I want it also for windows 7, and DXGI Output Duplication API is from version 8.1. Also, there has to be a way to do it with standard directX, since people did you before Duplication API. – BambooWoods Oct 20 '21 at 16:00
  • You must specify that strong requirement in your question as it changes the solutions. For Windows 7 you can capture with DirectX 9 like this: https://stackoverflow.com/questions/30021274/capture-screen-using-directx but this is not the fastest way or using hooks: https://github.com/spazzarama/Direct3DHook – Simon Mourier Oct 20 '21 at 16:05

0 Answers0