From 4da0c6458331ca3e362fda7dc7fd65f9676f7616 Mon Sep 17 00:00:00 2001 From: Quantum Date: Mon, 2 Aug 2021 05:10:22 -0400 Subject: [PATCH] [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. --- .../Windows/capture/NVFBC/src/nvfbc.c | 53 +++++++++++++------ .../Windows/capture/NVFBC/src/wrapper.cpp | 48 +++++++++++++++++ .../Windows/capture/NVFBC/src/wrapper.h | 8 +++ 3 files changed, 92 insertions(+), 17 deletions(-) diff --git a/host/platform/Windows/capture/NVFBC/src/nvfbc.c b/host/platform/Windows/capture/NVFBC/src/nvfbc.c index f2bf520e..cf5b392a 100644 --- a/host/platform/Windows/capture/NVFBC/src/nvfbc.c +++ b/host/platform/Windows/capture/NVFBC/src/nvfbc.c @@ -36,7 +36,7 @@ #include #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; diff --git a/host/platform/Windows/capture/NVFBC/src/wrapper.cpp b/host/platform/Windows/capture/NVFBC/src/wrapper.cpp index 0ed5729a..0d5d8a2c 100644 --- a/host/platform/Windows/capture/NVFBC/src/wrapper.cpp +++ b/host/platform/Windows/capture/NVFBC/src/wrapper.cpp @@ -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) diff --git a/host/platform/Windows/capture/NVFBC/src/wrapper.h b/host/platform/Windows/capture/NVFBC/src/wrapper.h index f64fd519..0f0f184b 100644 --- a/host/platform/Windows/capture/NVFBC/src/wrapper.h +++ b/host/platform/Windows/capture/NVFBC/src/wrapper.h @@ -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,