Files
CoopAllTheThings/host/src/capture_panel.hpp
BlackMark 36b861d167 Phase 2: Present-hook video path (shared-texture mirror)
Add an injected IDXGISwapChain::Present / Present1 hook as a lower-latency,
border-free alternative to WGC. The hook copies the swapchain backbuffer into a
shared keyed-mutex texture (coop_video_<pid>); the host opens it by name and
samples it. New opt-in HookSubsys_Video (protocol v6 -> v7); the Video mirror
panel gains a WGC vs Hooked source toggle that installs/removes the subsystem.

Verified by present_hook_test (drives a real D3D11 swapchain end-to-end and reads
the rendered pixels back through the shared texture) and against Phantom Brave
(D3D9: hook installs cleanly and stays idle, WGC fallback). All 5 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 11:34:12 +02:00

67 lines
1.8 KiB
C++

// Owns the video-mirror pipeline and its UI. Two interchangeable sources feed the
// same letterboxed renderer: Windows Graphics Capture (no injection, the default)
// and the injected Present-hook's shared backbuffer texture (lower latency, needs
// the video subsystem hooked). The target window/pid come from the injected hook.
#pragma once
#include <cstdint>
#include <d3d11.h>
#include <windows.h>
#include "capture/frame_renderer.hpp"
#include "capture/shared_texture.hpp"
#include "capture/window_capture.hpp"
#include "ui/app_chrome.hpp"
namespace coop
{
class InjectionPanel;
class CapturePanel
{
public:
bool init(ID3D11Device* device);
// The window to mirror via WGC (0 if none yet); typically the injected game's HWND.
void set_target(HWND target)
{
target_ = target;
}
// The injection panel supplies the target pid + Present-hook video channel and
// lets this panel install/remove the video subsystem when the source is Hooked.
void set_injection(InjectionPanel* injection)
{
injection_ = injection;
}
// `stats` are the host's render frame-timing, drawn as the mirror's
// frametime / FPS graphs (this window is what the mirror renders into).
void draw_ui(const FrameStats& stats);
// Render thread: draw the mirrored frame as the window background.
void render(ID3D11DeviceContext* ctx, std::uint32_t dst_w, std::uint32_t dst_h);
private:
enum Source : int
{
Source_Wgc = 0, // Windows Graphics Capture
Source_Hooked = 1, // injected Present-hook shared texture
};
void draw_perf_graphs(const FrameStats& stats);
ID3D11Device* device_ = nullptr;
FrameRenderer renderer_;
WindowCapture capture_;
SharedTextureSource shared_;
InjectionPanel* injection_ = nullptr;
HWND target_ = nullptr;
bool enabled_ = false;
int source_ = Source_Wgc;
};
} // namespace coop