mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-04 06:12:04 +00:00
[common] add frame scheduling protocol
This commit is contained in:
@@ -59,6 +59,7 @@ enum
|
|||||||
{
|
{
|
||||||
LG_TRANSPORT_FEATURE_SET_CURSOR_POS = 0x1,
|
LG_TRANSPORT_FEATURE_SET_CURSOR_POS = 0x1,
|
||||||
LG_TRANSPORT_FEATURE_WINDOW_SIZE = 0x2,
|
LG_TRANSPORT_FEATURE_WINDOW_SIZE = 0x2,
|
||||||
|
LG_TRANSPORT_FEATURE_FRAME_SCHEDULE = 0x4,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t LG_TransportFeatureFlags;
|
typedef uint32_t LG_TransportFeatureFlags;
|
||||||
@@ -133,6 +134,7 @@ typedef struct LG_TransportFrame
|
|||||||
{
|
{
|
||||||
uint64_t serial;
|
uint64_t serial;
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
|
uint32_t scheduleGeneration;
|
||||||
LG_TransportFrameFlags flags;
|
LG_TransportFrameFlags flags;
|
||||||
// Backend-owned immutable metadata, valid until releaseFrame.
|
// Backend-owned immutable metadata, valid until releaseFrame.
|
||||||
const LG_TransportFrameFormat * format;
|
const LG_TransportFrameFormat * format;
|
||||||
@@ -176,9 +178,20 @@ typedef enum LG_TransportControlType
|
|||||||
{
|
{
|
||||||
LG_TRANSPORT_CONTROL_SET_CURSOR_POS,
|
LG_TRANSPORT_CONTROL_SET_CURSOR_POS,
|
||||||
LG_TRANSPORT_CONTROL_WINDOW_SIZE,
|
LG_TRANSPORT_CONTROL_WINDOW_SIZE,
|
||||||
|
LG_TRANSPORT_CONTROL_FRAME_SCHEDULE,
|
||||||
}
|
}
|
||||||
LG_TransportControlType;
|
LG_TransportControlType;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
LG_TRANSPORT_FRAME_SCHEDULE_ACTIVE = 0x1,
|
||||||
|
LG_TRANSPORT_FRAME_SCHEDULE_RELEASE = 0x2,
|
||||||
|
LG_TRANSPORT_FRAME_SCHEDULE_RESET = 0x4,
|
||||||
|
LG_TRANSPORT_FRAME_SCHEDULE_IMMEDIATE = 0x8,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uint32_t LG_TransportFrameScheduleFlags;
|
||||||
|
|
||||||
typedef struct LG_TransportControl
|
typedef struct LG_TransportControl
|
||||||
{
|
{
|
||||||
LG_TransportControlType type;
|
LG_TransportControlType type;
|
||||||
@@ -186,6 +199,17 @@ typedef struct LG_TransportControl
|
|||||||
{
|
{
|
||||||
struct { int32_t x, y; } cursorPos;
|
struct { int32_t x, y; } cursorPos;
|
||||||
struct { uint32_t width, height; } windowSize;
|
struct { uint32_t width, height; } windowSize;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t generation;
|
||||||
|
LG_TransportFrameScheduleFlags flags;
|
||||||
|
uint64_t period;
|
||||||
|
uint64_t targetSlack;
|
||||||
|
int64_t phaseError;
|
||||||
|
uint32_t feedbackFrameSerial;
|
||||||
|
uint32_t lease;
|
||||||
|
}
|
||||||
|
frameSchedule;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
LG_TransportControl;
|
LG_TransportControl;
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ struct LG_Transport
|
|||||||
bool connected;
|
bool connected;
|
||||||
bool framePending;
|
bool framePending;
|
||||||
const KVMFRFrame * pendingFrame;
|
const KVMFRFrame * pendingFrame;
|
||||||
|
uint32_t clientID;
|
||||||
uint32_t frameSerial;
|
uint32_t frameSerial;
|
||||||
bool formatValid;
|
bool formatValid;
|
||||||
LG_TransportFrameFormat format;
|
LG_TransportFrameFormat format;
|
||||||
@@ -297,6 +298,8 @@ static bool lgmp_parseSession(const uint8_t * data, uint32_t size,
|
|||||||
session->features |= LG_TRANSPORT_FEATURE_SET_CURSOR_POS;
|
session->features |= LG_TRANSPORT_FEATURE_SET_CURSOR_POS;
|
||||||
if (header->features & KVMFR_FEATURE_WINDOWSIZE)
|
if (header->features & KVMFR_FEATURE_WINDOWSIZE)
|
||||||
session->features |= LG_TRANSPORT_FEATURE_WINDOW_SIZE;
|
session->features |= LG_TRANSPORT_FEATURE_WINDOW_SIZE;
|
||||||
|
if (header->features & KVMFR_FEATURE_FRAME_SCHEDULE)
|
||||||
|
session->features |= LG_TRANSPORT_FEATURE_FRAME_SCHEDULE;
|
||||||
|
|
||||||
data += sizeof(*header);
|
data += sizeof(*header);
|
||||||
size -= sizeof(*header);
|
size -= sizeof(*header);
|
||||||
@@ -359,8 +362,8 @@ static LG_TransportStatus lgmp_connect(LG_Transport * this,
|
|||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint8_t * data;
|
uint8_t * data;
|
||||||
uint32_t remoteVersion;
|
uint32_t remoteVersion;
|
||||||
LGMP_STATUS status = lgmpClientSessionInit(this->client, &size, &data, NULL,
|
LGMP_STATUS status = lgmpClientSessionInit(this->client, &size, &data,
|
||||||
&remoteVersion);
|
&this->clientID, &remoteVersion);
|
||||||
session->remoteVersion = remoteVersion;
|
session->remoteVersion = remoteVersion;
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
@@ -390,6 +393,7 @@ static void lgmp_disconnect(LG_Transport * this)
|
|||||||
lgmp_closeQueues(this);
|
lgmp_closeQueues(this);
|
||||||
lgmp_closeDMA(this);
|
lgmp_closeDMA(this);
|
||||||
this->connected = false;
|
this->connected = false;
|
||||||
|
this->clientID = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lgmp_sessionValid(LG_Transport * this)
|
static bool lgmp_sessionValid(LG_Transport * this)
|
||||||
@@ -538,7 +542,8 @@ static LG_TransportStatus lgmp_nextFrame(LG_Transport * this, bool useDMA,
|
|||||||
this->frameSerial = frame->frameSerial;
|
this->frameSerial = frame->frameSerial;
|
||||||
|
|
||||||
memset(result, 0, sizeof(*result));
|
memset(result, 0, sizeof(*result));
|
||||||
result->serial = frame->frameSerial;
|
result->serial = frame->frameSerial;
|
||||||
|
result->scheduleGeneration = message.udata;
|
||||||
if (frame->flags & FRAME_FLAG_BLOCK_SCREENSAVER)
|
if (frame->flags & FRAME_FLAG_BLOCK_SCREENSAVER)
|
||||||
result->flags |= LG_TRANSPORT_FRAME_BLOCK_SCREENSAVER;
|
result->flags |= LG_TRANSPORT_FRAME_BLOCK_SCREENSAVER;
|
||||||
if (frame->flags & FRAME_FLAG_REQUEST_ACTIVATION)
|
if (frame->flags & FRAME_FLAG_REQUEST_ACTIVATION)
|
||||||
@@ -763,7 +768,7 @@ static void lgmp_releasePointer(LG_Transport * this,
|
|||||||
static LG_TransportStatus lgmp_sendControl(LG_Transport * this,
|
static LG_TransportStatus lgmp_sendControl(LG_Transport * this,
|
||||||
const LG_TransportControl * control, LG_TransportControlToken * token)
|
const LG_TransportControl * control, LG_TransportControlToken * token)
|
||||||
{
|
{
|
||||||
uint8_t buffer[sizeof(KVMFRWindowSize)];
|
uint8_t buffer[LGMP_MSGS_SIZE];
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
switch (control->type)
|
switch (control->type)
|
||||||
{
|
{
|
||||||
@@ -789,6 +794,23 @@ static LG_TransportStatus lgmp_sendControl(LG_Transport * this,
|
|||||||
size = sizeof(message);
|
size = sizeof(message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case LG_TRANSPORT_CONTROL_FRAME_SCHEDULE:
|
||||||
|
{
|
||||||
|
const KVMFRFrameSchedule message = {
|
||||||
|
.msg.type = KVMFR_MESSAGE_FRAME_SCHEDULE,
|
||||||
|
.clientID = this->clientID,
|
||||||
|
.generation = control->frameSchedule.generation,
|
||||||
|
.flags = control->frameSchedule.flags,
|
||||||
|
.period = control->frameSchedule.period,
|
||||||
|
.targetSlack = control->frameSchedule.targetSlack,
|
||||||
|
.phaseError = control->frameSchedule.phaseError,
|
||||||
|
.feedbackFrameSerial = control->frameSchedule.feedbackFrameSerial,
|
||||||
|
.lease = control->frameSchedule.lease,
|
||||||
|
};
|
||||||
|
memcpy(buffer, &message, sizeof(message));
|
||||||
|
size = sizeof(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return LG_TRANSPORT_ERROR;
|
return LG_TRANSPORT_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
#include "LGMPConfig.h"
|
#include "LGMPConfig.h"
|
||||||
|
|
||||||
#define KVMFR_MAGIC "KVMFR---"
|
#define KVMFR_MAGIC "KVMFR---"
|
||||||
#define KVMFR_VERSION 25
|
#define KVMFR_VERSION 26
|
||||||
|
|
||||||
// Fallback used by producers that cannot report the source display's SDR
|
// Fallback used by producers that cannot report the source display's SDR
|
||||||
// white level. IDD frames override this with IDDCX_METADATA2::SdrWhiteLevel.
|
// white level. IDD frames override this with IDDCX_METADATA2::SdrWhiteLevel.
|
||||||
@@ -59,8 +59,9 @@ typedef uint32_t KVMFRCursorFlags;
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
KVMFR_FEATURE_SETCURSORPOS = 0x1,
|
KVMFR_FEATURE_SETCURSORPOS = 0x1,
|
||||||
KVMFR_FEATURE_WINDOWSIZE = 0x2
|
KVMFR_FEATURE_WINDOWSIZE = 0x2,
|
||||||
|
KVMFR_FEATURE_FRAME_SCHEDULE = 0x4
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t KVMFRFeatureFlags;
|
typedef uint32_t KVMFRFeatureFlags;
|
||||||
@@ -68,7 +69,8 @@ typedef uint32_t KVMFRFeatureFlags;
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
KVMFR_MESSAGE_SETCURSORPOS,
|
KVMFR_MESSAGE_SETCURSORPOS,
|
||||||
KVMFR_MESSAGE_WINDOWSIZE
|
KVMFR_MESSAGE_WINDOWSIZE,
|
||||||
|
KVMFR_MESSAGE_FRAME_SCHEDULE
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t KVMFRMessageType;
|
typedef uint32_t KVMFRMessageType;
|
||||||
@@ -268,6 +270,44 @@ typedef struct KVMFRWindowSize
|
|||||||
}
|
}
|
||||||
KVMFRWindowSize;
|
KVMFRWindowSize;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
KVMFR_FRAME_SCHEDULE_ACTIVE = 0x1,
|
||||||
|
KVMFR_FRAME_SCHEDULE_RELEASE = 0x2,
|
||||||
|
KVMFR_FRAME_SCHEDULE_RESET = 0x4,
|
||||||
|
KVMFR_FRAME_SCHEDULE_IMMEDIATE = 0x8
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uint32_t KVMFRFrameScheduleFlags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Client presentation scheduling is expressed entirely as durations. Client
|
||||||
|
* and producer monotonic clocks have unrelated epochs and must never be
|
||||||
|
* compared directly.
|
||||||
|
*/
|
||||||
|
typedef struct KVMFRFrameSchedule
|
||||||
|
{
|
||||||
|
KVMFRMessage msg;
|
||||||
|
uint32_t clientID;
|
||||||
|
uint32_t generation;
|
||||||
|
KVMFRFrameScheduleFlags flags;
|
||||||
|
uint64_t period;
|
||||||
|
uint64_t targetSlack;
|
||||||
|
int64_t phaseError;
|
||||||
|
uint32_t feedbackFrameSerial;
|
||||||
|
uint32_t lease;
|
||||||
|
uint8_t reserved[16];
|
||||||
|
}
|
||||||
|
KVMFRFrameSchedule;
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
static_assert(sizeof(KVMFRFrameSchedule) == 64,
|
||||||
|
"KVMFR frame schedule must fit in one LGMP control message");
|
||||||
|
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||||
|
_Static_assert(sizeof(KVMFRFrameSchedule) == 64,
|
||||||
|
"KVMFR frame schedule must fit in one LGMP control message");
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user