mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	backend/wayland: add support for wl_shm buffers
This commit is contained in:
		
							parent
							
								
									c6b009ef85
								
							
						
					
					
						commit
						80865351bd
					
				
					 3 changed files with 80 additions and 30 deletions
				
			
		| 
						 | 
					@ -20,6 +20,7 @@
 | 
				
			||||||
#include "backend/wayland.h"
 | 
					#include "backend/wayland.h"
 | 
				
			||||||
#include "render/drm_format_set.h"
 | 
					#include "render/drm_format_set.h"
 | 
				
			||||||
#include "render/gbm_allocator.h"
 | 
					#include "render/gbm_allocator.h"
 | 
				
			||||||
 | 
					#include "render/pixel_format.h"
 | 
				
			||||||
#include "render/wlr_renderer.h"
 | 
					#include "render/wlr_renderer.h"
 | 
				
			||||||
#include "util/signal.h"
 | 
					#include "util/signal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -190,6 +191,17 @@ static const struct wl_drm_listener legacy_drm_listener = {
 | 
				
			||||||
	.capabilities = legacy_drm_handle_capabilities,
 | 
						.capabilities = legacy_drm_handle_capabilities,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void shm_handle_format(void *data, struct wl_shm *shm,
 | 
				
			||||||
 | 
							uint32_t shm_format) {
 | 
				
			||||||
 | 
						struct wlr_wl_backend *wl = data;
 | 
				
			||||||
 | 
						uint32_t drm_format = convert_wl_shm_format_to_drm(shm_format);
 | 
				
			||||||
 | 
						wlr_drm_format_set_add(&wl->shm_formats, drm_format, DRM_FORMAT_MOD_INVALID);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct wl_shm_listener shm_listener = {
 | 
				
			||||||
 | 
						.format = shm_handle_format,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void registry_global(void *data, struct wl_registry *registry,
 | 
					static void registry_global(void *data, struct wl_registry *registry,
 | 
				
			||||||
		uint32_t name, const char *iface, uint32_t version) {
 | 
							uint32_t name, const char *iface, uint32_t version) {
 | 
				
			||||||
	struct wlr_wl_backend *wl = data;
 | 
						struct wlr_wl_backend *wl = data;
 | 
				
			||||||
| 
						 | 
					@ -233,6 +245,9 @@ static void registry_global(void *data, struct wl_registry *registry,
 | 
				
			||||||
	} else if (strcmp(iface, wl_drm_interface.name) == 0) {
 | 
						} else if (strcmp(iface, wl_drm_interface.name) == 0) {
 | 
				
			||||||
		wl->legacy_drm = wl_registry_bind(registry, name, &wl_drm_interface, 1);
 | 
							wl->legacy_drm = wl_registry_bind(registry, name, &wl_drm_interface, 1);
 | 
				
			||||||
		wl_drm_add_listener(wl->legacy_drm, &legacy_drm_listener, wl);
 | 
							wl_drm_add_listener(wl->legacy_drm, &legacy_drm_listener, wl);
 | 
				
			||||||
 | 
						} else if (strcmp(iface, wl_shm_interface.name) == 0) {
 | 
				
			||||||
 | 
							wl->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
 | 
				
			||||||
 | 
							wl_shm_add_listener(wl->shm, &shm_listener, wl);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -302,6 +317,7 @@ static void backend_destroy(struct wlr_backend *backend) {
 | 
				
			||||||
	wlr_allocator_destroy(wl->allocator);
 | 
						wlr_allocator_destroy(wl->allocator);
 | 
				
			||||||
	close(wl->drm_fd);
 | 
						close(wl->drm_fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_drm_format_set_finish(&wl->shm_formats);
 | 
				
			||||||
	wlr_drm_format_set_finish(&wl->linux_dmabuf_v1_formats);
 | 
						wlr_drm_format_set_finish(&wl->linux_dmabuf_v1_formats);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_wl_buffer *buffer, *tmp_buffer;
 | 
						struct wlr_wl_buffer *buffer, *tmp_buffer;
 | 
				
			||||||
| 
						 | 
					@ -322,6 +338,9 @@ static void backend_destroy(struct wlr_backend *backend) {
 | 
				
			||||||
	if (wl->zwp_linux_dmabuf_v1) {
 | 
						if (wl->zwp_linux_dmabuf_v1) {
 | 
				
			||||||
		zwp_linux_dmabuf_v1_destroy(wl->zwp_linux_dmabuf_v1);
 | 
							zwp_linux_dmabuf_v1_destroy(wl->zwp_linux_dmabuf_v1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (wl->shm) {
 | 
				
			||||||
 | 
							wl_shm_destroy(wl->shm);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (wl->zwp_relative_pointer_manager_v1) {
 | 
						if (wl->zwp_relative_pointer_manager_v1) {
 | 
				
			||||||
		zwp_relative_pointer_manager_v1_destroy(wl->zwp_relative_pointer_manager_v1);
 | 
							zwp_relative_pointer_manager_v1_destroy(wl->zwp_relative_pointer_manager_v1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@
 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <drm_fourcc.h>
 | 
				
			||||||
#include <wayland-client.h>
 | 
					#include <wayland-client.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <wlr/interfaces/wlr_output.h>
 | 
					#include <wlr/interfaces/wlr_output.h>
 | 
				
			||||||
| 
						 | 
					@ -15,6 +16,7 @@
 | 
				
			||||||
#include <wlr/util/log.h>
 | 
					#include <wlr/util/log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "backend/wayland.h"
 | 
					#include "backend/wayland.h"
 | 
				
			||||||
 | 
					#include "render/pixel_format.h"
 | 
				
			||||||
#include "render/swapchain.h"
 | 
					#include "render/swapchain.h"
 | 
				
			||||||
#include "render/wlr_renderer.h"
 | 
					#include "render/wlr_renderer.h"
 | 
				
			||||||
#include "util/signal.h"
 | 
					#include "util/signal.h"
 | 
				
			||||||
| 
						 | 
					@ -161,17 +163,58 @@ static void buffer_handle_buffer_destroy(struct wl_listener *listener,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool test_buffer(struct wlr_wl_backend *wl,
 | 
					static bool test_buffer(struct wlr_wl_backend *wl,
 | 
				
			||||||
		struct wlr_buffer *wlr_buffer) {
 | 
							struct wlr_buffer *wlr_buffer) {
 | 
				
			||||||
	struct wlr_dmabuf_attributes attribs;
 | 
						struct wlr_dmabuf_attributes dmabuf;
 | 
				
			||||||
	if (!wlr_buffer_get_dmabuf(wlr_buffer, &attribs)) {
 | 
						struct wlr_shm_attributes shm;
 | 
				
			||||||
 | 
						if (wlr_buffer_get_dmabuf(wlr_buffer, &dmabuf)) {
 | 
				
			||||||
 | 
							return wlr_drm_format_set_has(&wl->linux_dmabuf_v1_formats,
 | 
				
			||||||
 | 
								dmabuf.format, dmabuf.modifier);
 | 
				
			||||||
 | 
						} else if (wlr_buffer_get_shm(wlr_buffer, &shm)) {
 | 
				
			||||||
 | 
							return wlr_drm_format_set_has(&wl->shm_formats, shm.format,
 | 
				
			||||||
 | 
								DRM_FORMAT_MOD_INVALID);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!wlr_drm_format_set_has(&wl->linux_dmabuf_v1_formats,
 | 
					static struct wl_buffer *import_dmabuf(struct wlr_wl_backend *wl,
 | 
				
			||||||
			attribs.format, attribs.modifier)) {
 | 
							struct wlr_dmabuf_attributes *dmabuf) {
 | 
				
			||||||
		return false;
 | 
						uint32_t modifier_hi = dmabuf->modifier >> 32;
 | 
				
			||||||
 | 
						uint32_t modifier_lo = (uint32_t)dmabuf->modifier;
 | 
				
			||||||
 | 
						struct zwp_linux_buffer_params_v1 *params =
 | 
				
			||||||
 | 
							zwp_linux_dmabuf_v1_create_params(wl->zwp_linux_dmabuf_v1);
 | 
				
			||||||
 | 
						for (int i = 0; i < dmabuf->n_planes; i++) {
 | 
				
			||||||
 | 
							zwp_linux_buffer_params_v1_add(params, dmabuf->fd[i], i,
 | 
				
			||||||
 | 
								dmabuf->offset[i], dmabuf->stride[i], modifier_hi, modifier_lo);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						uint32_t flags = 0;
 | 
				
			||||||
 | 
						if (dmabuf->flags & WLR_DMABUF_ATTRIBUTES_FLAGS_Y_INVERT) {
 | 
				
			||||||
 | 
							flags |= ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (dmabuf->flags & WLR_DMABUF_ATTRIBUTES_FLAGS_INTERLACED) {
 | 
				
			||||||
 | 
							flags |= ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (dmabuf->flags & WLR_DMABUF_ATTRIBUTES_FLAGS_BOTTOM_FIRST) {
 | 
				
			||||||
 | 
							flags |= ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_BOTTOM_FIRST;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct wl_buffer *wl_buffer = zwp_linux_buffer_params_v1_create_immed(
 | 
				
			||||||
 | 
							params, dmabuf->width, dmabuf->height, dmabuf->format, flags);
 | 
				
			||||||
 | 
						// TODO: handle create() errors
 | 
				
			||||||
 | 
						return wl_buffer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct wl_buffer *import_shm(struct wlr_wl_backend *wl,
 | 
				
			||||||
 | 
							struct wlr_shm_attributes *shm) {
 | 
				
			||||||
 | 
						enum wl_shm_format wl_shm_format = convert_drm_format_to_wl_shm(shm->format);
 | 
				
			||||||
 | 
						uint32_t size = shm->stride * shm->height;
 | 
				
			||||||
 | 
						struct wl_shm_pool *pool = wl_shm_create_pool(wl->shm, shm->fd, size);
 | 
				
			||||||
 | 
						if (pool == NULL) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct wl_buffer *wl_buffer = wl_shm_pool_create_buffer(pool, shm->offset,
 | 
				
			||||||
 | 
							shm->width, shm->height, shm->stride, wl_shm_format);
 | 
				
			||||||
 | 
						wl_shm_pool_destroy(pool);
 | 
				
			||||||
 | 
						return wl_buffer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct wlr_wl_buffer *create_wl_buffer(struct wlr_wl_backend *wl,
 | 
					static struct wlr_wl_buffer *create_wl_buffer(struct wlr_wl_backend *wl,
 | 
				
			||||||
| 
						 | 
					@ -180,34 +223,20 @@ static struct wlr_wl_buffer *create_wl_buffer(struct wlr_wl_backend *wl,
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_dmabuf_attributes attribs;
 | 
						struct wlr_dmabuf_attributes dmabuf;
 | 
				
			||||||
	if (!wlr_buffer_get_dmabuf(wlr_buffer, &attribs)) {
 | 
						struct wlr_shm_attributes shm;
 | 
				
			||||||
 | 
						struct wl_buffer *wl_buffer;
 | 
				
			||||||
 | 
						if (wlr_buffer_get_dmabuf(wlr_buffer, &dmabuf)) {
 | 
				
			||||||
 | 
							wl_buffer = import_dmabuf(wl, &dmabuf);
 | 
				
			||||||
 | 
						} else if (wlr_buffer_get_shm(wlr_buffer, &shm)) {
 | 
				
			||||||
 | 
							wl_buffer = import_shm(wl, &shm);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (wl_buffer == NULL) {
 | 
				
			||||||
	uint32_t modifier_hi = attribs.modifier >> 32;
 | 
							return NULL;
 | 
				
			||||||
	uint32_t modifier_lo = (uint32_t)attribs.modifier;
 | 
					 | 
				
			||||||
	struct zwp_linux_buffer_params_v1 *params =
 | 
					 | 
				
			||||||
		zwp_linux_dmabuf_v1_create_params(wl->zwp_linux_dmabuf_v1);
 | 
					 | 
				
			||||||
	for (int i = 0; i < attribs.n_planes; i++) {
 | 
					 | 
				
			||||||
		zwp_linux_buffer_params_v1_add(params, attribs.fd[i], i,
 | 
					 | 
				
			||||||
			attribs.offset[i], attribs.stride[i], modifier_hi, modifier_lo);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t flags = 0;
 | 
					 | 
				
			||||||
	if (attribs.flags & WLR_DMABUF_ATTRIBUTES_FLAGS_Y_INVERT) {
 | 
					 | 
				
			||||||
		flags |= ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (attribs.flags & WLR_DMABUF_ATTRIBUTES_FLAGS_INTERLACED) {
 | 
					 | 
				
			||||||
		flags |= ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (attribs.flags & WLR_DMABUF_ATTRIBUTES_FLAGS_BOTTOM_FIRST) {
 | 
					 | 
				
			||||||
		flags |= ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_BOTTOM_FIRST;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	struct wl_buffer *wl_buffer = zwp_linux_buffer_params_v1_create_immed(
 | 
					 | 
				
			||||||
		params, attribs.width, attribs.height, attribs.format, flags);
 | 
					 | 
				
			||||||
	// TODO: handle create() errors
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct wlr_wl_buffer *buffer = calloc(1, sizeof(struct wlr_wl_buffer));
 | 
						struct wlr_wl_buffer *buffer = calloc(1, sizeof(struct wlr_wl_buffer));
 | 
				
			||||||
	if (buffer == NULL) {
 | 
						if (buffer == NULL) {
 | 
				
			||||||
		wl_buffer_destroy(wl_buffer);
 | 
							wl_buffer_destroy(wl_buffer);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,10 +38,12 @@ struct wlr_wl_backend {
 | 
				
			||||||
	struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1;
 | 
						struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1;
 | 
				
			||||||
	struct zwp_pointer_gestures_v1 *zwp_pointer_gestures_v1;
 | 
						struct zwp_pointer_gestures_v1 *zwp_pointer_gestures_v1;
 | 
				
			||||||
	struct wp_presentation *presentation;
 | 
						struct wp_presentation *presentation;
 | 
				
			||||||
 | 
						struct wl_shm *shm;
 | 
				
			||||||
	struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1;
 | 
						struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1;
 | 
				
			||||||
	struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1;
 | 
						struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1;
 | 
				
			||||||
	struct wl_list seats; // wlr_wl_seat.link
 | 
						struct wl_list seats; // wlr_wl_seat.link
 | 
				
			||||||
	struct zwp_tablet_manager_v2 *tablet_manager;
 | 
						struct zwp_tablet_manager_v2 *tablet_manager;
 | 
				
			||||||
 | 
						struct wlr_drm_format_set shm_formats;
 | 
				
			||||||
	struct wlr_drm_format_set linux_dmabuf_v1_formats;
 | 
						struct wlr_drm_format_set linux_dmabuf_v1_formats;
 | 
				
			||||||
	struct wl_drm *legacy_drm;
 | 
						struct wl_drm *legacy_drm;
 | 
				
			||||||
	char *drm_render_name;
 | 
						char *drm_render_name;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue