mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-09-02 04:03:56 +00:00
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Add LGProtocol as a pinned submodule and consume its KVMFR protocol definitions throughout the client, host, IDD, OBS, and profiler. Keep Looking Glass framebuffer helpers local while removing duplicated protocol headers and migrating users to KVMFR-scoped types.
223 lines
9.1 KiB
C++
223 lines
9.1 KiB
C++
/**
|
|
* 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 "Atomic.h"
|
|
#include "CSRWLock.h"
|
|
#include "transport/IFrameSink.h"
|
|
#include "transport/IFrameTransport.h"
|
|
#include "transport/ITransport.h"
|
|
|
|
class CFrameHub final : public IFrameTransport, public IFrameEvents
|
|
{
|
|
private:
|
|
struct Sink
|
|
{
|
|
struct ResourceLane
|
|
{
|
|
enum Phase
|
|
{
|
|
IDLE,
|
|
FILLING,
|
|
PENDING,
|
|
CANCELING,
|
|
COMPLETING,
|
|
};
|
|
|
|
uint8_t * mem = nullptr;
|
|
uint64_t heapOffset = 0;
|
|
unsigned localSlot = 0;
|
|
bool direct = false;
|
|
bool valid = false;
|
|
bool busy = false;
|
|
|
|
FrameToken token = {};
|
|
CFrameScheduler::Schedule schedule = {};
|
|
uint64_t content = 0;
|
|
uint64_t captureTime = 0;
|
|
uint64_t postProcessTime = 0;
|
|
uint64_t copyTime = 0;
|
|
uint64_t readyTime = 0;
|
|
uint64_t holdTime = 0;
|
|
uint64_t filledAt = 0;
|
|
uint64_t workStart = 0;
|
|
unsigned pitch = 0;
|
|
unsigned width = 0;
|
|
unsigned height = 0;
|
|
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
|
KVMFRFrameType frameType = FRAME_TYPE_INVALID;
|
|
Phase phase = IDLE;
|
|
FrameDone pendingResult = FrameDone::FAILED;
|
|
uint64_t pendingReadyAt = 0;
|
|
bool timingValid = false;
|
|
bool resultPending = false;
|
|
bool callActive = false;
|
|
bool cancelRequested = false;
|
|
};
|
|
|
|
CSRWLock callLock;
|
|
CSRWLock laneLock;
|
|
IFrameSink * target = nullptr;
|
|
HANDLE drained = nullptr;
|
|
std::atomic<unsigned> outstanding = 0;
|
|
std::atomic_bool active = false;
|
|
std::atomic<BackendId> backend = 0;
|
|
std::atomic<uint32_t> epoch = 0;
|
|
bool reserved = false;
|
|
bool primary = false;
|
|
bool needsFullCopy = true;
|
|
uint64_t lastContent = 0;
|
|
uint64_t lastTerminalContent = 0;
|
|
uint64_t blockedContent = 0;
|
|
size_t blockedFrameSize = 0;
|
|
bool blockedAllocation = false;
|
|
unsigned pitch = 0;
|
|
unsigned width = 0;
|
|
unsigned height = 0;
|
|
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
|
KVMFRFrameType frameType = FRAME_TYPE_INVALID;
|
|
ResourceLane lanes[FRAME_SINK_BUFFERS] = {};
|
|
};
|
|
|
|
struct BatchTarget
|
|
{
|
|
Sink * sink = nullptr;
|
|
BackendId backend = 0;
|
|
uint32_t epoch = 0;
|
|
unsigned localSlot = 0;
|
|
unsigned resourceLane = 0;
|
|
CFrameScheduler::Schedule schedule = {};
|
|
CFrameScheduler::Schedule deliverySchedule = {};
|
|
uint64_t content = 0;
|
|
unsigned pitch = 0;
|
|
unsigned width = 0;
|
|
unsigned height = 0;
|
|
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
|
KVMFRFrameType frameType = FRAME_TYPE_INVALID;
|
|
bool periodic = false;
|
|
bool published = false;
|
|
bool delivered = false;
|
|
bool submitted = false;
|
|
bool committed = false;
|
|
bool completionPending = false;
|
|
bool completionSucceeded = false;
|
|
bool releasePending = false;
|
|
uint64_t captureTime = 0;
|
|
uint64_t postProcessTime = 0;
|
|
uint64_t copyTime = 0;
|
|
uint64_t readyTime = 0;
|
|
uint64_t holdTime = 0;
|
|
uint64_t filledAt = 0;
|
|
uint64_t workStart = 0;
|
|
bool timingValid = false;
|
|
bool active = false;
|
|
};
|
|
|
|
struct Batch
|
|
{
|
|
CSRWLock lock;
|
|
uint64_t serial = 0;
|
|
unsigned count = 0;
|
|
bool active = false;
|
|
BatchTarget targets[FRAME_MAX_SINKS] = {};
|
|
};
|
|
|
|
struct SinkRef
|
|
{
|
|
Sink * sink;
|
|
unsigned index;
|
|
bool primary;
|
|
};
|
|
|
|
mutable CSRWLock m_listLock;
|
|
Sink m_sinks[FRAME_MAX_SINKS];
|
|
Batch m_batches[FRAME_BATCHES];
|
|
std::atomic<uint64_t> m_nextSerial = 0;
|
|
std::atomic<uint64_t> m_nextContent = 0;
|
|
std::atomic<uint64_t> m_newestContent = 0;
|
|
HANDLE m_wakeEvent = nullptr;
|
|
|
|
unsigned Snapshot(SinkRef refs[FRAME_MAX_SINKS]) const;
|
|
bool BatchValid(const Batch& batch, const FrameBatchToken& token) const;
|
|
void ReleaseTarget(Batch& batch, BatchTarget& target);
|
|
bool DetachTarget(Batch& batch, BatchTarget& target,
|
|
FrameToken& token);
|
|
void FillLane(Sink& sink, unsigned laneIndex,
|
|
const FrameToken& token);
|
|
void CancelLane(Sink& sink, unsigned laneIndex,
|
|
const FrameToken& token);
|
|
void CompleteLane(Sink& sink, unsigned laneIndex,
|
|
const FrameToken& token, FrameDone result, uint64_t readyAt);
|
|
|
|
public:
|
|
CFrameHub();
|
|
~CFrameHub() override;
|
|
|
|
CFrameHub(const CFrameHub&) = delete;
|
|
CFrameHub& operator=(const CFrameHub&) = delete;
|
|
|
|
bool Bind(BackendId backend, uint32_t epoch, bool primary,
|
|
IFrameSink& sink);
|
|
void Unbind(BackendId backend, uint32_t epoch);
|
|
|
|
void OnFrameDone(const FrameToken& token, FrameDone result,
|
|
uint64_t readyAt) override;
|
|
|
|
size_t GetMaxFrameSize() const override;
|
|
uint64_t NextContentSerial() override;
|
|
void FrameProductReady(uint64_t contentSerial) override;
|
|
bool NeedsFrame() const override;
|
|
bool GetFramePlan(
|
|
uint64_t now, bool productReady, FramePlan& plan) override;
|
|
bool GetImmediatePrimaryFramePlan(
|
|
uint64_t now, FramePlan& plan) override;
|
|
void MissFramePlan(const FramePlan& plan, uint64_t now) override;
|
|
bool PrepareFrameBatch(const FramePlan& plan,
|
|
uint64_t contentSerial, unsigned pitch, size_t frameSize,
|
|
const D12FrameFormat& srcFormat, const D12FrameFormat& dstFormat,
|
|
const RECT * dirtyRects, unsigned nbDirtyRects,
|
|
bool allowReadyReplacement, PreparedFrameBatch& batch) override;
|
|
uint32_t PublishFrameBatch(const FrameBatchToken& token) override;
|
|
void CommitFrameBatch(const FrameBatchToken& token) override;
|
|
void AbortFrameBatch(const FrameBatchToken& token) override;
|
|
void FailFrameBatch(const FrameBatchToken& token) override;
|
|
void WriteFrameTarget(const FrameBatchToken& token,
|
|
unsigned target, void * src, size_t offset, size_t len,
|
|
bool setWritePos) const override;
|
|
void WriteFrameTargetRows(const FrameBatchToken& token,
|
|
unsigned target, void * src, size_t offset, size_t rowBytes,
|
|
size_t pitch, unsigned rows) const override;
|
|
void FinalizeFrameTarget(const FrameBatchToken& token,
|
|
unsigned target) const override;
|
|
void SetFrameTargetTiming(const FrameBatchToken& token,
|
|
unsigned target, uint64_t captureTime, uint64_t postProcessTime,
|
|
uint64_t copyTime, uint64_t readyTime, uint64_t holdTime,
|
|
uint64_t completedAt) override;
|
|
void TryRecordFrameTiming(const FrameBatchToken& token,
|
|
unsigned target, uint64_t duration) override;
|
|
void CompleteFrameTarget(const FrameBatchToken& token,
|
|
unsigned target, bool succeeded) override;
|
|
void ObserveFrame(uint64_t now) override;
|
|
void ForceFrame() override;
|
|
void FrameSuperseded() override;
|
|
HANDLE GetFrameScheduleEvent() const override { return m_wakeEvent; }
|
|
};
|