Merge pull request #304 from LizardByte/bot/manual-update-global-workflow-nightly-cnnsp

ci: update global workflows
This commit is contained in:
ReenigneArcher
2022-08-08 20:35:16 -04:00
committed by GitHub
108 changed files with 3488 additions and 3323 deletions

View File

@@ -1,3 +1,4 @@
---
name: Bug Report name: Bug Report
description: Create a bug report to help us improve. description: Create a bug report to help us improve.
body: body:
@@ -5,7 +6,7 @@ body:
attributes: attributes:
value: > value: >
**THIS IS NOT THE PLACE TO ASK FOR SUPPORT!** **THIS IS NOT THE PLACE TO ASK FOR SUPPORT!**
Please use [Discord](https://docs.lizardbyte.dev/about/support.html#discord) for support issues. Please use [Discord](https://docs.lizardbyte.dev/en/latest/about/support.html#discord) for support issues.
- type: textarea - type: textarea
id: description id: description
attributes: attributes:
@@ -90,9 +91,12 @@ body:
id: logs id: logs
attributes: attributes:
label: Relevant log output label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. description: |
Please copy and paste any relevant log output. This will be automatically formatted into code,
so no need for backticks.
render: Shell render: Shell
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
Make sure to close your issue when it's solved! If you found the solution yourself please comment so that others benefit from it. Make sure to close your issue when it's solved! If you found the solution yourself please comment
so that others benefit from it.

View File

@@ -1,3 +1,4 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/ # This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo. # the above-mentioned repo.

View File

@@ -1,3 +1,4 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/ # This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo. # the above-mentioned repo.

View File

@@ -1,3 +1,4 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/ # This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo. # the above-mentioned repo.

View File

@@ -1,3 +1,4 @@
---
name: CI name: CI
on: on:
@@ -52,7 +53,8 @@ jobs:
- name: Check CMakeLists.txt Version - name: Check CMakeLists.txt Version
run: | run: |
version=$(grep -o -E '^project\(Sunshine VERSION [0-9]+\.[0-9]+\.[0-9]+' CMakeLists.txt | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+') version=$(grep -o -E '^project\(Sunshine VERSION [0-9]+\.[0-9]+\.[0-9]+' CMakeLists.txt | \
grep -o -E '[0-9]+\.[0-9]+\.[0-9]+')
echo "cmakelists_version=${version}" >> $GITHUB_ENV echo "cmakelists_version=${version}" >> $GITHUB_ENV
- name: Compare CMakeList.txt Version - name: Compare CMakeList.txt Version
@@ -60,7 +62,8 @@ jobs:
run: | run: |
echo CMakeLists version: "$cmakelists_version" echo CMakeLists version: "$cmakelists_version"
echo Changelog version: "${{ needs.check_changelog.outputs.next_version_bare }}" echo Changelog version: "${{ needs.check_changelog.outputs.next_version_bare }}"
echo Within 'CMakeLists.txt' change "project(Sunshine [VERSION $cmakelists_version]" to "project(Sunshine [VERSION ${{ needs.check_changelog.outputs.next_version_bare }}]" echo Within 'CMakeLists.txt' change "project(Sunshine [VERSION $cmakelists_version]" to \
"project(Sunshine [VERSION ${{ needs.check_changelog.outputs.next_version_bare }}]"
exit 1 exit 1
build_linux_aur: build_linux_aur:
@@ -76,7 +79,7 @@ jobs:
run: | run: |
sudo apt-get update -y sudo apt-get update -y
sudo apt-get install -y \ sudo apt-get install -y \
cmake cmake
- name: Configure PKGBUILD files - name: Configure PKGBUILD files
run: | run: |
@@ -86,47 +89,55 @@ jobs:
sub_version="" sub_version=""
conflicts="'sunshine'" conflicts="'sunshine'"
provides="'sunshine'" provides="'sunshine'"
branch=${GITHUB_HEAD_REF} branch=${GITHUB_HEAD_REF}
# check the branch variable # check the branch variable
if [ -z "$branch" ] if [ -z "$branch" ]
then then
echo "This is a PUSH event" echo "This is a PUSH event"
commit=${{ github.sha }} commit=${{ github.sha }}
clone_url=${{ github.event.repository.clone_url }} clone_url=${{ github.event.repository.clone_url }}
if [[ ${{ github.ref == 'refs/heads/master' }} ]]; then if [[ ${{ github.ref == 'refs/heads/master' }} ]]; then
aur_pkg=sunshine aur_pkg=sunshine
conflicts="" conflicts=""
provides="" provides=""
echo "aur_publish=true" >> $GITHUB_ENV echo "aur_publish=true" >> $GITHUB_ENV
elif [[ ${{ github.ref == 'refs/heads/nightly' }} ]]; then elif [[ ${{ github.ref == 'refs/heads/nightly' }} ]]; then
aur_pkg=sunshine-git aur_pkg=sunshine-git
sub_version=".r${commit}"
echo "aur_publish=true" >> $GITHUB_ENV
fi
else
echo "This is a PR event"
commit=${{ github.event.pull_request.head.sha }}
clone_url=${{ github.event.pull_request.head.repo.clone_url }}
sub_version=".r${commit}" sub_version=".r${commit}"
echo "aur_publish=true" >> $GITHUB_ENV
fi
else
echo "This is a PR event"
commit=${{ github.event.pull_request.head.sha }}
clone_url=${{ github.event.pull_request.head.repo.clone_url }}
sub_version=".r${commit}"
fi fi
echo "Commit: ${commit}" echo "Commit: ${commit}"
echo "Clone URL: ${clone_url}" echo "Clone URL: ${clone_url}"
echo "aur_pkg=${aur_pkg}" >> $GITHUB_ENV echo "aur_pkg=${aur_pkg}" >> $GITHUB_ENV
mkdir -p artifacts mkdir -p artifacts
mkdir -p build mkdir -p build
cd build cd build
cmake -DSUNSHINE_CONFIGURE_AUR=ON -DSUNSHINE_AUR_PKG=${aur_pkg} -DSUNSHINE_SUB_VERSION=${sub_version} -DSUNSHINE_AUR_CONFLICTS=${conflicts} -DSUNSHINE_AUR_PROVIDES=${provides} -DGITHUB_CLONE_URL=${clone_url} -DGITHUB_COMMIT=${commit} -DSUNSHINE_CONFIGURE_ONLY=ON .. cmake -DSUNSHINE_CONFIGURE_AUR=ON \
-DSUNSHINE_AUR_PKG=${aur_pkg} \
-DSUNSHINE_SUB_VERSION=${sub_version} \
-DSUNSHINE_AUR_CONFLICTS=${conflicts} \
-DSUNSHINE_AUR_PROVIDES=${provides} \
-DGITHUB_CLONE_URL=${clone_url} \
-DGITHUB_COMMIT=${commit} \
-DSUNSHINE_CONFIGURE_ONLY=ON \
..
cd .. cd ..
mv ./build/PKGBUILD ./artifacts/ mv ./build/PKGBUILD ./artifacts/
- name: Validate package - name: Validate package
@@ -172,42 +183,50 @@ jobs:
run: | run: |
sudo apt-get update -y sudo apt-get update -y
sudo apt-get install -y \ sudo apt-get install -y \
cmake \ cmake \
flatpak flatpak
sudo su $(whoami) -c 'flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo' sudo su $(whoami) -c 'flatpak remote-add --user --if-not-exists flathub \
sudo su $(whoami) -c 'flatpak install --user flathub org.flatpak.Builder org.freedesktop.Platform//21.08 org.freedesktop.Sdk//21.08 -y' https://flathub.org/repo/flathub.flatpakrepo'
sudo su $(whoami) -c 'flatpak install --user flathub \
org.flatpak.Builder org.freedesktop.Platform//21.08 org.freedesktop.Sdk//21.08 -y'
- name: Configure Flatpak Manifest - name: Configure Flatpak Manifest
run: | run: |
# variables for manifest # variables for manifest
branch=${GITHUB_HEAD_REF} branch=${GITHUB_HEAD_REF}
# check the branch variable # check the branch variable
if [ -z "$branch" ] if [ -z "$branch" ]
then then
echo "This is a PUSH event" echo "This is a PUSH event"
branch=${{ github.ref_name }} branch=${{ github.ref_name }}
commit=${{ github.sha }} commit=${{ github.sha }}
clone_url=${{ github.event.repository.clone_url }} clone_url=${{ github.event.repository.clone_url }}
else else
echo "This is a PR event" echo "This is a PR event"
commit=${{ github.event.pull_request.head.sha }} commit=${{ github.event.pull_request.head.sha }}
clone_url=${{ github.event.pull_request.head.repo.clone_url }} clone_url=${{ github.event.pull_request.head.repo.clone_url }}
fi fi
echo "Branch: ${branch}" echo "Branch: ${branch}"
echo "Commit: ${commit}" echo "Commit: ${commit}"
echo "Clone URL: ${clone_url}" echo "Clone URL: ${clone_url}"
mkdir -p build mkdir -p build
mkdir -p artifacts mkdir -p artifacts
cd build cd build
cmake -DGITHUB_CLONE_URL=${clone_url} -DGITHUB_BRANCH=${branch} -DGITHUB_COMMIT=${commit} -DSUNSHINE_CONFIGURE_FLATPAK=ON -DSUNSHINE_CONFIGURE_ONLY=ON .. cmake -DGITHUB_CLONE_URL=${clone_url} \
-DGITHUB_BRANCH=${branch} \
-DGITHUB_COMMIT=${commit} \
-DSUNSHINE_CONFIGURE_FLATPAK=ON \
-DSUNSHINE_CONFIGURE_ONLY=ON \
..
- name: Build Linux Flatpak - name: Build Linux Flatpak
working-directory: build working-directory: build
run: | run: |
sudo su $(whoami) -c 'flatpak run org.flatpak.Builder --repo=repo --force-clean build-sunshine dev.lizardbyte.sunshine.yml' sudo su $(whoami) -c 'flatpak run org.flatpak.Builder --repo=repo --force-clean build-sunshine \
dev.lizardbyte.sunshine.yml'
sudo su $(whoami) -c 'flatpak build-bundle ./repo ../artifacts/sunshine.flatpak dev.lizardbyte.sunshine' sudo su $(whoami) -c 'flatpak build-bundle ./repo ../artifacts/sunshine.flatpak dev.lizardbyte.sunshine'
- name: Upload Artifacts - name: Upload Artifacts
@@ -232,7 +251,7 @@ jobs:
strategy: strategy:
fail-fast: false # false to test all, true to fail entire job if any fail fail-fast: false # false to test all, true to fail entire job if any fail
matrix: matrix:
include: # package these differently include: # package these differently
- type: cpack - type: cpack
CMAKE_INSTALL_PREFIX: '/usr' CMAKE_INSTALL_PREFIX: '/usr'
SUNSHINE_ASSETS_DIR: 'local/sunshine/assets' SUNSHINE_ASSETS_DIR: 'local/sunshine/assets'
@@ -255,57 +274,60 @@ jobs:
sudo add-apt-repository ppa:savoury1/ffmpeg4 -y sudo add-apt-repository ppa:savoury1/ffmpeg4 -y
# sudo add-apt-repository ppa:savoury1/boost-defaults-1.71 -y # sudo add-apt-repository ppa:savoury1/boost-defaults-1.71 -y
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
sudo apt-get update -y sudo apt-get update -y
sudo apt-get install -y \ sudo apt-get install -y \
build-essential \ build-essential \
cmake \ cmake \
gcc-10 \ gcc-10 \
git \ git \
g++-10 \ g++-10 \
libavdevice-dev \ libavdevice-dev \
libboost-filesystem-dev \ libboost-filesystem-dev \
libboost-log-dev \ libboost-log-dev \
libboost-thread-dev \ libboost-thread-dev \
libcap-dev \ libcap-dev \
libdrm-dev \ libdrm-dev \
libevdev-dev \ libevdev-dev \
libpulse-dev \ libpulse-dev \
libopus-dev \ libopus-dev \
libssl-dev \ libssl-dev \
libwayland-dev \ libwayland-dev \
libx11-dev \ libx11-dev \
libxcb-shm0-dev \ libxcb-shm0-dev \
libxcb-xfixes0-dev \ libxcb-xfixes0-dev \
libxcb1-dev \ libxcb1-dev \
libxfixes-dev \ libxfixes-dev \
libxrandr-dev \ libxrandr-dev \
libxtst-dev \ libxtst-dev \
wget wget
# # Ubuntu 20.04+ packages # # Ubuntu 20.04+ packages
# libboost-filesystem-dev # libboost-filesystem-dev
# libboost-log-dev # libboost-log-dev
# libboost-thread-dev # libboost-thread-dev
# # Ubuntu 18.04 packages # # Ubuntu 18.04 packages
# libboost-filesystem1.71-dev \ # libboost-filesystem1.71-dev \
# libboost-log1.71-dev \ # libboost-log1.71-dev \
# libboost-regex1.71-dev \ # libboost-regex1.71-dev \
# libboost-thread1.71-dev \ # libboost-thread1.71-dev \
# clean apt cache # clean apt cache
sudo apt-get clean sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/* sudo rm -rf /var/lib/apt/lists/*
# Update gcc alias # Update gcc alias
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 sudo update-alternatives --install \
/usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10
# Install CuDA # Install CuDA
sudo wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run sudo wget \
https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run \
--progress=bar:force:noscroll -q --show-progress -O /root/cuda.run
sudo chmod a+x /root/cuda.run sudo chmod a+x /root/cuda.run
sudo /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm sudo /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm
sudo rm /root/cuda.run sudo rm /root/cuda.run
# # Install cmake (necessary for 18.04) # # Install cmake (necessary for 18.04)
# wget https://cmake.org/files/v3.22/cmake-3.22.2-linux-x86_64.sh # wget https://cmake.org/files/v3.22/cmake-3.22.2-linux-x86_64.sh
# chmod +x cmake-3.22.2-linux-x86_64.sh # chmod +x cmake-3.22.2-linux-x86_64.sh
@@ -318,9 +340,19 @@ jobs:
run: | run: |
mkdir -p build mkdir -p build
mkdir -p artifacts mkdir -p artifacts
cd build cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${{ matrix.CMAKE_INSTALL_PREFIX }} -DSUNSHINE_ASSETS_DIR=${{ matrix.SUNSHINE_ASSETS_DIR }} -DSUNSHINE_CONFIG_DIR=${{ matrix.SUNSHINE_CONFIG_DIR }} -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine -DSUNSHINE_ENABLE_WAYLAND=ON -DSUNSHINE_ENABLE_X11=ON -DSUNSHINE_ENABLE_DRM=ON -DSUNSHINE_ENABLE_CUDA=ON ${{ matrix.EXTRA_ARGS }} .. cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${{ matrix.CMAKE_INSTALL_PREFIX }} \
-DSUNSHINE_ASSETS_DIR=${{ matrix.SUNSHINE_ASSETS_DIR }} \
-DSUNSHINE_CONFIG_DIR=${{ matrix.SUNSHINE_CONFIG_DIR }} \
-DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine \
-DSUNSHINE_ENABLE_WAYLAND=ON \
-DSUNSHINE_ENABLE_X11=ON \
-DSUNSHINE_ENABLE_DRM=ON \
-DSUNSHINE_ENABLE_CUDA=ON \
${{ matrix.EXTRA_ARGS }} \
..
make -j ${nproc} make -j ${nproc}
- name: Package Linux - CPACK - name: Package Linux - CPACK
@@ -336,7 +368,7 @@ jobs:
mv ./cpack_artifacts/Sunshine.rpm ../artifacts/sunshine.rpm mv ./cpack_artifacts/Sunshine.rpm ../artifacts/sunshine.rpm
- name: Set AppImage Version - name: Set AppImage Version
if: ${{ matrix.type == 'appimage' && ( needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.latest_version ) }} if: ${{ matrix.type == 'appimage' && ( needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.latest_version ) }} # yamllint disable-line rule:line-length
run: | run: |
version=${{ needs.check_changelog.outputs.next_version_bare }} version=${{ needs.check_changelog.outputs.next_version_bare }}
echo "VERSION=${version}" >> $GITHUB_ENV echo "VERSION=${version}" >> $GITHUB_ENV
@@ -347,43 +379,44 @@ jobs:
run: | run: |
# install sunshine to the DESTDIR # install sunshine to the DESTDIR
make install DESTDIR=AppDir make install DESTDIR=AppDir
# portable home and config # portable home and config
# todo - this is ugly... we should use a custom AppRun script to take care of this # todo - this is ugly... we should use a custom AppRun script to take care of this
mv ./AppDir${{ matrix.CMAKE_INSTALL_PREFIX }}/sunshine.AppImage.* ../artifacts/ mv ./AppDir${{ matrix.CMAKE_INSTALL_PREFIX }}/sunshine.AppImage.* ../artifacts/
mkdir -p ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/.config/sunshine/${{ matrix.SUNSHINE_CONFIG_DIR }} mkdir -p ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/.config/sunshine/${{ matrix.SUNSHINE_CONFIG_DIR }}
cp ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/apps.json ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/.config/sunshine/${{ matrix.SUNSHINE_CONFIG_DIR }}/ cp ../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/apps.json \
../artifacts/${{ matrix.SUNSHINE_CONFIG_DIR }}/.config/sunshine/${{ matrix.SUNSHINE_CONFIG_DIR }}/
# variables # variables
DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}"
ICON_FILE="${ICON_FILE:-sunshine.png}" ICON_FILE="${ICON_FILE:-sunshine.png}"
# AppImage # AppImage
# https://docs.appimage.org/packaging-guide/index.html # https://docs.appimage.org/packaging-guide/index.html
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy-x86_64.AppImage chmod +x linuxdeploy-x86_64.AppImage
# # https://github.com/linuxdeploy/linuxdeploy-plugin-gtk # # https://github.com/linuxdeploy/linuxdeploy-plugin-gtk
# sudo apt-get install libgtk-3-dev librsvg2-dev -y # sudo apt-get install libgtk-3-dev librsvg2-dev -y
# wget https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh # wget https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh
# chmod +x linuxdeploy-plugin-gtk.sh # chmod +x linuxdeploy-plugin-gtk.sh
# export DEPLOY_GTK_VERSION=3 # export DEPLOY_GTK_VERSION=3
./linuxdeploy-x86_64.AppImage \ ./linuxdeploy-x86_64.AppImage \
--appdir ./AppDir \ --appdir ./AppDir \
--executable ./sunshine \ --executable ./sunshine \
--icon-file "../$ICON_FILE" \ --icon-file "../$ICON_FILE" \
--desktop-file "./$DESKTOP_FILE" \ --desktop-file "./$DESKTOP_FILE" \
--library /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 \ --library /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 \
--library /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 \ --library /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 \
--library /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 \ --library /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 \
--output appimage --output appimage
# # add this argument back if using gtk plugin # # add this argument back if using gtk plugin
# --plugin gtk \ # --plugin gtk \
# move # move
mv Sunshine*.AppImage ../artifacts/sunshine.AppImage mv Sunshine*.AppImage ../artifacts/sunshine.AppImage
# permissions # permissions
chmod +x ../artifacts/sunshine.AppImage chmod +x ../artifacts/sunshine.AppImage
@@ -392,9 +425,9 @@ jobs:
run: | run: |
wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage
chmod +x appimagelint-x86_64.AppImage chmod +x appimagelint-x86_64.AppImage
# rm -rf ~/.cache/appimagelint/ # rm -rf ~/.cache/appimagelint/
./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage ./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage
- name: Archive AppImage - name: Archive AppImage
@@ -402,7 +435,7 @@ jobs:
working-directory: artifacts working-directory: artifacts
run: | run: |
chmod +x ./sunshine.AppImage chmod +x ./sunshine.AppImage
zip --recurse-paths --move --test ./sunshine-appimage.zip ./* zip --recurse-paths --move --test ./sunshine-appimage.zip ./*
- name: Upload Artifacts - name: Upload Artifacts
@@ -443,7 +476,11 @@ jobs:
run: | run: |
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DSUNSHINE_ASSETS_DIR=local/sunshine/assets -DSUNSHINE_CONFIG_DIR=local/sunshine/config .. cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DSUNSHINE_ASSETS_DIR=local/sunshine/assets \
-DSUNSHINE_CONFIG_DIR=local/sunshine/config \
..
make -j ${nproc} make -j ${nproc}
- name: Package MacOS - name: Package MacOS
@@ -454,10 +491,10 @@ jobs:
# package # package
cpack -G DragNDrop cpack -G DragNDrop
mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos-experimental-dragndrop.dmg mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos-experimental-dragndrop.dmg
cpack -G Bundle cpack -G Bundle
mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos-experimental-bundle.dmg mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-macos-experimental-bundle.dmg
cpack -G ZIP cpack -G ZIP
mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-macos-experimental-archive.zip mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-macos-experimental-archive.zip
@@ -476,25 +513,20 @@ jobs:
rm -f ./sunshine-macos-experimental-bundle.dmg rm -f ./sunshine-macos-experimental-bundle.dmg
rm -f ./sunshine-macos-experimental-archive.zip rm -f ./sunshine-macos-experimental-archive.zip
# no artifacts to release currently ## no artifacts to release currently
# - name: Create Release # - name: Create Release
# if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} # if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
# uses: LizardByte/.github/actions/create_release@master # uses: LizardByte/.github/actions/create_release@master
# with: # with:
# token: ${{ secrets.GH_BOT_TOKEN }} # token: ${{ secrets.GH_BOT_TOKEN }}
# next_version: ${{ needs.check_changelog.outputs.next_version }} # next_version: ${{ needs.check_changelog.outputs.next_version }}
# last_version: ${{ needs.check_changelog.outputs.last_version }} # last_version: ${{ needs.check_changelog.outputs.last_version }}
# release_body: ${{ needs.check_changelog.outputs.release_body }} # release_body: ${{ needs.check_changelog.outputs.release_body }}
build_mac_port: build_mac_port:
name: Macports name: Macports
needs: check_changelog needs: check_changelog
runs-on: macos-11 runs-on: macos-11
# runs-on: ${{ matrix.os }}
# strategy:
# fail-fast: false
# matrix:
# os: [ macos-10.15, macos-11, macos-12 ]
steps: steps:
- name: Checkout - name: Checkout
@@ -522,42 +554,45 @@ jobs:
run: | run: |
# variables for Portfile # variables for Portfile
branch=${GITHUB_HEAD_REF} branch=${GITHUB_HEAD_REF}
# check the branch variable # check the branch variable
if [ -z "$branch" ] if [ -z "$branch" ]
then then
echo "This is a PUSH event" echo "This is a PUSH event"
commit=${{ github.sha }} commit=${{ github.sha }}
clone_url=${{ github.event.repository.clone_url }} clone_url=${{ github.event.repository.clone_url }}
else else
echo "This is a PR event" echo "This is a PR event"
commit=${{ github.event.pull_request.head.sha }} commit=${{ github.event.pull_request.head.sha }}
clone_url=${{ github.event.pull_request.head.repo.clone_url }} clone_url=${{ github.event.pull_request.head.repo.clone_url }}
fi fi
echo "Commit: ${commit}" echo "Commit: ${commit}"
echo "Clone URL: ${clone_url}" echo "Clone URL: ${clone_url}"
mkdir build mkdir build
cd build cd build
cmake -DGITHUB_COMMIT=${commit} -DGITHUB_CLONE_URL=${clone_url} -DSUNSHINE_CONFIGURE_PORTFILE=ON -DSUNSHINE_CONFIGURE_ONLY=ON .. cmake -DGITHUB_COMMIT=${commit} \
-DGITHUB_CLONE_URL=${clone_url} \
-DSUNSHINE_CONFIGURE_PORTFILE=ON \
-DSUNSHINE_CONFIGURE_ONLY=ON \
..
cd .. cd ..
# copy Portfile to artifacts # copy Portfile to artifacts
mkdir -p artifacts mkdir -p artifacts
cp -f ./build/Portfile ./artifacts/ cp -f ./build/Portfile ./artifacts/
# copy Portfile to ports # copy Portfile to ports
mkdir -p ./ports/multimedia/Sunshine mkdir -p ./ports/multimedia/Sunshine
cp -f ./build/Portfile ./ports/multimedia/Sunshine/Portfile cp -f ./build/Portfile ./ports/multimedia/Sunshine/Portfile
# testing # testing
cat ./artifacts/Portfile cat ./artifacts/Portfile
- name: Bootstrap MacPorts - name: Bootstrap MacPorts
run: | run: |
. ports/.github/workflows/bootstrap.sh . ports/.github/workflows/bootstrap.sh
# Add getopt, mpbb and the MacPorts paths to $PATH for the subsequent steps. # Add getopt, mpbb and the MacPorts paths to $PATH for the subsequent steps.
echo "/opt/mports/bin" >> $GITHUB_PATH echo "/opt/mports/bin" >> $GITHUB_PATH
echo "${PWD}/mpbb" >> $GITHUB_PATH echo "${PWD}/mpbb" >> $GITHUB_PATH
@@ -573,12 +608,12 @@ jobs:
echo "Listing subports for Sunshine" echo "Listing subports for Sunshine"
new_subports=$(mpbb \ new_subports=$(mpbb \
--work-dir /tmp/mpbb \ --work-dir /tmp/mpbb \
list-subports \ list-subports \
--archive-site= \ --archive-site= \
--archive-site-private= \ --archive-site-private= \
--include-deps=no \ --include-deps=no \
"$port" \ "$port" \
| tr '\n' ' ') | tr '\n' ' ')
for subport in $new_subports; do for subport in $new_subports; do
echo "$subport" echo "$subport"
@@ -671,14 +706,14 @@ jobs:
work=$(port work sunshine) work=$(port work sunshine)
echo "Sunshine port work directory: ${work}" echo "Sunshine port work directory: ${work}"
# move components out of port work directory # move components out of port work directory
sudo mv ${work}/Sunshine*component.pkg /tmp/ sudo mv ${work}/Sunshine*component.pkg /tmp/
# copy artifacts # copy artifacts
sudo mv ${work}/Sunshine*.pkg ./artifacts/sunshine.pkg sudo mv ${work}/Sunshine*.pkg ./artifacts/sunshine.pkg
sudo mv ${work}/Sunshine*.dmg ./artifacts/sunshine.dmg sudo mv ${work}/Sunshine*.dmg ./artifacts/sunshine.dmg
# move components back # move components back
# sudo mv /tmp/Sunshine*component.pkg ${work}/ # sudo mv /tmp/Sunshine*component.pkg ${work}/
@@ -733,7 +768,11 @@ jobs:
run: | run: |
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_BUILD_TYPE=Release -DSUNSHINE_ASSETS_DIR=assets -DSUNSHINE_CONFIG_DIR=config -G "MinGW Makefiles" .. cmake -DCMAKE_BUILD_TYPE=Release \
-DSUNSHINE_ASSETS_DIR=assets \
-DSUNSHINE_CONFIG_DIR=config \
-G "MinGW Makefiles" \
..
mingw32-make -j2 mingw32-make -j2
- name: Package Windows - name: Package Windows

View File

@@ -1,3 +1,4 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/ # This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo. # the above-mentioned repo.
@@ -5,15 +6,12 @@
name: Auto create PR name: Auto create PR
on: on:
pull_request: push:
types:
- closed
branches: branches:
- 'nightly' - 'nightly'
jobs: jobs:
create_pr: create_pr:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -25,7 +23,7 @@ jobs:
with: with:
source_branch: "" # should be "nightly" as it's the triggering branch source_branch: "" # should be "nightly" as it's the triggering branch
destination_branch: "master" destination_branch: "master"
pr_title: "Pulling ${{ github.ref }} into master" pr_title: "Pulling ${{ github.ref_name }} into master"
pr_template: ".github/pr_release_template.md" pr_template: ".github/pr_release_template.md"
pr_assignee: "${{ secrets.GH_BOT_NAME }}" pr_assignee: "${{ secrets.GH_BOT_NAME }}"
pr_draft: true pr_draft: true

View File

@@ -1,3 +1,4 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/ # This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo. # the above-mentioned repo.
@@ -17,22 +18,22 @@ jobs:
contains(fromJson('["LizardByte-bot"]'), github.actor) contains(fromJson('["LizardByte-bot"]'), github.actor)
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Autoapproving - name: Autoapproving
uses: hmarr/auto-approve-action@v2 uses: hmarr/auto-approve-action@v2
with: with:
github-token: "${{ secrets.GITHUB_TOKEN }}" github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Label autoapproved - name: Label autoapproved
uses: actions/github-script@v5 uses: actions/github-script@v6
with: with:
github-token: ${{ secrets.GH_BOT_TOKEN }} github-token: ${{ secrets.GH_BOT_TOKEN }}
script: | script: |
github.rest.issues.addLabels({ github.rest.issues.addLabels({
issue_number: context.issue.number, issue_number: context.issue.number,
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
labels: ['autoapproved', 'autoupdate'] labels: ['autoapproved', 'autoupdate']
}) })
automerge: automerge:
needs: [autoapprove] needs: [autoapprove]

32
.github/workflows/autoupdate.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.
# This workflow is designed to work with:
# - automerge workflows
# It uses GitHub Action that auto-updates pull requests branches, when changes are pushed to their destination branch.
# Auto-updating to the latest destination branch works only in the context of upstream repo and not forks.
name: autoupdate
on:
push:
branches:
- 'nightly'
jobs:
autoupdate-for-bot:
name: Autoupdate autoapproved PR created in the upstream
if: startsWith(github.repository, 'LizardByte/')
runs-on: ubuntu-latest
steps:
- name: Update
uses: docker://chinthakagodawita/autoupdate-action:v1
env:
GITHUB_TOKEN: '${{ secrets.GH_BOT_TOKEN }}'
PR_FILTER: "labelled"
PR_LABELS: "autoupdate"
PR_READY_STATE: "ready_for_review"
MERGE_CONFLICT_ACTION: "ignore"

View File

@@ -1,31 +0,0 @@
name: clang-format-lint
on:
pull_request:
branches: [master, nightly]
types: [opened, synchronize, reopened]
jobs:
lint:
name: Clang Format Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Clang format lint
uses: DoozyX/clang-format-lint-action@v0.14
with:
source: './sunshine'
extensions: 'cpp,h,m,mm'
clangFormatVersion: 13
style: file
inplace: false
- name: Upload Artifacts
if: failure()
uses: actions/upload-artifact@v3
with:
name: sunshine
path: sunshine/

View File

@@ -0,0 +1,60 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.
name: Clang Format Lint
on:
pull_request:
branches: [master, nightly]
types: [opened, synchronize, reopened]
jobs:
check_src:
name: Check src
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check
id: check
run: |
if [ -d "./src" ]
then
FOUND=true
else
FOUND=false
fi
echo "::set-output name=src::${FOUND}"
outputs:
src: ${{ steps.check.outputs.src }}
lint:
name: Clang Format Lint
needs: [check_src]
if: ${{ needs.check_src.outputs.src == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Clang format lint
uses: DoozyX/clang-format-lint-action@v0.14
with:
source: './src'
extensions: 'cpp,h,m,mm'
clangFormatVersion: 13
style: file
inplace: false
- name: Upload Artifacts
if: failure()
uses: actions/upload-artifact@v3
with:
name: clang-format-fixes
path: src/

View File

@@ -1,3 +1,4 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/ # This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo. # the above-mentioned repo.

View File

@@ -1,3 +1,4 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/ # This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo. # the above-mentioned repo.
@@ -8,7 +9,7 @@ on:
issues: issues:
types: [labeled, unlabeled] types: [labeled, unlabeled]
discussion: discussion:
types: [ labeled, unlabeled ] types: [labeled, unlabeled]
jobs: jobs:
label: label:

View File

@@ -1,3 +1,4 @@
---
name: localize name: localize
on: on:
@@ -5,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:
@@ -18,76 +19,77 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Install Python 3.9 - name: Install Python 3.9
uses: actions/setup-python@v4 # https://github.com/actions/setup-python uses: actions/setup-python@v4 # https://github.com/actions/setup-python
with: with:
python-version: '3.9' python-version: '3.9'
- name: Set up Python 3.9 Dependencies - name: Set up Python 3.9 Dependencies
run: | run: |
cd ./scripts cd ./scripts
python -m pip install --upgrade pip setuptools python -m pip install --upgrade pip setuptools
python -m pip install -r requirements.txt python -m pip install -r requirements.txt
- name: Set up xgettext - name: Set up xgettext
run: | run: |
sudo apt-get update -y && \ sudo apt-get update -y && \
sudo apt-get --reinstall install -y \ sudo apt-get --reinstall install -y \
gettext gettext
- name: Update Strings - name: Update Strings
run: | run: |
# first, try to remove existing file as xgettext does not remove unused translations # first, try to remove existing file as xgettext does not remove unused translations
if [ -f "${{ env.file }}" ]; if [ -f "${{ env.file }}" ];
then then
rm ${{ env.file }} rm ${{ env.file }}
echo "new_file=false" >> $GITHUB_ENV echo "new_file=false" >> $GITHUB_ENV
else else
echo "new_file=true" >> $GITHUB_ENV echo "new_file=true" >> $GITHUB_ENV
fi fi
# extract the new strings # extract the new strings
python ./scripts/_locale.py --extract python ./scripts/_locale.py --extract
- name: git diff - name: git diff
if: ${{ env.new_file == 'false' }} if: ${{ env.new_file == 'false' }}
run: | run: |
# disable the pager # disable the pager
git config --global pager.diff false git config --global pager.diff false
# print the git diff # print the git diff
git diff locale/sunshine.po git diff locale/sunshine.po
# set the variable with minimal output # set the variable with minimal output
OUTPUT=$(git diff --numstat locale/sunshine.po) OUTPUT=$(git diff --numstat locale/sunshine.po)
echo "git_diff=${OUTPUT}" >> $GITHUB_ENV echo "git_diff=${OUTPUT}" >> $GITHUB_ENV
- name: git reset - name: git reset
# only run if a single line changed (date/time) and file already existed # only run if a single line changed (date/time) and file already existed
if: ${{ env.git_diff == '1 1 locale/sunshine.po' && env.new_file == 'false' }} # \t in next line is a tab character
run: | if: ${{ env.git_diff == '1\t1\tlocale/sunshine.po' && env.new_file == 'false' }}
git reset --hard run: |
git reset --hard
- name: Create/Update Pull Request - name: Create/Update Pull Request
uses: peter-evans/create-pull-request@v4 uses: peter-evans/create-pull-request@v4
with: with:
add-paths: | add-paths: |
locale/*.po locale/*.po
token: ${{ secrets.GH_BOT_TOKEN }} # must trigger PR tests token: ${{ secrets.GH_BOT_TOKEN }} # must trigger PR tests
commit-message: New localization template commit-message: New localization template
branch: localize/update branch: localize/update
delete-branch: true delete-branch: true
base: nightly base: nightly
title: New Babel Updates title: New Babel Updates
body: | body: |
Update report Update report
- Updated with *today's* date - Updated with *today's* date
- Auto-generated by [create-pull-request][1] - Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request [1]: https://github.com/peter-evans/create-pull-request
labels: | labels: |
babel babel
l10n l10n

View File

@@ -1,3 +1,4 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/ # This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo. # the above-mentioned repo.
@@ -18,7 +19,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
target: master target: master
exclude: nightly # Don't prevent going from nightly -> master exclude: nightly # Don't prevent going from nightly -> master
change-to: nightly change-to: nightly
comment: | comment: |
Your PR was set to `master`, PRs should be sent to `nightly`. Your PR was set to `master`, PRs should be sent to `nightly`.

View File

@@ -1,3 +1,4 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/ # This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo. # the above-mentioned repo.

View File

@@ -1,3 +1,4 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/ # This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in # Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo. # the above-mentioned repo.

View File

@@ -1,14 +1,17 @@
name: Publish to WinGet ---
name: Publish to WinGet
on:
release: on:
types: [released] release:
types: [released]
jobs:
publish: jobs:
runs-on: windows-latest winget-releaser:
steps: name: winget releaser
- uses: vedantmgoyal2009/winget-releaser@latest runs-on: windows-latest
with: steps:
identifier: LizardByte.Sunshine - name: winget releaser
token: ${{ secrets.GH_BOT_TOKEN }} uses: vedantmgoyal2009/winget-releaser@latest
with:
identifier: LizardByte.Sunshine
token: ${{ secrets.GH_BOT_TOKEN }}

46
.github/workflows/yaml-lint.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.
name: yaml lint
on:
pull_request:
branches: [master, nightly]
types: [opened, synchronize, reopened]
jobs:
yaml-lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: yaml lint
id: yaml-lint
uses: ibiqlik/action-yamllint@v3
with:
# https://yamllint.readthedocs.io/en/stable/configuration.html#default-configuration
config_data: |
extends: default
rules:
comments:
level: error
line-length:
max: 120
truthy:
allowed-values: ['true', 'false', 'on'] # GitHub uses "on" for workflow event triggers
check-keys: true
level: error
- name: Log
run: |
echo ${{ steps.yaml-lint.outputs.logfile }}
- name: Upload logs
uses: actions/upload-artifact@v2
if: failure()
with:
name: yamllint-logfile
path: ${{ steps.yaml-lint.outputs.logfile }}

4
.gitmodules vendored
View File

@@ -13,6 +13,6 @@
[submodule "third-party/nv-codec-headers"] [submodule "third-party/nv-codec-headers"]
path = third-party/nv-codec-headers path = third-party/nv-codec-headers
url = https://github.com/FFmpeg/nv-codec-headers url = https://github.com/FFmpeg/nv-codec-headers
[submodule "sunshine/platform/macos/TPCircularBuffer"] [submodule "third-party/TPCircularBuffer"]
path = sunshine/platform/macos/TPCircularBuffer path = third-party/TPCircularBuffer
url = https://github.com/michaeltyson/TPCircularBuffer url = https://github.com/michaeltyson/TPCircularBuffer

View File

@@ -1,3 +1,4 @@
---
# .readthedocs.yaml # .readthedocs.yaml
# Read the Docs configuration file # Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
@@ -25,9 +26,9 @@ build:
# - cmake . # - cmake .
## Include the submodules, required for cmake ## Include the submodules, required for cmake
#submodules: # submodules:
# include: all # include: all
# recursive: true # recursive: true
# Build documentation in the docs/ directory with Sphinx # Build documentation in the docs/ directory with Sphinx
sphinx: sphinx:

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,21 +180,21 @@ 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
sunshine/platform/macos/TPCircularBuffer/TPCircularBuffer.c third-party/TPCircularBuffer/TPCircularBuffer.c
sunshine/platform/macos/TPCircularBuffer/TPCircularBuffer.h third-party/TPCircularBuffer/TPCircularBuffer.h
${APPLE_PLIST_FILE}) ${APPLE_PLIST_FILE})
else() else()
add_compile_definitions(SUNSHINE_PLATFORM="linux") add_compile_definitions(SUNSHINE_PLATFORM="linux")
@@ -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

@@ -1,3 +1,4 @@
---
"base_path": "." "base_path": "."
"base_url": "https://api.crowdin.com" # optional (for Crowdin Enterprise only) "base_url": "https://api.crowdin.com" # optional (for Crowdin Enterprise only)
"preserve_hierarchy": false # flatten tree on crowdin "preserve_hierarchy": false # flatten tree on crowdin
@@ -6,10 +7,10 @@
"l10n" "l10n"
] ]
"files" : [ "files": [
{ {
"source" : "/locale/*.po", "source": "/locale/*.po",
"translation" : "/locale/%two_letters_code%/LC_MESSAGES/%original_file_name%", "translation": "/locale/%two_letters_code%/LC_MESSAGES/%original_file_name%",
"languages_mapping": { "languages_mapping": {
"two_letters_code": { "two_letters_code": {
# map non-two letter codes here, left side is crowdin designation, right side is babel designation # map non-two letter codes here, left side is crowdin designation, right side is babel designation

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

@@ -1,3 +1,4 @@
---
app-id: dev.lizardbyte.sunshine app-id: dev.lizardbyte.sunshine
runtime: org.freedesktop.Platform runtime: org.freedesktop.Platform
runtime-version: "21.08" runtime-version: "21.08"
@@ -35,7 +36,7 @@ modules:
- '*' - '*'
build-commands: build-commands:
- chmod u+x ./cuda.run - chmod u+x ./cuda.run
- ./cuda.run --silent --toolkit --toolkitpath=$FLATPAK_DEST/cuda --no-opengl-libs --no-man-page --no-drm --tmpdir=$FLATPAK_BUILDER_BUILDDIR - ./cuda.run --silent --toolkit --toolkitpath=$FLATPAK_DEST/cuda --no-opengl-libs --no-man-page --no-drm --tmpdir=$FLATPAK_BUILDER_BUILDDIR # yamllint disable-line rule:line-length
- rm -r $FLATPAK_DEST/cuda/nsight-systems-2021.3.2 - rm -r $FLATPAK_DEST/cuda/nsight-systems-2021.3.2
- rm ./cuda.run - rm ./cuda.run
sources: sources:
@@ -48,7 +49,7 @@ modules:
- type: file - type: file
only-arches: only-arches:
- aarch64 - aarch64
url: https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux_sbsa.run url: https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux_sbsa.run # yamllint disable-line rule:line-length
sha256: f2c4a52e06329606c8dfb7c5ea3f4cb4c0b28f9d3fdffeeb734fcc98daf580d8 sha256: f2c4a52e06329606c8dfb7c5ea3f4cb4c0b28f9d3fdffeeb734fcc98daf580d8
dest-filename: cuda.run dest-filename: cuda.run
@@ -56,7 +57,7 @@ modules:
buildsystem: simple buildsystem: simple
build-commands: build-commands:
- ./bootstrap.sh --prefix=$FLATPAK_DEST --with-libraries=system,thread,log - ./bootstrap.sh --prefix=$FLATPAK_DEST --with-libraries=system,thread,log
- ./b2 install variant=release link=static,shared runtime-link=shared cxxflags="$CXXFLAGS" linkflags="$LDFLAGS" -j $FLATPAK_BUILDER_N_JOBS - ./b2 install variant=release link=static,shared runtime-link=shared cxxflags="$CXXFLAGS" linkflags="$LDFLAGS" -j $FLATPAK_BUILDER_N_JOBS # yamllint disable-line rule:line-length
sources: sources:
- type: archive - type: archive
url: https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2 url: https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2
@@ -170,7 +171,7 @@ modules:
- /bin - /bin
sources: sources:
- type: archive - type: archive
url: https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz url: https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz # yamllint disable-line rule:line-length
sha256: 92e6de1be9ec176428fd2367677e61ceffc2ee1cb119035037a27d346b0403bb sha256: 92e6de1be9ec176428fd2367677e61ceffc2ee1cb119035037a27d346b0403bb
- name: libevdev - name: libevdev
@@ -210,6 +211,6 @@ modules:
- -DSUNSHINE_ENABLE_CUDA=ON - -DSUNSHINE_ENABLE_CUDA=ON
sources: sources:
- type: git - type: git
url: @GITHUB_CLONE_URL@ url: '@GITHUB_CLONE_URL@'
branch: @GITHUB_BRANCH@ branch: '@GITHUB_BRANCH@'
commit: @GITHUB_COMMIT@ commit: '@GITHUB_COMMIT@'

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

@@ -3,7 +3,7 @@
#import <AVFoundation/AVFoundation.h> #import <AVFoundation/AVFoundation.h>
#include "sunshine/platform/macos/TPCircularBuffer/TPCircularBuffer.h" #include "third-party/TPCircularBuffer/TPCircularBuffer.h"
#define kBufferLength 2048 #define kBufferLength 2048

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

Some files were not shown because too many files have changed in this diff Show More