[host] nvfbc: make diff map size configurable

This commit adds a new host configuration option, nvfbc:diffRes, which
specifies the dimensions of every block in the diff map. This defaults to
128, meaning the default 128x128 block size.

Since block sizes other than 128x128 is not guaranteed to be supported by
NvFBC, the function NvFBCGetDiffMapBlockSize was introduced to query the
support and output the actual block size used.
This commit is contained in:
Quantum 2021-08-02 05:10:22 -04:00 committed by Geoffrey McRae
parent 0603a55492
commit 4da0c64583
3 changed files with 92 additions and 17 deletions

View File

@ -36,7 +36,7 @@
#include <NvFBC/nvFBC.h>
#include "wrapper.h"
#define DIFF_MAP_DIM(x) ((x + 127) / 128)
#define DIFF_MAP_DIM(x, shift) (((x) + (1 << (shift)) - 1) >> (shift))
struct FrameInfo
{
@ -64,6 +64,7 @@ struct iface
uint8_t * frameBuffer;
uint8_t * diffMap;
int diffShift;
NvFBCFrameGrabInfo grabInfo;
@ -130,6 +131,13 @@ static void nvfbc_initOptions(void)
.type = OPTION_TYPE_BOOL,
.value.x_bool = true
},
{
.module = "nvfbc",
.name = "diffRes",
.description = "The resolution of the diff map",
.type = OPTION_TYPE_INT,
.value.x_int = 128
},
{0}
};
@ -186,6 +194,10 @@ static bool nvfbc_init(void)
free(privData);
return false;
}
int diffRes = option_get_bool("nvfbc", "diffRes");
enum DiffMapBlockSize blockSize;
NvFBCGetDiffMapBlockSize(diffRes, &blockSize, &this->diffShift, privData, privDataLen);
free(privData);
getDesktopSize(&this->width, &this->height);
@ -197,7 +209,7 @@ static bool nvfbc_init(void)
!this->seperateCursor,
this->seperateCursor,
true,
DIFFMAP_BLOCKSIZE_128X128,
blockSize,
(void **)&this->frameBuffer,
(void **)&this->diffMap,
&event
@ -221,6 +233,10 @@ static bool nvfbc_init(void)
this->forceCompositionCreated = true;
}
if (diffRes != (1 << this->diffShift))
DEBUG_WARN("DiffMap block size not supported: %dx%d", diffRes, diffRes);
DEBUG_INFO("DiffMap block : %dx%d", 1 << this->diffShift, 1 << this->diffShift);
DEBUG_INFO("Cursor mode : %s", this->seperateCursor ? "decoupled" : "integrated");
for (int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
@ -228,7 +244,10 @@ static bool nvfbc_init(void)
this->frameInfo[i].width = 0;
this->frameInfo[i].height = 0;
this->frameInfo[i].wasFresh = false;
this->frameInfo[i].diffMap = malloc(DIFF_MAP_DIM(this->maxWidth) * DIFF_MAP_DIM(this->maxHeight));
this->frameInfo[i].diffMap = malloc(
DIFF_MAP_DIM(this->maxWidth, this->diffShift) *
DIFF_MAP_DIM(this->maxHeight, this->diffShift)
);
if (!this->frameInfo[i].diffMap)
{
DEBUG_ERROR("Failed to allocate memory for diffMaps");
@ -315,8 +334,8 @@ static CaptureResult nvfbc_capture(void)
return result;
bool changed = false;
const unsigned int h = DIFF_MAP_DIM(this->height);
const unsigned int w = DIFF_MAP_DIM(this->width);
const unsigned int h = DIFF_MAP_DIM(this->height, this->diffShift);
const unsigned int w = DIFF_MAP_DIM(this->width, this->diffShift);
for (unsigned int y = 0; y < h; ++y)
for (unsigned int x = 0; x < w; ++x)
if (this->diffMap[(y*w)+x])
@ -364,8 +383,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);
const unsigned int w = DIFF_MAP_DIM(this->width);
const unsigned int h = DIFF_MAP_DIM(this->height, this->diffShift);
const unsigned int w = DIFF_MAP_DIM(this->width, this->diffShift);
struct DisjointSet ds[w * h];
@ -395,10 +414,10 @@ static void updateDamageRects(CaptureFrame * frame)
goto done;
}
int x1 = ds[y * w + x].x1 * 128;
int y1 = ds[y * w + x].y1 * 128;
int x2 = min((ds[y * w + x].x2 + 1) * 128, this->width);
int y2 = min((ds[y * w + x].y2 + 1) * 128, this->height);
int x1 = ds[y * w + x].x1 << this->diffShift;
int y1 = ds[y * w + x].y1 << this->diffShift;
int x2 = min((ds[y * w + x].x2 + 1) << this->diffShift, this->width);
int y2 = min((ds[y * w + x].y2 + 1) << this->diffShift, this->height);
frame->damageRects[rectId++] = (FrameDamageRect) {
.x = x1,
.y = y1,
@ -473,8 +492,8 @@ inline static void rectCopyUnaligned(uint8_t * dest, uint8_t * src, int ystart,
static CaptureResult nvfbc_getFrame(FrameBuffer * frame,
const unsigned int height, int frameIndex)
{
const unsigned int h = DIFF_MAP_DIM(this->height);
const unsigned int w = DIFF_MAP_DIM(this->width);
const unsigned int h = DIFF_MAP_DIM(this->height, this->diffShift);
const unsigned int w = DIFF_MAP_DIM(this->width, this->diffShift);
uint8_t * frameData = framebuffer_get_data(frame);
struct FrameInfo * info = this->frameInfo + frameIndex;
@ -484,8 +503,8 @@ static CaptureResult nvfbc_getFrame(FrameBuffer * frame,
for (unsigned int y = 0; y < h; ++y)
{
const unsigned int ystart = y * 128;
const unsigned int yend = min(height, (y + 1) * 128);
const unsigned int ystart = y << this->diffShift;
const unsigned int yend = min(height, (y + 1) << this->diffShift);
for (unsigned int x = 0; x < w; )
{
@ -499,8 +518,8 @@ static CaptureResult nvfbc_getFrame(FrameBuffer * frame,
while (x2 < w && ((!wasFresh && info->diffMap[y * w + x2]) || this->diffMap[y * w + x2]))
++x2;
unsigned int width = (min(x2 * 128, this->grabStride) - x * 128) * 4;
rectCopyUnaligned(frameData, this->frameBuffer, ystart, yend, x * 512,
unsigned int width = (min(x2 << this->diffShift, this->grabStride) - (x << this->diffShift)) * 4;
rectCopyUnaligned(frameData, this->frameBuffer, ystart, yend, x << (2 + this->diffShift),
this->grabStride * 4, width);
x = x2;

View File

@ -145,6 +145,54 @@ bool NvFBCToSysCreate(
return true;
}
void NvFBCGetDiffMapBlockSize(
int diffRes,
enum DiffMapBlockSize * diffMapBlockSize,
int * diffShift,
void * privData,
unsigned int privDataSize
)
{
NvFBCStatusEx status = {0};
status.dwVersion = NVFBC_STATUS_VER;
status.dwPrivateDataSize = privDataSize;
status.pPrivateData = privData;
NVFBCRESULT result = nvapi.getStatusEx(&status);
if (result != NVFBC_SUCCESS)
status.bSupportConfigurableDiffMap = FALSE;
if (!status.bSupportConfigurableDiffMap)
{
*diffMapBlockSize = DIFFMAP_BLOCKSIZE_128X128;
*diffShift = 7;
return;
}
switch (diffRes)
{
case 16:
*diffMapBlockSize = DIFFMAP_BLOCKSIZE_16X16;
*diffShift = 4;
break;
case 32:
*diffMapBlockSize = DIFFMAP_BLOCKSIZE_32X32;
*diffShift = 5;
break;
case 64:
*diffMapBlockSize = DIFFMAP_BLOCKSIZE_64X64;
*diffShift = 6;
break;
default:
*diffMapBlockSize = DIFFMAP_BLOCKSIZE_128X128;
*diffShift = 7;
break;
}
}
void NvFBCToSysRelease(NvFBCHandle * handle)
{
if (!*handle)

View File

@ -60,6 +60,14 @@ bool NvFBCToSysCreate(
);
void NvFBCToSysRelease(NvFBCHandle * handle);
void NvFBCGetDiffMapBlockSize(
int diffRes,
enum DiffMapBlockSize * diffMapBlockSize,
int * diffShift,
void * privData,
unsigned int privDataSize
);
bool NvFBCToSysSetup(
NvFBCHandle handle,
enum BufferFormat format,