// Injected D3D9 capture path: inline-hooks IDirect3DDevice9::Present (discovered from a // throwaway device's vtable, so it catches the game's existing device regardless of when we // injected) in Direct3D 9 / 9Ex games, which don't present via IDXGISwapChain. It reads the // backbuffer back with GetRenderTargetData, swizzles BGRA->RGBA, and uploads it into the same // shared keyed-mutex texture (coop_video_) the host samples. Part of the video subsystem, // alongside present_hook and opengl_hook. // // A D3D9 backbuffer isn't directly shareable with D3D11, so this is a CPU read-back // (GetRenderTargetData -> system memory -> upload via a hook-owned D3D11 device), like the // OpenGL path. Works for both plain D3D9 and D3D9Ex (both call Present here). #pragma once #include "ipc_client.hpp" namespace coop::hook { // Installs the D3D9 Present hook. `ipc` must outlive the hook. Returns true if Present was // hooked (i.e. d3d9.dll is present and a probe device came up). Safe to call repeatedly. bool install_d3d9_hooks(IpcClient& ipc); // Removes the D3D9 hook and releases the shared texture (best effort). void remove_d3d9_hooks(); // --- Diagnostics ----------------------------------------------------------- std::uint64_t d3d9_presents(); // cumulative IDirect3DDevice9::Present detours std::uint64_t d3d9_frames_shared(); // frames uploaded into the shared texture } // namespace coop::hook