2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "ScreenshotSurfaceWindows.h"
11 #include "ServiceBroker.h"
12 #include "guilib/GUIComponent.h"
13 #include "guilib/GUIWindowManager.h"
14 #include "rendering/dx/DeviceResources.h"
15 #include "utils/Screenshot.h"
16 #include "utils/log.h"
17 #include "windowing/GraphicContext.h"
21 #include <wrl/client.h>
23 using namespace Microsoft::WRL
;
25 void CScreenshotSurfaceWindows::Register()
27 CScreenShot::Register(CScreenshotSurfaceWindows::CreateSurface
);
30 std::unique_ptr
<IScreenshotSurface
> CScreenshotSurfaceWindows::CreateSurface()
32 return std::unique_ptr
<CScreenshotSurfaceWindows
>(new CScreenshotSurfaceWindows());
35 bool CScreenshotSurfaceWindows::Capture()
37 CWinSystemBase
* winsystem
= CServiceBroker::GetWinSystem();
41 CGUIComponent
* gui
= CServiceBroker::GetGUI();
45 std::unique_lock
<CCriticalSection
> lock(winsystem
->GetGfxContext());
46 gui
->GetWindowManager().Render();
48 auto deviceResources
= DX::DeviceResources::Get();
49 deviceResources
->FinishCommandList();
51 ComPtr
<ID3D11DeviceContext
> pImdContext
= deviceResources
->GetImmediateContext();
52 ComPtr
<ID3D11Device
> pDevice
= deviceResources
->GetD3DDevice();
53 CD3DTexture
& backbuffer
= deviceResources
->GetBackBuffer();
54 if (!backbuffer
.Get())
57 D3D11_TEXTURE2D_DESC desc
= {};
58 backbuffer
.GetDesc(&desc
);
59 desc
.Usage
= D3D11_USAGE_STAGING
;
60 desc
.CPUAccessFlags
= D3D11_CPU_ACCESS_READ
;
63 ComPtr
<ID3D11Texture2D
> pCopyTexture
= nullptr;
64 if (SUCCEEDED(pDevice
->CreateTexture2D(&desc
, nullptr, &pCopyTexture
)))
67 pImdContext
->CopyResource(pCopyTexture
.Get(), backbuffer
.Get());
69 D3D11_MAPPED_SUBRESOURCE res
;
70 if (SUCCEEDED(pImdContext
->Map(pCopyTexture
.Get(), 0, D3D11_MAP_READ
, 0, &res
)))
73 m_height
= desc
.Height
;
74 m_stride
= res
.RowPitch
;
75 m_buffer
= new unsigned char[m_height
* m_stride
];
76 if (desc
.Format
== DXGI_FORMAT_R10G10B10A2_UNORM
)
78 // convert R10G10B10A2 -> B8G8R8A8
79 for (int y
= 0; y
< m_height
; y
++)
81 uint32_t* pixels10
= reinterpret_cast<uint32_t*>(static_cast<uint8_t*>(res
.pData
) + y
* res
.RowPitch
);
82 uint8_t* pixels8
= m_buffer
+ y
* m_stride
;
84 for (int x
= 0; x
< m_width
; x
++, pixels10
++, pixels8
+= 4)
86 // actual bit per channel is A2B10G10R10
87 uint32_t pixel
= *pixels10
;
89 pixels8
[2] = static_cast<uint8_t>((pixel
& 0x3FF) * 255 / 1023);
92 pixels8
[1] = static_cast<uint8_t>((pixel
& 0x3FF) * 255 / 1023);
95 pixels8
[0] = static_cast<uint8_t>((pixel
& 0x3FF) * 255 / 1023);
102 memcpy(m_buffer
, res
.pData
, m_height
* m_stride
);
103 pImdContext
->Unmap(pCopyTexture
.Get(), 0);
106 CLog::LogF(LOGERROR
, "MAP_READ failed.");
109 return m_buffer
!= nullptr;