diff options
Diffstat (limited to 'sway')
-rw-r--r-- | sway/server.c | 10 | ||||
-rw-r--r-- | sway/tree/container.c | 83 |
2 files changed, 92 insertions, 1 deletions
diff --git a/sway/server.c b/sway/server.c index 582a04ab..f50a0987 100644 --- a/sway/server.c +++ b/sway/server.c @@ -13,10 +13,12 @@ #include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_data_control_v1.h> #include <wlr/types/wlr_drm_lease_v1.h> +#include <wlr/types/wlr_drm.h> #include <wlr/types/wlr_export_dmabuf_v1.h> #include <wlr/types/wlr_gamma_control_v1.h> #include <wlr/types/wlr_idle.h> #include <wlr/types/wlr_layer_shell_v1.h> +#include <wlr/types/wlr_linux_dmabuf_v1.h> #include <wlr/types/wlr_pointer_constraints_v1.h> #include <wlr/types/wlr_primary_selection_v1.h> #include <wlr/types/wlr_relative_pointer_v1.h> @@ -78,7 +80,13 @@ bool server_init(struct sway_server *server) { return false; } - wlr_renderer_init_wl_display(server->renderer, server->wl_display); + wlr_renderer_init_wl_shm(server->renderer, server->wl_display); + + if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) { + wlr_drm_create(server->wl_display, server->renderer); + server->linux_dmabuf_v1 = + wlr_linux_dmabuf_v1_create(server->wl_display, server->renderer); + } server->allocator = wlr_allocator_autocreate(server->backend, server->renderer); diff --git a/sway/tree/container.c b/sway/tree/container.c index 0284c9a5..132b6819 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -5,8 +5,12 @@ #include <stdlib.h> #include <string.h> #include <strings.h> +#include <sys/stat.h> #include <wayland-server-core.h> +#include <wlr/types/wlr_linux_dmabuf_v1.h> #include <wlr/types/wlr_output_layout.h> +#include <wlr/render/drm_format_set.h> +#include "linux-dmabuf-unstable-v1-protocol.h" #include "cairo_util.h" #include "pango.h" #include "sway/config.h" @@ -1051,6 +1055,16 @@ void container_end_mouse_operation(struct sway_container *container) { } } +static bool devid_from_fd(int fd, dev_t *devid) { + struct stat stat; + if (fstat(fd, &stat) != 0) { + sway_log_errno(SWAY_ERROR, "fstat failed"); + return false; + } + *devid = stat.st_rdev; + return true; +} + static void set_fullscreen(struct sway_container *con, bool enable) { if (!con->view) { return; @@ -1062,6 +1076,75 @@ static void set_fullscreen(struct sway_container *con, bool enable) { con->view->foreign_toplevel, enable); } } + + if (!server.linux_dmabuf_v1 || !con->view->surface) { + return; + } + if (!enable) { + wlr_linux_dmabuf_v1_set_surface_feedback(server.linux_dmabuf_v1, + con->view->surface, NULL); + return; + } + + if (!con->pending.workspace || !con->pending.workspace->output) { + return; + } + + struct sway_output *output = con->pending.workspace->output; + struct wlr_output *wlr_output = output->wlr_output; + + // TODO: add wlroots helpers for all of this stuff + + const struct wlr_drm_format_set *renderer_formats = + wlr_renderer_get_dmabuf_texture_formats(server.renderer); + assert(renderer_formats); + + int renderer_drm_fd = wlr_renderer_get_drm_fd(server.renderer); + int backend_drm_fd = wlr_backend_get_drm_fd(wlr_output->backend); + if (renderer_drm_fd < 0 || backend_drm_fd < 0) { + return; + } + + dev_t render_dev, scanout_dev; + if (!devid_from_fd(renderer_drm_fd, &render_dev) || + !devid_from_fd(backend_drm_fd, &scanout_dev)) { + return; + } + + const struct wlr_drm_format_set *output_formats = + wlr_output_get_primary_formats(output->wlr_output, + WLR_BUFFER_CAP_DMABUF); + if (!output_formats) { + return; + } + + struct wlr_drm_format_set scanout_formats = {0}; + if (!wlr_drm_format_set_intersect(&scanout_formats, + output_formats, renderer_formats)) { + return; + } + + struct wlr_linux_dmabuf_feedback_v1_tranche tranches[] = { + { + .target_device = scanout_dev, + .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, + .formats = &scanout_formats, + }, + { + .target_device = render_dev, + .formats = renderer_formats, + }, + }; + + const struct wlr_linux_dmabuf_feedback_v1 feedback = { + .main_device = render_dev, + .tranches = tranches, + .tranches_len = sizeof(tranches) / sizeof(tranches[0]), + }; + wlr_linux_dmabuf_v1_set_surface_feedback(server.linux_dmabuf_v1, + con->view->surface, &feedback); + + wlr_drm_format_set_finish(&scanout_formats); } static void container_fullscreen_workspace(struct sway_container *con) { |