mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-08-09 20:24:14 +00:00
[c-host] renamed finall to just plain host
This commit is contained in:
19
host/platform/Windows/capture/NVFBC/CMakeLists.txt
Normal file
19
host/platform/Windows/capture/NVFBC/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(capture_NVFBC LANGUAGES C CXX)
|
||||
|
||||
add_library(capture_NVFBC STATIC
|
||||
src/nvfbc.c
|
||||
src/wrapper.cpp
|
||||
)
|
||||
|
||||
file(TO_CMAKE_PATH "${NVFBC_SDK}" nvfbc_sdk)
|
||||
include_directories(file, "${nvfbc_sdk}/inc")
|
||||
|
||||
target_include_directories(capture_NVFBC
|
||||
PRIVATE
|
||||
src
|
||||
)
|
||||
|
||||
target_link_libraries(capture_NVFBC
|
||||
platform_Windows
|
||||
)
|
387
host/platform/Windows/capture/NVFBC/src/nvfbc.c
Normal file
387
host/platform/Windows/capture/NVFBC/src/nvfbc.c
Normal file
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "interface/capture.h"
|
||||
#include "interface/platform.h"
|
||||
#include "common/windebug.h"
|
||||
#include "windows/mousehook.h"
|
||||
#include "common/option.h"
|
||||
#include "common/framebuffer.h"
|
||||
#include "common/event.h"
|
||||
#include "common/thread.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <NvFBC/nvFBC.h>
|
||||
#include "wrapper.h"
|
||||
|
||||
struct iface
|
||||
{
|
||||
bool stop;
|
||||
NvFBCHandle nvfbc;
|
||||
|
||||
bool seperateCursor;
|
||||
CaptureGetPointerBuffer getPointerBufferFn;
|
||||
CapturePostPointerBuffer postPointerBufferFn;
|
||||
LGThread * pointerThread;
|
||||
|
||||
unsigned int maxWidth, maxHeight;
|
||||
unsigned int width , height;
|
||||
|
||||
uint8_t * frameBuffer;
|
||||
uint8_t * diffMap;
|
||||
|
||||
NvFBCFrameGrabInfo grabInfo;
|
||||
|
||||
LGEvent * frameEvent;
|
||||
LGEvent * cursorEvents[2];
|
||||
|
||||
int mouseX, mouseY, mouseHotX, mouseHotY;
|
||||
bool mouseVisible;
|
||||
};
|
||||
|
||||
static struct iface * this = NULL;
|
||||
|
||||
static void nvfbc_free();
|
||||
static int pointerThread(void * unused);
|
||||
|
||||
static void getDesktopSize(unsigned int * width, unsigned int * height)
|
||||
{
|
||||
HMONITOR monitor = MonitorFromWindow(GetDesktopWindow(), MONITOR_DEFAULTTOPRIMARY);
|
||||
MONITORINFO monitorInfo = {
|
||||
.cbSize = sizeof(MONITORINFO)
|
||||
};
|
||||
|
||||
GetMonitorInfo(monitor, &monitorInfo);
|
||||
CloseHandle(monitor);
|
||||
|
||||
*width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
|
||||
*height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
|
||||
}
|
||||
|
||||
static void on_mouseMove(int x, int y)
|
||||
{
|
||||
this->mouseX = x;
|
||||
this->mouseY = y;
|
||||
lgSignalEvent(this->cursorEvents[0]);
|
||||
}
|
||||
|
||||
static const char * nvfbc_getName()
|
||||
{
|
||||
return "NVFBC (NVidia Frame Buffer Capture)";
|
||||
};
|
||||
|
||||
static void nvfbc_initOptions()
|
||||
{
|
||||
struct Option options[] =
|
||||
{
|
||||
{
|
||||
.module = "nvfbc",
|
||||
.name = "decoupleCursor",
|
||||
.description = "Capture the cursor seperately",
|
||||
.type = OPTION_TYPE_BOOL,
|
||||
.value.x_bool = true
|
||||
},
|
||||
{0}
|
||||
};
|
||||
|
||||
option_register(options);
|
||||
}
|
||||
|
||||
static bool nvfbc_create(
|
||||
CaptureGetPointerBuffer getPointerBufferFn,
|
||||
CapturePostPointerBuffer postPointerBufferFn)
|
||||
{
|
||||
if (!NvFBCInit())
|
||||
return false;
|
||||
|
||||
int bufferLen = GetEnvironmentVariable("NVFBC_PRIV_DATA", NULL, 0);
|
||||
uint8_t * privData = NULL;
|
||||
int privDataLen = 0;
|
||||
|
||||
if(bufferLen)
|
||||
{
|
||||
char * buffer = malloc(bufferLen);
|
||||
GetEnvironmentVariable("NVFBC_PRIV_DATA", buffer, bufferLen);
|
||||
|
||||
privDataLen = (bufferLen - 1) / 2;
|
||||
privData = (uint8_t *)malloc(privDataLen);
|
||||
char hex[3] = {0};
|
||||
for(int i = 0; i < privDataLen; ++i)
|
||||
{
|
||||
memcpy(hex, &buffer[i*2], 2);
|
||||
privData[i] = (uint8_t)strtoul(hex, NULL, 16);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
this = (struct iface *)calloc(sizeof(struct iface), 1);
|
||||
if (!NvFBCToSysCreate(privData, privDataLen, &this->nvfbc, &this->maxWidth, &this->maxHeight))
|
||||
{
|
||||
free(privData);
|
||||
nvfbc_free();
|
||||
return false;
|
||||
}
|
||||
free(privData);
|
||||
|
||||
this->frameEvent = lgCreateEvent(true, 17);
|
||||
if (!this->frameEvent)
|
||||
{
|
||||
DEBUG_ERROR("failed to create the frame event");
|
||||
nvfbc_free();
|
||||
return false;
|
||||
}
|
||||
|
||||
this->seperateCursor = option_get_bool("nvfbc", "decoupleCursor");
|
||||
this->getPointerBufferFn = getPointerBufferFn;
|
||||
this->postPointerBufferFn = postPointerBufferFn;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool nvfbc_init()
|
||||
{
|
||||
this->stop = false;
|
||||
getDesktopSize(&this->width, &this->height);
|
||||
lgResetEvent(this->frameEvent);
|
||||
|
||||
HANDLE event;
|
||||
if (!NvFBCToSysSetup(
|
||||
this->nvfbc,
|
||||
BUFFER_FMT_ARGB,
|
||||
!this->seperateCursor,
|
||||
this->seperateCursor,
|
||||
true,
|
||||
DIFFMAP_BLOCKSIZE_128X128,
|
||||
(void **)&this->frameBuffer,
|
||||
(void **)&this->diffMap,
|
||||
&event
|
||||
))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this->cursorEvents[0] = lgCreateEvent(true, 10);
|
||||
mouseHook_install(on_mouseMove);
|
||||
|
||||
if (this->seperateCursor)
|
||||
this->cursorEvents[1] = lgWrapEvent(event);
|
||||
|
||||
DEBUG_INFO("Cursor mode : %s", this->seperateCursor ? "decoupled" : "integrated");
|
||||
|
||||
Sleep(100);
|
||||
|
||||
if (!lgCreateThread("NvFBCPointer", pointerThread, NULL, &this->pointerThread))
|
||||
{
|
||||
DEBUG_ERROR("Failed to create the NvFBCPointer thread");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nvfbc_stop()
|
||||
{
|
||||
this->stop = true;
|
||||
lgSignalEvent(this->cursorEvents[0]);
|
||||
lgSignalEvent(this->frameEvent);
|
||||
|
||||
if (this->pointerThread)
|
||||
{
|
||||
lgJoinThread(this->pointerThread, NULL);
|
||||
this->pointerThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool nvfbc_deinit()
|
||||
{
|
||||
mouseHook_remove();
|
||||
|
||||
if (this->cursorEvents[0])
|
||||
{
|
||||
lgFreeEvent(this->cursorEvents[0]);
|
||||
this->cursorEvents[0] = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nvfbc_free()
|
||||
{
|
||||
NvFBCToSysRelease(&this->nvfbc);
|
||||
|
||||
if (this->frameEvent)
|
||||
lgFreeEvent(this->frameEvent);
|
||||
|
||||
free(this);
|
||||
this = NULL;
|
||||
NvFBCFree();
|
||||
}
|
||||
|
||||
static unsigned int nvfbc_getMaxFrameSize()
|
||||
{
|
||||
return this->maxWidth * this->maxHeight * 4;
|
||||
}
|
||||
|
||||
static CaptureResult nvfbc_capture()
|
||||
{
|
||||
getDesktopSize(&this->width, &this->height);
|
||||
NvFBCFrameGrabInfo grabInfo;
|
||||
CaptureResult result = NvFBCToSysCapture(
|
||||
this->nvfbc,
|
||||
1000,
|
||||
0, 0,
|
||||
this->width,
|
||||
this->height,
|
||||
&grabInfo
|
||||
);
|
||||
|
||||
if (result != CAPTURE_RESULT_OK)
|
||||
return result;
|
||||
|
||||
bool changed = false;
|
||||
const unsigned int h = (this->height + 127) / 128;
|
||||
const unsigned int w = (this->width + 127) / 128;
|
||||
for(unsigned int y = 0; y < h; ++y)
|
||||
for(unsigned int x = 0; x < w; ++x)
|
||||
if (this->diffMap[(y*w)+x])
|
||||
{
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!changed)
|
||||
return CAPTURE_RESULT_TIMEOUT;
|
||||
|
||||
memcpy(&this->grabInfo, &grabInfo, sizeof(grabInfo));
|
||||
lgSignalEvent(this->frameEvent);
|
||||
return CAPTURE_RESULT_OK;
|
||||
}
|
||||
|
||||
static CaptureResult nvfbc_waitFrame(CaptureFrame * frame)
|
||||
{
|
||||
if (!lgWaitEvent(this->frameEvent, 1000))
|
||||
return CAPTURE_RESULT_TIMEOUT;
|
||||
|
||||
if (this->stop)
|
||||
return CAPTURE_RESULT_REINIT;
|
||||
|
||||
frame->width = this->grabInfo.dwWidth;
|
||||
frame->height = this->grabInfo.dwHeight;
|
||||
frame->pitch = this->grabInfo.dwBufferWidth * 4;
|
||||
frame->stride = this->grabInfo.dwBufferWidth;
|
||||
|
||||
#if 0
|
||||
//NvFBC never sets bIsHDR so instead we check for any data in the alpha channel
|
||||
//If there is data, it's HDR. This is clearly suboptimal
|
||||
if (!this->grabInfo.bIsHDR)
|
||||
for(int y = 0; y < frame->height; ++y)
|
||||
for(int x = 0; x < frame->width; ++x)
|
||||
{
|
||||
int offset = (y * frame->pitch) + (x * 4);
|
||||
if (this->frameBuffer[offset + 3])
|
||||
{
|
||||
this->grabInfo.bIsHDR = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
frame->format = this->grabInfo.bIsHDR ? CAPTURE_FMT_RGBA10 : CAPTURE_FMT_BGRA;
|
||||
return CAPTURE_RESULT_OK;
|
||||
}
|
||||
|
||||
static CaptureResult nvfbc_getFrame(FrameBuffer * frame)
|
||||
{
|
||||
framebuffer_write(
|
||||
frame,
|
||||
this->frameBuffer,
|
||||
this->grabInfo.dwHeight * this->grabInfo.dwBufferWidth * 4
|
||||
);
|
||||
return CAPTURE_RESULT_OK;
|
||||
}
|
||||
|
||||
static int pointerThread(void * unused)
|
||||
{
|
||||
while(!this->stop)
|
||||
{
|
||||
LGEvent * events[2];
|
||||
memcpy(&events, &this->cursorEvents, sizeof(LGEvent *) * 2);
|
||||
if (!lgWaitEvents(events, this->seperateCursor ? 2 : 1, false, 1000))
|
||||
continue;
|
||||
|
||||
if (this->stop)
|
||||
break;
|
||||
|
||||
CaptureResult result;
|
||||
CapturePointer pointer = { 0 };
|
||||
|
||||
if (this->seperateCursor && events[1])
|
||||
{
|
||||
void * data;
|
||||
uint32_t size;
|
||||
if (!this->getPointerBufferFn(&data, &size))
|
||||
{
|
||||
DEBUG_WARN("failed to get a pointer buffer");
|
||||
continue;
|
||||
}
|
||||
|
||||
result = NvFBCToSysGetCursor(this->nvfbc, &pointer, data, size);
|
||||
if (result != CAPTURE_RESULT_OK)
|
||||
{
|
||||
DEBUG_WARN("NvFBCToSysGetCursor failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
this->mouseVisible = pointer.visible;
|
||||
this->mouseHotX = pointer.x;
|
||||
this->mouseHotY = pointer.y;
|
||||
}
|
||||
|
||||
if (events[0])
|
||||
{
|
||||
pointer.positionUpdate = true;
|
||||
pointer.visible = this->mouseVisible;
|
||||
pointer.x = this->mouseX - this->mouseHotX;
|
||||
pointer.y = this->mouseY - this->mouseHotY;
|
||||
}
|
||||
|
||||
this->postPointerBufferFn(pointer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct CaptureInterface Capture_NVFBC =
|
||||
{
|
||||
.getName = nvfbc_getName,
|
||||
.initOptions = nvfbc_initOptions,
|
||||
|
||||
.create = nvfbc_create,
|
||||
.init = nvfbc_init,
|
||||
.stop = nvfbc_stop,
|
||||
.deinit = nvfbc_deinit,
|
||||
.free = nvfbc_free,
|
||||
.getMaxFrameSize = nvfbc_getMaxFrameSize,
|
||||
.capture = nvfbc_capture,
|
||||
.waitFrame = nvfbc_waitFrame,
|
||||
.getFrame = nvfbc_getFrame
|
||||
};
|
330
host/platform/Windows/capture/NVFBC/src/wrapper.cpp
Normal file
330
host/platform/Windows/capture/NVFBC/src/wrapper.cpp
Normal file
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "wrapper.h"
|
||||
#include "common/windebug.h"
|
||||
#include <windows.h>
|
||||
#include <NvFBC/nvFBCToSys.h>
|
||||
|
||||
#ifdef _WIN64
|
||||
#define NVFBC_DLL "NvFBC64.dll"
|
||||
#else
|
||||
#define NVFBC_DLL "NvFBC.dll"
|
||||
#endif
|
||||
|
||||
struct NVAPI
|
||||
{
|
||||
bool initialized;
|
||||
HMODULE dll;
|
||||
|
||||
NvFBC_CreateFunctionExType createEx;
|
||||
NvFBC_SetGlobalFlagsType setGlobalFlags;
|
||||
NvFBC_GetStatusExFunctionType getStatusEx;
|
||||
NvFBC_EnableFunctionType enable;
|
||||
NvFBC_GetSDKVersionFunctionType getVersion;
|
||||
};
|
||||
|
||||
struct stNvFBCHandle
|
||||
{
|
||||
NvFBCToSys * nvfbc;
|
||||
HANDLE cursorEvent;
|
||||
int retry;
|
||||
};
|
||||
|
||||
static NVAPI nvapi;
|
||||
|
||||
bool NvFBCInit()
|
||||
{
|
||||
if (nvapi.initialized)
|
||||
return true;
|
||||
|
||||
nvapi.dll = LoadLibraryA(NVFBC_DLL);
|
||||
if (!nvapi.dll)
|
||||
{
|
||||
DEBUG_WINERROR("Failed to load " NVFBC_DLL, GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
nvapi.createEx = (NvFBC_CreateFunctionExType )GetProcAddress(nvapi.dll, "NvFBC_CreateEx" );
|
||||
nvapi.setGlobalFlags = (NvFBC_SetGlobalFlagsType )GetProcAddress(nvapi.dll, "NvFBC_SetGlobalFlags");
|
||||
nvapi.getStatusEx = (NvFBC_GetStatusExFunctionType )GetProcAddress(nvapi.dll, "NvFBC_GetStatusEx" );
|
||||
nvapi.enable = (NvFBC_EnableFunctionType )GetProcAddress(nvapi.dll, "NvFBC_Enable" );
|
||||
nvapi.getVersion = (NvFBC_GetSDKVersionFunctionType)GetProcAddress(nvapi.dll, "NvFBC_GetSDKVersion" );
|
||||
|
||||
if (
|
||||
!nvapi.createEx ||
|
||||
!nvapi.setGlobalFlags ||
|
||||
!nvapi.getStatusEx ||
|
||||
!nvapi.enable ||
|
||||
!nvapi.getVersion)
|
||||
{
|
||||
DEBUG_ERROR("Failed to get the required proc addresses");
|
||||
return false;
|
||||
}
|
||||
|
||||
NvU32 version;
|
||||
if (nvapi.getVersion(&version) != NVFBC_SUCCESS)
|
||||
{
|
||||
DEBUG_ERROR("Failed to get the NvFBC SDK version");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_INFO("NvFBC SDK Version: %lu", version);
|
||||
|
||||
if (nvapi.enable(NVFBC_STATE_ENABLE) != NVFBC_SUCCESS)
|
||||
{
|
||||
DEBUG_ERROR("Failed to enable the NvFBC interface");
|
||||
return false;
|
||||
}
|
||||
|
||||
nvapi.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void NvFBCFree()
|
||||
{
|
||||
if (!nvapi.initialized)
|
||||
return;
|
||||
|
||||
FreeLibrary(nvapi.dll);
|
||||
nvapi.initialized = false;
|
||||
}
|
||||
|
||||
bool NvFBCToSysCreate(
|
||||
void * privData,
|
||||
unsigned int privDataSize,
|
||||
NvFBCHandle * handle,
|
||||
unsigned int * maxWidth,
|
||||
unsigned int * maxHeight
|
||||
)
|
||||
{
|
||||
NvFBCCreateParams params = {0};
|
||||
|
||||
params.dwVersion = NVFBC_CREATE_PARAMS_VER;
|
||||
params.dwInterfaceType = NVFBC_TO_SYS;
|
||||
params.pDevice = NULL;
|
||||
params.dwAdapterIdx = 0;
|
||||
params.dwPrivateDataSize = privDataSize;
|
||||
params.pPrivateData = privData;
|
||||
|
||||
if (nvapi.createEx(¶ms) != NVFBC_SUCCESS)
|
||||
{
|
||||
*handle = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
*handle = (NvFBCHandle)calloc(sizeof(struct stNvFBCHandle), 1);
|
||||
(*handle)->nvfbc = static_cast<NvFBCToSys *>(params.pNvFBC);
|
||||
|
||||
if (maxWidth)
|
||||
*maxWidth = params.dwMaxDisplayWidth;
|
||||
|
||||
if (maxHeight)
|
||||
*maxHeight = params.dwMaxDisplayHeight;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NvFBCToSysRelease(NvFBCHandle * handle)
|
||||
{
|
||||
if (!*handle)
|
||||
return;
|
||||
|
||||
(*handle)->nvfbc->NvFBCToSysRelease();
|
||||
free(*handle);
|
||||
*handle = NULL;
|
||||
}
|
||||
|
||||
bool NvFBCToSysSetup(
|
||||
NvFBCHandle handle,
|
||||
enum BufferFormat format,
|
||||
bool hwCursor,
|
||||
bool seperateCursorCapture,
|
||||
bool useDiffMap,
|
||||
enum DiffMapBlockSize diffMapBlockSize,
|
||||
void ** frameBuffer,
|
||||
void ** diffMap,
|
||||
HANDLE * cursorEvent
|
||||
)
|
||||
{
|
||||
NVFBC_TOSYS_SETUP_PARAMS params = {0};
|
||||
params.dwVersion = NVFBC_TOSYS_SETUP_PARAMS_VER;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case BUFFER_FMT_ARGB : params.eMode = NVFBC_TOSYS_ARGB ; break;
|
||||
case BUFFER_FMT_RGB : params.eMode = NVFBC_TOSYS_RGB ; break;
|
||||
case BUFFER_FMT_YYYYUV420p: params.eMode = NVFBC_TOSYS_YYYYUV420p; break;
|
||||
case BUFFER_FMT_RGB_PLANAR: params.eMode = NVFBC_TOSYS_RGB_PLANAR; break;
|
||||
case BUFFER_FMT_XOR : params.eMode = NVFBC_TOSYS_XOR ; break;
|
||||
case BUFFER_FMT_YUV444p : params.eMode = NVFBC_TOSYS_YUV444p ; break;
|
||||
case BUFFER_FMT_ARGB10 :
|
||||
params.eMode = NVFBC_TOSYS_ARGB10;
|
||||
params.bHDRRequest = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_INFO("Invalid format");
|
||||
return false;
|
||||
}
|
||||
|
||||
params.bWithHWCursor = hwCursor ? TRUE : FALSE;
|
||||
params.bEnableSeparateCursorCapture = seperateCursorCapture ? TRUE : FALSE;
|
||||
params.bDiffMap = useDiffMap ? TRUE : FALSE;
|
||||
|
||||
switch(diffMapBlockSize)
|
||||
{
|
||||
case DIFFMAP_BLOCKSIZE_128X128: params.eDiffMapBlockSize = NVFBC_TOSYS_DIFFMAP_BLOCKSIZE_128X128; break;
|
||||
case DIFFMAP_BLOCKSIZE_16X16 : params.eDiffMapBlockSize = NVFBC_TOSYS_DIFFMAP_BLOCKSIZE_16X16 ; break;
|
||||
case DIFFMAP_BLOCKSIZE_32X32 : params.eDiffMapBlockSize = NVFBC_TOSYS_DIFFMAP_BLOCKSIZE_32X32 ; break;
|
||||
case DIFFMAP_BLOCKSIZE_64X64 : params.eDiffMapBlockSize = NVFBC_TOSYS_DIFFMAP_BLOCKSIZE_64X64 ; break;
|
||||
|
||||
default:
|
||||
DEBUG_ERROR("Invalid diffMapBlockSize");
|
||||
return false;
|
||||
}
|
||||
|
||||
params.ppBuffer = frameBuffer;
|
||||
params.ppDiffMap = diffMap;
|
||||
|
||||
NVFBCRESULT status = handle->nvfbc->NvFBCToSysSetUp(¶ms);
|
||||
if (status != NVFBC_SUCCESS)
|
||||
{
|
||||
DEBUG_ERROR("Failed to setup NVFBCToSys");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cursorEvent)
|
||||
*cursorEvent = params.hCursorCaptureEvent;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CaptureResult NvFBCToSysCapture(
|
||||
NvFBCHandle handle,
|
||||
const unsigned int waitTime,
|
||||
const unsigned int x,
|
||||
const unsigned int y,
|
||||
const unsigned int width,
|
||||
const unsigned int height,
|
||||
NvFBCFrameGrabInfo * grabInfo
|
||||
)
|
||||
{
|
||||
NVFBC_TOSYS_GRAB_FRAME_PARAMS params = {0};
|
||||
|
||||
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.dwStartX = x;
|
||||
params.dwStartY = y;
|
||||
params.dwTargetWidth = width;
|
||||
params.dwTargetHeight = height;
|
||||
params.pNvFBCFrameGrabInfo = grabInfo;
|
||||
|
||||
grabInfo->bMustRecreate = FALSE;
|
||||
NVFBCRESULT status = handle->nvfbc->NvFBCToSysGrabFrame(¶ms);
|
||||
if (grabInfo->bMustRecreate)
|
||||
{
|
||||
DEBUG_INFO("NvFBC reported recreation is required");
|
||||
return CAPTURE_RESULT_REINIT;
|
||||
}
|
||||
|
||||
switch(status)
|
||||
{
|
||||
case NVFBC_SUCCESS:
|
||||
handle->retry = 0;
|
||||
break;
|
||||
|
||||
case NVFBC_ERROR_INVALID_PARAM:
|
||||
if (handle->retry < 2)
|
||||
{
|
||||
Sleep(100);
|
||||
++handle->retry;
|
||||
return CAPTURE_RESULT_TIMEOUT;
|
||||
}
|
||||
return CAPTURE_RESULT_ERROR;
|
||||
|
||||
case NVFBC_ERROR_DYNAMIC_DISABLE:
|
||||
DEBUG_ERROR("NvFBC was disabled by someone else");
|
||||
return CAPTURE_RESULT_ERROR;
|
||||
|
||||
case NVFBC_ERROR_INVALIDATED_SESSION:
|
||||
DEBUG_WARN("Session was invalidated, attempting to restart");
|
||||
return CAPTURE_RESULT_REINIT;
|
||||
|
||||
default:
|
||||
DEBUG_ERROR("Unknown NVFBCRESULT failure 0x%x", status);
|
||||
return CAPTURE_RESULT_ERROR;
|
||||
}
|
||||
|
||||
return CAPTURE_RESULT_OK;
|
||||
}
|
||||
|
||||
CaptureResult NvFBCToSysGetCursor(NvFBCHandle handle, CapturePointer * pointer, void * buffer, unsigned int size)
|
||||
{
|
||||
NVFBC_CURSOR_CAPTURE_PARAMS params;
|
||||
params.dwVersion = NVFBC_CURSOR_CAPTURE_PARAMS_VER;
|
||||
|
||||
if (handle->nvfbc->NvFBCToSysCursorCapture(¶ms) != NVFBC_SUCCESS)
|
||||
{
|
||||
DEBUG_ERROR("Failed to get the cursor");
|
||||
return CAPTURE_RESULT_ERROR;
|
||||
}
|
||||
|
||||
pointer->x = params.dwXHotSpot;
|
||||
pointer->y = params.dwYHotSpot;
|
||||
pointer->width = params.dwWidth;
|
||||
pointer->height = params.dwHeight;
|
||||
pointer->pitch = params.dwPitch;
|
||||
pointer->visible = params.bIsHwCursor;
|
||||
pointer->shapeUpdate = params.bIsHwCursor;
|
||||
|
||||
if (!params.bIsHwCursor)
|
||||
return CAPTURE_RESULT_OK;
|
||||
|
||||
switch(params.dwPointerFlags & 0x7)
|
||||
{
|
||||
case 0x1:
|
||||
pointer->format = CAPTURE_FMT_MONO;
|
||||
pointer->height *= 2;
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
pointer->format = CAPTURE_FMT_COLOR;
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
pointer->format = CAPTURE_FMT_MASKED;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_ERROR("Invalid/unknown pointer data format");
|
||||
return CAPTURE_RESULT_ERROR;
|
||||
}
|
||||
|
||||
if (params.dwBufferSize > size)
|
||||
{
|
||||
DEBUG_WARN("Cursor data larger then provided buffer");
|
||||
params.dwBufferSize = size;
|
||||
}
|
||||
|
||||
memcpy(buffer, params.pBits, params.dwBufferSize);
|
||||
return CAPTURE_RESULT_OK;
|
||||
}
|
88
host/platform/Windows/capture/NVFBC/src/wrapper.h
Normal file
88
host/platform/Windows/capture/NVFBC/src/wrapper.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <NvFBC/nvFBC.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "interface/capture.h"
|
||||
|
||||
typedef struct stNvFBCHandle * NvFBCHandle;
|
||||
|
||||
enum BufferFormat
|
||||
{
|
||||
BUFFER_FMT_ARGB,
|
||||
BUFFER_FMT_RGB,
|
||||
BUFFER_FMT_YYYYUV420p,
|
||||
BUFFER_FMT_RGB_PLANAR,
|
||||
BUFFER_FMT_XOR,
|
||||
BUFFER_FMT_YUV444p,
|
||||
BUFFER_FMT_ARGB10
|
||||
};
|
||||
|
||||
enum DiffMapBlockSize
|
||||
{
|
||||
DIFFMAP_BLOCKSIZE_128X128 = 0,
|
||||
DIFFMAP_BLOCKSIZE_16X16,
|
||||
DIFFMAP_BLOCKSIZE_32X32,
|
||||
DIFFMAP_BLOCKSIZE_64X64
|
||||
};
|
||||
|
||||
bool NvFBCInit();
|
||||
void NvFBCFree();
|
||||
|
||||
bool NvFBCToSysCreate(
|
||||
void * privData,
|
||||
unsigned int privDataSize,
|
||||
NvFBCHandle * handle,
|
||||
unsigned int * maxWidth,
|
||||
unsigned int * maxHeight
|
||||
);
|
||||
void NvFBCToSysRelease(NvFBCHandle * handle);
|
||||
|
||||
bool NvFBCToSysSetup(
|
||||
NvFBCHandle handle,
|
||||
enum BufferFormat format,
|
||||
bool hwCursor,
|
||||
bool seperateCursorCapture,
|
||||
bool useDiffMap,
|
||||
enum DiffMapBlockSize diffMapBlockSize,
|
||||
void ** frameBuffer,
|
||||
void ** diffMap,
|
||||
HANDLE * cursorEvent
|
||||
);
|
||||
|
||||
CaptureResult NvFBCToSysCapture(
|
||||
NvFBCHandle handle,
|
||||
const unsigned int waitTime,
|
||||
const unsigned int x,
|
||||
const unsigned int y,
|
||||
const unsigned int width,
|
||||
const unsigned int height,
|
||||
NvFBCFrameGrabInfo * grabInfo
|
||||
);
|
||||
|
||||
CaptureResult NvFBCToSysGetCursor(NvFBCHandle handle, CapturePointer * pointer, void * buffer, unsigned int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user