mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 15:11:31 +00:00
[idd] transport: add frame sink boundary
This commit is contained in:
@@ -61,6 +61,7 @@
|
||||
<ClCompile Include="postprocess\effect\CHDR16to10Effect.cpp" />
|
||||
<ClCompile Include="postprocess\effect\CRGB24Effect.cpp" />
|
||||
<ClCompile Include="transport\CControlHub.cpp" />
|
||||
<ClCompile Include="transport\CFrameHub.cpp" />
|
||||
<ClCompile Include="transport\CTransportManager.cpp" />
|
||||
<ClCompile Include="transport\TransportFactory.cpp" />
|
||||
<ClCompile Include="transport\lgmp\CIVSHMEM.cpp" />
|
||||
@@ -109,10 +110,12 @@
|
||||
<ClInclude Include="postprocess\effect\CHDR16to10Effect.h" />
|
||||
<ClInclude Include="postprocess\effect\CRGB24Effect.h" />
|
||||
<ClInclude Include="transport\CControlHub.h" />
|
||||
<ClInclude Include="transport\CFrameHub.h" />
|
||||
<ClInclude Include="transport\CTransportManager.h" />
|
||||
<ClInclude Include="transport\DirectFrameBufferMemory.h" />
|
||||
<ClInclude Include="transport\FrameMemoryLimits.h" />
|
||||
<ClInclude Include="transport\IControlTransport.h" />
|
||||
<ClInclude Include="transport\IFrameSink.h" />
|
||||
<ClInclude Include="transport\IFrameTransport.h" />
|
||||
<ClInclude Include="transport\IInputTransport.h" />
|
||||
<ClInclude Include="transport\ITransport.h" />
|
||||
|
||||
@@ -157,6 +157,9 @@
|
||||
<ClInclude Include="transport\CControlHub.h">
|
||||
<Filter>Transport</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transport\CFrameHub.h">
|
||||
<Filter>Transport</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transport\CTransportManager.h">
|
||||
<Filter>Transport</Filter>
|
||||
</ClInclude>
|
||||
@@ -169,6 +172,9 @@
|
||||
<ClInclude Include="transport\IControlTransport.h">
|
||||
<Filter>Transport</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transport\IFrameSink.h">
|
||||
<Filter>Transport</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transport\IFrameTransport.h">
|
||||
<Filter>Transport</Filter>
|
||||
</ClInclude>
|
||||
@@ -300,6 +306,9 @@
|
||||
<ClCompile Include="transport\CControlHub.cpp">
|
||||
<Filter>Transport</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="transport\CFrameHub.cpp">
|
||||
<Filter>Transport</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="transport\CTransportManager.cpp">
|
||||
<Filter>Transport</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -25,11 +25,9 @@
|
||||
#include <cstring>
|
||||
|
||||
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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<LONG> m_initInProgress = 0;
|
||||
|
||||
std::unique_ptr<ITransport> m_transport;
|
||||
std::unique_ptr<CTransportManager> 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;
|
||||
}
|
||||
|
||||
307
idd/LGIdd/transport/CFrameHub.cpp
Normal file
307
idd/LGIdd/transport/CFrameHub.cpp
Normal 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);
|
||||
}
|
||||
105
idd/LGIdd/transport/CFrameHub.h
Normal file
105
idd/LGIdd/transport/CFrameHub.h
Normal 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;
|
||||
};
|
||||
@@ -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()
|
||||
|
||||
@@ -21,15 +21,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "transport/CControlHub.h"
|
||||
#include "transport/CFrameHub.h"
|
||||
#include "transport/ITransport.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class CTransportManager final : public ITransport
|
||||
class CTransportManager final
|
||||
{
|
||||
public:
|
||||
using CreateFn = std::unique_ptr<ITransport> (*)();
|
||||
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<std::unique_ptr<Entry>> 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();
|
||||
};
|
||||
|
||||
85
idd/LGIdd/transport/IFrameSink.h
Normal file
85
idd/LGIdd/transport/IFrameSink.h
Normal 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;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
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; }
|
||||
};
|
||||
|
||||
@@ -22,9 +22,26 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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;
|
||||
|
||||
@@ -30,11 +30,11 @@ static std::unique_ptr<ITransport> CreateLGMP()
|
||||
return std::unique_ptr<ITransport>(new (std::nothrow) CLGMPTransport());
|
||||
}
|
||||
|
||||
std::unique_ptr<ITransport> CreateTransport()
|
||||
std::unique_ptr<CTransportManager> CreateTransport()
|
||||
{
|
||||
std::unique_ptr<CTransportManager> manager(
|
||||
new (std::nothrow) CTransportManager());
|
||||
if (!manager || !manager->Add(1, "LGMP", true, true, CreateLGMP))
|
||||
return std::unique_ptr<ITransport>();
|
||||
return std::unique_ptr<ITransport>(manager.release());
|
||||
return std::unique_ptr<CTransportManager>();
|
||||
return manager;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "transport/ITransport.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
std::unique_ptr<ITransport> CreateTransport();
|
||||
class CTransportManager;
|
||||
|
||||
std::unique_ptr<CTransportManager> CreateTransport();
|
||||
|
||||
@@ -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<uintptr_t>(fb->data) -
|
||||
reinterpret_cast<uintptr_t>(m_ivshmem.GetMem());
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user