[idd] transport: abstract LGMP implementation

Introduce transport, frame, and control interfaces with an LGMP factory
backend.

Move LGMP and IVSHMEM implementation details under transport/lgmp and
expose direct frame-buffer memory through a neutral capability.
This commit is contained in:
Geoffrey McRae
2026-08-07 16:39:07 +10:00
parent 30a1383d5e
commit 6725133375
46 changed files with 1026 additions and 480 deletions

View File

@@ -19,11 +19,12 @@
*/
#include "capture/CFrameBufferPool.h"
#include "transport/IFrameTransport.h"
#include <stdint.h>
void CFrameBufferPool::Init(
CFrameTransport * transport, CD3D12Device * dx12)
IFrameTransport * transport, CD3D12Device * dx12)
{
m_transport = transport;
m_dx12 = dx12;
@@ -43,8 +44,9 @@ CFrameBufferResource * CFrameBufferPool::Get(
return nullptr;
CFrameBufferResource * fbr = &m_buffers[buffer.frameIndex];
if (!fbr->Init(m_transport, m_dx12, buffer.frameIndex, buffer.mem,
minSize, textureDesc))
if (!fbr->Init(m_dx12, buffer.frameIndex, buffer.mem,
buffer.heapOffset, minSize, m_transport->GetMaxFrameSize(),
textureDesc))
return nullptr;
return fbr;

View File

@@ -21,22 +21,22 @@
#pragma once
#include "capture/CFrameBufferResource.h"
#include "capture/FrameBufferTypes.h"
#include "common/KVMFR.h"
#include "transport/FrameBufferTypes.h"
#include "transport/TransportTypes.h"
struct CD3D12Device;
class CFrameTransport;
class IFrameTransport;
class CFrameBufferPool
{
private:
CFrameTransport * m_transport = nullptr;
IFrameTransport * m_transport = nullptr;
CD3D12Device * m_dx12 = nullptr;
CFrameBufferResource m_buffers[LGMP_Q_FRAME_BUFFER_LEN];
CFrameBufferResource m_buffers[TRANSPORT_FRAME_BUFFER_COUNT];
public:
void Init(CFrameTransport * transport, CD3D12Device * dx12);
void Init(IFrameTransport * transport, CD3D12Device * dx12);
void Reset();
CFrameBufferResource * Get(const PreparedFrameBuffer& buffer,

View File

@@ -21,21 +21,19 @@
#include "capture/CFrameBufferResource.h"
#include "capture/CFrameProcessorUtil.h"
#include "d3d/CD3D12Device.h"
#include "transport/CFrameTransport.h"
#include "transport/CIVSHMEM.h"
#include "CDebug.h"
#include <cstring>
bool CFrameBufferResource::Init(CFrameTransport * transport,
CD3D12Device * dx12, unsigned frameIndex, uint8_t * base, size_t size,
const D3D12_RESOURCE_DESC * textureDesc)
bool CFrameBufferResource::Init(CD3D12Device * dx12,
unsigned frameIndex, uint8_t * base, uint64_t heapOffset, size_t size,
size_t maxFrameSize, const D3D12_RESOURCE_DESC * textureDesc)
{
m_frameIndex = frameIndex;
if (size > transport->GetMaxFrameSize())
if (size > maxFrameSize)
{
DEBUG_ERROR("Frame size of %llu is too large to fit in shared ram",
DEBUG_ERROR("Frame size of %llu is too large for transport memory",
(unsigned long long)size);
return false;
}
@@ -47,7 +45,7 @@ bool CFrameBufferResource::Init(CFrameTransport * transport,
D3D12_RESOURCE_DESC desc = {};
if (textureDesc)
{
if (indirect || !dx12->CanUseIVSHMEMTexture())
if (indirect || !dx12->CanUseDirectTexture())
return false;
desc = *textureDesc;
if (desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D ||
@@ -130,20 +128,19 @@ bool CFrameBufferResource::Init(CFrameTransport * transport,
}
else
{
const UINT64 heapOffset =
(uintptr_t)base -
(uintptr_t)transport->GetIVSHMEM().GetMem();
const D3D12_RESOURCE_ALLOCATION_INFO allocation =
dx12->GetDevice()->GetResourceAllocationInfo(0, 1, &desc);
allocationSize = allocation.SizeInBytes;
const D3D12_HEAP_DESC heapDesc = dx12->GetHeap()->GetDesc();
const D3D12_HEAP_DESC heapDesc =
dx12->GetTransportHeap()->GetDesc();
if (!allocation.Alignment ||
heapOffset % allocation.Alignment ||
allocation.SizeInBytes > transport->GetMaxFrameSize() ||
allocation.SizeInBytes > maxFrameSize ||
heapOffset > heapDesc.SizeInBytes ||
allocation.SizeInBytes > heapDesc.SizeInBytes - heapOffset)
{
DEBUG_ERROR("IVSHMEM resource does not fit its framebuffer allocation");
DEBUG_ERROR(
"Transport resource does not fit its framebuffer allocation");
return false;
}
@@ -156,20 +153,20 @@ bool CFrameBufferResource::Init(CFrameTransport * transport,
if (FAILED(hr) ||
!(support.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D))
{
DEBUG_ERROR("IVSHMEM texture format is unsupported");
DEBUG_ERROR("Transport texture format is unsupported");
return false;
}
DEBUG_TRACE("Creating IVSHMEM texture for %p", base);
resName = L"IVSHMEM Texture";
DEBUG_TRACE("Creating transport texture for %p", base);
resName = L"Transport Texture";
}
else
{
DEBUG_TRACE("Creating IVSHMEM buffer for %p", base);
resName = L"IVSHMEM";
DEBUG_TRACE("Creating transport buffer for %p", base);
resName = L"Transport Buffer";
}
hr = dx12->GetDevice()->CreatePlacedResource(
dx12->GetHeap().Get(),
dx12->GetTransportHeap().Get(),
heapOffset,
&desc,
D3D12_RESOURCE_STATE_COMMON,

View File

@@ -27,11 +27,10 @@
#include <atomic>
#include <stdint.h>
#include "capture/CFrameScheduler.h"
#include "transport/CFrameScheduler.h"
#include "d3d/CInteropResource.h"
struct CD3D12Device;
class CFrameTransport;
using namespace Microsoft::WRL;
@@ -70,8 +69,8 @@ class CFrameBufferResource
void * m_map = nullptr;
public:
bool Init(CFrameTransport * transport, CD3D12Device * dx12,
unsigned frameIndex, uint8_t * base, size_t size,
bool Init(CD3D12Device * dx12, unsigned frameIndex, uint8_t * base,
uint64_t heapOffset, size_t size, size_t maxFrameSize,
const D3D12_RESOURCE_DESC * textureDesc = nullptr);
void Reset();

View File

@@ -27,9 +27,9 @@
#include <new>
#include <utility>
CFrameProcessor::CFrameProcessor(CFrameTransport * transport,
CFrameProcessor::CFrameProcessor(IFrameTransport * transport,
std::shared_ptr<CD3D12Device> dx12,
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
m_transport(transport),
m_dx12(std::move(dx12)),
@@ -154,9 +154,9 @@ void CFrameProcessor::GetPreviousDamage(
}
std::unique_ptr<CFrameProcessor> CreateFrameProcessor(
bool software, CFrameTransport * transport,
bool software, IFrameTransport * transport,
std::shared_ptr<CD3D12Device> dx12,
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
SRWLOCK * pipelineLock, HANDLE terminateEvent)
{
std::unique_ptr<CFrameProcessor> processor;

View File

@@ -24,13 +24,15 @@
#include "capture/CFrameBufferPool.h"
#include "d3d/CInteropResource.h"
#include "postprocess/CPostProcessor.h"
#include "transport/CFrameScheduler.h"
#include "transport/TransportTypes.h"
#include <Windows.h>
#include <memory>
using namespace Microsoft::WRL;
class CFrameTransport;
class IFrameTransport;
struct FrameSubmission
{
@@ -46,7 +48,7 @@ struct FrameSubmission
class CFrameProcessor
{
protected:
CFrameTransport * m_transport;
IFrameTransport * m_transport;
std::shared_ptr<CD3D12Device> m_dx12;
CPostProcessor * m_postProcessors;
SRWLOCK * m_pipelineLock;
@@ -72,9 +74,9 @@ protected:
virtual void SetFullDamageLocked();
public:
CFrameProcessor(CFrameTransport * transport,
CFrameProcessor(IFrameTransport * transport,
std::shared_ptr<CD3D12Device> dx12,
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
SRWLOCK * pipelineLock, HANDLE terminateEvent);
virtual ~CFrameProcessor() = default;
@@ -94,7 +96,7 @@ public:
};
std::unique_ptr<CFrameProcessor> CreateFrameProcessor(
bool software, CFrameTransport * transport,
bool software, IFrameTransport * transport,
std::shared_ptr<CD3D12Device> dx12,
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
SRWLOCK * pipelineLock, HANDLE terminateEvent);

File diff suppressed because it is too large Load Diff

View File

@@ -1,171 +0,0 @@
/**
* 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 <Windows.h>
#include <stdint.h>
extern "C" {
#include <lgmp/lgmp.h>
}
#include "common/KVMFR.h"
class CFrameScheduler
{
public:
struct Schedule
{
uint32_t clientID;
uint32_t generation;
uint32_t epoch;
uint64_t period;
uint64_t targetSlack;
uint64_t deadline;
uint64_t forceTicket;
uint64_t republishTicket;
uint32_t deadlineSerial;
uint32_t deliveryDeadlineSerial;
bool phaseEligible;
};
private:
struct Client
{
uint32_t clientID;
uint32_t generation;
uint64_t period;
uint64_t targetSlack;
uint64_t expiry;
uint64_t nextDelivery;
uint32_t lastFeedbackDeadlineSerial;
uint32_t lastDeliveredFrameSerial;
bool subscribed;
bool ownerCapable;
bool subscriptionSeen;
bool active;
bool immediate;
bool deliveredFrameValid;
};
struct Publication
{
uint32_t generation;
uint32_t epoch;
uint32_t deadlineSerial;
uint32_t frameSerial;
uint64_t deadline;
bool committed;
bool completed;
bool phaseValid;
bool accepted;
};
static const unsigned PUBLICATION_HISTORY_SIZE = 128;
static const unsigned WORK_TIMING_HISTORY_SIZE = 32;
mutable SRWLOCK m_lock = SRWLOCK_INIT;
HANDLE m_wakeEvent = nullptr;
Client m_clients[LGMP_MAX_CLIENTS] = {};
Schedule m_schedule = {};
bool m_scheduling = false;
uint32_t m_epoch = 0;
// A result acknowledges only the request tickets captured by its attempt.
uint64_t m_forceRequestTicket = 0;
uint64_t m_forceAckTicket = 0;
uint64_t m_republishRequestTicket = 0;
uint64_t m_republishAckTicket = 0;
uint64_t m_lastArrival = 0;
uint64_t m_guestPeriod = 0;
uint64_t m_workEstimate = 0;
uint64_t m_workTiming[WORK_TIMING_HISTORY_SIZE] = {};
unsigned m_workTimingCount = 0;
unsigned m_workTimingIndex = 0;
uint64_t m_nextDeadline = 0;
uint32_t m_deadlineSerial = 0;
int64_t m_pendingCorrection = 0;
Publication m_publications[PUBLICATION_HISTORY_SIZE] = {};
unsigned m_publicationIndex = 0;
int64_t m_lastPhaseError = 0;
uint64_t m_acquiredFrames = 0;
uint64_t m_skippedFrames = 0;
uint64_t m_publishedFrames = 0;
uint64_t m_lastLog = 0;
uint64_t m_lastLogAcquired = 0;
uint64_t m_lastLogSkipped = 0;
uint64_t m_lastLogPublished = 0;
Client * FindClient(uint32_t clientID);
Client * FindOrAllocateClient(uint32_t clientID);
Publication * FindPublication(const Schedule& schedule,
uint32_t frameSerial);
bool ElectOwner(uint64_t now, uint32_t resetClientID = 0);
bool ApplyFeedback(Client& client, const KVMFRFrameSchedule& schedule);
void AdvanceCurrentDeadline();
void AdvanceDeadlineSerial(uint64_t count);
void AdvanceDeadline(uint64_t now);
static void AdvanceDelivery(Client& client, uint64_t now);
void WakePublisher() const;
public:
CFrameScheduler();
~CFrameScheduler();
static uint64_t Nanotime();
void Reset();
void UpdateSubscribers(const uint32_t * clientIDs, unsigned count,
const uint32_t * ownerClientIDs, unsigned ownerCount, uint64_t now);
bool UpdateSchedule(uint32_t sourceClientID,
const KVMFRFrameSchedule& schedule, uint64_t now);
bool GetSchedule(Schedule& schedule) const;
HANDLE GetWakeEvent() const { return m_wakeEvent; }
void ObserveFrame(uint64_t now);
void ForceFrame();
bool GetPublishTarget(uint64_t now, uint64_t& target,
Schedule& schedule, bool& periodic, bool& republish);
void FrameMissed(const Schedule& schedule, uint64_t now, bool periodic);
void FrameSuperseded();
bool TryFrameSubmitted(const Schedule& schedule, uint32_t frameSerial);
void FramePublished(const Schedule& schedule, uint32_t frameSerial,
uint64_t now, bool periodic);
void FrameRetained(const Schedule& schedule, uint64_t now,
bool periodic);
void FrameRepublished(const Schedule& schedule, uint32_t frameSerial);
bool TryFrameCompleted(const Schedule& schedule, uint32_t frameSerial,
uint64_t completedAt);
unsigned GetSecondaryRecipients(const uint32_t * clientIDs,
unsigned count, uint32_t frameSerial, uint64_t now,
uint32_t * recipients) const;
bool GetSecondaryTarget(uint32_t frameSerial, uint64_t now,
const uint32_t * blockedClientIDs, unsigned blockedCount,
uint64_t& target) const;
void FrameDelivered(const uint32_t * clientIDs, unsigned count,
uint32_t frameSerial, uint64_t now);
void RequestRepublish();
void NotifyPublisher() const { WakePublisher(); }
void TryRecordFrameTiming(uint64_t duration);
void LogStatistics(uint64_t now);
};

View File

@@ -20,7 +20,7 @@
#include "capture/CHardwareFrameProcessor.h"
#include "capture/CFrameProcessorUtil.h"
#include "transport/CFrameTransport.h"
#include "transport/IFrameTransport.h"
#include "util/CSRWLock.h"
#include "CDebug.h"
@@ -29,7 +29,7 @@
using namespace Microsoft::WRL;
static_assert(LGMP_Q_FRAME_LEN == 2,
static_assert(TRANSPORT_FRAME_QUEUE_LENGTH == 2,
"IDD candidate pipeline assumes two slots");
class CPublishPending
@@ -71,8 +71,8 @@ public:
};
CHardwareFrameProcessor::CHardwareFrameProcessor(
CFrameTransport * transport, std::shared_ptr<CD3D12Device> dx12,
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
IFrameTransport * transport, std::shared_ptr<CD3D12Device> dx12,
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
CFrameProcessor(transport, std::move(dx12), postProcessors,
pipelineLock, terminateEvent)

View File

@@ -65,8 +65,8 @@ private:
bool active = false;
};
FrameCandidate m_candidates[LGMP_Q_FRAME_LEN];
CandidateDamageTail m_candidateDamageTail[LGMP_Q_FRAME_LEN];
FrameCandidate m_candidates[TRANSPORT_FRAME_QUEUE_LENGTH];
CandidateDamageTail m_candidateDamageTail[TRANSPORT_FRAME_QUEUE_LENGTH];
mutable SRWLOCK m_candidateLock = SRWLOCK_INIT;
SRWLOCK m_copySubmitLock = SRWLOCK_INIT;
uint64_t m_candidateSequence = 0;
@@ -89,9 +89,9 @@ private:
void SetFullDamageLocked() override;
public:
CHardwareFrameProcessor(CFrameTransport * transport,
CHardwareFrameProcessor(IFrameTransport * transport,
std::shared_ptr<CD3D12Device> dx12,
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
SRWLOCK * pipelineLock, HANDLE terminateEvent);
bool IsValid() const override;

View File

@@ -20,21 +20,21 @@
#include "capture/CSoftwareFrameProcessor.h"
#include "capture/CFrameProcessorUtil.h"
#include "capture/FrameBufferTypes.h"
#include "transport/CFrameTransport.h"
#include "transport/TransportTypes.h"
#include "transport/IFrameTransport.h"
#include "util/CSRWLock.h"
#include "CDebug.h"
#include <utility>
CSoftwareFrameProcessor::CSoftwareFrameProcessor(
CFrameTransport * transport, std::shared_ptr<CD3D12Device> dx12,
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
IFrameTransport * transport, std::shared_ptr<CD3D12Device> dx12,
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
CFrameProcessor(transport, std::move(dx12), postProcessors,
pipelineLock, terminateEvent),
m_directTexture(
!m_dx12->IsIndirectCopy() && m_dx12->CanUseIVSHMEMTexture())
!m_dx12->IsIndirectCopy() && m_dx12->CanUseDirectTexture())
{
}
@@ -152,18 +152,18 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
else
{
m_directTexture = false;
DEBUG_WARN("IVSHMEM texture layout does not fit the framebuffer");
DEBUG_WARN("Transport texture layout does not fit the framebuffer");
}
}
else if (m_directTexture)
{
m_directTexture = false;
DEBUG_WARN("Post-processor output cannot use an IVSHMEM texture");
DEBUG_WARN("Post-processor output cannot use a transport texture");
}
if (!pitch || !frameSize || frameSize > m_transport->GetMaxFrameSize())
{
DEBUG_ERROR("Software frame does not fit in shared memory");
DEBUG_ERROR("Software frame does not fit in transport memory");
SetFullDamage();
return false;
}
@@ -190,7 +190,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
deliverySchedule.deliveryDeadlineSerial = 0;
deliverySchedule.phaseEligible = false;
m_transport->ProcessFrameQueue();
m_transport->ProcessDeliveries();
if (!m_transport->FrameBufferAvailable(
deliverySchedule, submission.noImageUpdate))
{
@@ -258,7 +258,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
RestorePendingDamage(
currentDirtyRects, nbDirtyRects, hasDamage);
DEBUG_ERROR_HR(deviceStatus,
"D3D12 device removed while creating an IVSHMEM texture");
"D3D12 device removed while creating a transport texture");
SetFullDamage();
return false;
}
@@ -266,7 +266,7 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
m_directTexture = false;
textureDescPtr = nullptr;
DEBUG_WARN(
"IVSHMEM textures unavailable; using a direct buffer copy");
"Transport textures unavailable; using a direct buffer copy");
}
}

View File

@@ -31,9 +31,9 @@ private:
CD3D12CommandSlot * slot, bool result, void * param1, void * param2);
public:
CSoftwareFrameProcessor(CFrameTransport * transport,
CSoftwareFrameProcessor(IFrameTransport * transport,
std::shared_ptr<CD3D12Device> dx12,
CPostProcessor postProcessors[LGMP_Q_FRAME_LEN],
CPostProcessor postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH],
SRWLOCK * pipelineLock, HANDLE terminateEvent);
bool Submit(const FrameSubmission& submission) override;

View File

@@ -22,7 +22,7 @@
#include "display/IddCxCompat.h"
#include "display/device/CDeviceContext.h"
#include "transport/CLGMPControl.h"
#include "transport/IControlTransport.h"
#include "CDebug.h"

View File

@@ -24,8 +24,8 @@
#include "display/device/CDeviceContext.h"
#include "display/monitor/Context.h"
#include "platform/CPlatformInfo.h"
#include "transport/CFrameTransport.h"
#include "transport/CLGMPControl.h"
#include "transport/IFrameTransport.h"
#include "transport/IControlTransport.h"
#include "util/CSRWLock.h"
#include <avrt.h>
@@ -49,8 +49,8 @@ CSwapChainProcessor::CSwapChainProcessor(CMonitorContext * monitorContext,
m_assignmentGeneration(assignmentGeneration),
m_monitor(monitor),
m_devContext(devContext),
m_transport(devContext->GetFrameTransport()),
m_control(devContext->GetLGMPControl()),
m_transport(devContext->GetTransport().Frames()),
m_control(devContext->GetTransport().Control()),
m_hSwapChain(hSwapChain),
m_renderAdapter(renderAdapter),
m_dx11Device(dx11Device),
@@ -99,7 +99,8 @@ bool CSwapChainProcessor::InitializePipeline()
UINT64 alignSize = CPlatformInfo::GetPageSize();
auto dx12Device = std::make_shared<CD3D12Device>(m_renderAdapter);
const CD3D12Device::InitResult result = dx12Device->Init(
m_transport.GetIVSHMEM(), alignSize, !m_dx11Device->IsSoftware());
m_devContext->GetTransport().GetDirectMemory(), alignSize,
!m_dx11Device->IsSoftware());
if (result == CD3D12Device::RETRY)
{
const HRESULT deviceStatus =
@@ -115,9 +116,9 @@ bool CSwapChainProcessor::InitializePipeline()
if (result == CD3D12Device::FAILURE)
return false;
if (!m_devContext->SetupLGMP(alignSize))
if (!m_devContext->SetupTransport(alignSize))
{
DEBUG_ERROR("SetupLGMP failed");
DEBUG_ERROR("Transport setup failed");
return false;
}
@@ -333,7 +334,7 @@ void CSwapChainProcessor::SwapChainThreadCore()
// Only the buffer2 acquisition path (IddCx 1.10+) reports it; on the legacy
// path HDR is not available, so default to SDR.
DXGI_COLOR_SPACE_TYPE colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
UINT sdrWhiteLevel = KVMFR_SDR_WHITE_LEVEL_DEFAULT;
UINT sdrWhiteLevel = LG_SDR_WHITE_LEVEL_DEFAULT;
const uint64_t captureStart = CFrameScheduler::Nanotime();
#ifdef HAS_IDDCX_110

View File

@@ -25,7 +25,7 @@
#include "display/IddCxCompat.h"
#include "d3d/CInteropResourcePool.h"
#include "capture/CFrameProcessor.h"
#include "common/KVMFR.h"
#include "postprocess/D12FrameFormat.h"
#include "postprocess/CPostProcessor.h"
#include <Windows.h>
@@ -37,8 +37,8 @@ using namespace Microsoft::WRL;
class CMonitorContext;
class CDeviceContext;
class CFrameTransport;
class CLGMPControl;
class IFrameTransport;
class IControlTransport;
class CSwapChainProcessor
{
@@ -47,8 +47,8 @@ private:
UINT64 m_assignmentGeneration;
IDDCX_MONITOR m_monitor;
CDeviceContext * m_devContext;
CFrameTransport & m_transport;
CLGMPControl & m_control;
IFrameTransport & m_transport;
IControlTransport & m_control;
IDDCX_SWAPCHAIN m_hSwapChain;
LUID m_renderAdapter;
std::shared_ptr<CD3D11Device> m_dx11Device;
@@ -56,7 +56,7 @@ private:
HANDLE m_newFrameEvent;
CInteropResourcePool m_resPool;
CPostProcessor m_postProcessors[LGMP_Q_FRAME_LEN];
CPostProcessor m_postProcessors[TRANSPORT_FRAME_QUEUE_LENGTH];
std::unique_ptr<CFrameProcessor> m_frameProcessor;
// Reconfiguration is exclusive while per-candidate recording is shared.
SRWLOCK m_pipelineLock = SRWLOCK_INIT;
@@ -68,7 +68,7 @@ private:
Wrappers::Event m_cursorDataEvent;
BYTE* m_shapeBuffer;
DWORD m_lastShapeId = 0;
std::atomic<UINT> m_sdrWhiteLevel { KVMFR_SDR_WHITE_LEVEL_DEFAULT };
std::atomic<UINT> m_sdrWhiteLevel { LG_SDR_WHITE_LEVEL_DEFAULT };
#ifdef HAS_IDDCX_110
// The per-frame metadata stream can select the monitor default, provide a

View File

@@ -20,7 +20,7 @@
#include "capture/CSwapChainProcessor.h"
#include "transport/CFrameTransport.h"
#include "transport/IFrameTransport.h"
#include <avrt.h>
#include "CDebug.h"
@@ -83,7 +83,7 @@ void CSwapChainProcessor::PublisherThread()
const bool ready = m_frameProcessor->HasReadyFrame();
if (!ready)
{
m_transport.ProcessFrameQueue();
m_transport.ProcessDeliveries();
if (m_frameProcessor->HasReadyFrame())
continue;
@@ -123,12 +123,12 @@ void CSwapChainProcessor::PublisherThread()
}
uint64_t replayTarget;
if (m_transport.GetSharedFrameTarget(current, replayTarget))
if (m_transport.GetPendingDeliveryTarget(current, replayTarget))
{
bool retry = false;
if (replayTarget <= current)
{
if (m_transport.ReplaySharedFrame(current, retry))
if (m_transport.RetryPendingDelivery(current, retry))
continue;
current = CFrameScheduler::Nanotime();
@@ -205,15 +205,15 @@ void CSwapChainProcessor::PublisherThread()
uint64_t current = CFrameScheduler::Nanotime();
uint64_t replayTarget;
if (m_transport.GetSharedFrameTarget(current, replayTarget) &&
if (m_transport.GetPendingDeliveryTarget(current, replayTarget) &&
replayTarget < target)
{
if (replayTarget <= current)
{
m_transport.ProcessFrameQueue();
m_transport.ProcessDeliveries();
current = CFrameScheduler::Nanotime();
bool retry = false;
if (m_transport.ReplaySharedFrame(current, retry))
if (m_transport.RetryPendingDelivery(current, retry))
continue;
current = CFrameScheduler::Nanotime();
@@ -251,7 +251,7 @@ void CSwapChainProcessor::PublisherThread()
}
const uint64_t publishStart = CFrameScheduler::Nanotime();
m_transport.ProcessFrameQueue();
m_transport.ProcessDeliveries();
if (!m_transport.FrameBufferAvailable(schedule) ||
!m_frameProcessor->Publish(schedule, periodic, publishStart))
{

View File

@@ -1,40 +0,0 @@
/**
* 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 <stdint.h>
// FrameBuffer overlays LGMP shared memory and has a variable-length payload.
#pragma warning(push)
#pragma warning(disable: 4200)
struct FrameBuffer
{
volatile uint32_t wp;
uint8_t data[0];
};
#pragma warning(pop)
struct PreparedFrameBuffer
{
unsigned frameIndex;
uint8_t * mem;
bool fullCopy;
};