DXGICaptor.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #include "stdafx.h"
  2. #include "DXGICaptor.h"
  3. #include <windows.h>
  4. #include <gdiplus.h>
  5. #pragma comment(lib, "d3d11.lib")
  6. #pragma comment(lib, "dxgi.lib")
  7. #define RESET_OBJECT(obj) { if(obj) obj->Release(); obj = NULL; }
  8. static BOOL g_bAttach = FALSE;
  9. DXGICaptor::DXGICaptor()
  10. {
  11. m_bInit = FALSE;
  12. m_hDevice = NULL;
  13. m_hContext = NULL;
  14. m_hDeskDupl = NULL;
  15. ZeroMemory(&m_dxgiOutDesc, sizeof(m_dxgiOutDesc));
  16. }
  17. DXGICaptor::~DXGICaptor()
  18. {
  19. Deinit();
  20. }
  21. BOOL DXGICaptor::Init()
  22. {
  23. HRESULT hr = S_OK;
  24. if (m_bInit)
  25. {
  26. return FALSE;
  27. }
  28. // Driver types supported
  29. D3D_DRIVER_TYPE DriverTypes[] =
  30. {
  31. D3D_DRIVER_TYPE_HARDWARE,
  32. D3D_DRIVER_TYPE_WARP,
  33. D3D_DRIVER_TYPE_REFERENCE,
  34. };
  35. UINT NumDriverTypes = ARRAYSIZE(DriverTypes);
  36. // Feature levels supported
  37. D3D_FEATURE_LEVEL FeatureLevels[] =
  38. {
  39. D3D_FEATURE_LEVEL_11_0,
  40. D3D_FEATURE_LEVEL_10_1,
  41. D3D_FEATURE_LEVEL_10_0,
  42. D3D_FEATURE_LEVEL_9_1
  43. };
  44. UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);
  45. D3D_FEATURE_LEVEL FeatureLevel;
  46. //
  47. // Create D3D device
  48. //
  49. for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex)
  50. {
  51. hr = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, 0, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &m_hDevice, &FeatureLevel, &m_hContext);
  52. if (SUCCEEDED(hr))
  53. {
  54. break;
  55. }
  56. }
  57. if (FAILED(hr))
  58. {
  59. return FALSE;
  60. }
  61. //
  62. // Get DXGI device
  63. //
  64. IDXGIDevice* hDxgiDevice = NULL;
  65. hr = m_hDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&hDxgiDevice));
  66. if (FAILED(hr))
  67. {
  68. return FALSE;
  69. }
  70. //
  71. // Get DXGI adapter
  72. //
  73. IDXGIAdapter* hDxgiAdapter = NULL;
  74. hr = hDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&hDxgiAdapter));
  75. RESET_OBJECT(hDxgiDevice);
  76. if (FAILED(hr))
  77. {
  78. return FALSE;
  79. }
  80. //
  81. // Get output
  82. //
  83. INT nOutput = 0;
  84. IDXGIOutput* hDxgiOutput = NULL;
  85. hr = hDxgiAdapter->EnumOutputs(nOutput, &hDxgiOutput);
  86. RESET_OBJECT(hDxgiAdapter);
  87. if (FAILED(hr))
  88. {
  89. return FALSE;
  90. }
  91. //
  92. // get output description struct
  93. //
  94. hDxgiOutput->GetDesc(&m_dxgiOutDesc);
  95. //
  96. // QI for Output 1
  97. //
  98. IDXGIOutput1* hDxgiOutput1 = NULL;
  99. hr = hDxgiOutput->QueryInterface(__uuidof(hDxgiOutput1), reinterpret_cast<void**>(&hDxgiOutput1));
  100. RESET_OBJECT(hDxgiOutput);
  101. if (FAILED(hr))
  102. {
  103. return FALSE;
  104. }
  105. //
  106. // Create desktop duplication
  107. //
  108. hr = hDxgiOutput1->DuplicateOutput(m_hDevice, &m_hDeskDupl);
  109. RESET_OBJECT(hDxgiOutput1);
  110. if (FAILED(hr))
  111. {
  112. return FALSE;
  113. }
  114. // 初始化成功
  115. m_bInit = TRUE;
  116. return TRUE;
  117. // #else
  118. // 小于vs2012,此功能不能实现
  119. return FALSE;
  120. // #endif
  121. }
  122. VOID DXGICaptor::Deinit()
  123. {
  124. if (!m_bInit)
  125. {
  126. return;
  127. }
  128. m_bInit = FALSE;
  129. if (m_hDeskDupl)
  130. {
  131. m_hDeskDupl->Release();
  132. m_hDeskDupl = NULL;
  133. }
  134. if (m_hDevice)
  135. {
  136. m_hDevice->Release();
  137. m_hDevice = NULL;
  138. }
  139. if (m_hContext)
  140. {
  141. m_hContext->Release();
  142. m_hContext = NULL;
  143. }
  144. // #endif
  145. }
  146. BOOL DXGICaptor::AttatchToThread(VOID)
  147. {
  148. if (g_bAttach)
  149. {
  150. return TRUE;
  151. }
  152. HDESK hCurrentDesktop = OpenInputDesktop(0, FALSE, GENERIC_ALL);
  153. if (!hCurrentDesktop)
  154. {
  155. return FALSE;
  156. }
  157. // Attach desktop to this thread
  158. BOOL bDesktopAttached = SetThreadDesktop(hCurrentDesktop);
  159. CloseDesktop(hCurrentDesktop);
  160. hCurrentDesktop = NULL;
  161. g_bAttach = TRUE;
  162. return bDesktopAttached;
  163. }
  164. BOOL DXGICaptor::CaptureImage(RECT& rect, void* pData, INT& nLen)
  165. {
  166. return QueryFrame(pData, nLen);
  167. }
  168. BOOL DXGICaptor::CaptureImage(void* pData, INT& nLen)
  169. {
  170. return QueryFrame(pData, nLen);
  171. }
  172. BOOL DXGICaptor::ResetDevice()
  173. {
  174. Deinit();
  175. return Init();
  176. }
  177. BOOL DXGICaptor::QueryFrame(void* pImgData, INT& nImgSize)
  178. {
  179. if (!m_bInit || !AttatchToThread())
  180. {
  181. return FALSE;
  182. }
  183. nImgSize = 0;
  184. IDXGIResource* hDesktopResource = NULL;
  185. DXGI_OUTDUPL_FRAME_INFO FrameInfo;
  186. HRESULT hr = m_hDeskDupl->AcquireNextFrame(0, &FrameInfo, &hDesktopResource);
  187. if (FAILED(hr))
  188. {
  189. //
  190. // 在一些win10的系统上,如果桌面没有变化的情况下,;
  191. // 这里会发生超时现象,但是这并不是发生了错误,而是系统优化了刷新动作导致的。;
  192. // 所以,这里没必要返回FALSE,返回不带任何数据的TRUE即可;
  193. //
  194. return TRUE;
  195. }
  196. //
  197. // query next frame staging buffer
  198. //
  199. ID3D11Texture2D* hAcquiredDesktopImage = NULL;
  200. hr = hDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&hAcquiredDesktopImage));
  201. RESET_OBJECT(hDesktopResource);
  202. if (FAILED(hr))
  203. {
  204. return FALSE;
  205. }
  206. //
  207. // copy old description
  208. //
  209. D3D11_TEXTURE2D_DESC frameDescriptor;
  210. hAcquiredDesktopImage->GetDesc(&frameDescriptor);
  211. //
  212. // create a new staging buffer for fill frame image
  213. //
  214. ID3D11Texture2D* hNewDesktopImage = NULL;
  215. frameDescriptor.Usage = D3D11_USAGE_STAGING;
  216. frameDescriptor.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  217. frameDescriptor.BindFlags = 0;
  218. frameDescriptor.MiscFlags = 0;
  219. frameDescriptor.MipLevels = 1;
  220. frameDescriptor.ArraySize = 1;
  221. frameDescriptor.SampleDesc.Count = 1;
  222. hr = m_hDevice->CreateTexture2D(&frameDescriptor, NULL, &hNewDesktopImage);
  223. if (FAILED(hr))
  224. {
  225. RESET_OBJECT(hAcquiredDesktopImage);
  226. m_hDeskDupl->ReleaseFrame();
  227. return FALSE;
  228. }
  229. //
  230. // copy next staging buffer to new staging buffer
  231. //
  232. m_hContext->CopyResource(hNewDesktopImage, hAcquiredDesktopImage);
  233. RESET_OBJECT(hAcquiredDesktopImage);
  234. m_hDeskDupl->ReleaseFrame();
  235. //
  236. // create staging buffer for map bits
  237. //
  238. IDXGISurface* hStagingSurf = NULL;
  239. hr = hNewDesktopImage->QueryInterface(__uuidof(IDXGISurface), (void**)(&hStagingSurf));
  240. RESET_OBJECT(hNewDesktopImage);
  241. if (FAILED(hr))
  242. {
  243. return FALSE;
  244. }
  245. //
  246. // copy bits to user space
  247. //
  248. DXGI_MAPPED_RECT mappedRect;
  249. hr = hStagingSurf->Map(&mappedRect, DXGI_MAP_READ);
  250. if (SUCCEEDED(hr))
  251. {
  252. // nImgSize = GetWidth() * GetHeight() * 3;
  253. // PrepareBGR24From32(mappedRect.pBits, (BYTE*)pImgData, m_dxgiOutDesc.DesktopCoordinates);
  254. // mappedRect.pBits;
  255. // am_dxgiOutDesc.DesktopCoordinates;
  256. memcpy((BYTE*)pImgData, mappedRect.pBits, m_dxgiOutDesc.DesktopCoordinates.right * m_dxgiOutDesc.DesktopCoordinates.bottom * 4);
  257. hStagingSurf->Unmap();
  258. }
  259. RESET_OBJECT(hStagingSurf);
  260. return SUCCEEDED(hr);
  261. }