Clean up NvFBC interfaces

This commit is contained in:
Lily Tsuru 2024-11-30 01:03:26 -05:00
parent 80190c40af
commit 3521879ced
4 changed files with 57 additions and 59 deletions

View file

@ -110,14 +110,14 @@ namespace hazelnut {
}
bool NvfbcCreateInstance() {
// Destroy an existing NVFBC session to avoid memory leak
// Destroy an existing NvFBC instance to avoid resource leaks.
if(nvfbc) {
NvfbcDestroyInstance();
}
DWORD maxDisplayWidth = -1;
DWORD maxDisplayHeight = -1;
nvfbc = (NvFBCToSys*)nvfbcLib.create(NVFBC_TO_SYS, &maxDisplayWidth, &maxDisplayHeight);
nvfbc = nvfbcLib.CreateToSys(&maxDisplayWidth, &maxDisplayHeight);
if(!nvfbc) {
return false;
@ -133,22 +133,23 @@ namespace hazelnut {
blockSize = NVFBC_TOSYS_DIFFMAP_BLOCKSIZE_32X32;
// set up a session
NVFBC_TOSYS_SETUP_PARAMS fbcSysSetupParams = { 0 };
NVFBC_TOSYS_SETUP_PARAMS fbcSysSetupParams{};
fbcSysSetupParams.dwVersion = NVFBC_TOSYS_SETUP_PARAMS_VER;
fbcSysSetupParams.eMode = NVFBC_TOSYS_ARGB;
fbcSysSetupParams.bWithHWCursor = true;
fbcSysSetupParams.ppBuffer = (void**)&pRawFramebuffer;
fbcSysSetupParams.ppBuffer = reinterpret_cast<void**>(&pRawFramebuffer);
// enable a 32x32 difference map
// enable the difference map with configured blocksize
// (currently hardcoded to 32x32).
fbcSysSetupParams.bDiffMap = TRUE;
fbcSysSetupParams.ppDiffMap = (void**)&pDiffMap;
fbcSysSetupParams.ppDiffMap = reinterpret_cast<void**>(&pDiffMap);
fbcSysSetupParams.eDiffMapBlockSize = blockSize;
auto status = nvfbc->NvFBCToSysSetUp(&fbcSysSetupParams);
if(status != NVFBC_SUCCESS)
return false;
memset(&fbcSysGrabParams, 0, sizeof(NVFBC_TOSYS_GRAB_FRAME_PARAMS));
fbcSysGrabParams = {};
// set up grab params
fbcSysGrabParams.dwVersion = NVFBC_TOSYS_GRAB_FRAME_PARAMS_VER;
@ -196,11 +197,13 @@ namespace hazelnut {
auto* pSrcData = (u8*)&pRawFramebuffer[0];
for(u32 y = 0; y < grabInfo.dwHeight; ++y) {
// Convert to BGRA
// FIXME: Make this SIMD. I can't into this very well
#if 0
usize srcStart = (y * grabInfo.dwBufferWidth) * 4;
usize dstStart = (y * width) * 4;
// Convert to BGRA
for(u32 x = 0; x < grabInfo.dwWidth * 4; x += 4) {
pBufferData[(dstStart + x) + 0] = pSrcData[(srcStart + x) + 2]; // B
pBufferData[(dstStart + x) + 1] = pSrcData[(srcStart + x) + 1]; // G

View file

@ -100,12 +100,12 @@ class cStreamClient {
header.datalen = sizeof(tDataMessage);
// send tile header
//bool sendFull = false;
// bool sendFull = false;
tDataMessage dm;
//if(tiles.empty()) {
// if(tiles.empty()) {
// sendFull = true;
//}
// }
if(sendFull) {
dm.tileCount = 1;
@ -118,7 +118,7 @@ class cStreamClient {
dm.tileCount = 1;
sendFull = true;
} else {
}*/
// we have writev() at home
@ -143,7 +143,7 @@ class cStreamClient {
// send header
send(tcpSocket, (const char*)&tile_wire, (i32)sizeof(tile_wire), 0);
// send(tcpSocket, (const char*)&tileData[0], (i32)tileData.size() * 4, 0);
// send(tcpSocket, (const char*)&tileData[0], (i32)tileData.size() * 4, 0);
// send data now
/*for (auto y = tile.y; y < tile.y + tile.height; ++y) {
@ -154,7 +154,7 @@ class cStreamClient {
} else {
tTile tDummyTile { 0, 0, width, height };
send(tcpSocket, (const char*)&tDummyTile, sizeof(tDummyTile), 0);
//send(tcpSocket, (const char*)&pData[0], (i32)((width * height) * sizeof(u32)), 0);
// send(tcpSocket, (const char*)&pData[0], (i32)((width * height) * sizeof(u32)), 0);
}
send(tcpSocket, (const char*)&pData[0], (i32)((width * height) * sizeof(u32)), 0);
@ -193,21 +193,7 @@ int main(int argc, char** argv) {
while(true) {
auto result = capture->CaptureFrame();
if(result == hazelnut::DisplayCaptureResult::Ok || result == hazelnut::DisplayCaptureResult::OkButResized) {
// Check for resize.
if(result == hazelnut::DisplayCaptureResult::OkButResized) {
framebuffer = capture->GetFramebufferInformation();
diff = capture->GetDiffInformation();
firstFrame = true;
client.SendResize({ framebuffer.width, framebuffer.height });
// send empty frame
tiles.clear();
client.SendData(framebuffer.pFramebuffer, framebuffer.width, framebuffer.height, tiles, true);
continue;
}
if(result == hazelnut::DisplayCaptureResult::Ok) {
tiles.clear();
if(firstFrame == false) {
@ -230,10 +216,21 @@ int main(int argc, char** argv) {
}
// send that to the server
client.SendData(framebuffer.pFramebuffer, framebuffer.width, framebuffer.height, tiles, false);
client.SendData(framebuffer.pFramebuffer, framebuffer.width, framebuffer.height, tiles, firstFrame == false);
if(firstFrame)
firstFrame = false;
} else if(result == hazelnut::DisplayCaptureResult::OkButResized) {
// We resized. Notify of that
framebuffer = capture->GetFramebufferInformation();
diff = capture->GetDiffInformation();
firstFrame = true;
client.SendResize({ framebuffer.width, framebuffer.height });
// send empty frame
tiles.clear();
client.SendData(framebuffer.pFramebuffer, framebuffer.width, framebuffer.height, tiles, true);
} else {
printf("Failed to capture\n");
break;

View file

@ -1,4 +1,5 @@
#include "nvfbc_library.hpp"
#include "NvFBC/nvFBCToSys.h"
namespace {
// Get the default NvFBC library path
@ -10,6 +11,8 @@ namespace {
bool IsWow64() {
#ifdef _WIN64
// If we're built for a x64 target, we kinda can't be WOW64.
// Statically enforce this at compile time
return false;
#else
BOOL bIsWow64 = FALSE;
@ -56,10 +59,6 @@ NvFBCLibrary::~NvFBCLibrary() {
close();
}
// Attempts to load NvFBC from system directory.
// on 32-bit OS: looks for NvFBC.dll in system32
// for 32-bit app on 64-bit OS: looks for NvFBC.dll in syswow64
// for 64-bit app on 64-bit OS: looks for NvFBC64.dll in system32
bool NvFBCLibrary::load() {
if(m_handle != nullptr)
return true;
@ -67,23 +66,20 @@ bool NvFBCLibrary::load() {
char szDefaultPath[MAX_PATH] {};
GetNvFBCDefaultPath(&szDefaultPath[0]);
m_handle = ::LoadLibraryA(szDefaultPath);
m_handle = LoadLibraryA(szDefaultPath);
if(NULL == m_handle) {
fprintf(stderr, "Unable to load NvFBC.\n");
if(m_handle == nullptr) {
return false;
}
// Load the three functions exported by NvFBC
pfn_create = (NvFBC_CreateFunctionExType)::GetProcAddress(m_handle, "NvFBC_CreateEx");
pfn_set_global_flags = (NvFBC_SetGlobalFlagsType)::GetProcAddress(m_handle, "NvFBC_SetGlobalFlags");
pfn_get_status = (NvFBC_GetStatusExFunctionType)::GetProcAddress(m_handle, "NvFBC_GetStatusEx");
pfn_enable = (NvFBC_EnableFunctionType)::GetProcAddress(m_handle, "NvFBC_Enable");
// Load NvFBC exports
pfn_create = reinterpret_cast<NvFBC_CreateFunctionExType>(GetProcAddress(m_handle, "NvFBC_CreateEx"));
pfn_set_global_flags = reinterpret_cast<NvFBC_SetGlobalFlagsType>(GetProcAddress(m_handle, "NvFBC_SetGlobalFlags"));
pfn_get_status = reinterpret_cast<NvFBC_GetStatusExFunctionType>(GetProcAddress(m_handle, "NvFBC_GetStatusEx"));
pfn_enable = reinterpret_cast<NvFBC_EnableFunctionType>(GetProcAddress(m_handle, "NvFBC_Enable"));
if((NULL == pfn_create) || (NULL == pfn_set_global_flags) || (NULL == pfn_get_status) || (NULL == pfn_enable)) {
fprintf(stderr, "Unable to load the NvFBC function pointers.\n");
if((pfn_create == nullptr) || (pfn_set_global_flags == nullptr) || (pfn_get_status == nullptr) || (pfn_enable == nullptr)) {
close();
return false;
}
@ -118,30 +114,25 @@ void* NvFBCLibrary::create(DWORD type, DWORD* maxWidth, DWORD* maxHeight, int ad
return NULL;
NVFBCRESULT res = NVFBC_SUCCESS;
NvFBCStatusEx status = { 0 };
NvFBCStatusEx status{};
status.dwVersion = NVFBC_STATUS_VER;
status.dwAdapterIdx = adapter;
res = getStatus(&status);
if(res != NVFBC_SUCCESS) {
fprintf(stderr, "NvFBC not supported on this device + driver.\r\n");
return NULL;
return nullptr;
}
// Check to see if the device and driver are supported
if(!status.bIsCapturePossible) {
fprintf(stderr, "Unsupported device or driver.\r\n");
return NULL;
return nullptr;
}
// Check to see if an instance can be created
if(!status.bCanCreateNow) {
fprintf(stderr, "Unable to create an instance of NvFBC.\r\n");
return NULL;
return nullptr;
}
NvFBCCreateParams createParams;
memset(&createParams, 0, sizeof(createParams));
NvFBCCreateParams createParams{};
createParams.dwVersion = NVFBC_CREATE_PARAMS_VER;
createParams.dwInterfaceType = type;
createParams.pDevice = devicePtr;
@ -155,13 +146,16 @@ void* NvFBCLibrary::create(DWORD type, DWORD* maxWidth, DWORD* maxHeight, int ad
return createParams.pNvFBC;
}
INvFBCToSys_v4* NvFBCLibrary::CreateToSys(DWORD* maxWidth, DWORD* maxHeight, int adapter) {
return static_cast<NvFBCToSys*>(create(NVFBC_TO_SYS, maxWidth, maxHeight, adapter, nullptr));
}
NVFBCRESULT NvFBCLibrary::enable(NVFBC_STATE nvFBCState) {
NVFBCRESULT res = NVFBC_SUCCESS;
return pfn_enable(nvFBCState);
}
void NvFBCLibrary::setTargetAdapter(int adapter) {
char targetAdapter[10] = { 0 };
char targetAdapter[10]{};
_snprintf_s(targetAdapter, 10, 9, "%d", adapter);
SetEnvironmentVariableA("NVFBC_TARGET_ADAPTER", targetAdapter);
}

View file

@ -5,6 +5,8 @@
#include "NvFBC/nvFBC.h"
class INvFBCToSys_v4;
/// Wraps loading and using NvFBC
class NvFBCLibrary {
public:
@ -35,6 +37,8 @@ class NvFBCLibrary {
/// Creates an instance of the provided NvFBC type if possible.
void* create(DWORD type, DWORD* maxWidth, DWORD* maxHeight, int adapter = 0, void* devicePtr = NULL);
INvFBCToSys_v4* CreateToSys(DWORD* maxWidth, DWORD* maxHeight, int adapter = 0);
/// enable/disable NVFBC
NVFBCRESULT enable(NVFBC_STATE nvFBCState);