Phase 1b: video mirror via Windows Graphics Capture
Mirror the injected game's window into the host's borderless window so Steam RPT streams a live copy of the game. No injection needed for video. - capture/window_capture: WGC capture of a target HWND. Wraps our D3D11 device as an IDirect3DDevice, creates a free-threaded frame pool + capture session, hides the cursor and (best-effort) the capture border. Frames arrive on a WGC thread and are handed to the render thread, which copies the newest into a shader-resource texture and draws it -- keeping all D3D11 context use on one thread. Handles window resize via frame-pool Recreate. - capture/frame_renderer: fullscreen-triangle shader that blits the captured texture letterboxed (aspect-preserved) into the window. - capture_panel: "Mirror game window" toggle + lifecycle; target HWND comes from the hook's reported game window. - main: winrt apartment init; mirrored frame drawn as background, ImGui on top. - CMake: link windowsapp + d3dcompiler. Verified: builds clean; host starts (apartment init + shader compile succeed). Visual capture quality/latency to be judged on a real game. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
// CoopAllTheThings host -- Phase 0 spike.
|
||||
// CoopAllTheThings host.
|
||||
//
|
||||
// Brings up the borderless window Steam Remote Play Together will capture and an
|
||||
// ImGui overlay that lists every controller it can see. The goal of this build
|
||||
// is to validate the riskiest assumption end-to-end: launch this exe under a
|
||||
// donor appid (steam -applaunch <donorAppId> <path-to-host.exe>), invite a
|
||||
// friend, and confirm (a) the window streams and (b) the guest's gamepad shows
|
||||
// up in the overlay. Capture/injection are built on top of this once it holds.
|
||||
// Borderless window that Steam Remote Play Together captures, plus the overlay
|
||||
// that drives the tool: it forwards controller input into an injected game
|
||||
// (Injection panel), spoofs the game's focus, and mirrors the game's window into
|
||||
// this window via Windows Graphics Capture (Video mirror panel).
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
|
||||
#include "capture_panel.hpp"
|
||||
#include "d3d11_window.hpp"
|
||||
#include "debug_overlay.hpp"
|
||||
#include "imgui_layer.hpp"
|
||||
@@ -38,17 +39,34 @@ int run()
|
||||
|
||||
auto input = std::make_unique<coop::XInputSource>();
|
||||
coop::InjectionPanel injection;
|
||||
coop::CapturePanel capture;
|
||||
if (!capture.init(window.device()))
|
||||
{
|
||||
MessageBoxW(nullptr, L"Failed to initialize the video mirror.", L"CoopAllTheThings", MB_ICONERROR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (window.pump_messages())
|
||||
{
|
||||
input->poll();
|
||||
injection.publish(input->pads());
|
||||
capture.set_target(injection.game_hwnd());
|
||||
|
||||
imgui.begin_frame();
|
||||
coop::draw_debug_overlay(*input);
|
||||
injection.draw();
|
||||
capture.draw_ui();
|
||||
|
||||
window.render_frame([&imgui]() { imgui.end_frame(); });
|
||||
RECT client = {};
|
||||
GetClientRect(window.hwnd(), &client);
|
||||
const auto dst_w = static_cast<std::uint32_t>(client.right - client.left);
|
||||
const auto dst_h = static_cast<std::uint32_t>(client.bottom - client.top);
|
||||
|
||||
// Mirrored frame first (the window background), ImGui overlay on top.
|
||||
window.render_frame([&]() {
|
||||
capture.render(window.context(), dst_w, dst_h);
|
||||
imgui.end_frame();
|
||||
});
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -58,5 +76,10 @@ int run()
|
||||
|
||||
int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
|
||||
{
|
||||
return run();
|
||||
// WGC requires an initialized apartment; multi-threaded suits the
|
||||
// free-threaded frame pool.
|
||||
winrt::init_apartment(winrt::apartment_type::multi_threaded);
|
||||
const int result = run();
|
||||
winrt::uninit_apartment();
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user