feat(linux)!: Support streaming through XDG portals and Pipewire (#4417)
Co-authored-by: Carlos Garnacho <carlosg@gnome.org> Co-authored-by: Carson Katri <Carson.katri@gmail.com> Co-authored-by: Bond <bond-d@ukr.net> Co-authored-by: d.bondarev <d.bondarev@crm-onebox.com> Co-authored-by: Conn O'Griofa <connogriofa@gmail.com>
This commit is contained in:
parent
5dbeb74f0d
commit
874880e5ea
23 changed files with 1338 additions and 68 deletions
2
.github/workflows/ci-freebsd.yml
vendored
2
.github/workflows/ci-freebsd.yml
vendored
|
|
@ -114,6 +114,7 @@ jobs:
|
||||||
graphics/wayland \
|
graphics/wayland \
|
||||||
lang/python312 \
|
lang/python312 \
|
||||||
multimedia/libva \
|
multimedia/libva \
|
||||||
|
multimedia/pipewire \
|
||||||
net/miniupnpc \
|
net/miniupnpc \
|
||||||
ports-mgmt/pkg \
|
ports-mgmt/pkg \
|
||||||
security/openssl \
|
security/openssl \
|
||||||
|
|
@ -167,6 +168,7 @@ jobs:
|
||||||
-DSUNSHINE_EXECUTABLE_PATH=/usr/local/bin/sunshine \
|
-DSUNSHINE_EXECUTABLE_PATH=/usr/local/bin/sunshine \
|
||||||
-DSUNSHINE_ENABLE_CUDA=OFF \
|
-DSUNSHINE_ENABLE_CUDA=OFF \
|
||||||
-DSUNSHINE_ENABLE_DRM=OFF \
|
-DSUNSHINE_ENABLE_DRM=OFF \
|
||||||
|
-DSUNSHINE_ENABLE_PORTAL=ON \
|
||||||
-DSUNSHINE_ENABLE_WAYLAND=ON \
|
-DSUNSHINE_ENABLE_WAYLAND=ON \
|
||||||
-DSUNSHINE_ENABLE_X11=ON \
|
-DSUNSHINE_ENABLE_X11=ON \
|
||||||
-DSUNSHINE_PUBLISHER_NAME="${GITHUB_REPOSITORY_OWNER}" \
|
-DSUNSHINE_PUBLISHER_NAME="${GITHUB_REPOSITORY_OWNER}" \
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,11 @@ IF (NOT WIN32)
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
OUTPUT_VARIABLE SYSTEMD_USER_UNIT_INSTALL_DIR)
|
OUTPUT_VARIABLE SYSTEMD_USER_UNIT_INSTALL_DIR)
|
||||||
|
|
||||||
|
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
|
||||||
|
--variable=systemd_user_preset_dir systemd
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
OUTPUT_VARIABLE SYSTEMD_USER_PRESET_INSTALL_DIR)
|
||||||
|
|
||||||
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
|
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
|
||||||
--variable=systemd_system_unit_dir systemd
|
--variable=systemd_system_unit_dir systemd
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
|
@ -29,7 +34,12 @@ IF (NOT WIN32)
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
OUTPUT_VARIABLE SYSTEMD_MODULES_LOAD_DIR)
|
OUTPUT_VARIABLE SYSTEMD_MODULES_LOAD_DIR)
|
||||||
|
|
||||||
mark_as_advanced(SYSTEMD_USER_UNIT_INSTALL_DIR SYSTEMD_SYSTEM_UNIT_INSTALL_DIR SYSTEMD_MODULES_LOAD_DIR)
|
mark_as_advanced(
|
||||||
|
SYSTEMD_USER_UNIT_INSTALL_DIR
|
||||||
|
SYSTEMD_USER_PRESET_INSTALL_DIR
|
||||||
|
SYSTEMD_SYSTEM_UNIT_INSTALL_DIR
|
||||||
|
SYSTEMD_MODULES_LOAD_DIR
|
||||||
|
)
|
||||||
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -168,12 +168,29 @@ if(X11_FOUND)
|
||||||
"${CMAKE_SOURCE_DIR}/src/platform/linux/x11grab.cpp")
|
"${CMAKE_SOURCE_DIR}/src/platform/linux/x11grab.cpp")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# XDG portal
|
||||||
|
if(${SUNSHINE_ENABLE_PORTAL})
|
||||||
|
pkg_check_modules(GIO gio-2.0 gio-unix-2.0 REQUIRED)
|
||||||
|
pkg_check_modules(PIPEWIRE libpipewire-0.3 REQUIRED)
|
||||||
|
else()
|
||||||
|
set(GIO_FOUND OFF)
|
||||||
|
set(PIPEWIRE_FOUND OFF)
|
||||||
|
endif()
|
||||||
|
if(PIPEWIRE_FOUND)
|
||||||
|
add_compile_definitions(SUNSHINE_BUILD_PORTAL)
|
||||||
|
include_directories(SYSTEM ${GIO_INCLUDE_DIRS} ${PIPEWIRE_INCLUDE_DIRS})
|
||||||
|
list(APPEND PLATFORM_LIBRARIES ${GIO_LIBRARIES} ${PIPEWIRE_LIBRARIES})
|
||||||
|
list(APPEND PLATFORM_TARGET_FILES
|
||||||
|
"${CMAKE_SOURCE_DIR}/src/platform/linux/portalgrab.cpp")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT ${CUDA_FOUND}
|
if(NOT ${CUDA_FOUND}
|
||||||
AND NOT ${WAYLAND_FOUND}
|
AND NOT ${WAYLAND_FOUND}
|
||||||
AND NOT ${X11_FOUND}
|
AND NOT ${X11_FOUND}
|
||||||
|
AND NOT ${PIPEWIRE_FOUND}
|
||||||
AND NOT (${LIBDRM_FOUND} AND ${LIBCAP_FOUND})
|
AND NOT (${LIBDRM_FOUND} AND ${LIBCAP_FOUND})
|
||||||
AND NOT ${LIBVA_FOUND})
|
AND NOT ${LIBVA_FOUND})
|
||||||
message(FATAL_ERROR "Couldn't find either cuda, wayland, x11, (libdrm and libcap), or libva")
|
message(FATAL_ERROR "Couldn't find either cuda, libva, pipewire, wayland, x11, or (libdrm and libcap)")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# tray icon
|
# tray icon
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,10 @@ if(${SUNSHINE_BUILD_APPIMAGE} OR ${SUNSHINE_BUILD_FLATPAK})
|
||||||
DESTINATION "${SUNSHINE_ASSETS_DIR}/modules-load.d")
|
DESTINATION "${SUNSHINE_ASSETS_DIR}/modules-load.d")
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service"
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service"
|
||||||
DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user")
|
DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user")
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine-kms.service"
|
||||||
|
DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user")
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/00-sunshine-kms.preset"
|
||||||
|
DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user-preset")
|
||||||
else()
|
else()
|
||||||
find_package(Systemd)
|
find_package(Systemd)
|
||||||
find_package(Udev)
|
find_package(Udev)
|
||||||
|
|
@ -29,6 +33,10 @@ else()
|
||||||
if(SYSTEMD_FOUND)
|
if(SYSTEMD_FOUND)
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service"
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service"
|
||||||
DESTINATION "${SYSTEMD_USER_UNIT_INSTALL_DIR}")
|
DESTINATION "${SYSTEMD_USER_UNIT_INSTALL_DIR}")
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine-kms.service"
|
||||||
|
DESTINATION "${SYSTEMD_USER_UNIT_INSTALL_DIR}")
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/00-sunshine-kms.preset"
|
||||||
|
DESTINATION "${SYSTEMD_USER_PRESET_INSTALL_DIR}")
|
||||||
install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/60-sunshine.conf"
|
install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/60-sunshine.conf"
|
||||||
DESTINATION "${SYSTEMD_MODULES_LOAD_DIR}")
|
DESTINATION "${SYSTEMD_MODULES_LOAD_DIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
@ -105,10 +113,11 @@ list(APPEND CPACK_FREEBSD_PACKAGE_DEPS
|
||||||
audio/opus
|
audio/opus
|
||||||
ftp/curl
|
ftp/curl
|
||||||
devel/libevdev
|
devel/libevdev
|
||||||
|
multimedia/pipewire
|
||||||
net/avahi
|
net/avahi
|
||||||
x11/libX11
|
|
||||||
net/miniupnpc
|
net/miniupnpc
|
||||||
security/openssl
|
security/openssl
|
||||||
|
x11/libX11
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT BOOST_USE_STATIC)
|
if(NOT BOOST_USE_STATIC)
|
||||||
|
|
|
||||||
|
|
@ -64,4 +64,6 @@ elseif(UNIX) # Linux
|
||||||
"Enable building wayland specific code." ON)
|
"Enable building wayland specific code." ON)
|
||||||
option(SUNSHINE_ENABLE_X11
|
option(SUNSHINE_ENABLE_X11
|
||||||
"Enable X11 grab if available." ON)
|
"Enable X11 grab if available." ON)
|
||||||
|
option(SUNSHINE_ENABLE_PORTAL
|
||||||
|
"Enable XDG portal grab if available" ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ elseif(UNIX)
|
||||||
|
|
||||||
# configure service
|
# configure service
|
||||||
configure_file(packaging/linux/sunshine.service.in sunshine.service @ONLY)
|
configure_file(packaging/linux/sunshine.service.in sunshine.service @ONLY)
|
||||||
|
configure_file(packaging/linux/sunshine-kms.service.in sunshine-kms.service @ONLY)
|
||||||
|
configure_file(packaging/linux/00-sunshine-kms.preset.in 00-sunshine-kms.preset @ONLY)
|
||||||
|
|
||||||
# configure the arch linux pkgbuild
|
# configure the arch linux pkgbuild
|
||||||
if(${SUNSHINE_CONFIGURE_PKGBUILD})
|
if(${SUNSHINE_CONFIGURE_PKGBUILD})
|
||||||
|
|
|
||||||
|
|
@ -274,16 +274,11 @@ flatpak install --user ./sunshine_{arch}.flatpak
|
||||||
flatpak run --command=additional-install.sh dev.lizardbyte.app.Sunshine
|
flatpak run --command=additional-install.sh dev.lizardbyte.app.Sunshine
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Run with NVFBC capture (X11 Only)
|
##### Run with NVFBC capture (X11 Only) or XDG Portal (Wayland Only)
|
||||||
```bash
|
```bash
|
||||||
flatpak run dev.lizardbyte.app.Sunshine
|
flatpak run dev.lizardbyte.app.Sunshine
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Run with KMS capture (Wayland & X11)
|
|
||||||
```bash
|
|
||||||
sudo -i PULSE_SERVER=unix:/run/user/$(id -u $whoami)/pulse/native flatpak run dev.lizardbyte.app.Sunshine
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Uninstall
|
##### Uninstall
|
||||||
```bash
|
```bash
|
||||||
flatpak run --command=remove-additional-install.sh dev.lizardbyte.app.Sunshine
|
flatpak run --command=remove-additional-install.sh dev.lizardbyte.app.Sunshine
|
||||||
|
|
@ -405,37 +400,21 @@ After adding yourself to the group, log out and log back in for the changes to t
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
#### KMS Capture
|
#### Services
|
||||||
|
|
||||||
> [!WARNING]
|
|
||||||
> Capture of most Wayland-based desktop environments will fail unless this step is performed.
|
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> `cap_sys_admin` may as well be root, except you don't need to be root to run the program. This is necessary to
|
> Two service unit files are available. Pick "sunshine" for unprivileged XDG Portal or X11 capture, otherwise
|
||||||
> allow Sunshine to use KMS capture.
|
> pick "sunshine-kms" for privileged KMS capture.
|
||||||
|
|
||||||
##### Enable
|
|
||||||
```bash
|
|
||||||
sudo setcap cap_sys_admin+p $(readlink -f $(which sunshine))
|
|
||||||
```
|
|
||||||
|
|
||||||
#### X11 Capture
|
|
||||||
For X11 capture to work, you may need to disable the capabilities that were set for KMS capture.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo setcap -r $(readlink -f $(which sunshine))
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Service
|
|
||||||
|
|
||||||
**Start once**
|
**Start once**
|
||||||
```bash
|
```bash
|
||||||
systemctl --user start sunshine
|
systemctl --user start sunshine
|
||||||
```
|
```
|
||||||
|
|
||||||
**Start on boot**
|
**Start on boot (unprivileged; swap logic for KMS)**
|
||||||
```bash
|
```bash
|
||||||
systemctl --user enable sunshine
|
systemctl --user --now disable sunshine-kms
|
||||||
|
systemctl --user --now enable sunshine
|
||||||
```
|
```
|
||||||
|
|
||||||
### macOS
|
### macOS
|
||||||
|
|
|
||||||
|
|
@ -160,16 +160,18 @@ sudo usermod -aG input $USER
|
||||||
```
|
```
|
||||||
|
|
||||||
### KMS Streaming fails
|
### KMS Streaming fails
|
||||||
If screencasting fails with KMS, you may need to run the following to force unprivileged screencasting.
|
If screencasting fails with KMS, you may be using the unprivileged sunshine service unit. Switch to the privileged
|
||||||
|
sunshine-kms service:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo setcap -r $(readlink -f $(which sunshine))
|
systemctl --user --now disable sunshine
|
||||||
|
systemctl --user --now enable sunshine-kms
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> The above command will not work with the AppImage or Flatpak packages. Please refer to the
|
> The above commands will not work with the AppImage or Flatpak packages, as KMS screencasting
|
||||||
> [AppImage setup](md_docs_2getting__started.html#appimage) or
|
> requires elevated privileges which are not allowed by their respective packaging security policies.
|
||||||
> [Flatpak setup](md_docs_2getting__started.html#flatpak) for more specific instructions.
|
> As an alternative, XDG Portal capture is recommended.
|
||||||
|
|
||||||
### KMS streaming fails on Nvidia GPUs
|
### KMS streaming fails on Nvidia GPUs
|
||||||
If KMS screen capture results in a black screen being streamed, you may need to
|
If KMS screen capture results in a black screen being streamed, you may need to
|
||||||
|
|
|
||||||
4
packaging/linux/00-sunshine-kms.preset.in
Normal file
4
packaging/linux/00-sunshine-kms.preset.in
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# @PROJECT_DESCRIPTION@
|
||||||
|
# KMS service should preset to disabled
|
||||||
|
|
||||||
|
disable sunshine-kms.service
|
||||||
|
|
@ -37,6 +37,7 @@ depends=(
|
||||||
'libevdev'
|
'libevdev'
|
||||||
'libmfx'
|
'libmfx'
|
||||||
'libnotify'
|
'libnotify'
|
||||||
|
'libpipewire'
|
||||||
'libpulse'
|
'libpulse'
|
||||||
'libva'
|
'libva'
|
||||||
'libx11'
|
'libx11'
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ BuildRequires: libXinerama-devel
|
||||||
BuildRequires: libXrandr-devel
|
BuildRequires: libXrandr-devel
|
||||||
BuildRequires: libXtst-devel
|
BuildRequires: libXtst-devel
|
||||||
BuildRequires: openssl-devel
|
BuildRequires: openssl-devel
|
||||||
|
BuildRequires: pipewire-devel
|
||||||
BuildRequires: rpm-build
|
BuildRequires: rpm-build
|
||||||
BuildRequires: systemd-rpm-macros
|
BuildRequires: systemd-rpm-macros
|
||||||
BuildRequires: wget
|
BuildRequires: wget
|
||||||
|
|
@ -194,9 +195,10 @@ cmake_args=(
|
||||||
"-DCMAKE_INSTALL_PREFIX=%{_prefix}"
|
"-DCMAKE_INSTALL_PREFIX=%{_prefix}"
|
||||||
"-DSUNSHINE_ASSETS_DIR=%{_datadir}/sunshine"
|
"-DSUNSHINE_ASSETS_DIR=%{_datadir}/sunshine"
|
||||||
"-DSUNSHINE_EXECUTABLE_PATH=%{_bindir}/sunshine"
|
"-DSUNSHINE_EXECUTABLE_PATH=%{_bindir}/sunshine"
|
||||||
|
"-DSUNSHINE_ENABLE_DRM=ON"
|
||||||
|
"-DSUNSHINE_ENABLE_PORTAL=ON"
|
||||||
"-DSUNSHINE_ENABLE_WAYLAND=ON"
|
"-DSUNSHINE_ENABLE_WAYLAND=ON"
|
||||||
"-DSUNSHINE_ENABLE_X11=ON"
|
"-DSUNSHINE_ENABLE_X11=ON"
|
||||||
"-DSUNSHINE_ENABLE_DRM=ON"
|
|
||||||
"-DSUNSHINE_PUBLISHER_NAME=LizardByte"
|
"-DSUNSHINE_PUBLISHER_NAME=LizardByte"
|
||||||
"-DSUNSHINE_PUBLISHER_WEBSITE=https://app.lizardbyte.dev"
|
"-DSUNSHINE_PUBLISHER_WEBSITE=https://app.lizardbyte.dev"
|
||||||
"-DSUNSHINE_PUBLISHER_ISSUE_URL=https://app.lizardbyte.dev/support"
|
"-DSUNSHINE_PUBLISHER_ISSUE_URL=https://app.lizardbyte.dev/support"
|
||||||
|
|
@ -366,8 +368,10 @@ fi
|
||||||
%caps(cap_sys_admin+p) %{_bindir}/sunshine
|
%caps(cap_sys_admin+p) %{_bindir}/sunshine
|
||||||
%caps(cap_sys_admin+p) %{_bindir}/sunshine-*
|
%caps(cap_sys_admin+p) %{_bindir}/sunshine-*
|
||||||
|
|
||||||
# Systemd unit file for user services
|
# Systemd unit/preset files for user services
|
||||||
%{_userunitdir}/sunshine.service
|
%{_userunitdir}/sunshine.service
|
||||||
|
%{_userunitdir}/sunshine-kms.service
|
||||||
|
%{_userpresetdir}/00-sunshine-kms.preset
|
||||||
|
|
||||||
# Udev rules
|
# Udev rules
|
||||||
%{_udevrulesdir}/*-sunshine.rules
|
%{_udevrulesdir}/*-sunshine.rules
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,6 @@
|
||||||
<code>flatpak run --command=additional-install.sh @PROJECT_FQDN@</code>
|
<code>flatpak run --command=additional-install.sh @PROJECT_FQDN@</code>
|
||||||
</p>
|
</p>
|
||||||
<p>NOTE: Sunshine uses a self-signed certificate. The web browser will report it as not secure, but it is safe.</p>
|
<p>NOTE: Sunshine uses a self-signed certificate. The web browser will report it as not secure, but it is safe.</p>
|
||||||
<p>NOTE: KMS Grab (Flatpak)</p>
|
|
||||||
<p>
|
|
||||||
<code>sudo -i PULSE_SERVER=unix:/run/user/$(id -u $whoami)/pulse/native flatpak run @PROJECT_FQDN@</code>
|
|
||||||
</p>
|
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,11 @@ modules:
|
||||||
- -DSUNSHINE_ASSETS_DIR=share/sunshine
|
- -DSUNSHINE_ASSETS_DIR=share/sunshine
|
||||||
- -DSUNSHINE_BUILD_FLATPAK=ON
|
- -DSUNSHINE_BUILD_FLATPAK=ON
|
||||||
- -DSUNSHINE_EXECUTABLE_PATH=/app/bin/sunshine
|
- -DSUNSHINE_EXECUTABLE_PATH=/app/bin/sunshine
|
||||||
|
- -DSUNSHINE_ENABLE_CUDA=ON
|
||||||
|
- -DSUNSHINE_ENABLE_DRM=ON
|
||||||
|
- -DSUNSHINE_ENABLE_PORTAL=ON
|
||||||
- -DSUNSHINE_ENABLE_WAYLAND=ON
|
- -DSUNSHINE_ENABLE_WAYLAND=ON
|
||||||
- -DSUNSHINE_ENABLE_X11=ON
|
- -DSUNSHINE_ENABLE_X11=ON
|
||||||
- -DSUNSHINE_ENABLE_DRM=ON
|
|
||||||
- -DSUNSHINE_ENABLE_CUDA=ON
|
|
||||||
- -DSUNSHINE_PUBLISHER_NAME='LizardByte'
|
- -DSUNSHINE_PUBLISHER_NAME='LizardByte'
|
||||||
- -DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev'
|
- -DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev'
|
||||||
- -DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
|
- -DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
|
||||||
|
|
|
||||||
16
packaging/linux/sunshine-kms.service.in
Normal file
16
packaging/linux/sunshine-kms.service.in
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
[Unit]
|
||||||
|
Description=@PROJECT_DESCRIPTION@
|
||||||
|
StartLimitIntervalSec=500
|
||||||
|
StartLimitBurst=5
|
||||||
|
Conflicts=sunshine.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
# Avoid starting Sunshine before the desktop is fully initialized.
|
||||||
|
ExecStartPre=/bin/sleep 5
|
||||||
|
@SUNSHINE_SERVICE_START_COMMAND@
|
||||||
|
@SUNSHINE_SERVICE_STOP_COMMAND@
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5s
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=xdg-desktop-autostart.target
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
Description=@PROJECT_DESCRIPTION@
|
Description=@PROJECT_DESCRIPTION@
|
||||||
StartLimitIntervalSec=500
|
StartLimitIntervalSec=500
|
||||||
StartLimitBurst=5
|
StartLimitBurst=5
|
||||||
|
Conflicts=sunshine-kms.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
# Avoid starting Sunshine before the desktop is fully initialized.
|
# Avoid starting Sunshine before the desktop is fully initialized.
|
||||||
|
|
@ -10,6 +11,7 @@ ExecStartPre=/bin/sleep 5
|
||||||
@SUNSHINE_SERVICE_STOP_COMMAND@
|
@SUNSHINE_SERVICE_STOP_COMMAND@
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5s
|
RestartSec=5s
|
||||||
|
NoNewPrivileges=true
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=xdg-desktop-autostart.target
|
WantedBy=xdg-desktop-autostart.target
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ class Sunshine < Formula
|
||||||
depends_on "mesa"
|
depends_on "mesa"
|
||||||
depends_on "numactl"
|
depends_on "numactl"
|
||||||
depends_on "pango"
|
depends_on "pango"
|
||||||
|
depends_on "pipewire"
|
||||||
depends_on "pulseaudio"
|
depends_on "pulseaudio"
|
||||||
depends_on "systemd"
|
depends_on "systemd"
|
||||||
depends_on "wayland"
|
depends_on "wayland"
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,7 @@ function add_debian_based_deps() {
|
||||||
"libnotify-dev"
|
"libnotify-dev"
|
||||||
"libnuma-dev"
|
"libnuma-dev"
|
||||||
"libopus-dev"
|
"libopus-dev"
|
||||||
|
"libpipewire-0.3-dev"
|
||||||
"libpulse-dev"
|
"libpulse-dev"
|
||||||
"libssl-dev"
|
"libssl-dev"
|
||||||
"libsystemd-dev"
|
"libsystemd-dev"
|
||||||
|
|
@ -322,6 +323,7 @@ function add_fedora_deps() {
|
||||||
"numactl-devel"
|
"numactl-devel"
|
||||||
"openssl-devel"
|
"openssl-devel"
|
||||||
"opus-devel"
|
"opus-devel"
|
||||||
|
"pipewire-devel"
|
||||||
"pulseaudio-libs-devel"
|
"pulseaudio-libs-devel"
|
||||||
"rpm-build" # if you want to build an RPM binary package
|
"rpm-build" # if you want to build an RPM binary package
|
||||||
"wget" # necessary for cuda install with `run` file
|
"wget" # necessary for cuda install with `run` file
|
||||||
|
|
@ -545,9 +547,10 @@ function run_step_cmake() {
|
||||||
"-DCMAKE_INSTALL_PREFIX=/usr"
|
"-DCMAKE_INSTALL_PREFIX=/usr"
|
||||||
"-DSUNSHINE_ASSETS_DIR=share/sunshine"
|
"-DSUNSHINE_ASSETS_DIR=share/sunshine"
|
||||||
"-DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine"
|
"-DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine"
|
||||||
|
"-DSUNSHINE_ENABLE_DRM=ON"
|
||||||
|
"-DSUNSHINE_ENABLE_PORTAL=ON"
|
||||||
"-DSUNSHINE_ENABLE_WAYLAND=ON"
|
"-DSUNSHINE_ENABLE_WAYLAND=ON"
|
||||||
"-DSUNSHINE_ENABLE_X11=ON"
|
"-DSUNSHINE_ENABLE_X11=ON"
|
||||||
"-DSUNSHINE_ENABLE_DRM=ON"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ "$appimage_build" == 1 ]]; then
|
if [[ "$appimage_build" == 1 ]]; then
|
||||||
|
|
|
||||||
|
|
@ -1660,9 +1660,9 @@ namespace platf {
|
||||||
|
|
||||||
if (!fb->handles[0]) {
|
if (!fb->handles[0]) {
|
||||||
BOOST_LOG(error) << "Couldn't get handle for DRM Framebuffer ["sv << plane->fb_id << "]: Probably not permitted"sv;
|
BOOST_LOG(error) << "Couldn't get handle for DRM Framebuffer ["sv << plane->fb_id << "]: Probably not permitted"sv;
|
||||||
BOOST_LOG((window_system != window_system_e::X11 || config::video.capture == "kms") ? fatal : error)
|
BOOST_LOG((config::video.capture == "kms") ? fatal : error)
|
||||||
<< "You must run [sudo setcap cap_sys_admin+p $(readlink -f $(which sunshine))] for KMS display capture to work!\n"sv
|
<< "If you installed from AppImage or Flatpak, KMS capture is not supported.\n"sv
|
||||||
<< "If you installed from AppImage or Flatpak, please refer to the official documentation:\n"sv
|
<< "Please refer to the official documentation:\n"sv
|
||||||
<< "https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html#linux"sv;
|
<< "https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html#linux"sv;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -888,6 +888,9 @@ namespace platf {
|
||||||
#endif
|
#endif
|
||||||
#ifdef SUNSHINE_BUILD_X11
|
#ifdef SUNSHINE_BUILD_X11
|
||||||
X11, ///< X11
|
X11, ///< X11
|
||||||
|
#endif
|
||||||
|
#ifdef SUNSHINE_BUILD_PORTAL
|
||||||
|
PORTAL, ///< XDG PORTAL
|
||||||
#endif
|
#endif
|
||||||
MAX_FLAGS ///< The maximum number of flags
|
MAX_FLAGS ///< The maximum number of flags
|
||||||
};
|
};
|
||||||
|
|
@ -931,6 +934,15 @@ namespace platf {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SUNSHINE_BUILD_PORTAL
|
||||||
|
std::vector<std::string> portal_display_names();
|
||||||
|
std::shared_ptr<display_t> portal_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config);
|
||||||
|
|
||||||
|
bool verify_portal() {
|
||||||
|
return !portal_display_names().empty();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<std::string> display_names(mem_type_e hwdevice_type) {
|
std::vector<std::string> display_names(mem_type_e hwdevice_type) {
|
||||||
#ifdef SUNSHINE_BUILD_CUDA
|
#ifdef SUNSHINE_BUILD_CUDA
|
||||||
// display using NvFBC only supports mem_type_e::cuda
|
// display using NvFBC only supports mem_type_e::cuda
|
||||||
|
|
@ -952,6 +964,11 @@ namespace platf {
|
||||||
if (sources[source::X11]) {
|
if (sources[source::X11]) {
|
||||||
return x11_display_names();
|
return x11_display_names();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef SUNSHINE_BUILD_PORTAL
|
||||||
|
if (sources[source::PORTAL]) {
|
||||||
|
return portal_display_names();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -990,6 +1007,12 @@ namespace platf {
|
||||||
return x11_display(hwdevice_type, display_name, config);
|
return x11_display(hwdevice_type, display_name, config);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SUNSHINE_BUILD_PORTAL
|
||||||
|
if (sources[source::PORTAL]) {
|
||||||
|
BOOST_LOG(info) << "Screencasting with XDG portal"sv;
|
||||||
|
return portal_display(hwdevice_type, display_name, config);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -1019,33 +1042,30 @@ namespace platf {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SUNSHINE_BUILD_CUDA
|
#ifdef SUNSHINE_BUILD_CUDA
|
||||||
if ((config::video.capture.empty() && sources.none()) || config::video.capture == "nvfbc") {
|
if (((config::video.capture.empty() && sources.none()) || config::video.capture == "nvfbc") && verify_nvfbc()) {
|
||||||
if (verify_nvfbc()) {
|
sources[source::NVFBC] = true;
|
||||||
sources[source::NVFBC] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef SUNSHINE_BUILD_WAYLAND
|
#ifdef SUNSHINE_BUILD_WAYLAND
|
||||||
if ((config::video.capture.empty() && sources.none()) || config::video.capture == "wlr") {
|
if (((config::video.capture.empty() && sources.none()) || config::video.capture == "wlr") && verify_wl()) {
|
||||||
if (verify_wl()) {
|
sources[source::WAYLAND] = true;
|
||||||
sources[source::WAYLAND] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef SUNSHINE_BUILD_DRM
|
#ifdef SUNSHINE_BUILD_DRM
|
||||||
if ((config::video.capture.empty() && sources.none()) || config::video.capture == "kms") {
|
if (((config::video.capture.empty() && sources.none()) || config::video.capture == "kms") && verify_kms()) {
|
||||||
if (verify_kms()) {
|
sources[source::KMS] = true;
|
||||||
sources[source::KMS] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef SUNSHINE_BUILD_X11
|
#ifdef SUNSHINE_BUILD_X11
|
||||||
// We enumerate this capture backend regardless of other suitable sources,
|
// We enumerate this capture backend regardless of other suitable sources,
|
||||||
// since it may be needed as a NvFBC fallback for software encoding on X11.
|
// since it may be needed as a NvFBC fallback for software encoding on X11.
|
||||||
if (config::video.capture.empty() || config::video.capture == "x11") {
|
if ((config::video.capture.empty() || config::video.capture == "x11") && verify_x11()) {
|
||||||
if (verify_x11()) {
|
sources[source::X11] = true;
|
||||||
sources[source::X11] = true;
|
}
|
||||||
}
|
#endif
|
||||||
|
#ifdef SUNSHINE_BUILD_PORTAL
|
||||||
|
if ((config::video.capture.empty() || config::video.capture == "portal") && verify_portal()) {
|
||||||
|
sources[source::PORTAL] = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
1183
src/platform/linux/portalgrab.cpp
Normal file
1183
src/platform/linux/portalgrab.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -67,12 +67,14 @@ const config = ref(props.config)
|
||||||
<template #freebsd>
|
<template #freebsd>
|
||||||
<option value="wlr">wlroots</option>
|
<option value="wlr">wlroots</option>
|
||||||
<option value="x11">X11</option>
|
<option value="x11">X11</option>
|
||||||
|
<option value="portal">XDG Portal</option>
|
||||||
</template>
|
</template>
|
||||||
<template #linux>
|
<template #linux>
|
||||||
<option value="nvfbc">NvFBC</option>
|
<option value="nvfbc">NvFBC</option>
|
||||||
<option value="wlr">wlroots</option>
|
<option value="wlr">wlroots</option>
|
||||||
<option value="kms">KMS</option>
|
<option value="kms">KMS</option>
|
||||||
<option value="x11">X11</option>
|
<option value="x11">X11</option>
|
||||||
|
<option value="portal">XDG Portal</option>
|
||||||
</template>
|
</template>
|
||||||
<template #windows>
|
<template #windows>
|
||||||
<option value="ddx">Desktop Duplication API</option>
|
<option value="ddx">Desktop Duplication API</option>
|
||||||
|
|
|
||||||
8
third-party/glad/include/glad/egl.h
vendored
8
third-party/glad/include/glad/egl.h
vendored
|
|
@ -467,6 +467,14 @@ typedef EGLBoolean(GLAD_API_PTR *PFNEGLWAITSYNCPROC)(EGLDisplay dpy, EGLSync syn
|
||||||
typedef EGLImageKHR(EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
typedef EGLImageKHR(EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||||
typedef EGLBoolean(EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC)(EGLDisplay dpy, EGLImageKHR image);
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC)(EGLDisplay dpy, EGLImageKHR image);
|
||||||
|
|
||||||
|
typedef EGLenum(EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC)(EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
|
||||||
|
typedef EGLenum(EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC)(EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
|
||||||
|
|
||||||
|
GLAD_API_CALL PFNEGLQUERYDMABUFFORMATSEXTPROC glad_eglQueryDmaBufFormatsEXT;
|
||||||
|
#define eglQueryDmaBufFormatsEXT glad_eglQueryDmaBufFormatsEXT
|
||||||
|
GLAD_API_CALL PFNEGLQUERYDMABUFMODIFIERSEXTPROC glad_eglQueryDmaBufModifiersEXT;
|
||||||
|
#define eglQueryDmaBufModifiersEXT glad_eglQueryDmaBufModifiersEXT
|
||||||
|
|
||||||
GLAD_API_CALL PFNEGLCREATEIMAGEKHRPROC glad_eglCreateImageKHR;
|
GLAD_API_CALL PFNEGLCREATEIMAGEKHRPROC glad_eglCreateImageKHR;
|
||||||
#define eglCreateImageKHR glad_eglCreateImageKHR
|
#define eglCreateImageKHR glad_eglCreateImageKHR
|
||||||
GLAD_API_CALL PFNEGLDESTROYIMAGEKHRPROC glad_eglDestroyImageKHR;
|
GLAD_API_CALL PFNEGLDESTROYIMAGEKHRPROC glad_eglDestroyImageKHR;
|
||||||
|
|
|
||||||
8
third-party/glad/src/egl.c
vendored
8
third-party/glad/src/egl.c
vendored
|
|
@ -75,6 +75,8 @@ PFNEGLWAITNATIVEPROC glad_eglWaitNative = NULL;
|
||||||
PFNEGLWAITSYNCPROC glad_eglWaitSync = NULL;
|
PFNEGLWAITSYNCPROC glad_eglWaitSync = NULL;
|
||||||
PFNEGLCREATEIMAGEKHRPROC glad_eglCreateImageKHR = NULL;
|
PFNEGLCREATEIMAGEKHRPROC glad_eglCreateImageKHR = NULL;
|
||||||
PFNEGLDESTROYIMAGEKHRPROC glad_eglDestroyImageKHR = NULL;
|
PFNEGLDESTROYIMAGEKHRPROC glad_eglDestroyImageKHR = NULL;
|
||||||
|
PFNEGLQUERYDMABUFFORMATSEXTPROC glad_eglQueryDmaBufFormatsEXT = NULL;
|
||||||
|
PFNEGLQUERYDMABUFMODIFIERSEXTPROC glad_eglQueryDmaBufModifiersEXT = NULL;
|
||||||
|
|
||||||
|
|
||||||
static void glad_egl_load_EGL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
|
static void glad_egl_load_EGL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
|
@ -138,7 +140,10 @@ static void glad_egl_load_EGL_VERSION_1_5( GLADuserptrloadfunc load, void* userp
|
||||||
glad_eglGetSyncAttrib = (PFNEGLGETSYNCATTRIBPROC) load(userptr, "eglGetSyncAttrib");
|
glad_eglGetSyncAttrib = (PFNEGLGETSYNCATTRIBPROC) load(userptr, "eglGetSyncAttrib");
|
||||||
glad_eglWaitSync = (PFNEGLWAITSYNCPROC) load(userptr, "eglWaitSync");
|
glad_eglWaitSync = (PFNEGLWAITSYNCPROC) load(userptr, "eglWaitSync");
|
||||||
}
|
}
|
||||||
|
static void glad_egl_load_EGL_EXT_image_dma_buf_import_modifiers( GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
glad_eglQueryDmaBufFormatsEXT = (PFNEGLQUERYDMABUFFORMATSEXTPROC) load(userptr, "eglQueryDmaBufFormatsEXT");
|
||||||
|
glad_eglQueryDmaBufModifiersEXT = (PFNEGLQUERYDMABUFMODIFIERSEXTPROC) load(userptr, "eglQueryDmaBufModifiersEXT");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int glad_egl_get_extensions(EGLDisplay display, const char **extensions) {
|
static int glad_egl_get_extensions(EGLDisplay display, const char **extensions) {
|
||||||
|
|
@ -236,6 +241,7 @@ int gladLoadEGLUserPtr(EGLDisplay display, GLADuserptrloadfunc load, void* userp
|
||||||
glad_egl_load_EGL_VERSION_1_2(load, userptr);
|
glad_egl_load_EGL_VERSION_1_2(load, userptr);
|
||||||
glad_egl_load_EGL_VERSION_1_4(load, userptr);
|
glad_egl_load_EGL_VERSION_1_4(load, userptr);
|
||||||
glad_egl_load_EGL_VERSION_1_5(load, userptr);
|
glad_egl_load_EGL_VERSION_1_5(load, userptr);
|
||||||
|
glad_egl_load_EGL_EXT_image_dma_buf_import_modifiers(load, userptr);
|
||||||
|
|
||||||
if (!glad_egl_find_extensions_egl(display)) return 0;
|
if (!glad_egl_find_extensions_egl(display)) return 0;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue