mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 13:37:22 +00:00
[idd] resend the last captured frame if a new client connects
This commit is contained in:
parent
fd0cc6aa10
commit
d6b26b0eb1
@ -165,11 +165,12 @@ void CIndirectDeviceContext::FinishInit(UINT connectorIndex)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(createOut.MonitorObject);
|
m_monitor = createOut.MonitorObject;
|
||||||
wrapper->context = new CIndirectMonitorContext(createOut.MonitorObject, this);
|
auto * wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(m_monitor);
|
||||||
|
wrapper->context = new CIndirectMonitorContext(m_monitor, this);
|
||||||
|
|
||||||
IDARG_OUT_MONITORARRIVAL out;
|
IDARG_OUT_MONITORARRIVAL out;
|
||||||
status = IddCxMonitorArrival(createOut.MonitorObject, &out);
|
status = IddCxMonitorArrival(m_monitor, &out);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CIndirectDeviceContext::SetupLGMP()
|
bool CIndirectDeviceContext::SetupLGMP()
|
||||||
@ -366,6 +367,13 @@ void CIndirectDeviceContext::LGMPTimer()
|
|||||||
|
|
||||||
lgmpHostAckData(m_pointerQueue);
|
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)
|
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)
|
if (!m_lgmp || !m_frameQueue)
|
||||||
return;
|
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_width = width;
|
||||||
m_height = height;
|
m_height = height;
|
||||||
m_format = format;
|
m_format = format;
|
||||||
|
m_pitch = pitch;
|
||||||
++m_formatVer;
|
++m_formatVer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ class CIndirectDeviceContext
|
|||||||
private:
|
private:
|
||||||
WDFDEVICE m_wdfDevice;
|
WDFDEVICE m_wdfDevice;
|
||||||
IDDCX_ADAPTER m_adapter = nullptr;
|
IDDCX_ADAPTER m_adapter = nullptr;
|
||||||
|
IDDCX_MONITOR m_monitor = nullptr;
|
||||||
|
|
||||||
CIVSHMEM m_ivshmem;
|
CIVSHMEM m_ivshmem;
|
||||||
|
|
||||||
PLGMPHost m_lgmp = nullptr;
|
PLGMPHost m_lgmp = nullptr;
|
||||||
@ -36,7 +38,9 @@ private:
|
|||||||
|
|
||||||
int m_width = 0;
|
int m_width = 0;
|
||||||
int m_height = 0;
|
int m_height = 0;
|
||||||
|
int m_pitch = 0;
|
||||||
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
|
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
void * m_data = nullptr;
|
||||||
|
|
||||||
bool SetupLGMP();
|
bool SetupLGMP();
|
||||||
|
|
||||||
|
@ -22,6 +22,12 @@ public:
|
|||||||
|
|
||||||
void AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID renderAdapter, HANDLE newFrameEvent);
|
void AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID renderAdapter, HANDLE newFrameEvent);
|
||||||
void UnassignSwapChain();
|
void UnassignSwapChain();
|
||||||
|
|
||||||
|
inline void ResendLastFrame()
|
||||||
|
{
|
||||||
|
if (m_thread)
|
||||||
|
m_thread->ResendLastFrame();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CIndirectMonitorContextWrapper
|
struct CIndirectMonitorContextWrapper
|
||||||
|
@ -3,11 +3,16 @@
|
|||||||
#include <avrt.h>
|
#include <avrt.h>
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
|
|
||||||
#define LOCK_CONTEXT() \
|
#define LOCK(lock) \
|
||||||
while (InterlockedCompareExchange((volatile LONG*)&m_contextLock, 1, 0) != 0) {};
|
while (InterlockedCompareExchange((volatile LONG*)&(lock), 1, 0) != 0) {};
|
||||||
|
|
||||||
#define UNLOCK_CONTEXT() \
|
#define UNLOCK(lock) \
|
||||||
InterlockedExchange((volatile LONG*)&m_contextLock, 0);
|
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,
|
CSwapChainProcessor::CSwapChainProcessor(CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain,
|
||||||
std::shared_ptr<Direct3DDevice> device, HANDLE newFrameEvent) :
|
std::shared_ptr<Direct3DDevice> device, HANDLE newFrameEvent) :
|
||||||
@ -197,6 +202,7 @@ void CSwapChainProcessor::FrameThread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
StagingTexture & st = m_cpuTex[m_texRIndex];
|
StagingTexture & st = m_cpuTex[m_texRIndex];
|
||||||
|
LOCK(st);
|
||||||
|
|
||||||
LOCK_CONTEXT();
|
LOCK_CONTEXT();
|
||||||
HRESULT status = m_device->m_context->Map(st.tex.Get(), 0, D3D11_MAP_READ,
|
HRESULT status = m_device->m_context->Map(st.tex.Get(), 0, D3D11_MAP_READ,
|
||||||
@ -205,6 +211,7 @@ void CSwapChainProcessor::FrameThread()
|
|||||||
|
|
||||||
if (FAILED(status))
|
if (FAILED(status))
|
||||||
{
|
{
|
||||||
|
UNLOCK(st);
|
||||||
if (status == DXGI_ERROR_WAS_STILL_DRAWING)
|
if (status == DXGI_ERROR_WAS_STILL_DRAWING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -219,8 +226,11 @@ void CSwapChainProcessor::FrameThread()
|
|||||||
|
|
||||||
m_devContext->SendFrame(st.width, st.height, st.map.RowPitch, st.format, st.map.pData);
|
m_devContext->SendFrame(st.width, st.height, st.map.RowPitch, st.format, st.map.pData);
|
||||||
InterlockedAdd(&m_copyCount, -1);
|
InterlockedAdd(&m_copyCount, -1);
|
||||||
|
m_lastIndex = m_texRIndex;
|
||||||
if (++m_texRIndex == STAGING_TEXTURES)
|
if (++m_texRIndex == STAGING_TEXTURES)
|
||||||
m_texRIndex = 0;
|
m_texRIndex = 0;
|
||||||
|
|
||||||
|
UNLOCK(st);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,3 +265,20 @@ bool CSwapChainProcessor::SetupStagingTexture(StagingTexture & st, int width, in
|
|||||||
|
|
||||||
return true;
|
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);
|
||||||
|
}
|
@ -34,6 +34,8 @@ private:
|
|||||||
|
|
||||||
struct StagingTexture
|
struct StagingTexture
|
||||||
{
|
{
|
||||||
|
volatile LONG lock = 0;
|
||||||
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
||||||
@ -46,6 +48,7 @@ private:
|
|||||||
volatile LONG m_contextLock = 0;
|
volatile LONG m_contextLock = 0;
|
||||||
int m_texRIndex = 0;
|
int m_texRIndex = 0;
|
||||||
int m_texWIndex = 0;
|
int m_texWIndex = 0;
|
||||||
|
int m_lastIndex = 0;
|
||||||
|
|
||||||
bool SetupStagingTexture(StagingTexture & st, int width, int height, DXGI_FORMAT format);
|
bool SetupStagingTexture(StagingTexture & st, int width, int height, DXGI_FORMAT format);
|
||||||
|
|
||||||
@ -53,4 +56,6 @@ public:
|
|||||||
CSwapChainProcessor(CIndirectDeviceContext * devContext, IDDCX_SWAPCHAIN hSwapChain,
|
CSwapChainProcessor(CIndirectDeviceContext * devContext, IDDCX_SWAPCHAIN hSwapChain,
|
||||||
std::shared_ptr<Direct3DDevice> device, HANDLE newFrameEvent);
|
std::shared_ptr<Direct3DDevice> device, HANDLE newFrameEvent);
|
||||||
~CSwapChainProcessor();
|
~CSwapChainProcessor();
|
||||||
|
|
||||||
|
void ResendLastFrame();
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user