mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-04 06:12:04 +00:00
[idd] skip copies for static frames
Treat IddCx's single empty dirty rectangle as no image update instead of promoting it to full damage. Preserve pending damage and format changes, and fall back to full damage when legacy move regions are present.
This commit is contained in:
@@ -154,6 +154,7 @@ void CInteropResource::SetDirtyRects(const RECT * dirtyRects, unsigned nbDirtyRe
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nbDirtyRects)
|
||||||
memcpy(m_dirtyRects, dirtyRects, nbDirtyRects * sizeof(*m_dirtyRects));
|
memcpy(m_dirtyRects, dirtyRects, nbDirtyRects * sizeof(*m_dirtyRects));
|
||||||
m_nbDirtyRects = nbDirtyRects;
|
m_nbDirtyRects = nbDirtyRects;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,23 @@ static uint64_t Nanotime()
|
|||||||
ticks % frequency * 1000000000ULL / frequency;
|
ticks % frequency * 1000000000ULL / frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool FrameMetadataChanged(const D12FrameFormat& previous,
|
||||||
|
const D12FrameFormat& current)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
previous.hdrMetadata != current.hdrMetadata ||
|
||||||
|
previous.sdrWhiteLevel != current.sdrWhiteLevel ||
|
||||||
|
(current.hdrMetadata &&
|
||||||
|
(memcmp(previous.displayPrimary, current.displayPrimary,
|
||||||
|
sizeof(current.displayPrimary)) != 0 ||
|
||||||
|
memcmp(previous.whitePoint, current.whitePoint,
|
||||||
|
sizeof(current.whitePoint)) != 0 ||
|
||||||
|
previous.maxDisplayLuminance != current.maxDisplayLuminance ||
|
||||||
|
previous.minDisplayLuminance != current.minDisplayLuminance ||
|
||||||
|
previous.maxContentLightLevel != current.maxContentLightLevel ||
|
||||||
|
previous.maxFrameAverageLightLevel != current.maxFrameAverageLightLevel));
|
||||||
|
}
|
||||||
|
|
||||||
CSwapChainProcessor::CSwapChainProcessor(CIndirectMonitorContext * monitorContext,
|
CSwapChainProcessor::CSwapChainProcessor(CIndirectMonitorContext * monitorContext,
|
||||||
UINT64 assignmentGeneration, IDDCX_MONITOR monitor,
|
UINT64 assignmentGeneration, IDDCX_MONITOR monitor,
|
||||||
CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain,
|
CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain,
|
||||||
@@ -201,6 +218,7 @@ bool CSwapChainProcessor::SwapChainThreadCore()
|
|||||||
|
|
||||||
UINT frameNumber = 0;
|
UINT frameNumber = 0;
|
||||||
UINT dirtyRectCount = 0;
|
UINT dirtyRectCount = 0;
|
||||||
|
UINT moveRegionCount = 0;
|
||||||
ComPtr<IDXGIResource> surface;
|
ComPtr<IDXGIResource> surface;
|
||||||
|
|
||||||
// The surface colour space is the source of truth for the content format.
|
// The surface colour space is the source of truth for the content format.
|
||||||
@@ -242,6 +260,7 @@ bool CSwapChainProcessor::SwapChainThreadCore()
|
|||||||
{
|
{
|
||||||
frameNumber = buffer.MetaData.PresentationFrameNumber;
|
frameNumber = buffer.MetaData.PresentationFrameNumber;
|
||||||
dirtyRectCount = buffer.MetaData.DirtyRectCount;
|
dirtyRectCount = buffer.MetaData.DirtyRectCount;
|
||||||
|
moveRegionCount = buffer.MetaData.MoveRegionCount;
|
||||||
surface = buffer.MetaData.pSurface;
|
surface = buffer.MetaData.pSurface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,8 +288,8 @@ bool CSwapChainProcessor::SwapChainThreadCore()
|
|||||||
if (frameNumber != lastFrameNumber)
|
if (frameNumber != lastFrameNumber)
|
||||||
{
|
{
|
||||||
lastFrameNumber = frameNumber;
|
lastFrameNumber = frameNumber;
|
||||||
if (!SwapChainNewFrame(surface, dirtyRectCount, colorSpace,
|
if (!SwapChainNewFrame(surface, dirtyRectCount, moveRegionCount,
|
||||||
sdrWhiteLevel, Nanotime() - captureStart))
|
colorSpace, sdrWhiteLevel, Nanotime() - captureStart))
|
||||||
DEBUG_WARN("Failed to submit frame");
|
DEBUG_WARN("Failed to submit frame");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,8 +513,9 @@ bool CSwapChainProcessor::GetContentHDRMetadata(D12FrameFormat& format) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer,
|
bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer,
|
||||||
unsigned dirtyRectCount, DXGI_COLOR_SPACE_TYPE colorSpace,
|
unsigned dirtyRectCount, unsigned moveRegionCount,
|
||||||
UINT sdrWhiteLevel, uint64_t captureTime)
|
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel,
|
||||||
|
uint64_t captureTime)
|
||||||
{
|
{
|
||||||
// Preserve the fast drop path: never hold an IddCx frame while waiting for
|
// Preserve the fast drop path: never hold an IddCx frame while waiting for
|
||||||
// a slow or disconnected client. We have not read its rectangles, so force
|
// a slow or disconnected client. We have not read its rectangles, so force
|
||||||
@@ -533,8 +553,11 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
srcRes->Signal();
|
srcRes->Signal();
|
||||||
|
|
||||||
RECT dirtyRects[LG_MAX_DIRTY_RECTS] = {0};
|
RECT dirtyRects[LG_MAX_DIRTY_RECTS] = {0};
|
||||||
if (dirtyRectCount > ARRAYSIZE(dirtyRects))
|
bool noImageUpdate = false;
|
||||||
|
if (moveRegionCount || dirtyRectCount > ARRAYSIZE(dirtyRects))
|
||||||
{
|
{
|
||||||
|
// Move regions are not represented by the dirty rectangle list. Copy the
|
||||||
|
// full surface so the alternating destinations remain coherent.
|
||||||
srcRes->SetFullDamage();
|
srcRes->SetFullDamage();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -550,11 +573,21 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
DEBUG_ERROR_HR(hr, "IddCxSwapChainGetDirtyRects Failed");
|
DEBUG_ERROR_HR(hr, "IddCxSwapChainGetDirtyRects Failed");
|
||||||
srcRes->SetFullDamage();
|
srcRes->SetFullDamage();
|
||||||
}
|
}
|
||||||
|
else if (dirtyOut.DirtyRectOutCount == 1 &&
|
||||||
|
dirtyRects[0].left == 0 && dirtyRects[0].top == 0 &&
|
||||||
|
dirtyRects[0].right == 0 && dirtyRects[0].bottom == 0)
|
||||||
|
{
|
||||||
|
// One empty rectangle is IddCx's static-desktop re-encode marker. It
|
||||||
|
// does not describe an image update and must not become full damage.
|
||||||
|
noImageUpdate = true;
|
||||||
|
srcRes->SetDirtyRects(nullptr, 0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
srcRes->SetDirtyRects(dirtyRects, dirtyOut.DirtyRectOutCount);
|
srcRes->SetDirtyRects(dirtyRects, dirtyOut.DirtyRectOutCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC srcDesc = srcRes->GetRes()->GetDesc();
|
D3D12_RESOURCE_DESC srcDesc = srcRes->GetRes()->GetDesc();
|
||||||
|
if (!noImageUpdate)
|
||||||
AccumulateFrameDamage(
|
AccumulateFrameDamage(
|
||||||
srcRes->GetDirtyRects(), srcRes->GetDirtyRectCount());
|
srcRes->GetDirtyRects(), srcRes->GetDirtyRectCount());
|
||||||
|
|
||||||
@@ -643,6 +676,8 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool frameMetadataChanged = noImageUpdate &&
|
||||||
|
FrameMetadataChanged(m_postProcessor.GetOutputFormat(), srcFormat);
|
||||||
bool postProcessFormatChanged = false;
|
bool postProcessFormatChanged = false;
|
||||||
if (!m_postProcessor.Configure(srcFormat, &postProcessFormatChanged))
|
if (!m_postProcessor.Configure(srcFormat, &postProcessFormatChanged))
|
||||||
return false;
|
return false;
|
||||||
@@ -652,6 +687,11 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
m_nbDirtyRects = 0;
|
m_nbDirtyRects = 0;
|
||||||
SetFullPendingDamage();
|
SetFullPendingDamage();
|
||||||
}
|
}
|
||||||
|
else if (frameMetadataChanged)
|
||||||
|
SetFullPendingDamage();
|
||||||
|
|
||||||
|
if (noImageUpdate && !m_hasPendingDamage)
|
||||||
|
return true;
|
||||||
|
|
||||||
const D12FrameFormat& dstFormat = m_postProcessor.GetOutputFormat();
|
const D12FrameFormat& dstFormat = m_postProcessor.GetOutputFormat();
|
||||||
|
|
||||||
|
|||||||
@@ -101,8 +101,10 @@ private:
|
|||||||
void UpdateHDRMetadata(const IDDCX_METADATA2& metadata);
|
void UpdateHDRMetadata(const IDDCX_METADATA2& metadata);
|
||||||
#endif
|
#endif
|
||||||
bool GetContentHDRMetadata(D12FrameFormat& format) const;
|
bool GetContentHDRMetadata(D12FrameFormat& format) const;
|
||||||
bool SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer, unsigned dirtyRectCount,
|
bool SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer,
|
||||||
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel, uint64_t captureTime);
|
unsigned dirtyRectCount, unsigned moveRegionCount,
|
||||||
|
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel,
|
||||||
|
uint64_t captureTime);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSwapChainProcessor(CIndirectMonitorContext * monitorContext, UINT64 assignmentGeneration,
|
CSwapChainProcessor(CIndirectMonitorContext * monitorContext, UINT64 assignmentGeneration,
|
||||||
|
|||||||
Reference in New Issue
Block a user