[idd] capture: retire damage before copy submission

Retire candidate damage before submitting its publication copy. A fast
completion callback can otherwise release and reuse the candidate while
the publisher is still reading its fields and damage tail.
This commit is contained in:
Geoffrey McRae
2026-08-06 12:17:26 +10:00
parent c56b10b194
commit f04775823d

View File

@@ -1254,29 +1254,8 @@ bool CSwapChainProcessor::PublishNewestCandidate(
return false;
}
if (!copySlot->Execute())
{
AcquireSRWLockShared(&m_candidateLock);
const bool callbackPending =
candidate.state == CANDIDATE_PUBLISHING;
ReleaseSRWLockShared(&m_candidateLock);
if (callbackPending && !copySlot->HasSubmittedWork())
{
m_devContext->FailFrameBuffer(buffer.frameIndex);
SetFullPendingDamage();
ReleaseCandidate(candidateIndex);
}
m_devContext->ForceFrame();
AcquireSRWLockExclusive(&m_candidateLock);
for (FrameCandidate& held : m_candidates)
if (held.state == CANDIDATE_HELD)
held.state = CANDIDATE_READY;
ReleaseSRWLockExclusive(&m_candidateLock);
SignalCandidateState();
return false;
}
// Retire the candidate damage before submission. The completion callback
// may run before Execute returns and make this candidate reusable.
AcquireSRWLockExclusive(&m_damageLock);
if (candidate.nbDirtyRects)
memcpy(m_dirtyRects, candidate.dirtyRects,
@@ -1295,6 +1274,31 @@ bool CSwapChainProcessor::PublishNewestCandidate(
}
ReleaseSRWLockExclusive(&m_damageLock);
if (!copySlot->Execute())
{
// The logical damage state was advanced before submission. Force a full
// repair whether submission failed or its callback reported the failure.
SetFullPendingDamage();
AcquireSRWLockShared(&m_candidateLock);
const bool callbackPending =
candidate.state == CANDIDATE_PUBLISHING;
ReleaseSRWLockShared(&m_candidateLock);
if (callbackPending && !copySlot->HasSubmittedWork())
{
m_devContext->FailFrameBuffer(buffer.frameIndex);
ReleaseCandidate(candidateIndex);
}
m_devContext->ForceFrame();
AcquireSRWLockExclusive(&m_candidateLock);
for (FrameCandidate& held : m_candidates)
if (held.state == CANDIDATE_HELD)
held.state = CANDIDATE_READY;
ReleaseSRWLockExclusive(&m_candidateLock);
SignalCandidateState();
return false;
}
m_devContext->CommitFrameBuffer(
buffer.frameIndex, schedule, periodic);