mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +00:00
[host] removed old host application from the project, see c-host
This commit is contained in:
parent
7d26027752
commit
373d4ac932
308
host/.gitignore
vendored
308
host/.gitignore
vendored
@ -1,308 +0,0 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# compiled shader headers
|
||||
Shaders/*.h
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
**/Properties/launchSettings.json
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
@ -1,829 +0,0 @@
|
||||
/*
|
||||
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 "Capture/DXGI.h"
|
||||
using namespace Capture;
|
||||
|
||||
#include "WinDebug.h"
|
||||
#include "common/memcpySSE.h"
|
||||
|
||||
static const char * DXGI_FORMAT_STR[] = {
|
||||
"DXGI_FORMAT_UNKNOWN",
|
||||
"DXGI_FORMAT_R32G32B32A32_TYPELESS",
|
||||
"DXGI_FORMAT_R32G32B32A32_FLOAT",
|
||||
"DXGI_FORMAT_R32G32B32A32_UINT",
|
||||
"DXGI_FORMAT_R32G32B32A32_SINT",
|
||||
"DXGI_FORMAT_R32G32B32_TYPELESS",
|
||||
"DXGI_FORMAT_R32G32B32_FLOAT",
|
||||
"DXGI_FORMAT_R32G32B32_UINT",
|
||||
"DXGI_FORMAT_R32G32B32_SINT",
|
||||
"DXGI_FORMAT_R16G16B16A16_TYPELESS",
|
||||
"DXGI_FORMAT_R16G16B16A16_FLOAT",
|
||||
"DXGI_FORMAT_R16G16B16A16_UNORM",
|
||||
"DXGI_FORMAT_R16G16B16A16_UINT",
|
||||
"DXGI_FORMAT_R16G16B16A16_SNORM",
|
||||
"DXGI_FORMAT_R16G16B16A16_SINT",
|
||||
"DXGI_FORMAT_R32G32_TYPELESS",
|
||||
"DXGI_FORMAT_R32G32_FLOAT",
|
||||
"DXGI_FORMAT_R32G32_UINT",
|
||||
"DXGI_FORMAT_R32G32_SINT",
|
||||
"DXGI_FORMAT_R32G8X24_TYPELESS",
|
||||
"DXGI_FORMAT_D32_FLOAT_S8X24_UINT",
|
||||
"DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",
|
||||
"DXGI_FORMAT_X32_TYPELESS_G8X24_UINT",
|
||||
"DXGI_FORMAT_R10G10B10A2_TYPELESS",
|
||||
"DXGI_FORMAT_R10G10B10A2_UNORM",
|
||||
"DXGI_FORMAT_R10G10B10A2_UINT",
|
||||
"DXGI_FORMAT_R11G11B10_FLOAT",
|
||||
"DXGI_FORMAT_R8G8B8A8_TYPELESS",
|
||||
"DXGI_FORMAT_R8G8B8A8_UNORM",
|
||||
"DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
|
||||
"DXGI_FORMAT_R8G8B8A8_UINT",
|
||||
"DXGI_FORMAT_R8G8B8A8_SNORM",
|
||||
"DXGI_FORMAT_R8G8B8A8_SINT",
|
||||
"DXGI_FORMAT_R16G16_TYPELESS",
|
||||
"DXGI_FORMAT_R16G16_FLOAT",
|
||||
"DXGI_FORMAT_R16G16_UNORM",
|
||||
"DXGI_FORMAT_R16G16_UINT",
|
||||
"DXGI_FORMAT_R16G16_SNORM",
|
||||
"DXGI_FORMAT_R16G16_SINT",
|
||||
"DXGI_FORMAT_R32_TYPELESS",
|
||||
"DXGI_FORMAT_D32_FLOAT",
|
||||
"DXGI_FORMAT_R32_FLOAT",
|
||||
"DXGI_FORMAT_R32_UINT",
|
||||
"DXGI_FORMAT_R32_SINT",
|
||||
"DXGI_FORMAT_R24G8_TYPELESS",
|
||||
"DXGI_FORMAT_D24_UNORM_S8_UINT",
|
||||
"DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
|
||||
"DXGI_FORMAT_X24_TYPELESS_G8_UINT",
|
||||
"DXGI_FORMAT_R8G8_TYPELESS",
|
||||
"DXGI_FORMAT_R8G8_UNORM",
|
||||
"DXGI_FORMAT_R8G8_UINT",
|
||||
"DXGI_FORMAT_R8G8_SNORM",
|
||||
"DXGI_FORMAT_R8G8_SINT",
|
||||
"DXGI_FORMAT_R16_TYPELESS",
|
||||
"DXGI_FORMAT_R16_FLOAT",
|
||||
"DXGI_FORMAT_D16_UNORM",
|
||||
"DXGI_FORMAT_R16_UNORM",
|
||||
"DXGI_FORMAT_R16_UINT",
|
||||
"DXGI_FORMAT_R16_SNORM",
|
||||
"DXGI_FORMAT_R16_SINT",
|
||||
"DXGI_FORMAT_R8_TYPELESS",
|
||||
"DXGI_FORMAT_R8_UNORM",
|
||||
"DXGI_FORMAT_R8_UINT",
|
||||
"DXGI_FORMAT_R8_SNORM",
|
||||
"DXGI_FORMAT_R8_SINT",
|
||||
"DXGI_FORMAT_A8_UNORM",
|
||||
"DXGI_FORMAT_R1_UNORM",
|
||||
"DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
|
||||
"DXGI_FORMAT_R8G8_B8G8_UNORM",
|
||||
"DXGI_FORMAT_G8R8_G8B8_UNORM",
|
||||
"DXGI_FORMAT_BC1_TYPELESS",
|
||||
"DXGI_FORMAT_BC1_UNORM",
|
||||
"DXGI_FORMAT_BC1_UNORM_SRGB",
|
||||
"DXGI_FORMAT_BC2_TYPELESS",
|
||||
"DXGI_FORMAT_BC2_UNORM",
|
||||
"DXGI_FORMAT_BC2_UNORM_SRGB",
|
||||
"DXGI_FORMAT_BC3_TYPELESS",
|
||||
"DXGI_FORMAT_BC3_UNORM",
|
||||
"DXGI_FORMAT_BC3_UNORM_SRGB",
|
||||
"DXGI_FORMAT_BC4_TYPELESS",
|
||||
"DXGI_FORMAT_BC4_UNORM",
|
||||
"DXGI_FORMAT_BC4_SNORM",
|
||||
"DXGI_FORMAT_BC5_TYPELESS",
|
||||
"DXGI_FORMAT_BC5_UNORM",
|
||||
"DXGI_FORMAT_BC5_SNORM",
|
||||
"DXGI_FORMAT_B5G6R5_UNORM",
|
||||
"DXGI_FORMAT_B5G5R5A1_UNORM",
|
||||
"DXGI_FORMAT_B8G8R8A8_UNORM",
|
||||
"DXGI_FORMAT_B8G8R8X8_UNORM",
|
||||
"DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM",
|
||||
"DXGI_FORMAT_B8G8R8A8_TYPELESS",
|
||||
"DXGI_FORMAT_B8G8R8A8_UNORM_SRGB",
|
||||
"DXGI_FORMAT_B8G8R8X8_TYPELESS",
|
||||
"DXGI_FORMAT_B8G8R8X8_UNORM_SRGB",
|
||||
"DXGI_FORMAT_BC6H_TYPELESS",
|
||||
"DXGI_FORMAT_BC6H_UF16",
|
||||
"DXGI_FORMAT_BC6H_SF16",
|
||||
"DXGI_FORMAT_BC7_TYPELESS",
|
||||
"DXGI_FORMAT_BC7_UNORM",
|
||||
"DXGI_FORMAT_BC7_UNORM_SRGB",
|
||||
"DXGI_FORMAT_AYUV",
|
||||
"DXGI_FORMAT_Y410",
|
||||
"DXGI_FORMAT_Y416",
|
||||
"DXGI_FORMAT_NV12",
|
||||
"DXGI_FORMAT_P010",
|
||||
"DXGI_FORMAT_P016",
|
||||
"DXGI_FORMAT_420_OPAQUE",
|
||||
"DXGI_FORMAT_YUY2",
|
||||
"DXGI_FORMAT_Y210",
|
||||
"DXGI_FORMAT_Y216",
|
||||
"DXGI_FORMAT_NV11",
|
||||
"DXGI_FORMAT_AI44",
|
||||
"DXGI_FORMAT_IA44",
|
||||
"DXGI_FORMAT_P8",
|
||||
"DXGI_FORMAT_A8P8",
|
||||
"DXGI_FORMAT_B4G4R4A4_UNORM",
|
||||
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
"DXGI_FORMAT_P208",
|
||||
"DXGI_FORMAT_V208",
|
||||
"DXGI_FORMAT_V408"
|
||||
};
|
||||
|
||||
const char * GetDXGIFormatStr(DXGI_FORMAT format)
|
||||
{
|
||||
if (format > _countof(DXGI_FORMAT_STR))
|
||||
return DXGI_FORMAT_STR[0];
|
||||
return DXGI_FORMAT_STR[format];
|
||||
}
|
||||
|
||||
DXGI::DXGI() :
|
||||
m_options(NULL),
|
||||
m_initialized(false),
|
||||
m_dxgiFactory(),
|
||||
m_device(),
|
||||
m_deviceContext(),
|
||||
m_dup()
|
||||
{
|
||||
}
|
||||
|
||||
DXGI::~DXGI()
|
||||
{
|
||||
}
|
||||
|
||||
bool DXGI::CanInitialize()
|
||||
{
|
||||
HDESK desktop = OpenInputDesktop(0, TRUE, GENERIC_READ);
|
||||
if (!desktop)
|
||||
return false;
|
||||
|
||||
CloseDesktop(desktop);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DXGI::Initialize(CaptureOptions * options)
|
||||
{
|
||||
if (m_initialized)
|
||||
DeInitialize();
|
||||
|
||||
m_options = options;
|
||||
HRESULT status;
|
||||
|
||||
m_cursorRPos = 0;
|
||||
m_cursorWPos = 0;
|
||||
for (int i = 0; i < _countof(m_cursorRing); ++i)
|
||||
{
|
||||
CursorInfo & cursor = m_cursorRing[i];
|
||||
cursor.visible = false;
|
||||
cursor.hasPos = false;
|
||||
cursor.hasShape = false;
|
||||
}
|
||||
|
||||
status = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)(&m_dxgiFactory));
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_ERROR("Failed to create DXGIFactory: %08x", (int)status);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
IDXGIAdapter1Ptr adapter;
|
||||
for (int i = 0; m_dxgiFactory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; i++)
|
||||
{
|
||||
for (int i = 0; adapter->EnumOutputs(i, &m_output) != DXGI_ERROR_NOT_FOUND; i++)
|
||||
{
|
||||
DXGI_OUTPUT_DESC outputDesc;
|
||||
m_output->GetDesc(&outputDesc);
|
||||
if (!outputDesc.AttachedToDesktop)
|
||||
{
|
||||
m_output = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
DXGI_ADAPTER_DESC1 adapterDesc;
|
||||
adapter->GetDesc1(&adapterDesc);
|
||||
DEBUG_INFO("Device Descripion: %ls" , adapterDesc.Description);
|
||||
DEBUG_INFO("Device Vendor ID : 0x%x" , adapterDesc.VendorId);
|
||||
DEBUG_INFO("Device Device ID : 0x%x" , adapterDesc.DeviceId);
|
||||
DEBUG_INFO("Device Video Mem : %lld MB", adapterDesc.DedicatedVideoMemory / 1048576);
|
||||
DEBUG_INFO("Device Sys Mem : %lld MB", adapterDesc.DedicatedSystemMemory / 1048576);
|
||||
DEBUG_INFO("Shared Sys Mem : %lld MB", adapterDesc.SharedSystemMemory / 1048576);
|
||||
|
||||
m_width = outputDesc.DesktopCoordinates.right - outputDesc.DesktopCoordinates.left;
|
||||
m_height = outputDesc.DesktopCoordinates.bottom - outputDesc.DesktopCoordinates.top;
|
||||
DEBUG_INFO("Capture Size : %u x %u", m_width, m_height);
|
||||
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (done)
|
||||
break;
|
||||
|
||||
adapter = NULL;
|
||||
}
|
||||
|
||||
if (!done)
|
||||
{
|
||||
DEBUG_ERROR("Failed to locate a valid output device");
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
static const D3D_FEATURE_LEVEL featureLevels[] = {
|
||||
D3D_FEATURE_LEVEL_12_1,
|
||||
D3D_FEATURE_LEVEL_12_0,
|
||||
D3D_FEATURE_LEVEL_11_1,
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0,
|
||||
D3D_FEATURE_LEVEL_9_3,
|
||||
D3D_FEATURE_LEVEL_9_2,
|
||||
D3D_FEATURE_LEVEL_9_1
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define CREATE_FLAGS (D3D11_CREATE_DEVICE_DEBUG)
|
||||
#else
|
||||
#define CREATE_FLAGS (0)
|
||||
#endif
|
||||
|
||||
status = D3D11CreateDevice(
|
||||
adapter,
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
NULL,
|
||||
CREATE_FLAGS | D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
|
||||
featureLevels, ARRAYSIZE(featureLevels),
|
||||
D3D11_SDK_VERSION,
|
||||
&m_device,
|
||||
&m_featureLevel,
|
||||
&m_deviceContext
|
||||
);
|
||||
#undef CREATE_FLAGS
|
||||
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create D3D11 device", status);
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_INFO("Feature Level : 0x%x", m_featureLevel);
|
||||
|
||||
IDXGIDevicePtr dxgi;
|
||||
status = m_device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgi);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to obtain the IDXGIDevice interface from the D3D11 device", status);
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
dxgi->SetGPUThreadPriority(7);
|
||||
|
||||
// first try to use the newer API
|
||||
IDXGIOutput5Ptr output5 = m_output;
|
||||
if (output5)
|
||||
{
|
||||
// we try this twice in case we still get an error on re-initialization
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
const DXGI_FORMAT supportedFormats[] = {
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM
|
||||
};
|
||||
|
||||
status = output5->DuplicateOutput1(m_device, 0, _countof(supportedFormats), supportedFormats, &m_dup);
|
||||
if (SUCCEEDED(status))
|
||||
break;
|
||||
Sleep(200);
|
||||
}
|
||||
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("DuplicateOutput1 Failed", status);
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_WARN("IDXGIOutput5 is not available, please update windows for improved performance!");
|
||||
DEBUG_WARN("Falling back to IDXIGOutput1");
|
||||
IDXGIOutput1Ptr output1 = m_output;
|
||||
if (!output1)
|
||||
{
|
||||
DEBUG_ERROR("Failed to get IDXGIOutput1");
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
// we try this twice in case we still get an error on re-initialization
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
status = output1->DuplicateOutput(m_device, &m_dup);
|
||||
if (SUCCEEDED(status))
|
||||
break;
|
||||
Sleep(200);
|
||||
}
|
||||
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("DuplicateOutput Failed", status);
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
DXGI_OUTDUPL_DESC dupDesc;
|
||||
m_dup->GetDesc(&dupDesc);
|
||||
DEBUG_INFO("Source Format : %s", GetDXGIFormatStr(dupDesc.ModeDesc.Format));
|
||||
|
||||
m_started = false;
|
||||
m_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DXGI::InitRawCapture()
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC texDesc;
|
||||
ZeroMemory(&texDesc, sizeof(texDesc));
|
||||
texDesc.Width = m_width;
|
||||
texDesc.Height = m_height;
|
||||
texDesc.MipLevels = 1;
|
||||
texDesc.ArraySize = 1;
|
||||
texDesc.SampleDesc.Count = 1;
|
||||
texDesc.SampleDesc.Quality = 0;
|
||||
texDesc.Usage = D3D11_USAGE_STAGING;
|
||||
texDesc.Format = m_pixelFormat;
|
||||
texDesc.BindFlags = 0;
|
||||
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
texDesc.MiscFlags = 0;
|
||||
|
||||
HRESULT status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[0]);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create texture", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DXGI::InitYUV420Capture()
|
||||
{
|
||||
HRESULT status;
|
||||
D3D11_TEXTURE2D_DESC texDesc;
|
||||
|
||||
ZeroMemory(&texDesc, sizeof(texDesc));
|
||||
texDesc.Width = m_width;
|
||||
texDesc.Height = m_height;
|
||||
texDesc.MipLevels = 1;
|
||||
texDesc.ArraySize = 1;
|
||||
texDesc.SampleDesc.Count = 1;
|
||||
texDesc.SampleDesc.Quality = 0;
|
||||
texDesc.Usage = D3D11_USAGE_STAGING;
|
||||
texDesc.Format = DXGI_FORMAT_R8_UNORM;
|
||||
texDesc.BindFlags = 0;
|
||||
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
texDesc.MiscFlags = 0;
|
||||
|
||||
status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[0]);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create texture", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
texDesc.Width /= 2;
|
||||
texDesc.Height /= 2;
|
||||
|
||||
status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[1]);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create texture", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[2]);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create texture", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_textureConverter = new TextureConverter();
|
||||
if (!m_textureConverter->Initialize(m_deviceContext, m_device, m_width, m_height, FRAME_TYPE_YUV420))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DXGI::DeInitialize()
|
||||
{
|
||||
if (m_h264)
|
||||
{
|
||||
delete m_h264;
|
||||
m_h264 = NULL;
|
||||
}
|
||||
|
||||
if (m_textureConverter)
|
||||
{
|
||||
delete m_textureConverter;
|
||||
m_textureConverter = NULL;
|
||||
}
|
||||
|
||||
ReleaseFrame();
|
||||
|
||||
for(int i = 0; i < _countof(m_cursorRing); ++i)
|
||||
{
|
||||
if (m_cursorRing[i].shape.buffer)
|
||||
delete[] m_cursorRing[i].shape.buffer;
|
||||
m_cursorRing[i].shape.buffer = NULL;
|
||||
m_cursorRing[i].shape.bufferSize = 0;
|
||||
}
|
||||
|
||||
for(int i = 0; i < _countof(m_texture); ++i)
|
||||
m_texture[i] = NULL;
|
||||
|
||||
m_dup = NULL;
|
||||
m_output = NULL;
|
||||
m_deviceContext = NULL;
|
||||
m_device = NULL;
|
||||
m_dxgiFactory = NULL;
|
||||
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
FrameType DXGI::GetFrameType()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return FRAME_TYPE_INVALID;
|
||||
return m_frameType;
|
||||
}
|
||||
|
||||
size_t DXGI::GetMaxFrameSize()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return 0;
|
||||
|
||||
return (m_width * m_height * 4);
|
||||
}
|
||||
|
||||
unsigned int Capture::DXGI::Capture()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return GRAB_STATUS_ERROR;
|
||||
|
||||
CursorInfo & cursor = m_cursorRing[m_cursorWPos];
|
||||
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
||||
IDXGIResourcePtr res;
|
||||
unsigned int ret;
|
||||
|
||||
HRESULT status;
|
||||
for (int retryCount = 0; retryCount < 2; ++retryCount)
|
||||
{
|
||||
ret = ReleaseFrame();
|
||||
if (ret != GRAB_STATUS_OK)
|
||||
return ret;
|
||||
|
||||
status = m_dup->AcquireNextFrame(1000, &frameInfo, &res);
|
||||
switch (status)
|
||||
{
|
||||
case S_OK:
|
||||
m_releaseFrame = true;
|
||||
break;
|
||||
|
||||
case DXGI_ERROR_WAIT_TIMEOUT:
|
||||
return GRAB_STATUS_TIMEOUT;
|
||||
|
||||
// desktop switch, mode change, switch DWM on or off or Secure Desktop
|
||||
case DXGI_ERROR_ACCESS_LOST:
|
||||
case WAIT_ABANDONED:
|
||||
return GRAB_STATUS_REINIT;
|
||||
|
||||
default:
|
||||
// unknown failure
|
||||
DEBUG_WINERROR("AcquireNextFrame failed", status);
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// if the pointer shape has changed
|
||||
if (frameInfo.PointerShapeBufferSize > 0)
|
||||
{
|
||||
// resize the buffer if required
|
||||
if (cursor.shape.bufferSize < frameInfo.PointerShapeBufferSize)
|
||||
{
|
||||
delete[] cursor.shape.buffer;
|
||||
cursor.shape.buffer = new char[frameInfo.PointerShapeBufferSize];
|
||||
cursor.shape.bufferSize = frameInfo.PointerShapeBufferSize;
|
||||
}
|
||||
|
||||
cursor.shape.pointerSize = 0;
|
||||
ret |= GRAB_STATUS_CURSOR;
|
||||
|
||||
DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo;
|
||||
status = m_dup->GetFramePointerShape(cursor.shape.bufferSize, cursor.shape.buffer, &cursor.shape.pointerSize, &shapeInfo);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to get the new pointer shape", status);
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
switch (shapeInfo.Type)
|
||||
{
|
||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR : cursor.type = CURSOR_TYPE_COLOR; break;
|
||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: cursor.type = CURSOR_TYPE_MASKED_COLOR; break;
|
||||
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME : cursor.type = CURSOR_TYPE_MONOCHROME; break;
|
||||
default:
|
||||
DEBUG_ERROR("Invalid cursor type");
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
cursor.hasShape = true;
|
||||
cursor.w = shapeInfo.Width;
|
||||
cursor.h = shapeInfo.Height;
|
||||
cursor.pitch = shapeInfo.Pitch;
|
||||
}
|
||||
|
||||
// if we have a mouse update
|
||||
if (frameInfo.LastMouseUpdateTime.QuadPart)
|
||||
{
|
||||
if (
|
||||
m_lastCursorX != frameInfo.PointerPosition.Position.x ||
|
||||
m_lastCursorY != frameInfo.PointerPosition.Position.y
|
||||
) {
|
||||
ret |= GRAB_STATUS_CURSOR;
|
||||
cursor.hasPos = true;
|
||||
cursor.x = m_lastCursorX = frameInfo.PointerPosition.Position.x;
|
||||
cursor.y = m_lastCursorY = frameInfo.PointerPosition.Position.y;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_lastMouseVis != frameInfo.PointerPosition.Visible)
|
||||
m_lastMouseVis = frameInfo.PointerPosition.Visible;
|
||||
cursor.visible = m_lastMouseVis == TRUE;
|
||||
|
||||
if (ret & GRAB_STATUS_CURSOR && m_cursorWPos == m_cursorRPos)
|
||||
{
|
||||
// atomic advance so we don't have to worry about locking
|
||||
m_cursorWPos = (m_cursorWPos + 1 == DXGI_CURSOR_RING_SIZE) ? 0 : m_cursorWPos + 1;
|
||||
}
|
||||
|
||||
// if we don't have frame data
|
||||
if (frameInfo.LastPresentTime.QuadPart == 0)
|
||||
{
|
||||
// if there is nothing to update, just start again
|
||||
if (!ret)
|
||||
{
|
||||
--retryCount;
|
||||
continue;
|
||||
}
|
||||
|
||||
res = NULL;
|
||||
ret |= GRAB_STATUS_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// success, break out of the retry loop
|
||||
break;
|
||||
}
|
||||
|
||||
ret |= GRAB_STATUS_FRAME;
|
||||
|
||||
// ensure we have a frame
|
||||
if (!m_releaseFrame)
|
||||
{
|
||||
DEBUG_WINERROR("Failed to acquire next frame", status);
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// get the texture
|
||||
res.QueryInterface(IID_PPV_ARGS(&m_ftexture));
|
||||
res = NULL;
|
||||
if (!m_ftexture)
|
||||
{
|
||||
DEBUG_ERROR("Failed to get src ID3D11Texture2D");
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (!m_started)
|
||||
{
|
||||
m_started = true;
|
||||
|
||||
// determine the native pixel format
|
||||
D3D11_TEXTURE2D_DESC dupDesc;
|
||||
ZeroMemory(&dupDesc, sizeof(dupDesc));
|
||||
m_ftexture->GetDesc(&dupDesc);
|
||||
m_pixelFormat = dupDesc.Format;
|
||||
|
||||
switch(m_pixelFormat)
|
||||
{
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
m_frameType = FRAME_TYPE_RGBA;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
m_frameType = FRAME_TYPE_BGRA;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
||||
m_frameType = FRAME_TYPE_RGBA10;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_WARN("Unsupported pixel format %s, enabling conversions", GetDXGIFormatStr(m_pixelFormat));
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
DEBUG_INFO("Pixel Format : %s", GetDXGIFormatStr(m_pixelFormat));
|
||||
|
||||
for(CaptureOptions::const_iterator it = m_options->cbegin(); it != m_options->cend(); ++it)
|
||||
{
|
||||
if (_stricmp(*it, "yuv420") == 0) m_frameType = FRAME_TYPE_YUV420;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
switch (m_frameType)
|
||||
{
|
||||
case FRAME_TYPE_BGRA :
|
||||
case FRAME_TYPE_RGBA :
|
||||
case FRAME_TYPE_RGBA10: ok = InitRawCapture (); break;
|
||||
case FRAME_TYPE_YUV420: ok = InitYUV420Capture(); break;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// initiate the texture copy as early as possible
|
||||
if (m_frameType == FRAME_TYPE_YUV420)
|
||||
{
|
||||
TextureList planes;
|
||||
if (!m_textureConverter->Convert(m_ftexture, planes))
|
||||
return GRAB_STATUS_ERROR;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
ID3D11Texture2DPtr t = planes.at(i);
|
||||
m_deviceContext->CopyResource(m_texture[i], t);
|
||||
}
|
||||
}
|
||||
else
|
||||
m_deviceContext->CopyResource(m_texture[0], m_ftexture);
|
||||
|
||||
ret |= GRAB_STATUS_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
GrabStatus Capture::DXGI::ReleaseFrame()
|
||||
{
|
||||
if (!m_releaseFrame)
|
||||
return GRAB_STATUS_OK;
|
||||
|
||||
m_releaseFrame = false;
|
||||
m_ftexture = NULL;
|
||||
|
||||
switch (m_dup->ReleaseFrame())
|
||||
{
|
||||
case S_OK:
|
||||
break;
|
||||
|
||||
case DXGI_ERROR_INVALID_CALL:
|
||||
DEBUG_ERROR("Frame was already released");
|
||||
return GRAB_STATUS_ERROR;
|
||||
|
||||
case WAIT_ABANDONED:
|
||||
case DXGI_ERROR_ACCESS_LOST:
|
||||
return GRAB_STATUS_REINIT;
|
||||
}
|
||||
|
||||
return GRAB_STATUS_OK;
|
||||
}
|
||||
|
||||
GrabStatus Capture::DXGI::DiscardFrame()
|
||||
{
|
||||
return ReleaseFrame();
|
||||
}
|
||||
|
||||
GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapping;
|
||||
|
||||
HRESULT status;
|
||||
status = m_deviceContext->Map(m_texture[0], 0, D3D11_MAP_READ, 0, &mapping);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to map the texture", status);
|
||||
DeInitialize();
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
frame.pitch = mapping.RowPitch;
|
||||
frame.stride = mapping.RowPitch / 4;
|
||||
|
||||
memcpySSE(frame.buffer, mapping.pData, frame.pitch * m_height);
|
||||
m_deviceContext->Unmap(m_texture[0], 0);
|
||||
|
||||
return GRAB_STATUS_OK;
|
||||
}
|
||||
|
||||
GrabStatus Capture::DXGI::GrabFrameYUV420(struct FrameInfo & frame)
|
||||
{
|
||||
uint8_t * data = (uint8_t *)frame.buffer;
|
||||
size_t remain = frame.bufferSize;
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
HRESULT status;
|
||||
D3D11_MAPPED_SUBRESOURCE mapping;
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
|
||||
m_texture[i]->GetDesc(&desc);
|
||||
status = m_deviceContext->Map(m_texture[i], 0, D3D11_MAP_READ, 0, &mapping);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to map the texture", status);
|
||||
DeInitialize();
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
const unsigned int size = desc.Height * desc.Width;
|
||||
if (size > remain)
|
||||
{
|
||||
m_deviceContext->Unmap(m_texture[i], 0);
|
||||
DEBUG_ERROR("Too much data to fit in buffer");
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
const uint8_t * src = (uint8_t *)mapping.pData;
|
||||
for(unsigned int y = 0; y < desc.Height; ++y)
|
||||
{
|
||||
memcpySSE(data, src, desc.Width);
|
||||
data += desc.Width;
|
||||
src += mapping.RowPitch;
|
||||
}
|
||||
m_deviceContext->Unmap(m_texture[i], 0);
|
||||
remain -= size;
|
||||
}
|
||||
|
||||
frame.pitch = m_width;
|
||||
frame.stride = m_width;
|
||||
return GRAB_STATUS_OK;
|
||||
}
|
||||
|
||||
GrabStatus DXGI::GetFrame(struct FrameInfo & frame)
|
||||
{
|
||||
if (!m_ftexture)
|
||||
{
|
||||
DEBUG_ERROR("A frame has not been captured");
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
frame.width = m_width;
|
||||
frame.height = m_height;
|
||||
|
||||
if (m_frameType == FRAME_TYPE_YUV420)
|
||||
return GrabFrameYUV420(frame);
|
||||
|
||||
return GrabFrameRaw(frame);
|
||||
}
|
||||
|
||||
bool DXGI::GetCursor(CursorInfo & cursor)
|
||||
{
|
||||
if (m_cursorRPos == m_cursorWPos)
|
||||
return false;
|
||||
|
||||
cursor = m_cursorRing[m_cursorRPos];
|
||||
return true;
|
||||
}
|
||||
|
||||
void DXGI::FreeCursor()
|
||||
{
|
||||
assert(m_cursorRPos != m_cursorWPos);
|
||||
|
||||
CursorInfo & cursor = m_cursorRing[m_cursorRPos];
|
||||
cursor.visible = false;
|
||||
cursor.hasPos = false;
|
||||
cursor.hasShape = false;
|
||||
|
||||
m_cursorRPos = (m_cursorRPos + 1 == DXGI_CURSOR_RING_SIZE) ? 0 : m_cursorRPos + 1;
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ICapture.h"
|
||||
#include "Com.h"
|
||||
#include "TextureConverter.h"
|
||||
#include "MFT/H264.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
#define W32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <shlwapi.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define DXGI_CURSOR_RING_SIZE 3
|
||||
|
||||
namespace Capture
|
||||
{
|
||||
class DXGI : public ICapture
|
||||
{
|
||||
public:
|
||||
DXGI();
|
||||
virtual ~DXGI();
|
||||
|
||||
const char * GetName() { return "DXGI"; }
|
||||
|
||||
bool CanInitialize();
|
||||
bool Initialize(CaptureOptions * options);
|
||||
|
||||
void DeInitialize();
|
||||
bool ReInitialize()
|
||||
{
|
||||
DeInitialize();
|
||||
/*
|
||||
DXGI needs some time when mode switches occur, failing to do so causes
|
||||
failure to start and exceptions internal to DXGI
|
||||
*/
|
||||
Sleep(400);
|
||||
return Initialize(m_options);
|
||||
}
|
||||
|
||||
enum FrameType GetFrameType();
|
||||
size_t GetMaxFrameSize();
|
||||
unsigned int Capture();
|
||||
GrabStatus GetFrame (struct FrameInfo & frame );
|
||||
bool GetCursor(CursorInfo & cursor);
|
||||
void FreeCursor();
|
||||
GrabStatus DiscardFrame();
|
||||
|
||||
private:
|
||||
|
||||
bool InitRawCapture();
|
||||
bool InitYUV420Capture();
|
||||
|
||||
CursorInfo m_cursorRing[DXGI_CURSOR_RING_SIZE];
|
||||
unsigned int m_cursorRPos, m_cursorWPos;
|
||||
|
||||
ID3D11Texture2DPtr m_ftexture;
|
||||
|
||||
GrabStatus ReleaseFrame();
|
||||
GrabStatus GrabFrameRaw (struct FrameInfo & frame);
|
||||
GrabStatus GrabFrameYUV420 (struct FrameInfo & frame);
|
||||
|
||||
CaptureOptions * m_options;
|
||||
|
||||
bool m_initialized;
|
||||
bool m_started;
|
||||
unsigned int m_width;
|
||||
unsigned int m_height;
|
||||
DXGI_FORMAT m_pixelFormat;
|
||||
enum FrameType m_frameType;
|
||||
|
||||
IDXGIFactory1Ptr m_dxgiFactory;
|
||||
ID3D11DevicePtr m_device;
|
||||
D3D_FEATURE_LEVEL m_featureLevel;
|
||||
ID3D11DeviceContextPtr m_deviceContext;
|
||||
IDXGIOutputPtr m_output;
|
||||
IDXGIOutputDuplicationPtr m_dup;
|
||||
bool m_releaseFrame;
|
||||
ID3D11Texture2DPtr m_texture[3];
|
||||
TextureConverter * m_textureConverter;
|
||||
MFT::H264 * m_h264;
|
||||
|
||||
int m_lastCursorX, m_lastCursorY;
|
||||
BOOL m_lastMouseVis;
|
||||
};
|
||||
};
|
@ -1,395 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#if CONFIG_CAPTURE_NVFBC
|
||||
|
||||
#include "NvFBC.h"
|
||||
using namespace Capture;
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/memcpySSE.h"
|
||||
#include "Util.h"
|
||||
|
||||
#ifdef _WIN64
|
||||
#define NVFBC_LIBRARY_NAME "NvFBC64.dll"
|
||||
#else
|
||||
#define NVFBC_LIBRARY_NAME "NvFBC.dll"
|
||||
#endif
|
||||
|
||||
#define MOPT "privData"
|
||||
|
||||
NvFBC::NvFBC() :
|
||||
m_options(NULL),
|
||||
m_optNoCrop(false),
|
||||
m_optNoWait(false),
|
||||
m_initialized(false),
|
||||
m_first(true),
|
||||
m_hDLL(NULL),
|
||||
m_nvFBC(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
NvFBC::~NvFBC()
|
||||
{
|
||||
}
|
||||
|
||||
bool Capture::NvFBC::CanInitialize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NvFBC::Initialize(CaptureOptions * options)
|
||||
{
|
||||
if (m_initialized)
|
||||
DeInitialize();
|
||||
|
||||
m_first = true;
|
||||
m_options = options;
|
||||
m_optNoCrop = false;
|
||||
|
||||
uint8_t * privData = NULL;
|
||||
NvU32 privDataSize = 0;
|
||||
|
||||
for (CaptureOptions::const_iterator it = options->cbegin(); it != options->cend(); ++it)
|
||||
{
|
||||
if (_strcmpi(*it, "nocrop") == 0) { m_optNoCrop = false; continue; }
|
||||
if (_strcmpi(*it, "nowait") == 0) { m_optNoWait = true ; continue; }
|
||||
|
||||
if (_strnicmp(*it, MOPT " ", sizeof(MOPT)) == 0)
|
||||
{
|
||||
std::string value(*it);
|
||||
value.erase(0, sizeof(MOPT));
|
||||
|
||||
if (value.empty() || value.length() & 1)
|
||||
continue;
|
||||
|
||||
privDataSize = (NvU32)(value.length() / 2);
|
||||
privData = new uint8_t[privDataSize];
|
||||
uint8_t *p = privData;
|
||||
for (int i = 0; i < value.length(); i += 2, ++p)
|
||||
{
|
||||
char hex[3];
|
||||
#pragma warning(disable:4996)
|
||||
value.copy(hex, 2, i);
|
||||
#pragma warning(restore:4996)
|
||||
hex[2] = 0;
|
||||
*p = (uint8_t)strtoul(hex, NULL, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string nvfbc = Util::GetSystemRoot() + "\\" + NVFBC_LIBRARY_NAME;
|
||||
m_hDLL = LoadLibraryA(nvfbc.c_str());
|
||||
if (!m_hDLL)
|
||||
{
|
||||
DEBUG_ERROR("Failed to load the NvFBC library: %d - %s", (int)GetLastError(), nvfbc.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_fnCreateEx = (NvFBC_CreateFunctionExType )GetProcAddress(m_hDLL, "NvFBC_CreateEx" );
|
||||
m_fnSetGlobalFlags = (NvFBC_SetGlobalFlagsType )GetProcAddress(m_hDLL, "NvFBC_SetGlobalFlags");
|
||||
m_fnGetStatusEx = (NvFBC_GetStatusExFunctionType)GetProcAddress(m_hDLL, "NvFBC_GetStatusEx" );
|
||||
m_fnEnable = (NvFBC_EnableFunctionType )GetProcAddress(m_hDLL, "NvFBC_Enable" );
|
||||
|
||||
if (!m_fnCreateEx || !m_fnSetGlobalFlags || !m_fnGetStatusEx || !m_fnEnable)
|
||||
{
|
||||
DEBUG_ERROR("Unable to locate required entry points in %s", nvfbc.c_str());
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
NvFBCStatusEx status;
|
||||
ZeroMemory(&status, sizeof(NvFBCStatusEx));
|
||||
status.dwVersion = NVFBC_STATUS_VER;
|
||||
status.dwAdapterIdx = 0;
|
||||
|
||||
NVFBCRESULT ret = m_fnGetStatusEx(&status);
|
||||
if (ret != NVFBC_SUCCESS)
|
||||
{
|
||||
DEBUG_ERROR("Failed to get NvFBC status");
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!status.bIsCapturePossible)
|
||||
{
|
||||
DEBUG_INFO("Attempting to enable NvFBC");
|
||||
switch(m_fnEnable(NVFBC_STATE_ENABLE))
|
||||
{
|
||||
case NVFBC_SUCCESS:
|
||||
DEBUG_INFO("Success, attempting to get status again");
|
||||
if (m_fnGetStatusEx(&status) != NVFBC_SUCCESS)
|
||||
{
|
||||
DEBUG_ERROR("Failed to get NvFBC status");
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case NVFBC_ERROR_INSUFFICIENT_PRIVILEGES:
|
||||
DEBUG_ERROR("Please run once as administrator to enable the NvFBC API");
|
||||
DeInitialize();
|
||||
return false;
|
||||
|
||||
default:
|
||||
DEBUG_ERROR("Unknown failure enabling NvFBC");
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!status.bIsCapturePossible)
|
||||
{
|
||||
DEBUG_ERROR("Capture is not possible, unsupported device or driver");
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!status.bCanCreateNow)
|
||||
{
|
||||
DEBUG_ERROR("Can not create an instance of NvFBC at this time");
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
NvFBCCreateParams params;
|
||||
ZeroMemory(¶ms, sizeof(NvFBCCreateParams));
|
||||
params.dwVersion = NVFBC_CREATE_PARAMS_VER;
|
||||
params.dwInterfaceType = NVFBC_TO_SYS;
|
||||
params.pDevice = NULL;
|
||||
params.dwAdapterIdx = 0;
|
||||
params.dwPrivateDataSize = privDataSize;
|
||||
params.pPrivateData = privData;
|
||||
|
||||
if (m_fnCreateEx(¶ms) != NVFBC_SUCCESS)
|
||||
{
|
||||
if (privData)
|
||||
delete [] privData;
|
||||
|
||||
DEBUG_ERROR("Failed to create an instance of NvFBC");
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (privData)
|
||||
delete[] privData;
|
||||
|
||||
m_maxCaptureWidth = params.dwMaxDisplayWidth;
|
||||
m_maxCaptureHeight = params.dwMaxDisplayHeight;
|
||||
m_nvFBC = static_cast<NvFBCToSys *>(params.pNvFBC);
|
||||
|
||||
NVFBC_TOSYS_SETUP_PARAMS setupParams;
|
||||
ZeroMemory(&setupParams, sizeof(NVFBC_TOSYS_SETUP_PARAMS));
|
||||
setupParams.dwVersion = NVFBC_TOSYS_SETUP_PARAMS_VER;
|
||||
setupParams.eMode = NVFBC_TOSYS_ARGB;
|
||||
setupParams.bWithHWCursor = TRUE;
|
||||
setupParams.bDiffMap = TRUE;
|
||||
setupParams.eDiffMapBlockSize = NVFBC_TOSYS_DIFFMAP_BLOCKSIZE_128X128;
|
||||
setupParams.ppBuffer = (void **)&m_frameBuffer;
|
||||
setupParams.ppDiffMap = (void **)&m_diffMap;
|
||||
|
||||
if (m_nvFBC->NvFBCToSysSetUp(&setupParams) != NVFBC_SUCCESS)
|
||||
{
|
||||
DEBUG_ERROR("NvFBCToSysSetUp Failed");
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
// this is required according to NVidia sample code
|
||||
Sleep(100);
|
||||
|
||||
HMONITOR monitor = MonitorFromWindow(GetDesktopWindow(), MONITOR_DEFAULTTOPRIMARY);
|
||||
MONITORINFO monitorInfo;
|
||||
monitorInfo.cbSize = sizeof(MONITORINFO);
|
||||
unsigned int screenWidth, screenHeight;
|
||||
GetMonitorInfo(monitor, &monitorInfo);
|
||||
screenWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
|
||||
screenHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
|
||||
|
||||
ZeroMemory(&m_grabFrameParams, sizeof(NVFBC_TOSYS_GRAB_FRAME_PARAMS));
|
||||
ZeroMemory(&m_grabInfo, sizeof(NvFBCFrameGrabInfo));
|
||||
m_grabFrameParams.dwVersion = NVFBC_TOSYS_GRAB_FRAME_PARAMS_VER;
|
||||
m_grabFrameParams.dwFlags = m_optNoWait ? NVFBC_TOSYS_NOWAIT : NVFBC_TOSYS_WAIT_WITH_TIMEOUT;
|
||||
m_grabFrameParams.dwWaitTime = 1000;
|
||||
m_grabFrameParams.eGMode = NVFBC_TOSYS_SOURCEMODE_CROP;
|
||||
m_grabFrameParams.dwStartX = 0;
|
||||
m_grabFrameParams.dwStartY = 0;
|
||||
m_grabFrameParams.dwTargetWidth = screenWidth;
|
||||
m_grabFrameParams.dwTargetHeight = screenHeight;
|
||||
m_grabFrameParams.pNvFBCFrameGrabInfo = &m_grabInfo;
|
||||
|
||||
m_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void NvFBC::DeInitialize()
|
||||
{
|
||||
m_frameBuffer = NULL;
|
||||
|
||||
if (m_nvFBC)
|
||||
{
|
||||
m_nvFBC->NvFBCToSysRelease();
|
||||
m_nvFBC = NULL;
|
||||
}
|
||||
|
||||
m_maxCaptureWidth = 0;
|
||||
m_maxCaptureHeight = 0;
|
||||
m_fnCreateEx = NULL;
|
||||
m_fnSetGlobalFlags = NULL;
|
||||
m_fnGetStatusEx = NULL;
|
||||
m_fnEnable = NULL;
|
||||
|
||||
if (m_hDLL)
|
||||
{
|
||||
FreeLibrary(m_hDLL);
|
||||
m_hDLL = NULL;
|
||||
}
|
||||
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
FrameType NvFBC::GetFrameType()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return FRAME_TYPE_INVALID;
|
||||
|
||||
return FRAME_TYPE_BGRA;
|
||||
}
|
||||
|
||||
size_t NvFBC::GetMaxFrameSize()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return false;
|
||||
|
||||
return m_maxCaptureWidth * m_maxCaptureHeight * 4;
|
||||
}
|
||||
|
||||
unsigned int Capture::NvFBC::Capture()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return GRAB_STATUS_ERROR;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
NVFBCRESULT status = m_nvFBC->NvFBCToSysGrabFrame(&m_grabFrameParams);
|
||||
if (status == NVFBC_SUCCESS)
|
||||
{
|
||||
const int diffW = (m_grabInfo.dwWidth + 0x7F) >> 7;
|
||||
const int diffH = (m_grabInfo.dwHeight + 0x7F) >> 7;
|
||||
bool hasDiff = false;
|
||||
for (int y = 0; y < diffH && !hasDiff; ++y)
|
||||
for (int x = 0; x < diffW; ++x)
|
||||
if (m_diffMap[y * diffW + x])
|
||||
{
|
||||
hasDiff = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hasDiff)
|
||||
{
|
||||
i = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status == NVFBC_ERROR_DYNAMIC_DISABLE)
|
||||
{
|
||||
DEBUG_ERROR("NvFBC was disabled by someone else");
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (status == NVFBC_ERROR_INVALIDATED_SESSION)
|
||||
{
|
||||
DEBUG_WARN("Session was invalidated, attempting to restart");
|
||||
return GRAB_STATUS_REINIT;
|
||||
}
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
DEBUG_ERROR("NvFBCToSysGrabFrame failed");
|
||||
return GRAB_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the capture size doesn't match the screen resolution then re-initialize to avoid
|
||||
// copying black/blank areas of the screen
|
||||
HMONITOR monitor = MonitorFromWindow(GetDesktopWindow(), MONITOR_DEFAULTTOPRIMARY);
|
||||
MONITORINFO monitorInfo;
|
||||
monitorInfo.cbSize = sizeof(MONITORINFO);
|
||||
unsigned int screenWidth, screenHeight;
|
||||
GetMonitorInfo(monitor, &monitorInfo);
|
||||
screenWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
|
||||
screenHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
|
||||
if (m_grabInfo.dwWidth != screenWidth || m_grabInfo.dwHeight != screenHeight)
|
||||
{
|
||||
DEBUG_INFO("Resolution change detected");
|
||||
return GRAB_STATUS_REINIT;
|
||||
}
|
||||
|
||||
// turn off the cursor on the first frame as NvFBC is drawing it
|
||||
if (m_first)
|
||||
return GRAB_STATUS_OK | GRAB_STATUS_FRAME | GRAB_STATUS_CURSOR;
|
||||
else
|
||||
return GRAB_STATUS_OK | GRAB_STATUS_FRAME;
|
||||
}
|
||||
|
||||
bool Capture::NvFBC::GetCursor(CursorInfo & cursor)
|
||||
{
|
||||
cursor.hasShape = false;
|
||||
cursor.hasPos = false;
|
||||
cursor.visible = false;
|
||||
|
||||
if (m_first)
|
||||
{
|
||||
m_first = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Capture::NvFBC::FreeCursor()
|
||||
{
|
||||
}
|
||||
|
||||
GrabStatus Capture::NvFBC::DiscardFrame()
|
||||
{
|
||||
return GrabStatus();
|
||||
}
|
||||
|
||||
enum GrabStatus NvFBC::GetFrame(struct FrameInfo & frame)
|
||||
{
|
||||
if (!m_initialized)
|
||||
return GRAB_STATUS_ERROR;
|
||||
|
||||
frame.width = m_grabInfo.dwWidth;
|
||||
frame.height = m_grabInfo.dwHeight;
|
||||
frame.stride = m_grabInfo.dwBufferWidth;
|
||||
frame.pitch = m_grabInfo.dwBufferWidth * 4;
|
||||
|
||||
memcpySSE((uint8_t*)frame.buffer, (uint8_t *)m_frameBuffer, frame.pitch * frame.height);
|
||||
return GRAB_STATUS_OK;
|
||||
}
|
||||
|
||||
#endif// CONFIG_CAPTURE_NVFBC
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#if CONFIG_CAPTURE_NVFBC
|
||||
|
||||
#pragma once
|
||||
#include "ICapture.h"
|
||||
|
||||
#define W32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include <NvFBC/nvFBC.h>
|
||||
#include <NvFBC/nvFBCToSys.h>
|
||||
|
||||
namespace Capture
|
||||
{
|
||||
class NvFBC : public ICapture
|
||||
{
|
||||
public:
|
||||
NvFBC();
|
||||
~NvFBC();
|
||||
|
||||
const char * GetName() { return "NvFBC"; }
|
||||
bool CanInitialize();
|
||||
bool Initialize(CaptureOptions * options);
|
||||
void DeInitialize();
|
||||
bool ReInitialize()
|
||||
{
|
||||
DeInitialize();
|
||||
return Initialize(m_options);
|
||||
}
|
||||
enum FrameType GetFrameType();
|
||||
size_t GetMaxFrameSize();
|
||||
unsigned int Capture();
|
||||
enum GrabStatus GetFrame(struct FrameInfo & frame);
|
||||
bool GetCursor(CursorInfo & cursor);
|
||||
void FreeCursor() ;
|
||||
enum GrabStatus DiscardFrame();
|
||||
|
||||
private:
|
||||
CaptureOptions * m_options;
|
||||
bool m_optNoCrop;
|
||||
bool m_optNoWait;
|
||||
|
||||
bool m_initialized;
|
||||
bool m_first;
|
||||
HMODULE m_hDLL;
|
||||
|
||||
NvFBC_CreateFunctionExType m_fnCreateEx;
|
||||
NvFBC_SetGlobalFlagsType m_fnSetGlobalFlags;
|
||||
NvFBC_GetStatusExFunctionType m_fnGetStatusEx;
|
||||
NvFBC_EnableFunctionType m_fnEnable;
|
||||
|
||||
DWORD m_maxCaptureWidth, m_maxCaptureHeight;
|
||||
NvFBCToSys * m_nvFBC;
|
||||
uint8_t * m_frameBuffer;
|
||||
uint8_t * m_diffMap;
|
||||
NvFBCFrameGrabInfo m_grabInfo;
|
||||
NVFBC_TOSYS_GRAB_FRAME_PARAMS m_grabFrameParams;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //CONFIG_CAPTURE_NVFBC
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define W32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "ICapture.h"
|
||||
#if CONFIG_CAPTURE_NVFBC
|
||||
#include "Capture/NvFBC.h"
|
||||
#endif
|
||||
#include "Capture/DXGI.h"
|
||||
|
||||
class CaptureFactory
|
||||
{
|
||||
public:
|
||||
typedef std::vector<ICapture *> DeviceList;
|
||||
|
||||
static DeviceList & GetDevices()
|
||||
{
|
||||
static DeviceList devices;
|
||||
if (!devices.empty())
|
||||
return devices;
|
||||
|
||||
#if CONFIG_CAPTURE_NVFBC
|
||||
devices.push_back(new Capture::NvFBC());
|
||||
#endif
|
||||
devices.push_back(new Capture::DXGI ());
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
static ICapture * GetDevice(const char * name, CaptureOptions * options)
|
||||
{
|
||||
DeviceList devices = GetDevices();
|
||||
for (DeviceList::const_iterator it = devices.begin(); it != devices.end(); ++it)
|
||||
{
|
||||
ICapture * device = *it;
|
||||
if (_strcmpi(name, device->GetName()) != 0)
|
||||
continue;
|
||||
|
||||
if (device->Initialize(options))
|
||||
{
|
||||
DEBUG_INFO("Using %s", device->GetName());
|
||||
return device;
|
||||
}
|
||||
|
||||
device->DeInitialize();
|
||||
DEBUG_ERROR("Failed to initialize %s", device->GetName());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG_ERROR("No such device: %s", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ICapture * DetectDevice(CaptureOptions * options)
|
||||
{
|
||||
DeviceList devices = GetDevices();
|
||||
for (DeviceList::const_iterator it = devices.cbegin(); it != devices.cend(); ++it)
|
||||
{
|
||||
ICapture * device = *it;
|
||||
|
||||
DEBUG_INFO("Trying %s", device->GetName());
|
||||
if (device->Initialize(options))
|
||||
{
|
||||
DEBUG_INFO("Using %s", device->GetName());
|
||||
return device;
|
||||
}
|
||||
device->DeInitialize();
|
||||
}
|
||||
|
||||
DEBUG_ERROR("Failed to initialize a capture device");
|
||||
return NULL;
|
||||
}
|
||||
};
|
58
host/Com.h
58
host/Com.h
@ -1,58 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <comdef.h>
|
||||
#include <dxgi1_2.h>
|
||||
#include <dxgi1_5.h>
|
||||
#include <d3d11.h>
|
||||
#include <mftransform.h>
|
||||
|
||||
_COM_SMARTPTR_TYPEDEF(IDXGIFactory1 , __uuidof(IDXGIFactory1 ));
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11Device , __uuidof(ID3D11Device ));
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11DeviceContext , __uuidof(ID3D11DeviceContext ));
|
||||
_COM_SMARTPTR_TYPEDEF(IDXGIDevice , __uuidof(IDXGIDevice ));
|
||||
_COM_SMARTPTR_TYPEDEF(IDXGIOutput1 , __uuidof(IDXGIOutput1 ));
|
||||
_COM_SMARTPTR_TYPEDEF(IDXGIOutput5 , __uuidof(IDXGIOutput5 ));
|
||||
_COM_SMARTPTR_TYPEDEF(IDXGIOutput , __uuidof(IDXGIOutput ));
|
||||
_COM_SMARTPTR_TYPEDEF(IDXGIAdapter1 , __uuidof(IDXGIAdapter1 ));
|
||||
_COM_SMARTPTR_TYPEDEF(IDXGIOutputDuplication , __uuidof(IDXGIOutputDuplication ));
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11Texture2D , __uuidof(ID3D11Texture2D ));
|
||||
_COM_SMARTPTR_TYPEDEF(IDXGIResource , __uuidof(IDXGIResource ));
|
||||
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D10Multithread , __uuidof(ID3D10Multithread ));
|
||||
_COM_SMARTPTR_TYPEDEF(IMFActivate , __uuidof(IMFActivate ));
|
||||
_COM_SMARTPTR_TYPEDEF(IMFAttributes , __uuidof(IMFAttributes ));
|
||||
_COM_SMARTPTR_TYPEDEF(IMFDXGIDeviceManager , __uuidof(IMFDXGIDeviceManager ));
|
||||
_COM_SMARTPTR_TYPEDEF(IMFTransform , __uuidof(IMFTransform ));
|
||||
_COM_SMARTPTR_TYPEDEF(IMFMediaEvent , __uuidof(IMFMediaEvent ));
|
||||
_COM_SMARTPTR_TYPEDEF(IMFMediaEventGenerator , __uuidof(IMFMediaEventGenerator ));
|
||||
_COM_SMARTPTR_TYPEDEF(IMFMediaType , __uuidof(IMFMediaType ));
|
||||
_COM_SMARTPTR_TYPEDEF(IMFSample , __uuidof(IMFSample ));
|
||||
_COM_SMARTPTR_TYPEDEF(IMFMediaBuffer , __uuidof(IMFMediaBuffer ));
|
||||
_COM_SMARTPTR_TYPEDEF(IMF2DBuffer , __uuidof(IMF2DBuffer ));
|
||||
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11RenderTargetView , __uuidof(ID3D11RenderTargetView ));
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11ShaderResourceView, __uuidof(ID3D11ShaderResourceView));
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11DepthStencilView , __uuidof(ID3D11DepthStencilView ));
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11InputLayout , __uuidof(ID3D11InputLayout ));
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11VertexShader , __uuidof(ID3D11VertexShader ));
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11PixelShader , __uuidof(ID3D11PixelShader ));
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11SamplerState , __uuidof(ID3D11SamplerState ));
|
||||
_COM_SMARTPTR_TYPEDEF(ID3D11Buffer , __uuidof(ID3D11Buffer ));
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
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 "CrashHandler.h"
|
||||
|
||||
typedef BOOL (WINAPI * PMiniDumpWriteDump)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD ProcessId,
|
||||
_In_ HANDLE hFile,
|
||||
_In_ MINIDUMP_TYPE DumpType,
|
||||
_In_opt_ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||
_In_opt_ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
||||
_In_opt_ PMINIDUMP_CALLBACK_INFORMATION CallbackParam
|
||||
);
|
||||
|
||||
void CrashHandler::Initialize()
|
||||
{
|
||||
SetUnhandledExceptionFilter(CrashHandler::ExceptionFilter);
|
||||
}
|
||||
|
||||
LONG WINAPI CrashHandler::ExceptionFilter(struct _EXCEPTION_POINTERS * apExceptionInfo)
|
||||
{
|
||||
HMODULE lib;
|
||||
PMiniDumpWriteDump fn_MiniDumpWriteDump;
|
||||
|
||||
lib = LoadLibraryA("dbghelp.dll");
|
||||
if (!lib)
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
||||
fn_MiniDumpWriteDump = (PMiniDumpWriteDump)GetProcAddress(lib, "MiniDumpWriteDump");
|
||||
if (!fn_MiniDumpWriteDump)
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
||||
HANDLE hFile = CreateFileA(
|
||||
"looking-glass-host.dump",
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
||||
_MINIDUMP_EXCEPTION_INFORMATION info;
|
||||
info.ThreadId = GetCurrentThreadId();
|
||||
info.ExceptionPointers = apExceptionInfo;
|
||||
info.ClientPointers = FALSE;
|
||||
|
||||
fn_MiniDumpWriteDump(
|
||||
GetCurrentProcess(),
|
||||
GetCurrentProcessId(),
|
||||
hFile,
|
||||
MiniDumpNormal,
|
||||
&info,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
CloseHandle(hFile);
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
|
||||
class CrashHandler
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
private:
|
||||
static LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS * apExceptionInfo);
|
||||
};
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/KVMFR.h"
|
||||
#include <vector>
|
||||
#include <windows.h>
|
||||
|
||||
struct CursorBuffer
|
||||
{
|
||||
unsigned int bufferSize;
|
||||
char * buffer;
|
||||
unsigned int pointerSize;
|
||||
};
|
||||
|
||||
struct CursorInfo
|
||||
{
|
||||
bool visible;
|
||||
bool hasPos;
|
||||
bool hasShape;
|
||||
int x, y;
|
||||
|
||||
enum CursorType type;
|
||||
unsigned int w, h;
|
||||
unsigned int pitch;
|
||||
CursorBuffer shape;
|
||||
};
|
||||
|
||||
struct FrameInfo
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int stride;
|
||||
unsigned int pitch;
|
||||
void * buffer;
|
||||
size_t bufferSize;
|
||||
};
|
||||
|
||||
enum GrabStatus
|
||||
{
|
||||
GRAB_STATUS_OK = 1,
|
||||
GRAB_STATUS_TIMEOUT = 2,
|
||||
GRAB_STATUS_REINIT = 4,
|
||||
GRAB_STATUS_CURSOR = 8,
|
||||
GRAB_STATUS_FRAME = 16,
|
||||
GRAB_STATUS_ERROR = 32
|
||||
};
|
||||
|
||||
typedef std::vector<const char *> CaptureOptions;
|
||||
|
||||
class ICapture
|
||||
{
|
||||
public:
|
||||
virtual const char * GetName() = 0;
|
||||
|
||||
virtual bool CanInitialize() = 0;
|
||||
virtual bool Initialize(CaptureOptions * options) = 0;
|
||||
virtual void DeInitialize() = 0;
|
||||
virtual bool ReInitialize() = 0;
|
||||
virtual enum FrameType GetFrameType() = 0;
|
||||
virtual size_t GetMaxFrameSize() = 0;
|
||||
virtual unsigned int Capture() = 0;
|
||||
virtual enum GrabStatus GetFrame(struct FrameInfo & frame) = 0;
|
||||
virtual bool GetCursor(CursorInfo & cursor) = 0;
|
||||
virtual void FreeCursor() = 0;
|
||||
virtual enum GrabStatus DiscardFrame() = 0;
|
||||
};
|
380
host/IVSHMEM.cpp
380
host/IVSHMEM.cpp
@ -1,380 +0,0 @@
|
||||
/*
|
||||
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 "IVSHMEM.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include "kvm-guest-drivers-windows/ivshmem/Public.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
IVSHMEM * IVSHMEM::m_instance = NULL;
|
||||
|
||||
void IVSHMEM::listDevices() {
|
||||
|
||||
HDEVINFO deviceInfoSet;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL;
|
||||
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
||||
|
||||
deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
|
||||
ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
|
||||
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
|
||||
fprintf(stderr, "Found devices:\n");
|
||||
|
||||
DWORD i = 0;
|
||||
while(SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, i, &deviceInterfaceData) != FALSE)
|
||||
{
|
||||
DWORD reqSize = 0;
|
||||
SP_DEVINFO_DATA d;
|
||||
d.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
|
||||
SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &reqSize, &d);
|
||||
if (!reqSize)
|
||||
{
|
||||
fprintf(stderr, "SetupDiGetDeviceInterfaceDetail");
|
||||
break;
|
||||
}
|
||||
|
||||
infData = static_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(reqSize));
|
||||
ZeroMemory(infData, reqSize);
|
||||
infData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, infData, reqSize, NULL, NULL))
|
||||
{
|
||||
fprintf(stderr, "SetupDiGetDeviceInterfaceDetail");
|
||||
break;
|
||||
}
|
||||
|
||||
DWORD bus, addr, slot, func;
|
||||
|
||||
if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, &d,SPDRP_BUSNUMBER,NULL,(PBYTE)&bus,sizeof(bus),NULL))
|
||||
{
|
||||
DEBUG_ERROR("SetupDiGetDeviceRegistryProperty - SPDRP_BUSNUMBER: %lu\n", GetLastError());
|
||||
free(infData);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, &d,SPDRP_ADDRESS,NULL, (PBYTE)&addr,sizeof(addr),NULL))
|
||||
{
|
||||
DEBUG_ERROR("SetupDiGetDeviceRegistryProperty - SPDRP_ADDRESS: %lu\n", GetLastError());
|
||||
free(infData);
|
||||
break;
|
||||
}
|
||||
|
||||
slot = (addr >> 16) & 0xFFFF;
|
||||
func = addr & 0xFFFF;
|
||||
|
||||
fprintf(stderr, "[%lu] Found Device: %ls\n"
|
||||
" Bus: 0x%lx\n"
|
||||
" Slot: 0x%lx\n"
|
||||
" Func: 0x%lx\n",
|
||||
i, infData->DevicePath, bus, slot, func);
|
||||
i++;
|
||||
}
|
||||
|
||||
DWORD error = GetLastError();
|
||||
if (error != ERROR_NO_MORE_ITEMS)
|
||||
{
|
||||
fprintf(stderr, "Unknown error on index %u: %lu\n", i, error);
|
||||
}
|
||||
|
||||
fprintf(stderr, "%lu devices found\n\n", i);
|
||||
}
|
||||
|
||||
IVSHMEM::IVSHMEM() :
|
||||
m_initialized(false),
|
||||
m_handle(INVALID_HANDLE_VALUE),
|
||||
m_gotSize(false),
|
||||
m_gotPeerID(false),
|
||||
m_gotMemory(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
IVSHMEM::~IVSHMEM()
|
||||
{
|
||||
DeInitialize();
|
||||
}
|
||||
|
||||
bool IVSHMEM::Initialize(PCI_DEVICE dev)
|
||||
{
|
||||
if (m_initialized)
|
||||
DeInitialize();
|
||||
|
||||
HDEVINFO deviceInfoSet;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL;
|
||||
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
||||
|
||||
deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
|
||||
ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
|
||||
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
|
||||
DWORD devid = 0;
|
||||
while (SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, devid, &deviceInterfaceData) != FALSE)
|
||||
{
|
||||
DWORD reqSize = 0;
|
||||
SP_DEVINFO_DATA d;
|
||||
d.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &reqSize, &d);
|
||||
if (!reqSize)
|
||||
{
|
||||
DEBUG_ERROR("SetupDiGetDeviceInterfaceDetail");
|
||||
break;
|
||||
}
|
||||
|
||||
infData = static_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(reqSize));
|
||||
ZeroMemory(infData, reqSize);
|
||||
infData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, infData, reqSize, NULL, NULL))
|
||||
{
|
||||
DEBUG_ERROR("SetupDiGetDeviceInterfaceDetail");
|
||||
free(infData);
|
||||
break;
|
||||
}
|
||||
|
||||
DWORD bus, addr, slot, func;
|
||||
|
||||
if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, &d,SPDRP_BUSNUMBER,NULL,(PBYTE)&bus,sizeof(bus),NULL))
|
||||
{
|
||||
DEBUG_ERROR("SetupDiGetDeviceRegistryProperty - SPDRP_BUSNUMBER");
|
||||
free(infData);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, &d,SPDRP_ADDRESS,NULL, (PBYTE)&addr,sizeof(addr),NULL))
|
||||
{
|
||||
DEBUG_ERROR("SetupDiGetDeviceRegistryProperty - SPDRP_ADDRESS");
|
||||
free(infData);
|
||||
break;
|
||||
}
|
||||
|
||||
slot = (addr >> 16) & 0xFFFF;
|
||||
func = addr & 0xFFFF;
|
||||
|
||||
if (dev.bus != bus || dev.addr != slot || dev.func != func) //not the right device, keep searching
|
||||
{
|
||||
free(infData);
|
||||
devid++;
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Found Device at Index %lu: %ls\n"
|
||||
" Bus: %lu\n"
|
||||
" Addr: %lu\n"
|
||||
" Func: %lu\n",
|
||||
devid, infData->DevicePath, bus, slot, func);
|
||||
|
||||
m_handle = CreateFile(infData->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0);
|
||||
if (m_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DEBUG_ERROR("CreateFile returned INVALID_HANDLE_VALUE");
|
||||
free(infData);
|
||||
break;
|
||||
}
|
||||
|
||||
m_initialized = true;
|
||||
break;
|
||||
}
|
||||
|
||||
DWORD error = GetLastError();
|
||||
if (m_initialized == false)
|
||||
{
|
||||
if (error == ERROR_NO_MORE_ITEMS)
|
||||
{
|
||||
DEBUG_ERROR("Unable to enumerate the device, is it attached?");
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_ERROR("Unable to enumerate the device. Error: %lu\n", error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
void IVSHMEM::DeInitialize()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return;
|
||||
|
||||
if (m_gotMemory)
|
||||
{
|
||||
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_RELEASE_MMAP, NULL, 0, NULL, 0, NULL, NULL))
|
||||
DEBUG_ERROR("DeviceIoControl failed: %d", (int)GetLastError());
|
||||
m_memory = NULL;
|
||||
}
|
||||
|
||||
if (m_handle != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(m_handle);
|
||||
|
||||
m_initialized = false;
|
||||
m_handle = INVALID_HANDLE_VALUE;
|
||||
m_gotSize = false;
|
||||
m_gotPeerID = false;
|
||||
m_gotVectors = false;
|
||||
m_gotMemory = false;
|
||||
}
|
||||
|
||||
bool IVSHMEM::IsInitialized()
|
||||
{
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
UINT64 IVSHMEM::GetSize()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return 0;
|
||||
|
||||
if (m_gotSize)
|
||||
return m_size;
|
||||
|
||||
IVSHMEM_SIZE size;
|
||||
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &size, sizeof(IVSHMEM_SIZE), NULL, NULL))
|
||||
{
|
||||
DEBUG_ERROR("DeviceIoControl Failed: %d", (int)GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_gotSize = true;
|
||||
m_size = static_cast<UINT64>(size);
|
||||
return m_size;
|
||||
}
|
||||
|
||||
UINT16 IVSHMEM::GetPeerID()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return 0;
|
||||
|
||||
if (m_gotPeerID)
|
||||
return m_peerID;
|
||||
|
||||
IVSHMEM_PEERID peerID;
|
||||
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &peerID, sizeof(IVSHMEM_PEERID), NULL, NULL))
|
||||
{
|
||||
DEBUG_ERROR("DeviceIoControl Failed: %d", (int)GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_gotPeerID = true;
|
||||
m_peerID = static_cast<UINT16>(peerID);
|
||||
return m_peerID;
|
||||
}
|
||||
|
||||
UINT16 IVSHMEM::GetVectors()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return 0;
|
||||
|
||||
if (!m_gotVectors)
|
||||
return 0;
|
||||
|
||||
return m_vectors;
|
||||
}
|
||||
|
||||
void * IVSHMEM::GetMemory()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return NULL;
|
||||
|
||||
if (m_gotMemory)
|
||||
return m_memory;
|
||||
|
||||
// this if define can be removed later once everyone is un the latest version
|
||||
// old versions of the IVSHMEM driver ignore the input argument, as such this
|
||||
// is completely backwards compatible
|
||||
#if defined(IVSHMEM_CACHE_WRITECOMBINED)
|
||||
IVSHMEM_MMAP_CONFIG config;
|
||||
config.cacheMode = IVSHMEM_CACHE_WRITECOMBINED;
|
||||
#endif
|
||||
|
||||
IVSHMEM_MMAP map;
|
||||
ZeroMemory(&map, sizeof(IVSHMEM_MMAP));
|
||||
if (!DeviceIoControl(
|
||||
m_handle,
|
||||
IOCTL_IVSHMEM_REQUEST_MMAP,
|
||||
#if defined(IVSHMEM_CACHE_WRITECOMBINED)
|
||||
&config, sizeof(IVSHMEM_MMAP_CONFIG),
|
||||
#else
|
||||
NULL , 0,
|
||||
#endif
|
||||
&map , sizeof(IVSHMEM_MMAP ),
|
||||
NULL, NULL))
|
||||
{
|
||||
DEBUG_ERROR("DeviceIoControl Failed: %d", (int)GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_gotSize = true;
|
||||
m_gotPeerID = true;
|
||||
m_gotMemory = true;
|
||||
m_gotVectors = true;
|
||||
m_size = static_cast<UINT64>(map.size );
|
||||
m_peerID = static_cast<UINT16>(map.peerID );
|
||||
m_vectors = static_cast<UINT16>(map.vectors);
|
||||
m_memory = map.ptr;
|
||||
|
||||
return m_memory;
|
||||
}
|
||||
|
||||
HANDLE IVSHMEM::CreateVectorEvent(UINT16 vector)
|
||||
{
|
||||
if (!m_initialized)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (event == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DEBUG_ERROR("CreateEvent Failed: %d", (int)GetLastError());
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
IVSHMEM_EVENT msg;
|
||||
msg.event = event;
|
||||
msg.singleShot = false;
|
||||
msg.vector = vector;
|
||||
|
||||
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REGISTER_EVENT, &msg, sizeof(IVSHMEM_EVENT), NULL, 0, NULL, NULL))
|
||||
{
|
||||
DEBUG_ERROR("DeviceIoControl Failed: %d", (int)GetLastError());
|
||||
CloseHandle(event);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
bool IVSHMEM::RingDoorbell(UINT16 peerID, UINT16 door)
|
||||
{
|
||||
if (!m_initialized)
|
||||
return false;
|
||||
|
||||
IVSHMEM_RING msg;
|
||||
msg.peerID = peerID;
|
||||
msg.vector = door;
|
||||
|
||||
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_RING_DOORBELL, &msg, sizeof(IVSHMEM_RING), NULL, 0, NULL, NULL))
|
||||
{
|
||||
DEBUG_ERROR("DeviceIoControl Failed: %d", (int)GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define W32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct PCI_DEVICE {
|
||||
BYTE bus, addr, func;
|
||||
};
|
||||
|
||||
class IVSHMEM
|
||||
{
|
||||
public:
|
||||
static IVSHMEM * Get()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new IVSHMEM();
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
static void listDevices();
|
||||
|
||||
bool Initialize(PCI_DEVICE dev);
|
||||
void DeInitialize();
|
||||
bool IsInitialized();
|
||||
|
||||
UINT64 GetSize();
|
||||
UINT16 GetPeerID();
|
||||
UINT16 GetVectors();
|
||||
void * GetMemory();
|
||||
HANDLE CreateVectorEvent(UINT16 vector);
|
||||
bool RingDoorbell(UINT16 peerID, UINT16 door);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
private:
|
||||
static IVSHMEM * m_instance;
|
||||
|
||||
IVSHMEM();
|
||||
~IVSHMEM();
|
||||
|
||||
bool m_initialized;
|
||||
HANDLE m_handle;
|
||||
|
||||
UINT64 m_size ; bool m_gotSize ;
|
||||
UINT16 m_peerID ; bool m_gotPeerID;
|
||||
void * m_memory ; bool m_gotMemory;
|
||||
UINT16 m_vectors; bool m_gotVectors;
|
||||
};
|
@ -1,60 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "looking-glass-host", "looking-glass-host.vcxproj", "{D439DE3E-32FB-4599-8B5D-C92674D400D4}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sync-test", "sync-test\sync-test.vcxproj", "{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BE5778A4-4447-410B-B8E8-D86087F62CFD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug - NvFBC|x64 = Debug - NvFBC|x64
|
||||
Debug - NvFBC|x86 = Debug - NvFBC|x86
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release - NvFBC|x64 = Release - NvFBC|x64
|
||||
Release - NvFBC|x86 = Release - NvFBC|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug - NvFBC|x64.ActiveCfg = Debug - NvFBC|x64
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug - NvFBC|x64.Build.0 = Debug - NvFBC|x64
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug - NvFBC|x86.ActiveCfg = Debug - NvFBC|Win32
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug - NvFBC|x86.Build.0 = Debug - NvFBC|Win32
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug|x64.Build.0 = Debug|x64
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release - NvFBC|x64.ActiveCfg = Release - NvFBC|x64
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release - NvFBC|x64.Build.0 = Release - NvFBC|x64
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release - NvFBC|x86.ActiveCfg = Release - NvFBC|Win32
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release - NvFBC|x86.Build.0 = Release - NvFBC|Win32
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release|x64.ActiveCfg = Release|x64
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release|x64.Build.0 = Release|x64
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D439DE3E-32FB-4599-8B5D-C92674D400D4}.Release|x86.Build.0 = Release|Win32
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug - NvFBC|x64.ActiveCfg = Debug - NvFBC|x64
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug - NvFBC|x64.Build.0 = Debug - NvFBC|x64
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug - NvFBC|x86.ActiveCfg = Debug - NvFBC|Win32
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug - NvFBC|x86.Build.0 = Debug - NvFBC|Win32
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug|x64.Build.0 = Debug|x64
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release - NvFBC|x64.ActiveCfg = Release - NvFBC|x64
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release - NvFBC|x64.Build.0 = Release - NvFBC|x64
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release - NvFBC|x86.ActiveCfg = Release - NvFBC|Win32
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release - NvFBC|x86.Build.0 = Release - NvFBC|Win32
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release|x64.ActiveCfg = Release|x64
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release|x64.Build.0 = Release|x64
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -1,453 +0,0 @@
|
||||
/*
|
||||
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 "MFT/H264.h"
|
||||
|
||||
#include "WinDebug.h"
|
||||
#include "common/memcpySSE.h"
|
||||
|
||||
#include <mfapi.h>
|
||||
#include <mfidl.h>
|
||||
#include <mfreadwrite.h>
|
||||
#include <wmcodecdsp.h>
|
||||
#include <codecapi.h>
|
||||
#include <mferror.h>
|
||||
#include <evr.h>
|
||||
|
||||
using namespace MFT;
|
||||
|
||||
#if __MINGW32__
|
||||
EXTERN_GUID(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 0xa634a91c, 0x822b, 0x41b9, 0xa4, 0x94, 0x4d, 0xe4, 0x64, 0x36, 0x12, 0xb0);
|
||||
EXTERN_GUID(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, 0xf81da2c, 0xb537, 0x4672, 0xa8, 0xb2, 0xa6, 0x81, 0xb1, 0x73, 0x07, 0xa3);
|
||||
EXTERN_GUID(MF_SA_D3D11_AWARE, 0x206b4fc8, 0xfcf9, 0x4c51, 0xaf, 0xe3, 0x97, 0x64, 0x36, 0x9e, 0x33, 0xa0);
|
||||
|
||||
#define METransformUnknown 600
|
||||
#define METransformNeedInput 601
|
||||
#define METransformHaveOutput 602
|
||||
#define METransformDrainComplete 603
|
||||
#define METransformMarker 604
|
||||
#endif
|
||||
|
||||
MFT::H264::H264() :
|
||||
m_cRef(1)
|
||||
{
|
||||
MFStartup(MF_VERSION);
|
||||
}
|
||||
|
||||
MFT::H264::~H264()
|
||||
{
|
||||
DeInitialize();
|
||||
}
|
||||
|
||||
bool MFT::H264::Initialize(ID3D11DevicePtr device, unsigned int width, unsigned int height)
|
||||
{
|
||||
DeInitialize();
|
||||
HRESULT status;
|
||||
|
||||
MFT_REGISTER_TYPE_INFO typeInfo;
|
||||
IMFActivate **activationPointers;
|
||||
UINT32 activationPointerCount;
|
||||
|
||||
m_device = device;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
|
||||
m_encodeEvent = CreateEvent(NULL, TRUE , FALSE, NULL);
|
||||
m_shutdownEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
InitializeCriticalSection(&m_encodeCS);
|
||||
|
||||
ID3D10MultithreadPtr mt(m_device);
|
||||
mt->SetMultithreadProtected(TRUE);
|
||||
mt = NULL;
|
||||
|
||||
typeInfo.guidMajorType = MFMediaType_Video;
|
||||
typeInfo.guidSubtype = MFVideoFormat_H264;
|
||||
|
||||
status = MFTEnumEx(
|
||||
MFT_CATEGORY_VIDEO_ENCODER,
|
||||
MFT_ENUM_FLAG_HARDWARE,
|
||||
NULL,
|
||||
&typeInfo,
|
||||
&activationPointers,
|
||||
&activationPointerCount
|
||||
);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to enumerate encoder MFTs", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (activationPointerCount == 0)
|
||||
{
|
||||
DEBUG_WINERROR("Hardware H264 MFT not available", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
UINT32 nameLen = 0;
|
||||
activationPointers[0]->GetStringLength(MFT_FRIENDLY_NAME_Attribute, &nameLen);
|
||||
wchar_t * name = new wchar_t[nameLen + 1];
|
||||
activationPointers[0]->GetString(MFT_FRIENDLY_NAME_Attribute, name, nameLen + 1, NULL);
|
||||
DEBUG_INFO("Using Encoder: %S", name);
|
||||
delete[] name;
|
||||
}
|
||||
|
||||
m_mfActivation = activationPointers[0];
|
||||
CoTaskMemFree(activationPointers);
|
||||
|
||||
status = m_mfActivation->ActivateObject(IID_PPV_ARGS(&m_mfTransform));
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create H264 encoder MFT", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
IMFAttributesPtr attribs;
|
||||
m_mfTransform->GetAttributes(&attribs);
|
||||
attribs->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
|
||||
attribs->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, TRUE);
|
||||
attribs->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, TRUE);
|
||||
attribs->SetUINT32(MF_LOW_LATENCY, TRUE);
|
||||
|
||||
UINT32 d3d11Aware = 0;
|
||||
UINT32 async = 0;
|
||||
attribs->GetUINT32(MF_TRANSFORM_ASYNC, &async);
|
||||
attribs->GetUINT32(MF_SA_D3D11_AWARE, &d3d11Aware);
|
||||
if (async)
|
||||
attribs->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
|
||||
attribs = NULL;
|
||||
|
||||
status = m_mfTransform.QueryInterface(IID_PPV_ARGS(&m_mediaEventGen));
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to obtain the media event generator interface", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
status = m_mediaEventGen->BeginGetEvent(this, NULL);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to set the begin get event", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d3d11Aware)
|
||||
{
|
||||
MFCreateDXGIDeviceManager(&m_resetToken, &m_mfDeviceManager);
|
||||
status = m_mfDeviceManager->ResetDevice(m_device, m_resetToken);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to call reset device", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
status = m_mfTransform->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, ULONG_PTR(m_mfDeviceManager.GetInterfacePtr()));
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to set the D3D manager", status);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
IMFMediaTypePtr outType;
|
||||
MFCreateMediaType(&outType);
|
||||
|
||||
outType->SetGUID (MF_MT_MAJOR_TYPE , MFMediaType_Video );
|
||||
outType->SetGUID (MF_MT_SUBTYPE , MFVideoFormat_H264 );
|
||||
outType->SetUINT32(MF_MT_AVG_BITRATE , 384 * 1000 );
|
||||
outType->SetUINT32(MF_MT_INTERLACE_MODE , MFVideoInterlace_Progressive);
|
||||
outType->SetUINT32(MF_MT_MPEG2_PROFILE , eAVEncH264VProfile_High );
|
||||
outType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
|
||||
|
||||
MFSetAttributeSize (outType, MF_MT_FRAME_SIZE , m_width, m_height);
|
||||
MFSetAttributeRatio(outType, MF_MT_FRAME_RATE , 60 , 1 );
|
||||
MFSetAttributeRatio(outType, MF_MT_PIXEL_ASPECT_RATIO, 1 , 1 );
|
||||
|
||||
status = m_mfTransform->SetOutputType(0, outType, 0);
|
||||
outType = NULL;
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to set the output media type on the H264 encoder MFT", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
IMFMediaTypePtr inType;
|
||||
MFCreateMediaType(&inType);
|
||||
|
||||
inType->SetGUID (MF_MT_MAJOR_TYPE , MFMediaType_Video );
|
||||
inType->SetGUID (MF_MT_SUBTYPE , MFVideoFormat_NV12 );
|
||||
inType->SetUINT32(MF_MT_INTERLACE_MODE , MFVideoInterlace_Progressive);
|
||||
inType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE );
|
||||
|
||||
MFSetAttributeSize (inType, MF_MT_FRAME_SIZE , m_width, m_height);
|
||||
MFSetAttributeRatio(inType, MF_MT_FRAME_RATE , 60 , 1 );
|
||||
MFSetAttributeRatio(inType, MF_MT_PIXEL_ASPECT_RATIO, 1 , 1 );
|
||||
|
||||
status = m_mfTransform->SetInputType(0, inType, 0);
|
||||
inType = NULL;
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to set the input media type on the H264 encoder MFT", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_mfTransform->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0);
|
||||
m_mfTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
|
||||
m_mfTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MFT::H264::DeInitialize()
|
||||
{
|
||||
if (m_mediaEventGen)
|
||||
{
|
||||
m_mfTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0);
|
||||
m_mfTransform->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0);
|
||||
while (WaitForSingleObject(m_shutdownEvent, INFINITE) != WAIT_OBJECT_0) {}
|
||||
m_mfTransform->DeleteInputStream(0);
|
||||
}
|
||||
|
||||
m_mediaEventGen = NULL;
|
||||
m_mfTransform = NULL;
|
||||
m_mfDeviceManager = NULL;
|
||||
|
||||
if (m_encodeEvent)
|
||||
{
|
||||
CloseHandle(m_encodeEvent );
|
||||
CloseHandle(m_shutdownEvent);
|
||||
m_encodeEvent = NULL;
|
||||
m_shutdownEvent = NULL;
|
||||
DeleteCriticalSection(&m_encodeCS);
|
||||
}
|
||||
|
||||
if (m_mfActivation)
|
||||
{
|
||||
m_mfActivation->ShutdownObject();
|
||||
m_mfActivation = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int MFT::H264::Process()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
// only reset the event if there isn't work pending
|
||||
EnterCriticalSection(&m_encodeCS);
|
||||
if (!m_encodeHasData && !m_encodeNeedsData)
|
||||
ResetEvent(m_encodeEvent);
|
||||
LeaveCriticalSection(&m_encodeCS);
|
||||
|
||||
switch (WaitForSingleObject(m_encodeEvent, 1000))
|
||||
{
|
||||
case WAIT_FAILED:
|
||||
DEBUG_WINERROR("Wait for encode event failed", GetLastError());
|
||||
return H264_EVENT_ERROR;
|
||||
|
||||
case WAIT_ABANDONED:
|
||||
DEBUG_ERROR("Wait abandoned");
|
||||
return H264_EVENT_ERROR;
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
continue;
|
||||
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int events = 0;
|
||||
EnterCriticalSection(&m_encodeCS);
|
||||
if (m_encodeNeedsData) events |= H264_EVENT_NEEDS_DATA;
|
||||
if (m_encodeHasData ) events |= H264_EVENT_HAS_DATA;
|
||||
LeaveCriticalSection(&m_encodeCS);
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
return H264_EVENT_ERROR;
|
||||
}
|
||||
|
||||
bool MFT::H264::ProvideFrame(ID3D11Texture2DPtr texture)
|
||||
{
|
||||
EnterCriticalSection(&m_encodeCS);
|
||||
if (!m_encodeNeedsData)
|
||||
{
|
||||
LeaveCriticalSection(&m_encodeCS);
|
||||
return false;
|
||||
}
|
||||
m_encodeNeedsData = false;
|
||||
LeaveCriticalSection(&m_encodeCS);
|
||||
|
||||
HRESULT status;
|
||||
IMFMediaBufferPtr buffer;
|
||||
status = MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), texture, 0, FALSE, &buffer);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create DXGI surface buffer from texture", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
IMF2DBufferPtr imfBuffer(buffer);
|
||||
DWORD length;
|
||||
imfBuffer->GetContiguousLength(&length);
|
||||
buffer->SetCurrentLength(length);
|
||||
|
||||
IMFSamplePtr sample;
|
||||
MFCreateSample(&sample);
|
||||
sample->AddBuffer(buffer);
|
||||
|
||||
status = m_mfTransform->ProcessInput(0, sample, 0);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to process the input", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MFT::H264::GetFrame(void * buffer, const size_t bufferSize, unsigned int & dataLen)
|
||||
{
|
||||
EnterCriticalSection(&m_encodeCS);
|
||||
if (!m_encodeHasData)
|
||||
{
|
||||
LeaveCriticalSection(&m_encodeCS);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_encodeHasData = false;
|
||||
LeaveCriticalSection(&m_encodeCS);
|
||||
|
||||
HRESULT status;
|
||||
MFT_OUTPUT_STREAM_INFO streamInfo;
|
||||
status = m_mfTransform->GetOutputStreamInfo(0, &streamInfo);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("GetOutputStreamInfo", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD outStatus;
|
||||
MFT_OUTPUT_DATA_BUFFER outDataBuffer = { 0 };
|
||||
status = m_mfTransform->ProcessOutput(0, 1, &outDataBuffer, &outStatus);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("ProcessOutput", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
IMFMediaBufferPtr mb;
|
||||
outDataBuffer.pSample->ConvertToContiguousBuffer(&mb);
|
||||
|
||||
BYTE *pixels;
|
||||
DWORD curLen;
|
||||
mb->Lock(&pixels, NULL, &curLen);
|
||||
memcpy(buffer, pixels, curLen);
|
||||
mb->Unlock();
|
||||
|
||||
if (outDataBuffer.pSample)
|
||||
outDataBuffer.pSample->Release();
|
||||
|
||||
if (outDataBuffer.pEvents)
|
||||
outDataBuffer.pEvents->Release();
|
||||
|
||||
dataLen = curLen;
|
||||
return true;
|
||||
}
|
||||
|
||||
STDMETHODIMP MFT::H264::Invoke(IMFAsyncResult * pAsyncResult)
|
||||
{
|
||||
HRESULT status, evtStatus;
|
||||
MediaEventType meType = MEUnknown;
|
||||
IMFMediaEventPtr pEvent = NULL;
|
||||
|
||||
status = m_mediaEventGen->EndGetEvent(pAsyncResult, &pEvent);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("EndGetEvent", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = pEvent->GetStatus(&evtStatus);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("GetStatus", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (FAILED(evtStatus))
|
||||
{
|
||||
DEBUG_WINERROR("evtStatus", evtStatus);
|
||||
return evtStatus;
|
||||
}
|
||||
|
||||
status = pEvent->GetType(&meType);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("GetType", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
switch (meType)
|
||||
{
|
||||
case METransformNeedInput:
|
||||
EnterCriticalSection(&m_encodeCS);
|
||||
m_encodeNeedsData = true;
|
||||
SetEvent(m_encodeEvent);
|
||||
LeaveCriticalSection(&m_encodeCS);
|
||||
break;
|
||||
|
||||
case METransformHaveOutput:
|
||||
EnterCriticalSection(&m_encodeCS);
|
||||
m_encodeHasData = true;
|
||||
SetEvent(m_encodeEvent);
|
||||
LeaveCriticalSection(&m_encodeCS);
|
||||
break;
|
||||
|
||||
case METransformDrainComplete:
|
||||
{
|
||||
status = m_mfTransform->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("MFT_MESSAGE_COMMAND_FLUSH", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
SetEvent(m_shutdownEvent);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
case MEError:
|
||||
DEBUG_INFO("err");
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_INFO("unk");
|
||||
break;
|
||||
}
|
||||
|
||||
status = m_mediaEventGen->BeginGetEvent(this, NULL);
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("BeginGetEvent", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
101
host/MFT/H264.h
101
host/MFT/H264.h
@ -1,101 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define W32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <shlwapi.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Com.h"
|
||||
|
||||
namespace MFT
|
||||
{
|
||||
enum H264_Event
|
||||
{
|
||||
H264_EVENT_ENCODE = 0x01,
|
||||
H264_EVENT_NEEDS_DATA = 0x04,
|
||||
H264_EVENT_HAS_DATA = 0x08,
|
||||
H264_EVENT_ERROR = 0x10
|
||||
};
|
||||
|
||||
class H264: public IMFAsyncCallback
|
||||
{
|
||||
public:
|
||||
H264();
|
||||
~H264();
|
||||
bool Initialize(ID3D11DevicePtr device, unsigned int width, unsigned int height);
|
||||
void DeInitialize();
|
||||
unsigned int Process();
|
||||
bool ProvideFrame(ID3D11Texture2DPtr texture);
|
||||
bool GetFrame(void * buffer, const size_t bufferSize, unsigned int & dataLen);
|
||||
|
||||
ID3D11DevicePtr m_device;
|
||||
unsigned int m_width;
|
||||
unsigned int m_height;
|
||||
|
||||
HANDLE m_encodeEvent;
|
||||
HANDLE m_shutdownEvent;
|
||||
bool m_encodeNeedsData;
|
||||
bool m_encodeHasData;
|
||||
CRITICAL_SECTION m_encodeCS;
|
||||
|
||||
UINT m_resetToken;
|
||||
IMFDXGIDeviceManagerPtr m_mfDeviceManager;
|
||||
IMFActivatePtr m_mfActivation;
|
||||
IMFTransformPtr m_mfTransform;
|
||||
IMFMediaEventGeneratorPtr m_mediaEventGen;
|
||||
|
||||
/*
|
||||
Junk needed for the horrid IMFAsyncCallback interface
|
||||
*/
|
||||
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv)
|
||||
{
|
||||
if (riid == __uuidof(IUnknown) || riid == __uuidof(IMFAsyncCallback)) {
|
||||
*ppv = static_cast<IMFAsyncCallback*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
else {
|
||||
*ppv = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) AddRef()
|
||||
{
|
||||
return InterlockedIncrement(&m_cRef);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) Release()
|
||||
{
|
||||
long cRef = InterlockedDecrement(&m_cRef);
|
||||
if (!cRef)
|
||||
delete this;
|
||||
return cRef;
|
||||
}
|
||||
|
||||
STDMETHODIMP GetParameters(DWORD *pdwFlags, DWORD *pdwQueue) { return E_NOTIMPL; }
|
||||
STDMETHODIMP Invoke(IMFAsyncResult *pAsyncResult);
|
||||
|
||||
private:
|
||||
long m_cRef;
|
||||
};
|
||||
};
|
@ -1,59 +0,0 @@
|
||||
BINARY = looking-glass-host.exe
|
||||
CFLAGS = -g -O3 -march=native -Wall -Werror -I./ -I../common # -DDEBUG
|
||||
LDFLAGS = -lshlwapi -ldxgi -ld3d11 -lsetupapi -luuid -lole32 -lmfplat -lmfuuid
|
||||
|
||||
CFLAGS += -ffast-math
|
||||
CFLAGS += -fdata-sections -ffunction-sections
|
||||
CFLAGS += -I../ -I.
|
||||
LDFLAGS += -Wl,--gc-sections -mwindows
|
||||
CFLAGS += -DWINVER=0x0602 -DUNICODE
|
||||
|
||||
PREFIX ?= x86_64-w64-mingw32-
|
||||
STRIP = $(PREFIX)strip
|
||||
CC = $(PREFIX)cc
|
||||
CXX = $(PREFIX)c++
|
||||
LD = $(CXX)
|
||||
|
||||
BUILD ?= .build
|
||||
BIN ?= bin
|
||||
|
||||
CFLAGS += -DBUILD_VERSION='"$(shell git describe --always --long --dirty --abbrev=10 --tags)"'
|
||||
|
||||
OBJS = main.o \
|
||||
CrashHandler.o \
|
||||
MultiMemcpy.o \
|
||||
IVSHMEM.o \
|
||||
Service.o \
|
||||
Capture/DXGI.o
|
||||
|
||||
ifeq ($(ENABLE_TRACING),1)
|
||||
CFLAGS += -DENABLE_TRACING
|
||||
OBJS += TraceUtil.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CAPTURE_NVFBC),1)
|
||||
CFLAGS += -DCONFIG_CAPTURE_NVFBC=1 -I../vendor
|
||||
OBJS += Capture/NvFBC.o
|
||||
endif
|
||||
|
||||
BUILD_OBJS = $(foreach obj,$(OBJS),$(BUILD)/$(obj))
|
||||
|
||||
all: $(BIN)/$(BINARY)
|
||||
|
||||
$(BUILD)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
$(BUILD)/%.o: %.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
$(CXX) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
$(BIN)/$(BINARY): $(BUILD_OBJS)
|
||||
@mkdir -p $(dir $@)
|
||||
$(LD) -o $@ $^ $(LDFLAGS)
|
||||
$(STRIP) -s $@
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD) $(BIN)
|
||||
|
||||
.PHONY: clean
|
391
host/Service.cpp
391
host/Service.cpp
@ -1,391 +0,0 @@
|
||||
/*
|
||||
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 "Service.h"
|
||||
#include "IVSHMEM.h"
|
||||
#include "TraceUtil.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/KVMFR.h"
|
||||
|
||||
#include "Util.h"
|
||||
#include "CaptureFactory.h"
|
||||
|
||||
PCI_DEVICE Service::s_dev = {0x13, 0x01, 0x00};
|
||||
|
||||
Service::Service() :
|
||||
m_initialized(false),
|
||||
m_memory(NULL),
|
||||
m_timer(NULL),
|
||||
m_capture(NULL),
|
||||
m_shmHeader(NULL),
|
||||
m_frameIndex(0),
|
||||
m_cursorDataSize(0),
|
||||
m_cursorData(NULL)
|
||||
{
|
||||
m_consoleSessionID = WTSGetActiveConsoleSessionId();
|
||||
m_ivshmem = IVSHMEM::Get();
|
||||
|
||||
if (!m_ivshmem->Initialize(s_dev))
|
||||
throw "IVSHMEM failed to initalize";
|
||||
|
||||
if (m_ivshmem->GetSize() < sizeof(KVMFRHeader))
|
||||
throw "Shared memory is not large enough for the KVMFRHeader";
|
||||
|
||||
m_memory = static_cast<uint8_t*>(m_ivshmem->GetMemory());
|
||||
if (!m_memory)
|
||||
throw "Failed to get IVSHMEM memory";
|
||||
|
||||
if (!InitPointers())
|
||||
throw "Failed to initialize the shared memory pointers";
|
||||
}
|
||||
|
||||
Service::~Service()
|
||||
{
|
||||
DeInitialize();
|
||||
}
|
||||
|
||||
LRESULT Service::LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (nCode == HC_ACTION && wParam == WM_MOUSEMOVE)
|
||||
{
|
||||
MSLLHOOKSTRUCT *msg = (MSLLHOOKSTRUCT *)lParam;
|
||||
volatile KVMFRCursor * cursor = &(m_shmHeader->cursor);
|
||||
volatile char * flags = (volatile char *)&(cursor->flags);
|
||||
|
||||
cursor->x = (int16_t)msg->pt.x;
|
||||
cursor->y = (int16_t)msg->pt.y;
|
||||
INTERLOCKED_OR8(flags, KVMFR_CURSOR_FLAG_POS);
|
||||
}
|
||||
return CallNextHookEx(m_mouseHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
bool Service::Initialize(ICapture * captureDevice)
|
||||
{
|
||||
if (m_initialized)
|
||||
DeInitialize();
|
||||
|
||||
m_tryTarget = 0;
|
||||
m_capture = captureDevice;
|
||||
|
||||
if (m_capture->GetMaxFrameSize() > m_frameSize)
|
||||
{
|
||||
DEBUG_ERROR("Maximum frame size of %zu bytes excceds maximum space available", m_capture->GetMaxFrameSize());
|
||||
DeInitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the cursor thread
|
||||
m_cursorThread = CreateThread(NULL, 0, _CursorThread, NULL, 0, NULL);
|
||||
m_cursorEvent = CreateEvent (NULL, FALSE, FALSE, L"CursorEvent");
|
||||
InitializeCriticalSection(&m_cursorCS);
|
||||
|
||||
// update everything except for the hostID
|
||||
memcpy(m_shmHeader->magic, KVMFR_HEADER_MAGIC, sizeof(KVMFR_HEADER_MAGIC));
|
||||
m_shmHeader->version = KVMFR_HEADER_VERSION;
|
||||
|
||||
// zero and tell the client we have restarted
|
||||
ZeroMemory(&(m_shmHeader->frame ), sizeof(KVMFRFrame ));
|
||||
ZeroMemory(&(m_shmHeader->cursor), sizeof(KVMFRCursor));
|
||||
m_shmHeader->flags &= ~KVMFR_HEADER_FLAG_RESTART;
|
||||
|
||||
m_haveFrame = false;
|
||||
m_initialized = true;
|
||||
m_running = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ALIGN_DN(x) ((uintptr_t)(x) & ~0x7F)
|
||||
#define ALIGN_UP(x) ALIGN_DN(x + 0x7F)
|
||||
|
||||
bool Service::InitPointers()
|
||||
{
|
||||
m_shmHeader = reinterpret_cast<KVMFRHeader *>(m_memory);
|
||||
m_cursorData = (uint8_t *)ALIGN_UP(m_memory + sizeof(KVMFRHeader));
|
||||
m_cursorDataSize = 1048576; // 1MB fixed for cursor size, should be more then enough
|
||||
m_cursorOffset = m_cursorData - m_memory;
|
||||
|
||||
uint8_t * m_frames = (uint8_t *)ALIGN_UP(m_cursorData + m_cursorDataSize);
|
||||
m_frameSize = ALIGN_DN((m_ivshmem->GetSize() - (m_frames - m_memory)) / MAX_FRAMES);
|
||||
|
||||
DEBUG_INFO("Total Available : %3u MB", (unsigned int)(m_ivshmem->GetSize() / 1024 / 1024));
|
||||
DEBUG_INFO("Max Cursor Size : %3u MB", (unsigned int)(m_cursorDataSize / 1024 / 1024));
|
||||
DEBUG_INFO("Max Frame Size : %3u MB", (unsigned int)(m_frameSize / 1024 / 1024));
|
||||
DEBUG_INFO("Cursor : %p (0x%08x)", m_cursorData, (int)m_cursorOffset);
|
||||
|
||||
for (int i = 0; i < MAX_FRAMES; ++i)
|
||||
{
|
||||
m_frame[i] = m_frames + i * m_frameSize;
|
||||
m_dataOffset[i] = m_frame[i] - m_memory;
|
||||
DEBUG_INFO("Frame %d : %p (0x%08x)", i, m_frame[i], (int)m_dataOffset[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Service::DeInitialize()
|
||||
{
|
||||
m_running = false;
|
||||
|
||||
WaitForSingleObject(m_cursorThread, INFINITE);
|
||||
CloseHandle(m_cursorThread);
|
||||
CloseHandle(m_cursorEvent);
|
||||
|
||||
m_shmHeader = NULL;
|
||||
m_cursorData = NULL;
|
||||
m_cursorDataSize = 0;
|
||||
m_cursorOffset = 0;
|
||||
m_haveFrame = false;
|
||||
|
||||
for(int i = 0; i < MAX_FRAMES; ++i)
|
||||
{
|
||||
m_frame [i] = NULL;
|
||||
m_dataOffset[i] = 0;
|
||||
}
|
||||
m_frameSize = 0;
|
||||
|
||||
m_ivshmem->DeInitialize();
|
||||
|
||||
if (m_capture)
|
||||
{
|
||||
m_capture->DeInitialize();
|
||||
m_capture = NULL;
|
||||
}
|
||||
|
||||
m_memory = NULL;
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
bool Service::ReInit(volatile char * flags)
|
||||
{
|
||||
DEBUG_INFO("ReInitialize Requested");
|
||||
|
||||
INTERLOCKED_OR8(flags, KVMFR_HEADER_FLAG_PAUSED);
|
||||
if (WTSGetActiveConsoleSessionId() != m_consoleSessionID)
|
||||
{
|
||||
DEBUG_INFO("User switch detected, waiting to regain control");
|
||||
while (WTSGetActiveConsoleSessionId() != m_consoleSessionID)
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
while (!m_capture->CanInitialize())
|
||||
Sleep(100);
|
||||
|
||||
if (!m_capture->ReInitialize())
|
||||
{
|
||||
DEBUG_ERROR("ReInitialize Failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_capture->GetMaxFrameSize() > m_frameSize)
|
||||
{
|
||||
DEBUG_ERROR("Maximum frame size of %zd bytes excceds maximum space available", m_capture->GetMaxFrameSize());
|
||||
return false;
|
||||
}
|
||||
|
||||
INTERLOCKED_AND8(flags, ~KVMFR_HEADER_FLAG_PAUSED);
|
||||
return true;
|
||||
}
|
||||
|
||||
ProcessStatus Service::Process()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return PROCESS_STATUS_ERROR;
|
||||
|
||||
volatile char * flags = (volatile char *)&(m_shmHeader->flags);
|
||||
|
||||
// check if the client has flagged a restart
|
||||
if (*flags & KVMFR_HEADER_FLAG_RESTART)
|
||||
{
|
||||
DEBUG_INFO("Restart Requested");
|
||||
if (!m_capture->ReInitialize())
|
||||
{
|
||||
DEBUG_ERROR("ReInitialize Failed");
|
||||
return PROCESS_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (m_capture->GetMaxFrameSize() > m_frameSize)
|
||||
{
|
||||
DEBUG_ERROR("Maximum frame size of %zd bytes exceeds maximum space available", m_capture->GetMaxFrameSize());
|
||||
return PROCESS_STATUS_ERROR;
|
||||
}
|
||||
|
||||
INTERLOCKED_AND8(flags, ~(KVMFR_HEADER_FLAG_RESTART));
|
||||
}
|
||||
|
||||
unsigned int status;
|
||||
bool notify = false;
|
||||
|
||||
status = m_capture->Capture();
|
||||
if (status & GRAB_STATUS_ERROR)
|
||||
{
|
||||
DEBUG_WARN("Capture error, retrying");
|
||||
return PROCESS_STATUS_RETRY;
|
||||
}
|
||||
|
||||
if (status & GRAB_STATUS_TIMEOUT)
|
||||
{
|
||||
// timeouts should not count towards a failure to capture
|
||||
if (!m_haveFrame)
|
||||
return PROCESS_STATUS_OK;
|
||||
|
||||
notify = true;
|
||||
}
|
||||
|
||||
if (status & GRAB_STATUS_REINIT)
|
||||
{
|
||||
if (!ReInit(flags))
|
||||
return PROCESS_STATUS_ERROR;
|
||||
|
||||
// re-init request should not count towards a failure to capture
|
||||
return PROCESS_STATUS_OK;
|
||||
}
|
||||
|
||||
if ((status & (GRAB_STATUS_OK | GRAB_STATUS_TIMEOUT)) == 0)
|
||||
{
|
||||
DEBUG_ERROR("Capture interface returned an unexpected result");
|
||||
return PROCESS_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (status & GRAB_STATUS_CURSOR)
|
||||
SetEvent(m_cursorEvent);
|
||||
|
||||
volatile KVMFRFrame * fi = &(m_shmHeader->frame);
|
||||
if (status & GRAB_STATUS_FRAME)
|
||||
{
|
||||
FrameInfo frame = { 0 };
|
||||
frame.buffer = m_frame[m_frameIndex];
|
||||
frame.bufferSize = m_frameSize;
|
||||
|
||||
GrabStatus result = m_capture->GetFrame(frame);
|
||||
if (result != GRAB_STATUS_OK)
|
||||
{
|
||||
if (result == GRAB_STATUS_REINIT)
|
||||
{
|
||||
if (!ReInit(flags))
|
||||
return PROCESS_STATUS_ERROR;
|
||||
|
||||
// re-init request should not count towards a failure to capture
|
||||
return PROCESS_STATUS_OK;
|
||||
}
|
||||
|
||||
DEBUG_INFO("GetFrame failed");
|
||||
return PROCESS_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* don't touch the frame information until the client is done with it */
|
||||
while (fi->flags & KVMFR_FRAME_FLAG_UPDATE)
|
||||
{
|
||||
/* this generally never occurs */
|
||||
Sleep(1);
|
||||
if (*flags & KVMFR_HEADER_FLAG_RESTART)
|
||||
break;
|
||||
}
|
||||
|
||||
fi->type = m_capture->GetFrameType();
|
||||
fi->width = frame.width;
|
||||
fi->height = frame.height;
|
||||
fi->stride = frame.stride;
|
||||
fi->pitch = frame.pitch;
|
||||
fi->dataPos = m_dataOffset[m_frameIndex];
|
||||
|
||||
if (++m_frameIndex == MAX_FRAMES)
|
||||
m_frameIndex = 0;
|
||||
|
||||
// remember that we have a valid frame
|
||||
m_haveFrame = true;
|
||||
notify = true;
|
||||
}
|
||||
|
||||
if (notify)
|
||||
{
|
||||
/* don't touch the frame inforamtion until the client is done with it */
|
||||
while (fi->flags & KVMFR_FRAME_FLAG_UPDATE)
|
||||
{
|
||||
if (*flags & KVMFR_HEADER_FLAG_RESTART)
|
||||
break;
|
||||
}
|
||||
// signal a frame update
|
||||
fi->flags |= KVMFR_FRAME_FLAG_UPDATE;
|
||||
}
|
||||
|
||||
// update the flags
|
||||
INTERLOCKED_AND8(flags, KVMFR_HEADER_FLAG_RESTART);
|
||||
return PROCESS_STATUS_OK;
|
||||
}
|
||||
|
||||
DWORD Service::CursorThread()
|
||||
{
|
||||
while(m_running)
|
||||
{
|
||||
if (WaitForSingleObject(m_cursorEvent, 1000) != WAIT_OBJECT_0)
|
||||
continue;
|
||||
|
||||
CursorInfo ci;
|
||||
while (m_capture->GetCursor(ci))
|
||||
{
|
||||
volatile KVMFRCursor * cursor = &(m_shmHeader->cursor);
|
||||
// wait until the client is ready
|
||||
while ((cursor->flags & ~KVMFR_CURSOR_FLAG_POS) != 0)
|
||||
{
|
||||
Sleep(1);
|
||||
if (!m_capture)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t flags = cursor->flags;
|
||||
|
||||
if (ci.hasPos)
|
||||
{
|
||||
cursor->x = ci.x;
|
||||
cursor->y = ci.y;
|
||||
flags |= KVMFR_CURSOR_FLAG_POS;
|
||||
}
|
||||
|
||||
if (ci.hasShape)
|
||||
{
|
||||
if (ci.shape.pointerSize > m_cursorDataSize)
|
||||
DEBUG_ERROR("Cursor size exceeds allocated space");
|
||||
else
|
||||
{
|
||||
// give the client the new cursor shape
|
||||
flags |= KVMFR_CURSOR_FLAG_SHAPE;
|
||||
++cursor->version;
|
||||
|
||||
cursor->type = ci.type;
|
||||
cursor->width = ci.w;
|
||||
cursor->height = ci.h;
|
||||
cursor->pitch = ci.pitch;
|
||||
cursor->dataPos = m_cursorOffset;
|
||||
|
||||
memcpy(m_cursorData, ci.shape.buffer, ci.shape.bufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (ci.visible)
|
||||
flags |= KVMFR_CURSOR_FLAG_VISIBLE;
|
||||
|
||||
flags |= KVMFR_CURSOR_FLAG_UPDATE;
|
||||
cursor->flags = flags;
|
||||
m_capture->FreeCursor();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
114
host/Service.h
114
host/Service.h
@ -1,114 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define W32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "IVSHMEM.h"
|
||||
#include "ICapture.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
#define MAX_FRAMES 2
|
||||
|
||||
enum ProcessStatus
|
||||
{
|
||||
PROCESS_STATUS_OK,
|
||||
PROCESS_STATUS_RETRY,
|
||||
PROCESS_STATUS_ERROR
|
||||
};
|
||||
|
||||
class Service
|
||||
{
|
||||
public:
|
||||
static Service & Instance()
|
||||
{
|
||||
static Service service;
|
||||
return service;
|
||||
}
|
||||
|
||||
static void InstallHook()
|
||||
{
|
||||
if (Instance().m_mouseHook)
|
||||
RemoveHook();
|
||||
Instance().m_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, _LowLevelMouseProc, NULL, 0);
|
||||
}
|
||||
|
||||
static void RemoveHook()
|
||||
{
|
||||
if (Instance().m_mouseHook)
|
||||
{
|
||||
UnhookWindowsHookEx(Instance().m_mouseHook);
|
||||
Instance().m_mouseHook = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void SetDevice(PCI_DEVICE dev)
|
||||
{
|
||||
s_dev = dev;
|
||||
}
|
||||
|
||||
bool Initialize(ICapture * captureDevice);
|
||||
void DeInitialize();
|
||||
ProcessStatus Process();
|
||||
|
||||
private:
|
||||
bool InitPointers();
|
||||
|
||||
int m_tryTarget;
|
||||
int m_lastTryCount;
|
||||
|
||||
Service();
|
||||
~Service();
|
||||
|
||||
HHOOK m_mouseHook;
|
||||
LRESULT LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
static LRESULT WINAPI _LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) { return Service::Instance().LowLevelMouseProc(nCode, wParam, lParam); }
|
||||
|
||||
bool ReInit(volatile char * flags);
|
||||
|
||||
bool m_initialized;
|
||||
bool m_running;
|
||||
DWORD m_consoleSessionID;
|
||||
uint8_t * m_memory;
|
||||
IVSHMEM * m_ivshmem;
|
||||
HANDLE m_timer;
|
||||
ICapture * m_capture;
|
||||
|
||||
KVMFRHeader * m_shmHeader;
|
||||
|
||||
bool m_haveFrame;
|
||||
uint8_t * m_frame[MAX_FRAMES];
|
||||
size_t m_frameSize;
|
||||
uint64_t m_dataOffset[MAX_FRAMES];
|
||||
int m_frameIndex;
|
||||
static PCI_DEVICE s_dev;
|
||||
|
||||
static DWORD WINAPI _CursorThread(LPVOID lpParameter) { return Service::Instance().CursorThread(); }
|
||||
DWORD CursorThread();
|
||||
|
||||
HANDLE m_cursorThread;
|
||||
HANDLE m_cursorEvent;
|
||||
CRITICAL_SECTION m_cursorCS;
|
||||
size_t m_cursorDataSize;
|
||||
uint8_t * m_cursorData;
|
||||
uint64_t m_cursorOffset;
|
||||
};
|
@ -1,13 +0,0 @@
|
||||
Texture2D texTexture;
|
||||
SamplerState texSampler;
|
||||
|
||||
struct VS
|
||||
{
|
||||
float4 pos : SV_Position;
|
||||
float2 tex : TEXCOORD;
|
||||
};
|
||||
|
||||
float4 main(VS input): SV_Target
|
||||
{
|
||||
return texTexture.Sample(texSampler, input.tex);
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
Texture2D texTexture;
|
||||
SamplerState texSampler;
|
||||
|
||||
struct VS
|
||||
{
|
||||
float4 pos : SV_Position;
|
||||
float2 tex : TEXCOORD;
|
||||
};
|
||||
|
||||
struct OUT
|
||||
{
|
||||
float4 y: SV_TARGET0;
|
||||
float4 u: SV_TARGET1;
|
||||
float4 v: SV_TARGET2;
|
||||
};
|
||||
|
||||
OUT main(VS input)
|
||||
{
|
||||
OUT o;
|
||||
const float4 rgba = texTexture.Sample(texSampler, input.tex);
|
||||
|
||||
o.y.gba = 1.0f;
|
||||
o.u.gba = 1.0f;
|
||||
o.v.gba = 1.0f;
|
||||
|
||||
o.y.r = rgba.r * 0.2126 + 0.7152 * rgba.g + 0.0722 * rgba.b;
|
||||
o.u.r = ((rgba.b - o.y.r) / 1.8556) + 0.5;
|
||||
o.v.r = ((rgba.r - o.y.r) / 1.5748) + 0.5;
|
||||
|
||||
return o;
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
struct VS
|
||||
{
|
||||
float4 pos : POSITION;
|
||||
float2 tex : TEXCOORD;
|
||||
};
|
||||
|
||||
struct PS
|
||||
{
|
||||
float4 pos : SV_Position;
|
||||
float2 tex : TEXCOORD;
|
||||
};
|
||||
|
||||
PS main(VS input)
|
||||
{
|
||||
return input;
|
||||
}
|
@ -1,418 +0,0 @@
|
||||
/*
|
||||
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 "TextureConverter.h"
|
||||
#include "common\debug.h"
|
||||
|
||||
#include "Shaders\Vertex.h"
|
||||
#include "Shaders\Pixel.h"
|
||||
#include "Shaders\RGBtoYUV.h"
|
||||
|
||||
TextureConverter::TextureConverter()
|
||||
{
|
||||
}
|
||||
|
||||
TextureConverter::~TextureConverter()
|
||||
{
|
||||
DeInitialize();
|
||||
}
|
||||
|
||||
bool TextureConverter::Initialize(
|
||||
ID3D11DeviceContextPtr deviceContext,
|
||||
ID3D11DevicePtr device,
|
||||
const unsigned int width,
|
||||
const unsigned int height,
|
||||
FrameType format
|
||||
)
|
||||
{
|
||||
HRESULT result;
|
||||
D3D11_TEXTURE2D_DESC texDesc;
|
||||
D3D11_RENDER_TARGET_VIEW_DESC targetDesc;
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC shaderDesc;
|
||||
D3D11_SAMPLER_DESC samplerDesc;
|
||||
|
||||
m_deviceContext = deviceContext;
|
||||
m_device = device;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_format = format;
|
||||
|
||||
result = device->CreatePixelShader(g_Pixel, sizeof(g_Pixel), NULL, &m_psCopy);
|
||||
if (FAILED(result))
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create the copy pixel shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case FRAME_TYPE_YUV420:
|
||||
result = device->CreatePixelShader(g_RGBtoYUV, sizeof(g_RGBtoYUV), NULL, &m_psConversion);
|
||||
m_texFormats[0] = DXGI_FORMAT_R8_UNORM; m_scaleFormats[0] = 1;
|
||||
m_texFormats[1] = DXGI_FORMAT_R8_UNORM; m_scaleFormats[1] = 2;
|
||||
m_texFormats[2] = DXGI_FORMAT_R8_UNORM; m_scaleFormats[2] = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_ERROR("Unsupported format");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create the pixel shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
const D3D11_INPUT_ELEMENT_DESC inputDesc[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT , 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
|
||||
};
|
||||
|
||||
result = device->CreateInputLayout(inputDesc, _countof(inputDesc), g_Vertex, sizeof(g_Vertex), &m_layout);
|
||||
if (FAILED(result))
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create the input layout");
|
||||
return false;
|
||||
}
|
||||
|
||||
result = device->CreateVertexShader(g_Vertex, sizeof(g_Vertex), NULL, &m_vertexShader);
|
||||
if (FAILED(result))
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create the vertex shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
ZeroMemory(&texDesc , sizeof(texDesc ));
|
||||
ZeroMemory(&targetDesc , sizeof(targetDesc ));
|
||||
ZeroMemory(&shaderDesc , sizeof(shaderDesc ));
|
||||
ZeroMemory(&samplerDesc, sizeof(samplerDesc));
|
||||
|
||||
texDesc.Width = width;
|
||||
texDesc.Height = height;
|
||||
texDesc.MipLevels = 1;
|
||||
texDesc.ArraySize = 1;
|
||||
texDesc.SampleDesc.Count = 1;
|
||||
texDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
texDesc.CPUAccessFlags = 0;
|
||||
texDesc.MiscFlags = 0;
|
||||
texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
|
||||
targetDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
|
||||
shaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderDesc.Texture2D.MipLevels = 1;
|
||||
|
||||
for(int i = 0; i < _countof(m_targetTexture); ++i)
|
||||
{
|
||||
if (m_texFormats[i] == DXGI_FORMAT_UNKNOWN)
|
||||
continue;
|
||||
|
||||
texDesc .Format = m_texFormats[i];
|
||||
targetDesc.Format = m_texFormats[i];
|
||||
shaderDesc.Format = m_texFormats[i];
|
||||
|
||||
result = device->CreateTexture2D(&texDesc, NULL, &m_targetTexture[i]);
|
||||
if (FAILED(result))
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create the render texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
result = device->CreateRenderTargetView(m_targetTexture[i], &targetDesc, &m_renderView[i]);
|
||||
if (FAILED(result))
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create the render view");
|
||||
return false;
|
||||
}
|
||||
|
||||
result = device->CreateShaderResourceView(m_targetTexture[i], &shaderDesc, &m_shaderView[i]);
|
||||
if (FAILED(result))
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create the resource view");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.MipLODBias = 0.0f;
|
||||
samplerDesc.MaxAnisotropy = 1;
|
||||
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
samplerDesc.BorderColor[0] = 1.0f;
|
||||
samplerDesc.BorderColor[1] = 1.0f;
|
||||
samplerDesc.BorderColor[2] = 1.0f;
|
||||
samplerDesc.MinLOD = -FLT_MAX;
|
||||
samplerDesc.MaxLOD = FLT_MAX;
|
||||
|
||||
result = device->CreateSamplerState(&samplerDesc, &m_samplerState);
|
||||
if (FAILED(result))
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create sampler state");
|
||||
return false;
|
||||
}
|
||||
|
||||
return IntializeBuffers();
|
||||
}
|
||||
|
||||
bool TextureConverter::IntializeBuffers()
|
||||
{
|
||||
struct VS_INPUT * verticies;
|
||||
unsigned long * indicies;
|
||||
HRESULT result;
|
||||
D3D11_BUFFER_DESC vertexDesc, indexDesc;
|
||||
D3D11_SUBRESOURCE_DATA vertexData, indexData;
|
||||
|
||||
m_vertexCount = 4;
|
||||
m_indexCount = 4;
|
||||
|
||||
verticies = new struct VS_INPUT[m_vertexCount];
|
||||
if (!verticies)
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("new failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
indicies = new unsigned long[m_indexCount];
|
||||
if (!indicies)
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("new failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
verticies[0].pos = DirectX::XMFLOAT3(-1.0f, -1.0f, 0.5f); //BL
|
||||
verticies[1].pos = DirectX::XMFLOAT3(-1.0f, 1.0f, 0.5f); //TL
|
||||
verticies[2].pos = DirectX::XMFLOAT3( 1.0f, -1.0f, 0.5f); //BR
|
||||
verticies[3].pos = DirectX::XMFLOAT3( 1.0f, 1.0f, 0.5f); //TR
|
||||
verticies[0].tex = DirectX::XMFLOAT2(0.0f, 1.0f);
|
||||
verticies[1].tex = DirectX::XMFLOAT2(0.0f, 0.0f);
|
||||
verticies[2].tex = DirectX::XMFLOAT2(1.0f, 1.0f);
|
||||
verticies[3].tex = DirectX::XMFLOAT2(1.0f, 0.0f);
|
||||
indicies[0] = 0;
|
||||
indicies[1] = 1;
|
||||
indicies[2] = 2;
|
||||
indicies[3] = 3;
|
||||
|
||||
vertexDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
vertexDesc.ByteWidth = sizeof(struct VS_INPUT) * m_vertexCount;
|
||||
vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
vertexDesc.CPUAccessFlags = 0;
|
||||
vertexDesc.MiscFlags = 0;
|
||||
vertexDesc.StructureByteStride = 0;
|
||||
|
||||
vertexData.pSysMem = verticies;
|
||||
vertexData.SysMemPitch = 0;
|
||||
vertexData.SysMemSlicePitch = 0;
|
||||
|
||||
result = m_device->CreateBuffer(&vertexDesc, &vertexData, &m_vertexBuffer);
|
||||
if (FAILED(result))
|
||||
{
|
||||
delete[] indicies;
|
||||
delete[] verticies;
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create vertex buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
indexDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
indexDesc.ByteWidth = sizeof(unsigned long) * m_indexCount;
|
||||
indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
indexDesc.CPUAccessFlags = 0;
|
||||
indexDesc.MiscFlags = 0;
|
||||
indexDesc.StructureByteStride = 0;
|
||||
|
||||
indexData.pSysMem = indicies;
|
||||
indexData.SysMemPitch = 0;
|
||||
indexData.SysMemSlicePitch = 0;
|
||||
|
||||
result = m_device->CreateBuffer(&indexDesc, &indexData, &m_indexBuffer);
|
||||
if (FAILED(result))
|
||||
{
|
||||
delete[] indicies;
|
||||
delete[] verticies;
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create index buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
delete[] indicies;
|
||||
delete[] verticies;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextureConverter::DeInitialize()
|
||||
{
|
||||
m_samplerState = NULL;
|
||||
m_indexBuffer = NULL;
|
||||
m_indexBuffer = NULL;
|
||||
|
||||
for(int i = 0; i < _countof(m_targetTexture); ++i)
|
||||
{
|
||||
m_shaderView [i] = NULL;
|
||||
m_renderView [i] = NULL;
|
||||
m_targetTexture[i] = NULL;
|
||||
}
|
||||
|
||||
m_vertexShader = NULL;
|
||||
m_psConversion = NULL;
|
||||
m_layout = NULL;
|
||||
m_psCopy = NULL;
|
||||
}
|
||||
|
||||
bool TextureConverter::Convert(ID3D11Texture2DPtr texture, TextureList & output)
|
||||
{
|
||||
unsigned int stride;
|
||||
unsigned int offset;
|
||||
float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
HRESULT result;
|
||||
D3D11_TEXTURE2D_DESC texDesc;
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
|
||||
ID3D11ShaderResourceViewPtr textureView;
|
||||
texture->GetDesc(&texDesc);
|
||||
viewDesc.Format = texDesc.Format;
|
||||
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
viewDesc.Texture2D.MostDetailedMip = 0;
|
||||
viewDesc.Texture2D.MipLevels = 1;
|
||||
|
||||
result = m_device->CreateShaderResourceView(texture, &viewDesc, &textureView);
|
||||
if (FAILED(result))
|
||||
{
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create shader resource view");
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D11Buffer *buffers [] = { m_vertexBuffer.GetInterfacePtr() };
|
||||
ID3D11SamplerState *samplerStates[] = { m_samplerState.GetInterfacePtr() };
|
||||
ID3D11ShaderResourceView *shaderViews [] = { textureView .GetInterfacePtr() };
|
||||
D3D11_VIEWPORT viewPorts [] = { {
|
||||
0.0f , 0.0f,
|
||||
(float)m_width, (float)m_height,
|
||||
0.0f , 1.0f
|
||||
} };
|
||||
|
||||
int targetCount = 0;
|
||||
ID3D11RenderTargetView **renderViews = new ID3D11RenderTargetView*[_countof(m_renderView)];
|
||||
for(int i = 0; i < _countof(m_renderView); ++i)
|
||||
{
|
||||
if (m_texFormats[i] == DXGI_FORMAT_UNKNOWN)
|
||||
continue;
|
||||
|
||||
m_deviceContext->ClearRenderTargetView(m_renderView[i], color);
|
||||
renderViews[i] = m_renderView[i].GetInterfacePtr();
|
||||
++targetCount;
|
||||
}
|
||||
|
||||
m_deviceContext->PSSetShaderResources(0, _countof(shaderViews), shaderViews);
|
||||
m_deviceContext->OMSetRenderTargets(targetCount, renderViews, NULL);
|
||||
delete [] renderViews;
|
||||
|
||||
stride = sizeof(VS_INPUT);
|
||||
offset = 0;
|
||||
|
||||
m_deviceContext->RSSetViewports (_countof(viewPorts), viewPorts);
|
||||
m_deviceContext->IASetInputLayout (m_layout);
|
||||
m_deviceContext->IASetVertexBuffers (0, _countof(buffers), buffers, &stride, &offset);
|
||||
m_deviceContext->IASetIndexBuffer (m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
|
||||
m_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
m_deviceContext->VSSetShader (m_vertexShader, NULL, 0);
|
||||
|
||||
m_deviceContext->PSSetSamplers (0, _countof(samplerStates), samplerStates);
|
||||
m_deviceContext->PSSetShader (m_psConversion, NULL, 0);
|
||||
|
||||
m_deviceContext->DrawIndexed(m_indexCount, 0, 0);
|
||||
textureView = NULL;
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC targetDesc;
|
||||
ZeroMemory(&targetDesc, sizeof(targetDesc));
|
||||
targetDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
m_deviceContext->PSSetShader(m_psCopy, NULL, 0);
|
||||
|
||||
renderViews = new ID3D11RenderTargetView*[1];
|
||||
for (int i = 0; i < _countof(m_renderView); ++i)
|
||||
{
|
||||
if (m_texFormats[i] == DXGI_FORMAT_UNKNOWN)
|
||||
continue;
|
||||
|
||||
ID3D11Texture2DPtr src = m_targetTexture[i];
|
||||
ID3D11Texture2DPtr dest;
|
||||
ID3D11RenderTargetViewPtr view;
|
||||
D3D11_TEXTURE2D_DESC srcDesc;
|
||||
|
||||
// if there is no scaling
|
||||
if (m_scaleFormats[i] == 1)
|
||||
{
|
||||
output.push_back(src);
|
||||
continue;
|
||||
}
|
||||
|
||||
src->GetDesc(&srcDesc);
|
||||
viewPorts[0].Width = srcDesc.Width / m_scaleFormats[i];
|
||||
viewPorts[0].Height = srcDesc.Height / m_scaleFormats[i];
|
||||
srcDesc.Width = (UINT)viewPorts[0].Width;
|
||||
srcDesc.Height = (UINT)viewPorts[0].Height;
|
||||
|
||||
result = m_device->CreateTexture2D(&srcDesc, NULL, &dest);
|
||||
if (FAILED(result))
|
||||
{
|
||||
delete[] renderViews;
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create the target texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
targetDesc.Format = srcDesc.Format;
|
||||
result = m_device->CreateRenderTargetView(dest, &targetDesc, &view);
|
||||
if (FAILED(result))
|
||||
{
|
||||
delete[] renderViews;
|
||||
DeInitialize();
|
||||
DEBUG_ERROR("Failed to create the target view");
|
||||
return false;
|
||||
}
|
||||
|
||||
renderViews[0] = view.GetInterfacePtr();
|
||||
shaderViews[0] = m_shaderView[i].GetInterfacePtr();
|
||||
|
||||
m_deviceContext->OMSetRenderTargets(1, renderViews, NULL);
|
||||
m_deviceContext->RSSetViewports(_countof(viewPorts), viewPorts);
|
||||
m_deviceContext->PSSetShaderResources(0, 1, shaderViews);
|
||||
m_deviceContext->DrawIndexed(m_indexCount, 0, 0);
|
||||
|
||||
output.push_back(dest);
|
||||
view = NULL;
|
||||
}
|
||||
|
||||
delete[] renderViews;
|
||||
return true;
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Com.h"
|
||||
#include "common\KVMFR.h"
|
||||
|
||||
#include <DirectXMath.h>
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<ID3D11Texture2DPtr> TextureList;
|
||||
|
||||
class TextureConverter
|
||||
{
|
||||
public:
|
||||
TextureConverter();
|
||||
~TextureConverter();
|
||||
|
||||
bool Initialize(
|
||||
ID3D11DeviceContextPtr deviceContext,
|
||||
ID3D11DevicePtr device,
|
||||
const unsigned int width,
|
||||
const unsigned int height,
|
||||
FrameType format
|
||||
);
|
||||
|
||||
void DeInitialize();
|
||||
|
||||
bool Convert(ID3D11Texture2DPtr texture, TextureList & output);
|
||||
|
||||
private:
|
||||
struct VS_INPUT
|
||||
{
|
||||
DirectX::XMFLOAT3 pos;
|
||||
DirectX::XMFLOAT2 tex;
|
||||
};
|
||||
|
||||
bool IntializeBuffers();
|
||||
|
||||
ID3D11DeviceContextPtr m_deviceContext;
|
||||
ID3D11DevicePtr m_device;
|
||||
unsigned int m_width, m_height;
|
||||
FrameType m_format;
|
||||
|
||||
DXGI_FORMAT m_texFormats [3];
|
||||
unsigned int m_scaleFormats [3];
|
||||
|
||||
ID3D11Texture2DPtr m_targetTexture[3];
|
||||
ID3D11RenderTargetViewPtr m_renderView [3];
|
||||
ID3D11ShaderResourceViewPtr m_shaderView [3];
|
||||
|
||||
ID3D11InputLayoutPtr m_layout;
|
||||
ID3D11VertexShaderPtr m_vertexShader;
|
||||
ID3D11PixelShaderPtr m_psCopy;
|
||||
ID3D11PixelShaderPtr m_psConversion;
|
||||
ID3D11SamplerStatePtr m_samplerState;
|
||||
|
||||
ID3D11BufferPtr m_vertexBuffer;
|
||||
unsigned int m_vertexCount;
|
||||
ID3D11BufferPtr m_indexBuffer;
|
||||
unsigned int m_indexCount;
|
||||
};
|
||||
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
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 "TraceUtil.h"
|
||||
|
||||
double TraceUtil::m_freq;
|
||||
LARGE_INTEGER TraceUtil::m_last;
|
||||
LARGE_INTEGER TraceUtil::m_start;
|
||||
const char * TraceUtil::m_traceName;
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
#include "common/debug.h"
|
||||
|
||||
#ifdef ENABLE_TRACING
|
||||
#define TRACE TraceUtil::Trace(__FUNCTION__, __LINE__)
|
||||
#define TRACE_START(x) TraceUtil::TraceStart(x)
|
||||
#define TRACE_END TraceUtil::TraceEnd()
|
||||
#else
|
||||
#define TRACE
|
||||
#define TRACE_START(x)
|
||||
#define TRACE_END
|
||||
#endif
|
||||
|
||||
class TraceUtil
|
||||
{
|
||||
private:
|
||||
static double m_freq;
|
||||
static LARGE_INTEGER m_last;
|
||||
static LARGE_INTEGER m_start;
|
||||
static const char * m_traceName;
|
||||
|
||||
public:
|
||||
static void Initialize()
|
||||
{
|
||||
#ifdef ENABLE_TRACING
|
||||
LARGE_INTEGER now;
|
||||
QueryPerformanceFrequency(&now);
|
||||
m_freq = (double)now.QuadPart / 1000.0;
|
||||
QueryPerformanceCounter(&m_last);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void Trace(const char * function, const unsigned int line)
|
||||
{
|
||||
LARGE_INTEGER now;
|
||||
QueryPerformanceCounter(&now);
|
||||
const double diff = (now.QuadPart - m_last.QuadPart) / m_freq;
|
||||
m_last = now;
|
||||
|
||||
DEBUG_INFO("Trace [%8.4f] %s:%u", diff, function, line);
|
||||
}
|
||||
|
||||
static inline void TraceStart(const char * traceName)
|
||||
{
|
||||
QueryPerformanceCounter(&m_start);
|
||||
m_traceName = traceName;
|
||||
}
|
||||
|
||||
static inline void TraceEnd()
|
||||
{
|
||||
LARGE_INTEGER now;
|
||||
QueryPerformanceCounter(&now);
|
||||
const double diff = (now.QuadPart - m_start.QuadPart) / m_freq;
|
||||
|
||||
DEBUG_INFO("Trace [%8.4f] %s", diff, m_traceName);
|
||||
}
|
||||
};
|
154
host/Util.h
154
host/Util.h
@ -1,154 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <tmmintrin.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
#if !defined(min)
|
||||
#define LG_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#else
|
||||
#define LG_MIN min
|
||||
#endif
|
||||
|
||||
#if __MINGW32__
|
||||
#define INTERLOCKED_AND8 __sync_and_and_fetch
|
||||
#define INTERLOCKED_OR8 __sync_or_and_fetch
|
||||
#else
|
||||
#define INTERLOCKED_OR8 InterlockedOr8
|
||||
#define INTERLOCKED_AND8 InterlockedAnd8
|
||||
#endif
|
||||
|
||||
class Util
|
||||
{
|
||||
public:
|
||||
static void DebugWinError(const char * file, const unsigned int line, const char * function, const char * desc, HRESULT status)
|
||||
{
|
||||
char *buffer;
|
||||
FormatMessageA(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
NULL,
|
||||
status,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(char*)&buffer,
|
||||
1024,
|
||||
NULL
|
||||
);
|
||||
|
||||
for(size_t i = strlen(buffer) - 1; i > 0; --i)
|
||||
if (buffer[i] == '\n' || buffer[i] == '\r')
|
||||
buffer[i] = 0;
|
||||
|
||||
fprintf(stderr, "[E] %20s:%-4u | %-30s | %s: 0x%08x (%s)\n", file, line, function, desc, (int)status, buffer);
|
||||
LocalFree(buffer);
|
||||
}
|
||||
|
||||
static std::string GetSystemRoot()
|
||||
{
|
||||
std::string defaultPath;
|
||||
|
||||
#if __MINGW32__
|
||||
const char * libPath = getenv("SystemRoot");
|
||||
const size_t libPathLen = strlen(libPath);
|
||||
#else
|
||||
char * libPath;
|
||||
size_t libPathLen;
|
||||
_dupenv_s(&libPath, &libPathLen, "SystemRoot");
|
||||
#endif
|
||||
|
||||
if (!libPath)
|
||||
{
|
||||
DEBUG_ERROR("Unable to get the SystemRoot environment variable");
|
||||
return defaultPath;
|
||||
}
|
||||
|
||||
if (!libPathLen)
|
||||
{
|
||||
DEBUG_ERROR("The SystemRoot environment variable is not set");
|
||||
#ifndef __MINGW32__
|
||||
free(libPath);
|
||||
#endif
|
||||
return defaultPath;
|
||||
}
|
||||
#ifdef _WIN64
|
||||
defaultPath = std::string(libPath) + "\\System32";
|
||||
#else
|
||||
if (IsWow64())
|
||||
{
|
||||
defaultPath = std::string(libPath) + "\\Syswow64";
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultPath = std::string(libPath) + "\\System32";
|
||||
}
|
||||
#endif
|
||||
#ifndef __MINGW32__
|
||||
free(libPath);
|
||||
#endif
|
||||
return defaultPath;
|
||||
}
|
||||
|
||||
static inline void BGRAtoRGB(uint8_t * orig, size_t imagesize, uint8_t * dest)
|
||||
{
|
||||
assert((uintptr_t)orig % 16 == 0);
|
||||
assert((uintptr_t)dest % 16 == 0);
|
||||
assert(imagesize % 16 == 0);
|
||||
|
||||
__m128i mask_right = _mm_set_epi8
|
||||
(
|
||||
12, 13, 14, 8,
|
||||
9, 10, 4, 5,
|
||||
6, 0, 1, 2,
|
||||
-128, -128, -128, -128
|
||||
);
|
||||
|
||||
__m128i mask_left = _mm_set_epi8
|
||||
(
|
||||
-128, -128, -128, -128,
|
||||
12, 13, 14, 8,
|
||||
9, 10, 4, 5,
|
||||
6, 0, 1, 2
|
||||
);
|
||||
|
||||
|
||||
uint8_t *end = orig + imagesize * 4;
|
||||
for (; orig != end; orig += 64, dest += 48)
|
||||
{
|
||||
_mm_prefetch((char *)(orig + 128), _MM_HINT_NTA);
|
||||
_mm_prefetch((char *)(orig + 192), _MM_HINT_NTA);
|
||||
|
||||
__m128i v0 = _mm_shuffle_epi8(_mm_load_si128((__m128i *)&orig[0 ]), mask_right);
|
||||
__m128i v1 = _mm_shuffle_epi8(_mm_load_si128((__m128i *)&orig[16]), mask_left );
|
||||
__m128i v2 = _mm_shuffle_epi8(_mm_load_si128((__m128i *)&orig[32]), mask_left );
|
||||
__m128i v3 = _mm_shuffle_epi8(_mm_load_si128((__m128i *)&orig[48]), mask_left );
|
||||
|
||||
v0 = _mm_alignr_epi8(v1, v0, 4);
|
||||
v1 = _mm_alignr_epi8(v2, _mm_slli_si128(v1, 4), 8);
|
||||
v2 = _mm_alignr_epi8(v3, _mm_slli_si128(v2, 4), 12);
|
||||
|
||||
_mm_stream_si128((__m128i *)&dest[0 ], v0);
|
||||
_mm_stream_si128((__m128i *)&dest[16], v1);
|
||||
_mm_stream_si128((__m128i *)&dest[32], v2);
|
||||
}
|
||||
}
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
#define DEBUG_WINERROR(x, y) Util::DebugWinError(STRIPPATH(__FILE__), __LINE__, __FUNCTION__, x, y)
|
@ -1,418 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug - NvFBC|Win32">
|
||||
<Configuration>Debug - NvFBC</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug - NvFBC|x64">
|
||||
<Configuration>Debug - NvFBC</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release - NvFBC|Win32">
|
||||
<Configuration>Release - NvFBC</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release - NvFBC|x64">
|
||||
<Configuration>Release - NvFBC</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D439DE3E-32FB-4599-8B5D-C92674D400D4}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>kvmivshmemhost</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>looking-glass-host</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
|
||||
<ExecutablePath>C:\Program Files (x86)\Windows Kits\10\bin\$(TargetPlatformVersion)\$(PreferredToolArchitecture);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
|
||||
<ExecutablePath>C:\Program Files (x86)\Windows Kits\10\bin\$(TargetPlatformVersion)\$(PreferredToolArchitecture);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
|
||||
<ExecutablePath>C:\Program Files (x86)\Windows Kits\10\bin\$(TargetPlatformVersion)\$(PreferredToolArchitecture);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
|
||||
<ExecutablePath>C:\Program Files (x86)\Windows Kits\10\bin\$(TargetPlatformVersion)\$(PreferredToolArchitecture);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
|
||||
<ExecutablePath>C:\Program Files (x86)\Windows Kits\10\bin\$(TargetPlatformVersion)\$(PreferredToolArchitecture);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
|
||||
<ExecutablePath>C:\Program Files (x86)\Windows Kits\10\bin\$(TargetPlatformVersion)\$(PreferredToolArchitecture);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
|
||||
<ExecutablePath>C:\Program Files (x86)\Windows Kits\10\bin\$(TargetPlatformVersion)\$(PreferredToolArchitecture);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc</IncludePath>
|
||||
<ExecutablePath>C:\Program Files (x86)\Windows Kits\10\bin\$(TargetPlatformVersion)\$(PreferredToolArchitecture);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>ENABLE_TRACING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\vendor;..\common\include;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;wmcodecdspuuid.lib;mfplat.lib;mfuuid.lib;evr.lib;avrt.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>ENABLE_TRACING;CONFIG_CAPTURE_NVFBC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\vendor;..\common\include;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;wmcodecdspuuid.lib;mfplat.lib;mfuuid.lib;evr.lib;avrt.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>ENABLE_TRACING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\vendor;..\common\include;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;wmcodecdspuuid.lib;mfplat.lib;mfuuid.lib;evr.lib;avrt.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>ENABLE_TRACING;CONFIG_CAPTURE_NVFBC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\vendor;..\common\include;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;wmcodecdspuuid.lib;mfplat.lib;mfuuid.lib;evr.lib;avrt.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\vendor;..\common\include;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;wmcodecdspuuid.lib;mfplat.lib;mfuuid.lib;evr.lib;avrt.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>CONFIG_CAPTURE_NVFBC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\vendor;..\common\include;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;wmcodecdspuuid.lib;mfplat.lib;mfuuid.lib;evr.lib;avrt.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\vendor;..\common\include;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;wmcodecdspuuid.lib;mfplat.lib;mfuuid.lib;evr.lib;avrt.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>CONFIG_CAPTURE_NVFBC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\vendor;..\common\include;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>kernel32.lib;shlwapi.lib;dxgi.lib;d3d11.lib;setupapi.lib;uuid.lib;wmcodecdspuuid.lib;mfplat.lib;mfuuid.lib;evr.lib;avrt.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\vendor\getopt\getopt.c" />
|
||||
<ClCompile Include="Capture\DXGI.cpp" />
|
||||
<ClCompile Include="Capture\NvFBC.cpp" />
|
||||
<ClCompile Include="CrashHandler.cpp" />
|
||||
<ClCompile Include="ivshmem.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="MFT\H264.cpp" />
|
||||
<ClCompile Include="TextureConverter.cpp" />
|
||||
<ClCompile Include="Service.cpp" />
|
||||
<ClCompile Include="TraceUtil.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CaptureFactory.h" />
|
||||
<ClInclude Include="Capture\DXGI.h" />
|
||||
<ClInclude Include="Capture\NvFBC.h" />
|
||||
<ClInclude Include="Com.h" />
|
||||
<ClInclude Include="CrashHandler.h" />
|
||||
<ClInclude Include="ICapture.h" />
|
||||
<ClInclude Include="ivshmem.h" />
|
||||
<ClInclude Include="MFT\H264.h" />
|
||||
<ClInclude Include="TextureConverter.h" />
|
||||
<ClInclude Include="Service.h" />
|
||||
<ClInclude Include="TraceUtil.h" />
|
||||
<ClInclude Include="Util.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="..\common\src\memcpySSE.asm" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FxCompile Include="Shaders\Pixel.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">g_Pixel</VariableName>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Shaders\Pixel.h</HeaderFileOutput>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0_level_9_1</ShaderModel>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">Pixel</ShaderType>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">4.0_level_9_1</ShaderModel>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">Pixel</ShaderType>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">g_Pixel</VariableName>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">Shaders\Pixel.h</HeaderFileOutput>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">g_Pixel</VariableName>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">Shaders\Pixel.h</HeaderFileOutput>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">g_Pixel</VariableName>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Shaders\Pixel.h</HeaderFileOutput>
|
||||
</FxCompile>
|
||||
<FxCompile Include="Shaders\RGBtoYUV.hlsl">
|
||||
<FileType>HLSL</FileType>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">g_RGBtoYUV</VariableName>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Shaders\RGBtoYUV.h</HeaderFileOutput>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">Pixel</ShaderType>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">Pixel</ShaderType>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0_level_9_1</ShaderModel>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">4.0_level_9_1</ShaderModel>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">g_RGBtoYUV</VariableName>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">g_RGBtoYUV</VariableName>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">g_RGBtoYUV</VariableName>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">Shaders\RGBtoYUV.h</HeaderFileOutput>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">Shaders\RGBtoYUV.h</HeaderFileOutput>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Shaders\RGBtoYUV.h</HeaderFileOutput>
|
||||
</FxCompile>
|
||||
<FxCompile Include="Shaders\Vertex.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">g_Vertex</VariableName>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Shaders\Vertex.h</HeaderFileOutput>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">g_Vertex</VariableName>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">g_Vertex</VariableName>
|
||||
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">g_Vertex</VariableName>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">Shaders\Vertex.h</HeaderFileOutput>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">Shaders\Vertex.h</HeaderFileOutput>
|
||||
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Shaders\Vertex.h</HeaderFileOutput>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0_level_9_1</ShaderModel>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">Vertex</ShaderType>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">4.0_level_9_1</ShaderModel>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">Vertex</ShaderType>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Vertex</ShaderType>
|
||||
</FxCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -1,118 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Capture">
|
||||
<UniqueIdentifier>{3a65593b-37a9-448d-acf0-6339dea46ed1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Capture">
|
||||
<UniqueIdentifier>{0a865d22-907e-44ea-a230-ad7ede7edeb0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\MFT">
|
||||
<UniqueIdentifier>{bd9c6e76-f398-49eb-acfb-3f50cd99724c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\MFT">
|
||||
<UniqueIdentifier>{fead4000-1954-4480-8ee7-b817d7042761}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Shaders">
|
||||
<UniqueIdentifier>{afb06b60-4959-4447-92ec-75cc07995a8f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ivshmem.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Service.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Capture\NvFBC.cpp">
|
||||
<Filter>Source Files\Capture</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Capture\DXGI.cpp">
|
||||
<Filter>Source Files\Capture</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\vendor\getopt\getopt.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CrashHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TraceUtil.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MFT\H264.cpp">
|
||||
<Filter>Source Files\MFT</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TextureConverter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ivshmem.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ICapture.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Service.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CaptureFactory.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Capture\NvFBC.h">
|
||||
<Filter>Header Files\Capture</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Util.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Capture\DXGI.h">
|
||||
<Filter>Header Files\Capture</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CrashHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TraceUtil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MFT\H264.h">
|
||||
<Filter>Header Files\MFT</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Com.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TextureConverter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FxCompile Include="Shaders\Vertex.hlsl">
|
||||
<Filter>Source Files\Shaders</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="Shaders\RGBtoYUV.hlsl">
|
||||
<Filter>Source Files\Shaders</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="Shaders\Pixel.hlsl">
|
||||
<Filter>Source Files\Shaders</Filter>
|
||||
</FxCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="..\common\src\memcpySSE.asm">
|
||||
<Filter>Source Files</Filter>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
</Project>
|
373
host/main.cpp
373
host/main.cpp
@ -1,373 +0,0 @@
|
||||
/*
|
||||
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 <windows.h>
|
||||
#include <shlwapi.h>
|
||||
#include <avrt.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "getopt/getopt.h"
|
||||
|
||||
#include "CrashHandler.h"
|
||||
#include "TraceUtil.h"
|
||||
#include "CaptureFactory.h"
|
||||
#include "Service.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
|
||||
int parseArgs(struct StartupArgs & args);
|
||||
static DWORD WINAPI CaptureThread(LPVOID lpParameter);
|
||||
int run();
|
||||
|
||||
void doHelp();
|
||||
void doLicense();
|
||||
|
||||
bool running = true;
|
||||
bool consoleActive = false;
|
||||
void setupConsole();
|
||||
|
||||
extern "C" NTSYSAPI NTSTATUS NTAPI NtSetTimerResolution(ULONG DesiredResolution, BOOLEAN SetResolution, PULONG CurrentResolution);
|
||||
|
||||
struct StartupArgs
|
||||
{
|
||||
bool foreground;
|
||||
const char * captureDevice;
|
||||
CaptureOptions captureOptions;
|
||||
};
|
||||
struct StartupArgs args;
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam, int iCmdShow)
|
||||
{
|
||||
CrashHandler::Initialize();
|
||||
TraceUtil::Initialize();
|
||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||
|
||||
args.foreground = false;
|
||||
args.captureDevice = NULL;
|
||||
int ret = parseArgs(args);
|
||||
if (ret != 0)
|
||||
fprintf(stderr, "Failed to parse command line arguments\n");
|
||||
else
|
||||
{
|
||||
if (args.foreground)
|
||||
setupConsole();
|
||||
|
||||
Service::InstallHook();
|
||||
HANDLE captureThread = CreateThread(NULL, 0, CaptureThread, NULL, 0, NULL);
|
||||
while (running)
|
||||
{
|
||||
MSG msg;
|
||||
BOOL bRet = GetMessage(&msg, NULL, 0, 0);
|
||||
if (bRet == -1 || bRet == 0)
|
||||
{
|
||||
ret = msg.wParam;
|
||||
break;
|
||||
}
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
Service::RemoveHook();
|
||||
running = false;
|
||||
ret = WaitForSingleObject(captureThread, INFINITE);
|
||||
CloseHandle(captureThread);
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
if (!args.foreground)
|
||||
{
|
||||
setupConsole();
|
||||
fprintf(stderr, "An error occurred, re-run in forground mode (-f) for more information\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (consoleActive)
|
||||
{
|
||||
fprintf(stderr, "\nPress enter to terminate...");
|
||||
fflush(stderr);
|
||||
getc(stdin);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DWORD WINAPI CaptureThread(LPVOID lpParameter)
|
||||
{
|
||||
int ret = 0;
|
||||
while (running)
|
||||
{
|
||||
ret = run();
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
running = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int run()
|
||||
{
|
||||
/* increase the system timer resolution */
|
||||
ULONG currentRes;
|
||||
NtSetTimerResolution(0, TRUE, ¤tRes);
|
||||
|
||||
/* boost our thread priority class as high as possible */
|
||||
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
|
||||
|
||||
/* use MMCSS to boost our priority for capture */
|
||||
DWORD taskIndex = 0;
|
||||
HANDLE task = AvSetMmThreadCharacteristics(L"Capture", &taskIndex);
|
||||
if (!task || (AvSetMmThreadPriority(task, AVRT_PRIORITY_CRITICAL) == FALSE))
|
||||
DEBUG_WARN("Failed to boosted priority using MMCSS");
|
||||
|
||||
ICapture * captureDevice;
|
||||
if (args.captureDevice == NULL)
|
||||
captureDevice = CaptureFactory::DetectDevice(&args.captureOptions);
|
||||
else
|
||||
{
|
||||
captureDevice = CaptureFactory::GetDevice(args.captureDevice, &args.captureOptions);
|
||||
if (!captureDevice)
|
||||
{
|
||||
setupConsole();
|
||||
fprintf(stderr, "Failed to configure requested capture device\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!captureDevice)
|
||||
{
|
||||
setupConsole();
|
||||
fprintf(stderr, "Unable to configure a capture device\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Service &svc = Service::Instance();
|
||||
if (!svc.Initialize(captureDevice))
|
||||
return -1;
|
||||
|
||||
int retry = 0;
|
||||
bool running = true;
|
||||
while (running)
|
||||
{
|
||||
switch (svc.Process())
|
||||
{
|
||||
case PROCESS_STATUS_OK:
|
||||
retry = 0;
|
||||
break;
|
||||
|
||||
case PROCESS_STATUS_RETRY:
|
||||
if (retry++ == 3)
|
||||
{
|
||||
fprintf(stderr, "Too many consecutive retries, aborting");
|
||||
running = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROCESS_STATUS_ERROR:
|
||||
fprintf(stderr, "Capture process returned error");
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
svc.DeInitialize();
|
||||
|
||||
if (task)
|
||||
AvRevertMmThreadCharacteristics(task);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parseArgs(struct StartupArgs & args)
|
||||
{
|
||||
int c;
|
||||
while((c = getopt(__argc, __argv, "hc:o:fld:")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '?':
|
||||
case 'h':
|
||||
doHelp();
|
||||
return -1;
|
||||
|
||||
case 'c':
|
||||
{
|
||||
const CaptureFactory::DeviceList deviceList = CaptureFactory::GetDevices();
|
||||
|
||||
bool found = false;
|
||||
if (strcmp(optarg, "?") != 0)
|
||||
{
|
||||
for (CaptureFactory::DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it)
|
||||
{
|
||||
if (_strcmpi(optarg, (*it)->GetName()) == 0)
|
||||
{
|
||||
args.captureDevice = (*it)->GetName();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
setupConsole();
|
||||
fprintf(stderr, "Invalid capture device: %s\n\n", optarg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
setupConsole();
|
||||
fprintf(stderr, "Available Capture Devices:\n\n");
|
||||
for (CaptureFactory::DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it)
|
||||
fprintf(stderr, " %s\n", (*it)->GetName());
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o':
|
||||
{
|
||||
args.captureOptions.push_back(optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f':
|
||||
args.foreground = true;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
doLicense();
|
||||
return -1;
|
||||
|
||||
case 'd':
|
||||
if (optarg == NULL || strlen(optarg) == 0)
|
||||
{
|
||||
setupConsole();
|
||||
fprintf(stderr, "Device ID missing\n");
|
||||
return -1;
|
||||
}
|
||||
else if (*optarg == '?')
|
||||
{
|
||||
setupConsole();
|
||||
IVSHMEM::listDevices();
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PCI_DEVICE dev;
|
||||
int cnt = sscanf_s(optarg, "%hhu,%hhu,%hhu", &dev.bus, &dev.addr, &dev.func);
|
||||
if (cnt == 3)
|
||||
{
|
||||
Service::SetDevice(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
setupConsole();
|
||||
fprintf(stderr, "Invalid Parameter\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void doHelp()
|
||||
{
|
||||
setupConsole();
|
||||
const char *app = PathFindFileNameA(__argv[0]);
|
||||
fprintf(stderr,
|
||||
"Usage: %s [OPTION]...\n"
|
||||
"Example: %s -c ?\n"
|
||||
"\n"
|
||||
" -h Print out this help\n"
|
||||
" -c Specify the capture device to use or ? to list availble (device is probed if not specified)\n"
|
||||
" -o Option to pass to the capture device, may be specified multiple times for extra options\n"
|
||||
" -f Foreground mode\n"
|
||||
" -l License information\n"
|
||||
" -d Specify the IVSHMEM device with \"<bus>,<slot>,<function>\" or ? to list available\n",
|
||||
app,
|
||||
app
|
||||
);
|
||||
}
|
||||
|
||||
void doLicense()
|
||||
{
|
||||
setupConsole();
|
||||
fprintf(stderr,
|
||||
"Looking Glass - KVM FrameRelay (KVMFR) Client\n"
|
||||
"Copyright(C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>\n"
|
||||
"\n"
|
||||
"This program is free software; you can redistribute it and / or modify it under\n"
|
||||
"the terms of the GNU General Public License as published by the Free Software\n"
|
||||
"Foundation; either version 2 of the License, or (at your option) any later\n"
|
||||
"version.\n"
|
||||
"\n"
|
||||
"This program is distributed in the hope that it will be useful, but WITHOUT ANY\n"
|
||||
"WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n"
|
||||
"PARTICULAR PURPOSE.See the GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
"You should have received a copy of the GNU General Public License along with\n"
|
||||
"this program; if not, write to the Free Software Foundation, Inc., 59 Temple\n"
|
||||
"Place, Suite 330, Boston, MA 02111 - 1307 USA\n"
|
||||
);
|
||||
}
|
||||
|
||||
void setupConsole()
|
||||
{
|
||||
if (consoleActive)
|
||||
return;
|
||||
|
||||
HANDLE _handle;
|
||||
int _conout;
|
||||
FILE * fp;
|
||||
|
||||
AllocConsole();
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO conInfo;
|
||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &conInfo);
|
||||
conInfo.dwSize.Y = 500;
|
||||
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), conInfo.dwSize);
|
||||
|
||||
_handle = GetStdHandle(STD_INPUT_HANDLE);
|
||||
_conout = _open_osfhandle((intptr_t)_handle, _O_TEXT);
|
||||
fp = _fdopen(_conout, "r");
|
||||
freopen_s(&fp, "CONIN$", "r", stdin);
|
||||
|
||||
_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
_conout = _open_osfhandle((intptr_t)_handle, _O_TEXT);
|
||||
fp = _fdopen(_conout, "w");
|
||||
freopen_s(&fp, "CONOUT$", "w", stdout);
|
||||
|
||||
_handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
_conout = _open_osfhandle((intptr_t)_handle, _O_TEXT);
|
||||
fp = _fdopen(_conout, "w");
|
||||
freopen_s(&fp, "CONOUT$", "w", stderr);
|
||||
|
||||
std::ios::sync_with_stdio();
|
||||
std::wcout.clear();
|
||||
std::cout.clear();
|
||||
std::wcerr.clear();
|
||||
std::cerr.clear();
|
||||
std::wcin.clear();
|
||||
std::cin.clear();
|
||||
|
||||
consoleActive = true;
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
#include <stdbool.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_ttf.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
SDL_Window * window;
|
||||
SDL_Renderer * renderer;
|
||||
|
||||
TTF_Init();
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
window = SDL_CreateWindow("sync-test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 1040, SDL_WINDOW_RESIZABLE);
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
|
||||
SDL_Event event;
|
||||
bool running = true;
|
||||
unsigned int frameCount = 0;
|
||||
Uint32 fpsFrame = 0;
|
||||
Uint32 fpsStart = SDL_GetTicks();
|
||||
float fps = 0.0f;
|
||||
TTF_Font * fpsFont = NULL;
|
||||
SDL_Rect fpsTextRect = {5, 5};
|
||||
SDL_Texture * fpsText = NULL;
|
||||
|
||||
int width = 1000;
|
||||
int boxX = 100;
|
||||
int boxY = 100;
|
||||
|
||||
fpsFont = TTF_OpenFont("C:\\Windows\\Fonts\\cour.ttf", 24);
|
||||
|
||||
while (running)
|
||||
{
|
||||
while (SDL_PollEvent(&event))
|
||||
switch(event.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
running = false;
|
||||
break;
|
||||
|
||||
case SDL_KEYUP:
|
||||
switch(event.key.keysym.scancode)
|
||||
{
|
||||
case SDL_SCANCODE_ESCAPE:
|
||||
running = false;
|
||||
break;
|
||||
|
||||
case SDL_SCANCODE_F11:
|
||||
SDL_SetWindowFullscreen(window, (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
width = event.window.data1;
|
||||
boxX = event.window.data1 / 10;
|
||||
boxY = (event.window.data2 - 40) / 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, SDL_ALPHA_OPAQUE);
|
||||
for (int y = 0; y < 10; ++y)
|
||||
for (int x = 0; x < 10; ++x)
|
||||
{
|
||||
const SDL_Rect rect = { x * boxX, y * boxY + 40, boxX, boxY};
|
||||
if (y * 10 + x == frameCount % 100)
|
||||
SDL_RenderFillRect(renderer, &rect);
|
||||
else
|
||||
SDL_RenderDrawRect(renderer, &rect);
|
||||
}
|
||||
|
||||
if (SDL_GetTicks() - fpsStart > 1000)
|
||||
{
|
||||
const float delta = (float)(SDL_GetTicks() - fpsStart) / 1000.0f;
|
||||
const unsigned int frames = frameCount - fpsFrame;
|
||||
fps = (float)frames / delta;
|
||||
|
||||
fpsStart = SDL_GetTicks();
|
||||
fpsFrame = frameCount;
|
||||
}
|
||||
|
||||
const SDL_Color c = {0x00, 0xff, 0x00, 0xff};
|
||||
char text[128];
|
||||
snprintf(text, sizeof(text), "FPS: %7.4f, Frame: %05u \"F11\" to toggle Full Screen", fps, frameCount);
|
||||
SDL_Surface * fpsSurf = TTF_RenderText_Solid(fpsFont, text, c);
|
||||
if (fpsText)
|
||||
SDL_DestroyTexture(fpsText);
|
||||
fpsText = SDL_CreateTextureFromSurface(renderer, fpsSurf);
|
||||
fpsTextRect.x = width / 2 - fpsSurf->w / 2;
|
||||
fpsTextRect.y = 20 - fpsSurf->h / 2;
|
||||
fpsTextRect.w = fpsSurf->w;
|
||||
fpsTextRect.h = fpsSurf->h;
|
||||
SDL_FreeSurface(fpsSurf);
|
||||
SDL_RenderCopy(renderer, fpsText, NULL, &fpsTextRect);
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
++frameCount;
|
||||
}
|
||||
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
return 0;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="freetype.redist" version="2.6.2.1" targetFramework="native" />
|
||||
<package id="sdl2.v140" version="2.0.4" targetFramework="native" />
|
||||
<package id="sdl2.v140.redist" version="2.0.4" targetFramework="native" />
|
||||
<package id="sdl2_ttf.v140" version="2.0.14" targetFramework="native" />
|
||||
<package id="sdl2_ttf.v140.redist" version="2.0.14" targetFramework="native" />
|
||||
</packages>
|
@ -1,302 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug - NvFBC|Win32">
|
||||
<Configuration>Debug - NvFBC</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug - NvFBC|x64">
|
||||
<Configuration>Debug - NvFBC</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release - NvFBC|Win32">
|
||||
<Configuration>Release - NvFBC</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release - NvFBC|x64">
|
||||
<Configuration>Release - NvFBC</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{6CC4DA30-6FBD-4ACA-9BA6-2DE731032800}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>synctest</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NvFBC|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - NvFBC|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\packages\freetype.redist.2.6.2.1\build\native\freetype.redist.targets" Condition="Exists('..\packages\freetype.redist.2.6.2.1\build\native\freetype.redist.targets')" />
|
||||
<Import Project="..\packages\sdl2.v140.redist.2.0.4\build\native\sdl2.v140.redist.targets" Condition="Exists('..\packages\sdl2.v140.redist.2.0.4\build\native\sdl2.v140.redist.targets')" />
|
||||
<Import Project="..\packages\sdl2_ttf.v140.redist.2.0.14\build\native\sdl2_ttf.v140.redist.targets" Condition="Exists('..\packages\sdl2_ttf.v140.redist.2.0.14\build\native\sdl2_ttf.v140.redist.targets')" />
|
||||
<Import Project="..\packages\sdl2_ttf.v140.2.0.14\build\native\sdl2_ttf.v140.targets" Condition="Exists('..\packages\sdl2_ttf.v140.2.0.14\build\native\sdl2_ttf.v140.targets')" />
|
||||
<Import Project="..\packages\sdl2.v140.2.0.4\build\native\sdl2.v140.targets" Condition="Exists('..\packages\sdl2.v140.2.0.4\build\native\sdl2.v140.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\freetype.redist.2.6.2.1\build\native\freetype.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\freetype.redist.2.6.2.1\build\native\freetype.redist.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\sdl2.v140.redist.2.0.4\build\native\sdl2.v140.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\sdl2.v140.redist.2.0.4\build\native\sdl2.v140.redist.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\sdl2_ttf.v140.redist.2.0.14\build\native\sdl2_ttf.v140.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\sdl2_ttf.v140.redist.2.0.14\build\native\sdl2_ttf.v140.redist.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\sdl2_ttf.v140.2.0.14\build\native\sdl2_ttf.v140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\sdl2_ttf.v140.2.0.14\build\native\sdl2_ttf.v140.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\sdl2.v140.2.0.4\build\native\sdl2.v140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\sdl2.v140.2.0.4\build\native\sdl2.v140.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user