graphics-hook.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #pragma once
  2. #ifdef _MSC_VER
  3. /* conversion from data/function pointer */
  4. #pragma warning(disable : 4152)
  5. #endif
  6. #include "../graphics-hook-info.h"
  7. #include <ipc-util/pipe.h>
  8. #include <psapi.h>
  9. #ifdef __cplusplus
  10. extern "C" {
  11. #else
  12. #if defined(_MSC_VER) && !defined(inline)
  13. #define inline __inline
  14. #endif
  15. #endif
  16. #define NUM_BUFFERS 3
  17. #define HOOK_VERBOSE_LOGGING 0
  18. #if HOOK_VERBOSE_LOGGING
  19. #define hlog_verbose(...) hlog(__VA_ARGS__)
  20. #else
  21. #define hlog_verbose(...) (void)0
  22. #endif
  23. extern void hlog(const char *format, ...);
  24. extern void hlog_hr(const char *text, HRESULT hr);
  25. static inline const char *get_process_name(void);
  26. static inline HMODULE get_system_module(const char *module);
  27. static inline HMODULE load_system_library(const char *module);
  28. extern uint64_t os_gettime_ns(void);
  29. #define flog(format, ...) hlog("%s: " format, __FUNCTION__, ##__VA_ARGS__)
  30. #define flog_hr(text, hr) hlog_hr(__FUNCTION__ ": " text, hr)
  31. static inline bool capture_active(void);
  32. static inline bool capture_ready(void);
  33. static inline bool capture_should_stop(void);
  34. static inline bool capture_should_init(void);
  35. extern void shmem_copy_data(size_t idx, void *volatile data);
  36. extern bool shmem_texture_data_lock(int idx);
  37. extern void shmem_texture_data_unlock(int idx);
  38. extern bool hook_ddraw(void);
  39. extern bool hook_d3d8(void);
  40. extern bool hook_d3d9(void);
  41. extern bool hook_d3d12(void);
  42. extern bool hook_dxgi(void);
  43. extern bool hook_gl(void);
  44. #ifdef COMPILE_VULKAN_HOOK
  45. extern bool hook_vulkan(void);
  46. #endif
  47. extern void d3d10_capture(void *swap, void *backbuffer);
  48. extern void d3d10_free(void);
  49. extern void d3d11_capture(void *swap, void *backbuffer);
  50. extern void d3d11_free(void);
  51. #ifdef COMPILE_D3D12_HOOK
  52. extern void d3d12_capture(void *swap, void *backbuffer);
  53. extern void d3d12_free(void);
  54. #endif
  55. extern bool rehook_gl(void);
  56. extern bool capture_init_shtex(struct shtex_data **data, HWND window,
  57. uint32_t cx, uint32_t cy, uint32_t format,
  58. bool flip, uintptr_t handle);
  59. extern bool capture_init_shmem(struct shmem_data **data, HWND window,
  60. uint32_t cx, uint32_t cy, uint32_t pitch,
  61. uint32_t format, bool flip);
  62. extern void capture_free(void);
  63. extern struct hook_info *global_hook_info;
  64. struct vertex {
  65. struct {
  66. float x, y, z, w;
  67. } pos;
  68. struct {
  69. float u, v;
  70. } tex;
  71. };
  72. static inline bool duplicate_handle(HANDLE *dst, HANDLE src)
  73. {
  74. return !!DuplicateHandle(GetCurrentProcess(), src, GetCurrentProcess(),
  75. dst, 0, false, DUPLICATE_SAME_ACCESS);
  76. }
  77. static inline void *get_offset_addr(HMODULE module, uint32_t offset)
  78. {
  79. return (void *)((uintptr_t)module + (uintptr_t)offset);
  80. }
  81. /* ------------------------------------------------------------------------- */
  82. extern ipc_pipe_client_t pipe;
  83. extern HANDLE signal_restart;
  84. extern HANDLE signal_stop;
  85. extern HANDLE signal_ready;
  86. extern HANDLE signal_exit;
  87. extern HANDLE tex_mutexes[2];
  88. extern char system_path[MAX_PATH];
  89. extern char process_name[MAX_PATH];
  90. extern wchar_t keepalive_name[64];
  91. extern HWND dummy_window;
  92. extern volatile bool active;
  93. static inline const char *get_process_name(void)
  94. {
  95. return process_name;
  96. }
  97. static inline HMODULE get_system_module(const char *module)
  98. {
  99. char base_path[MAX_PATH];
  100. strcpy(base_path, system_path);
  101. strcat(base_path, "\\");
  102. strcat(base_path, module);
  103. return GetModuleHandleA(base_path);
  104. }
  105. static inline uint32_t module_size(HMODULE module)
  106. {
  107. MODULEINFO info;
  108. bool success = !!GetModuleInformation(GetCurrentProcess(), module,
  109. &info, sizeof(info));
  110. return success ? info.SizeOfImage : 0;
  111. }
  112. static inline HMODULE load_system_library(const char *name)
  113. {
  114. char base_path[MAX_PATH];
  115. HMODULE module;
  116. strcpy(base_path, system_path);
  117. strcat(base_path, "\\");
  118. strcat(base_path, name);
  119. module = GetModuleHandleA(base_path);
  120. if (module)
  121. return module;
  122. return LoadLibraryA(base_path);
  123. }
  124. static inline bool capture_alive(void)
  125. {
  126. HANDLE handle = OpenMutexW(SYNCHRONIZE, false, keepalive_name);
  127. const bool success = handle != NULL;
  128. if (success)
  129. CloseHandle(handle);
  130. return success;
  131. }
  132. static inline bool capture_active(void)
  133. {
  134. return active;
  135. }
  136. static inline bool frame_ready(uint64_t interval)
  137. {
  138. static uint64_t last_time = 0;
  139. uint64_t elapsed;
  140. uint64_t t;
  141. if (!interval) {
  142. return true;
  143. }
  144. t = os_gettime_ns();
  145. elapsed = t - last_time;
  146. if (elapsed < interval) {
  147. return false;
  148. }
  149. last_time = (elapsed > interval * 2) ? t : last_time + interval;
  150. return true;
  151. }
  152. static inline bool capture_ready(void)
  153. {
  154. return capture_active() &&
  155. frame_ready(global_hook_info->frame_interval);
  156. }
  157. static inline bool capture_stopped(void)
  158. {
  159. return WaitForSingleObject(signal_stop, 0) == WAIT_OBJECT_0;
  160. }
  161. static inline bool capture_restarted(void)
  162. {
  163. return WaitForSingleObject(signal_restart, 0) == WAIT_OBJECT_0;
  164. }
  165. static inline bool capture_should_stop(void)
  166. {
  167. bool stop_requested = false;
  168. if (capture_active()) {
  169. static uint64_t last_keepalive_check = 0;
  170. uint64_t cur_time = os_gettime_ns();
  171. bool alive = true;
  172. if (cur_time - last_keepalive_check > 5000000000) {
  173. alive = capture_alive();
  174. last_keepalive_check = cur_time;
  175. }
  176. stop_requested = capture_stopped() || !alive;
  177. }
  178. return stop_requested;
  179. }
  180. extern bool init_pipe(void);
  181. static inline bool capture_should_init(void)
  182. {
  183. bool should_init = false;
  184. if (!capture_active()) {
  185. if (capture_restarted()) {
  186. if (capture_alive()) {
  187. if (!ipc_pipe_client_valid(&pipe)) {
  188. init_pipe();
  189. }
  190. should_init = true;
  191. } else {
  192. hlog_verbose(
  193. "capture_should_init: inactive, restarted, not alive");
  194. }
  195. } else {
  196. hlog_verbose(
  197. "capture_should_init: inactive, not restarted");
  198. }
  199. }
  200. return should_init;
  201. }
  202. #if COMPILE_VULKAN_HOOK
  203. extern __declspec(thread) int vk_presenting;
  204. #endif
  205. static inline bool should_passthrough()
  206. {
  207. #if COMPILE_VULKAN_HOOK
  208. return vk_presenting > 0;
  209. #else
  210. return false;
  211. #endif
  212. }
  213. #ifdef __cplusplus
  214. }
  215. #endif