Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save quietvoid/ab2bbe395579972da04f27435a72644d to your computer and use it in GitHub Desktop.

Select an option

Save quietvoid/ab2bbe395579972da04f27435a72644d to your computer and use it in GitHub Desktop.
Sunshine AUR patch
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, &params_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