diff --git a/idd/LGIdd/CIndirectDeviceContext.cpp b/idd/LGIdd/CIndirectDeviceContext.cpp index 2628d622..b10f7a2a 100644 --- a/idd/LGIdd/CIndirectDeviceContext.cpp +++ b/idd/LGIdd/CIndirectDeviceContext.cpp @@ -165,11 +165,12 @@ void CIndirectDeviceContext::FinishInit(UINT connectorIndex) return; } - auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(createOut.MonitorObject); - wrapper->context = new CIndirectMonitorContext(createOut.MonitorObject, this); + m_monitor = createOut.MonitorObject; + auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(m_monitor); + wrapper->context = new CIndirectMonitorContext(m_monitor, this); IDARG_OUT_MONITORARRIVAL out; - status = IddCxMonitorArrival(createOut.MonitorObject, &out); + status = IddCxMonitorArrival(m_monitor, &out); } bool CIndirectDeviceContext::SetupLGMP() @@ -366,6 +367,13 @@ void CIndirectDeviceContext::LGMPTimer() lgmpHostAckData(m_pointerQueue); } + + if (lgmpHostQueueNewSubs(m_frameQueue) && m_monitor) + { + auto* wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(m_monitor); + if (wrapper) + wrapper->context->ResendLastFrame(); + } } void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FORMAT format, void* data) @@ -373,11 +381,12 @@ void CIndirectDeviceContext::SendFrame(int width, int height, int pitch, DXGI_FO if (!m_lgmp || !m_frameQueue) return; - if (m_width != width || m_height != height || m_format != format) + if (m_width != width || m_height != height || m_pitch != pitch || m_format != format) { m_width = width; m_height = height; m_format = format; + m_pitch = pitch; ++m_formatVer; } diff --git a/idd/LGIdd/CIndirectDeviceContext.h b/idd/LGIdd/CIndirectDeviceContext.h index 611db8e2..afdeca98 100644 --- a/idd/LGIdd/CIndirectDeviceContext.h +++ b/idd/LGIdd/CIndirectDeviceContext.h @@ -19,6 +19,8 @@ class CIndirectDeviceContext private: WDFDEVICE m_wdfDevice; IDDCX_ADAPTER m_adapter = nullptr; + IDDCX_MONITOR m_monitor = nullptr; + CIVSHMEM m_ivshmem; PLGMPHost m_lgmp = nullptr; @@ -36,7 +38,9 @@ private: int m_width = 0; int m_height = 0; + int m_pitch = 0; DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN; + void * m_data = nullptr; bool SetupLGMP(); diff --git a/idd/LGIdd/CIndirectMonitorContext.h b/idd/LGIdd/CIndirectMonitorContext.h index 23cfb704..e233c388 100644 --- a/idd/LGIdd/CIndirectMonitorContext.h +++ b/idd/LGIdd/CIndirectMonitorContext.h @@ -22,6 +22,12 @@ public: void AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID renderAdapter, HANDLE newFrameEvent); void UnassignSwapChain(); + + inline void ResendLastFrame() + { + if (m_thread) + m_thread->ResendLastFrame(); + } }; struct CIndirectMonitorContextWrapper diff --git a/idd/LGIdd/CSwapChainProcessor.cpp b/idd/LGIdd/CSwapChainProcessor.cpp index 83adfc39..5d556f2b 100644 --- a/idd/LGIdd/CSwapChainProcessor.cpp +++ b/idd/LGIdd/CSwapChainProcessor.cpp @@ -3,11 +3,16 @@ #include #include "Debug.h" -#define LOCK_CONTEXT() \ - while (InterlockedCompareExchange((volatile LONG*)&m_contextLock, 1, 0) != 0) {}; +#define LOCK(lock) \ + while (InterlockedCompareExchange((volatile LONG*)&(lock), 1, 0) != 0) {}; -#define UNLOCK_CONTEXT() \ - InterlockedExchange((volatile LONG*)&m_contextLock, 0); +#define UNLOCK(lock) \ + InterlockedExchange((volatile LONG*)&(lock), 0); + +#define LOCK_CONTEXT() LOCK(m_contextLock); +#define UNLOCK_CONTEXT() UNLOCK(m_contextLock); +#define LOCK_ST(st) LOCK((st).lock); +#define UNLOCK_ST(st) UNLOCK((st).lock); CSwapChainProcessor::CSwapChainProcessor(CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain, std::shared_ptr device, HANDLE newFrameEvent) : @@ -197,6 +202,7 @@ void CSwapChainProcessor::FrameThread() } StagingTexture & st = m_cpuTex[m_texRIndex]; + LOCK(st); LOCK_CONTEXT(); HRESULT status = m_device->m_context->Map(st.tex.Get(), 0, D3D11_MAP_READ, @@ -205,6 +211,7 @@ void CSwapChainProcessor::FrameThread() if (FAILED(status)) { + UNLOCK(st); if (status == DXGI_ERROR_WAS_STILL_DRAWING) continue; @@ -219,8 +226,11 @@ void CSwapChainProcessor::FrameThread() m_devContext->SendFrame(st.width, st.height, st.map.RowPitch, st.format, st.map.pData); InterlockedAdd(&m_copyCount, -1); + m_lastIndex = m_texRIndex; if (++m_texRIndex == STAGING_TEXTURES) m_texRIndex = 0; + + UNLOCK(st); } } @@ -254,4 +264,21 @@ bool CSwapChainProcessor::SetupStagingTexture(StagingTexture & st, int width, in } return true; +} + +void CSwapChainProcessor::ResendLastFrame() +{ + LOCK_CONTEXT() + StagingTexture & st = m_cpuTex[m_lastIndex]; + LOCK_ST(st); + UNLOCK_CONTEXT(); + + if (!st.map.pData) + { + UNLOCK_ST(st); + return; + } + + m_devContext->SendFrame(st.width, st.height, st.map.RowPitch, st.format, st.map.pData); + UNLOCK_ST(st); } \ No newline at end of file diff --git a/idd/LGIdd/CSwapChainProcessor.h b/idd/LGIdd/CSwapChainProcessor.h index 61f7b158..aa6ca9f0 100644 --- a/idd/LGIdd/CSwapChainProcessor.h +++ b/idd/LGIdd/CSwapChainProcessor.h @@ -34,6 +34,8 @@ private: struct StagingTexture { + volatile LONG lock = 0; + int width = 0; int height = 0; DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; @@ -46,6 +48,7 @@ private: volatile LONG m_contextLock = 0; int m_texRIndex = 0; int m_texWIndex = 0; + int m_lastIndex = 0; bool SetupStagingTexture(StagingTexture & st, int width, int height, DXGI_FORMAT format); @@ -53,4 +56,6 @@ public: CSwapChainProcessor(CIndirectDeviceContext * devContext, IDDCX_SWAPCHAIN hSwapChain, std::shared_ptr device, HANDLE newFrameEvent); ~CSwapChainProcessor(); + + void ResendLastFrame(); }; \ No newline at end of file