mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-22 21:43:40 +00:00
[host] nvfbc: add downscale support
This commit is contained in:
parent
7ed18e24e2
commit
87077dfe6e
@ -31,6 +31,7 @@
|
||||
#include "common/rects.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/KVMFR.h"
|
||||
#include "common/vector.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdatomic.h>
|
||||
#include <windows.h>
|
||||
@ -49,6 +50,17 @@ struct FrameInfo
|
||||
uint8_t * diffMap;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int id;
|
||||
bool greater;
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
unsigned int targetX;
|
||||
unsigned int targetY;
|
||||
}
|
||||
DownsampleRule;
|
||||
|
||||
struct iface
|
||||
{
|
||||
bool stop;
|
||||
@ -62,6 +74,8 @@ struct iface
|
||||
|
||||
unsigned int maxWidth , maxHeight;
|
||||
unsigned int width , height;
|
||||
bool resChanged, scale;
|
||||
unsigned int targetWidth, targetHeight;
|
||||
|
||||
unsigned int formatVer;
|
||||
unsigned int grabWidth, grabHeight, grabStride;
|
||||
@ -84,6 +98,8 @@ struct iface
|
||||
struct FrameInfo frameInfo[LGMP_Q_FRAME_LEN];
|
||||
};
|
||||
|
||||
static Vector downsampleRules = {0};
|
||||
|
||||
static struct iface * this = NULL;
|
||||
|
||||
static bool nvfbc_deinit(void);
|
||||
@ -125,10 +141,78 @@ static const char * nvfbc_getName(void)
|
||||
return "NVFBC";
|
||||
};
|
||||
|
||||
static bool downsampleOptParser(struct Option * opt, const char * str)
|
||||
{
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
opt->value.x_string = strdup(str);
|
||||
|
||||
if (downsampleRules.data)
|
||||
vector_destroy(&downsampleRules);
|
||||
|
||||
if (!vector_create(&downsampleRules, sizeof(DownsampleRule), 10))
|
||||
{
|
||||
DEBUG_ERROR("Failed to allocate ram");
|
||||
return false;
|
||||
}
|
||||
|
||||
char * tmp = strdup(str);
|
||||
char * token = strtok(tmp, ",");
|
||||
int count = 0;
|
||||
while(token)
|
||||
{
|
||||
DownsampleRule rule = {0};
|
||||
if (token[0] == '>')
|
||||
{
|
||||
rule.greater = true;
|
||||
++token;
|
||||
}
|
||||
|
||||
if (sscanf(token, "%ux%u:%ux%u",
|
||||
&rule.x,
|
||||
&rule.y,
|
||||
&rule.targetX,
|
||||
&rule.targetY) != 4)
|
||||
{
|
||||
DEBUG_INFO("Unable to parse NvFBC downsample rules");
|
||||
return false;
|
||||
}
|
||||
|
||||
rule.id = count++;
|
||||
|
||||
DEBUG_INFO(
|
||||
"Rule %u: %ux%u IF X %s %4u %s Y %s %4u",
|
||||
rule.id,
|
||||
rule.targetX,
|
||||
rule.targetY,
|
||||
rule.greater ? "> " : "==",
|
||||
rule.x,
|
||||
rule.greater ? "OR " : "AND",
|
||||
rule.greater ? "> " : "==",
|
||||
rule.y
|
||||
);
|
||||
vector_push(&downsampleRules, &rule);
|
||||
|
||||
token = strtok(NULL, ",");
|
||||
}
|
||||
free(tmp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nvfbc_initOptions(void)
|
||||
{
|
||||
struct Option options[] =
|
||||
{
|
||||
{
|
||||
.module = "nvfbc",
|
||||
.name = "downsample", //dxgi:downsample=>1920x1080:1920x1080
|
||||
.description = "Downsample rules, format: [>](width)x(height):(toWidth)x(toHeight)",
|
||||
.type = OPTION_TYPE_STRING,
|
||||
.value.x_string = NULL,
|
||||
.parser = downsampleOptParser
|
||||
},
|
||||
{
|
||||
.module = "nvfbc",
|
||||
.name = "decoupleCursor",
|
||||
@ -180,6 +264,33 @@ static bool nvfbc_create(
|
||||
return true;
|
||||
}
|
||||
|
||||
static void updateScale(void)
|
||||
{
|
||||
DownsampleRule * rule, * match = NULL;
|
||||
vector_forEachRef(rule, &downsampleRules)
|
||||
{
|
||||
if (
|
||||
( rule->greater && (this->width > rule->x || this->height > rule->y)) ||
|
||||
(!rule->greater && (this->width == rule->x && this->height == rule->y)))
|
||||
{
|
||||
match = rule;
|
||||
}
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
DEBUG_INFO("Matched downsample rule %d", rule->id);
|
||||
this->scale = true;
|
||||
this->targetWidth = match->targetX;
|
||||
this->targetHeight = match->targetY;
|
||||
return;
|
||||
}
|
||||
|
||||
this->scale = false;
|
||||
this->targetWidth = this->width;
|
||||
this->targetHeight = this->height;
|
||||
}
|
||||
|
||||
static bool nvfbc_init(void)
|
||||
{
|
||||
int bufferLen = GetEnvironmentVariable("NVFBC_PRIV_DATA", NULL, 0);
|
||||
@ -221,6 +332,7 @@ static bool nvfbc_init(void)
|
||||
free(privData);
|
||||
|
||||
getDesktopSize(&this->width, &this->height);
|
||||
updateScale();
|
||||
|
||||
HANDLE event;
|
||||
if (!NvFBCToSysSetup(
|
||||
@ -356,14 +468,24 @@ static CaptureResult nvfbc_capture(void)
|
||||
if (this->dwmFlush)
|
||||
DwmFlush();
|
||||
|
||||
getDesktopSize(&this->width, &this->height);
|
||||
unsigned int width, height;
|
||||
getDesktopSize(&width, &height);
|
||||
if (this->width != width || this->height != height)
|
||||
{
|
||||
this->resChanged = true;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
updateScale();
|
||||
}
|
||||
|
||||
NvFBCFrameGrabInfo grabInfo;
|
||||
CaptureResult result = NvFBCToSysCapture(
|
||||
this->nvfbc,
|
||||
1000,
|
||||
0, 0,
|
||||
this->width,
|
||||
this->height,
|
||||
this->targetWidth,
|
||||
this->targetHeight,
|
||||
this->scale,
|
||||
&grabInfo
|
||||
);
|
||||
|
||||
@ -371,8 +493,8 @@ static CaptureResult nvfbc_capture(void)
|
||||
return result;
|
||||
|
||||
bool changed = false;
|
||||
const unsigned int h = DIFF_MAP_DIM(this->height, this->diffShift);
|
||||
const unsigned int w = DIFF_MAP_DIM(this->width, this->diffShift);
|
||||
const unsigned int h = DIFF_MAP_DIM(grabInfo.dwWidth , this->diffShift);
|
||||
const unsigned int w = DIFF_MAP_DIM(grabInfo.dwHeight, this->diffShift);
|
||||
for (unsigned int y = 0; y < h; ++y)
|
||||
for (unsigned int x = 0; x < w; ++x)
|
||||
if (this->diffMap[(y*w)+x])
|
||||
@ -420,8 +542,8 @@ static void dsUnion(struct DisjointSet * ds, int a, int b)
|
||||
|
||||
static void updateDamageRects(CaptureFrame * frame)
|
||||
{
|
||||
const unsigned int h = DIFF_MAP_DIM(this->height, this->diffShift);
|
||||
const unsigned int w = DIFF_MAP_DIM(this->width, this->diffShift);
|
||||
const unsigned int h = DIFF_MAP_DIM(this->grabHeight, this->diffShift);
|
||||
const unsigned int w = DIFF_MAP_DIM(this->grabWidth, this->diffShift);
|
||||
|
||||
struct DisjointSet ds[w * h];
|
||||
|
||||
@ -521,8 +643,8 @@ static void updateDamageRects(CaptureFrame * frame)
|
||||
|
||||
int x1 = ds[c].x1 << this->diffShift;
|
||||
int y1 = ds[c].y1 << this->diffShift;
|
||||
int x2 = min((ds[c].x2 + 1) << this->diffShift, this->width);
|
||||
int y2 = min((ds[c].y2 + 1) << this->diffShift, this->height);
|
||||
int x2 = min((ds[c].x2 + 1) << this->diffShift, this->grabWidth);
|
||||
int y2 = min((ds[c].y2 + 1) << this->diffShift, this->grabHeight);
|
||||
frame->damageRects[rectId++] = (FrameDamageRect) {
|
||||
.x = x1,
|
||||
.y = y1,
|
||||
@ -545,21 +667,24 @@ static CaptureResult nvfbc_waitFrame(CaptureFrame * frame,
|
||||
if (
|
||||
this->grabInfo.dwWidth != this->grabWidth ||
|
||||
this->grabInfo.dwHeight != this->grabHeight ||
|
||||
this->grabInfo.dwBufferWidth != this->grabStride)
|
||||
this->grabInfo.dwBufferWidth != this->grabStride ||
|
||||
this->resChanged)
|
||||
{
|
||||
this->grabWidth = this->grabInfo.dwWidth;
|
||||
this->grabHeight = this->grabInfo.dwHeight;
|
||||
this->grabStride = this->grabInfo.dwBufferWidth;
|
||||
// Round up stride in IVSHMEM to avoid issues with dmabuf import.
|
||||
this->shmStride = ALIGN_PAD(this->grabStride, 32);
|
||||
|
||||
this->resChanged = false;
|
||||
++this->formatVer;
|
||||
}
|
||||
|
||||
const unsigned int maxHeight = maxFrameSize / (this->shmStride * 4);
|
||||
|
||||
frame->formatVer = this->formatVer;
|
||||
frame->screenWidth = this->grabWidth;
|
||||
frame->screenHeight = this->grabHeight;
|
||||
frame->screenWidth = this->width;
|
||||
frame->screenHeight = this->height;
|
||||
frame->frameWidth = this->grabWidth;
|
||||
frame->frameHeight = min(maxHeight, this->grabHeight);
|
||||
frame->truncated = maxHeight < this->grabHeight;
|
||||
@ -592,8 +717,8 @@ static CaptureResult nvfbc_waitFrame(CaptureFrame * frame,
|
||||
static CaptureResult nvfbc_getFrame(FrameBuffer * frame,
|
||||
const unsigned int height, int frameIndex)
|
||||
{
|
||||
const unsigned int h = DIFF_MAP_DIM(this->height, this->diffShift);
|
||||
const unsigned int w = DIFF_MAP_DIM(this->width, this->diffShift);
|
||||
const unsigned int h = DIFF_MAP_DIM(this->grabHeight, this->diffShift);
|
||||
const unsigned int w = DIFF_MAP_DIM(this->grabWidth, this->diffShift);
|
||||
uint8_t * frameData = framebuffer_get_data(frame);
|
||||
struct FrameInfo * info = this->frameInfo + frameIndex;
|
||||
|
||||
|
@ -276,6 +276,7 @@ CaptureResult NvFBCToSysCapture(
|
||||
const unsigned int y,
|
||||
const unsigned int width,
|
||||
const unsigned int height,
|
||||
bool scale,
|
||||
NvFBCFrameGrabInfo * grabInfo
|
||||
)
|
||||
{
|
||||
@ -284,7 +285,8 @@ CaptureResult NvFBCToSysCapture(
|
||||
params.dwVersion = NVFBC_TOSYS_GRAB_FRAME_PARAMS_VER;
|
||||
params.dwFlags = NVFBC_TOSYS_WAIT_WITH_TIMEOUT;
|
||||
params.dwWaitTime = waitTime;
|
||||
params.eGMode = NVFBC_TOSYS_SOURCEMODE_CROP;
|
||||
params.eGMode = scale ?
|
||||
NVFBC_TOSYS_SOURCEMODE_SCALE : NVFBC_TOSYS_SOURCEMODE_CROP;
|
||||
params.dwStartX = x;
|
||||
params.dwStartY = y;
|
||||
params.dwTargetWidth = width;
|
||||
|
@ -88,6 +88,7 @@ CaptureResult NvFBCToSysCapture(
|
||||
const unsigned int y,
|
||||
const unsigned int width,
|
||||
const unsigned int height,
|
||||
bool scale,
|
||||
NvFBCFrameGrabInfo * grabInfo
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user