graphics-hook.h 5.6 KB

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