From d6773ced37132a71ab24f14a27c94ac5b59d8be9 Mon Sep 17 00:00:00 2001 From: ScoochAside Date: Fri, 5 Jul 2024 00:04:10 -0400 Subject: [PATCH] Fix issue #6427 --- gfx/drivers/d3d11.c | 74 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index f7e942178a..3b2d9b7b93 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -1000,6 +1000,7 @@ static uint32_t d3d11_get_flags(void *data) BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); BIT32_SET(flags, GFX_CTX_FLAGS_OVERLAY_BEHIND_MENU_SUPPORTED); BIT32_SET(flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION); + BIT32_SET(flags, GFX_CTX_FLAGS_SCREENSHOTS_SUPPORTED); #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_SLANG); BIT32_SET(flags, GFX_CTX_FLAGS_SUBFRAME_SHADERS); @@ -3626,6 +3627,77 @@ static void d3d11_gfx_viewport_info(void* data, struct video_viewport* vp) *vp = d3d11->vp; } +static bool d3d11_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle) +{ + d3d11_video_t* d3d11 = (d3d11_video_t*)data; + ID3D11Texture2D* BackBuffer; + DXGISwapChain m_SwapChain; + ID3D11Texture2D* BackBufferStagingTexture; + ID3D11Resource* BackBufferStaging = NULL; /* This will hold the ID3D11Resource instance */ + ID3D11Resource* BackBufferResource = NULL; + D3D11_TEXTURE2D_DESC StagingDesc; + D3D11_MAPPED_SUBRESOURCE Map; + const uint8_t* BackBufferData; + uint8_t* bufferRow; + uint32_t y; + uint32_t x; + + if(!d3d11) + return false; + + /* Get the back buffer. */ + m_SwapChain = d3d11->swapChain; + m_SwapChain->lpVtbl->GetBuffer(m_SwapChain, 0, &IID_ID3D11Texture2D, (void*)(&BackBuffer)); + + if(!BackBuffer) + return false; + + if (!is_idle) + { + video_driver_cached_frame(); + } + + /* Set the staging desc. */ + BackBuffer->lpVtbl->GetDesc(BackBuffer, &StagingDesc); + StagingDesc.Usage = D3D11_USAGE_STAGING; + StagingDesc.BindFlags = 0; + StagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + + /* Create the back buffer staging texture. */ + d3d11->device->lpVtbl->CreateTexture2D(d3d11->device, &StagingDesc, NULL, &BackBufferStagingTexture); + + BackBufferStagingTexture->lpVtbl->QueryInterface(BackBufferStagingTexture, &IID_ID3D11Resource, (void**)&BackBufferStaging); + + BackBuffer->lpVtbl->QueryInterface(BackBuffer, &IID_ID3D11Resource, (void**)&BackBufferResource); + + /* Copy back buffer to back buffer staging. */ + d3d11->context->lpVtbl->CopyResource(d3d11->context, BackBufferStaging, BackBufferResource); + + /* Create the image. */ + d3d11->context->lpVtbl->Map(d3d11->context, BackBufferStaging, 0, D3D11_MAP_READ, 0, &Map); + BackBufferData = (const uint8_t*)Map.pData; + + /* Assuming format is DXGI_FORMAT_R8G8B8A8_UNORM */ + for (y = 0; y < d3d11->vp.height; y++, BackBufferData += Map.RowPitch) + { + bufferRow = buffer + 3 * (d3d11->vp.height - y - 1) * d3d11->vp.width; + + for (x = 0; x < d3d11->vp.width; x++) + { + bufferRow[3 * x + 2] = BackBufferData[4 * x + 0]; + bufferRow[3 * x + 1] = BackBufferData[4 * x + 1]; + bufferRow[3 * x + 0] = BackBufferData[4 * x + 2]; + } + } + + d3d11->context->lpVtbl->Unmap(d3d11->context, BackBufferStaging, 0); + + /* Release the backbuffer staging. */ + BackBufferStaging->lpVtbl->Release(BackBufferStaging); + BackBufferStagingTexture->lpVtbl->Release(BackBufferStagingTexture); + return true; +} + static void d3d11_set_menu_texture_frame( void* data, const void* frame, bool rgb32, unsigned width, unsigned height, float alpha) @@ -3858,7 +3930,7 @@ video_driver_t video_d3d11 = { NULL, /* set_viewport */ d3d11_gfx_set_rotation, d3d11_gfx_viewport_info, - NULL, /* read_viewport */ + d3d11_gfx_read_viewport, NULL, /* read_frame_raw */ #ifdef HAVE_OVERLAY d3d11_get_overlay_interface,