feat(linux/glad): implement EGL_IMG_context_priority (#4857)

This commit is contained in:
Conn O'Griofa
2026-03-22 00:27:21 +00:00
committed by GitHub
parent 0d3be0bb1e
commit ae8adfd8ed
9 changed files with 72 additions and 23 deletions

View File

@@ -179,6 +179,7 @@ glad_add_library(glad_egl
EGL_EXT_platform_base
EGL_EXT_platform_wayland
EGL_EXT_platform_x11
EGL_IMG_context_priority
EGL_KHR_create_context
EGL_KHR_image_base
EGL_KHR_surfaceless_context

View File

@@ -64,7 +64,7 @@ endif()
# Apply setcap for RPM
# https://github.com/coreos/rpm-ostree/discussions/5036#discussioncomment-10291071
set(CPACK_RPM_USER_FILELIST "%caps(cap_sys_admin+p) ${SUNSHINE_EXECUTABLE_PATH}")
set(CPACK_RPM_USER_FILELIST "%caps(cap_sys_admin,cap_sys_nice+p) ${SUNSHINE_EXECUTABLE_PATH}")
# Dependencies
set(CPACK_DEB_COMPONENT_INSTALL ON)

View File

@@ -59,7 +59,7 @@ from source and using the binary directly, this will also work:
```bash
sudo cp build/sunshine /tmp
sudo setcap cap_sys_admin+p /tmp/sunshine
sudo setcap cap_sys_admin,cap_sys_nice+p /tmp/sunshine
sudo getcap /tmp/sunshine
sudo mv /tmp/sunshine build/sunshine
```

View File

@@ -60,7 +60,7 @@ function install() {
sed -i -e "s#$SUNSHINE_PATH#$(readlink -f $ARGV0)#g" ~/.config/systemd/user/app-dev.lizardbyte.app.Sunshine.service
# setcap
sudo setcap cap_sys_admin+p "$(readlink -f "$SUNSHINE_BIN_HERE")"
sudo setcap cap_sys_admin,cap_sys_nice+p "$(readlink -f "$SUNSHINE_BIN_HERE")"
}
function remove() {

View File

@@ -1,5 +1,5 @@
do_setcap() {
setcap cap_sys_admin+p $(readlink -f usr/bin/sunshine)
setcap cap_sys_admin,cap_sys_nice+p $(readlink -f usr/bin/sunshine)
}
do_udev_reload() {

View File

@@ -387,8 +387,8 @@ fi
%files
# Executables
%caps(cap_sys_admin+p) %{_bindir}/sunshine
%caps(cap_sys_admin+p) %{_bindir}/sunshine-*
%caps(cap_sys_admin,cap_sys_nice+p) %{_bindir}/sunshine
%caps(cap_sys_admin,cap_sys_nice+p) %{_bindir}/sunshine-*
# Systemd unit files for user services
%{_userunitdir}/*.service

View File

@@ -11,6 +11,11 @@
#include "src/logging.h"
#include "src/video.h"
// platform includes
#if !defined(__FreeBSD__)
#include <sys/capability.h>
#endif
extern "C" {
#include <libavutil/pixdesc.h>
}
@@ -387,6 +392,18 @@ namespace egl {
}
std::optional<ctx_t> make_ctx(display_t::pointer display) {
bool nice_warning = false;
#if !defined(__FreeBSD__)
cap_t caps = cap_get_proc();
cap_value_t sys_nice = CAP_SYS_NICE;
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &sys_nice, CAP_SET) || cap_set_proc(caps)) {
BOOST_LOG(debug) << "Failed to gain CAP_SYS_NICE"sv;
nice_warning = true;
}
cap_free(caps);
#endif
constexpr int conf_attr[] {
EGL_RENDERABLE_TYPE,
EGL_OPENGL_BIT,
@@ -405,20 +422,42 @@ namespace egl {
return std::nullopt;
}
constexpr int attr[] {
EGL_CONTEXT_CLIENT_VERSION,
3,
EGL_NONE
};
const char *extension_st = eglQueryString(display, EGL_EXTENSIONS);
ctx_t ctx {display, eglCreateContext(display, conf, EGL_NO_CONTEXT, attr)};
if (fail()) {
std::vector<EGLint> attr;
attr.push_back(EGL_CONTEXT_CLIENT_VERSION);
attr.push_back(3);
// Only add the high priority attribute if the driver explicitly supports it
if (extension_st && std::string_view(extension_st).contains("EGL_IMG_context_priority"sv)) {
BOOST_LOG(debug) << "EGL: High priority context supported"sv;
attr.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
attr.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
}
attr.push_back(EGL_NONE);
EGLContext raw_ctx = eglCreateContext(display, conf, EGL_NO_CONTEXT, attr.data());
if (raw_ctx == EGL_NO_CONTEXT) {
BOOST_LOG(error) << "Couldn't create EGL context: ["sv << util::hex(eglGetError()).to_string_view() << ']';
return std::nullopt;
}
TUPLE_EL_REF(ctx_p, 1, ctx.el);
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx_p)) {
ctx_t ctx {display, raw_ctx};
EGLint actual_priority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
std::string actual_priority_str = "MEDIUM";
if (eglQueryContext(display, raw_ctx, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &actual_priority)) {
if (actual_priority == EGL_CONTEXT_PRIORITY_HIGH_IMG) {
actual_priority_str = "HIGH";
}
if (nice_warning) {
BOOST_LOG(warning) << "EGL: context priority set to "sv << actual_priority_str << " but CAP_SYS_NICE capability is missing"sv;
} else {
BOOST_LOG(info) << "EGL: context priority set to "sv << actual_priority_str;
}
}
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, raw_ctx)) {
BOOST_LOG(error) << "Couldn't make current display"sv;
return std::nullopt;
}
@@ -453,6 +492,14 @@ namespace egl {
gl::ctx.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
#if !defined(__FreeBSD__)
caps = cap_get_proc();
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &sys_nice, CAP_CLEAR) || cap_set_proc(caps)) {
BOOST_LOG(debug) << "Failed to drop CAP_SYS_NICE"sv;
}
cap_free(caps);
#endif
return ctx;
}

View File

@@ -236,7 +236,7 @@ namespace portal {
void finalize_portal_security() {
#if !defined(__FreeBSD__)
BOOST_LOG(debug) << "Finalizing Portal security: dropping CAP_SYS_ADMIN and resetting dumpable"sv;
BOOST_LOG(debug) << "Finalizing Portal security: dropping capabilities and resetting dumpable"sv;
cap_t caps = cap_get_proc();
if (!caps) {
@@ -244,10 +244,11 @@ namespace portal {
return;
}
std::array<cap_value_t, 1> remove_list {CAP_SYS_ADMIN};
std::array<cap_value_t, 2> effective_list {CAP_SYS_ADMIN, CAP_SYS_NICE};
std::array<cap_value_t, 2> permitted_list {CAP_SYS_ADMIN, CAP_SYS_NICE};
cap_set_flag(caps, CAP_PERMITTED, remove_list.size(), remove_list.data(), CAP_CLEAR);
cap_set_flag(caps, CAP_EFFECTIVE, remove_list.size(), remove_list.data(), CAP_CLEAR);
cap_set_flag(caps, CAP_EFFECTIVE, effective_list.size(), effective_list.data(), CAP_CLEAR);
cap_set_flag(caps, CAP_PERMITTED, permitted_list.size(), permitted_list.data(), CAP_CLEAR);
if (cap_set_proc(caps) != 0) {
BOOST_LOG(error) << "Failed to prune capabilities: "sv << std::strerror(errno);

View File

@@ -12,10 +12,10 @@ if [ ! -x "$(command -v rpm-ostree)" ]; then
path_to_setcap=$(which setcap)
path_to_sunshine=$(readlink -f "$(which sunshine)")
if [ -x "$path_to_setcap" ] ; then
echo "Setting CAP_SYS_ADMIN capability on Sunshine binary."
echo "$path_to_setcap cap_sys_admin+p $path_to_sunshine"
$path_to_setcap cap_sys_admin+p $path_to_sunshine
echo "CAP_SYS_ADMIN capability set on Sunshine binary."
echo "Setting CAP_SYS_ADMIN, CAP_SYS_NICE capabilities on Sunshine binary."
echo "$path_to_setcap cap_sys_admin,cap_sys_nice+p $path_to_sunshine"
$path_to_setcap cap_sys_admin,cap_sys_nice+p $path_to_sunshine
echo "CAP_SYS_ADMIN, CAP_SYS_NICE capabilities set on Sunshine binary."
else
echo "error: setcap not found or not executable."
fi