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>
This commit is contained in:
69
host/src/capture/shared_texture.hpp
Normal file
69
host/src/capture/shared_texture.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
// Host-side consumer of the injected Present-hook's shared backbuffer texture.
|
||||
// Opens the keyed-mutex texture the hook publishes (coop_video_<pid>) by name,
|
||||
// copies the latest frame into a private texture under the keyed mutex, and
|
||||
// exposes an SRV the FrameRenderer can draw -- the lower-latency alternative to
|
||||
// Windows Graphics Capture. See hook/src/present_hook.cpp and coop/protocol.hpp.
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <d3d11_1.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
#include "ipc/ipc_server.hpp"
|
||||
|
||||
namespace coop
|
||||
{
|
||||
|
||||
class SharedTextureSource
|
||||
{
|
||||
public:
|
||||
// Binds to the host's device (must support ID3D11Device1). Returns false if not.
|
||||
bool init(ID3D11Device* device);
|
||||
|
||||
// Polls the hook's video channel for `pid`. (Re)opens the shared texture when
|
||||
// the pid/dimensions/format change, and copies the newest frame into the
|
||||
// private texture under the keyed mutex. Returns true if a frame is available
|
||||
// to draw (sticky: keeps the last copy until a new one or a reset).
|
||||
bool update(const VideoShareView& share, unsigned long pid);
|
||||
|
||||
// Drop the opened resources (target changed / mirror turned off).
|
||||
void reset();
|
||||
|
||||
[[nodiscard]] ID3D11ShaderResourceView* srv() const
|
||||
{
|
||||
return srv_.Get();
|
||||
}
|
||||
[[nodiscard]] std::uint32_t width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
[[nodiscard]] std::uint32_t height() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
[[nodiscard]] std::uint64_t frames_copied() const
|
||||
{
|
||||
return frames_copied_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool reopen(unsigned long pid, const VideoShareView& share);
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D11Device1> device_;
|
||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext> ctx_;
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> shared_; // opened from the hook, by name
|
||||
Microsoft::WRL::ComPtr<IDXGIKeyedMutex> mutex_;
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> private_; // our sampled copy
|
||||
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> srv_;
|
||||
|
||||
unsigned long pid_ = 0;
|
||||
std::uint32_t width_ = 0;
|
||||
std::uint32_t height_ = 0;
|
||||
std::uint32_t format_ = 0;
|
||||
std::uint32_t last_generation_ = 0;
|
||||
std::uint64_t frames_copied_ = 0;
|
||||
};
|
||||
|
||||
} // namespace coop
|
||||
Reference in New Issue
Block a user