diff --git a/idd/LGIdd/transport/FrameProfile.h b/idd/LGIdd/transport/FrameProfile.h index 7d0bdf51..6f3ef406 100644 --- a/idd/LGIdd/transport/FrameProfile.h +++ b/idd/LGIdd/transport/FrameProfile.h @@ -153,10 +153,14 @@ namespace Frame enum class CfgResult : uint8_t { + // The proposed route may be prepared or committed. ACCEPTED, // The transport declined this profile and permits another candidate. NEXT, + // The route is unavailable without affecting sibling routes. REJECTED, + // Preserve the active route and offer the proposal again later. RETRY, + // The frame component failed; required policy decides escalation. FAILED, }; diff --git a/idd/LGIdd/transport/ITransport.h b/idd/LGIdd/transport/ITransport.h index a4d5bb60..c2ae1766 100644 --- a/idd/LGIdd/transport/ITransport.h +++ b/idd/LGIdd/transport/ITransport.h @@ -148,6 +148,16 @@ public: virtual void RecoveryStatus(const SourceKey&, uint64_t, uint32_t, bool, Recovery, uint32_t) {} + // Profiles is an immutable, ordered preference list whose pointer remains + // valid for the lifetime of this instance. + // Probe has no side effects. Prepare changes pending state only; Commit + // promotes it without failure, while Abort preserves the active route. + virtual const FrameProfile * Profiles(unsigned& count) const = 0; + virtual CfgResult Probe(const FrameCfg& cfg) const = 0; + virtual CfgResult Prepare(const FrameCfg& cfg) = 0; + virtual void Commit() = 0; + virtual void Abort() = 0; + // Frame capabilities describe the configured instance, not transient // runtime state. CanUseMode answers are immutable for the returned // object's lifetime, and recreating an instance from the same descriptor diff --git a/idd/LGIdd/transport/lgmp/CLGMPTransport.cpp b/idd/LGIdd/transport/lgmp/CLGMPTransport.cpp index bb1e4d44..fe352b6a 100644 --- a/idd/LGIdd/transport/lgmp/CLGMPTransport.cpp +++ b/idd/LGIdd/transport/lgmp/CLGMPTransport.cpp @@ -49,6 +49,20 @@ static bool TranslateFrameScheduleFlags( return true; } +static const FrameProfile FRAME_PROFILES[] = +{ + { + FrameStorage::D3D12_TEXTURE, + FramePixel::BGRA8, + FrameSignal::SRGB, + }, + { + FrameStorage::D3D12_TEXTURE, + FramePixel::RGB10A2, + FrameSignal::PQ_BT2020, + }, +}; + CLGMPTransport::CLGMPTransport(const TransportInstance& config) : m_config(config), m_control(m_host), @@ -226,6 +240,8 @@ ITransport::ProcessResult CLGMPTransport::Process(ITransportEvents& events) void CLGMPTransport::Stop() { Atomic::Store(m_ready, false, std::memory_order_release); + Abort(); + m_hasActive = false; m_input.Stop(); } @@ -283,6 +299,62 @@ void CLGMPTransport::RecoveryStatus(const SourceKey& source, session, serial, active, wireState, wireError); } +const FrameProfile * CLGMPTransport::Profiles(unsigned& count) const +{ + count = ARRAYSIZE(FRAME_PROFILES); + return FRAME_PROFILES; +} + +CfgResult CLGMPTransport::Probe(const FrameCfg& cfg) const +{ + if (!cfg.width || !cfg.height) + return CfgResult::REJECTED; + + switch (cfg.mode) + { + case GpuMode::HARDWARE: + for (const FrameProfile& profile : FRAME_PROFILES) + if (Frame::Same(cfg.profile, profile)) + return CfgResult::ACCEPTED; + break; + + case GpuMode::SOFTWARE: + if (Frame::Same(cfg.profile, FRAME_PROFILES[0])) + return CfgResult::ACCEPTED; + break; + + default: + return CfgResult::REJECTED; + } + return CfgResult::NEXT; +} + +CfgResult CLGMPTransport::Prepare(const FrameCfg& cfg) +{ + m_hasPending = false; + const CfgResult result = Probe(cfg); + if (result != CfgResult::ACCEPTED) + return result; + + m_pendingCfg = cfg; + m_hasPending = true; + return CfgResult::ACCEPTED; +} + +void CLGMPTransport::Commit() +{ + if (!m_hasPending) + return; + m_activeCfg = m_pendingCfg; + m_hasActive = true; + m_hasPending = false; +} + +void CLGMPTransport::Abort() +{ + m_hasPending = false; +} + std::shared_ptr CLGMPTransport::GetFrameCaps() const { return m_frames.GetFrameCaps(); diff --git a/idd/LGIdd/transport/lgmp/CLGMPTransport.h b/idd/LGIdd/transport/lgmp/CLGMPTransport.h index 903e544b..23b9f867 100644 --- a/idd/LGIdd/transport/lgmp/CLGMPTransport.h +++ b/idd/LGIdd/transport/lgmp/CLGMPTransport.h @@ -42,6 +42,10 @@ private: CLGMPInputTransport m_input; CRecovery m_recovery; std::atomic m_ready = false; + FrameCfg m_activeCfg; + FrameCfg m_pendingCfg; + bool m_hasActive = false; + bool m_hasPending = false; public: explicit CLGMPTransport(const TransportInstance& config); @@ -60,6 +64,12 @@ public: uint64_t session, uint32_t serial, bool active, Recovery state, uint32_t error) override; + const FrameProfile * Profiles(unsigned& count) const override; + CfgResult Probe(const FrameCfg& cfg) const override; + CfgResult Prepare(const FrameCfg& cfg) override; + void Commit() override; + void Abort() override; + std::shared_ptr GetFrameCaps() const override; DirectFrameBufferMemory GetDirectMemory() const override;