// Frame-source trait (PLAN.md locked decision 6): content producers behind // one interface — capture / remote-stream / test-pattern. v1 implements // desktop capture (DXGI duplication, M3); the trait is the streaming-bridge // and PipeWire seam. // // Contract: the source owns its producer thread and a small ring of // textures living on the RENDER device in COMMON state. A buffer index is // published only after the producer's GPU work is CPU-confirmed complete, // so consumers may sample a published texture with no cross-API sync — // just COMMON <-> PIXEL_SHADER_RESOURCE barriers around use. A published // buffer is never rewritten until two newer publishes have happened // (ring of 3); proper fence pacing is M4. #pragma once #include #include namespace sauna { class FrameSource { public: virtual ~FrameSource() = default; // Spawns the producer. renderDev outlives the source. virtual bool start(ID3D12Device* renderDev) = 0; virtual void stop() = 0; // Park the producer pipeline (zero GPU work) without tearing it down — // SteamVR coexistence: while another runtime owns the headset our // capture would only contend with its compositor. Resume republishes // the latest content. Thread-safe; default no-op for sources with no // meaningful GPU cost (test card). virtual void setPaused(bool) {} // Texture-set description for the CURRENT generation. Valid after // start() succeeds; changes only when generation() bumps. virtual uint32_t width() const = 0; virtual uint32_t height() const = 0; virtual uint32_t mipLevels() const = 0; virtual uint32_t textureCount() const = 0; virtual ID3D12Resource* texture(uint32_t i) const = 0; // Latest published buffer index, or -1 if none yet this generation. // *gen bumps whenever the texture set was recreated (e.g. display mode // change) — consumers must rebuild SRVs when it changes. virtual int latest(uint32_t* gen) const = 0; }; } // namespace sauna