mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-09 08:41:31 +00:00
[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:
209
idd/LGIdd/transport/CFrameTransport.h
Normal file
209
idd/LGIdd/transport/CFrameTransport.h
Normal 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);
|
||||
};
|
||||
Reference in New Issue
Block a user