graphics-hook.h 5.8 KB

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