retappingly
This commit is contained in:
parent
c1bb08c31f
commit
2f2114aca3
3 changed files with 74 additions and 91 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace hazelnut {
|
||||
|
||||
// capture_nvfbc.cpp
|
||||
// capture_nvfbc.cpp
|
||||
IFramebufferCapture* CreateFramebufferCapture_NVFBC();
|
||||
|
||||
DisplayCaptureInterface GuessBestCaptureInterface() {
|
||||
|
@ -14,15 +14,13 @@ namespace hazelnut {
|
|||
IFramebufferCapture* pCapture = nullptr;
|
||||
|
||||
switch(type) {
|
||||
case DisplayCaptureInterface::NVFBC:
|
||||
pCapture = CreateFramebufferCapture_NVFBC();
|
||||
break;
|
||||
|
||||
case DisplayCaptureInterface::NVFBC: pCapture = CreateFramebufferCapture_NVFBC(); break;
|
||||
|
||||
default: return nullptr;
|
||||
}
|
||||
|
||||
// Initalize capture.
|
||||
if (pCapture->Initialize())
|
||||
if(pCapture->Initialize())
|
||||
return nullptr;
|
||||
|
||||
return std::unique_ptr<IFramebufferCapture>(pCapture);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "Utils.hpp"
|
||||
#include <memory>
|
||||
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace hazelnut {
|
||||
|
||||
enum class DisplayCaptureResult {
|
||||
|
@ -17,15 +18,15 @@ namespace hazelnut {
|
|||
};
|
||||
|
||||
// Difference tile information
|
||||
struct DiffInformation {
|
||||
u8* pDiffMap;
|
||||
u32 diffmapWidth;
|
||||
u32 diffMapHeight;
|
||||
};
|
||||
struct DiffInformation {
|
||||
u8* pDiffMap;
|
||||
u32 diffmapWidth;
|
||||
u32 diffMapHeight;
|
||||
};
|
||||
|
||||
/// Interface used for framebuffer capture independence.
|
||||
/// Interface used for framebuffer capture independence.
|
||||
class IFramebufferCapture {
|
||||
public:
|
||||
public:
|
||||
virtual ~IFramebufferCapture() = default;
|
||||
|
||||
virtual bool Initialize() = 0;
|
||||
|
@ -36,26 +37,25 @@ namespace hazelnut {
|
|||
/// Get framebuffer information.
|
||||
virtual FramebufferInformation GetFramebufferInformation() = 0;
|
||||
|
||||
/// Gets the tile difference block information.
|
||||
virtual DiffInformation GetDiffInformation() = 0;
|
||||
/// Gets the tile difference block information.
|
||||
virtual DiffInformation GetDiffInformation() = 0;
|
||||
};
|
||||
|
||||
|
||||
enum class DisplayCaptureInterface : u32 {
|
||||
Invalid,
|
||||
NVFBC, // NVFBC capture
|
||||
// FIXME: DXGI support
|
||||
};
|
||||
enum class DisplayCaptureInterface : u32 {
|
||||
Invalid,
|
||||
NVFBC, // NVFBC capture
|
||||
// FIXME: DXGI support
|
||||
};
|
||||
|
||||
/// Returns a guess for the best capture interface.
|
||||
/// On a NVIDIA GPU on Windows > 8.1, we prefer NVFBC.
|
||||
/// On a NVIDIA GPU on Windows < 8.1, we prefer NVFBC.
|
||||
/// Otherwise, we should prefer DXGI.
|
||||
///
|
||||
/// If no API works Invalid is returned.
|
||||
DisplayCaptureInterface GuessBestCaptureInterface();
|
||||
|
||||
/// Creates a instance of the framebuffer capture interface for a particular interface.
|
||||
/// Returns a null pointer on failure to create.
|
||||
std::unique_ptr<IFramebufferCapture> CreateFramebufferCapture(DisplayCaptureInterface type);
|
||||
|
||||
/// Creates a instance of the framebuffer capture interface for a particular interface.
|
||||
/// Returns a null pointer on failure to create.
|
||||
std::unique_ptr<IFramebufferCapture> CreateFramebufferCapture(DisplayCaptureInterface type);
|
||||
|
||||
} // namespace hazelnut
|
|
@ -15,7 +15,7 @@ namespace hazelnut {
|
|||
NVFBCRESULT nvfbcStatus;
|
||||
NvFBCLibrary nvfbcLib;
|
||||
|
||||
NVFBC_TOSYS_GRAB_FRAME_PARAMS fbcSysGrabParams;
|
||||
NVFBC_TOSYS_GRAB_FRAME_PARAMS fbcSysGrabParams;
|
||||
NvFBCFrameGrabInfo grabInfo;
|
||||
NvFBCToSys* nvfbc;
|
||||
|
||||
|
@ -37,19 +37,19 @@ namespace hazelnut {
|
|||
nvfbcLib.close();
|
||||
}
|
||||
|
||||
bool Initialize() override {
|
||||
if (!nvfbcLib.load()) {
|
||||
bool Initialize() override {
|
||||
if(!nvfbcLib.load()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NvfbcInitSession())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
if(!NvfbcInitSession())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NvfbcDestroyInstance() {
|
||||
if (nvfbc) {
|
||||
if(nvfbc) {
|
||||
nvfbc->NvFBCToSysRelease();
|
||||
nvfbc = nullptr;
|
||||
|
||||
|
@ -66,52 +66,52 @@ namespace hazelnut {
|
|||
|
||||
bool NvfbcCreateInstance() {
|
||||
// Destroy an existing NVFBC session to avoid memory leak
|
||||
if (nvfbc) {
|
||||
if(nvfbc) {
|
||||
NvfbcDestroyInstance();
|
||||
}
|
||||
|
||||
DWORD maxDisplayWidth = -1;
|
||||
DWORD maxDisplayHeight = -1;
|
||||
nvfbc = (NvFBCToSys*)nvfbcLib.create(NVFBC_TO_SYS, &maxDisplayWidth, &maxDisplayHeight);
|
||||
|
||||
if (!nvfbc) {
|
||||
return false;
|
||||
DWORD maxDisplayWidth = -1;
|
||||
DWORD maxDisplayHeight = -1;
|
||||
nvfbc = (NvFBCToSys*)nvfbcLib.create(NVFBC_TO_SYS, &maxDisplayWidth, &maxDisplayHeight);
|
||||
|
||||
if(!nvfbc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NvfbcInitSession() {
|
||||
if (!NvfbcCreateInstance())
|
||||
if(!NvfbcCreateInstance())
|
||||
return false;
|
||||
|
||||
// set up a session
|
||||
NVFBC_TOSYS_SETUP_PARAMS fbcSysSetupParams = { 0 };
|
||||
fbcSysSetupParams.dwVersion = NVFBC_TOSYS_SETUP_PARAMS_VER;
|
||||
fbcSysSetupParams.eMode = NVFBC_TOSYS_ARGB;
|
||||
fbcSysSetupParams.bWithHWCursor = true;
|
||||
fbcSysSetupParams.ppBuffer = (void**)&pRawFramebuffer;
|
||||
|
||||
// enable a 32x32 difference map
|
||||
fbcSysSetupParams.bDiffMap = TRUE;
|
||||
fbcSysSetupParams.ppDiffMap = (void**)&pDiffMap;
|
||||
fbcSysSetupParams.eDiffMapBlockSize = NVFBC_TOSYS_DIFFMAP_BLOCKSIZE_32X32;
|
||||
|
||||
auto status = nvfbc->NvFBCToSysSetUp(&fbcSysSetupParams);
|
||||
// set up a session
|
||||
NVFBC_TOSYS_SETUP_PARAMS fbcSysSetupParams = { 0 };
|
||||
fbcSysSetupParams.dwVersion = NVFBC_TOSYS_SETUP_PARAMS_VER;
|
||||
fbcSysSetupParams.eMode = NVFBC_TOSYS_ARGB;
|
||||
fbcSysSetupParams.bWithHWCursor = true;
|
||||
fbcSysSetupParams.ppBuffer = (void**)&pRawFramebuffer;
|
||||
|
||||
// enable a 32x32 difference map
|
||||
fbcSysSetupParams.bDiffMap = TRUE;
|
||||
fbcSysSetupParams.ppDiffMap = (void**)&pDiffMap;
|
||||
fbcSysSetupParams.eDiffMapBlockSize = NVFBC_TOSYS_DIFFMAP_BLOCKSIZE_32X32;
|
||||
|
||||
auto status = nvfbc->NvFBCToSysSetUp(&fbcSysSetupParams);
|
||||
if(status != NVFBC_SUCCESS)
|
||||
return false;
|
||||
|
||||
memset(&fbcSysGrabParams, 0, sizeof(NVFBC_TOSYS_GRAB_FRAME_PARAMS));
|
||||
|
||||
// set up grab params
|
||||
fbcSysGrabParams.dwVersion = NVFBC_TOSYS_GRAB_FRAME_PARAMS_VER;
|
||||
fbcSysGrabParams.dwFlags = NVFBC_TOSYS_WAIT_WITH_TIMEOUT;
|
||||
fbcSysGrabParams.dwTargetWidth = 0;
|
||||
fbcSysGrabParams.dwTargetHeight = 0;
|
||||
fbcSysGrabParams.dwStartX = 0;
|
||||
fbcSysGrabParams.dwStartY = 0;
|
||||
fbcSysGrabParams.eGMode = NVFBC_TOSYS_SOURCEMODE_FULL;
|
||||
fbcSysGrabParams.pNvFBCFrameGrabInfo = &grabInfo;
|
||||
fbcSysGrabParams.dwVersion = NVFBC_TOSYS_GRAB_FRAME_PARAMS_VER;
|
||||
fbcSysGrabParams.dwFlags = NVFBC_TOSYS_WAIT_WITH_TIMEOUT;
|
||||
fbcSysGrabParams.dwTargetWidth = 0;
|
||||
fbcSysGrabParams.dwTargetHeight = 0;
|
||||
fbcSysGrabParams.dwStartX = 0;
|
||||
fbcSysGrabParams.dwStartY = 0;
|
||||
fbcSysGrabParams.eGMode = NVFBC_TOSYS_SOURCEMODE_FULL;
|
||||
fbcSysGrabParams.pNvFBCFrameGrabInfo = &grabInfo;
|
||||
fbcSysGrabParams.dwWaitTime = 16;
|
||||
return true;
|
||||
}
|
||||
|
@ -119,13 +119,12 @@ namespace hazelnut {
|
|||
DisplayCaptureResult CaptureFrame() override {
|
||||
auto nvStatus = nvfbc->NvFBCToSysGrabFrame(&this->fbcSysGrabParams);
|
||||
|
||||
switch (nvStatus) {
|
||||
case NVFBC_SUCCESS:
|
||||
break;
|
||||
switch(nvStatus) {
|
||||
case NVFBC_SUCCESS: break;
|
||||
|
||||
// Need to recreate the session. If it fails then we fail too.
|
||||
case NVFBC_ERROR_INVALIDATED_SESSION: {
|
||||
if (!NvfbcInitSession())
|
||||
if(!NvfbcInitSession())
|
||||
return DisplayCaptureResult::Fail;
|
||||
|
||||
// Recurse. This looks naughty, but will allow us to directly retry
|
||||
|
@ -133,15 +132,14 @@ namespace hazelnut {
|
|||
return CaptureFrame();
|
||||
} break;
|
||||
|
||||
default:
|
||||
return DisplayCaptureResult::Fail;
|
||||
default: return DisplayCaptureResult::Fail;
|
||||
}
|
||||
|
||||
if (width != grabInfo.dwWidth || height != grabInfo.dwHeight) {
|
||||
if(width != grabInfo.dwWidth || height != grabInfo.dwHeight) {
|
||||
width = grabInfo.dwWidth;
|
||||
height = grabInfo.dwHeight;
|
||||
|
||||
diffmapWidth = (u32)ceil((f32)width / 32);
|
||||
|
||||
diffmapWidth = (u32)ceil((f32)width / 32);
|
||||
diffmapHeight = (u32)ceil((f32)height / 32);
|
||||
|
||||
convertedFramebuffer.resize(width * height);
|
||||
|
@ -151,29 +149,16 @@ namespace hazelnut {
|
|||
|
||||
// Splat to the converted framebuffer. It doesn't have padding on it.
|
||||
auto* pBufferData = convertedFramebuffer.data();
|
||||
for (u32 y = 0; y < grabInfo.dwHeight; ++y) {
|
||||
memcpy(&pBufferData[y * width], &pRawFramebuffer[(y * grabInfo.dwBufferWidth)], grabInfo.dwWidth * 4);
|
||||
for(u32 y = 0; y < grabInfo.dwHeight; ++y) {
|
||||
memcpy(&pBufferData[y * width], &pRawFramebuffer[(y * grabInfo.dwBufferWidth)], grabInfo.dwWidth * 4);
|
||||
}
|
||||
|
||||
return DisplayCaptureResult::Ok;
|
||||
}
|
||||
|
||||
FramebufferInformation GetFramebufferInformation() override {
|
||||
return FramebufferInformation{
|
||||
convertedFramebuffer.data(),
|
||||
width,
|
||||
height
|
||||
};
|
||||
}
|
||||
FramebufferInformation GetFramebufferInformation() override { return FramebufferInformation { convertedFramebuffer.data(), width, height }; }
|
||||
|
||||
DiffInformation GetDiffInformation() override {
|
||||
return DiffInformation{
|
||||
pDiffMap,
|
||||
diffmapWidth,
|
||||
diffmapHeight
|
||||
};
|
||||
}
|
||||
|
||||
DiffInformation GetDiffInformation() override { return DiffInformation { pDiffMap, diffmapWidth, diffmapHeight }; }
|
||||
};
|
||||
|
||||
IFramebufferCapture* CreateFramebufferCapture_NVFBC() {
|
||||
|
|
Loading…
Reference in a new issue