[idd] project: organize driver sources by responsibility

Group the IDD sources and Visual Studio filters by subsystem.

Split the device and swap-chain implementations into focused units,
rename the context classes, and reduce header coupling.
This commit is contained in:
Geoffrey McRae
2026-08-07 14:38:36 +10:00
parent 3ddc199bec
commit 30a1383d5e
76 changed files with 5067 additions and 3923 deletions

View File

@@ -0,0 +1,209 @@
/**
* 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 <atomic>
#include <stdint.h>
extern "C" {
#include "lgmp/host.h"
}
#include "capture/CFrameScheduler.h"
#include "capture/FrameBufferTypes.h"
#include "common/KVMFR.h"
#include "postprocess/D12FrameFormat.h"
#include "transport/FrameMemoryLimits.h"
class CIVSHMEM;
class CLGMPHost;
class CFrameTransport
{
public:
struct SubscriberSnapshot
{
uint32_t clientIDs [LGMP_MAX_CLIENTS] = {};
uint32_t ownerClientIDs[LGMP_MAX_CLIENTS] = {};
unsigned clientCount = 0;
unsigned ownerClientCount = 0;
LGMP_STATUS status = LGMP_OK;
};
private:
enum SharedFramePostResult
{
SHARED_FRAME_FAILED,
SHARED_FRAME_IDLE,
SHARED_FRAME_POSTED,
};
struct FrameDelivery
{
uint64_t sharedOwnerToken = 0;
unsigned ownerQueueMask = 0;
uint32_t sharedOwnerClientID = 0;
bool sharedOwnerPending = false;
bool sharedPending = false;
};
struct OwnerDelivery
{
uint64_t token = 0;
uint32_t clientID = 0;
unsigned frameIndex = 0;
bool active = false;
};
CLGMPHost& m_host;
CIVSHMEM& m_ivshmem;
PLGMPHostQueue m_frameQueue = nullptr;
PLGMPHostQueue m_frameOwnerQueue[LGMP_Q_FRAME_LEN] = {};
CFrameScheduler m_frameScheduler;
size_t m_alignSize = 0;
size_t m_frameMemoryOffset = 0;
size_t m_maxFrameSize = 0;
// LGMP publication precedes copy completion. Replay only completed frames;
// the deferred index tracks the newest frame still owed to the owner.
std::atomic<LONG> m_submittedFrameIndex = -1;
std::atomic<LONG> m_readyFrameIndex = -1;
LONG m_deferredOwnerFrameIndex = -1;
std::atomic<bool> m_frameInFlight[LGMP_Q_FRAME_BUFFER_LEN] = {};
bool m_frameCompleted[LGMP_Q_FRAME_BUFFER_LEN] = {};
SRWLOCK m_framePublishLock = SRWLOCK_INIT;
uint64_t m_framePublishSequence = 0;
uint64_t m_frameLastPublishSequence[LGMP_Q_FRAME_BUFFER_LEN] = {};
FrameDelivery m_frameDelivery[LGMP_Q_FRAME_BUFFER_LEN] = {};
OwnerDelivery m_ownerDelivery[LGMP_Q_FRAME_LEN] = {};
uint32_t m_formatVer = 0;
uint32_t m_frameSerial = 0;
PLGMPMemory m_frameMemory[LGMP_Q_FRAME_BUFFER_LEN] = {};
KVMFRFrame * m_frame [LGMP_Q_FRAME_BUFFER_LEN] = {};
FrameBuffer * m_frameBuffer[LGMP_Q_FRAME_BUFFER_LEN] = {};
unsigned m_width = 0;
unsigned m_height = 0;
unsigned m_frameWidth = 0;
unsigned m_frameHeight = 0;
unsigned m_pitch = 0;
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
FrameType m_frameType = FRAME_TYPE_INVALID;
// Previous HDR metadata used to detect changes for formatVer bumps.
uint16_t m_lastHDRDisplayPrimary[3][2] = {};
uint16_t m_lastHDRWhitePoint[2] = {};
uint32_t m_lastHDRMaxDisplayLuminance = 0;
uint32_t m_lastHDRMinDisplayLuminance = 0;
uint32_t m_lastHDRMaxContentLightLevel = 0;
uint32_t m_lastHDRMaxFrameAverageLightLevel = 0;
uint32_t m_lastSDRWhiteLevel = 0;
bool m_lastHDRActive = false;
bool m_lastHDRMetadata = false;
void ProcessFrameDeliveries();
bool FrameBufferReferenced(unsigned frameIndex) const;
int FindAvailableFrameBuffer(bool allowReady) const;
int FindNewestCompletedFrame(unsigned excludeFrameIndex) const;
int FindAvailableOwnerQueue(unsigned preferredIndex) const;
unsigned CountOwnerDeliveries(uint32_t clientID) const;
bool HasMatchingOwnerDelivery(uint32_t clientID, unsigned frameIndex,
uint64_t token) const;
SharedFramePostResult PostSharedFrame(unsigned frameIndex,
uint32_t excludeClientID, uint64_t now);
bool PostSharedOwnerFrame(unsigned frameIndex,
const CFrameScheduler::Schedule& schedule);
public:
CFrameTransport(CLGMPHost& host, CIVSHMEM& ivshmem);
~CFrameTransport();
CFrameTransport(const CFrameTransport&) = delete;
CFrameTransport& operator=(const CFrameTransport&) = delete;
bool Initialize();
void SealMemoryLayout();
bool Setup(size_t alignSize);
void DeInit();
FrameMemoryLimits GetMemoryLimits() const;
size_t GetMaxFrameSize() const { return m_maxFrameSize; }
CIVSHMEM& GetIVSHMEM() { return m_ivshmem; }
SubscriberSnapshot SnapshotSubscribers() const;
void FinalizeSubscribers(
const SubscriberSnapshot& snapshot, uint64_t now);
bool UpdateSchedule(uint32_t sourceClientID,
const KVMFRFrameSchedule& schedule, uint64_t now);
bool FrameBufferAvailable(const CFrameScheduler::Schedule& schedule,
bool allowReadyReplacement = true);
bool HasPublishedFrame() const
{
return m_readyFrameIndex.load(std::memory_order_acquire) >= 0;
}
void ProcessFrameQueue();
bool GetSharedFrameTarget(uint64_t now, uint64_t& target);
bool ReplaySharedFrame(uint64_t now, bool& retry);
PreparedFrameBuffer PrepareFrameBuffer(unsigned pitch,
const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
const RECT * dirtyRects, unsigned nbDirtyRects,
const CFrameScheduler::Schedule& schedule,
bool allowReadyReplacement = true);
bool PublishFrameBuffer(unsigned frameIndex,
const CFrameScheduler::Schedule& schedule, bool& deliveredToOwner);
bool RepublishFrameBuffer(const CFrameScheduler::Schedule& schedule);
bool TryFrameSubmitted(unsigned frameIndex,
const CFrameScheduler::Schedule& schedule);
void CommitFrameBuffer(unsigned frameIndex,
const CFrameScheduler::Schedule& schedule, bool periodic,
bool deliveredToOwner);
void AbortFrameBuffer(unsigned frameIndex);
void FailFrameBuffer(unsigned frameIndex);
void CompleteFrameBuffer(unsigned frameIndex, bool succeeded);
void SetFrameTiming(unsigned frameIndex, uint64_t captureTime,
uint64_t postProcessTime, uint64_t copyTime, uint64_t readyTime,
uint64_t holdTime, const CFrameScheduler::Schedule& schedule,
uint64_t completedAt);
void WriteFrameBuffer(unsigned frameIndex, void * src, size_t offset,
size_t len, bool setWritePos) const;
void WriteFrameBufferRows(unsigned frameIndex, void * src,
size_t offset, size_t rowBytes, size_t pitch, unsigned rows) const;
void FinalizeFrameBuffer(unsigned frameIndex) const;
void ObserveFrame(uint64_t now);
void ForceFrame();
bool GetPublishTarget(uint64_t now, uint64_t& target,
CFrameScheduler::Schedule& schedule, bool& periodic, bool& republish);
void FrameMissed(const CFrameScheduler::Schedule& schedule,
uint64_t now, bool periodic);
void FrameSuperseded();
HANDLE GetFrameScheduleEvent() const
{
return m_frameScheduler.GetWakeEvent();
}
void TryRecordFrameTiming(uint64_t duration);
};