move sunshine to src

- this will allow for common cpp workflow files within org
This commit is contained in:
ReenigneArcher 2022-08-07 23:37:57 -04:00
commit a4acaf15b0
No known key found for this signature in database
GPG key ID: 0CA6A47B0630EA9B
86 changed files with 3031 additions and 3031 deletions

View file

@ -6,7 +6,7 @@ on:
branches: [nightly] branches: [nightly]
paths: # prevents workflow from running unless these files change paths: # prevents workflow from running unless these files change
- '.github/workflows/localize.yml' - '.github/workflows/localize.yml'
- 'sunshine/**' - 'src/**'
- 'locale/sunshine.po' - 'locale/sunshine.po'
workflow_dispatch: workflow_dispatch:

View file

@ -100,18 +100,18 @@ if(WIN32)
if(NOT DEFINED SUNSHINE_ICON_PATH) if(NOT DEFINED SUNSHINE_ICON_PATH)
set(SUNSHINE_ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/sunshine.ico") set(SUNSHINE_ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/sunshine.ico")
endif() endif()
configure_file(sunshine/platform/windows/windows.rs.in windows.rc @ONLY) configure_file(src/platform/windows/windows.rs.in windows.rc @ONLY)
set(PLATFORM_TARGET_FILES set(PLATFORM_TARGET_FILES
"${CMAKE_CURRENT_BINARY_DIR}/windows.rc" "${CMAKE_CURRENT_BINARY_DIR}/windows.rc"
sunshine/platform/windows/publish.cpp src/platform/windows/publish.cpp
sunshine/platform/windows/misc.h src/platform/windows/misc.h
sunshine/platform/windows/misc.cpp src/platform/windows/misc.cpp
sunshine/platform/windows/input.cpp src/platform/windows/input.cpp
sunshine/platform/windows/display.h src/platform/windows/display.h
sunshine/platform/windows/display_base.cpp src/platform/windows/display_base.cpp
sunshine/platform/windows/display_vram.cpp src/platform/windows/display_vram.cpp
sunshine/platform/windows/display_ram.cpp src/platform/windows/display_ram.cpp
sunshine/platform/windows/audio.cpp src/platform/windows/audio.cpp
third-party/ViGEmClient/src/ViGEmClient.cpp third-party/ViGEmClient/src/ViGEmClient.cpp
third-party/ViGEmClient/include/ViGEm/Client.h third-party/ViGEmClient/include/ViGEm/Client.h
third-party/ViGEmClient/include/ViGEm/Common.h third-party/ViGEmClient/include/ViGEm/Common.h
@ -180,19 +180,19 @@ elseif(APPLE)
set(APPLE_PLIST_FILE ${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/Info.plist) set(APPLE_PLIST_FILE ${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/Info.plist)
set(PLATFORM_TARGET_FILES set(PLATFORM_TARGET_FILES
sunshine/platform/macos/av_audio.h src/platform/macos/av_audio.h
sunshine/platform/macos/av_audio.m src/platform/macos/av_audio.m
sunshine/platform/macos/av_img_t.h src/platform/macos/av_img_t.h
sunshine/platform/macos/av_video.h src/platform/macos/av_video.h
sunshine/platform/macos/av_video.m src/platform/macos/av_video.m
sunshine/platform/macos/display.mm src/platform/macos/display.mm
sunshine/platform/macos/input.cpp src/platform/macos/input.cpp
sunshine/platform/macos/microphone.mm src/platform/macos/microphone.mm
sunshine/platform/macos/misc.cpp src/platform/macos/misc.cpp
sunshine/platform/macos/misc.h src/platform/macos/misc.h
sunshine/platform/macos/nv12_zero_device.cpp src/platform/macos/nv12_zero_device.cpp
sunshine/platform/macos/nv12_zero_device.h src/platform/macos/nv12_zero_device.h
sunshine/platform/macos/publish.cpp src/platform/macos/publish.cpp
third-party/TPCircularBuffer/TPCircularBuffer.c third-party/TPCircularBuffer/TPCircularBuffer.c
third-party/TPCircularBuffer/TPCircularBuffer.h third-party/TPCircularBuffer/TPCircularBuffer.h
${APPLE_PLIST_FILE}) ${APPLE_PLIST_FILE})
@ -242,14 +242,14 @@ else()
if(X11_FOUND) if(X11_FOUND)
add_compile_definitions(SUNSHINE_BUILD_X11) add_compile_definitions(SUNSHINE_BUILD_X11)
include_directories(${X11_INCLUDE_DIR}) include_directories(${X11_INCLUDE_DIR})
list(APPEND PLATFORM_TARGET_FILES sunshine/platform/linux/x11grab.cpp) list(APPEND PLATFORM_TARGET_FILES src/platform/linux/x11grab.cpp)
endif() endif()
if(CUDA_FOUND) if(CUDA_FOUND)
include_directories(third-party/nvfbc) include_directories(third-party/nvfbc)
list(APPEND PLATFORM_TARGET_FILES list(APPEND PLATFORM_TARGET_FILES
sunshine/platform/linux/cuda.cu src/platform/linux/cuda.cu
sunshine/platform/linux/cuda.cpp src/platform/linux/cuda.cpp
third-party/nvfbc/NvFBC.h) third-party/nvfbc/NvFBC.h)
add_compile_definitions(SUNSHINE_BUILD_CUDA) add_compile_definitions(SUNSHINE_BUILD_CUDA)
@ -259,7 +259,7 @@ else()
add_compile_definitions(SUNSHINE_BUILD_DRM) add_compile_definitions(SUNSHINE_BUILD_DRM)
include_directories(${LIBDRM_INCLUDE_DIRS} ${LIBCAP_INCLUDE_DIRS}) include_directories(${LIBDRM_INCLUDE_DIRS} ${LIBCAP_INCLUDE_DIRS})
list(APPEND PLATFORM_LIBRARIES ${LIBDRM_LIBRARIES} ${LIBCAP_LIBRARIES}) list(APPEND PLATFORM_LIBRARIES ${LIBDRM_LIBRARIES} ${LIBCAP_LIBRARIES})
list(APPEND PLATFORM_TARGET_FILES sunshine/platform/linux/kmsgrab.cpp) list(APPEND PLATFORM_TARGET_FILES src/platform/linux/kmsgrab.cpp)
list(APPEND SUNSHINE_DEFINITIONS EGL_NO_X11=1) list(APPEND SUNSHINE_DEFINITIONS EGL_NO_X11=1)
elseif(LIBDRM_FOUND) elseif(LIBDRM_FOUND)
message(WARNING "Found libdrm, yet there is no libcap") message(WARNING "Found libdrm, yet there is no libcap")
@ -301,26 +301,26 @@ else()
list(APPEND PLATFORM_LIBRARIES ${WAYLAND_LIBRARIES}) list(APPEND PLATFORM_LIBRARIES ${WAYLAND_LIBRARIES})
list(APPEND PLATFORM_TARGET_FILES list(APPEND PLATFORM_TARGET_FILES
sunshine/platform/linux/wlgrab.cpp src/platform/linux/wlgrab.cpp
sunshine/platform/linux/wayland.cpp) src/platform/linux/wayland.cpp)
endif() endif()
if(NOT ${X11_FOUND} AND NOT (${LIBDRM_FOUND} AND ${LIBCAP_FOUND}) AND NOT ${WAYLAND_FOUND} AND NOT ${}) if(NOT ${X11_FOUND} AND NOT (${LIBDRM_FOUND} AND ${LIBCAP_FOUND}) AND NOT ${WAYLAND_FOUND} AND NOT ${})
message(FATAL_ERROR "Couldn't find either x11, wayland, cuda or (libdrm and libcap)") message(FATAL_ERROR "Couldn't find either x11, wayland, cuda or (libdrm and libcap)")
endif() endif()
list(APPEND PLATFORM_TARGET_FILES list(APPEND PLATFORM_TARGET_FILES
sunshine/platform/linux/publish.cpp src/platform/linux/publish.cpp
sunshine/platform/linux/vaapi.h src/platform/linux/vaapi.h
sunshine/platform/linux/vaapi.cpp src/platform/linux/vaapi.cpp
sunshine/platform/linux/cuda.h src/platform/linux/cuda.h
sunshine/platform/linux/graphics.h src/platform/linux/graphics.h
sunshine/platform/linux/graphics.cpp src/platform/linux/graphics.cpp
sunshine/platform/linux/misc.h src/platform/linux/misc.h
sunshine/platform/linux/misc.cpp src/platform/linux/misc.cpp
sunshine/platform/linux/audio.cpp src/platform/linux/audio.cpp
sunshine/platform/linux/input.cpp src/platform/linux/input.cpp
sunshine/platform/linux/x11grab.h src/platform/linux/x11grab.h
sunshine/platform/linux/wayland.h src/platform/linux/wayland.h
third-party/glad/src/egl.c third-party/glad/src/egl.c
third-party/glad/src/gl.c third-party/glad/src/gl.c
third-party/glad/include/EGL/eglplatform.h third-party/glad/include/EGL/eglplatform.h
@ -356,47 +356,47 @@ set(SUNSHINE_TARGET_FILES
third-party/moonlight-common-c/src/Rtsp.h third-party/moonlight-common-c/src/Rtsp.h
third-party/moonlight-common-c/src/RtspParser.c third-party/moonlight-common-c/src/RtspParser.c
third-party/moonlight-common-c/src/Video.h third-party/moonlight-common-c/src/Video.h
sunshine/upnp.cpp src/upnp.cpp
sunshine/upnp.h src/upnp.h
sunshine/cbs.cpp src/cbs.cpp
sunshine/utility.h src/utility.h
sunshine/uuid.h src/uuid.h
sunshine/config.h src/config.h
sunshine/config.cpp src/config.cpp
sunshine/main.cpp src/main.cpp
sunshine/main.h src/main.h
sunshine/crypto.cpp src/crypto.cpp
sunshine/crypto.h src/crypto.h
sunshine/nvhttp.cpp src/nvhttp.cpp
sunshine/nvhttp.h src/nvhttp.h
sunshine/httpcommon.cpp src/httpcommon.cpp
sunshine/httpcommon.h src/httpcommon.h
sunshine/confighttp.cpp src/confighttp.cpp
sunshine/confighttp.h src/confighttp.h
sunshine/rtsp.cpp src/rtsp.cpp
sunshine/rtsp.h src/rtsp.h
sunshine/stream.cpp src/stream.cpp
sunshine/stream.h src/stream.h
sunshine/video.cpp src/video.cpp
sunshine/video.h src/video.h
sunshine/input.cpp src/input.cpp
sunshine/input.h src/input.h
sunshine/audio.cpp src/audio.cpp
sunshine/audio.h src/audio.h
sunshine/platform/common.h src/platform/common.h
sunshine/process.cpp src/process.cpp
sunshine/process.h src/process.h
sunshine/network.cpp src/network.cpp
sunshine/network.h src/network.h
sunshine/move_by_copy.h src/move_by_copy.h
sunshine/task_pool.h src/task_pool.h
sunshine/thread_pool.h src/thread_pool.h
sunshine/thread_safe.h src/thread_safe.h
sunshine/sync.h src/sync.h
sunshine/round_robin.h src/round_robin.h
${PLATFORM_TARGET_FILES}) ${PLATFORM_TARGET_FILES})
set_source_files_properties(sunshine/upnp.cpp PROPERTIES COMPILE_FLAGS -Wno-pedantic) set_source_files_properties(src/upnp.cpp PROPERTIES COMPILE_FLAGS -Wno-pedantic)
include_directories( include_directories(
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
@ -414,7 +414,7 @@ string(TOUPPER "x${CMAKE_BUILD_TYPE}" BUILD_TYPE)
if("${BUILD_TYPE}" STREQUAL "XDEBUG") if("${BUILD_TYPE}" STREQUAL "XDEBUG")
list(APPEND SUNSHINE_COMPILE_OPTIONS -O0 -ggdb3) list(APPEND SUNSHINE_COMPILE_OPTIONS -O0 -ggdb3)
if(WIN32) if(WIN32)
set_source_files_properties(sunshine/nvhttp.cpp PROPERTIES COMPILE_FLAGS -O2) set_source_files_properties(src/nvhttp.cpp PROPERTIES COMPILE_FLAGS -O2)
endif() endif()
else() else()
add_definitions(-DNDEBUG) add_definitions(-DNDEBUG)

View file

@ -67,7 +67,7 @@ any of the following paths are modified.
.. code-block:: yaml .. code-block:: yaml
- 'sunshine/**' - 'src/**'
When testing locally it may be desirable to manually extract, initialize, update, and compile strings. Python is When testing locally it may be desirable to manually extract, initialize, update, and compile strings. Python is
required for this, along with the python dependencies in the `./scripts/requirements.txt` file. Additionally, required for this, along with the python dependencies in the `./scripts/requirements.txt` file. Additionally,

View file

@ -11,8 +11,8 @@
#include <mutex> #include <mutex>
#include <string> #include <string>
#include "sunshine/thread_safe.h" #include "src/thread_safe.h"
#include "sunshine/utility.h" #include "src/utility.h"
struct sockaddr; struct sockaddr;
struct AVFrame; struct AVFrame;

View file

@ -10,11 +10,11 @@
#include <pulse/pulseaudio.h> #include <pulse/pulseaudio.h>
#include <pulse/simple.h> #include <pulse/simple.h>
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/config.h" #include "src/config.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/thread_safe.h" #include "src/thread_safe.h"
namespace platf { namespace platf {
using namespace std::literals; using namespace std::literals;

View file

@ -11,8 +11,8 @@ extern "C" {
#include "cuda.h" #include "cuda.h"
#include "graphics.h" #include "graphics.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/utility.h" #include "src/utility.h"
#include "wayland.h" #include "wayland.h"
#define SUNSHINE_STRINGVIEW_HELPER(x) x##sv #define SUNSHINE_STRINGVIEW_HELPER(x) x##sv

View file

@ -1,5 +1,5 @@
#include "graphics.h" #include "graphics.h"
#include "sunshine/video.h" #include "src/video.h"
#include <fcntl.h> #include <fcntl.h>

View file

@ -8,9 +8,9 @@
#include <glad/gl.h> #include <glad/gl.h>
#include "misc.h" #include "misc.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/utility.h" #include "src/utility.h"
#define SUNSHINE_STRINGIFY_HELPER(x) #x #define SUNSHINE_STRINGIFY_HELPER(x) #x
#define SUNSHINE_STRINGIFY(x) SUNSHINE_STRINGIFY_HELPER(x) #define SUNSHINE_STRINGIFY(x) SUNSHINE_STRINGIFY_HELPER(x)

View file

@ -9,11 +9,11 @@
#include <cstring> #include <cstring>
#include <filesystem> #include <filesystem>
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/utility.h" #include "src/utility.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
// Support older versions // Support older versions
#ifndef REL_HWHEEL_HI_RES #ifndef REL_HWHEEL_HI_RES

View file

@ -8,10 +8,10 @@
#include <filesystem> #include <filesystem>
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/round_robin.h" #include "src/round_robin.h"
#include "sunshine/utility.h" #include "src/utility.h"
// Cursor rendering support through x11 // Cursor rendering support through x11
#include "graphics.h" #include "graphics.h"

View file

@ -11,8 +11,8 @@
#include "misc.h" #include "misc.h"
#include "vaapi.h" #include "vaapi.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#ifdef __GNUC__ #ifdef __GNUC__
#define SUNSHINE_GNUC_EXTENSION __extension__ #define SUNSHINE_GNUC_EXTENSION __extension__

View file

@ -4,7 +4,7 @@
#include <unistd.h> #include <unistd.h>
#include <vector> #include <vector>
#include "sunshine/utility.h" #include "src/utility.h"
KITTY_USING_MOVE_T(file_t, int, -1, { KITTY_USING_MOVE_T(file_t, int, -1, {
if(el >= 0) { if(el >= 0) {

View file

@ -3,10 +3,10 @@
#include <thread> #include <thread>
#include "misc.h" #include "misc.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/nvhttp.h" #include "src/nvhttp.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/utility.h" #include "src/utility.h"
using namespace std::literals; using namespace std::literals;

View file

@ -9,10 +9,10 @@ extern "C" {
#include "graphics.h" #include "graphics.h"
#include "misc.h" #include "misc.h"
#include "sunshine/config.h" #include "src/config.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/utility.h" #include "src/utility.h"
using namespace std::literals; using namespace std::literals;

View file

@ -2,7 +2,7 @@
#define SUNSHINE_VAAPI_H #define SUNSHINE_VAAPI_H
#include "misc.h" #include "misc.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
namespace egl { namespace egl {
struct surface_descriptor_t; struct surface_descriptor_t;

View file

@ -4,10 +4,10 @@
#include <cstdlib> #include <cstdlib>
#include "graphics.h" #include "graphics.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/round_robin.h" #include "src/round_robin.h"
#include "sunshine/utility.h" #include "src/utility.h"
#include "wayland.h" #include "wayland.h"
extern const wl_interface wl_output_interface; extern const wl_interface wl_output_interface;

View file

@ -1,6 +1,6 @@
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/main.h" #include "src/main.h"
#include "vaapi.h" #include "vaapi.h"
#include "wayland.h" #include "wayland.h"

View file

@ -2,7 +2,7 @@
// Created by loki on 6/21/19. // Created by loki on 6/21/19.
// //
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include <fstream> #include <fstream>
@ -16,9 +16,9 @@
#include <xcb/shm.h> #include <xcb/shm.h>
#include <xcb/xfixes.h> #include <xcb/xfixes.h>
#include "sunshine/config.h" #include "src/config.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/task_pool.h" #include "src/task_pool.h"
#include "cuda.h" #include "cuda.h"
#include "graphics.h" #include "graphics.h"

View file

@ -3,8 +3,8 @@
#include <optional> #include <optional>
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/utility.h" #include "src/utility.h"
// X11 Display // X11 Display
extern "C" struct _XDisplay; extern "C" struct _XDisplay;

View file

@ -1,7 +1,7 @@
#ifndef av_img_t_h #ifndef av_img_t_h
#define av_img_t_h #define av_img_t_h
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include <CoreMedia/CoreMedia.h> #include <CoreMedia/CoreMedia.h>
#include <CoreVideo/CoreVideo.h> #include <CoreVideo/CoreVideo.h>

View file

@ -1,10 +1,10 @@
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/platform/macos/av_img_t.h" #include "src/platform/macos/av_img_t.h"
#include "sunshine/platform/macos/av_video.h" #include "src/platform/macos/av_video.h"
#include "sunshine/platform/macos/nv12_zero_device.h" #include "src/platform/macos/nv12_zero_device.h"
#include "sunshine/config.h" #include "src/config.h"
#include "sunshine/main.h" #include "src/main.h"
namespace fs = std::filesystem; namespace fs = std::filesystem;

View file

@ -2,9 +2,9 @@
#include <mach/mach.h> #include <mach/mach.h>
#include <mach/mach_time.h> #include <mach/mach_time.h>
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/utility.h" #include "src/utility.h"
// Delay for a double click // Delay for a double click
// FIXME: we probably want to make this configurable // FIXME: we probably want to make this configurable

View file

@ -1,8 +1,8 @@
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/platform/macos/av_audio.h" #include "src/platform/macos/av_audio.h"
#include "sunshine/config.h" #include "src/config.h"
#include "sunshine/main.h" #include "src/main.h"
namespace platf { namespace platf {
using namespace std::literals; using namespace std::literals;

View file

@ -6,8 +6,8 @@
#include <pwd.h> #include <pwd.h>
#include "misc.h" #include "misc.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
using namespace std::literals; using namespace std::literals;
namespace fs = std::filesystem; namespace fs = std::filesystem;

View file

@ -1,7 +1,7 @@
#include "sunshine/platform/macos/nv12_zero_device.h" #include "src/platform/macos/nv12_zero_device.h"
#include "sunshine/platform/macos/av_img_t.h" #include "src/platform/macos/av_img_t.h"
#include "sunshine/video.h" #include "src/video.h"
extern "C" { extern "C" {
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"

View file

@ -1,7 +1,7 @@
#ifndef vtdevice_h #ifndef vtdevice_h
#define vtdevice_h #define vtdevice_h
#include "sunshine/platform/common.h" #include "src/platform/common.h"
namespace platf { namespace platf {

View file

@ -3,10 +3,10 @@
#include <thread> #include <thread>
#include "misc.h" #include "misc.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/nvhttp.h" #include "src/nvhttp.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/utility.h" #include "src/utility.h"
using namespace std::literals; using namespace std::literals;

View file

@ -1,164 +1,164 @@
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// PolicyConfig.h // PolicyConfig.h
// Undocumented COM-interface IPolicyConfig. // Undocumented COM-interface IPolicyConfig.
// Use for set default audio render endpoint // Use for set default audio render endpoint
// @author EreTIk // @author EreTIk
// http://eretik.omegahg.com/ // http://eretik.omegahg.com/
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#pragma once #pragma once
#ifdef __MINGW32__ #ifdef __MINGW32__
#undef DEFINE_GUID #undef DEFINE_GUID
#ifdef __cplusplus #ifdef __cplusplus
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) EXTERN_C const GUID DECLSPEC_SELECTANY name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) EXTERN_C const GUID DECLSPEC_SELECTANY name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#else #else
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID DECLSPEC_SELECTANY name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID DECLSPEC_SELECTANY name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#endif #endif
DEFINE_GUID(IID_IPolicyConfig, 0xf8679f50, 0x850a, 0x41cf, 0x9c, 0x72, 0x43, 0x0f, 0x29, 0x02, 0x90, 0xc8); DEFINE_GUID(IID_IPolicyConfig, 0xf8679f50, 0x850a, 0x41cf, 0x9c, 0x72, 0x43, 0x0f, 0x29, 0x02, 0x90, 0xc8);
DEFINE_GUID(CLSID_CPolicyConfigClient, 0x870af99c, 0x171d, 0x4f9e, 0xaf, 0x0d, 0xe6, 0x3d, 0xf4, 0x0c, 0x2b, 0xc9); DEFINE_GUID(CLSID_CPolicyConfigClient, 0x870af99c, 0x171d, 0x4f9e, 0xaf, 0x0d, 0xe6, 0x3d, 0xf4, 0x0c, 0x2b, 0xc9);
#endif #endif
interface DECLSPEC_UUID("f8679f50-850a-41cf-9c72-430f290290c8") IPolicyConfig; interface DECLSPEC_UUID("f8679f50-850a-41cf-9c72-430f290290c8") IPolicyConfig;
class DECLSPEC_UUID("870af99c-171d-4f9e-af0d-e63df40c2bc9") CPolicyConfigClient; class DECLSPEC_UUID("870af99c-171d-4f9e-af0d-e63df40c2bc9") CPolicyConfigClient;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// class CPolicyConfigClient // class CPolicyConfigClient
// {870af99c-171d-4f9e-af0d-e63df40c2bc9} // {870af99c-171d-4f9e-af0d-e63df40c2bc9}
// //
// interface IPolicyConfig // interface IPolicyConfig
// {f8679f50-850a-41cf-9c72-430f290290c8} // {f8679f50-850a-41cf-9c72-430f290290c8}
// //
// Query interface: // Query interface:
// CComPtr<IPolicyConfig> PolicyConfig; // CComPtr<IPolicyConfig> PolicyConfig;
// PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigClient)); // PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigClient));
// //
// @compatible: Windows 7 and Later // @compatible: Windows 7 and Later
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
interface IPolicyConfig : public IUnknown { interface IPolicyConfig : public IUnknown {
public: public:
virtual HRESULT GetMixFormat( virtual HRESULT GetMixFormat(
PCWSTR, PCWSTR,
WAVEFORMATEX **); WAVEFORMATEX **);
virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat(
PCWSTR, PCWSTR,
INT, INT,
WAVEFORMATEX **); WAVEFORMATEX **);
virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat(
PCWSTR); PCWSTR);
virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat(
PCWSTR, PCWSTR,
WAVEFORMATEX *, WAVEFORMATEX *,
WAVEFORMATEX *); WAVEFORMATEX *);
virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod(
PCWSTR, PCWSTR,
INT, INT,
PINT64, PINT64,
PINT64); PINT64);
virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod(
PCWSTR, PCWSTR,
PINT64); PINT64);
virtual HRESULT STDMETHODCALLTYPE GetShareMode( virtual HRESULT STDMETHODCALLTYPE GetShareMode(
PCWSTR, PCWSTR,
struct DeviceShareMode *); struct DeviceShareMode *);
virtual HRESULT STDMETHODCALLTYPE SetShareMode( virtual HRESULT STDMETHODCALLTYPE SetShareMode(
PCWSTR, PCWSTR,
struct DeviceShareMode *); struct DeviceShareMode *);
virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( virtual HRESULT STDMETHODCALLTYPE GetPropertyValue(
PCWSTR, PCWSTR,
const PROPERTYKEY &, const PROPERTYKEY &,
PROPVARIANT *); PROPVARIANT *);
virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( virtual HRESULT STDMETHODCALLTYPE SetPropertyValue(
PCWSTR, PCWSTR,
const PROPERTYKEY &, const PROPERTYKEY &,
PROPVARIANT *); PROPVARIANT *);
virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint(
PCWSTR wszDeviceId, PCWSTR wszDeviceId,
ERole eRole); ERole eRole);
virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility(
PCWSTR, PCWSTR,
INT); INT);
}; };
interface DECLSPEC_UUID("568b9108-44bf-40b4-9006-86afe5b5a620") IPolicyConfigVista; interface DECLSPEC_UUID("568b9108-44bf-40b4-9006-86afe5b5a620") IPolicyConfigVista;
class DECLSPEC_UUID("294935CE-F637-4E7C-A41B-AB255460B862") CPolicyConfigVistaClient; class DECLSPEC_UUID("294935CE-F637-4E7C-A41B-AB255460B862") CPolicyConfigVistaClient;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// class CPolicyConfigVistaClient // class CPolicyConfigVistaClient
// {294935CE-F637-4E7C-A41B-AB255460B862} // {294935CE-F637-4E7C-A41B-AB255460B862}
// //
// interface IPolicyConfigVista // interface IPolicyConfigVista
// {568b9108-44bf-40b4-9006-86afe5b5a620} // {568b9108-44bf-40b4-9006-86afe5b5a620}
// //
// Query interface: // Query interface:
// CComPtr<IPolicyConfigVista> PolicyConfig; // CComPtr<IPolicyConfigVista> PolicyConfig;
// PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigVistaClient)); // PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigVistaClient));
// //
// @compatible: Windows Vista and Later // @compatible: Windows Vista and Later
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
interface IPolicyConfigVista : public IUnknown { interface IPolicyConfigVista : public IUnknown {
public: public:
virtual HRESULT GetMixFormat( virtual HRESULT GetMixFormat(
PCWSTR, PCWSTR,
WAVEFORMATEX **); // not available on Windows 7, use method from IPolicyConfig WAVEFORMATEX **); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat(
PCWSTR, PCWSTR,
INT, INT,
WAVEFORMATEX **); WAVEFORMATEX **);
virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat(
PCWSTR, PCWSTR,
WAVEFORMATEX *, WAVEFORMATEX *,
WAVEFORMATEX *); WAVEFORMATEX *);
virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod(
PCWSTR, PCWSTR,
INT, INT,
PINT64, PINT64,
PINT64); // not available on Windows 7, use method from IPolicyConfig PINT64); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod(
PCWSTR, PCWSTR,
PINT64); // not available on Windows 7, use method from IPolicyConfig PINT64); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE GetShareMode( virtual HRESULT STDMETHODCALLTYPE GetShareMode(
PCWSTR, PCWSTR,
struct DeviceShareMode *); // not available on Windows 7, use method from IPolicyConfig struct DeviceShareMode *); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE SetShareMode( virtual HRESULT STDMETHODCALLTYPE SetShareMode(
PCWSTR, PCWSTR,
struct DeviceShareMode *); // not available on Windows 7, use method from IPolicyConfig struct DeviceShareMode *); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( virtual HRESULT STDMETHODCALLTYPE GetPropertyValue(
PCWSTR, PCWSTR,
const PROPERTYKEY &, const PROPERTYKEY &,
PROPVARIANT *); PROPVARIANT *);
virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( virtual HRESULT STDMETHODCALLTYPE SetPropertyValue(
PCWSTR, PCWSTR,
const PROPERTYKEY &, const PROPERTYKEY &,
PROPVARIANT *); PROPVARIANT *);
virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint(
PCWSTR wszDeviceId, PCWSTR wszDeviceId,
ERole eRole); ERole eRole);
virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility(
PCWSTR, PCWSTR,
INT); // not available on Windows 7, use method from IPolicyConfig INT); // not available on Windows 7, use method from IPolicyConfig
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View file

@ -1,177 +1,177 @@
// //
// Created by loki on 4/23/20. // Created by loki on 4/23/20.
// //
#ifndef SUNSHINE_DISPLAY_H #ifndef SUNSHINE_DISPLAY_H
#define SUNSHINE_DISPLAY_H #define SUNSHINE_DISPLAY_H
#include <d3d11.h> #include <d3d11.h>
#include <d3d11_4.h> #include <d3d11_4.h>
#include <d3dcommon.h> #include <d3dcommon.h>
#include <dwmapi.h> #include <dwmapi.h>
#include <dxgi.h> #include <dxgi.h>
#include <dxgi1_2.h> #include <dxgi1_2.h>
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/utility.h" #include "src/utility.h"
namespace platf::dxgi { namespace platf::dxgi {
extern const char *format_str[]; extern const char *format_str[];
template<class T> template<class T>
void Release(T *dxgi) { void Release(T *dxgi) {
dxgi->Release(); dxgi->Release();
} }
using factory1_t = util::safe_ptr<IDXGIFactory1, Release<IDXGIFactory1>>; using factory1_t = util::safe_ptr<IDXGIFactory1, Release<IDXGIFactory1>>;
using dxgi_t = util::safe_ptr<IDXGIDevice, Release<IDXGIDevice>>; using dxgi_t = util::safe_ptr<IDXGIDevice, Release<IDXGIDevice>>;
using dxgi1_t = util::safe_ptr<IDXGIDevice1, Release<IDXGIDevice1>>; using dxgi1_t = util::safe_ptr<IDXGIDevice1, Release<IDXGIDevice1>>;
using device_t = util::safe_ptr<ID3D11Device, Release<ID3D11Device>>; using device_t = util::safe_ptr<ID3D11Device, Release<ID3D11Device>>;
using device_ctx_t = util::safe_ptr<ID3D11DeviceContext, Release<ID3D11DeviceContext>>; using device_ctx_t = util::safe_ptr<ID3D11DeviceContext, Release<ID3D11DeviceContext>>;
using adapter_t = util::safe_ptr<IDXGIAdapter1, Release<IDXGIAdapter1>>; using adapter_t = util::safe_ptr<IDXGIAdapter1, Release<IDXGIAdapter1>>;
using output_t = util::safe_ptr<IDXGIOutput, Release<IDXGIOutput>>; using output_t = util::safe_ptr<IDXGIOutput, Release<IDXGIOutput>>;
using output1_t = util::safe_ptr<IDXGIOutput1, Release<IDXGIOutput1>>; using output1_t = util::safe_ptr<IDXGIOutput1, Release<IDXGIOutput1>>;
using dup_t = util::safe_ptr<IDXGIOutputDuplication, Release<IDXGIOutputDuplication>>; using dup_t = util::safe_ptr<IDXGIOutputDuplication, Release<IDXGIOutputDuplication>>;
using texture2d_t = util::safe_ptr<ID3D11Texture2D, Release<ID3D11Texture2D>>; using texture2d_t = util::safe_ptr<ID3D11Texture2D, Release<ID3D11Texture2D>>;
using texture1d_t = util::safe_ptr<ID3D11Texture1D, Release<ID3D11Texture1D>>; using texture1d_t = util::safe_ptr<ID3D11Texture1D, Release<ID3D11Texture1D>>;
using resource_t = util::safe_ptr<IDXGIResource, Release<IDXGIResource>>; using resource_t = util::safe_ptr<IDXGIResource, Release<IDXGIResource>>;
using multithread_t = util::safe_ptr<ID3D11Multithread, Release<ID3D11Multithread>>; using multithread_t = util::safe_ptr<ID3D11Multithread, Release<ID3D11Multithread>>;
using vs_t = util::safe_ptr<ID3D11VertexShader, Release<ID3D11VertexShader>>; using vs_t = util::safe_ptr<ID3D11VertexShader, Release<ID3D11VertexShader>>;
using ps_t = util::safe_ptr<ID3D11PixelShader, Release<ID3D11PixelShader>>; using ps_t = util::safe_ptr<ID3D11PixelShader, Release<ID3D11PixelShader>>;
using blend_t = util::safe_ptr<ID3D11BlendState, Release<ID3D11BlendState>>; using blend_t = util::safe_ptr<ID3D11BlendState, Release<ID3D11BlendState>>;
using input_layout_t = util::safe_ptr<ID3D11InputLayout, Release<ID3D11InputLayout>>; using input_layout_t = util::safe_ptr<ID3D11InputLayout, Release<ID3D11InputLayout>>;
using render_target_t = util::safe_ptr<ID3D11RenderTargetView, Release<ID3D11RenderTargetView>>; using render_target_t = util::safe_ptr<ID3D11RenderTargetView, Release<ID3D11RenderTargetView>>;
using shader_res_t = util::safe_ptr<ID3D11ShaderResourceView, Release<ID3D11ShaderResourceView>>; using shader_res_t = util::safe_ptr<ID3D11ShaderResourceView, Release<ID3D11ShaderResourceView>>;
using buf_t = util::safe_ptr<ID3D11Buffer, Release<ID3D11Buffer>>; using buf_t = util::safe_ptr<ID3D11Buffer, Release<ID3D11Buffer>>;
using raster_state_t = util::safe_ptr<ID3D11RasterizerState, Release<ID3D11RasterizerState>>; using raster_state_t = util::safe_ptr<ID3D11RasterizerState, Release<ID3D11RasterizerState>>;
using sampler_state_t = util::safe_ptr<ID3D11SamplerState, Release<ID3D11SamplerState>>; using sampler_state_t = util::safe_ptr<ID3D11SamplerState, Release<ID3D11SamplerState>>;
using blob_t = util::safe_ptr<ID3DBlob, Release<ID3DBlob>>; using blob_t = util::safe_ptr<ID3DBlob, Release<ID3DBlob>>;
using depth_stencil_state_t = util::safe_ptr<ID3D11DepthStencilState, Release<ID3D11DepthStencilState>>; using depth_stencil_state_t = util::safe_ptr<ID3D11DepthStencilState, Release<ID3D11DepthStencilState>>;
using depth_stencil_view_t = util::safe_ptr<ID3D11DepthStencilView, Release<ID3D11DepthStencilView>>; using depth_stencil_view_t = util::safe_ptr<ID3D11DepthStencilView, Release<ID3D11DepthStencilView>>;
namespace video { namespace video {
using device_t = util::safe_ptr<ID3D11VideoDevice, Release<ID3D11VideoDevice>>; using device_t = util::safe_ptr<ID3D11VideoDevice, Release<ID3D11VideoDevice>>;
using ctx_t = util::safe_ptr<ID3D11VideoContext, Release<ID3D11VideoContext>>; using ctx_t = util::safe_ptr<ID3D11VideoContext, Release<ID3D11VideoContext>>;
using processor_t = util::safe_ptr<ID3D11VideoProcessor, Release<ID3D11VideoProcessor>>; using processor_t = util::safe_ptr<ID3D11VideoProcessor, Release<ID3D11VideoProcessor>>;
using processor_out_t = util::safe_ptr<ID3D11VideoProcessorOutputView, Release<ID3D11VideoProcessorOutputView>>; using processor_out_t = util::safe_ptr<ID3D11VideoProcessorOutputView, Release<ID3D11VideoProcessorOutputView>>;
using processor_in_t = util::safe_ptr<ID3D11VideoProcessorInputView, Release<ID3D11VideoProcessorInputView>>; using processor_in_t = util::safe_ptr<ID3D11VideoProcessorInputView, Release<ID3D11VideoProcessorInputView>>;
using processor_enum_t = util::safe_ptr<ID3D11VideoProcessorEnumerator, Release<ID3D11VideoProcessorEnumerator>>; using processor_enum_t = util::safe_ptr<ID3D11VideoProcessorEnumerator, Release<ID3D11VideoProcessorEnumerator>>;
} // namespace video } // namespace video
class hwdevice_t; class hwdevice_t;
struct cursor_t { struct cursor_t {
std::vector<std::uint8_t> img_data; std::vector<std::uint8_t> img_data;
DXGI_OUTDUPL_POINTER_SHAPE_INFO shape_info; DXGI_OUTDUPL_POINTER_SHAPE_INFO shape_info;
int x, y; int x, y;
bool visible; bool visible;
}; };
class gpu_cursor_t { class gpu_cursor_t {
public: public:
gpu_cursor_t() : cursor_view { 0, 0, 0, 0, 0.0f, 1.0f } {}; gpu_cursor_t() : cursor_view { 0, 0, 0, 0, 0.0f, 1.0f } {};
void set_pos(LONG rel_x, LONG rel_y, bool visible) { void set_pos(LONG rel_x, LONG rel_y, bool visible) {
cursor_view.TopLeftX = rel_x; cursor_view.TopLeftX = rel_x;
cursor_view.TopLeftY = rel_y; cursor_view.TopLeftY = rel_y;
this->visible = visible; this->visible = visible;
} }
void set_texture(LONG width, LONG height, texture2d_t &&texture) { void set_texture(LONG width, LONG height, texture2d_t &&texture) {
cursor_view.Width = width; cursor_view.Width = width;
cursor_view.Height = height; cursor_view.Height = height;
this->texture = std::move(texture); this->texture = std::move(texture);
} }
texture2d_t texture; texture2d_t texture;
shader_res_t input_res; shader_res_t input_res;
D3D11_VIEWPORT cursor_view; D3D11_VIEWPORT cursor_view;
bool visible; bool visible;
}; };
class duplication_t { class duplication_t {
public: public:
dup_t dup; dup_t dup;
bool has_frame {}; bool has_frame {};
bool use_dwmflush {}; bool use_dwmflush {};
capture_e next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p); capture_e next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p);
capture_e reset(dup_t::pointer dup_p = dup_t::pointer()); capture_e reset(dup_t::pointer dup_p = dup_t::pointer());
capture_e release_frame(); capture_e release_frame();
~duplication_t(); ~duplication_t();
}; };
class display_base_t : public display_t { class display_base_t : public display_t {
public: public:
int init(int framerate, const std::string &display_name); int init(int framerate, const std::string &display_name);
std::chrono::nanoseconds delay; std::chrono::nanoseconds delay;
factory1_t factory; factory1_t factory;
adapter_t adapter; adapter_t adapter;
output_t output; output_t output;
device_t device; device_t device;
device_ctx_t device_ctx; device_ctx_t device_ctx;
duplication_t dup; duplication_t dup;
DXGI_FORMAT format; DXGI_FORMAT format;
D3D_FEATURE_LEVEL feature_level; D3D_FEATURE_LEVEL feature_level;
typedef enum _D3DKMT_SCHEDULINGPRIORITYCLASS { typedef enum _D3DKMT_SCHEDULINGPRIORITYCLASS {
D3DKMT_SCHEDULINGPRIORITYCLASS_IDLE, D3DKMT_SCHEDULINGPRIORITYCLASS_IDLE,
D3DKMT_SCHEDULINGPRIORITYCLASS_BELOW_NORMAL, D3DKMT_SCHEDULINGPRIORITYCLASS_BELOW_NORMAL,
D3DKMT_SCHEDULINGPRIORITYCLASS_NORMAL, D3DKMT_SCHEDULINGPRIORITYCLASS_NORMAL,
D3DKMT_SCHEDULINGPRIORITYCLASS_ABOVE_NORMAL, D3DKMT_SCHEDULINGPRIORITYCLASS_ABOVE_NORMAL,
D3DKMT_SCHEDULINGPRIORITYCLASS_HIGH, D3DKMT_SCHEDULINGPRIORITYCLASS_HIGH,
D3DKMT_SCHEDULINGPRIORITYCLASS_REALTIME D3DKMT_SCHEDULINGPRIORITYCLASS_REALTIME
} D3DKMT_SCHEDULINGPRIORITYCLASS; } D3DKMT_SCHEDULINGPRIORITYCLASS;
typedef NTSTATUS WINAPI (*PD3DKMTSetProcessSchedulingPriorityClass)(HANDLE, D3DKMT_SCHEDULINGPRIORITYCLASS); typedef NTSTATUS WINAPI (*PD3DKMTSetProcessSchedulingPriorityClass)(HANDLE, D3DKMT_SCHEDULINGPRIORITYCLASS);
}; };
class display_ram_t : public display_base_t { class display_ram_t : public display_base_t {
public: public:
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override; capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override;
capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible); capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible);
std::shared_ptr<img_t> alloc_img() override; std::shared_ptr<img_t> alloc_img() override;
int dummy_img(img_t *img) override; int dummy_img(img_t *img) override;
int init(int framerate, const std::string &display_name); int init(int framerate, const std::string &display_name);
cursor_t cursor; cursor_t cursor;
D3D11_MAPPED_SUBRESOURCE img_info; D3D11_MAPPED_SUBRESOURCE img_info;
texture2d_t texture; texture2d_t texture;
}; };
class display_vram_t : public display_base_t, public std::enable_shared_from_this<display_vram_t> { class display_vram_t : public display_base_t, public std::enable_shared_from_this<display_vram_t> {
public: public:
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override; capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override;
capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible); capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible);
std::shared_ptr<img_t> alloc_img() override; std::shared_ptr<img_t> alloc_img() override;
int dummy_img(img_t *img_base) override; int dummy_img(img_t *img_base) override;
int init(int framerate, const std::string &display_name); int init(int framerate, const std::string &display_name);
std::shared_ptr<platf::hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override; std::shared_ptr<platf::hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override;
sampler_state_t sampler_linear; sampler_state_t sampler_linear;
blend_t blend_enable; blend_t blend_enable;
blend_t blend_disable; blend_t blend_disable;
ps_t scene_ps; ps_t scene_ps;
vs_t scene_vs; vs_t scene_vs;
texture2d_t src; texture2d_t src;
gpu_cursor_t cursor; gpu_cursor_t cursor;
}; };
} // namespace platf::dxgi } // namespace platf::dxgi
#endif #endif

View file

@ -7,9 +7,9 @@
#include "display.h" #include "display.h"
#include "misc.h" #include "misc.h"
#include "sunshine/config.h" #include "src/config.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
namespace platf { namespace platf {
using namespace std::literals; using namespace std::literals;

View file

@ -1,327 +1,327 @@
#include "display.h" #include "display.h"
#include "sunshine/main.h" #include "src/main.h"
namespace platf { namespace platf {
using namespace std::literals; using namespace std::literals;
} }
namespace platf::dxgi { namespace platf::dxgi {
struct img_t : public ::platf::img_t { struct img_t : public ::platf::img_t {
~img_t() override { ~img_t() override {
delete[] data; delete[] data;
data = nullptr; data = nullptr;
} }
}; };
void blend_cursor_monochrome(const cursor_t &cursor, img_t &img) { void blend_cursor_monochrome(const cursor_t &cursor, img_t &img) {
int height = cursor.shape_info.Height / 2; int height = cursor.shape_info.Height / 2;
int width = cursor.shape_info.Width; int width = cursor.shape_info.Width;
int pitch = cursor.shape_info.Pitch; int pitch = cursor.shape_info.Pitch;
// img cursor.{x,y} < 0, skip parts of the cursor.img_data // img cursor.{x,y} < 0, skip parts of the cursor.img_data
auto cursor_skip_y = -std::min(0, cursor.y); auto cursor_skip_y = -std::min(0, cursor.y);
auto cursor_skip_x = -std::min(0, cursor.x); auto cursor_skip_x = -std::min(0, cursor.x);
// img cursor.{x,y} > img.{x,y}, truncate parts of the cursor.img_data // img cursor.{x,y} > img.{x,y}, truncate parts of the cursor.img_data
auto cursor_truncate_y = std::max(0, cursor.y - img.height); auto cursor_truncate_y = std::max(0, cursor.y - img.height);
auto cursor_truncate_x = std::max(0, cursor.x - img.width); auto cursor_truncate_x = std::max(0, cursor.x - img.width);
auto cursor_width = width - cursor_skip_x - cursor_truncate_x; auto cursor_width = width - cursor_skip_x - cursor_truncate_x;
auto cursor_height = height - cursor_skip_y - cursor_truncate_y; auto cursor_height = height - cursor_skip_y - cursor_truncate_y;
if(cursor_height > height || cursor_width > width) { if(cursor_height > height || cursor_width > width) {
return; return;
} }
auto img_skip_y = std::max(0, cursor.y); auto img_skip_y = std::max(0, cursor.y);
auto img_skip_x = std::max(0, cursor.x); auto img_skip_x = std::max(0, cursor.x);
auto cursor_img_data = cursor.img_data.data() + cursor_skip_y * pitch; auto cursor_img_data = cursor.img_data.data() + cursor_skip_y * pitch;
int delta_height = std::min(cursor_height - cursor_truncate_y, std::max(0, img.height - img_skip_y)); int delta_height = std::min(cursor_height - cursor_truncate_y, std::max(0, img.height - img_skip_y));
int delta_width = std::min(cursor_width - cursor_truncate_x, std::max(0, img.width - img_skip_x)); int delta_width = std::min(cursor_width - cursor_truncate_x, std::max(0, img.width - img_skip_x));
auto pixels_per_byte = width / pitch; auto pixels_per_byte = width / pitch;
auto bytes_per_row = delta_width / pixels_per_byte; auto bytes_per_row = delta_width / pixels_per_byte;
auto img_data = (int *)img.data; auto img_data = (int *)img.data;
for(int i = 0; i < delta_height; ++i) { for(int i = 0; i < delta_height; ++i) {
auto and_mask = &cursor_img_data[i * pitch]; auto and_mask = &cursor_img_data[i * pitch];
auto xor_mask = &cursor_img_data[(i + height) * pitch]; auto xor_mask = &cursor_img_data[(i + height) * pitch];
auto img_pixel_p = &img_data[(i + img_skip_y) * (img.row_pitch / img.pixel_pitch) + img_skip_x]; auto img_pixel_p = &img_data[(i + img_skip_y) * (img.row_pitch / img.pixel_pitch) + img_skip_x];
auto skip_x = cursor_skip_x; auto skip_x = cursor_skip_x;
for(int x = 0; x < bytes_per_row; ++x) { for(int x = 0; x < bytes_per_row; ++x) {
for(auto bit = 0u; bit < 8; ++bit) { for(auto bit = 0u; bit < 8; ++bit) {
if(skip_x > 0) { if(skip_x > 0) {
--skip_x; --skip_x;
continue; continue;
} }
int and_ = *and_mask & (1 << (7 - bit)) ? -1 : 0; int and_ = *and_mask & (1 << (7 - bit)) ? -1 : 0;
int xor_ = *xor_mask & (1 << (7 - bit)) ? -1 : 0; int xor_ = *xor_mask & (1 << (7 - bit)) ? -1 : 0;
*img_pixel_p &= and_; *img_pixel_p &= and_;
*img_pixel_p ^= xor_; *img_pixel_p ^= xor_;
++img_pixel_p; ++img_pixel_p;
} }
++and_mask; ++and_mask;
++xor_mask; ++xor_mask;
} }
} }
} }
void apply_color_alpha(int *img_pixel_p, int cursor_pixel) { void apply_color_alpha(int *img_pixel_p, int cursor_pixel) {
auto colors_out = (std::uint8_t *)&cursor_pixel; auto colors_out = (std::uint8_t *)&cursor_pixel;
auto colors_in = (std::uint8_t *)img_pixel_p; auto colors_in = (std::uint8_t *)img_pixel_p;
//TODO: When use of IDXGIOutput5 is implemented, support different color formats //TODO: When use of IDXGIOutput5 is implemented, support different color formats
auto alpha = colors_out[3]; auto alpha = colors_out[3];
if(alpha == 255) { if(alpha == 255) {
*img_pixel_p = cursor_pixel; *img_pixel_p = cursor_pixel;
} }
else { else {
colors_in[0] = colors_out[0] + (colors_in[0] * (255 - alpha) + 255 / 2) / 255; colors_in[0] = colors_out[0] + (colors_in[0] * (255 - alpha) + 255 / 2) / 255;
colors_in[1] = colors_out[1] + (colors_in[1] * (255 - alpha) + 255 / 2) / 255; colors_in[1] = colors_out[1] + (colors_in[1] * (255 - alpha) + 255 / 2) / 255;
colors_in[2] = colors_out[2] + (colors_in[2] * (255 - alpha) + 255 / 2) / 255; colors_in[2] = colors_out[2] + (colors_in[2] * (255 - alpha) + 255 / 2) / 255;
} }
} }
void apply_color_masked(int *img_pixel_p, int cursor_pixel) { void apply_color_masked(int *img_pixel_p, int cursor_pixel) {
//TODO: When use of IDXGIOutput5 is implemented, support different color formats //TODO: When use of IDXGIOutput5 is implemented, support different color formats
auto alpha = ((std::uint8_t *)&cursor_pixel)[3]; auto alpha = ((std::uint8_t *)&cursor_pixel)[3];
if(alpha == 0xFF) { if(alpha == 0xFF) {
*img_pixel_p ^= cursor_pixel; *img_pixel_p ^= cursor_pixel;
} }
else { else {
*img_pixel_p = cursor_pixel; *img_pixel_p = cursor_pixel;
} }
} }
void blend_cursor_color(const cursor_t &cursor, img_t &img, const bool masked) { void blend_cursor_color(const cursor_t &cursor, img_t &img, const bool masked) {
int height = cursor.shape_info.Height; int height = cursor.shape_info.Height;
int width = cursor.shape_info.Width; int width = cursor.shape_info.Width;
int pitch = cursor.shape_info.Pitch; int pitch = cursor.shape_info.Pitch;
// img cursor.y < 0, skip parts of the cursor.img_data // img cursor.y < 0, skip parts of the cursor.img_data
auto cursor_skip_y = -std::min(0, cursor.y); auto cursor_skip_y = -std::min(0, cursor.y);
auto cursor_skip_x = -std::min(0, cursor.x); auto cursor_skip_x = -std::min(0, cursor.x);
// img cursor.{x,y} > img.{x,y}, truncate parts of the cursor.img_data // img cursor.{x,y} > img.{x,y}, truncate parts of the cursor.img_data
auto cursor_truncate_y = std::max(0, cursor.y - img.height); auto cursor_truncate_y = std::max(0, cursor.y - img.height);
auto cursor_truncate_x = std::max(0, cursor.x - img.width); auto cursor_truncate_x = std::max(0, cursor.x - img.width);
auto img_skip_y = std::max(0, cursor.y); auto img_skip_y = std::max(0, cursor.y);
auto img_skip_x = std::max(0, cursor.x); auto img_skip_x = std::max(0, cursor.x);
auto cursor_width = width - cursor_skip_x - cursor_truncate_x; auto cursor_width = width - cursor_skip_x - cursor_truncate_x;
auto cursor_height = height - cursor_skip_y - cursor_truncate_y; auto cursor_height = height - cursor_skip_y - cursor_truncate_y;
if(cursor_height > height || cursor_width > width) { if(cursor_height > height || cursor_width > width) {
return; return;
} }
auto cursor_img_data = (int *)&cursor.img_data[cursor_skip_y * pitch]; auto cursor_img_data = (int *)&cursor.img_data[cursor_skip_y * pitch];
int delta_height = std::min(cursor_height - cursor_truncate_y, std::max(0, img.height - img_skip_y)); int delta_height = std::min(cursor_height - cursor_truncate_y, std::max(0, img.height - img_skip_y));
int delta_width = std::min(cursor_width - cursor_truncate_x, std::max(0, img.width - img_skip_x)); int delta_width = std::min(cursor_width - cursor_truncate_x, std::max(0, img.width - img_skip_x));
auto img_data = (int *)img.data; auto img_data = (int *)img.data;
for(int i = 0; i < delta_height; ++i) { for(int i = 0; i < delta_height; ++i) {
auto cursor_begin = &cursor_img_data[i * cursor.shape_info.Width + cursor_skip_x]; auto cursor_begin = &cursor_img_data[i * cursor.shape_info.Width + cursor_skip_x];
auto cursor_end = &cursor_begin[delta_width]; auto cursor_end = &cursor_begin[delta_width];
auto img_pixel_p = &img_data[(i + img_skip_y) * (img.row_pitch / img.pixel_pitch) + img_skip_x]; auto img_pixel_p = &img_data[(i + img_skip_y) * (img.row_pitch / img.pixel_pitch) + img_skip_x];
std::for_each(cursor_begin, cursor_end, [&](int cursor_pixel) { std::for_each(cursor_begin, cursor_end, [&](int cursor_pixel) {
if(masked) { if(masked) {
apply_color_masked(img_pixel_p, cursor_pixel); apply_color_masked(img_pixel_p, cursor_pixel);
} }
else { else {
apply_color_alpha(img_pixel_p, cursor_pixel); apply_color_alpha(img_pixel_p, cursor_pixel);
} }
++img_pixel_p; ++img_pixel_p;
}); });
} }
} }
void blend_cursor(const cursor_t &cursor, img_t &img) { void blend_cursor(const cursor_t &cursor, img_t &img) {
switch(cursor.shape_info.Type) { switch(cursor.shape_info.Type) {
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR: case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR:
blend_cursor_color(cursor, img, false); blend_cursor_color(cursor, img, false);
break; break;
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME: case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME:
blend_cursor_monochrome(cursor, img); blend_cursor_monochrome(cursor, img);
break; break;
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR:
blend_cursor_color(cursor, img, true); blend_cursor_color(cursor, img, true);
break; break;
default: default:
BOOST_LOG(warning) << "Unsupported cursor format ["sv << cursor.shape_info.Type << ']'; BOOST_LOG(warning) << "Unsupported cursor format ["sv << cursor.shape_info.Type << ']';
} }
} }
capture_e display_ram_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<::platf::img_t> img, bool *cursor) { capture_e display_ram_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<::platf::img_t> img, bool *cursor) {
auto next_frame = std::chrono::steady_clock::now(); auto next_frame = std::chrono::steady_clock::now();
while(img) { while(img) {
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
while(next_frame > now) { while(next_frame > now) {
now = std::chrono::steady_clock::now(); now = std::chrono::steady_clock::now();
} }
next_frame = now + delay; next_frame = now + delay;
auto status = snapshot(img.get(), 1000ms, *cursor); auto status = snapshot(img.get(), 1000ms, *cursor);
switch(status) { switch(status) {
case platf::capture_e::reinit: case platf::capture_e::reinit:
case platf::capture_e::error: case platf::capture_e::error:
return status; return status;
case platf::capture_e::timeout: case platf::capture_e::timeout:
std::this_thread::sleep_for(1ms); std::this_thread::sleep_for(1ms);
continue; continue;
case platf::capture_e::ok: case platf::capture_e::ok:
img = snapshot_cb(img); img = snapshot_cb(img);
break; break;
default: default:
BOOST_LOG(error) << "Unrecognized capture status ["sv << (int)status << ']'; BOOST_LOG(error) << "Unrecognized capture status ["sv << (int)status << ']';
return status; return status;
} }
} }
return capture_e::ok; return capture_e::ok;
} }
capture_e display_ram_t::snapshot(::platf::img_t *img_base, std::chrono::milliseconds timeout, bool cursor_visible) { capture_e display_ram_t::snapshot(::platf::img_t *img_base, std::chrono::milliseconds timeout, bool cursor_visible) {
auto img = (img_t *)img_base; auto img = (img_t *)img_base;
HRESULT status; HRESULT status;
DXGI_OUTDUPL_FRAME_INFO frame_info; DXGI_OUTDUPL_FRAME_INFO frame_info;
resource_t::pointer res_p {}; resource_t::pointer res_p {};
auto capture_status = dup.next_frame(frame_info, timeout, &res_p); auto capture_status = dup.next_frame(frame_info, timeout, &res_p);
resource_t res { res_p }; resource_t res { res_p };
if(capture_status != capture_e::ok) { if(capture_status != capture_e::ok) {
return capture_status; return capture_status;
} }
if(frame_info.PointerShapeBufferSize > 0) { if(frame_info.PointerShapeBufferSize > 0) {
auto &img_data = cursor.img_data; auto &img_data = cursor.img_data;
img_data.resize(frame_info.PointerShapeBufferSize); img_data.resize(frame_info.PointerShapeBufferSize);
UINT dummy; UINT dummy;
status = dup.dup->GetFramePointerShape(img_data.size(), img_data.data(), &dummy, &cursor.shape_info); status = dup.dup->GetFramePointerShape(img_data.size(), img_data.data(), &dummy, &cursor.shape_info);
if(FAILED(status)) { if(FAILED(status)) {
BOOST_LOG(error) << "Failed to get new pointer shape [0x"sv << util::hex(status).to_string_view() << ']'; BOOST_LOG(error) << "Failed to get new pointer shape [0x"sv << util::hex(status).to_string_view() << ']';
return capture_e::error; return capture_e::error;
} }
} }
if(frame_info.LastMouseUpdateTime.QuadPart) { if(frame_info.LastMouseUpdateTime.QuadPart) {
cursor.x = frame_info.PointerPosition.Position.x; cursor.x = frame_info.PointerPosition.Position.x;
cursor.y = frame_info.PointerPosition.Position.y; cursor.y = frame_info.PointerPosition.Position.y;
cursor.visible = frame_info.PointerPosition.Visible; cursor.visible = frame_info.PointerPosition.Visible;
} }
// If frame has been updated // If frame has been updated
if(frame_info.LastPresentTime.QuadPart != 0) { if(frame_info.LastPresentTime.QuadPart != 0) {
{ {
texture2d_t src {}; texture2d_t src {};
status = res->QueryInterface(IID_ID3D11Texture2D, (void **)&src); status = res->QueryInterface(IID_ID3D11Texture2D, (void **)&src);
if(FAILED(status)) { if(FAILED(status)) {
BOOST_LOG(error) << "Couldn't query interface [0x"sv << util::hex(status).to_string_view() << ']'; BOOST_LOG(error) << "Couldn't query interface [0x"sv << util::hex(status).to_string_view() << ']';
return capture_e::error; return capture_e::error;
} }
//Copy from GPU to CPU //Copy from GPU to CPU
device_ctx->CopyResource(texture.get(), src.get()); device_ctx->CopyResource(texture.get(), src.get());
} }
if(img_info.pData) { if(img_info.pData) {
device_ctx->Unmap(texture.get(), 0); device_ctx->Unmap(texture.get(), 0);
img_info.pData = nullptr; img_info.pData = nullptr;
} }
status = device_ctx->Map(texture.get(), 0, D3D11_MAP_READ, 0, &img_info); status = device_ctx->Map(texture.get(), 0, D3D11_MAP_READ, 0, &img_info);
if(FAILED(status)) { if(FAILED(status)) {
BOOST_LOG(error) << "Failed to map texture [0x"sv << util::hex(status).to_string_view() << ']'; BOOST_LOG(error) << "Failed to map texture [0x"sv << util::hex(status).to_string_view() << ']';
return capture_e::error; return capture_e::error;
} }
} }
const bool mouse_update = const bool mouse_update =
(frame_info.LastMouseUpdateTime.QuadPart || frame_info.PointerShapeBufferSize > 0) && (frame_info.LastMouseUpdateTime.QuadPart || frame_info.PointerShapeBufferSize > 0) &&
(cursor_visible && cursor.visible); (cursor_visible && cursor.visible);
const bool update_flag = frame_info.LastPresentTime.QuadPart != 0 || mouse_update; const bool update_flag = frame_info.LastPresentTime.QuadPart != 0 || mouse_update;
if(!update_flag) { if(!update_flag) {
return capture_e::timeout; return capture_e::timeout;
} }
std::copy_n((std::uint8_t *)img_info.pData, height * img_info.RowPitch, (std::uint8_t *)img->data); std::copy_n((std::uint8_t *)img_info.pData, height * img_info.RowPitch, (std::uint8_t *)img->data);
if(cursor_visible && cursor.visible) { if(cursor_visible && cursor.visible) {
blend_cursor(cursor, *img); blend_cursor(cursor, *img);
} }
return capture_e::ok; return capture_e::ok;
} }
std::shared_ptr<platf::img_t> display_ram_t::alloc_img() { std::shared_ptr<platf::img_t> display_ram_t::alloc_img() {
auto img = std::make_shared<img_t>(); auto img = std::make_shared<img_t>();
img->pixel_pitch = 4; img->pixel_pitch = 4;
img->row_pitch = img_info.RowPitch; img->row_pitch = img_info.RowPitch;
img->width = width; img->width = width;
img->height = height; img->height = height;
img->data = new std::uint8_t[img->row_pitch * height]; img->data = new std::uint8_t[img->row_pitch * height];
return img; return img;
} }
int display_ram_t::dummy_img(platf::img_t *img) { int display_ram_t::dummy_img(platf::img_t *img) {
return 0; return 0;
} }
int display_ram_t::init(int framerate, const std::string &display_name) { int display_ram_t::init(int framerate, const std::string &display_name) {
if(display_base_t::init(framerate, display_name)) { if(display_base_t::init(framerate, display_name)) {
return -1; return -1;
} }
D3D11_TEXTURE2D_DESC t {}; D3D11_TEXTURE2D_DESC t {};
t.Width = width; t.Width = width;
t.Height = height; t.Height = height;
t.MipLevels = 1; t.MipLevels = 1;
t.ArraySize = 1; t.ArraySize = 1;
t.SampleDesc.Count = 1; t.SampleDesc.Count = 1;
t.Usage = D3D11_USAGE_STAGING; t.Usage = D3D11_USAGE_STAGING;
t.Format = format; t.Format = format;
t.CPUAccessFlags = D3D11_CPU_ACCESS_READ; t.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
auto status = device->CreateTexture2D(&t, nullptr, &texture); auto status = device->CreateTexture2D(&t, nullptr, &texture);
if(FAILED(status)) { if(FAILED(status)) {
BOOST_LOG(error) << "Failed to create texture [0x"sv << util::hex(status).to_string_view() << ']'; BOOST_LOG(error) << "Failed to create texture [0x"sv << util::hex(status).to_string_view() << ']';
return -1; return -1;
} }
// map the texture simply to get the pitch and stride // map the texture simply to get the pitch and stride
status = device_ctx->Map(texture.get(), 0, D3D11_MAP_READ, 0, &img_info); status = device_ctx->Map(texture.get(), 0, D3D11_MAP_READ, 0, &img_info);
if(FAILED(status)) { if(FAILED(status)) {
BOOST_LOG(error) << "Failed to map the texture [0x"sv << util::hex(status).to_string_view() << ']'; BOOST_LOG(error) << "Failed to map the texture [0x"sv << util::hex(status).to_string_view() << ']';
return -1; return -1;
} }
return 0; return 0;
} }
} // namespace platf::dxgi } // namespace platf::dxgi

View file

@ -5,9 +5,9 @@
#include <ViGEm/Client.h> #include <ViGEm/Client.h>
#include "misc.h" #include "misc.h"
#include "sunshine/config.h" #include "src/config.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
namespace platf { namespace platf {
using namespace std::literals; using namespace std::literals;

View file

@ -1,123 +1,123 @@
#include <filesystem> #include <filesystem>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
// prevent clang format from "optimizing" the header include order // prevent clang format from "optimizing" the header include order
// clang-format off // clang-format off
#include <winsock2.h> #include <winsock2.h>
#include <iphlpapi.h> #include <iphlpapi.h>
#include <windows.h> #include <windows.h>
#include <winuser.h> #include <winuser.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
// clang-format on // clang-format on
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/utility.h" #include "src/utility.h"
using namespace std::literals; using namespace std::literals;
namespace platf { namespace platf {
using adapteraddrs_t = util::c_ptr<IP_ADAPTER_ADDRESSES>; using adapteraddrs_t = util::c_ptr<IP_ADAPTER_ADDRESSES>;
std::filesystem::path appdata() { std::filesystem::path appdata() {
return L"."sv; return L"."sv;
} }
std::string from_sockaddr(const sockaddr *const socket_address) { std::string from_sockaddr(const sockaddr *const socket_address) {
char data[INET6_ADDRSTRLEN]; char data[INET6_ADDRSTRLEN];
auto family = socket_address->sa_family; auto family = socket_address->sa_family;
if(family == AF_INET6) { if(family == AF_INET6) {
inet_ntop(AF_INET6, &((sockaddr_in6 *)socket_address)->sin6_addr, data, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &((sockaddr_in6 *)socket_address)->sin6_addr, data, INET6_ADDRSTRLEN);
} }
if(family == AF_INET) { if(family == AF_INET) {
inet_ntop(AF_INET, &((sockaddr_in *)socket_address)->sin_addr, data, INET_ADDRSTRLEN); inet_ntop(AF_INET, &((sockaddr_in *)socket_address)->sin_addr, data, INET_ADDRSTRLEN);
} }
return std::string { data }; return std::string { data };
} }
std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const ip_addr) { std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const ip_addr) {
char data[INET6_ADDRSTRLEN]; char data[INET6_ADDRSTRLEN];
auto family = ip_addr->sa_family; auto family = ip_addr->sa_family;
std::uint16_t port; std::uint16_t port;
if(family == AF_INET6) { if(family == AF_INET6) {
inet_ntop(AF_INET6, &((sockaddr_in6 *)ip_addr)->sin6_addr, data, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &((sockaddr_in6 *)ip_addr)->sin6_addr, data, INET6_ADDRSTRLEN);
port = ((sockaddr_in6 *)ip_addr)->sin6_port; port = ((sockaddr_in6 *)ip_addr)->sin6_port;
} }
if(family == AF_INET) { if(family == AF_INET) {
inet_ntop(AF_INET, &((sockaddr_in *)ip_addr)->sin_addr, data, INET_ADDRSTRLEN); inet_ntop(AF_INET, &((sockaddr_in *)ip_addr)->sin_addr, data, INET_ADDRSTRLEN);
port = ((sockaddr_in *)ip_addr)->sin_port; port = ((sockaddr_in *)ip_addr)->sin_port;
} }
return { port, std::string { data } }; return { port, std::string { data } };
} }
adapteraddrs_t get_adapteraddrs() { adapteraddrs_t get_adapteraddrs() {
adapteraddrs_t info { nullptr }; adapteraddrs_t info { nullptr };
ULONG size = 0; ULONG size = 0;
while(GetAdaptersAddresses(AF_UNSPEC, 0, nullptr, info.get(), &size) == ERROR_BUFFER_OVERFLOW) { while(GetAdaptersAddresses(AF_UNSPEC, 0, nullptr, info.get(), &size) == ERROR_BUFFER_OVERFLOW) {
info.reset((PIP_ADAPTER_ADDRESSES)malloc(size)); info.reset((PIP_ADAPTER_ADDRESSES)malloc(size));
} }
return info; return info;
} }
std::string get_mac_address(const std::string_view &address) { std::string get_mac_address(const std::string_view &address) {
adapteraddrs_t info = get_adapteraddrs(); adapteraddrs_t info = get_adapteraddrs();
for(auto adapter_pos = info.get(); adapter_pos != nullptr; adapter_pos = adapter_pos->Next) { for(auto adapter_pos = info.get(); adapter_pos != nullptr; adapter_pos = adapter_pos->Next) {
for(auto addr_pos = adapter_pos->FirstUnicastAddress; addr_pos != nullptr; addr_pos = addr_pos->Next) { for(auto addr_pos = adapter_pos->FirstUnicastAddress; addr_pos != nullptr; addr_pos = addr_pos->Next) {
if(adapter_pos->PhysicalAddressLength != 0 && address == from_sockaddr(addr_pos->Address.lpSockaddr)) { if(adapter_pos->PhysicalAddressLength != 0 && address == from_sockaddr(addr_pos->Address.lpSockaddr)) {
std::stringstream mac_addr; std::stringstream mac_addr;
mac_addr << std::hex; mac_addr << std::hex;
for(int i = 0; i < adapter_pos->PhysicalAddressLength; i++) { for(int i = 0; i < adapter_pos->PhysicalAddressLength; i++) {
if(i > 0) { if(i > 0) {
mac_addr << ':'; mac_addr << ':';
} }
mac_addr << std::setw(2) << std::setfill('0') << (int)adapter_pos->PhysicalAddress[i]; mac_addr << std::setw(2) << std::setfill('0') << (int)adapter_pos->PhysicalAddress[i];
} }
return mac_addr.str(); return mac_addr.str();
} }
} }
} }
BOOST_LOG(warning) << "Unable to find MAC address for "sv << address; BOOST_LOG(warning) << "Unable to find MAC address for "sv << address;
return "00:00:00:00:00:00"s; return "00:00:00:00:00:00"s;
} }
HDESK syncThreadDesktop() { HDESK syncThreadDesktop() {
auto hDesk = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL); auto hDesk = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
if(!hDesk) { if(!hDesk) {
auto err = GetLastError(); auto err = GetLastError();
BOOST_LOG(error) << "Failed to Open Input Desktop [0x"sv << util::hex(err).to_string_view() << ']'; BOOST_LOG(error) << "Failed to Open Input Desktop [0x"sv << util::hex(err).to_string_view() << ']';
return nullptr; return nullptr;
} }
if(!SetThreadDesktop(hDesk)) { if(!SetThreadDesktop(hDesk)) {
auto err = GetLastError(); auto err = GetLastError();
BOOST_LOG(error) << "Failed to sync desktop to thread [0x"sv << util::hex(err).to_string_view() << ']'; BOOST_LOG(error) << "Failed to sync desktop to thread [0x"sv << util::hex(err).to_string_view() << ']';
} }
CloseDesktop(hDesk); CloseDesktop(hDesk);
return hDesk; return hDesk;
} }
void print_status(const std::string_view &prefix, HRESULT status) { void print_status(const std::string_view &prefix, HRESULT status) {
char err_string[1024]; char err_string[1024];
DWORD bytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, DWORD bytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, nullptr,
status, status,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_string, err_string,
sizeof(err_string), sizeof(err_string),
nullptr); nullptr);
BOOST_LOG(error) << prefix << ": "sv << std::string_view { err_string, bytes }; BOOST_LOG(error) << prefix << ": "sv << std::string_view { err_string, bytes };
} }
} // namespace platf } // namespace platf

View file

@ -1,13 +1,13 @@
#ifndef SUNSHINE_WINDOWS_MISC_H #ifndef SUNSHINE_WINDOWS_MISC_H
#define SUNSHINE_WINDOWS_MISC_H #define SUNSHINE_WINDOWS_MISC_H
#include <string_view> #include <string_view>
#include <windows.h> #include <windows.h>
#include <winnt.h> #include <winnt.h>
namespace platf { namespace platf {
void print_status(const std::string_view &prefix, HRESULT status); void print_status(const std::string_view &prefix, HRESULT status);
HDESK syncThreadDesktop(); HDESK syncThreadDesktop();
} // namespace platf } // namespace platf
#endif #endif

View file

@ -1,195 +1,195 @@
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#include <windns.h> #include <windns.h>
#include <winerror.h> #include <winerror.h>
#include <boost/asio/ip/host_name.hpp> #include <boost/asio/ip/host_name.hpp>
#include "misc.h" #include "misc.h"
#include "sunshine/config.h" #include "src/config.h"
#include "sunshine/main.h" #include "src/main.h"
#include "sunshine/network.h" #include "src/network.h"
#include "sunshine/nvhttp.h" #include "src/nvhttp.h"
#include "sunshine/platform/common.h" #include "src/platform/common.h"
#include "sunshine/thread_safe.h" #include "src/thread_safe.h"
#define _FN(x, ret, args) \ #define _FN(x, ret, args) \
typedef ret(*x##_fn) args; \ typedef ret(*x##_fn) args; \
static x##_fn x static x##_fn x
using namespace std::literals; using namespace std::literals;
#define __SV(quote) L##quote##sv #define __SV(quote) L##quote##sv
#define SV(quote) __SV(quote) #define SV(quote) __SV(quote)
extern "C" { extern "C" {
#ifndef __MINGW32__ #ifndef __MINGW32__
constexpr auto DNS_REQUEST_PENDING = 9506L; constexpr auto DNS_REQUEST_PENDING = 9506L;
constexpr auto DNS_QUERY_REQUEST_VERSION1 = 0x1; constexpr auto DNS_QUERY_REQUEST_VERSION1 = 0x1;
constexpr auto DNS_QUERY_RESULTS_VERSION1 = 0x1; constexpr auto DNS_QUERY_RESULTS_VERSION1 = 0x1;
#endif #endif
#define SERVICE_DOMAIN "local" #define SERVICE_DOMAIN "local"
constexpr auto SERVICE_INSTANCE_NAME = SV(SERVICE_NAME "." SERVICE_TYPE "." SERVICE_DOMAIN); constexpr auto SERVICE_INSTANCE_NAME = SV(SERVICE_NAME "." SERVICE_TYPE "." SERVICE_DOMAIN);
constexpr auto SERVICE_TYPE_DOMAIN = SV(SERVICE_TYPE "." SERVICE_DOMAIN); constexpr auto SERVICE_TYPE_DOMAIN = SV(SERVICE_TYPE "." SERVICE_DOMAIN);
#ifndef __MINGW32__ #ifndef __MINGW32__
typedef struct _DNS_SERVICE_INSTANCE { typedef struct _DNS_SERVICE_INSTANCE {
LPWSTR pszInstanceName; LPWSTR pszInstanceName;
LPWSTR pszHostName; LPWSTR pszHostName;
IP4_ADDRESS *ip4Address; IP4_ADDRESS *ip4Address;
IP6_ADDRESS *ip6Address; IP6_ADDRESS *ip6Address;
WORD wPort; WORD wPort;
WORD wPriority; WORD wPriority;
WORD wWeight; WORD wWeight;
// Property list // Property list
DWORD dwPropertyCount; DWORD dwPropertyCount;
PWSTR *keys; PWSTR *keys;
PWSTR *values; PWSTR *values;
DWORD dwInterfaceIndex; DWORD dwInterfaceIndex;
} DNS_SERVICE_INSTANCE, *PDNS_SERVICE_INSTANCE; } DNS_SERVICE_INSTANCE, *PDNS_SERVICE_INSTANCE;
#endif #endif
typedef VOID WINAPI DNS_SERVICE_REGISTER_COMPLETE( typedef VOID WINAPI DNS_SERVICE_REGISTER_COMPLETE(
_In_ DWORD Status, _In_ DWORD Status,
_In_ PVOID pQueryContext, _In_ PVOID pQueryContext,
_In_ PDNS_SERVICE_INSTANCE pInstance); _In_ PDNS_SERVICE_INSTANCE pInstance);
typedef DNS_SERVICE_REGISTER_COMPLETE *PDNS_SERVICE_REGISTER_COMPLETE; typedef DNS_SERVICE_REGISTER_COMPLETE *PDNS_SERVICE_REGISTER_COMPLETE;
#ifndef __MINGW32__ #ifndef __MINGW32__
typedef struct _DNS_SERVICE_CANCEL { typedef struct _DNS_SERVICE_CANCEL {
PVOID reserved; PVOID reserved;
} DNS_SERVICE_CANCEL, *PDNS_SERVICE_CANCEL; } DNS_SERVICE_CANCEL, *PDNS_SERVICE_CANCEL;
typedef struct _DNS_SERVICE_REGISTER_REQUEST { typedef struct _DNS_SERVICE_REGISTER_REQUEST {
ULONG Version; ULONG Version;
ULONG InterfaceIndex; ULONG InterfaceIndex;
PDNS_SERVICE_INSTANCE pServiceInstance; PDNS_SERVICE_INSTANCE pServiceInstance;
PDNS_SERVICE_REGISTER_COMPLETE pRegisterCompletionCallback; PDNS_SERVICE_REGISTER_COMPLETE pRegisterCompletionCallback;
PVOID pQueryContext; PVOID pQueryContext;
HANDLE hCredentials; HANDLE hCredentials;
BOOL unicastEnabled; BOOL unicastEnabled;
} DNS_SERVICE_REGISTER_REQUEST, *PDNS_SERVICE_REGISTER_REQUEST; } DNS_SERVICE_REGISTER_REQUEST, *PDNS_SERVICE_REGISTER_REQUEST;
#endif #endif
_FN(_DnsServiceFreeInstance, VOID, (_In_ PDNS_SERVICE_INSTANCE pInstance)); _FN(_DnsServiceFreeInstance, VOID, (_In_ PDNS_SERVICE_INSTANCE pInstance));
_FN(_DnsServiceDeRegister, DWORD, (_In_ PDNS_SERVICE_REGISTER_REQUEST pRequest, _Inout_opt_ PDNS_SERVICE_CANCEL pCancel)); _FN(_DnsServiceDeRegister, DWORD, (_In_ PDNS_SERVICE_REGISTER_REQUEST pRequest, _Inout_opt_ PDNS_SERVICE_CANCEL pCancel));
_FN(_DnsServiceRegister, DWORD, (_In_ PDNS_SERVICE_REGISTER_REQUEST pRequest, _Inout_opt_ PDNS_SERVICE_CANCEL pCancel)); _FN(_DnsServiceRegister, DWORD, (_In_ PDNS_SERVICE_REGISTER_REQUEST pRequest, _Inout_opt_ PDNS_SERVICE_CANCEL pCancel));
} /* extern "C" */ } /* extern "C" */
namespace platf::publish { namespace platf::publish {
VOID WINAPI register_cb(DWORD status, PVOID pQueryContext, PDNS_SERVICE_INSTANCE pInstance) { VOID WINAPI register_cb(DWORD status, PVOID pQueryContext, PDNS_SERVICE_INSTANCE pInstance) {
auto alarm = (safe::alarm_t<DNS_STATUS>::element_type *)pQueryContext; auto alarm = (safe::alarm_t<DNS_STATUS>::element_type *)pQueryContext;
auto fg = util::fail_guard([&]() { auto fg = util::fail_guard([&]() {
if(pInstance) { if(pInstance) {
_DnsServiceFreeInstance(pInstance); _DnsServiceFreeInstance(pInstance);
} }
}); });
if(status) { if(status) {
print_status("register_cb()"sv, status); print_status("register_cb()"sv, status);
alarm->ring(-1); alarm->ring(-1);
return; return;
} }
alarm->ring(0); alarm->ring(0);
} }
static int service(bool enable) { static int service(bool enable) {
auto alarm = safe::make_alarm<DNS_STATUS>(); auto alarm = safe::make_alarm<DNS_STATUS>();
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter; std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter;
std::wstring name { SERVICE_INSTANCE_NAME.data(), SERVICE_INSTANCE_NAME.size() }; std::wstring name { SERVICE_INSTANCE_NAME.data(), SERVICE_INSTANCE_NAME.size() };
std::wstring domain { SERVICE_TYPE_DOMAIN.data(), SERVICE_TYPE_DOMAIN.size() }; std::wstring domain { SERVICE_TYPE_DOMAIN.data(), SERVICE_TYPE_DOMAIN.size() };
auto host = converter.from_bytes(boost::asio::ip::host_name() + ".local"); auto host = converter.from_bytes(boost::asio::ip::host_name() + ".local");
DNS_SERVICE_INSTANCE instance {}; DNS_SERVICE_INSTANCE instance {};
instance.pszInstanceName = name.data(); instance.pszInstanceName = name.data();
instance.wPort = map_port(nvhttp::PORT_HTTP); instance.wPort = map_port(nvhttp::PORT_HTTP);
instance.pszHostName = host.data(); instance.pszHostName = host.data();
DNS_SERVICE_REGISTER_REQUEST req {}; DNS_SERVICE_REGISTER_REQUEST req {};
req.Version = DNS_QUERY_REQUEST_VERSION1; req.Version = DNS_QUERY_REQUEST_VERSION1;
req.pQueryContext = alarm.get(); req.pQueryContext = alarm.get();
req.pServiceInstance = &instance; req.pServiceInstance = &instance;
req.pRegisterCompletionCallback = register_cb; req.pRegisterCompletionCallback = register_cb;
DNS_STATUS status {}; DNS_STATUS status {};
if(enable) { if(enable) {
status = _DnsServiceRegister(&req, nullptr); status = _DnsServiceRegister(&req, nullptr);
} }
else { else {
status = _DnsServiceDeRegister(&req, nullptr); status = _DnsServiceDeRegister(&req, nullptr);
} }
alarm->wait(); alarm->wait();
status = *alarm->status(); status = *alarm->status();
if(status) { if(status) {
BOOST_LOG(error) << "No mDNS service"sv; BOOST_LOG(error) << "No mDNS service"sv;
return -1; return -1;
} }
return 0; return 0;
} }
class deinit_t : public ::platf::deinit_t { class deinit_t : public ::platf::deinit_t {
public: public:
~deinit_t() override { ~deinit_t() override {
if(service(false)) { if(service(false)) {
std::abort(); std::abort();
} }
BOOST_LOG(info) << "Unregistered Sunshine Gamestream service"sv; BOOST_LOG(info) << "Unregistered Sunshine Gamestream service"sv;
} }
}; };
int load_funcs(HMODULE handle) { int load_funcs(HMODULE handle) {
auto fg = util::fail_guard([handle]() { auto fg = util::fail_guard([handle]() {
FreeLibrary(handle); FreeLibrary(handle);
}); });
_DnsServiceFreeInstance = (_DnsServiceFreeInstance_fn)GetProcAddress(handle, "DnsServiceFreeInstance"); _DnsServiceFreeInstance = (_DnsServiceFreeInstance_fn)GetProcAddress(handle, "DnsServiceFreeInstance");
_DnsServiceDeRegister = (_DnsServiceDeRegister_fn)GetProcAddress(handle, "DnsServiceDeRegister"); _DnsServiceDeRegister = (_DnsServiceDeRegister_fn)GetProcAddress(handle, "DnsServiceDeRegister");
_DnsServiceRegister = (_DnsServiceRegister_fn)GetProcAddress(handle, "DnsServiceRegister"); _DnsServiceRegister = (_DnsServiceRegister_fn)GetProcAddress(handle, "DnsServiceRegister");
if(!(_DnsServiceFreeInstance && _DnsServiceDeRegister && _DnsServiceRegister)) { if(!(_DnsServiceFreeInstance && _DnsServiceDeRegister && _DnsServiceRegister)) {
BOOST_LOG(error) << "mDNS service not available in dnsapi.dll"sv; BOOST_LOG(error) << "mDNS service not available in dnsapi.dll"sv;
return -1; return -1;
} }
fg.disable(); fg.disable();
return 0; return 0;
} }
std::unique_ptr<::platf::deinit_t> start() { std::unique_ptr<::platf::deinit_t> start() {
HMODULE handle = LoadLibrary("dnsapi.dll"); HMODULE handle = LoadLibrary("dnsapi.dll");
if(!handle || load_funcs(handle)) { if(!handle || load_funcs(handle)) {
BOOST_LOG(error) << "Couldn't load dnsapi.dll, You'll need to add PC manually from Moonlight"sv; BOOST_LOG(error) << "Couldn't load dnsapi.dll, You'll need to add PC manually from Moonlight"sv;
return nullptr; return nullptr;
} }
if(service(true)) { if(service(true)) {
return nullptr; return nullptr;
} }
BOOST_LOG(info) << "Registered Sunshine Gamestream service"sv; BOOST_LOG(info) << "Registered Sunshine Gamestream service"sv;
return std::make_unique<deinit_t>(); return std::make_unique<deinit_t>();
} }
} // namespace platf::publish } // namespace platf::publish

View file

@ -14,7 +14,7 @@
#include <iostream> #include <iostream>
#include "sunshine/utility.h" #include "src/utility.h"
DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2); // DEVPROP_TYPE_STRING DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14); // DEVPROP_TYPE_STRING DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14); // DEVPROP_TYPE_STRING

View file

@ -7,7 +7,7 @@
#include <iostream> #include <iostream>
#include "sunshine/utility.h" #include "src/utility.h"
using namespace std::literals; using namespace std::literals;
namespace dxgi { namespace dxgi {