d3d10-capture.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <d3d10.h>
  3. #include <dxgi.h>
  4. #include "dxgi-helpers.hpp"
  5. #include "graphics-hook.h"
  6. #include "../funchook.h"
  7. struct d3d10_data {
  8. ID3D10Device *device; /* do not release */
  9. uint32_t base_cx;
  10. uint32_t base_cy;
  11. uint32_t cx;
  12. uint32_t cy;
  13. DXGI_FORMAT format;
  14. bool using_shtex : 1;
  15. bool using_scale : 1;
  16. bool multisampled : 1;
  17. ID3D10Texture2D *scale_tex;
  18. ID3D10ShaderResourceView *scale_resource;
  19. ID3D10VertexShader *vertex_shader;
  20. ID3D10InputLayout *vertex_layout;
  21. ID3D10PixelShader *pixel_shader;
  22. ID3D10SamplerState *sampler_state;
  23. ID3D10BlendState *blend_state;
  24. ID3D10DepthStencilState *zstencil_state;
  25. ID3D10RasterizerState *raster_state;
  26. ID3D10Buffer *vertex_buffer;
  27. union {
  28. /* shared texture */
  29. struct {
  30. struct shtex_data *shtex_info;
  31. ID3D10Texture2D *texture;
  32. ID3D10RenderTargetView *render_target;
  33. HANDLE handle;
  34. };
  35. /* shared memory */
  36. struct {
  37. struct shmem_data *shmem_info;
  38. ID3D10Texture2D *copy_surfaces[NUM_BUFFERS];
  39. ID3D10Texture2D *textures[NUM_BUFFERS];
  40. ID3D10RenderTargetView *render_targets[NUM_BUFFERS];
  41. bool texture_ready[NUM_BUFFERS];
  42. bool texture_mapped[NUM_BUFFERS];
  43. uint32_t pitch;
  44. int cur_tex;
  45. int copy_wait;
  46. };
  47. };
  48. };
  49. static struct d3d10_data data = {};
  50. void d3d10_free(void)
  51. {
  52. if (data.scale_tex)
  53. data.scale_tex->Release();
  54. if (data.scale_resource)
  55. data.scale_resource->Release();
  56. if (data.vertex_shader)
  57. data.vertex_shader->Release();
  58. if (data.vertex_layout)
  59. data.vertex_layout->Release();
  60. if (data.pixel_shader)
  61. data.pixel_shader->Release();
  62. if (data.sampler_state)
  63. data.sampler_state->Release();
  64. if (data.blend_state)
  65. data.blend_state->Release();
  66. if (data.zstencil_state)
  67. data.zstencil_state->Release();
  68. if (data.raster_state)
  69. data.raster_state->Release();
  70. if (data.vertex_buffer)
  71. data.vertex_buffer->Release();
  72. capture_free();
  73. if (data.using_shtex) {
  74. if (data.texture)
  75. data.texture->Release();
  76. if (data.render_target)
  77. data.render_target->Release();
  78. } else {
  79. for (size_t i = 0; i < NUM_BUFFERS; i++) {
  80. if (data.copy_surfaces[i]) {
  81. if (data.texture_mapped[i])
  82. data.copy_surfaces[i]->Unmap(0);
  83. data.copy_surfaces[i]->Release();
  84. }
  85. if (data.textures[i])
  86. data.textures[i]->Release();
  87. if (data.render_targets[i])
  88. data.render_targets[i]->Release();
  89. }
  90. }
  91. memset(&data, 0, sizeof(data));
  92. hlog("----------------- d3d10 capture freed ----------------");
  93. }
  94. static bool create_d3d10_stage_surface(ID3D10Texture2D **tex)
  95. {
  96. HRESULT hr;
  97. D3D10_TEXTURE2D_DESC desc = {};
  98. desc.Width = data.cx;
  99. desc.Height = data.cy;
  100. desc.Format = data.format;
  101. desc.MipLevels = 1;
  102. desc.ArraySize = 1;
  103. desc.SampleDesc.Count = 1;
  104. desc.Usage = D3D10_USAGE_STAGING;
  105. desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
  106. hr = data.device->CreateTexture2D(&desc, nullptr, tex);
  107. if (FAILED(hr)) {
  108. hlog_hr("create_d3d10_stage_surface: failed to create texture",
  109. hr);
  110. return false;
  111. }
  112. return true;
  113. }
  114. static bool create_d3d10_tex(uint32_t cx, uint32_t cy,
  115. ID3D10Texture2D **tex,
  116. ID3D10ShaderResourceView **resource,
  117. ID3D10RenderTargetView **render_target,
  118. HANDLE *handle)
  119. {
  120. UINT flags = 0;
  121. UINT misc_flags = 0;
  122. HRESULT hr;
  123. if (!!resource)
  124. flags |= D3D10_BIND_SHADER_RESOURCE;
  125. if (!!render_target)
  126. flags |= D3D10_BIND_RENDER_TARGET;
  127. if (!!handle)
  128. misc_flags |= D3D10_RESOURCE_MISC_SHARED;
  129. D3D10_TEXTURE2D_DESC desc = {};
  130. desc.Width = cx;
  131. desc.Height = cy;
  132. desc.MipLevels = 1;
  133. desc.ArraySize = 1;
  134. desc.Format = data.format;
  135. desc.BindFlags = flags;
  136. desc.SampleDesc.Count = 1;
  137. desc.Usage = D3D10_USAGE_DEFAULT;
  138. desc.MiscFlags = misc_flags;
  139. hr = data.device->CreateTexture2D(&desc, nullptr, tex);
  140. if (FAILED(hr)) {
  141. hlog_hr("create_d3d10_tex: failed to create texture", hr);
  142. return false;
  143. }
  144. if (!!resource) {
  145. D3D10_SHADER_RESOURCE_VIEW_DESC res_desc = {};
  146. res_desc.Format = data.format;
  147. res_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
  148. res_desc.Texture2D.MipLevels = 1;
  149. hr = data.device->CreateShaderResourceView(*tex, &res_desc,
  150. resource);
  151. if (FAILED(hr)) {
  152. hlog_hr("create_d3d10_tex: failed to create resource "
  153. "view", hr);
  154. return false;
  155. }
  156. }
  157. if (!!render_target) {
  158. hr = data.device->CreateRenderTargetView(*tex, nullptr,
  159. render_target);
  160. if (FAILED(hr)) {
  161. hlog_hr("create_d3d10_tex: failed to create render "
  162. "target view", hr);
  163. return false;
  164. }
  165. }
  166. if (!!handle) {
  167. IDXGIResource *dxgi_res;
  168. hr = (*tex)->QueryInterface(__uuidof(IDXGIResource),
  169. (void**)&dxgi_res);
  170. if (FAILED(hr)) {
  171. hlog_hr("create_d3d10_tex: failed to query "
  172. "IDXGIResource interface from texture", hr);
  173. return false;
  174. }
  175. hr = dxgi_res->GetSharedHandle(handle);
  176. dxgi_res->Release();
  177. if (FAILED(hr)) {
  178. hlog_hr("create_d3d10_tex: failed to get shared handle",
  179. hr);
  180. return false;
  181. }
  182. }
  183. return true;
  184. }
  185. static inline bool d3d10_init_format(IDXGISwapChain *swap, HWND &window)
  186. {
  187. DXGI_SWAP_CHAIN_DESC desc;
  188. HRESULT hr;
  189. hr = swap->GetDesc(&desc);
  190. if (FAILED(hr)) {
  191. hlog_hr("d3d10_init_format: swap->GetDesc failed", hr);
  192. return false;
  193. }
  194. data.format = fix_dxgi_format(desc.BufferDesc.Format);
  195. data.multisampled = desc.SampleDesc.Count > 1;
  196. window = desc.OutputWindow;
  197. data.base_cx = desc.BufferDesc.Width;
  198. data.base_cy = desc.BufferDesc.Height;
  199. if (data.using_scale) {
  200. data.cx = global_hook_info->cx;
  201. data.cy = global_hook_info->cy;
  202. } else {
  203. data.cx = desc.BufferDesc.Width;
  204. data.cy = desc.BufferDesc.Height;
  205. }
  206. return true;
  207. }
  208. static inline bool d3d10_init_vertex_shader(void)
  209. {
  210. D3D10_INPUT_ELEMENT_DESC desc[2];
  211. uint8_t *vs_data;
  212. size_t size;
  213. HRESULT hr;
  214. vs_data = get_d3d1x_vertex_shader(&size);
  215. hr = data.device->CreateVertexShader(vs_data, size,
  216. &data.vertex_shader);
  217. if (FAILED(hr)) {
  218. hlog_hr("d3d10_init_vertex_shader: failed to create shader",
  219. hr);
  220. return false;
  221. }
  222. desc[0].SemanticName = "SV_Position";
  223. desc[0].SemanticIndex = 0;
  224. desc[0].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
  225. desc[0].InputSlot = 0;
  226. desc[0].AlignedByteOffset = 0;
  227. desc[0].InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA;
  228. desc[0].InstanceDataStepRate = 0;
  229. desc[1].SemanticName = "TEXCOORD";
  230. desc[1].SemanticIndex = 0;
  231. desc[1].Format = DXGI_FORMAT_R32G32_FLOAT;
  232. desc[1].InputSlot = 0;
  233. desc[1].AlignedByteOffset = D3D10_APPEND_ALIGNED_ELEMENT;
  234. desc[1].InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA;
  235. desc[1].InstanceDataStepRate = 0;
  236. hr = data.device->CreateInputLayout(desc, 2, vs_data, size,
  237. &data.vertex_layout);
  238. if (FAILED(hr)) {
  239. hlog_hr("d3d10_init_vertex_shader: failed to create layout",
  240. hr);
  241. return false;
  242. }
  243. return true;
  244. }
  245. static inline bool d3d10_init_pixel_shader(void)
  246. {
  247. uint8_t *ps_data;
  248. size_t size;
  249. HRESULT hr;
  250. ps_data = get_d3d1x_pixel_shader(&size);
  251. hr = data.device->CreatePixelShader(ps_data, size, &data.pixel_shader);
  252. if (FAILED(hr)) {
  253. hlog_hr("d3d10_init_pixel_shader: failed to create shader", hr);
  254. return false;
  255. }
  256. return true;
  257. }
  258. static inline bool d3d10_init_sampler_state(void)
  259. {
  260. HRESULT hr;
  261. D3D10_SAMPLER_DESC desc = {};
  262. desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
  263. desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;
  264. desc.AddressV = D3D10_TEXTURE_ADDRESS_CLAMP;
  265. desc.AddressW = D3D10_TEXTURE_ADDRESS_CLAMP;
  266. hr = data.device->CreateSamplerState(&desc, &data.sampler_state);
  267. if (FAILED(hr)) {
  268. hlog_hr("d3d10_init_sampler_state: failed to create sampler "
  269. "state", hr);
  270. return false;
  271. }
  272. return true;
  273. }
  274. static inline bool d3d10_init_blend_state(void)
  275. {
  276. D3D10_BLEND_DESC desc = {};
  277. HRESULT hr;
  278. for (size_t i = 0; i < 8; i++)
  279. desc.RenderTargetWriteMask[i] = D3D10_COLOR_WRITE_ENABLE_ALL;
  280. hr = data.device->CreateBlendState(&desc, &data.blend_state);
  281. if (FAILED(hr)) {
  282. hlog_hr("d3d10_init_blend_state: failed to create blend state",
  283. hr);
  284. return false;
  285. }
  286. return true;
  287. }
  288. static inline bool d3d10_init_zstencil_state(void)
  289. {
  290. D3D10_DEPTH_STENCIL_DESC desc = {}; /* defaults all to off */
  291. HRESULT hr;
  292. hr = data.device->CreateDepthStencilState(&desc, &data.zstencil_state);
  293. if (FAILED(hr)) {
  294. hlog_hr("d3d10_init_zstencil_state: failed to create "
  295. "zstencil state", hr);
  296. return false;
  297. }
  298. return true;
  299. }
  300. static inline bool d3d10_init_raster_state(void)
  301. {
  302. D3D10_RASTERIZER_DESC desc = {};
  303. HRESULT hr;
  304. desc.FillMode = D3D10_FILL_SOLID;
  305. desc.CullMode = D3D10_CULL_NONE;
  306. hr = data.device->CreateRasterizerState(&desc, &data.raster_state);
  307. if (FAILED(hr)) {
  308. hlog_hr("d3d10_init_raster_state: failed to create raster "
  309. "state", hr);
  310. return false;
  311. }
  312. return true;
  313. }
  314. #define NUM_VERTS 4
  315. static inline bool d3d10_init_vertex_buffer(void)
  316. {
  317. HRESULT hr;
  318. const vertex verts[NUM_VERTS] = {
  319. {{-1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
  320. {{-1.0f, -1.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
  321. {{ 1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
  322. {{ 1.0f, -1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}
  323. };
  324. D3D10_BUFFER_DESC desc;
  325. desc.ByteWidth = sizeof(vertex) * NUM_VERTS;
  326. desc.Usage = D3D10_USAGE_DEFAULT;
  327. desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
  328. desc.CPUAccessFlags = 0;
  329. desc.MiscFlags = 0;
  330. D3D10_SUBRESOURCE_DATA srd = {};
  331. srd.pSysMem = (const void*)verts;
  332. hr = data.device->CreateBuffer(&desc, &srd, &data.vertex_buffer);
  333. if (FAILED(hr)) {
  334. hlog_hr("d3d10_init_vertex_buffer: failed to create vertex "
  335. "buffer", hr);
  336. return false;
  337. }
  338. return true;
  339. }
  340. static bool d3d10_init_scaling(void)
  341. {
  342. bool success;
  343. success = create_d3d10_tex(data.base_cx, data.base_cy,
  344. &data.scale_tex, &data.scale_resource, nullptr,
  345. nullptr);
  346. if (!success) {
  347. hlog("d3d10_init_scaling: failed to create scale texture");
  348. return false;
  349. }
  350. if (!d3d10_init_vertex_shader()) {
  351. return false;
  352. }
  353. if (!d3d10_init_pixel_shader()) {
  354. return false;
  355. }
  356. if (!d3d10_init_sampler_state()) {
  357. return false;
  358. }
  359. if (!d3d10_init_blend_state()) {
  360. return false;
  361. }
  362. if (!d3d10_init_zstencil_state()) {
  363. return false;
  364. }
  365. if (!d3d10_init_raster_state()) {
  366. return false;
  367. }
  368. if (!d3d10_init_vertex_buffer()) {
  369. return false;
  370. }
  371. return true;
  372. }
  373. static bool d3d10_shmem_init_buffers(size_t idx)
  374. {
  375. bool success;
  376. success = create_d3d10_stage_surface(&data.copy_surfaces[idx]);
  377. if (!success) {
  378. hlog("d3d10_shmem_init_buffers: failed to create copy surface");
  379. return false;
  380. }
  381. if (idx == 0) {
  382. D3D10_MAPPED_TEXTURE2D map = {};
  383. HRESULT hr;
  384. hr = data.copy_surfaces[idx]->Map(0, D3D10_MAP_READ, 0, &map);
  385. if (FAILED(hr)) {
  386. hlog_hr("d3d10_shmem_init_buffers: failed to get "
  387. "pitch", hr);
  388. return false;
  389. }
  390. data.pitch = map.RowPitch;
  391. data.copy_surfaces[idx]->Unmap(0);
  392. }
  393. success = create_d3d10_tex(data.cx, data.cy, &data.textures[idx],
  394. nullptr, &data.render_targets[idx], nullptr);
  395. if (!success) {
  396. hlog("d3d10_shmem_init_buffers: failed to create texture");
  397. return false;
  398. }
  399. return true;
  400. }
  401. static bool d3d10_shmem_init(HWND window)
  402. {
  403. data.using_shtex = false;
  404. for (size_t i = 0; i < NUM_BUFFERS; i++) {
  405. if (!d3d10_shmem_init_buffers(i)) {
  406. return false;
  407. }
  408. }
  409. if (!capture_init_shmem(&data.shmem_info, window,
  410. data.base_cx, data.base_cy, data.cx, data.cy,
  411. data.pitch, data.format, false)) {
  412. return false;
  413. }
  414. hlog("d3d10 memory capture successful");
  415. return true;
  416. }
  417. static bool d3d10_shtex_init(HWND window)
  418. {
  419. ID3D10ShaderResourceView *resource = nullptr;
  420. bool success;
  421. data.using_shtex = true;
  422. success = create_d3d10_tex(data.cx, data.cy, &data.texture, &resource,
  423. &data.render_target, &data.handle);
  424. if (resource)
  425. resource->Release();
  426. if (!success) {
  427. hlog("d3d10_shtex_init: failed to create texture");
  428. return false;
  429. }
  430. if (!capture_init_shtex(&data.shtex_info, window,
  431. data.base_cx, data.base_cy, data.cx, data.cy,
  432. data.format, false, (uintptr_t)data.handle)) {
  433. return false;
  434. }
  435. hlog("d3d10 shared texture capture successful");
  436. return true;
  437. }
  438. static void d3d10_init(IDXGISwapChain *swap)
  439. {
  440. bool success = true;
  441. HWND window;
  442. HRESULT hr;
  443. data.using_scale = global_hook_info->use_scale;
  444. hr = swap->GetDevice(__uuidof(ID3D10Device), (void**)&data.device);
  445. if (FAILED(hr)) {
  446. hlog_hr("d3d10_init: failed to get device from swap", hr);
  447. return;
  448. }
  449. /* remove the unneeded extra reference */
  450. data.device->Release();
  451. if (!d3d10_init_format(swap, window)) {
  452. return;
  453. }
  454. if (data.using_scale && !d3d10_init_scaling()) {
  455. hlog("d3d10_init: failed to initialize scaling");
  456. success = false;
  457. }
  458. if (success) {
  459. if (global_hook_info->force_shmem) {
  460. success = d3d10_shmem_init(window);
  461. } else {
  462. success = d3d10_shtex_init(window);
  463. }
  464. }
  465. if (!success)
  466. d3d10_free();
  467. }
  468. #define MAX_RENDER_TARGETS D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT
  469. #define MAX_SO_TARGETS 4
  470. struct d3d10_state {
  471. ID3D10GeometryShader *geom_shader;
  472. ID3D10InputLayout *vertex_layout;
  473. D3D10_PRIMITIVE_TOPOLOGY topology;
  474. ID3D10Buffer *vertex_buffer;
  475. UINT vb_stride;
  476. UINT vb_offset;
  477. ID3D10BlendState *blend_state;
  478. float blend_factor[4];
  479. UINT sample_mask;
  480. ID3D10DepthStencilState *zstencil_state;
  481. UINT zstencil_ref;
  482. ID3D10RenderTargetView *render_targets[MAX_RENDER_TARGETS];
  483. ID3D10DepthStencilView *zstencil_view;
  484. ID3D10SamplerState *sampler_state;
  485. ID3D10PixelShader *pixel_shader;
  486. ID3D10ShaderResourceView *resource;
  487. ID3D10RasterizerState *raster_state;
  488. UINT num_viewports;
  489. D3D10_VIEWPORT *viewports;
  490. ID3D10Buffer *stream_output_targets[MAX_SO_TARGETS];
  491. UINT so_offsets[MAX_SO_TARGETS];
  492. ID3D10VertexShader *vertex_shader;
  493. };
  494. static inline void d3d10_save_state(struct d3d10_state *state)
  495. {
  496. data.device->GSGetShader(&state->geom_shader);
  497. data.device->IAGetInputLayout(&state->vertex_layout);
  498. data.device->IAGetPrimitiveTopology(&state->topology);
  499. data.device->IAGetVertexBuffers(0, 1, &state->vertex_buffer,
  500. &state->vb_stride, &state->vb_offset);
  501. data.device->OMGetBlendState(&state->blend_state, state->blend_factor,
  502. &state->sample_mask);
  503. data.device->OMGetDepthStencilState(&state->zstencil_state,
  504. &state->zstencil_ref);
  505. data.device->OMGetRenderTargets(MAX_RENDER_TARGETS,
  506. state->render_targets, &state->zstencil_view);
  507. data.device->PSGetSamplers(0, 1, &state->sampler_state);
  508. data.device->PSGetShader(&state->pixel_shader);
  509. data.device->PSGetShaderResources(0, 1, &state->resource);
  510. data.device->RSGetState(&state->raster_state);
  511. data.device->RSGetViewports(&state->num_viewports, nullptr);
  512. if (state->num_viewports) {
  513. state->viewports = (D3D10_VIEWPORT*)malloc(
  514. sizeof(D3D10_VIEWPORT) * state->num_viewports);
  515. data.device->RSGetViewports(&state->num_viewports,
  516. state->viewports);
  517. }
  518. data.device->SOGetTargets(MAX_SO_TARGETS, state->stream_output_targets,
  519. state->so_offsets);
  520. data.device->VSGetShader(&state->vertex_shader);
  521. }
  522. static inline void safe_release(IUnknown *p)
  523. {
  524. if (p) p->Release();
  525. }
  526. static inline void d3d10_restore_state(struct d3d10_state *state)
  527. {
  528. data.device->GSSetShader(state->geom_shader);
  529. data.device->IASetInputLayout(state->vertex_layout);
  530. data.device->IASetPrimitiveTopology(state->topology);
  531. data.device->IASetVertexBuffers(0, 1, &state->vertex_buffer,
  532. &state->vb_stride, &state->vb_offset);
  533. data.device->OMSetBlendState(state->blend_state, state->blend_factor,
  534. state->sample_mask);
  535. data.device->OMSetDepthStencilState(state->zstencil_state,
  536. state->zstencil_ref);
  537. data.device->OMSetRenderTargets(MAX_RENDER_TARGETS,
  538. state->render_targets, state->zstencil_view);
  539. data.device->PSSetSamplers(0, 1, &state->sampler_state);
  540. data.device->PSSetShader(state->pixel_shader);
  541. data.device->PSSetShaderResources(0, 1, &state->resource);
  542. data.device->RSSetState(state->raster_state);
  543. data.device->RSSetViewports(state->num_viewports, state->viewports);
  544. data.device->SOSetTargets(MAX_SO_TARGETS, state->stream_output_targets,
  545. state->so_offsets);
  546. data.device->VSSetShader(state->vertex_shader);
  547. safe_release(state->geom_shader);
  548. safe_release(state->vertex_layout);
  549. safe_release(state->vertex_buffer);
  550. safe_release(state->blend_state);
  551. safe_release(state->zstencil_state);
  552. for (size_t i = 0; i < MAX_RENDER_TARGETS; i++)
  553. safe_release(state->render_targets[i]);
  554. safe_release(state->zstencil_view);
  555. safe_release(state->sampler_state);
  556. safe_release(state->pixel_shader);
  557. safe_release(state->resource);
  558. safe_release(state->raster_state);
  559. for (size_t i = 0; i < MAX_SO_TARGETS; i++)
  560. safe_release(state->stream_output_targets[i]);
  561. safe_release(state->vertex_shader);
  562. free(state->viewports);
  563. memset(state, 0, sizeof(*state));
  564. }
  565. static inline void d3d10_setup_pipeline(ID3D10RenderTargetView *target,
  566. ID3D10ShaderResourceView *resource)
  567. {
  568. D3D10_VIEWPORT viewport = {0};
  569. const float factor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
  570. void *emptyptr = nullptr;
  571. UINT stride = sizeof(vertex);
  572. UINT zero = 0;
  573. viewport.Width = data.cx;
  574. viewport.Height = data.cy;
  575. viewport.MaxDepth = 1.0f;
  576. data.device->GSSetShader(nullptr);
  577. data.device->IASetInputLayout(data.vertex_layout);
  578. data.device->IASetPrimitiveTopology(
  579. D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
  580. data.device->IASetVertexBuffers(0, 1, &data.vertex_buffer, &stride,
  581. &zero);
  582. data.device->OMSetBlendState(data.blend_state, factor, 0xFFFFFFFF);
  583. data.device->OMSetDepthStencilState(data.zstencil_state, 0);
  584. data.device->OMSetRenderTargets(1, &target, nullptr);
  585. data.device->PSSetSamplers(0, 1, &data.sampler_state);
  586. data.device->PSSetShader(data.pixel_shader);
  587. data.device->PSSetShaderResources(0, 1, &resource);
  588. data.device->RSSetState(data.raster_state);
  589. data.device->RSSetViewports(1, &viewport);
  590. data.device->SOSetTargets(1, (ID3D10Buffer**)&emptyptr, &zero);
  591. data.device->VSSetShader(data.vertex_shader);
  592. }
  593. static inline void d3d10_scale_texture(ID3D10RenderTargetView *target,
  594. ID3D10ShaderResourceView *resource)
  595. {
  596. struct d3d10_state old_state = {};
  597. d3d10_save_state(&old_state);
  598. d3d10_setup_pipeline(target, resource);
  599. data.device->Draw(4, 0);
  600. d3d10_restore_state(&old_state);
  601. }
  602. static inline void d3d10_copy_texture(ID3D10Resource *dst, ID3D10Resource *src)
  603. {
  604. if (data.multisampled) {
  605. data.device->ResolveSubresource(dst, 0, src, 0, data.format);
  606. } else {
  607. data.device->CopyResource(dst, src);
  608. }
  609. }
  610. static inline void d3d10_shtex_capture(ID3D10Resource *backbuffer)
  611. {
  612. if (data.using_scale) {
  613. d3d10_copy_texture(data.scale_tex, backbuffer);
  614. d3d10_scale_texture(data.render_target, data.scale_resource);
  615. } else {
  616. d3d10_copy_texture(data.texture, backbuffer);
  617. }
  618. }
  619. static inline void d3d10_shmem_queue_copy()
  620. {
  621. for (size_t i = 0; i < NUM_BUFFERS; i++) {
  622. D3D10_MAPPED_TEXTURE2D map;
  623. HRESULT hr;
  624. if (data.texture_ready[i]) {
  625. data.texture_ready[i] = false;
  626. hr = data.copy_surfaces[i]->Map(0, D3D10_MAP_READ,
  627. 0, &map);
  628. if (SUCCEEDED(hr)) {
  629. data.texture_mapped[i] = true;
  630. shmem_copy_data(i, map.pData);
  631. }
  632. break;
  633. }
  634. }
  635. }
  636. static inline void d3d10_shmem_capture(ID3D10Resource *backbuffer)
  637. {
  638. int next_tex;
  639. d3d10_shmem_queue_copy();
  640. next_tex = (data.cur_tex == NUM_BUFFERS - 1) ? 0 : data.cur_tex + 1;
  641. if (data.using_scale) {
  642. d3d10_copy_texture(data.scale_tex, backbuffer);
  643. d3d10_scale_texture(data.render_targets[data.cur_tex],
  644. data.scale_resource);
  645. } else {
  646. d3d10_copy_texture(data.textures[data.cur_tex], backbuffer);
  647. }
  648. if (data.copy_wait < NUM_BUFFERS - 1) {
  649. data.copy_wait++;
  650. } else {
  651. ID3D10Texture2D *src = data.textures[next_tex];
  652. ID3D10Texture2D *dst = data.copy_surfaces[next_tex];
  653. if (shmem_texture_data_lock(next_tex)) {
  654. dst->Unmap(0);
  655. data.texture_mapped[next_tex] = false;
  656. shmem_texture_data_unlock(next_tex);
  657. }
  658. d3d10_copy_texture(dst, src);
  659. data.texture_ready[next_tex] = true;
  660. }
  661. data.cur_tex = next_tex;
  662. }
  663. void d3d10_capture(void *swap_ptr, void *backbuffer_ptr)
  664. {
  665. IDXGIResource *dxgi_backbuffer = (IDXGIResource*)backbuffer_ptr;
  666. IDXGISwapChain *swap = (IDXGISwapChain*)swap_ptr;
  667. HRESULT hr;
  668. if (capture_should_stop()) {
  669. d3d10_free();
  670. }
  671. if (capture_should_init()) {
  672. d3d10_init(swap);
  673. }
  674. if (capture_ready()) {
  675. ID3D10Resource *backbuffer;
  676. hr = dxgi_backbuffer->QueryInterface(__uuidof(ID3D10Resource),
  677. (void**)&backbuffer);
  678. if (FAILED(hr)) {
  679. hlog_hr("d3d10_shtex_capture: failed to get "
  680. "backbuffer", hr);
  681. return;
  682. }
  683. if (data.using_shtex)
  684. d3d10_shtex_capture(backbuffer);
  685. else
  686. d3d10_shmem_capture(backbuffer);
  687. backbuffer->Release();
  688. }
  689. }