mirror of
https://github.com/thinkonmay/sunshine-sdk.git
synced 2026-01-09 22:21:56 +00:00
fix link errors
This commit is contained in:
parent
d07cb8c0b7
commit
9bc4dd06cc
@ -38,6 +38,7 @@ list(PREPEND PLATFORM_LIBRARIES
|
||||
libstdc++.a
|
||||
libwinpthread.a
|
||||
libssp.a
|
||||
ntdll
|
||||
ksuser
|
||||
wsock32
|
||||
ws2_32
|
||||
@ -47,10 +48,5 @@ list(PREPEND PLATFORM_LIBRARIES
|
||||
userenv
|
||||
synchronization.lib
|
||||
avrt
|
||||
ole32
|
||||
oleaut32
|
||||
imm32
|
||||
winmm
|
||||
version
|
||||
iphlpapi
|
||||
shlwapi)
|
||||
|
||||
@ -640,11 +640,6 @@ namespace platf {
|
||||
void
|
||||
adjust_thread_priority(thread_priority_e priority);
|
||||
|
||||
// Allow OS-specific actions to be taken to prepare for streaming
|
||||
void
|
||||
streaming_will_start();
|
||||
void
|
||||
streaming_will_stop();
|
||||
|
||||
void
|
||||
restart();
|
||||
|
||||
@ -285,16 +285,6 @@ namespace platf {
|
||||
// Unimplemented
|
||||
}
|
||||
|
||||
void
|
||||
streaming_will_start() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void
|
||||
streaming_will_stop() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void
|
||||
restart_on_exit() {
|
||||
char executable[PATH_MAX];
|
||||
|
||||
@ -213,15 +213,7 @@ namespace platf {
|
||||
// Unimplemented
|
||||
}
|
||||
|
||||
void
|
||||
streaming_will_start() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void
|
||||
streaming_will_stop() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void
|
||||
restart_on_exit() {
|
||||
|
||||
@ -162,9 +162,6 @@ namespace platf::dxgi {
|
||||
int
|
||||
init(const ::video::config_t &config, const std::string &display_name);
|
||||
|
||||
void
|
||||
high_precision_sleep(std::chrono::nanoseconds duration);
|
||||
|
||||
capture_e
|
||||
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override;
|
||||
|
||||
@ -263,9 +260,6 @@ namespace platf::dxgi {
|
||||
|
||||
class display_ram_t: public display_base_t {
|
||||
public:
|
||||
virtual capture_e
|
||||
snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor_visible) override;
|
||||
|
||||
std::shared_ptr<img_t>
|
||||
alloc_img() override;
|
||||
int
|
||||
@ -275,9 +269,6 @@ namespace platf::dxgi {
|
||||
std::vector<DXGI_FORMAT>
|
||||
get_supported_capture_formats() override;
|
||||
|
||||
int
|
||||
init(const ::video::config_t &config, const std::string &display_name);
|
||||
|
||||
std::unique_ptr<avcodec_encode_device_t>
|
||||
make_avcodec_encode_device(pix_fmt_e pix_fmt) override;
|
||||
|
||||
@ -288,9 +279,6 @@ namespace platf::dxgi {
|
||||
|
||||
class display_vram_t: public display_base_t, public std::enable_shared_from_this<display_vram_t> {
|
||||
public:
|
||||
virtual capture_e
|
||||
snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor_visible) override;
|
||||
|
||||
std::shared_ptr<img_t>
|
||||
alloc_img() override;
|
||||
int
|
||||
@ -300,9 +288,6 @@ namespace platf::dxgi {
|
||||
std::vector<DXGI_FORMAT>
|
||||
get_supported_capture_formats() override;
|
||||
|
||||
int
|
||||
init(const ::video::config_t &config, const std::string &display_name);
|
||||
|
||||
bool
|
||||
is_codec_supported(std::string_view name, const ::video::config_t &config) override;
|
||||
|
||||
|
||||
@ -386,15 +386,6 @@ namespace platf::dxgi {
|
||||
return { DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8X8_UNORM };
|
||||
}
|
||||
|
||||
int
|
||||
display_ram_t::init(const ::video::config_t &config, const std::string &display_name) {
|
||||
if (display_base_t::init(config, display_name)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
display_ddup_ram_t::init(const ::video::config_t &config, const std::string &display_name) {
|
||||
if (display_base_t::init(config, display_name) || dup.init(this, config)) {
|
||||
|
||||
@ -1414,88 +1414,6 @@ namespace platf::dxgi {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
display_vram_t::init(const ::video::config_t &config, const std::string &display_name) {
|
||||
if (display_base_t::init(config, display_name)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
D3D11_SAMPLER_DESC sampler_desc {};
|
||||
sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
sampler_desc.MinLOD = 0;
|
||||
sampler_desc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
|
||||
auto status = device->CreateSamplerState(&sampler_desc, &sampler_linear);
|
||||
if (FAILED(status)) {
|
||||
BOOST_LOG(error) << "Failed to create point sampler state [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = device->CreateVertexShader(cursor_vs_hlsl->GetBufferPointer(), cursor_vs_hlsl->GetBufferSize(), nullptr, &cursor_vs);
|
||||
if (status) {
|
||||
BOOST_LOG(error) << "Failed to create scene vertex shader [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
int32_t rotation_modifier = display_rotation == DXGI_MODE_ROTATION_UNSPECIFIED ? 0 : display_rotation - 1;
|
||||
int32_t rotation_data[16 / sizeof(int32_t)] { rotation_modifier }; // aligned to 16-byte
|
||||
auto rotation = make_buffer(device.get(), rotation_data);
|
||||
if (!rotation) {
|
||||
BOOST_LOG(error) << "Failed to create display rotation vertex constant buffer";
|
||||
return -1;
|
||||
}
|
||||
device_ctx->VSSetConstantBuffers(2, 1, &rotation);
|
||||
}
|
||||
|
||||
if (config.dynamicRange && is_hdr()) {
|
||||
// This shader will normalize scRGB white levels to a user-defined white level
|
||||
status = device->CreatePixelShader(cursor_ps_normalize_white_hlsl->GetBufferPointer(), cursor_ps_normalize_white_hlsl->GetBufferSize(), nullptr, &cursor_ps);
|
||||
if (status) {
|
||||
BOOST_LOG(error) << "Failed to create cursor blending (normalized white) pixel shader [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Use a 300 nit target for the mouse cursor. We should really get
|
||||
// the user's SDR white level in nits, but there is no API that
|
||||
// provides that information to Win32 apps.
|
||||
float white_multiplier_data[16 / sizeof(float)] { 300.0f / 80.f }; // aligned to 16-byte
|
||||
auto white_multiplier = make_buffer(device.get(), white_multiplier_data);
|
||||
if (!white_multiplier) {
|
||||
BOOST_LOG(warning) << "Failed to create cursor blending (normalized white) white multiplier constant buffer";
|
||||
return -1;
|
||||
}
|
||||
|
||||
device_ctx->PSSetConstantBuffers(1, 1, &white_multiplier);
|
||||
}
|
||||
else {
|
||||
status = device->CreatePixelShader(cursor_ps_hlsl->GetBufferPointer(), cursor_ps_hlsl->GetBufferSize(), nullptr, &cursor_ps);
|
||||
if (status) {
|
||||
BOOST_LOG(error) << "Failed to create cursor blending pixel shader [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
blend_alpha = make_blend(device.get(), true, false);
|
||||
blend_invert = make_blend(device.get(), true, true);
|
||||
blend_disable = make_blend(device.get(), false, false);
|
||||
|
||||
if (!blend_disable || !blend_alpha || !blend_invert) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
device_ctx->OMSetBlendState(blend_disable.get(), nullptr, 0xFFFFFFFFu);
|
||||
device_ctx->PSSetSamplers(0, 1, &sampler_linear);
|
||||
device_ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next frame from the Windows.Graphics.Capture API and copy it into a new snapshot texture.
|
||||
* @param pull_free_image_cb call this to get a new free image from the video subsystem.
|
||||
|
||||
@ -1080,145 +1080,7 @@ namespace platf {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
streaming_will_start() {
|
||||
static std::once_flag load_wlanapi_once_flag;
|
||||
std::call_once(load_wlanapi_once_flag, []() {
|
||||
// wlanapi.dll is not installed by default on Windows Server, so we load it dynamically
|
||||
HMODULE wlanapi = LoadLibraryExA("wlanapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (!wlanapi) {
|
||||
BOOST_LOG(debug) << "wlanapi.dll is not available on this OS"sv;
|
||||
return;
|
||||
}
|
||||
|
||||
fn_WlanOpenHandle = (decltype(fn_WlanOpenHandle)) GetProcAddress(wlanapi, "WlanOpenHandle");
|
||||
fn_WlanCloseHandle = (decltype(fn_WlanCloseHandle)) GetProcAddress(wlanapi, "WlanCloseHandle");
|
||||
fn_WlanFreeMemory = (decltype(fn_WlanFreeMemory)) GetProcAddress(wlanapi, "WlanFreeMemory");
|
||||
fn_WlanEnumInterfaces = (decltype(fn_WlanEnumInterfaces)) GetProcAddress(wlanapi, "WlanEnumInterfaces");
|
||||
fn_WlanSetInterface = (decltype(fn_WlanSetInterface)) GetProcAddress(wlanapi, "WlanSetInterface");
|
||||
|
||||
if (!fn_WlanOpenHandle || !fn_WlanCloseHandle || !fn_WlanFreeMemory || !fn_WlanEnumInterfaces || !fn_WlanSetInterface) {
|
||||
BOOST_LOG(error) << "wlanapi.dll is missing exports?"sv;
|
||||
|
||||
fn_WlanOpenHandle = nullptr;
|
||||
fn_WlanCloseHandle = nullptr;
|
||||
fn_WlanFreeMemory = nullptr;
|
||||
fn_WlanEnumInterfaces = nullptr;
|
||||
fn_WlanSetInterface = nullptr;
|
||||
|
||||
FreeLibrary(wlanapi);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Enable MMCSS scheduling for DWM
|
||||
DwmEnableMMCSS(true);
|
||||
|
||||
// Reduce timer period to 1ms
|
||||
timeBeginPeriod(1);
|
||||
|
||||
// Promote ourselves to high priority class
|
||||
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
||||
|
||||
// Modify NVIDIA control panel settings again, in case they have been changed externally since sunshine launch
|
||||
if (nvprefs_instance.load()) {
|
||||
if (!nvprefs_instance.owning_undo_file()) {
|
||||
nvprefs_instance.restore_from_and_delete_undo_file_if_exists();
|
||||
}
|
||||
nvprefs_instance.modify_application_profile();
|
||||
nvprefs_instance.modify_global_profile();
|
||||
nvprefs_instance.unload();
|
||||
}
|
||||
|
||||
// Enable low latency mode on all connected WLAN NICs if wlanapi.dll is available
|
||||
if (fn_WlanOpenHandle) {
|
||||
DWORD negotiated_version;
|
||||
|
||||
if (fn_WlanOpenHandle(WLAN_API_MAKE_VERSION(2, 0), nullptr, &negotiated_version, &wlan_handle) == ERROR_SUCCESS) {
|
||||
PWLAN_INTERFACE_INFO_LIST wlan_interface_list;
|
||||
|
||||
if (fn_WlanEnumInterfaces(wlan_handle, nullptr, &wlan_interface_list) == ERROR_SUCCESS) {
|
||||
for (DWORD i = 0; i < wlan_interface_list->dwNumberOfItems; i++) {
|
||||
if (wlan_interface_list->InterfaceInfo[i].isState == wlan_interface_state_connected) {
|
||||
// Enable media streaming mode for 802.11 wireless interfaces to reduce latency and
|
||||
// unnecessary background scanning operations that cause packet loss and jitter.
|
||||
//
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/network/oid-wdi-set-connection-quality
|
||||
// https://docs.microsoft.com/en-us/previous-versions/windows/hardware/wireless/native-802-11-media-streaming
|
||||
BOOL value = TRUE;
|
||||
auto error = fn_WlanSetInterface(wlan_handle, &wlan_interface_list->InterfaceInfo[i].InterfaceGuid,
|
||||
wlan_intf_opcode_media_streaming_mode, sizeof(value), &value, nullptr);
|
||||
if (error == ERROR_SUCCESS) {
|
||||
BOOST_LOG(info) << "WLAN interface "sv << i << " is now in low latency mode"sv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn_WlanFreeMemory(wlan_interface_list);
|
||||
}
|
||||
else {
|
||||
fn_WlanCloseHandle(wlan_handle, nullptr);
|
||||
wlan_handle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no mouse connected, enable Mouse Keys to force the cursor to appear
|
||||
if (!GetSystemMetrics(SM_MOUSEPRESENT)) {
|
||||
BOOST_LOG(info) << "A mouse was not detected. Sunshine will enable Mouse Keys while streaming to force the mouse cursor to appear.";
|
||||
|
||||
// Get the current state of Mouse Keys so we can restore it when streaming is over
|
||||
previous_mouse_keys_state.cbSize = sizeof(previous_mouse_keys_state);
|
||||
if (SystemParametersInfoW(SPI_GETMOUSEKEYS, 0, &previous_mouse_keys_state, 0)) {
|
||||
MOUSEKEYS new_mouse_keys_state = {};
|
||||
|
||||
// Enable Mouse Keys
|
||||
new_mouse_keys_state.cbSize = sizeof(new_mouse_keys_state);
|
||||
new_mouse_keys_state.dwFlags = MKF_MOUSEKEYSON | MKF_AVAILABLE;
|
||||
new_mouse_keys_state.iMaxSpeed = 10;
|
||||
new_mouse_keys_state.iTimeToMaxSpeed = 1000;
|
||||
if (SystemParametersInfoW(SPI_SETMOUSEKEYS, 0, &new_mouse_keys_state, 0)) {
|
||||
// Remember to restore the previous settings when we stop streaming
|
||||
enabled_mouse_keys = true;
|
||||
}
|
||||
else {
|
||||
auto winerr = GetLastError();
|
||||
BOOST_LOG(warning) << "Unable to enable Mouse Keys: "sv << winerr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto winerr = GetLastError();
|
||||
BOOST_LOG(warning) << "Unable to get current state of Mouse Keys: "sv << winerr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
streaming_will_stop() {
|
||||
// Demote ourselves back to normal priority class
|
||||
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
|
||||
|
||||
// End our 1ms timer request
|
||||
timeEndPeriod(1);
|
||||
|
||||
// Disable MMCSS scheduling for DWM
|
||||
DwmEnableMMCSS(false);
|
||||
|
||||
// Closing our WLAN client handle will undo our optimizations
|
||||
if (wlan_handle != nullptr) {
|
||||
fn_WlanCloseHandle(wlan_handle, nullptr);
|
||||
wlan_handle = nullptr;
|
||||
}
|
||||
|
||||
// Restore Mouse Keys back to the previous settings if we turned it on
|
||||
if (enabled_mouse_keys) {
|
||||
enabled_mouse_keys = false;
|
||||
if (!SystemParametersInfoW(SPI_SETMOUSEKEYS, 0, &previous_mouse_keys_state, 0)) {
|
||||
auto winerr = GetLastError();
|
||||
BOOST_LOG(warning) << "Unable to restore original state of Mouse Keys: "sv << winerr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
restart_on_exit() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user