Sunshine0.0.5917
Sunshine 0.0.5917
Self-hosted game stream host for Moonlight.
Loading...
Searching...
No Matches
Go to the documentation of this file.
1
5#pragma once
6
7// standard includes
8#include <array>
9#include <bitset>
10#include <chrono>
11#include <cstdint>
12#include <map>
13#include <optional>
14#include <string>
15#include <vector>
16
17#ifdef SUNSHINE_BUILD_WAYLAND
18 #include <linux-dmabuf-unstable-v1.h>
19 #include <wlr-screencopy-unstable-v1.h>
20 #include <xdg-output-unstable-v1.h>
21#endif
22
23// local includes
24#include "graphics.h"
25
30#ifdef SUNSHINE_BUILD_WAYLAND
31
32struct gbm_bo;
33struct gbm_device;
34
35namespace wl {
42 bool use_vram_capture(platf::mem_type_e hwdevice_type);
43
58 bool use_damage_capture(std::uint32_t screencopy_version, double stream_fps, std::int32_t refresh_mhz);
59
73 std::chrono::steady_clock::time_point next_damage_request(
74 std::chrono::steady_clock::time_point next_request,
75 std::chrono::steady_clock::time_point frame_time,
76 std::chrono::nanoseconds delay
77 );
78
93 std::chrono::steady_clock::time_point damage_frame_time(
94 std::optional<std::chrono::steady_clock::time_point> compositor_time,
95 std::chrono::steady_clock::time_point now,
96 std::chrono::nanoseconds delay
97 );
98
107
130 screencopy_request_e next_screencopy_request(bool pending, bool requested_cursor, bool cursor, bool event_driven, bool have_frame);
131
142 bool should_wait_for_damage_request(
143 std::chrono::steady_clock::time_point next_request,
144 std::chrono::steady_clock::time_point now,
145 std::chrono::nanoseconds delay
146 );
147
155 std::map<std::uint32_t, std::vector<std::uint64_t>> intersect_modifiers(
156 const std::map<std::uint32_t, std::vector<std::uint64_t>> &compositor_modifiers,
157 const std::map<std::uint32_t, std::vector<std::uint64_t>> &encoder_modifiers
158 );
159
164
169 int (*get_plane_count)(gbm_bo *bo);
170 int (*get_fd_for_plane)(gbm_bo *bo, int plane);
171 std::uint32_t (*get_stride_for_plane)(gbm_bo *bo, int plane);
172 std::uint32_t (*get_offset)(gbm_bo *bo, int plane);
173 std::uint64_t (*get_modifier)(gbm_bo *bo);
174 };
175
180 int (*open_render_node)(const char *path);
181 gbm_device *(*create_device)(int fd);
182 void (*destroy_device)(gbm_device *device);
183 };
184
192 public:
196 gbm_device_t() = default;
197
201 gbm_device_t(const gbm_device_t &) = delete;
202
207
212
220 bool init(const std::string &render_path, const gbm_device_accessors_t &accessors);
221
225 void reset();
226
230 gbm_device *get() const {
231 return device;
232 }
233
237 int fd() const {
238 return drm_fd;
239 }
240
244 explicit operator bool() const {
245 return device != nullptr;
246 }
247
248 private:
249 gbm_device_accessors_t accessors {};
250 int drm_fd {-1};
251 gbm_device *device {nullptr};
252 };
253
257 class frame_t {
258 public:
259 frame_t();
263 void destroy();
264
266 std::optional<std::chrono::steady_clock::time_point> frame_timestamp;
267 };
268
277 std::optional<std::uint32_t> export_gbm_bo_planes(gbm_bo *bo, frame_t &frame, const gbm_bo_accessors_t &accessors);
278
282 class dmabuf_t {
283 public:
292
293 dmabuf_t();
294 ~dmabuf_t();
295
296 dmabuf_t(dmabuf_t &&) = delete;
297 dmabuf_t(const dmabuf_t &) = delete;
298 dmabuf_t &operator=(const dmabuf_t &) = delete;
299 dmabuf_t &operator=(dmabuf_t &&) = delete;
300
311 void listen(zwlr_screencopy_manager_v1 *screencopy_manager, zwp_linux_dmabuf_v1 *dmabuf_interface, const std::map<std::uint32_t, std::vector<std::uint64_t>> *supported_modifiers, wl_output *output, bool blend_cursor = false, const std::map<std::uint32_t, std::vector<std::uint64_t>> *encoder_modifiers = nullptr);
319 static void buffer_params_created(void *data, struct zwp_linux_buffer_params_v1 *params, struct wl_buffer *wl_buffer);
326 static void buffer_params_failed(void *data, struct zwp_linux_buffer_params_v1 *params);
336 void buffer(zwlr_screencopy_frame_v1 *frame, std::uint32_t format, std::uint32_t width, std::uint32_t height, std::uint32_t stride);
345 void linux_dmabuf(zwlr_screencopy_frame_v1 *frame, std::uint32_t format, std::uint32_t width, std::uint32_t height);
351 void buffer_done(zwlr_screencopy_frame_v1 *frame);
358 void flags(zwlr_screencopy_frame_v1 *frame, std::uint32_t flags);
368 void damage(zwlr_screencopy_frame_v1 *frame, std::uint32_t x, std::uint32_t y, std::uint32_t width, std::uint32_t height);
377 void ready(zwlr_screencopy_frame_v1 *frame, std::uint32_t tv_sec_hi, std::uint32_t tv_sec_lo, std::uint32_t tv_nsec);
383 void failed(zwlr_screencopy_frame_v1 *frame);
384
393 bool cancel();
394
401 return current_frame == &frames[0] ? &frames[1] : &frames[0];
402 }
403
405 bool with_damage {false};
406 std::array<frame_t, 2> frames {};
408 zwlr_screencopy_frame_v1_listener listener;
409
410 private:
411 bool init_gbm();
412 void cleanup_gbm();
413 void create_and_copy_dmabuf(zwlr_screencopy_frame_v1 *frame);
414
415 zwp_linux_dmabuf_v1 *dmabuf_interface {nullptr};
416 const std::map<std::uint32_t, std::vector<std::uint64_t>> *supported_modifiers {nullptr};
417 const std::map<std::uint32_t, std::vector<std::uint64_t>> *encoder_modifiers {nullptr};
418
419 struct {
420 bool supported {false};
421 std::uint32_t format;
422 std::uint32_t width;
423 std::uint32_t height;
424 std::uint32_t stride;
425 } shm_info;
426
427 struct {
428 bool supported {false};
429 std::uint32_t format;
430 std::uint32_t width;
431 std::uint32_t height;
432 } dmabuf_info;
433
434 gbm_device_t gbm;
435 struct gbm_bo *current_bo {nullptr};
436 struct wl_buffer *current_wl_buffer {nullptr};
437 zwlr_screencopy_frame_v1 *pending_copy {nullptr};
438 bool y_invert {false};
439 };
440
444 class monitor_t {
445 public:
451 explicit monitor_t(wl_output *output);
452
453 monitor_t(monitor_t &&) = delete;
454 monitor_t(const monitor_t &) = delete;
455 monitor_t &operator=(const monitor_t &) = delete;
456 monitor_t &operator=(monitor_t &&) = delete;
457
463 void listen(zxdg_output_manager_v1 *output_manager);
469 void xdg_name(zxdg_output_v1 *, const char *name);
475 void xdg_description(zxdg_output_v1 *, const char *description);
482 void xdg_position(zxdg_output_v1 *, std::int32_t x, std::int32_t y);
489 void xdg_size(zxdg_output_v1 *, std::int32_t width, std::int32_t height);
490
494 void xdg_done(zxdg_output_v1 *) {}
495
500 void wl_geometry(wl_output *, std::int32_t, std::int32_t, std::int32_t, std::int32_t, std::int32_t, const char *, const char *, std::int32_t) {
501 // Logical placement comes from xdg-output, so physical geometry has nothing to update.
502 }
503
513 void wl_mode(wl_output *wl_output, std::uint32_t flags, std::int32_t width, std::int32_t height, std::int32_t refresh);
514
519 void wl_done(wl_output *) {
520 // Metadata is stored as each event arrives; completion requires no additional work.
521 }
522
527 void wl_scale(wl_output *, std::int32_t) {
528 // Pixel mode and xdg-output logical size already describe the capture and input coordinate spaces.
529 }
530
531 wl_output *output;
532 std::string name;
533 std::string description;
535 std::int32_t refresh_mhz {0};
536 wl_output_listener wl_listener;
537 zxdg_output_v1_listener xdg_listener;
538 };
539
543 class interface_t {
544 struct bind_t {
545 std::uint32_t id;
546 std::uint32_t version;
547 };
548
549 public:
559
560 interface_t() noexcept;
561
562 interface_t(interface_t &&) = delete;
563 interface_t(const interface_t &) = delete;
564 interface_t &operator=(const interface_t &) = delete;
565 interface_t &operator=(interface_t &&) = delete;
566
572 void listen(wl_registry *registry);
573
580 bool operator[](interface_e bit) const {
581 return interface[bit];
582 }
583
590 void dmabuf_format(zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format);
600 void dmabuf_modifier(zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo);
601
602 std::vector<std::unique_ptr<monitor_t>> monitors;
603 std::map<std::uint32_t, std::vector<std::uint64_t>> supported_modifiers;
604 zwlr_screencopy_manager_v1 *screencopy_manager {nullptr};
605 std::uint32_t screencopy_version {0};
606 zwp_linux_dmabuf_v1 *dmabuf_interface {nullptr};
607 zxdg_output_manager_v1 *output_manager {nullptr};
608
609 private:
610 void add_interface(wl_registry *registry, std::uint32_t id, const char *interface, std::uint32_t version);
611 void del_interface(wl_registry *registry, uint32_t id);
612
613 std::bitset<MAX_INTERFACES> interface;
614 wl_registry_listener listener;
615 zwp_linux_dmabuf_v1_listener dmabuf_listener;
616 };
617
621 class display_t {
622 public:
629 int init(const char *display_name = nullptr);
630
631 // Roundtrip with Wayland connection
635 void roundtrip();
636
637 // Wait up to the timeout to read and dispatch new events
638 bool dispatch(std::chrono::milliseconds timeout);
639
645 wl_registry *registry();
646
653 return display_internal.get();
654 }
655
656 private:
657 display_internal_t display_internal;
658 };
659
666 std::vector<std::unique_ptr<monitor_t>> monitors(const char *display_name = nullptr);
672 int init();
673} // namespace wl
674#else
675
676struct wl_output;
677struct zxdg_output_manager_v1;
678
679namespace wl {
680 class monitor_t {
681 public:
682 monitor_t(wl_output *output);
683
684 monitor_t(monitor_t &&) = delete;
685 monitor_t(const monitor_t &) = delete;
686 monitor_t &operator=(const monitor_t &) = delete;
687 monitor_t &operator=(monitor_t &&) = delete;
688
689 void listen(zxdg_output_manager_v1 *output_manager);
690
691 wl_output *output;
692 std::string name;
693 std::string description;
694 platf::touch_port_t viewport;
695 };
696
697 inline std::vector<std::unique_ptr<monitor_t>> monitors(const char *display_name = nullptr) {
698 return {};
699 }
700
701 inline int init() {
702 return -1;
703 }
704} // namespace wl
705#endif
element_type * pointer
Definition utility.h:823
Wayland display connection used to dispatch capture events.
Definition wayland.h:621
wl_registry * registry()
Return the Wayland registry for global discovery.
Definition wayland.cpp:170
int init(const char *display_name=nullptr)
Connect to the requested Wayland display.
Definition wayland.cpp:112
void roundtrip()
Flush pending Wayland requests and wait for replies.
Definition wayland.cpp:136
display_internal_t::pointer get()
Return the native Wayland display pointer.
Definition wayland.h:652
bool dispatch(std::chrono::milliseconds timeout)
Waits up to the specified timeout to dispatch new events on the wl_display.
Definition wayland.cpp:145
Listener state for Wayland screencopy frames backed by DMA-BUFs.
Definition wayland.h:282
void linux_dmabuf(zwlr_screencopy_frame_v1 *frame, std::uint32_t format, std::uint32_t width, std::uint32_t height)
Record Linux DMA-BUF parameters advertised for the frame.
Definition wayland.cpp:432
void ready(zwlr_screencopy_frame_v1 *frame, std::uint32_t tv_sec_hi, std::uint32_t tv_sec_lo, std::uint32_t tv_nsec)
Mark the current screencopy frame as ready and store its timestamp.
Definition wayland.cpp:601
status_e status
Current state of the active screencopy request, initially ready.
Definition wayland.h:404
void buffer_done(zwlr_screencopy_frame_v1 *frame)
Allocate or import the buffer once the compositor finished describing it.
Definition wayland.cpp:537
void damage(zwlr_screencopy_frame_v1 *frame, std::uint32_t x, std::uint32_t y, std::uint32_t width, std::uint32_t height)
Record damaged frame bounds reported by the compositor.
Definition wayland.cpp:661
void flags(zwlr_screencopy_frame_v1 *frame, std::uint32_t flags)
Record frame flags reported by the compositor.
Definition wayland.cpp:445
static void buffer_params_failed(void *data, struct zwp_linux_buffer_params_v1 *params)
Mark DMA-BUF buffer creation as failed.
Definition wayland.cpp:584
void listen(zwlr_screencopy_manager_v1 *screencopy_manager, zwp_linux_dmabuf_v1 *dmabuf_interface, const std::map< std::uint32_t, std::vector< std::uint64_t > > *supported_modifiers, wl_output *output, bool blend_cursor=false, const std::map< std::uint32_t, std::vector< std::uint64_t > > *encoder_modifiers=nullptr)
Start a screencopy request and attach the DMA-BUF listener callbacks.
Definition wayland.cpp:375
bool with_damage
Ask the compositor for the next frame that differs, rather than for a frame now.
Definition wayland.h:405
frame_t * get_next_frame()
Select the inactive frame slot for the next screencopy request.
Definition wayland.h:400
static void buffer_params_created(void *data, struct zwp_linux_buffer_params_v1 *params, struct wl_buffer *wl_buffer)
Store the Wayland buffer created for a DMA-BUF parameter request.
Definition wayland.cpp:562
bool cancel()
Withdraw the request that is waiting for the compositor to copy a frame.
Definition wayland.cpp:644
void failed(zwlr_screencopy_frame_v1 *frame)
Mark the frame capture as failed.
Definition wayland.cpp:631
frame_t * current_frame
Frame descriptor currently being filled by the compositor.
Definition wayland.h:407
status_e
Capture state for the active screencopy request.
Definition wayland.h:287
@ WAITING
Waiting for a frame.
Definition wayland.h:288
@ READY
Frame is ready.
Definition wayland.h:289
@ REINIT
Reinitialize the frame.
Definition wayland.h:290
void buffer(zwlr_screencopy_frame_v1 *frame, std::uint32_t format, std::uint32_t width, std::uint32_t height, std::uint32_t stride)
Record DMA-BUF buffer parameters from the compositor.
Definition wayland.cpp:417
std::array< frame_t, 2 > frames
Double-buffered frame descriptors.
Definition wayland.h:406
zwlr_screencopy_frame_v1_listener listener
Callback table registered on screencopy frames.
Definition wayland.h:408
Captured Wayland frame metadata and DMA-BUF surface state.
Definition wayland.h:257
egl::surface_descriptor_t sd
DMA-BUF surface descriptor received from the compositor.
Definition wayland.h:265
void destroy()
Release file descriptors and native buffers associated with this frame.
Definition wayland.cpp:669
std::optional< std::chrono::steady_clock::time_point > frame_timestamp
Capture timestamp associated with the frame.
Definition wayland.h:266
void reset()
Destroy the GBM device and close the render-node descriptor.
Definition wayland.cpp:81
int fd() const
Definition wayland.h:237
gbm_device_t(const gbm_device_t &)=delete
Copying is disabled: the descriptor and the device have exactly one owner.
gbm_device_t()=default
Construct an empty owner that holds neither a device nor a descriptor.
gbm_device * get() const
Definition wayland.h:230
bool init(const std::string &render_path, const gbm_device_accessors_t &accessors)
Open the render node and create the GBM device on it.
Definition wayland.cpp:61
gbm_device_t & operator=(const gbm_device_t &)=delete
Copy assignment is disabled: the descriptor and the device have exactly one owner.
Wayland registry state for screencopy, DMA-BUF, and output globals.
Definition wayland.h:543
std::vector< std::unique_ptr< monitor_t > > monitors
Outputs discovered from the Wayland registry.
Definition wayland.h:602
void listen(wl_registry *registry)
Discover compositor globals from the Wayland registry.
Definition wayland.cpp:255
zwlr_screencopy_manager_v1 * screencopy_manager
WLR screencopy global used to request frames.
Definition wayland.h:604
interface_e
Wayland globals required by the WLR capture backend.
Definition wayland.h:553
@ WLR_EXPORT_DMABUF
screencopy manager
Definition wayland.h:555
@ LINUX_DMABUF
linux-dmabuf protocol
Definition wayland.h:556
@ MAX_INTERFACES
Maximum number of interfaces.
Definition wayland.h:557
@ XDG_OUTPUT
xdg-output
Definition wayland.h:554
zwp_linux_dmabuf_v1 * dmabuf_interface
Linux DMA-BUF global used to allocate frame buffers.
Definition wayland.h:606
std::uint32_t screencopy_version
Version of the screencopy global the compositor offered.
Definition wayland.h:605
void dmabuf_modifier(zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo)
Record an explicit DMA-BUF format modifier advertised by the compositor.
Definition wayland.cpp:262
std::map< std::uint32_t, std::vector< std::uint64_t > > supported_modifiers
DRM format modifiers grouped by format.
Definition wayland.h:603
void dmabuf_format(zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format)
Record a DMA-BUF format advertised by the compositor.
Definition wayland.cpp:259
zxdg_output_manager_v1 * output_manager
xdg-output global used to query monitor names and sizes.
Definition wayland.h:607
Wayland output metadata used to match a configured display name.
Definition wayland.h:444
std::string name
xdg-output name used for display selection.
Definition wayland.h:532
void xdg_description(zxdg_output_v1 *, const char *description)
Store the xdg-output human-readable monitor description.
Definition wayland.cpp:197
void xdg_done(zxdg_output_v1 *)
Acknowledge completion of an xdg-output metadata update.
Definition wayland.h:494
void wl_scale(wl_output *, std::int32_t)
Ignore wl-output scale; capture uses the active pixel mode and xdg-output logical size.
Definition wayland.h:527
wl_output * output
Wayland output associated with this monitor.
Definition wayland.h:531
zxdg_output_v1_listener xdg_listener
Callback table for xdg-output events.
Definition wayland.h:537
void wl_geometry(wl_output *, std::int32_t, std::int32_t, std::int32_t, std::int32_t, std::int32_t, const char *, const char *, std::int32_t)
Ignore physical wl-output geometry; monitor placement comes from xdg-output metadata.
Definition wayland.h:500
wl_output_listener wl_listener
Callback table for wl-output events.
Definition wayland.h:536
void wl_done(wl_output *)
Acknowledge completion of a wl-output metadata update.
Definition wayland.h:519
void xdg_name(zxdg_output_v1 *, const char *name)
Store the xdg-output logical monitor name.
Definition wayland.cpp:191
std::string description
xdg-output description used for logs and UI.
Definition wayland.h:533
void listen(zxdg_output_manager_v1 *output_manager)
Attach xdg-output and wl-output listeners for this monitor.
Definition wayland.cpp:234
void xdg_size(zxdg_output_v1 *, std::int32_t width, std::int32_t height)
Store the logical monitor size reported by xdg-output.
Definition wayland.cpp:210
std::int32_t refresh_mhz
Refresh rate of the current mode in mHz, 0 when the compositor did not say.
Definition wayland.h:535
void wl_mode(wl_output *wl_output, std::uint32_t flags, std::int32_t width, std::int32_t height, std::int32_t refresh)
Store the active pixel mode reported by wl-output.
Definition wayland.cpp:216
monitor_t(wl_output *output)
Track a Wayland output and its advertised modes.
Definition wayland.cpp:174
platf::touch_port_t viewport
Logical monitor bounds used to scale absolute input.
Definition wayland.h:534
void xdg_position(zxdg_output_v1 *, std::int32_t x, std::int32_t y)
Store the logical monitor position reported by xdg-output.
Definition wayland.cpp:203
Declarations for graphics related functions.
EGL surface descriptor used to import a captured DMA-BUF.
Definition graphics.h:497
Touchscreen coordinate bounds used to scale absolute input.
Definition common.h:387
GBM buffer accessors used to export DMA-BUF plane metadata.
Definition wayland.h:168
std::uint32_t(*) get_offset(gbm_bo *bo, int plane)
Return the byte offset for one plane.
Definition wayland.h:172
std::uint32_t(*) get_stride_for_plane(gbm_bo *bo, int plane)
Return the row stride for one plane.
Definition wayland.h:171
std::uint64_t(*) get_modifier(gbm_bo *bo)
Return the DRM format modifier shared by the planes.
Definition wayland.h:173
int(*) get_fd_for_plane(gbm_bo *bo, int plane)
Duplicate the DMA-BUF descriptor for one plane.
Definition wayland.h:170
int(*) get_plane_count(gbm_bo *bo)
Return the number of memory planes in the buffer.
Definition wayland.h:169
Functions used to open a render node and create/destroy a GBM device on it.
Definition wayland.h:179
int(*) open_render_node(const char *path)
Open the render node and return its descriptor, or -1.
Definition wayland.h:180
void(*) destroy_device(gbm_device *device)
Destroy a GBM device (does not close the descriptor).
Definition wayland.h:182
uniq_ptr< T, Destroy< T *, void, function > > safe_ptr
Unique pointer using a compile-time C-style destroy function.
Definition utility.h:1590
std::vector< std::unique_ptr< monitor_t > > monitors(const char *display_name)
Refresh the monitor list reported by the display server.
Definition wayland.cpp:687
std::optional< std::uint32_t > export_gbm_bo_planes(gbm_bo *bo, frame_t &frame, const gbm_bo_accessors_t &accessors)
Export every GBM buffer plane into a captured frame descriptor.
Definition wayland.cpp:450
int init()
Initialize Wayland registry interfaces required for capture.
Definition wayland.cpp:722
screencopy_request_e
What a capture does about its screencopy request before waiting for a frame.
Definition wayland.h:102
@ copy
Ask for a frame now.
Definition wayland.h:104
@ keep
Keep waiting for the request that is already out.
Definition wayland.h:103
@ copy_with_damage
Ask for the next frame that differs.
Definition wayland.h:105
std::chrono::steady_clock::time_point next_damage_request(std::chrono::steady_clock::time_point next_request, std::chrono::steady_clock::time_point frame_time, std::chrono::nanoseconds delay)
Move the earliest time of the next damage-driven request on by one captured frame.
Definition wlgrab.cpp:45
util::safe_ptr< wl_display, wl_display_disconnect > display_internal_t
Owning pointer for a Wayland display connection.
Definition wayland.h:163
bool use_vram_capture(platf::mem_type_e hwdevice_type)
Determine whether wlroots capture should keep frames in VRAM for the requested memory type.
Definition wlgrab.cpp:23
std::chrono::steady_clock::time_point damage_frame_time(std::optional< std::chrono::steady_clock::time_point > compositor_time, std::chrono::steady_clock::time_point now, std::chrono::nanoseconds delay)
Pick the time a captured frame is charged to the damage-driven budget at.
Definition wlgrab.cpp:53
bool use_damage_capture(std::uint32_t screencopy_version, double stream_fps, std::int32_t refresh_mhz)
Determine whether wlroots capture should ask for frames with copy_with_damage.
Definition wlgrab.cpp:41