Created
November 12, 2025 17:43
-
-
Save quietvoid/ab2bbe395579972da04f27435a72644d to your computer and use it in GitHub Desktop.
Sunshine AUR patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| From f66f1eb6589dfd1385a9f33abb7d31d0d0b836ba Mon Sep 17 00:00:00 2001 | |
| From: quietvoid <[email protected]> | |
| Date: Wed, 12 Nov 2025 12:37:06 -0500 | |
| Subject: [PATCH] Revert b43a9b8efb44fd69f32d79ae52e224f455aae1a3 | |
| --- | |
| ...ux-headless-monitors-on-wayland-3783.patch | 779 ++++++++++++++++++ | |
| PKGBUILD | 8 +- | |
| 2 files changed, 785 insertions(+), 2 deletions(-) | |
| create mode 100644 0001-Revert-fix-linux-headless-monitors-on-wayland-3783.patch | |
| diff --git a/0001-Revert-fix-linux-headless-monitors-on-wayland-3783.patch b/0001-Revert-fix-linux-headless-monitors-on-wayland-3783.patch | |
| new file mode 100644 | |
| index 0000000..a51ec3f | |
| --- /dev/null | |
| +++ b/0001-Revert-fix-linux-headless-monitors-on-wayland-3783.patch | |
| @@ -0,0 +1,779 @@ | |
| +From d1a7cbf3b5864675feaae5f39dc51ba5d6c77843 Mon Sep 17 00:00:00 2001 | |
| +From: quietvoid <[email protected]> | |
| +Date: Wed, 12 Nov 2025 12:35:14 -0500 | |
| +Subject: [PATCH] Revert "fix(linux): headless monitors on wayland (#3783)" | |
| + | |
| +This reverts commit b43a9b8efb44fd69f32d79ae52e224f455aae1a3. | |
| +--- | |
| + cmake/compile_definitions/linux.cmake | 5 +- | |
| + packaging/sunshine.rb | 1 - | |
| + scripts/linux_build.sh | 2 - | |
| + src/platform/linux/wayland.cpp | 329 ++++---------------------- | |
| + src/platform/linux/wayland.h | 145 +++++++----- | |
| + src/platform/linux/wlgrab.cpp | 2 +- | |
| + 6 files changed, 128 insertions(+), 356 deletions(-) | |
| + | |
| +diff --git a/cmake/compile_definitions/linux.cmake b/cmake/compile_definitions/linux.cmake | |
| +index 6f98c355..d6611530 100644 | |
| +--- a/cmake/compile_definitions/linux.cmake | |
| ++++ b/cmake/compile_definitions/linux.cmake | |
| +@@ -137,8 +137,7 @@ if(WAYLAND_FOUND) | |
| + endif() | |
| + | |
| + GEN_WAYLAND("${WAYLAND_PROTOCOLS_DIR}" "unstable/xdg-output" xdg-output-unstable-v1) | |
| +- GEN_WAYLAND("${WAYLAND_PROTOCOLS_DIR}" "unstable/linux-dmabuf" linux-dmabuf-unstable-v1) | |
| +- GEN_WAYLAND("${CMAKE_SOURCE_DIR}/third-party/wlr-protocols" "unstable" wlr-screencopy-unstable-v1) | |
| ++ GEN_WAYLAND("${CMAKE_SOURCE_DIR}/third-party/wlr-protocols" "unstable" wlr-export-dmabuf-unstable-v1) | |
| + | |
| + include_directories( | |
| + SYSTEM | |
| +@@ -146,7 +145,7 @@ if(WAYLAND_FOUND) | |
| + ${CMAKE_BINARY_DIR}/generated-src | |
| + ) | |
| + | |
| +- list(APPEND PLATFORM_LIBRARIES ${WAYLAND_LIBRARIES} gbm) | |
| ++ list(APPEND PLATFORM_LIBRARIES ${WAYLAND_LIBRARIES}) | |
| + list(APPEND PLATFORM_TARGET_FILES | |
| + "${CMAKE_SOURCE_DIR}/src/platform/linux/wlgrab.cpp" | |
| + "${CMAKE_SOURCE_DIR}/src/platform/linux/wayland.h" | |
| +diff --git a/packaging/sunshine.rb b/packaging/sunshine.rb | |
| +index 159778a8..d07f93bf 100644 | |
| +--- a/packaging/sunshine.rb | |
| ++++ b/packaging/sunshine.rb | |
| +@@ -54,7 +54,6 @@ class Sunshine < Formula | |
| + depends_on "libxinerama" | |
| + depends_on "libxrandr" | |
| + depends_on "libxtst" | |
| +- depends_on "mesa" | |
| + depends_on "numactl" | |
| + depends_on "pulseaudio" | |
| + depends_on "systemd" | |
| +diff --git a/scripts/linux_build.sh b/scripts/linux_build.sh | |
| +index 2c10065f..74d5da4d 100755 | |
| +--- a/scripts/linux_build.sh | |
| ++++ b/scripts/linux_build.sh | |
| +@@ -222,7 +222,6 @@ function add_debian_based_deps() { | |
| + "libcurl4-openssl-dev" | |
| + "libdrm-dev" # KMS | |
| + "libevdev-dev" | |
| +- "libgbm-dev" | |
| + "libminiupnpc-dev" | |
| + "libnotify-dev" | |
| + "libnuma-dev" | |
| +@@ -304,7 +303,6 @@ function add_fedora_deps() { | |
| + "libXrandr-devel" # X11 | |
| + "libXtst-devel" # X11 | |
| + "mesa-libGL-devel" | |
| +- "mesa-libgbm-devel" | |
| + "miniupnpc-devel" | |
| + "ninja-build" | |
| + "npm" | |
| +diff --git a/src/platform/linux/wayland.cpp b/src/platform/linux/wayland.cpp | |
| +index 4fa05a27..c6e02d72 100644 | |
| +--- a/src/platform/linux/wayland.cpp | |
| ++++ b/src/platform/linux/wayland.cpp | |
| +@@ -6,14 +6,9 @@ | |
| + #include <cstdlib> | |
| + | |
| + // platform includes | |
| +-#include <drm_fourcc.h> | |
| +-#include <fcntl.h> | |
| +-#include <gbm.h> | |
| + #include <poll.h> | |
| +-#include <unistd.h> | |
| + #include <wayland-client.h> | |
| + #include <wayland-util.h> | |
| +-#include <xf86drm.h> | |
| + | |
| + // local includes | |
| + #include "graphics.h" | |
| +@@ -42,12 +37,6 @@ namespace wl { | |
| + | |
| + #define CLASS_CALL(c, m) classCall<c, decltype(&c::m), &c::m> | |
| + | |
| +- // Define buffer params listener | |
| +- static const struct zwp_linux_buffer_params_v1_listener params_listener = { | |
| +- .created = dmabuf_t::buffer_params_created, | |
| +- .failed = dmabuf_t::buffer_params_failed | |
| +- }; | |
| +- | |
| + int display_t::init(const char *display_name) { | |
| + if (!display_name) { | |
| + display_name = std::getenv("WAYLAND_DISPLAY"); | |
| +@@ -147,13 +136,7 @@ namespace wl { | |
| + BOOST_LOG(info) << "Logical size: "sv << width << 'x' << height; | |
| + } | |
| + | |
| +- void monitor_t::wl_mode( | |
| +- wl_output *wl_output, | |
| +- std::uint32_t flags, | |
| +- std::int32_t width, | |
| +- std::int32_t height, | |
| +- std::int32_t refresh | |
| +- ) { | |
| ++ void monitor_t::wl_mode(wl_output *wl_output, std::uint32_t flags, std::int32_t width, std::int32_t height, std::int32_t refresh) { | |
| + viewport.width = width; | |
| + viewport.height = height; | |
| + | |
| +@@ -168,8 +151,6 @@ namespace wl { | |
| + | |
| + interface_t::interface_t() noexcept | |
| + : | |
| +- screencopy_manager {nullptr}, | |
| +- dmabuf_interface {nullptr}, | |
| + output_manager {nullptr}, | |
| + listener { | |
| + &CLASS_CALL(interface_t, add_interface), | |
| +@@ -181,12 +162,7 @@ namespace wl { | |
| + wl_registry_add_listener(registry, &listener, this); | |
| + } | |
| + | |
| +- void interface_t::add_interface( | |
| +- wl_registry *registry, | |
| +- std::uint32_t id, | |
| +- const char *interface, | |
| +- std::uint32_t version | |
| +- ) { | |
| ++ void interface_t::add_interface(wl_registry *registry, std::uint32_t id, const char *interface, std::uint32_t version) { | |
| + BOOST_LOG(debug) << "Available interface: "sv << interface << '(' << id << ") version "sv << version; | |
| + | |
| + if (!std::strcmp(interface, wl_output_interface.name)) { | |
| +@@ -201,16 +177,11 @@ namespace wl { | |
| + output_manager = (zxdg_output_manager_v1 *) wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, version); | |
| + | |
| + this->interface[XDG_OUTPUT] = true; | |
| +- } else if (!std::strcmp(interface, zwlr_screencopy_manager_v1_interface.name)) { | |
| ++ } else if (!std::strcmp(interface, zwlr_export_dmabuf_manager_v1_interface.name)) { | |
| + BOOST_LOG(info) << "Found interface: "sv << interface << '(' << id << ") version "sv << version; | |
| +- screencopy_manager = (zwlr_screencopy_manager_v1 *) wl_registry_bind(registry, id, &zwlr_screencopy_manager_v1_interface, version); | |
| ++ dmabuf_manager = (zwlr_export_dmabuf_manager_v1 *) wl_registry_bind(registry, id, &zwlr_export_dmabuf_manager_v1_interface, version); | |
| + | |
| + this->interface[WLR_EXPORT_DMABUF] = true; | |
| +- } else if (!std::strcmp(interface, zwp_linux_dmabuf_v1_interface.name)) { | |
| +- BOOST_LOG(info) << "Found interface: "sv << interface << '(' << id << ") version "sv << version; | |
| +- dmabuf_interface = (zwp_linux_dmabuf_v1 *) wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, version); | |
| +- | |
| +- this->interface[LINUX_DMABUF] = true; | |
| + } | |
| + } | |
| + | |
| +@@ -218,306 +189,94 @@ namespace wl { | |
| + BOOST_LOG(info) << "Delete: "sv << id; | |
| + } | |
| + | |
| +- // Initialize GBM | |
| +- bool dmabuf_t::init_gbm() { | |
| +- if (gbm_device) { | |
| +- return true; | |
| +- } | |
| +- | |
| +- // Find render node | |
| +- drmDevice *devices[16]; | |
| +- int n = drmGetDevices2(0, devices, 16); | |
| +- if (n <= 0) { | |
| +- BOOST_LOG(error) << "No DRM devices found"sv; | |
| +- return false; | |
| +- } | |
| +- | |
| +- int drm_fd = -1; | |
| +- for (int i = 0; i < n; i++) { | |
| +- if (devices[i]->available_nodes & (1 << DRM_NODE_RENDER)) { | |
| +- drm_fd = open(devices[i]->nodes[DRM_NODE_RENDER], O_RDWR); | |
| +- if (drm_fd >= 0) { | |
| +- break; | |
| +- } | |
| +- } | |
| +- } | |
| +- drmFreeDevices(devices, n); | |
| +- | |
| +- if (drm_fd < 0) { | |
| +- BOOST_LOG(error) << "Failed to open DRM render node"sv; | |
| +- return false; | |
| +- } | |
| +- | |
| +- gbm_device = gbm_create_device(drm_fd); | |
| +- if (!gbm_device) { | |
| +- close(drm_fd); | |
| +- BOOST_LOG(error) << "Failed to create GBM device"sv; | |
| +- return false; | |
| +- } | |
| +- | |
| +- return true; | |
| +- } | |
| +- | |
| +- // Cleanup GBM | |
| +- void dmabuf_t::cleanup_gbm() { | |
| +- if (current_bo) { | |
| +- gbm_bo_destroy(current_bo); | |
| +- current_bo = nullptr; | |
| +- } | |
| +- | |
| +- if (current_wl_buffer) { | |
| +- wl_buffer_destroy(current_wl_buffer); | |
| +- current_wl_buffer = nullptr; | |
| +- } | |
| +- } | |
| +- | |
| + dmabuf_t::dmabuf_t(): | |
| + status {READY}, | |
| + frames {}, | |
| + current_frame {&frames[0]}, | |
| + listener { | |
| +- &CLASS_CALL(dmabuf_t, buffer), | |
| +- &CLASS_CALL(dmabuf_t, flags), | |
| ++ &CLASS_CALL(dmabuf_t, frame), | |
| ++ &CLASS_CALL(dmabuf_t, object), | |
| + &CLASS_CALL(dmabuf_t, ready), | |
| +- &CLASS_CALL(dmabuf_t, failed), | |
| +- &CLASS_CALL(dmabuf_t, damage), | |
| +- &CLASS_CALL(dmabuf_t, linux_dmabuf), | |
| +- &CLASS_CALL(dmabuf_t, buffer_done), | |
| ++ &CLASS_CALL(dmabuf_t, cancel) | |
| + } { | |
| + } | |
| + | |
| +- // Start capture | |
| +- void dmabuf_t::listen( | |
| +- zwlr_screencopy_manager_v1 *screencopy_manager, | |
| +- zwp_linux_dmabuf_v1 *dmabuf_interface, | |
| +- wl_output *output, | |
| +- bool blend_cursor | |
| +- ) { | |
| +- this->dmabuf_interface = dmabuf_interface; | |
| +- // Reset state | |
| +- shm_info.supported = false; | |
| +- dmabuf_info.supported = false; | |
| +- | |
| +- // Create new frame | |
| +- auto frame = zwlr_screencopy_manager_v1_capture_output( | |
| +- screencopy_manager, | |
| +- blend_cursor ? 1 : 0, | |
| +- output | |
| +- ); | |
| +- | |
| +- // Store frame data pointer for callbacks | |
| +- zwlr_screencopy_frame_v1_set_user_data(frame, this); | |
| +- | |
| +- // Add listener | |
| +- zwlr_screencopy_frame_v1_add_listener(frame, &listener, this); | |
| ++ void dmabuf_t::listen(zwlr_export_dmabuf_manager_v1 *dmabuf_manager, wl_output *output, bool blend_cursor) { | |
| ++ auto frame = zwlr_export_dmabuf_manager_v1_capture_output(dmabuf_manager, blend_cursor, output); | |
| ++ zwlr_export_dmabuf_frame_v1_add_listener(frame, &listener, this); | |
| + | |
| + status = WAITING; | |
| + } | |
| + | |
| + dmabuf_t::~dmabuf_t() { | |
| +- cleanup_gbm(); | |
| +- | |
| + for (auto &frame : frames) { | |
| + frame.destroy(); | |
| + } | |
| +- | |
| +- if (gbm_device) { | |
| +- // We should close the DRM FD, but it's owned by GBM | |
| +- gbm_device_destroy(gbm_device); | |
| +- gbm_device = nullptr; | |
| +- } | |
| + } | |
| + | |
| +- // Buffer format callback | |
| +- void dmabuf_t::buffer( | |
| +- zwlr_screencopy_frame_v1 *frame, | |
| +- uint32_t format, | |
| +- uint32_t width, | |
| +- uint32_t height, | |
| +- uint32_t stride | |
| +- ) { | |
| +- shm_info.supported = true; | |
| +- shm_info.format = format; | |
| +- shm_info.width = width; | |
| +- shm_info.height = height; | |
| +- shm_info.stride = stride; | |
| +- | |
| +- BOOST_LOG(debug) << "Screencopy supports SHM format: "sv << format; | |
| +- } | |
| +- | |
| +- // DMA-BUF format callback | |
| +- void dmabuf_t::linux_dmabuf( | |
| +- zwlr_screencopy_frame_v1 *frame, | |
| +- std::uint32_t format, | |
| ++ void dmabuf_t::frame( | |
| ++ zwlr_export_dmabuf_frame_v1 *frame, | |
| + std::uint32_t width, | |
| +- std::uint32_t height | |
| ++ std::uint32_t height, | |
| ++ std::uint32_t x, | |
| ++ std::uint32_t y, | |
| ++ std::uint32_t buffer_flags, | |
| ++ std::uint32_t flags, | |
| ++ std::uint32_t format, | |
| ++ std::uint32_t high, | |
| ++ std::uint32_t low, | |
| ++ std::uint32_t obj_count | |
| + ) { | |
| +- dmabuf_info.supported = true; | |
| +- dmabuf_info.format = format; | |
| +- dmabuf_info.width = width; | |
| +- dmabuf_info.height = height; | |
| +- | |
| +- BOOST_LOG(debug) << "Screencopy supports DMA-BUF format: "sv << format; | |
| +- } | |
| +- | |
| +- // Flags callback | |
| +- void dmabuf_t::flags(zwlr_screencopy_frame_v1 *frame, std::uint32_t flags) { | |
| +- y_invert = flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT; | |
| +- BOOST_LOG(debug) << "Frame flags: "sv << flags << (y_invert ? " (y_invert)" : ""); | |
| +- } | |
| +- | |
| +- // DMA-BUF creation helper | |
| +- void dmabuf_t::create_and_copy_dmabuf(zwlr_screencopy_frame_v1 *frame) { | |
| +- if (!init_gbm()) { | |
| +- BOOST_LOG(error) << "Failed to initialize GBM"sv; | |
| +- zwlr_screencopy_frame_v1_destroy(frame); | |
| +- status = REINIT; | |
| +- return; | |
| +- } | |
| +- | |
| +- // Create GBM buffer | |
| +- current_bo = gbm_bo_create(gbm_device, dmabuf_info.width, dmabuf_info.height, dmabuf_info.format, GBM_BO_USE_RENDERING); | |
| +- if (!current_bo) { | |
| +- BOOST_LOG(error) << "Failed to create GBM buffer"sv; | |
| +- zwlr_screencopy_frame_v1_destroy(frame); | |
| +- status = REINIT; | |
| +- return; | |
| +- } | |
| +- | |
| +- // Get buffer info | |
| +- int fd = gbm_bo_get_fd(current_bo); | |
| +- if (fd < 0) { | |
| +- BOOST_LOG(error) << "Failed to get buffer FD"sv; | |
| +- gbm_bo_destroy(current_bo); | |
| +- current_bo = nullptr; | |
| +- zwlr_screencopy_frame_v1_destroy(frame); | |
| +- status = REINIT; | |
| +- return; | |
| +- } | |
| +- | |
| +- uint32_t stride = gbm_bo_get_stride(current_bo); | |
| +- uint64_t modifier = gbm_bo_get_modifier(current_bo); | |
| +- | |
| +- // Store in surface descriptor for later use | |
| +- auto next_frame = get_next_frame(); | |
| +- next_frame->sd.fds[0] = fd; | |
| +- next_frame->sd.pitches[0] = stride; | |
| +- next_frame->sd.offsets[0] = 0; | |
| +- next_frame->sd.modifier = modifier; | |
| +- | |
| +- // Create linux-dmabuf buffer | |
| +- auto params = zwp_linux_dmabuf_v1_create_params(dmabuf_interface); | |
| +- zwp_linux_buffer_params_v1_add(params, fd, 0, 0, stride, modifier >> 32, modifier & 0xffffffff); | |
| +- | |
| +- // Add listener for buffer creation | |
| +- zwp_linux_buffer_params_v1_add_listener(params, ¶ms_listener, frame); | |
| +- | |
| +- // Create Wayland buffer (async - callback will handle copy) | |
| +- zwp_linux_buffer_params_v1_create(params, dmabuf_info.width, dmabuf_info.height, dmabuf_info.format, 0); | |
| +- } | |
| +- | |
| +- // Buffer done callback - time to create buffer | |
| +- void dmabuf_t::buffer_done(zwlr_screencopy_frame_v1 *frame) { | |
| + auto next_frame = get_next_frame(); | |
| + | |
| +- // Prefer DMA-BUF if supported | |
| +- if (dmabuf_info.supported && dmabuf_interface) { | |
| +- // Store format info first | |
| +- next_frame->sd.fourcc = dmabuf_info.format; | |
| +- next_frame->sd.width = dmabuf_info.width; | |
| +- next_frame->sd.height = dmabuf_info.height; | |
| +- | |
| +- // Create and start copy | |
| +- create_and_copy_dmabuf(frame); | |
| +- } else if (shm_info.supported) { | |
| +- // SHM fallback would go here | |
| +- BOOST_LOG(warning) << "SHM capture not implemented"sv; | |
| +- zwlr_screencopy_frame_v1_destroy(frame); | |
| +- status = REINIT; | |
| +- } else { | |
| +- BOOST_LOG(error) << "No supported buffer types"sv; | |
| +- zwlr_screencopy_frame_v1_destroy(frame); | |
| +- status = REINIT; | |
| +- } | |
| +- } | |
| +- | |
| +- // Buffer params created callback | |
| +- void dmabuf_t::buffer_params_created( | |
| +- void *data, | |
| +- struct zwp_linux_buffer_params_v1 *params, | |
| +- struct wl_buffer *buffer | |
| +- ) { | |
| +- auto frame = static_cast<zwlr_screencopy_frame_v1 *>(data); | |
| +- auto self = static_cast<dmabuf_t *>(zwlr_screencopy_frame_v1_get_user_data(frame)); | |
| +- | |
| +- // Store for cleanup | |
| +- self->current_wl_buffer = buffer; | |
| +- | |
| +- // Start the actual copy | |
| +- zwlr_screencopy_frame_v1_copy(frame, buffer); | |
| ++ next_frame->sd.fourcc = format; | |
| ++ next_frame->sd.width = width; | |
| ++ next_frame->sd.height = height; | |
| ++ next_frame->sd.modifier = (((std::uint64_t) high) << 32) | low; | |
| + } | |
| + | |
| +- // Buffer params failed callback | |
| +- void dmabuf_t::buffer_params_failed( | |
| +- void *data, | |
| +- struct zwp_linux_buffer_params_v1 *params | |
| ++ void dmabuf_t::object( | |
| ++ zwlr_export_dmabuf_frame_v1 *frame, | |
| ++ std::uint32_t index, | |
| ++ std::int32_t fd, | |
| ++ std::uint32_t size, | |
| ++ std::uint32_t offset, | |
| ++ std::uint32_t stride, | |
| ++ std::uint32_t plane_index | |
| + ) { | |
| +- auto frame = static_cast<zwlr_screencopy_frame_v1 *>(data); | |
| +- auto self = static_cast<dmabuf_t *>(zwlr_screencopy_frame_v1_get_user_data(frame)); | |
| +- | |
| +- BOOST_LOG(error) << "Failed to create buffer from params"sv; | |
| +- self->cleanup_gbm(); | |
| ++ auto next_frame = get_next_frame(); | |
| + | |
| +- zwlr_screencopy_frame_v1_destroy(frame); | |
| +- self->status = REINIT; | |
| ++ next_frame->sd.fds[plane_index] = fd; | |
| ++ next_frame->sd.pitches[plane_index] = stride; | |
| ++ next_frame->sd.offsets[plane_index] = offset; | |
| + } | |
| + | |
| +- // Ready callback | |
| + void dmabuf_t::ready( | |
| +- zwlr_screencopy_frame_v1 *frame, | |
| ++ zwlr_export_dmabuf_frame_v1 *frame, | |
| + std::uint32_t tv_sec_hi, | |
| + std::uint32_t tv_sec_lo, | |
| + std::uint32_t tv_nsec | |
| + ) { | |
| +- BOOST_LOG(debug) << "Frame ready"sv; | |
| ++ zwlr_export_dmabuf_frame_v1_destroy(frame); | |
| + | |
| +- // Frame is ready for use, GBM buffer now contains screen content | |
| + current_frame->destroy(); | |
| + current_frame = get_next_frame(); | |
| + | |
| +- // Keep the GBM buffer alive but destroy the Wayland objects | |
| +- if (current_wl_buffer) { | |
| +- wl_buffer_destroy(current_wl_buffer); | |
| +- current_wl_buffer = nullptr; | |
| +- } | |
| +- | |
| +- cleanup_gbm(); | |
| +- | |
| +- zwlr_screencopy_frame_v1_destroy(frame); | |
| + status = READY; | |
| + } | |
| + | |
| +- // Failed callback | |
| +- void dmabuf_t::failed(zwlr_screencopy_frame_v1 *frame) { | |
| +- BOOST_LOG(error) << "Frame capture failed"sv; | |
| ++ void dmabuf_t::cancel( | |
| ++ zwlr_export_dmabuf_frame_v1 *frame, | |
| ++ std::uint32_t reason | |
| ++ ) { | |
| ++ zwlr_export_dmabuf_frame_v1_destroy(frame); | |
| + | |
| +- // Clean up resources | |
| +- cleanup_gbm(); | |
| + auto next_frame = get_next_frame(); | |
| + next_frame->destroy(); | |
| + | |
| +- zwlr_screencopy_frame_v1_destroy(frame); | |
| + status = REINIT; | |
| + } | |
| + | |
| +- void dmabuf_t::damage( | |
| +- zwlr_screencopy_frame_v1 *frame, | |
| +- std::uint32_t x, | |
| +- std::uint32_t y, | |
| +- std::uint32_t width, | |
| +- std::uint32_t height | |
| +- ) {}; | |
| +- | |
| + void frame_t::destroy() { | |
| + for (auto x = 0; x < 4; ++x) { | |
| + if (sd.fds[x] >= 0) { | |
| +diff --git a/src/platform/linux/wayland.h b/src/platform/linux/wayland.h | |
| +index 08d5acbd..6a6986f6 100644 | |
| +--- a/src/platform/linux/wayland.h | |
| ++++ b/src/platform/linux/wayland.h | |
| +@@ -8,8 +8,7 @@ | |
| + #include <bitset> | |
| + | |
| + #ifdef SUNSHINE_BUILD_WAYLAND | |
| +- #include <linux-dmabuf-unstable-v1.h> | |
| +- #include <wlr-screencopy-unstable-v1.h> | |
| ++ #include <wlr-export-dmabuf-unstable-v1.h> | |
| + #include <xdg-output-unstable-v1.h> | |
| + #endif | |
| + | |
| +@@ -28,9 +27,9 @@ namespace wl { | |
| + class frame_t { | |
| + public: | |
| + frame_t(); | |
| +- void destroy(); | |
| +- | |
| + egl::surface_descriptor_t sd; | |
| ++ | |
| ++ void destroy(); | |
| + }; | |
| + | |
| + class dmabuf_t { | |
| +@@ -41,91 +40,104 @@ namespace wl { | |
| + REINIT, ///< Reinitialize the frame | |
| + }; | |
| + | |
| +- dmabuf_t(); | |
| +- ~dmabuf_t(); | |
| +- | |
| + dmabuf_t(dmabuf_t &&) = delete; | |
| + dmabuf_t(const dmabuf_t &) = delete; | |
| ++ | |
| + dmabuf_t &operator=(const dmabuf_t &) = delete; | |
| + dmabuf_t &operator=(dmabuf_t &&) = delete; | |
| + | |
| +- void listen(zwlr_screencopy_manager_v1 *screencopy_manager, zwp_linux_dmabuf_v1 *dmabuf_interface, wl_output *output, bool blend_cursor = false); | |
| +- static void buffer_params_created(void *data, struct zwp_linux_buffer_params_v1 *params, struct wl_buffer *wl_buffer); | |
| +- static void buffer_params_failed(void *data, struct zwp_linux_buffer_params_v1 *params); | |
| +- void buffer(zwlr_screencopy_frame_v1 *frame, std::uint32_t format, std::uint32_t width, std::uint32_t height, std::uint32_t stride); | |
| +- void linux_dmabuf(zwlr_screencopy_frame_v1 *frame, std::uint32_t format, std::uint32_t width, std::uint32_t height); | |
| +- void buffer_done(zwlr_screencopy_frame_v1 *frame); | |
| +- void flags(zwlr_screencopy_frame_v1 *frame, std::uint32_t flags); | |
| +- void damage(zwlr_screencopy_frame_v1 *frame, std::uint32_t x, std::uint32_t y, std::uint32_t width, std::uint32_t height); | |
| +- void ready(zwlr_screencopy_frame_v1 *frame, std::uint32_t tv_sec_hi, std::uint32_t tv_sec_lo, std::uint32_t tv_nsec); | |
| +- void failed(zwlr_screencopy_frame_v1 *frame); | |
| +- | |
| +- frame_t *get_next_frame() { | |
| ++ dmabuf_t(); | |
| ++ | |
| ++ void listen(zwlr_export_dmabuf_manager_v1 *dmabuf_manager, wl_output *output, bool blend_cursor = false); | |
| ++ | |
| ++ ~dmabuf_t(); | |
| ++ | |
| ++ void frame( | |
| ++ zwlr_export_dmabuf_frame_v1 *frame, | |
| ++ std::uint32_t width, | |
| ++ std::uint32_t height, | |
| ++ std::uint32_t x, | |
| ++ std::uint32_t y, | |
| ++ std::uint32_t buffer_flags, | |
| ++ std::uint32_t flags, | |
| ++ std::uint32_t format, | |
| ++ std::uint32_t high, | |
| ++ std::uint32_t low, | |
| ++ std::uint32_t obj_count | |
| ++ ); | |
| ++ | |
| ++ void object( | |
| ++ zwlr_export_dmabuf_frame_v1 *frame, | |
| ++ std::uint32_t index, | |
| ++ std::int32_t fd, | |
| ++ std::uint32_t size, | |
| ++ std::uint32_t offset, | |
| ++ std::uint32_t stride, | |
| ++ std::uint32_t plane_index | |
| ++ ); | |
| ++ | |
| ++ void ready( | |
| ++ zwlr_export_dmabuf_frame_v1 *frame, | |
| ++ std::uint32_t tv_sec_hi, | |
| ++ std::uint32_t tv_sec_lo, | |
| ++ std::uint32_t tv_nsec | |
| ++ ); | |
| ++ | |
| ++ void cancel( | |
| ++ zwlr_export_dmabuf_frame_v1 *frame, | |
| ++ std::uint32_t reason | |
| ++ ); | |
| ++ | |
| ++ inline frame_t *get_next_frame() { | |
| + return current_frame == &frames[0] ? &frames[1] : &frames[0]; | |
| + } | |
| + | |
| + status_e status; | |
| ++ | |
| + std::array<frame_t, 2> frames; | |
| + frame_t *current_frame; | |
| +- zwlr_screencopy_frame_v1_listener listener; | |
| + | |
| +- private: | |
| +- bool init_gbm(); | |
| +- void cleanup_gbm(); | |
| +- void create_and_copy_dmabuf(zwlr_screencopy_frame_v1 *frame); | |
| +- | |
| +- zwp_linux_dmabuf_v1 *dmabuf_interface {nullptr}; | |
| +- | |
| +- struct { | |
| +- bool supported {false}; | |
| +- std::uint32_t format; | |
| +- std::uint32_t width; | |
| +- std::uint32_t height; | |
| +- std::uint32_t stride; | |
| +- } shm_info; | |
| +- | |
| +- struct { | |
| +- bool supported {false}; | |
| +- std::uint32_t format; | |
| +- std::uint32_t width; | |
| +- std::uint32_t height; | |
| +- } dmabuf_info; | |
| +- | |
| +- struct gbm_device *gbm_device {nullptr}; | |
| +- struct gbm_bo *current_bo {nullptr}; | |
| +- struct wl_buffer *current_wl_buffer {nullptr}; | |
| +- bool y_invert {false}; | |
| ++ zwlr_export_dmabuf_frame_v1_listener listener; | |
| + }; | |
| + | |
| + class monitor_t { | |
| + public: | |
| +- explicit monitor_t(wl_output *output); | |
| +- | |
| + monitor_t(monitor_t &&) = delete; | |
| + monitor_t(const monitor_t &) = delete; | |
| ++ | |
| + monitor_t &operator=(const monitor_t &) = delete; | |
| + monitor_t &operator=(monitor_t &&) = delete; | |
| + | |
| +- void listen(zxdg_output_manager_v1 *output_manager); | |
| ++ monitor_t(wl_output *output); | |
| ++ | |
| + void xdg_name(zxdg_output_v1 *, const char *name); | |
| + void xdg_description(zxdg_output_v1 *, const char *description); | |
| + void xdg_position(zxdg_output_v1 *, std::int32_t x, std::int32_t y); | |
| + void xdg_size(zxdg_output_v1 *, std::int32_t width, std::int32_t height); | |
| + | |
| +- void xdg_done(zxdg_output_v1 *) {} | |
| ++ void xdg_done(zxdg_output_v1 *) { | |
| ++ } | |
| + | |
| +- void wl_geometry(wl_output *wl_output, std::int32_t x, std::int32_t y, std::int32_t physical_width, std::int32_t physical_height, std::int32_t subpixel, const char *make, const char *model, std::int32_t transform) {} | |
| ++ void wl_geometry(wl_output *wl_output, std::int32_t x, std::int32_t y, std::int32_t physical_width, std::int32_t physical_height, std::int32_t subpixel, const char *make, const char *model, std::int32_t transform) { | |
| ++ } | |
| + | |
| + void wl_mode(wl_output *wl_output, std::uint32_t flags, std::int32_t width, std::int32_t height, std::int32_t refresh); | |
| + | |
| +- void wl_done(wl_output *wl_output) {} | |
| ++ void wl_done(wl_output *wl_output) { | |
| ++ } | |
| ++ | |
| ++ void wl_scale(wl_output *wl_output, std::int32_t factor) { | |
| ++ } | |
| + | |
| +- void wl_scale(wl_output *wl_output, std::int32_t factor) {} | |
| ++ void listen(zxdg_output_manager_v1 *output_manager); | |
| + | |
| + wl_output *output; | |
| ++ | |
| + std::string name; | |
| + std::string description; | |
| ++ | |
| + platf::touch_port_t viewport; | |
| ++ | |
| + wl_output_listener wl_listener; | |
| + zxdg_output_v1_listener xdg_listener; | |
| + }; | |
| +@@ -139,34 +151,35 @@ namespace wl { | |
| + public: | |
| + enum interface_e { | |
| + XDG_OUTPUT, ///< xdg-output | |
| +- WLR_EXPORT_DMABUF, ///< screencopy manager | |
| +- LINUX_DMABUF, ///< linux-dmabuf protocol | |
| ++ WLR_EXPORT_DMABUF, ///< Export dmabuf | |
| + MAX_INTERFACES, ///< Maximum number of interfaces | |
| + }; | |
| + | |
| +- interface_t() noexcept; | |
| +- | |
| + interface_t(interface_t &&) = delete; | |
| + interface_t(const interface_t &) = delete; | |
| ++ | |
| + interface_t &operator=(const interface_t &) = delete; | |
| + interface_t &operator=(interface_t &&) = delete; | |
| + | |
| ++ interface_t() noexcept; | |
| ++ | |
| + void listen(wl_registry *registry); | |
| + | |
| ++ std::vector<std::unique_ptr<monitor_t>> monitors; | |
| ++ | |
| ++ zwlr_export_dmabuf_manager_v1 *dmabuf_manager; | |
| ++ zxdg_output_manager_v1 *output_manager; | |
| ++ | |
| + bool operator[](interface_e bit) const { | |
| + return interface[bit]; | |
| + } | |
| + | |
| +- std::vector<std::unique_ptr<monitor_t>> monitors; | |
| +- zwlr_screencopy_manager_v1 *screencopy_manager {nullptr}; | |
| +- zwp_linux_dmabuf_v1 *dmabuf_interface {nullptr}; | |
| +- zxdg_output_manager_v1 *output_manager {nullptr}; | |
| +- | |
| + private: | |
| + void add_interface(wl_registry *registry, std::uint32_t id, const char *interface, std::uint32_t version); | |
| + void del_interface(wl_registry *registry, uint32_t id); | |
| + | |
| + std::bitset<MAX_INTERFACES> interface; | |
| ++ | |
| + wl_registry_listener listener; | |
| + }; | |
| + | |
| +@@ -199,6 +212,7 @@ namespace wl { | |
| + }; | |
| + | |
| + std::vector<std::unique_ptr<monitor_t>> monitors(const char *display_name = nullptr); | |
| ++ | |
| + int init(); | |
| + } // namespace wl | |
| + #else | |
| +@@ -209,18 +223,21 @@ struct zxdg_output_manager_v1; | |
| + namespace wl { | |
| + class monitor_t { | |
| + public: | |
| +- monitor_t(wl_output *output); | |
| +- | |
| + monitor_t(monitor_t &&) = delete; | |
| + monitor_t(const monitor_t &) = delete; | |
| ++ | |
| + monitor_t &operator=(const monitor_t &) = delete; | |
| + monitor_t &operator=(monitor_t &&) = delete; | |
| + | |
| ++ monitor_t(wl_output *output); | |
| ++ | |
| + void listen(zxdg_output_manager_v1 *output_manager); | |
| + | |
| + wl_output *output; | |
| ++ | |
| + std::string name; | |
| + std::string description; | |
| ++ | |
| + platf::touch_port_t viewport; | |
| + }; | |
| + | |
| +diff --git a/src/platform/linux/wlgrab.cpp b/src/platform/linux/wlgrab.cpp | |
| +index 9ef3e09f..b867b908 100644 | |
| +--- a/src/platform/linux/wlgrab.cpp | |
| ++++ b/src/platform/linux/wlgrab.cpp | |
| +@@ -90,7 +90,7 @@ namespace wl { | |
| + auto to = std::chrono::steady_clock::now() + timeout; | |
| + | |
| + // Dispatch events until we get a new frame or the timeout expires | |
| +- dmabuf.listen(interface.screencopy_manager, interface.dmabuf_interface, output, cursor); | |
| ++ dmabuf.listen(interface.dmabuf_manager, output, cursor); | |
| + do { | |
| + auto remaining_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(to - std::chrono::steady_clock::now()); | |
| + if (remaining_time_ms.count() < 0 || !display.dispatch(remaining_time_ms)) { | |
| +-- | |
| +2.51.2 | |
| + | |
| diff --git a/PKGBUILD b/PKGBUILD | |
| index 706d748..e20c575 100644 | |
| --- a/PKGBUILD | |
| +++ b/PKGBUILD | |
| @@ -16,6 +16,7 @@ arch=('x86_64' 'aarch64') | |
| url=https://app.lizardbyte.dev/Sunshine | |
| license=('GPL-3.0-only') | |
| install=sunshine.install | |
| +options=('!debug') | |
| _gcc_version=14 | |
| @@ -62,8 +63,9 @@ optdepends=( | |
| provides=() | |
| conflicts=() | |
| -source=("$pkgname::git+https://github.com/LizardByte/Sunshine.git#commit=${_commit}") | |
| -sha256sums=('SKIP') | |
| +source=("$pkgname::git+https://github.com/LizardByte/Sunshine.git#commit=${_commit}" | |
| + "0001-Revert-fix-linux-headless-monitors-on-wayland-3783.patch") | |
| +sha256sums=('SKIP' 'a4d20f250b9deb34598aedf34e477020de3f509a41ab2d4e18dfee2783520cb5') | |
| # Options Handling | |
| if [[ "${_use_cuda::1}" == "d" ]] && pacman -Qi cuda &> /dev/null; then | |
| @@ -97,6 +99,8 @@ fi | |
| prepare() { | |
| cd "$pkgname" | |
| + git am 0001-Revert-fix-linux-headless-monitors-on-wayland-3783.patch | |
| + | |
| git submodule update --recursive --init | |
| } | |
| -- | |
| 2.51.2 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment