diff --git a/idd/LGIdd/LGIdd.vcxproj b/idd/LGIdd/LGIdd.vcxproj
index 7569d02e..b83e345b 100644
--- a/idd/LGIdd/LGIdd.vcxproj
+++ b/idd/LGIdd/LGIdd.vcxproj
@@ -61,6 +61,7 @@
+
@@ -109,10 +110,12 @@
+
+
diff --git a/idd/LGIdd/LGIdd.vcxproj.filters b/idd/LGIdd/LGIdd.vcxproj.filters
index ef899d4d..01466c65 100644
--- a/idd/LGIdd/LGIdd.vcxproj.filters
+++ b/idd/LGIdd/LGIdd.vcxproj.filters
@@ -157,6 +157,9 @@
Transport
+
+ Transport
+
Transport
@@ -169,6 +172,9 @@
Transport
+
+ Transport
+
Transport
@@ -300,6 +306,9 @@
Transport
+
+ Transport
+
Transport
diff --git a/idd/LGIdd/capture/CFrameBufferPool.cpp b/idd/LGIdd/capture/CFrameBufferPool.cpp
index 12d48570..d63d62f7 100644
--- a/idd/LGIdd/capture/CFrameBufferPool.cpp
+++ b/idd/LGIdd/capture/CFrameBufferPool.cpp
@@ -39,11 +39,11 @@ void CFrameBufferPool::Reset()
CFrameBufferResource * CFrameBufferPool::Get(
const PreparedFrameBuffer& buffer, size_t minSize)
{
- if (buffer.frameIndex > ARRAYSIZE(m_buffers) - 1)
+ if (buffer.resourceSlot > ARRAYSIZE(m_buffers) - 1)
return nullptr;
- CFrameBufferResource * fbr = &m_buffers[buffer.frameIndex];
- if (!fbr->Init(m_dx12, buffer.frameIndex, buffer.mem,
+ CFrameBufferResource * fbr = &m_buffers[buffer.resourceSlot];
+ if (!fbr->Init(m_dx12, buffer.token, buffer.mem,
buffer.heapOffset, minSize, m_transport->GetMaxFrameSize()))
return nullptr;
diff --git a/idd/LGIdd/capture/CFrameBufferResource.cpp b/idd/LGIdd/capture/CFrameBufferResource.cpp
index db6c6b79..912cd9fd 100644
--- a/idd/LGIdd/capture/CFrameBufferResource.cpp
+++ b/idd/LGIdd/capture/CFrameBufferResource.cpp
@@ -25,11 +25,9 @@
#include
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)
{
- m_frameIndex = frameIndex;
-
if (size > maxFrameSize)
{
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.
if (m_base == base && m_size >= size)
{
+ m_token = token;
m_frameSize = size;
return true;
}
@@ -137,6 +136,7 @@ bool CFrameBufferResource::Init(CD3D12Device * dx12,
m_res->SetName(resName);
+ m_token = token;
m_base = base;
m_size = size;
m_frameSize = size;
@@ -151,6 +151,7 @@ void CFrameBufferResource::Reset()
m_map = NULL;
}
+ m_token = {};
m_base = nullptr;
m_size = 0;
m_frameSize = 0;
diff --git a/idd/LGIdd/capture/CFrameBufferResource.h b/idd/LGIdd/capture/CFrameBufferResource.h
index 5bb2880b..4106e7af 100644
--- a/idd/LGIdd/capture/CFrameBufferResource.h
+++ b/idd/LGIdd/capture/CFrameBufferResource.h
@@ -29,6 +29,7 @@
#include "capture/CFrameScheduler.h"
#include "d3d/CInteropResource.h"
+#include "transport/PreparedFrameBuffer.h"
struct CD3D12Device;
@@ -37,7 +38,7 @@ using namespace Microsoft::WRL;
class CFrameBufferResource
{
private:
- unsigned m_frameIndex = 0;
+ FrameToken m_token = {};
uint8_t * m_base = nullptr;
size_t m_size = 0;
size_t m_frameSize = 0;
@@ -60,13 +61,13 @@ class CFrameBufferResource
void * m_map = nullptr;
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);
void Reset();
- unsigned GetFrameIndex() { return m_frameIndex; }
- size_t GetFrameSize() { return m_frameSize; }
- void * GetMap() { return m_map; }
+ const FrameToken& GetToken() const { return m_token; }
+ size_t GetFrameSize() { return m_frameSize; }
+ void * GetMap() { return m_map; }
void SetTiming(uint64_t captureTime, uint64_t postProcessStart,
uint64_t copyStart)
diff --git a/idd/LGIdd/capture/CHardwareFrameProcessor.cpp b/idd/LGIdd/capture/CHardwareFrameProcessor.cpp
index d05def87..766bb2e6 100644
--- a/idd/LGIdd/capture/CHardwareFrameProcessor.cpp
+++ b/idd/LGIdd/capture/CHardwareFrameProcessor.cpp
@@ -346,7 +346,7 @@ void CHardwareFrameProcessor::CompletionFunction(
if (!result)
{
- processor->m_transport->FailFrameBuffer(fbRes->GetFrameIndex());
+ processor->m_transport->FailFrameBuffer(fbRes->GetToken());
processor->SetFullDamage();
processor->m_transport->ForceFrame();
processor->ReleaseCandidate(candidateIndex);
@@ -379,7 +379,7 @@ void CHardwareFrameProcessor::CompletionFunction(
{
const uint64_t indirectCopyStart = CFrameScheduler::Nanotime();
processor->m_transport->WriteFrameBuffer(
- fbRes->GetFrameIndex(), fbRes->GetMap(), 0,
+ fbRes->GetToken(), fbRes->GetMap(), 0,
fbRes->GetFrameSize(), false);
indirectCopyTime = CFrameScheduler::Nanotime() - indirectCopyStart;
}
@@ -405,7 +405,7 @@ void CHardwareFrameProcessor::CompletionFunction(
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 prepareElapsed = prepareReady >= postProcessStart ?
prepareReady - postProcessStart : 0;
@@ -420,10 +420,11 @@ void CHardwareFrameProcessor::CompletionFunction(
const uint64_t holdTime = publishStart >= prepareReady ?
publishStart - prepareReady : 0;
- processor->m_transport->SetFrameTiming(fbRes->GetFrameIndex(),
+ processor->m_transport->SetFrameTiming(fbRes->GetToken(),
fbRes->GetCaptureTime(), postProcessTime, copyTime, readyTime, holdTime,
fbRes->GetSchedule(), publishedAt);
- processor->m_transport->TryRecordFrameTiming(publishedAt - publishStart);
+ processor->m_transport->TryRecordFrameTiming(
+ fbRes->GetToken(), publishedAt - publishStart);
const uint64_t timingToken = fbRes->GetTimingToken();
if (timingToken && timingStart && prepareReady >= timingStart &&
@@ -436,7 +437,7 @@ void CHardwareFrameProcessor::CompletionFunction(
fbRes->IsFullCopy(), totalTime);
}
- processor->m_transport->CompleteFrameBuffer(fbRes->GetFrameIndex(), true);
+ processor->m_transport->CompleteFrameBuffer(fbRes->GetToken(), true);
processor->ReleaseCandidate(candidateIndex);
}
@@ -512,7 +513,7 @@ bool CHardwareFrameProcessor::Publish(
m_frameBuffers.Get(buffer, candidate.frameSize);
if (!fbRes)
{
- m_transport->AbortFrameBuffer(buffer.frameIndex);
+ m_transport->AbortFrameBuffer(buffer.token);
restoreCandidate();
DEBUG_ERROR("Failed to get a CFrameBufferResource from the pool");
SetFullDamage();
@@ -522,7 +523,7 @@ bool CHardwareFrameProcessor::Publish(
CD3D12CommandSlot * copySlot = m_dx12->GetCopySlot(candidateIndex);
if (!copySlot)
{
- m_transport->AbortFrameBuffer(buffer.frameIndex);
+ m_transport->AbortFrameBuffer(buffer.token);
restoreCandidate();
DEBUG_ERROR("Failed to get a copy CommandSlot for publication");
SetFullDamage();
@@ -557,16 +558,16 @@ bool CHardwareFrameProcessor::Publish(
bool deliveredToOwner;
if (!m_transport->PublishFrameBuffer(
- buffer.frameIndex, schedule, deliveredToOwner))
+ buffer.token, schedule, deliveredToOwner))
{
copySlot->Cancel();
- m_transport->AbortFrameBuffer(buffer.frameIndex);
+ m_transport->AbortFrameBuffer(buffer.token);
restoreCandidate();
return false;
}
CFrameScheduler::Schedule frameSchedule = schedule;
if (!deliveredToOwner ||
- !m_transport->TryFrameSubmitted(buffer.frameIndex, schedule))
+ !m_transport->TryFrameSubmitted(buffer.token, schedule))
frameSchedule.phaseEligible = false;
fbRes->SetSchedule(frameSchedule);
@@ -601,7 +602,7 @@ bool CHardwareFrameProcessor::Publish(
}
if (callbackPending && !copySlot->HasSubmittedWork())
{
- m_transport->FailFrameBuffer(buffer.frameIndex);
+ m_transport->FailFrameBuffer(buffer.token);
ReleaseCandidate(candidateIndex);
}
m_transport->ForceFrame();
@@ -610,7 +611,7 @@ bool CHardwareFrameProcessor::Publish(
}
m_transport->CommitFrameBuffer(
- buffer.frameIndex, schedule, periodic, deliveredToOwner);
+ buffer.token, schedule, periodic, deliveredToOwner);
unsigned superseded = 0;
{
diff --git a/idd/LGIdd/capture/CSoftwareFrameProcessor.cpp b/idd/LGIdd/capture/CSoftwareFrameProcessor.cpp
index 3cbc3b1d..5bb683a4 100644
--- a/idd/LGIdd/capture/CSoftwareFrameProcessor.cpp
+++ b/idd/LGIdd/capture/CSoftwareFrameProcessor.cpp
@@ -45,7 +45,7 @@ void CSoftwareFrameProcessor::CompletionFunction(
if (!result)
{
- processor->m_transport->FailFrameBuffer(fbRes->GetFrameIndex());
+ processor->m_transport->FailFrameBuffer(fbRes->GetToken());
processor->SetFullDamage();
processor->m_transport->ForceFrame();
return;
@@ -56,7 +56,7 @@ void CSoftwareFrameProcessor::CompletionFunction(
{
const uint64_t indirectCopyStart = CFrameScheduler::Nanotime();
if (fbRes->IsFullCopy())
- processor->m_transport->WriteFrameBuffer(fbRes->GetFrameIndex(),
+ processor->m_transport->WriteFrameBuffer(fbRes->GetToken(),
fbRes->GetMap(), 0, fbRes->GetFrameSize(), false);
else
{
@@ -71,7 +71,7 @@ void CSoftwareFrameProcessor::CompletionFunction(
(size_t)rect->left * bytesPerPixel;
const size_t rowBytes =
(size_t)(rect->right - rect->left) * bytesPerPixel;
- processor->m_transport->WriteFrameBufferRows(fbRes->GetFrameIndex(),
+ processor->m_transport->WriteFrameBufferRows(fbRes->GetToken(),
fbRes->GetMap(), rowOffset, rowBytes, pitch,
(unsigned)(rect->bottom - rect->top));
}
@@ -84,7 +84,7 @@ void CSoftwareFrameProcessor::CompletionFunction(
const uint64_t copyReady = CFrameScheduler::Nanotime();
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 postProcessStart = fbRes->GetPostProcessStart();
const uint64_t copyStart = fbRes->GetCopyStart();
@@ -104,10 +104,10 @@ void CSoftwareFrameProcessor::CompletionFunction(
const uint64_t measured = postProcessTime + copyTime;
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->GetSchedule(), publishedAt);
- processor->m_transport->CompleteFrameBuffer(fbRes->GetFrameIndex(), true);
+ processor->m_transport->CompleteFrameBuffer(fbRes->GetToken(), true);
}
bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
@@ -209,7 +209,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
if (!fbRes)
{
copySlot->Cancel();
- m_transport->AbortFrameBuffer(buffer.frameIndex);
+ m_transport->AbortFrameBuffer(buffer.token);
RestorePendingDamage(
currentDirtyRects, nbDirtyRects, hasDamage);
DEBUG_ERROR("Failed to get a framebuffer for software capture");
@@ -221,7 +221,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
!submission.source->Sync(*copySlot))
{
copySlot->Cancel();
- m_transport->AbortFrameBuffer(buffer.frameIndex);
+ m_transport->AbortFrameBuffer(buffer.token);
RestorePendingDamage(
currentDirtyRects, nbDirtyRects, hasDamage);
SetFullDamage();
@@ -260,10 +260,10 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
bool deliveredToOwner;
if (!m_transport->PublishFrameBuffer(
- buffer.frameIndex, deliverySchedule, deliveredToOwner))
+ buffer.token, deliverySchedule, deliveredToOwner))
{
copySlot->Cancel();
- m_transport->AbortFrameBuffer(buffer.frameIndex);
+ m_transport->AbortFrameBuffer(buffer.token);
RestorePendingDamage(
currentDirtyRects, nbDirtyRects, hasDamage);
if (!submission.noImageUpdate)
@@ -283,7 +283,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
const bool submittedWork = copySlot->HasSubmittedWork();
const bool completionHandled = fbRes->CompletionHandled();
if (!submittedWork && !completionHandled)
- m_transport->FailFrameBuffer(buffer.frameIndex);
+ m_transport->FailFrameBuffer(buffer.token);
RestorePendingDamage(
currentDirtyRects, nbDirtyRects, hasDamage);
if (!submittedWork && !completionHandled)
@@ -295,7 +295,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
}
m_transport->CommitFrameBuffer(
- buffer.frameIndex, commitSchedule, false, deliveredToOwner);
+ buffer.token, commitSchedule, false, deliveredToOwner);
return true;
}
}
diff --git a/idd/LGIdd/display/CDeviceContext.h b/idd/LGIdd/display/CDeviceContext.h
index 48ea40b5..d2c0a416 100644
--- a/idd/LGIdd/display/CDeviceContext.h
+++ b/idd/LGIdd/display/CDeviceContext.h
@@ -31,7 +31,7 @@
#include "display/CDisplayConfiguration.h"
#include "display/CMonitorManager.h"
-#include "transport/ITransport.h"
+#include "transport/CTransportManager.h"
class CDeviceContext : private ITransportEvents
{
@@ -47,7 +47,7 @@ private:
bool m_transportOpened = false;
std::atomic m_initInProgress = 0;
- std::unique_ptr m_transport;
+ std::unique_ptr m_transport;
CDisplayConfiguration m_displayConfiguration;
CMonitorManager m_monitorManager;
@@ -98,7 +98,7 @@ public:
bool CanProcessFP16 () const { return m_canProcessFP16; }
bool IsSoftwareMode () const { return m_softwareMode; }
- ITransport& GetTransport()
+ CTransportManager& GetTransport()
{
return *m_transport;
}
diff --git a/idd/LGIdd/transport/CFrameHub.cpp b/idd/LGIdd/transport/CFrameHub.cpp
new file mode 100644
index 00000000..201b39e0
--- /dev/null
+++ b/idd/LGIdd/transport/CFrameHub.cpp
@@ -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);
+}
diff --git a/idd/LGIdd/transport/CFrameHub.h b/idd/LGIdd/transport/CFrameHub.h
new file mode 100644
index 00000000..6ccfeece
--- /dev/null
+++ b/idd/LGIdd/transport/CFrameHub.h
@@ -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
+
+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 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;
+};
diff --git a/idd/LGIdd/transport/CTransportManager.cpp b/idd/LGIdd/transport/CTransportManager.cpp
index c845e8a3..284765b5 100644
--- a/idd/LGIdd/transport/CTransportManager.cpp
+++ b/idd/LGIdd/transport/CTransportManager.cpp
@@ -145,6 +145,16 @@ bool CTransportManager::InitializeEntry(Entry& entry)
}
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;
return true;
}
@@ -311,6 +321,12 @@ void CTransportManager::Stop()
void CTransportManager::RemoveServices(Entry& entry)
{
+ if (entry.frameAdded)
+ {
+ m_frames.Unbind(entry.id, entry.epoch);
+ entry.frameAdded = false;
+ }
+
if (entry.controlAdded)
{
m_control.Remove(entry.id, entry.epoch);
@@ -356,7 +372,8 @@ DirectFrameBufferMemory CTransportManager::GetDirectMemory() const
IFrameTransport& CTransportManager::Frames()
{
- return Primary().Frames();
+ m_exposed = true;
+ return m_frames;
}
IControlTransport& CTransportManager::Control()
diff --git a/idd/LGIdd/transport/CTransportManager.h b/idd/LGIdd/transport/CTransportManager.h
index 3ce3395e..b0ea3e5d 100644
--- a/idd/LGIdd/transport/CTransportManager.h
+++ b/idd/LGIdd/transport/CTransportManager.h
@@ -21,15 +21,19 @@
#pragma once
#include "transport/CControlHub.h"
+#include "transport/CFrameHub.h"
#include "transport/ITransport.h"
#include
#include
-class CTransportManager final : public ITransport
+class CTransportManager final
{
public:
using CreateFn = std::unique_ptr (*)();
+ using OpenResult = ITransport::OpenResult;
+ using ProcessResult = ITransport::ProcessResult;
+ using Recovery = ITransport::Recovery;
private:
enum class State
@@ -55,10 +59,12 @@ private:
uint32_t epoch = 1;
uint64_t retryAt = 0;
bool controlAdded = false;
+ bool frameAdded = false;
};
std::vector> m_entries;
CControlHub m_control;
+ CFrameHub m_frames;
Entry * m_primary = nullptr;
bool m_initialized = false;
bool m_setup = false;
@@ -76,7 +82,7 @@ private:
public:
CTransportManager() = default;
- ~CTransportManager() override;
+ ~CTransportManager();
CTransportManager(const CTransportManager&) = delete;
CTransportManager& operator=(const CTransportManager&) = delete;
@@ -84,19 +90,19 @@ public:
bool Add(BackendId id, const char * name, bool required, bool primary,
CreateFn create);
- OpenResult Open() override;
- bool Initialize() override;
- bool Setup(size_t alignment) override;
- ProcessResult Process(ITransportEvents& events) override;
- void Stop() override;
- void SyncRecovery() override;
+ OpenResult Open();
+ bool Initialize();
+ bool Setup(size_t alignment);
+ ProcessResult Process(ITransportEvents& events);
+ void Stop();
+ void SyncRecovery();
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;
- DirectFrameBufferMemory GetDirectMemory() const override;
+ FrameMemoryLimits GetMemoryLimits() const;
+ DirectFrameBufferMemory GetDirectMemory() const;
- IFrameTransport& Frames() override;
- IControlTransport& Control() override;
- IInputTransport * Input() override;
+ IFrameTransport& Frames();
+ IControlTransport& Control();
+ IInputTransport * Input();
};
diff --git a/idd/LGIdd/transport/IFrameSink.h b/idd/LGIdd/transport/IFrameSink.h
new file mode 100644
index 00000000..4f53be75
--- /dev/null
+++ b/idd/LGIdd/transport/IFrameSink.h
@@ -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
+#include
+#include
+
+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;
+};
diff --git a/idd/LGIdd/transport/IFrameTransport.h b/idd/LGIdd/transport/IFrameTransport.h
index dc016c7a..752a586e 100644
--- a/idd/LGIdd/transport/IFrameTransport.h
+++ b/idd/LGIdd/transport/IFrameTransport.h
@@ -48,30 +48,30 @@ public:
const RECT * dirtyRects, unsigned nbDirtyRects,
const CFrameScheduler::Schedule& schedule,
bool allowReadyReplacement = true) = 0;
- virtual bool PublishFrameBuffer(unsigned frameIndex,
+ virtual bool PublishFrameBuffer(const FrameToken& token,
const CFrameScheduler::Schedule& schedule,
bool& deliveredToOwner) = 0;
virtual bool RepublishFrameBuffer(
const CFrameScheduler::Schedule& schedule) = 0;
- virtual bool TryFrameSubmitted(unsigned frameIndex,
+ virtual bool TryFrameSubmitted(const FrameToken& token,
const CFrameScheduler::Schedule& schedule) = 0;
- virtual void CommitFrameBuffer(unsigned frameIndex,
+ virtual void CommitFrameBuffer(const FrameToken& token,
const CFrameScheduler::Schedule& schedule, bool periodic,
bool deliveredToOwner) = 0;
- virtual void AbortFrameBuffer(unsigned frameIndex) = 0;
- virtual void FailFrameBuffer(unsigned frameIndex) = 0;
+ virtual void AbortFrameBuffer(const FrameToken& token) = 0;
+ virtual void FailFrameBuffer(const FrameToken& token) = 0;
virtual void CompleteFrameBuffer(
- unsigned frameIndex, bool succeeded) = 0;
- virtual void SetFrameTiming(unsigned frameIndex, uint64_t captureTime,
+ const FrameToken& token, bool succeeded) = 0;
+ virtual 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) = 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;
- virtual void WriteFrameBufferRows(unsigned frameIndex, void * src,
+ virtual void WriteFrameBufferRows(const FrameToken& token, void * src,
size_t offset, size_t rowBytes, size_t pitch,
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 ForceFrame() = 0;
@@ -82,5 +82,6 @@ public:
uint64_t now, bool periodic) = 0;
virtual void FrameSuperseded() = 0;
virtual HANDLE GetFrameScheduleEvent() const = 0;
- virtual void TryRecordFrameTiming(uint64_t duration) = 0;
+ virtual void TryRecordFrameTiming(
+ const FrameToken& token, uint64_t duration) = 0;
};
diff --git a/idd/LGIdd/transport/ITransport.h b/idd/LGIdd/transport/ITransport.h
index 70b2485c..26d6167d 100644
--- a/idd/LGIdd/transport/ITransport.h
+++ b/idd/LGIdd/transport/ITransport.h
@@ -27,7 +27,7 @@
#include
class IControlTransport;
-class IFrameTransport;
+class IFrameSink;
class IInputTransport;
using BackendId = uint32_t;
@@ -93,7 +93,7 @@ public:
virtual FrameMemoryLimits GetMemoryLimits() const = 0;
virtual DirectFrameBufferMemory GetDirectMemory() const = 0;
- virtual IFrameTransport& Frames() = 0;
+ virtual IFrameSink& FrameSink() = 0;
virtual IControlTransport& Control() = 0;
virtual IInputTransport * Input() { return nullptr; }
};
diff --git a/idd/LGIdd/transport/PreparedFrameBuffer.h b/idd/LGIdd/transport/PreparedFrameBuffer.h
index c8dcfd71..a1d96fb7 100644
--- a/idd/LGIdd/transport/PreparedFrameBuffer.h
+++ b/idd/LGIdd/transport/PreparedFrameBuffer.h
@@ -22,9 +22,26 @@
#include
+struct FrameToken
+{
+ uint32_t sink = 0;
+ uint32_t epoch = 0;
+ uint32_t slot = 0;
+ uint64_t serial = 0;
+};
+
struct PreparedFrameBuffer
{
- unsigned frameIndex;
+ FrameToken token;
+ unsigned resourceSlot;
+ uint8_t * mem;
+ uint64_t heapOffset;
+ bool fullCopy;
+};
+
+struct SinkTarget
+{
+ unsigned slot;
uint8_t * mem;
uint64_t heapOffset;
bool fullCopy;
diff --git a/idd/LGIdd/transport/TransportFactory.cpp b/idd/LGIdd/transport/TransportFactory.cpp
index b0e7b5d9..0dd5d73b 100644
--- a/idd/LGIdd/transport/TransportFactory.cpp
+++ b/idd/LGIdd/transport/TransportFactory.cpp
@@ -30,11 +30,11 @@ static std::unique_ptr CreateLGMP()
return std::unique_ptr(new (std::nothrow) CLGMPTransport());
}
-std::unique_ptr CreateTransport()
+std::unique_ptr CreateTransport()
{
std::unique_ptr manager(
new (std::nothrow) CTransportManager());
if (!manager || !manager->Add(1, "LGMP", true, true, CreateLGMP))
- return std::unique_ptr();
- return std::unique_ptr(manager.release());
+ return std::unique_ptr();
+ return manager;
}
diff --git a/idd/LGIdd/transport/TransportFactory.h b/idd/LGIdd/transport/TransportFactory.h
index b11671e9..cfd705d3 100644
--- a/idd/LGIdd/transport/TransportFactory.h
+++ b/idd/LGIdd/transport/TransportFactory.h
@@ -20,8 +20,8 @@
#pragma once
-#include "transport/ITransport.h"
-
#include
-std::unique_ptr CreateTransport();
+class CTransportManager;
+
+std::unique_ptr CreateTransport();
diff --git a/idd/LGIdd/transport/lgmp/CLGMPFrameTransport.cpp b/idd/LGIdd/transport/lgmp/CLGMPFrameTransport.cpp
index 9cf1dbc6..19737bbb 100644
--- a/idd/LGIdd/transport/lgmp/CLGMPFrameTransport.cpp
+++ b/idd/LGIdd/transport/lgmp/CLGMPFrameTransport.cpp
@@ -717,13 +717,13 @@ bool CLGMPFrameTransport::RetryPendingDelivery(uint64_t now, bool& retry)
return result == SHARED_FRAME_POSTED;
}
-PreparedFrameBuffer CLGMPFrameTransport::PrepareFrameBuffer(
+SinkTarget CLGMPFrameTransport::PrepareFrameBuffer(
unsigned pitch, const D12FrameFormat& srcFormat,
const D12FrameFormat& dstFormat, const RECT * dirtyRects,
unsigned nbDirtyRects, const CFrameScheduler::Schedule& schedule,
bool allowReadyReplacement)
{
- PreparedFrameBuffer result = {};
+ SinkTarget result = {};
const unsigned dataWidth = dstFormat.dataWidth ?
dstFormat.dataWidth : (unsigned)dstFormat.desc.Width;
@@ -913,7 +913,7 @@ PreparedFrameBuffer CLGMPFrameTransport::PrepareFrameBuffer(
LGMPBuffer * fb = m_frameBuffer[frameIndex];
fb->wp = 0;
- result.frameIndex = frameIndex;
+ result.slot = frameIndex;
result.mem = fb->data;
result.heapOffset = reinterpret_cast(fb->data) -
reinterpret_cast(m_ivshmem.GetMem());
diff --git a/idd/LGIdd/transport/lgmp/CLGMPFrameTransport.h b/idd/LGIdd/transport/lgmp/CLGMPFrameTransport.h
index d68f694b..2672cb1c 100644
--- a/idd/LGIdd/transport/lgmp/CLGMPFrameTransport.h
+++ b/idd/LGIdd/transport/lgmp/CLGMPFrameTransport.h
@@ -34,14 +34,14 @@ extern "C" {
#include "capture/CFrameScheduler.h"
#include "capture/FramePipeline.h"
#include "transport/FrameMemoryLimits.h"
-#include "transport/IFrameTransport.h"
+#include "transport/IFrameSink.h"
class CIVSHMEM;
class CLGMPHost;
class CLGMPTransport;
struct LGMPBuffer;
-class CLGMPFrameTransport final : public IFrameTransport
+class CLGMPFrameTransport final : public IFrameSink
{
private:
friend class CLGMPTransport;
@@ -172,7 +172,7 @@ public:
bool GetPendingDeliveryTarget(
uint64_t now, uint64_t& target) override;
bool RetryPendingDelivery(uint64_t now, bool& retry) override;
- PreparedFrameBuffer PrepareFrameBuffer(unsigned pitch,
+ SinkTarget PrepareFrameBuffer(unsigned pitch,
const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
const RECT * dirtyRects, unsigned nbDirtyRects,
const CFrameScheduler::Schedule& schedule,
diff --git a/idd/LGIdd/transport/lgmp/CLGMPTransport.h b/idd/LGIdd/transport/lgmp/CLGMPTransport.h
index 36f3656e..a51b98b9 100644
--- a/idd/LGIdd/transport/lgmp/CLGMPTransport.h
+++ b/idd/LGIdd/transport/lgmp/CLGMPTransport.h
@@ -63,7 +63,7 @@ public:
FrameMemoryLimits GetMemoryLimits() const override;
DirectFrameBufferMemory GetDirectMemory() const override;
- IFrameTransport& Frames() override { return m_frames; }
+ IFrameSink& FrameSink() override { return m_frames; }
IControlTransport& Control() override { return m_control; }
IInputTransport * Input() override { return &m_input; }
};