[idd] transport: add frame sink boundary

This commit is contained in:
Geoffrey McRae
2026-08-12 16:45:01 +10:00
parent 801a1e58f8
commit bd4d31f0bd
21 changed files with 634 additions and 81 deletions

View File

@@ -61,6 +61,7 @@
<ClCompile Include="postprocess\effect\CHDR16to10Effect.cpp" /> <ClCompile Include="postprocess\effect\CHDR16to10Effect.cpp" />
<ClCompile Include="postprocess\effect\CRGB24Effect.cpp" /> <ClCompile Include="postprocess\effect\CRGB24Effect.cpp" />
<ClCompile Include="transport\CControlHub.cpp" /> <ClCompile Include="transport\CControlHub.cpp" />
<ClCompile Include="transport\CFrameHub.cpp" />
<ClCompile Include="transport\CTransportManager.cpp" /> <ClCompile Include="transport\CTransportManager.cpp" />
<ClCompile Include="transport\TransportFactory.cpp" /> <ClCompile Include="transport\TransportFactory.cpp" />
<ClCompile Include="transport\lgmp\CIVSHMEM.cpp" /> <ClCompile Include="transport\lgmp\CIVSHMEM.cpp" />
@@ -109,10 +110,12 @@
<ClInclude Include="postprocess\effect\CHDR16to10Effect.h" /> <ClInclude Include="postprocess\effect\CHDR16to10Effect.h" />
<ClInclude Include="postprocess\effect\CRGB24Effect.h" /> <ClInclude Include="postprocess\effect\CRGB24Effect.h" />
<ClInclude Include="transport\CControlHub.h" /> <ClInclude Include="transport\CControlHub.h" />
<ClInclude Include="transport\CFrameHub.h" />
<ClInclude Include="transport\CTransportManager.h" /> <ClInclude Include="transport\CTransportManager.h" />
<ClInclude Include="transport\DirectFrameBufferMemory.h" /> <ClInclude Include="transport\DirectFrameBufferMemory.h" />
<ClInclude Include="transport\FrameMemoryLimits.h" /> <ClInclude Include="transport\FrameMemoryLimits.h" />
<ClInclude Include="transport\IControlTransport.h" /> <ClInclude Include="transport\IControlTransport.h" />
<ClInclude Include="transport\IFrameSink.h" />
<ClInclude Include="transport\IFrameTransport.h" /> <ClInclude Include="transport\IFrameTransport.h" />
<ClInclude Include="transport\IInputTransport.h" /> <ClInclude Include="transport\IInputTransport.h" />
<ClInclude Include="transport\ITransport.h" /> <ClInclude Include="transport\ITransport.h" />

View File

@@ -157,6 +157,9 @@
<ClInclude Include="transport\CControlHub.h"> <ClInclude Include="transport\CControlHub.h">
<Filter>Transport</Filter> <Filter>Transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="transport\CFrameHub.h">
<Filter>Transport</Filter>
</ClInclude>
<ClInclude Include="transport\CTransportManager.h"> <ClInclude Include="transport\CTransportManager.h">
<Filter>Transport</Filter> <Filter>Transport</Filter>
</ClInclude> </ClInclude>
@@ -169,6 +172,9 @@
<ClInclude Include="transport\IControlTransport.h"> <ClInclude Include="transport\IControlTransport.h">
<Filter>Transport</Filter> <Filter>Transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="transport\IFrameSink.h">
<Filter>Transport</Filter>
</ClInclude>
<ClInclude Include="transport\IFrameTransport.h"> <ClInclude Include="transport\IFrameTransport.h">
<Filter>Transport</Filter> <Filter>Transport</Filter>
</ClInclude> </ClInclude>
@@ -300,6 +306,9 @@
<ClCompile Include="transport\CControlHub.cpp"> <ClCompile Include="transport\CControlHub.cpp">
<Filter>Transport</Filter> <Filter>Transport</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="transport\CFrameHub.cpp">
<Filter>Transport</Filter>
</ClCompile>
<ClCompile Include="transport\CTransportManager.cpp"> <ClCompile Include="transport\CTransportManager.cpp">
<Filter>Transport</Filter> <Filter>Transport</Filter>
</ClCompile> </ClCompile>

View File

@@ -39,11 +39,11 @@ void CFrameBufferPool::Reset()
CFrameBufferResource * CFrameBufferPool::Get( CFrameBufferResource * CFrameBufferPool::Get(
const PreparedFrameBuffer& buffer, size_t minSize) const PreparedFrameBuffer& buffer, size_t minSize)
{ {
if (buffer.frameIndex > ARRAYSIZE(m_buffers) - 1) if (buffer.resourceSlot > ARRAYSIZE(m_buffers) - 1)
return nullptr; return nullptr;
CFrameBufferResource * fbr = &m_buffers[buffer.frameIndex]; CFrameBufferResource * fbr = &m_buffers[buffer.resourceSlot];
if (!fbr->Init(m_dx12, buffer.frameIndex, buffer.mem, if (!fbr->Init(m_dx12, buffer.token, buffer.mem,
buffer.heapOffset, minSize, m_transport->GetMaxFrameSize())) buffer.heapOffset, minSize, m_transport->GetMaxFrameSize()))
return nullptr; return nullptr;

View File

@@ -25,11 +25,9 @@
#include <cstring> #include <cstring>
bool CFrameBufferResource::Init(CD3D12Device * dx12, bool CFrameBufferResource::Init(CD3D12Device * dx12,
unsigned frameIndex, uint8_t * base, uint64_t heapOffset, size_t size, const FrameToken& token, uint8_t * base, uint64_t heapOffset, size_t size,
size_t maxFrameSize) size_t maxFrameSize)
{ {
m_frameIndex = frameIndex;
if (size > maxFrameSize) if (size > maxFrameSize)
{ {
DEBUG_ERROR("Frame size of %llu is too large for transport memory", DEBUG_ERROR("Frame size of %llu is too large for transport memory",
@@ -59,6 +57,7 @@ bool CFrameBufferResource::Init(CD3D12Device * dx12,
// Nothing to do if the resource already represents this allocation. // Nothing to do if the resource already represents this allocation.
if (m_base == base && m_size >= size) if (m_base == base && m_size >= size)
{ {
m_token = token;
m_frameSize = size; m_frameSize = size;
return true; return true;
} }
@@ -137,6 +136,7 @@ bool CFrameBufferResource::Init(CD3D12Device * dx12,
m_res->SetName(resName); m_res->SetName(resName);
m_token = token;
m_base = base; m_base = base;
m_size = size; m_size = size;
m_frameSize = size; m_frameSize = size;
@@ -151,6 +151,7 @@ void CFrameBufferResource::Reset()
m_map = NULL; m_map = NULL;
} }
m_token = {};
m_base = nullptr; m_base = nullptr;
m_size = 0; m_size = 0;
m_frameSize = 0; m_frameSize = 0;

View File

@@ -29,6 +29,7 @@
#include "capture/CFrameScheduler.h" #include "capture/CFrameScheduler.h"
#include "d3d/CInteropResource.h" #include "d3d/CInteropResource.h"
#include "transport/PreparedFrameBuffer.h"
struct CD3D12Device; struct CD3D12Device;
@@ -37,7 +38,7 @@ using namespace Microsoft::WRL;
class CFrameBufferResource class CFrameBufferResource
{ {
private: private:
unsigned m_frameIndex = 0; FrameToken m_token = {};
uint8_t * m_base = nullptr; uint8_t * m_base = nullptr;
size_t m_size = 0; size_t m_size = 0;
size_t m_frameSize = 0; size_t m_frameSize = 0;
@@ -60,13 +61,13 @@ class CFrameBufferResource
void * m_map = nullptr; void * m_map = nullptr;
public: public:
bool Init(CD3D12Device * dx12, unsigned frameIndex, uint8_t * base, bool Init(CD3D12Device * dx12, const FrameToken& token, uint8_t * base,
uint64_t heapOffset, size_t size, size_t maxFrameSize); uint64_t heapOffset, size_t size, size_t maxFrameSize);
void Reset(); void Reset();
unsigned GetFrameIndex() { return m_frameIndex; } const FrameToken& GetToken() const { return m_token; }
size_t GetFrameSize() { return m_frameSize; } size_t GetFrameSize() { return m_frameSize; }
void * GetMap() { return m_map; } void * GetMap() { return m_map; }
void SetTiming(uint64_t captureTime, uint64_t postProcessStart, void SetTiming(uint64_t captureTime, uint64_t postProcessStart,
uint64_t copyStart) uint64_t copyStart)

View File

@@ -346,7 +346,7 @@ void CHardwareFrameProcessor::CompletionFunction(
if (!result) if (!result)
{ {
processor->m_transport->FailFrameBuffer(fbRes->GetFrameIndex()); processor->m_transport->FailFrameBuffer(fbRes->GetToken());
processor->SetFullDamage(); processor->SetFullDamage();
processor->m_transport->ForceFrame(); processor->m_transport->ForceFrame();
processor->ReleaseCandidate(candidateIndex); processor->ReleaseCandidate(candidateIndex);
@@ -379,7 +379,7 @@ void CHardwareFrameProcessor::CompletionFunction(
{ {
const uint64_t indirectCopyStart = CFrameScheduler::Nanotime(); const uint64_t indirectCopyStart = CFrameScheduler::Nanotime();
processor->m_transport->WriteFrameBuffer( processor->m_transport->WriteFrameBuffer(
fbRes->GetFrameIndex(), fbRes->GetMap(), 0, fbRes->GetToken(), fbRes->GetMap(), 0,
fbRes->GetFrameSize(), false); fbRes->GetFrameSize(), false);
indirectCopyTime = CFrameScheduler::Nanotime() - indirectCopyStart; indirectCopyTime = CFrameScheduler::Nanotime() - indirectCopyStart;
} }
@@ -405,7 +405,7 @@ void CHardwareFrameProcessor::CompletionFunction(
const uint64_t copyTime = prepareCopyTime + publishCopyTime; const uint64_t copyTime = prepareCopyTime + publishCopyTime;
processor->m_transport->FinalizeFrameBuffer(fbRes->GetFrameIndex()); processor->m_transport->FinalizeFrameBuffer(fbRes->GetToken());
const uint64_t publishedAt = CFrameScheduler::Nanotime(); const uint64_t publishedAt = CFrameScheduler::Nanotime();
const uint64_t prepareElapsed = prepareReady >= postProcessStart ? const uint64_t prepareElapsed = prepareReady >= postProcessStart ?
prepareReady - postProcessStart : 0; prepareReady - postProcessStart : 0;
@@ -420,10 +420,11 @@ void CHardwareFrameProcessor::CompletionFunction(
const uint64_t holdTime = publishStart >= prepareReady ? const uint64_t holdTime = publishStart >= prepareReady ?
publishStart - prepareReady : 0; publishStart - prepareReady : 0;
processor->m_transport->SetFrameTiming(fbRes->GetFrameIndex(), processor->m_transport->SetFrameTiming(fbRes->GetToken(),
fbRes->GetCaptureTime(), postProcessTime, copyTime, readyTime, holdTime, fbRes->GetCaptureTime(), postProcessTime, copyTime, readyTime, holdTime,
fbRes->GetSchedule(), publishedAt); fbRes->GetSchedule(), publishedAt);
processor->m_transport->TryRecordFrameTiming(publishedAt - publishStart); processor->m_transport->TryRecordFrameTiming(
fbRes->GetToken(), publishedAt - publishStart);
const uint64_t timingToken = fbRes->GetTimingToken(); const uint64_t timingToken = fbRes->GetTimingToken();
if (timingToken && timingStart && prepareReady >= timingStart && if (timingToken && timingStart && prepareReady >= timingStart &&
@@ -436,7 +437,7 @@ void CHardwareFrameProcessor::CompletionFunction(
fbRes->IsFullCopy(), totalTime); fbRes->IsFullCopy(), totalTime);
} }
processor->m_transport->CompleteFrameBuffer(fbRes->GetFrameIndex(), true); processor->m_transport->CompleteFrameBuffer(fbRes->GetToken(), true);
processor->ReleaseCandidate(candidateIndex); processor->ReleaseCandidate(candidateIndex);
} }
@@ -512,7 +513,7 @@ bool CHardwareFrameProcessor::Publish(
m_frameBuffers.Get(buffer, candidate.frameSize); m_frameBuffers.Get(buffer, candidate.frameSize);
if (!fbRes) if (!fbRes)
{ {
m_transport->AbortFrameBuffer(buffer.frameIndex); m_transport->AbortFrameBuffer(buffer.token);
restoreCandidate(); restoreCandidate();
DEBUG_ERROR("Failed to get a CFrameBufferResource from the pool"); DEBUG_ERROR("Failed to get a CFrameBufferResource from the pool");
SetFullDamage(); SetFullDamage();
@@ -522,7 +523,7 @@ bool CHardwareFrameProcessor::Publish(
CD3D12CommandSlot * copySlot = m_dx12->GetCopySlot(candidateIndex); CD3D12CommandSlot * copySlot = m_dx12->GetCopySlot(candidateIndex);
if (!copySlot) if (!copySlot)
{ {
m_transport->AbortFrameBuffer(buffer.frameIndex); m_transport->AbortFrameBuffer(buffer.token);
restoreCandidate(); restoreCandidate();
DEBUG_ERROR("Failed to get a copy CommandSlot for publication"); DEBUG_ERROR("Failed to get a copy CommandSlot for publication");
SetFullDamage(); SetFullDamage();
@@ -557,16 +558,16 @@ bool CHardwareFrameProcessor::Publish(
bool deliveredToOwner; bool deliveredToOwner;
if (!m_transport->PublishFrameBuffer( if (!m_transport->PublishFrameBuffer(
buffer.frameIndex, schedule, deliveredToOwner)) buffer.token, schedule, deliveredToOwner))
{ {
copySlot->Cancel(); copySlot->Cancel();
m_transport->AbortFrameBuffer(buffer.frameIndex); m_transport->AbortFrameBuffer(buffer.token);
restoreCandidate(); restoreCandidate();
return false; return false;
} }
CFrameScheduler::Schedule frameSchedule = schedule; CFrameScheduler::Schedule frameSchedule = schedule;
if (!deliveredToOwner || if (!deliveredToOwner ||
!m_transport->TryFrameSubmitted(buffer.frameIndex, schedule)) !m_transport->TryFrameSubmitted(buffer.token, schedule))
frameSchedule.phaseEligible = false; frameSchedule.phaseEligible = false;
fbRes->SetSchedule(frameSchedule); fbRes->SetSchedule(frameSchedule);
@@ -601,7 +602,7 @@ bool CHardwareFrameProcessor::Publish(
} }
if (callbackPending && !copySlot->HasSubmittedWork()) if (callbackPending && !copySlot->HasSubmittedWork())
{ {
m_transport->FailFrameBuffer(buffer.frameIndex); m_transport->FailFrameBuffer(buffer.token);
ReleaseCandidate(candidateIndex); ReleaseCandidate(candidateIndex);
} }
m_transport->ForceFrame(); m_transport->ForceFrame();
@@ -610,7 +611,7 @@ bool CHardwareFrameProcessor::Publish(
} }
m_transport->CommitFrameBuffer( m_transport->CommitFrameBuffer(
buffer.frameIndex, schedule, periodic, deliveredToOwner); buffer.token, schedule, periodic, deliveredToOwner);
unsigned superseded = 0; unsigned superseded = 0;
{ {

View File

@@ -45,7 +45,7 @@ void CSoftwareFrameProcessor::CompletionFunction(
if (!result) if (!result)
{ {
processor->m_transport->FailFrameBuffer(fbRes->GetFrameIndex()); processor->m_transport->FailFrameBuffer(fbRes->GetToken());
processor->SetFullDamage(); processor->SetFullDamage();
processor->m_transport->ForceFrame(); processor->m_transport->ForceFrame();
return; return;
@@ -56,7 +56,7 @@ void CSoftwareFrameProcessor::CompletionFunction(
{ {
const uint64_t indirectCopyStart = CFrameScheduler::Nanotime(); const uint64_t indirectCopyStart = CFrameScheduler::Nanotime();
if (fbRes->IsFullCopy()) if (fbRes->IsFullCopy())
processor->m_transport->WriteFrameBuffer(fbRes->GetFrameIndex(), processor->m_transport->WriteFrameBuffer(fbRes->GetToken(),
fbRes->GetMap(), 0, fbRes->GetFrameSize(), false); fbRes->GetMap(), 0, fbRes->GetFrameSize(), false);
else else
{ {
@@ -71,7 +71,7 @@ void CSoftwareFrameProcessor::CompletionFunction(
(size_t)rect->left * bytesPerPixel; (size_t)rect->left * bytesPerPixel;
const size_t rowBytes = const size_t rowBytes =
(size_t)(rect->right - rect->left) * bytesPerPixel; (size_t)(rect->right - rect->left) * bytesPerPixel;
processor->m_transport->WriteFrameBufferRows(fbRes->GetFrameIndex(), processor->m_transport->WriteFrameBufferRows(fbRes->GetToken(),
fbRes->GetMap(), rowOffset, rowBytes, pitch, fbRes->GetMap(), rowOffset, rowBytes, pitch,
(unsigned)(rect->bottom - rect->top)); (unsigned)(rect->bottom - rect->top));
} }
@@ -84,7 +84,7 @@ void CSoftwareFrameProcessor::CompletionFunction(
const uint64_t copyReady = CFrameScheduler::Nanotime(); const uint64_t copyReady = CFrameScheduler::Nanotime();
const bool gpuTimingValid = slot->GetGPUTimes(gpuStart, gpuEnd); const bool gpuTimingValid = slot->GetGPUTimes(gpuStart, gpuEnd);
processor->m_transport->FinalizeFrameBuffer(fbRes->GetFrameIndex()); processor->m_transport->FinalizeFrameBuffer(fbRes->GetToken());
const uint64_t publishedAt = CFrameScheduler::Nanotime(); const uint64_t publishedAt = CFrameScheduler::Nanotime();
const uint64_t postProcessStart = fbRes->GetPostProcessStart(); const uint64_t postProcessStart = fbRes->GetPostProcessStart();
const uint64_t copyStart = fbRes->GetCopyStart(); const uint64_t copyStart = fbRes->GetCopyStart();
@@ -104,10 +104,10 @@ void CSoftwareFrameProcessor::CompletionFunction(
const uint64_t measured = postProcessTime + copyTime; const uint64_t measured = postProcessTime + copyTime;
const uint64_t readyTime = elapsed > measured ? elapsed - measured : 0; const uint64_t readyTime = elapsed > measured ? elapsed - measured : 0;
processor->m_transport->SetFrameTiming(fbRes->GetFrameIndex(), processor->m_transport->SetFrameTiming(fbRes->GetToken(),
fbRes->GetCaptureTime(), postProcessTime, copyTime, readyTime, 0, fbRes->GetCaptureTime(), postProcessTime, copyTime, readyTime, 0,
fbRes->GetSchedule(), publishedAt); fbRes->GetSchedule(), publishedAt);
processor->m_transport->CompleteFrameBuffer(fbRes->GetFrameIndex(), true); processor->m_transport->CompleteFrameBuffer(fbRes->GetToken(), true);
} }
bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission) bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
@@ -209,7 +209,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
if (!fbRes) if (!fbRes)
{ {
copySlot->Cancel(); copySlot->Cancel();
m_transport->AbortFrameBuffer(buffer.frameIndex); m_transport->AbortFrameBuffer(buffer.token);
RestorePendingDamage( RestorePendingDamage(
currentDirtyRects, nbDirtyRects, hasDamage); currentDirtyRects, nbDirtyRects, hasDamage);
DEBUG_ERROR("Failed to get a framebuffer for software capture"); DEBUG_ERROR("Failed to get a framebuffer for software capture");
@@ -221,7 +221,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
!submission.source->Sync(*copySlot)) !submission.source->Sync(*copySlot))
{ {
copySlot->Cancel(); copySlot->Cancel();
m_transport->AbortFrameBuffer(buffer.frameIndex); m_transport->AbortFrameBuffer(buffer.token);
RestorePendingDamage( RestorePendingDamage(
currentDirtyRects, nbDirtyRects, hasDamage); currentDirtyRects, nbDirtyRects, hasDamage);
SetFullDamage(); SetFullDamage();
@@ -260,10 +260,10 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
bool deliveredToOwner; bool deliveredToOwner;
if (!m_transport->PublishFrameBuffer( if (!m_transport->PublishFrameBuffer(
buffer.frameIndex, deliverySchedule, deliveredToOwner)) buffer.token, deliverySchedule, deliveredToOwner))
{ {
copySlot->Cancel(); copySlot->Cancel();
m_transport->AbortFrameBuffer(buffer.frameIndex); m_transport->AbortFrameBuffer(buffer.token);
RestorePendingDamage( RestorePendingDamage(
currentDirtyRects, nbDirtyRects, hasDamage); currentDirtyRects, nbDirtyRects, hasDamage);
if (!submission.noImageUpdate) if (!submission.noImageUpdate)
@@ -283,7 +283,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
const bool submittedWork = copySlot->HasSubmittedWork(); const bool submittedWork = copySlot->HasSubmittedWork();
const bool completionHandled = fbRes->CompletionHandled(); const bool completionHandled = fbRes->CompletionHandled();
if (!submittedWork && !completionHandled) if (!submittedWork && !completionHandled)
m_transport->FailFrameBuffer(buffer.frameIndex); m_transport->FailFrameBuffer(buffer.token);
RestorePendingDamage( RestorePendingDamage(
currentDirtyRects, nbDirtyRects, hasDamage); currentDirtyRects, nbDirtyRects, hasDamage);
if (!submittedWork && !completionHandled) if (!submittedWork && !completionHandled)
@@ -295,7 +295,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
} }
m_transport->CommitFrameBuffer( m_transport->CommitFrameBuffer(
buffer.frameIndex, commitSchedule, false, deliveredToOwner); buffer.token, commitSchedule, false, deliveredToOwner);
return true; return true;
} }
} }

View File

@@ -31,7 +31,7 @@
#include "display/CDisplayConfiguration.h" #include "display/CDisplayConfiguration.h"
#include "display/CMonitorManager.h" #include "display/CMonitorManager.h"
#include "transport/ITransport.h" #include "transport/CTransportManager.h"
class CDeviceContext : private ITransportEvents class CDeviceContext : private ITransportEvents
{ {
@@ -47,7 +47,7 @@ private:
bool m_transportOpened = false; bool m_transportOpened = false;
std::atomic<LONG> m_initInProgress = 0; std::atomic<LONG> m_initInProgress = 0;
std::unique_ptr<ITransport> m_transport; std::unique_ptr<CTransportManager> m_transport;
CDisplayConfiguration m_displayConfiguration; CDisplayConfiguration m_displayConfiguration;
CMonitorManager m_monitorManager; CMonitorManager m_monitorManager;
@@ -98,7 +98,7 @@ public:
bool CanProcessFP16 () const { return m_canProcessFP16; } bool CanProcessFP16 () const { return m_canProcessFP16; }
bool IsSoftwareMode () const { return m_softwareMode; } bool IsSoftwareMode () const { return m_softwareMode; }
ITransport& GetTransport() CTransportManager& GetTransport()
{ {
return *m_transport; return *m_transport;
} }

View File

@@ -0,0 +1,307 @@
/**
* Looking Glass
* Copyright © 2017-2026 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "transport/CFrameHub.h"
bool CFrameHub::Bind(
BackendId backend, uint32_t epoch, IFrameSink& sink)
{
if (!backend || !epoch)
return false;
CSRWExclusiveLock lock(m_lock);
if (m_sink)
return false;
m_sink = &sink;
m_backend = backend;
m_epoch = epoch;
m_slots.clear();
return true;
}
void CFrameHub::Unbind(BackendId backend, uint32_t epoch)
{
CSRWExclusiveLock lock(m_lock);
if (m_backend != backend || m_epoch != epoch)
return;
m_sink = nullptr;
m_backend = 0;
m_epoch = 0;
m_slots.clear();
}
bool CFrameHub::Valid(const FrameToken& token) const
{
return m_sink && token.sink == m_backend && token.epoch == m_epoch &&
token.slot < m_slots.size() && token.serial &&
m_slots[token.slot].serial == token.serial;
}
void CFrameHub::Invalidate(const FrameToken& token)
{
if (Valid(token))
m_slots[token.slot] = {};
}
size_t CFrameHub::GetMaxFrameSize() const
{
CSRWSharedLock lock(m_lock);
return m_sink ? m_sink->GetMaxFrameSize() : 0;
}
bool CFrameHub::FrameBufferAvailable(
const CFrameScheduler::Schedule& schedule, bool allowReadyReplacement)
{
CSRWSharedLock lock(m_lock);
return m_sink &&
m_sink->FrameBufferAvailable(schedule, allowReadyReplacement);
}
bool CFrameHub::HasPublishedFrame() const
{
CSRWSharedLock lock(m_lock);
return m_sink && m_sink->HasPublishedFrame();
}
void CFrameHub::ProcessDeliveries()
{
CSRWSharedLock lock(m_lock);
if (m_sink)
m_sink->ProcessDeliveries();
}
bool CFrameHub::GetPendingDeliveryTarget(uint64_t now, uint64_t& target)
{
CSRWSharedLock lock(m_lock);
return m_sink && m_sink->GetPendingDeliveryTarget(now, target);
}
bool CFrameHub::RetryPendingDelivery(uint64_t now, bool& retry)
{
CSRWSharedLock lock(m_lock);
return m_sink && m_sink->RetryPendingDelivery(now, retry);
}
PreparedFrameBuffer CFrameHub::PrepareFrameBuffer(unsigned pitch,
const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
const RECT * dirtyRects, unsigned nbDirtyRects,
const CFrameScheduler::Schedule& schedule, bool allowReadyReplacement)
{
PreparedFrameBuffer result = {};
CSRWExclusiveLock lock(m_lock);
if (!m_sink)
return result;
const SinkTarget target = m_sink->PrepareFrameBuffer(
pitch, srcFormat, dstFormat, dirtyRects, nbDirtyRects, schedule,
allowReadyReplacement);
if (!target.mem || target.slot >= MAX_SLOTS)
{
if (target.mem)
m_sink->AbortFrameBuffer(target.slot);
return result;
}
if (target.slot >= m_slots.size())
m_slots.resize(target.slot + 1);
if (++m_nextSerial == 0)
++m_nextSerial;
m_slots[target.slot].serial = m_nextSerial;
result.token.sink = m_backend;
result.token.epoch = m_epoch;
result.token.slot = target.slot;
result.token.serial = m_nextSerial;
result.resourceSlot = target.slot;
result.mem = target.mem;
result.heapOffset = target.heapOffset;
result.fullCopy = target.fullCopy;
return result;
}
bool CFrameHub::PublishFrameBuffer(const FrameToken& token,
const CFrameScheduler::Schedule& schedule, bool& deliveredToOwner)
{
CSRWSharedLock lock(m_lock);
return Valid(token) &&
m_sink->PublishFrameBuffer(token.slot, schedule, deliveredToOwner);
}
bool CFrameHub::RepublishFrameBuffer(
const CFrameScheduler::Schedule& schedule)
{
CSRWSharedLock lock(m_lock);
return m_sink && m_sink->RepublishFrameBuffer(schedule);
}
bool CFrameHub::TryFrameSubmitted(const FrameToken& token,
const CFrameScheduler::Schedule& schedule)
{
CSRWSharedLock lock(m_lock);
return Valid(token) &&
m_sink->TryFrameSubmitted(token.slot, schedule);
}
void CFrameHub::CommitFrameBuffer(const FrameToken& token,
const CFrameScheduler::Schedule& schedule, bool periodic,
bool deliveredToOwner)
{
CSRWExclusiveLock lock(m_lock);
if (Valid(token))
{
m_sink->CommitFrameBuffer(
token.slot, schedule, periodic, deliveredToOwner);
Slot& slot = m_slots[token.slot];
slot.committed = true;
if (slot.completionPending)
{
m_sink->CompleteFrameBuffer(
token.slot, slot.completionSucceeded);
Invalidate(token);
}
}
}
void CFrameHub::AbortFrameBuffer(const FrameToken& token)
{
CSRWExclusiveLock lock(m_lock);
if (Valid(token))
{
m_sink->AbortFrameBuffer(token.slot);
Invalidate(token);
}
}
void CFrameHub::FailFrameBuffer(const FrameToken& token)
{
CSRWExclusiveLock lock(m_lock);
if (Valid(token))
{
m_sink->FailFrameBuffer(token.slot);
Invalidate(token);
}
}
void CFrameHub::CompleteFrameBuffer(
const FrameToken& token, bool succeeded)
{
CSRWExclusiveLock lock(m_lock);
if (Valid(token))
{
Slot& slot = m_slots[token.slot];
if (slot.committed)
{
m_sink->CompleteFrameBuffer(token.slot, succeeded);
Invalidate(token);
}
else
{
slot.completionPending = true;
slot.completionSucceeded = succeeded;
}
}
}
void CFrameHub::SetFrameTiming(const FrameToken& token,
uint64_t captureTime, uint64_t postProcessTime, uint64_t copyTime,
uint64_t readyTime, uint64_t holdTime,
const CFrameScheduler::Schedule& schedule, uint64_t completedAt)
{
CSRWSharedLock lock(m_lock);
if (Valid(token))
m_sink->SetFrameTiming(token.slot, captureTime, postProcessTime,
copyTime, readyTime, holdTime, schedule, completedAt);
}
void CFrameHub::WriteFrameBuffer(const FrameToken& token, void * src,
size_t offset, size_t len, bool setWritePos) const
{
CSRWSharedLock lock(m_lock);
if (Valid(token))
m_sink->WriteFrameBuffer(
token.slot, src, offset, len, setWritePos);
}
void CFrameHub::WriteFrameBufferRows(const FrameToken& token, void * src,
size_t offset, size_t rowBytes, size_t pitch, unsigned rows) const
{
CSRWSharedLock lock(m_lock);
if (Valid(token))
m_sink->WriteFrameBufferRows(
token.slot, src, offset, rowBytes, pitch, rows);
}
void CFrameHub::FinalizeFrameBuffer(const FrameToken& token) const
{
CSRWSharedLock lock(m_lock);
if (Valid(token))
m_sink->FinalizeFrameBuffer(token.slot);
}
void CFrameHub::ObserveFrame(uint64_t now)
{
CSRWSharedLock lock(m_lock);
if (m_sink)
m_sink->ObserveFrame(now);
}
void CFrameHub::ForceFrame()
{
CSRWSharedLock lock(m_lock);
if (m_sink)
m_sink->ForceFrame();
}
bool CFrameHub::GetPublishTarget(uint64_t now, uint64_t& target,
CFrameScheduler::Schedule& schedule, bool& periodic, bool& republish)
{
CSRWSharedLock lock(m_lock);
return m_sink && m_sink->GetPublishTarget(
now, target, schedule, periodic, republish);
}
void CFrameHub::FrameMissed(const CFrameScheduler::Schedule& schedule,
uint64_t now, bool periodic)
{
CSRWSharedLock lock(m_lock);
if (m_sink)
m_sink->FrameMissed(schedule, now, periodic);
}
void CFrameHub::FrameSuperseded()
{
CSRWSharedLock lock(m_lock);
if (m_sink)
m_sink->FrameSuperseded();
}
HANDLE CFrameHub::GetFrameScheduleEvent() const
{
CSRWSharedLock lock(m_lock);
return m_sink ? m_sink->GetFrameScheduleEvent() : nullptr;
}
void CFrameHub::TryRecordFrameTiming(
const FrameToken& token, uint64_t duration)
{
CSRWSharedLock lock(m_lock);
if (Valid(token))
m_sink->TryRecordFrameTiming(duration);
}

View File

@@ -0,0 +1,105 @@
/**
* Looking Glass
* Copyright © 2017-2026 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
#include "CSRWLock.h"
#include "transport/IFrameSink.h"
#include "transport/IFrameTransport.h"
#include "transport/ITransport.h"
#include <vector>
class CFrameHub final : public IFrameTransport
{
private:
static const unsigned MAX_SLOTS = 1024;
struct Slot
{
uint64_t serial = 0;
bool committed = false;
bool completionPending = false;
bool completionSucceeded = false;
};
mutable CSRWLock m_lock;
IFrameSink * m_sink = nullptr;
BackendId m_backend = 0;
uint32_t m_epoch = 0;
uint64_t m_nextSerial = 0;
std::vector<Slot> m_slots;
bool Valid(const FrameToken& token) const;
void Invalidate(const FrameToken& token);
public:
bool Bind(BackendId backend, uint32_t epoch, IFrameSink& sink);
void Unbind(BackendId backend, uint32_t epoch);
size_t GetMaxFrameSize() const override;
bool FrameBufferAvailable(const CFrameScheduler::Schedule& schedule,
bool allowReadyReplacement = true) override;
bool HasPublishedFrame() const override;
void ProcessDeliveries() override;
bool GetPendingDeliveryTarget(uint64_t now, uint64_t& target) override;
bool RetryPendingDelivery(uint64_t now, bool& retry) override;
PreparedFrameBuffer PrepareFrameBuffer(unsigned pitch,
const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
const RECT * dirtyRects, unsigned nbDirtyRects,
const CFrameScheduler::Schedule& schedule,
bool allowReadyReplacement = true) override;
bool PublishFrameBuffer(const FrameToken& token,
const CFrameScheduler::Schedule& schedule,
bool& deliveredToOwner) override;
bool RepublishFrameBuffer(
const CFrameScheduler::Schedule& schedule) override;
bool TryFrameSubmitted(const FrameToken& token,
const CFrameScheduler::Schedule& schedule) override;
void CommitFrameBuffer(const FrameToken& token,
const CFrameScheduler::Schedule& schedule, bool periodic,
bool deliveredToOwner) override;
void AbortFrameBuffer(const FrameToken& token) override;
void FailFrameBuffer(const FrameToken& token) override;
void CompleteFrameBuffer(
const FrameToken& token, bool succeeded) override;
void SetFrameTiming(const FrameToken& token, uint64_t captureTime,
uint64_t postProcessTime, uint64_t copyTime, uint64_t readyTime,
uint64_t holdTime, const CFrameScheduler::Schedule& schedule,
uint64_t completedAt) override;
void WriteFrameBuffer(const FrameToken& token, void * src,
size_t offset, size_t len, bool setWritePos) const override;
void WriteFrameBufferRows(const FrameToken& token, void * src,
size_t offset, size_t rowBytes, size_t pitch,
unsigned rows) const override;
void FinalizeFrameBuffer(const FrameToken& token) const override;
void ObserveFrame(uint64_t now) override;
void ForceFrame() override;
bool GetPublishTarget(uint64_t now, uint64_t& target,
CFrameScheduler::Schedule& schedule, bool& periodic,
bool& republish) override;
void FrameMissed(const CFrameScheduler::Schedule& schedule,
uint64_t now, bool periodic) override;
void FrameSuperseded() override;
HANDLE GetFrameScheduleEvent() const override;
void TryRecordFrameTiming(
const FrameToken& token, uint64_t duration) override;
};

View File

@@ -145,6 +145,16 @@ bool CTransportManager::InitializeEntry(Entry& entry)
} }
entry.controlAdded = true; entry.controlAdded = true;
if (entry.primary &&
!m_frames.Bind(entry.id, entry.epoch, entry.transport->FrameSink()))
{
m_control.Remove(entry.id, entry.epoch);
entry.controlAdded = false;
entry.state = State::FAILED;
return false;
}
entry.frameAdded = entry.primary;
entry.state = State::INITIALIZED; entry.state = State::INITIALIZED;
return true; return true;
} }
@@ -311,6 +321,12 @@ void CTransportManager::Stop()
void CTransportManager::RemoveServices(Entry& entry) void CTransportManager::RemoveServices(Entry& entry)
{ {
if (entry.frameAdded)
{
m_frames.Unbind(entry.id, entry.epoch);
entry.frameAdded = false;
}
if (entry.controlAdded) if (entry.controlAdded)
{ {
m_control.Remove(entry.id, entry.epoch); m_control.Remove(entry.id, entry.epoch);
@@ -356,7 +372,8 @@ DirectFrameBufferMemory CTransportManager::GetDirectMemory() const
IFrameTransport& CTransportManager::Frames() IFrameTransport& CTransportManager::Frames()
{ {
return Primary().Frames(); m_exposed = true;
return m_frames;
} }
IControlTransport& CTransportManager::Control() IControlTransport& CTransportManager::Control()

View File

@@ -21,15 +21,19 @@
#pragma once #pragma once
#include "transport/CControlHub.h" #include "transport/CControlHub.h"
#include "transport/CFrameHub.h"
#include "transport/ITransport.h" #include "transport/ITransport.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
class CTransportManager final : public ITransport class CTransportManager final
{ {
public: public:
using CreateFn = std::unique_ptr<ITransport> (*)(); using CreateFn = std::unique_ptr<ITransport> (*)();
using OpenResult = ITransport::OpenResult;
using ProcessResult = ITransport::ProcessResult;
using Recovery = ITransport::Recovery;
private: private:
enum class State enum class State
@@ -55,10 +59,12 @@ private:
uint32_t epoch = 1; uint32_t epoch = 1;
uint64_t retryAt = 0; uint64_t retryAt = 0;
bool controlAdded = false; bool controlAdded = false;
bool frameAdded = false;
}; };
std::vector<std::unique_ptr<Entry>> m_entries; std::vector<std::unique_ptr<Entry>> m_entries;
CControlHub m_control; CControlHub m_control;
CFrameHub m_frames;
Entry * m_primary = nullptr; Entry * m_primary = nullptr;
bool m_initialized = false; bool m_initialized = false;
bool m_setup = false; bool m_setup = false;
@@ -76,7 +82,7 @@ private:
public: public:
CTransportManager() = default; CTransportManager() = default;
~CTransportManager() override; ~CTransportManager();
CTransportManager(const CTransportManager&) = delete; CTransportManager(const CTransportManager&) = delete;
CTransportManager& operator=(const CTransportManager&) = delete; CTransportManager& operator=(const CTransportManager&) = delete;
@@ -84,19 +90,19 @@ public:
bool Add(BackendId id, const char * name, bool required, bool primary, bool Add(BackendId id, const char * name, bool required, bool primary,
CreateFn create); CreateFn create);
OpenResult Open() override; OpenResult Open();
bool Initialize() override; bool Initialize();
bool Setup(size_t alignment) override; bool Setup(size_t alignment);
ProcessResult Process(ITransportEvents& events) override; ProcessResult Process(ITransportEvents& events);
void Stop() override; void Stop();
void SyncRecovery() override; void SyncRecovery();
void RecoveryStatus(uint64_t session, uint32_t serial, bool active, void RecoveryStatus(uint64_t session, uint32_t serial, bool active,
Recovery state, uint32_t error) override; Recovery state, uint32_t error);
FrameMemoryLimits GetMemoryLimits() const override; FrameMemoryLimits GetMemoryLimits() const;
DirectFrameBufferMemory GetDirectMemory() const override; DirectFrameBufferMemory GetDirectMemory() const;
IFrameTransport& Frames() override; IFrameTransport& Frames();
IControlTransport& Control() override; IControlTransport& Control();
IInputTransport * Input() override; IInputTransport * Input();
}; };

View File

@@ -0,0 +1,85 @@
/**
* Looking Glass
* Copyright © 2017-2026 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
#include "postprocess/D12FrameFormat.h"
#include "capture/CFrameScheduler.h"
#include "transport/PreparedFrameBuffer.h"
#include <Windows.h>
#include <stddef.h>
#include <stdint.h>
class IFrameSink
{
public:
virtual ~IFrameSink() = default;
virtual size_t GetMaxFrameSize() const = 0;
virtual bool FrameBufferAvailable(
const CFrameScheduler::Schedule& schedule,
bool allowReadyReplacement = true) = 0;
virtual bool HasPublishedFrame() const = 0;
virtual void ProcessDeliveries() = 0;
virtual bool GetPendingDeliveryTarget(
uint64_t now, uint64_t& target) = 0;
virtual bool RetryPendingDelivery(uint64_t now, bool& retry) = 0;
virtual SinkTarget PrepareFrameBuffer(unsigned pitch,
const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
const RECT * dirtyRects, unsigned nbDirtyRects,
const CFrameScheduler::Schedule& schedule,
bool allowReadyReplacement = true) = 0;
virtual bool PublishFrameBuffer(unsigned slot,
const CFrameScheduler::Schedule& schedule,
bool& deliveredToOwner) = 0;
virtual bool RepublishFrameBuffer(
const CFrameScheduler::Schedule& schedule) = 0;
virtual bool TryFrameSubmitted(unsigned slot,
const CFrameScheduler::Schedule& schedule) = 0;
virtual void CommitFrameBuffer(unsigned slot,
const CFrameScheduler::Schedule& schedule, bool periodic,
bool deliveredToOwner) = 0;
virtual void AbortFrameBuffer(unsigned slot) = 0;
virtual void FailFrameBuffer(unsigned slot) = 0;
virtual void CompleteFrameBuffer(unsigned slot, bool succeeded) = 0;
virtual void SetFrameTiming(unsigned slot, uint64_t captureTime,
uint64_t postProcessTime, uint64_t copyTime, uint64_t readyTime,
uint64_t holdTime, const CFrameScheduler::Schedule& schedule,
uint64_t completedAt) = 0;
virtual void WriteFrameBuffer(unsigned slot, void * src,
size_t offset, size_t len, bool setWritePos) const = 0;
virtual void WriteFrameBufferRows(unsigned slot, void * src,
size_t offset, size_t rowBytes, size_t pitch,
unsigned rows) const = 0;
virtual void FinalizeFrameBuffer(unsigned slot) const = 0;
virtual void ObserveFrame(uint64_t now) = 0;
virtual void ForceFrame() = 0;
virtual bool GetPublishTarget(uint64_t now, uint64_t& target,
CFrameScheduler::Schedule& schedule, bool& periodic,
bool& republish) = 0;
virtual void FrameMissed(const CFrameScheduler::Schedule& schedule,
uint64_t now, bool periodic) = 0;
virtual void FrameSuperseded() = 0;
virtual HANDLE GetFrameScheduleEvent() const = 0;
virtual void TryRecordFrameTiming(uint64_t duration) = 0;
};

View File

@@ -48,30 +48,30 @@ public:
const RECT * dirtyRects, unsigned nbDirtyRects, const RECT * dirtyRects, unsigned nbDirtyRects,
const CFrameScheduler::Schedule& schedule, const CFrameScheduler::Schedule& schedule,
bool allowReadyReplacement = true) = 0; bool allowReadyReplacement = true) = 0;
virtual bool PublishFrameBuffer(unsigned frameIndex, virtual bool PublishFrameBuffer(const FrameToken& token,
const CFrameScheduler::Schedule& schedule, const CFrameScheduler::Schedule& schedule,
bool& deliveredToOwner) = 0; bool& deliveredToOwner) = 0;
virtual bool RepublishFrameBuffer( virtual bool RepublishFrameBuffer(
const CFrameScheduler::Schedule& schedule) = 0; const CFrameScheduler::Schedule& schedule) = 0;
virtual bool TryFrameSubmitted(unsigned frameIndex, virtual bool TryFrameSubmitted(const FrameToken& token,
const CFrameScheduler::Schedule& schedule) = 0; const CFrameScheduler::Schedule& schedule) = 0;
virtual void CommitFrameBuffer(unsigned frameIndex, virtual void CommitFrameBuffer(const FrameToken& token,
const CFrameScheduler::Schedule& schedule, bool periodic, const CFrameScheduler::Schedule& schedule, bool periodic,
bool deliveredToOwner) = 0; bool deliveredToOwner) = 0;
virtual void AbortFrameBuffer(unsigned frameIndex) = 0; virtual void AbortFrameBuffer(const FrameToken& token) = 0;
virtual void FailFrameBuffer(unsigned frameIndex) = 0; virtual void FailFrameBuffer(const FrameToken& token) = 0;
virtual void CompleteFrameBuffer( virtual void CompleteFrameBuffer(
unsigned frameIndex, bool succeeded) = 0; const FrameToken& token, bool succeeded) = 0;
virtual void SetFrameTiming(unsigned frameIndex, uint64_t captureTime, virtual void SetFrameTiming(const FrameToken& token, uint64_t captureTime,
uint64_t postProcessTime, uint64_t copyTime, uint64_t readyTime, uint64_t postProcessTime, uint64_t copyTime, uint64_t readyTime,
uint64_t holdTime, const CFrameScheduler::Schedule& schedule, uint64_t holdTime, const CFrameScheduler::Schedule& schedule,
uint64_t completedAt) = 0; uint64_t completedAt) = 0;
virtual void WriteFrameBuffer(unsigned frameIndex, void * src, virtual void WriteFrameBuffer(const FrameToken& token, void * src,
size_t offset, size_t len, bool setWritePos) const = 0; size_t offset, size_t len, bool setWritePos) const = 0;
virtual void WriteFrameBufferRows(unsigned frameIndex, void * src, virtual void WriteFrameBufferRows(const FrameToken& token, void * src,
size_t offset, size_t rowBytes, size_t pitch, size_t offset, size_t rowBytes, size_t pitch,
unsigned rows) const = 0; unsigned rows) const = 0;
virtual void FinalizeFrameBuffer(unsigned frameIndex) const = 0; virtual void FinalizeFrameBuffer(const FrameToken& token) const = 0;
virtual void ObserveFrame(uint64_t now) = 0; virtual void ObserveFrame(uint64_t now) = 0;
virtual void ForceFrame() = 0; virtual void ForceFrame() = 0;
@@ -82,5 +82,6 @@ public:
uint64_t now, bool periodic) = 0; uint64_t now, bool periodic) = 0;
virtual void FrameSuperseded() = 0; virtual void FrameSuperseded() = 0;
virtual HANDLE GetFrameScheduleEvent() const = 0; virtual HANDLE GetFrameScheduleEvent() const = 0;
virtual void TryRecordFrameTiming(uint64_t duration) = 0; virtual void TryRecordFrameTiming(
const FrameToken& token, uint64_t duration) = 0;
}; };

View File

@@ -27,7 +27,7 @@
#include <stdint.h> #include <stdint.h>
class IControlTransport; class IControlTransport;
class IFrameTransport; class IFrameSink;
class IInputTransport; class IInputTransport;
using BackendId = uint32_t; using BackendId = uint32_t;
@@ -93,7 +93,7 @@ public:
virtual FrameMemoryLimits GetMemoryLimits() const = 0; virtual FrameMemoryLimits GetMemoryLimits() const = 0;
virtual DirectFrameBufferMemory GetDirectMemory() const = 0; virtual DirectFrameBufferMemory GetDirectMemory() const = 0;
virtual IFrameTransport& Frames() = 0; virtual IFrameSink& FrameSink() = 0;
virtual IControlTransport& Control() = 0; virtual IControlTransport& Control() = 0;
virtual IInputTransport * Input() { return nullptr; } virtual IInputTransport * Input() { return nullptr; }
}; };

View File

@@ -22,9 +22,26 @@
#include <stdint.h> #include <stdint.h>
struct FrameToken
{
uint32_t sink = 0;
uint32_t epoch = 0;
uint32_t slot = 0;
uint64_t serial = 0;
};
struct PreparedFrameBuffer struct PreparedFrameBuffer
{ {
unsigned frameIndex; FrameToken token;
unsigned resourceSlot;
uint8_t * mem;
uint64_t heapOffset;
bool fullCopy;
};
struct SinkTarget
{
unsigned slot;
uint8_t * mem; uint8_t * mem;
uint64_t heapOffset; uint64_t heapOffset;
bool fullCopy; bool fullCopy;

View File

@@ -30,11 +30,11 @@ static std::unique_ptr<ITransport> CreateLGMP()
return std::unique_ptr<ITransport>(new (std::nothrow) CLGMPTransport()); return std::unique_ptr<ITransport>(new (std::nothrow) CLGMPTransport());
} }
std::unique_ptr<ITransport> CreateTransport() std::unique_ptr<CTransportManager> CreateTransport()
{ {
std::unique_ptr<CTransportManager> manager( std::unique_ptr<CTransportManager> manager(
new (std::nothrow) CTransportManager()); new (std::nothrow) CTransportManager());
if (!manager || !manager->Add(1, "LGMP", true, true, CreateLGMP)) if (!manager || !manager->Add(1, "LGMP", true, true, CreateLGMP))
return std::unique_ptr<ITransport>(); return std::unique_ptr<CTransportManager>();
return std::unique_ptr<ITransport>(manager.release()); return manager;
} }

View File

@@ -20,8 +20,8 @@
#pragma once #pragma once
#include "transport/ITransport.h"
#include <memory> #include <memory>
std::unique_ptr<ITransport> CreateTransport(); class CTransportManager;
std::unique_ptr<CTransportManager> CreateTransport();

View File

@@ -717,13 +717,13 @@ bool CLGMPFrameTransport::RetryPendingDelivery(uint64_t now, bool& retry)
return result == SHARED_FRAME_POSTED; return result == SHARED_FRAME_POSTED;
} }
PreparedFrameBuffer CLGMPFrameTransport::PrepareFrameBuffer( SinkTarget CLGMPFrameTransport::PrepareFrameBuffer(
unsigned pitch, const D12FrameFormat& srcFormat, unsigned pitch, const D12FrameFormat& srcFormat,
const D12FrameFormat& dstFormat, const RECT * dirtyRects, const D12FrameFormat& dstFormat, const RECT * dirtyRects,
unsigned nbDirtyRects, const CFrameScheduler::Schedule& schedule, unsigned nbDirtyRects, const CFrameScheduler::Schedule& schedule,
bool allowReadyReplacement) bool allowReadyReplacement)
{ {
PreparedFrameBuffer result = {}; SinkTarget result = {};
const unsigned dataWidth = dstFormat.dataWidth ? const unsigned dataWidth = dstFormat.dataWidth ?
dstFormat.dataWidth : (unsigned)dstFormat.desc.Width; dstFormat.dataWidth : (unsigned)dstFormat.desc.Width;
@@ -913,7 +913,7 @@ PreparedFrameBuffer CLGMPFrameTransport::PrepareFrameBuffer(
LGMPBuffer * fb = m_frameBuffer[frameIndex]; LGMPBuffer * fb = m_frameBuffer[frameIndex];
fb->wp = 0; fb->wp = 0;
result.frameIndex = frameIndex; result.slot = frameIndex;
result.mem = fb->data; result.mem = fb->data;
result.heapOffset = reinterpret_cast<uintptr_t>(fb->data) - result.heapOffset = reinterpret_cast<uintptr_t>(fb->data) -
reinterpret_cast<uintptr_t>(m_ivshmem.GetMem()); reinterpret_cast<uintptr_t>(m_ivshmem.GetMem());

View File

@@ -34,14 +34,14 @@ extern "C" {
#include "capture/CFrameScheduler.h" #include "capture/CFrameScheduler.h"
#include "capture/FramePipeline.h" #include "capture/FramePipeline.h"
#include "transport/FrameMemoryLimits.h" #include "transport/FrameMemoryLimits.h"
#include "transport/IFrameTransport.h" #include "transport/IFrameSink.h"
class CIVSHMEM; class CIVSHMEM;
class CLGMPHost; class CLGMPHost;
class CLGMPTransport; class CLGMPTransport;
struct LGMPBuffer; struct LGMPBuffer;
class CLGMPFrameTransport final : public IFrameTransport class CLGMPFrameTransport final : public IFrameSink
{ {
private: private:
friend class CLGMPTransport; friend class CLGMPTransport;
@@ -172,7 +172,7 @@ public:
bool GetPendingDeliveryTarget( bool GetPendingDeliveryTarget(
uint64_t now, uint64_t& target) override; uint64_t now, uint64_t& target) override;
bool RetryPendingDelivery(uint64_t now, bool& retry) override; bool RetryPendingDelivery(uint64_t now, bool& retry) override;
PreparedFrameBuffer PrepareFrameBuffer(unsigned pitch, SinkTarget PrepareFrameBuffer(unsigned pitch,
const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat, const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
const RECT * dirtyRects, unsigned nbDirtyRects, const RECT * dirtyRects, unsigned nbDirtyRects,
const CFrameScheduler::Schedule& schedule, const CFrameScheduler::Schedule& schedule,

View File

@@ -63,7 +63,7 @@ public:
FrameMemoryLimits GetMemoryLimits() const override; FrameMemoryLimits GetMemoryLimits() const override;
DirectFrameBufferMemory GetDirectMemory() const override; DirectFrameBufferMemory GetDirectMemory() const override;
IFrameTransport& Frames() override { return m_frames; } IFrameSink& FrameSink() override { return m_frames; }
IControlTransport& Control() override { return m_control; } IControlTransport& Control() override { return m_control; }
IInputTransport * Input() override { return &m_input; } IInputTransport * Input() override { return &m_input; }
}; };