diff --git a/include/wlr/interfaces/wlr_ext_image_capture_source_v1.h b/include/wlr/interfaces/wlr_ext_image_capture_source_v1.h new file mode 100644 index 00000000..239e515c --- /dev/null +++ b/include/wlr/interfaces/wlr_ext_image_capture_source_v1.h @@ -0,0 +1,30 @@ +/* + * This an unstable interface of wlroots. No guarantees are made regarding the + * future consistency of this API. + */ +#ifndef WLR_USE_UNSTABLE +#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" +#endif + +#ifndef WLR_INTERFACES_WLR_EXT_IMAGE_CAPTURE_SOURCE_V1_H +#define WLR_INTERFACES_WLR_EXT_IMAGE_CAPTURE_SOURCE_V1_H + +#include +#include + +struct wlr_ext_image_copy_capture_frame_v1; + +struct wlr_ext_image_capture_source_v1_interface { + void (*schedule_frame)(struct wlr_ext_image_capture_source_v1 *source); + void (*copy_frame)(struct wlr_ext_image_capture_source_v1 *source, + struct wlr_ext_image_copy_capture_frame_v1 *dst_frame, + struct wlr_ext_image_capture_source_v1_frame_event *frame_event); +}; + +void wlr_ext_image_capture_source_v1_init(struct wlr_ext_image_capture_source_v1 *source, + const struct wlr_ext_image_capture_source_v1_interface *impl); +void wlr_ext_image_capture_source_v1_finish(struct wlr_ext_image_capture_source_v1 *source); +bool wlr_ext_image_capture_source_v1_create_resource(struct wlr_ext_image_capture_source_v1 *source, + struct wl_client *client, uint32_t new_id); + +#endif diff --git a/include/wlr/types/wlr_ext_image_capture_source_v1.h b/include/wlr/types/wlr_ext_image_capture_source_v1.h new file mode 100644 index 00000000..5405bf01 --- /dev/null +++ b/include/wlr/types/wlr_ext_image_capture_source_v1.h @@ -0,0 +1,60 @@ +/* + * This an unstable interface of wlroots. No guarantees are made regarding the + * future consistency of this API. + */ +#ifndef WLR_USE_UNSTABLE +#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" +#endif + +#ifndef WLR_TYPES_WLR_EXT_IMAGE_CAPTURE_SOURCE_V1_H +#define WLR_TYPES_WLR_EXT_IMAGE_CAPTURE_SOURCE_V1_H + +#include +#include +#include + +/** + * A screen capture source. + * + * When the size, device or formats change, the constraints_update event is + * emitted. + * + * The device and formats advertised are suitable for copying into a + * struct wlr_buffer. + */ +struct wlr_ext_image_capture_source_v1 { + const struct wlr_ext_image_capture_source_v1_interface *impl; + struct wl_list resources; // wl_resource_get_link() + + uint32_t width, height; + + uint32_t *shm_formats; + size_t shm_formats_len; + + dev_t dmabuf_device; + struct wlr_drm_format_set dmabuf_formats; + + struct { + struct wl_signal constraints_update; + struct wl_signal frame; // struct wlr_ext_image_capture_source_v1_frame_event + struct wl_signal destroy; + } events; +}; + +/** + * Event indicating that the source has produced a new frame. + */ +struct wlr_ext_image_capture_source_v1_frame_event { + const pixman_region32_t *damage; +}; + +/** + * Obtain a struct wlr_ext_image_capture_source_v1 from an ext_image_capture_source_v1 + * resource. + * + * Asserts that the resource has the correct type. Returns NULL if the resource + * is inert. + */ +struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_from_resource(struct wl_resource *resource); + +#endif diff --git a/protocol/meson.build b/protocol/meson.build index a4476918..b8b22003 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -1,5 +1,5 @@ wayland_protos = dependency('wayland-protocols', - version: '>=1.35', + version: '>=1.37', fallback: 'wayland-protocols', default_options: ['tests=false'], ) @@ -26,6 +26,7 @@ protocols = { 'drm-lease-v1': wl_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml', 'ext-foreign-toplevel-list-v1': wl_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml', 'ext-idle-notify-v1': wl_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml', + 'ext-image-capture-source-v1': wl_protocol_dir / 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml', 'ext-session-lock-v1': wl_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml', 'fractional-scale-v1': wl_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml', 'linux-drm-syncobj-v1': wl_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml', diff --git a/types/ext_image_capture_source_v1/base.c b/types/ext_image_capture_source_v1/base.c new file mode 100644 index 00000000..1b45da75 --- /dev/null +++ b/types/ext_image_capture_source_v1/base.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include "ext-image-capture-source-v1-protocol.h" + +static void source_handle_destroy(struct wl_client *client, + struct wl_resource *source_resource) { + wl_resource_destroy(source_resource); +} + +static const struct ext_image_capture_source_v1_interface source_impl = { + .destroy = source_handle_destroy, +}; + +struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_from_resource(struct wl_resource *resource) { + assert(wl_resource_instance_of(resource, + &ext_image_capture_source_v1_interface, &source_impl)); + return wl_resource_get_user_data(resource); +} + +static void source_handle_resource_destroy(struct wl_resource *resource) { + wl_list_remove(wl_resource_get_link(resource)); +} + +void wlr_ext_image_capture_source_v1_init(struct wlr_ext_image_capture_source_v1 *source, + const struct wlr_ext_image_capture_source_v1_interface *impl) { + *source = (struct wlr_ext_image_capture_source_v1){ + .impl = impl, + }; + wl_list_init(&source->resources); + wl_signal_init(&source->events.destroy); + wl_signal_init(&source->events.constraints_update); + wl_signal_init(&source->events.frame); +} + +void wlr_ext_image_capture_source_v1_finish(struct wlr_ext_image_capture_source_v1 *source) { + wl_signal_emit_mutable(&source->events.destroy, NULL); + + struct wl_resource *resource, *resource_tmp; + wl_resource_for_each_safe(resource, resource_tmp, &source->resources) { + wl_resource_set_user_data(resource, NULL); + wl_list_remove(wl_resource_get_link(resource)); + wl_list_init(wl_resource_get_link(resource)); + } + + free(source->shm_formats); + wlr_drm_format_set_finish(&source->dmabuf_formats); +} + +bool wlr_ext_image_capture_source_v1_create_resource(struct wlr_ext_image_capture_source_v1 *source, + struct wl_client *client, uint32_t new_id) { + struct wl_resource *resource = wl_resource_create(client, + &ext_image_capture_source_v1_interface, 1, new_id); + if (resource == NULL) { + wl_client_post_no_memory(client); + return false; + } + wl_resource_set_implementation(resource, &source_impl, source, + source_handle_resource_destroy); + if (source != NULL) { + wl_list_insert(&source->resources, wl_resource_get_link(resource)); + } else { + wl_list_init(wl_resource_get_link(resource)); + } + return true; +} diff --git a/types/meson.build b/types/meson.build index ec70d4b7..899959da 100644 --- a/types/meson.build +++ b/types/meson.build @@ -3,6 +3,7 @@ wlr_files += files( 'data_device/wlr_data_offer.c', 'data_device/wlr_data_source.c', 'data_device/wlr_drag.c', + 'ext_image_capture_source_v1/base.c', 'output/cursor.c', 'output/output.c', 'output/render.c',