diff --git a/include/wlr_screencast.h b/include/wlr_screencast.h index 0f711aa..09cbe84 100644 --- a/include/wlr_screencast.h +++ b/include/wlr_screencast.h @@ -3,7 +3,14 @@ #include "screencast_common.h" -#define SC_MANAGER_VERSION 2 +#define WL_OUTPUT_VERSION 1 + +#define SC_MANAGER_VERSION 3 +#define SC_MANAGER_VERSION_MIN 2 + +#define WL_SHM_VERSION 1 + +#define XDG_OUTPUT_MANAGER_VERSION 3 struct xdpw_state; diff --git a/protocols/wlr-screencopy-unstable-v1.xml b/protocols/wlr-screencopy-unstable-v1.xml index a07cbca..b60ae2c 100644 --- a/protocols/wlr-screencopy-unstable-v1.xml +++ b/protocols/wlr-screencopy-unstable-v1.xml @@ -38,7 +38,7 @@ interface version number is reset. - + This object is a manager which offers requests to start capturing from a source. @@ -80,13 +80,18 @@ - + This object represents a single frame. - When created, a "buffer" event will be sent. The client will then be able - to send a "copy" request. If the capture is successful, the compositor - will send a "flags" followed by a "ready" event. + When created, a series of buffer events will be sent, each representing a + supported buffer type. The "buffer_done" event is sent afterwards to + indicate that all supported buffer types have been enumerated. The client + will then be able to send a "copy" request. If the capture is successful, + the compositor will send a "flags" followed by a "ready" event. + + For objects version 2 or lower, wl_shm buffers are always supported, ie. + the "buffer" event is guaranteed to be sent. If the capture failed, the "failed" event is sent. This can happen anytime before the "ready" event. @@ -96,14 +101,12 @@ - - Provides information about the frame's buffer. This event is sent once - as soon as the frame is created. - - The client should then create a buffer with the provided attributes, and - send a "copy" request. + + Provides information about wl_shm buffer parameters that need to be + used for this frame. This event is sent once after the frame is created + if wl_shm buffers are supported. - + @@ -112,8 +115,9 @@ Copy the frame to the supplied buffer. The buffer must have a the - correct size, see zwlr_screencopy_frame_v1.buffer. The buffer needs to - have a supported format. + correct size, see zwlr_screencopy_frame_v1.buffer and + zwlr_screencopy_frame_v1.linux_dmabuf. The buffer needs to have a + supported format. If the frame is successfully copied, a "flags" and a "ready" events are sent. Otherwise, a "failed" event is sent. @@ -203,5 +207,26 @@ + + + + + Provides information about linux-dmabuf buffer parameters that need to + be used for this frame. This event is sent once after the frame is + created if linux-dmabuf buffers are supported. + + + + + + + + + This event is sent once after all buffer events have been sent. + + The client should proceed to create a buffer of one of the supported + types, and send a "copy" request. + + diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index 3b324a9..a93e248 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -21,13 +21,13 @@ static void wlr_frame_buffer_destroy(struct xdpw_screencast_instance *cast) { // Even though this check may be deemed unnecessary, - // this has been found to cause SEGFAULTs, like this one: + // this has been found to cause SEGFAULTs, like this one: // https://github.com/emersion/xdg-desktop-portal-wlr/issues/50 if (cast->simple_frame.data != NULL) { munmap(cast->simple_frame.data, cast->simple_frame.size); cast->simple_frame.data = NULL; } - + if (cast->simple_frame.buffer != NULL) { wl_buffer_destroy(cast->simple_frame.buffer); cast->simple_frame.buffer = NULL; @@ -123,6 +123,22 @@ static void wlr_frame_buffer_chparam(struct xdpw_screencast_instance *cast, wlr_frame_buffer_destroy(cast); } +static void wlr_frame_linux_dmabuf(void *data, + struct zwlr_screencopy_frame_v1 *frame, + uint32_t format, uint32_t width, uint32_t height) { + + logprint(TRACE, "wlroots: linux_dmabuf event handler"); +} + +static void wlr_frame_buffer_done(void *data, + struct zwlr_screencopy_frame_v1 *frame) { + struct xdpw_screencast_instance *cast = data; + + logprint(TRACE, "wlroots: buffer_done event handler"); + zwlr_screencopy_frame_v1_copy_with_damage(frame, cast->simple_frame.buffer); + logprint(TRACE, "wlroots: frame copied"); +} + static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) { struct xdpw_screencast_instance *cast = data; @@ -150,8 +166,9 @@ static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, abort(); } - zwlr_screencopy_frame_v1_copy_with_damage(frame, cast->simple_frame.buffer); - logprint(TRACE, "wlroots: frame copied"); + if (zwlr_screencopy_manager_v1_get_version(cast->ctx->screencopy_manager) < 3) { + wlr_frame_buffer_done(cast,frame); + } } static void wlr_frame_flags(void *data, struct zwlr_screencopy_frame_v1 *frame, @@ -203,6 +220,8 @@ static void wlr_frame_damage(void *data, struct zwlr_screencopy_frame_v1 *frame, static const struct zwlr_screencopy_frame_v1_listener wlr_frame_listener = { .buffer = wlr_frame_buffer, + .buffer_done = wlr_frame_buffer_done, + .linux_dmabuf = wlr_frame_linux_dmabuf, .flags = wlr_frame_flags, .ready = wlr_frame_ready, .failed = wlr_frame_failed, @@ -325,28 +344,39 @@ static void wlr_registry_handle_add(void *data, struct wl_registry *reg, uint32_t id, const char *interface, uint32_t ver) { struct xdpw_screencast_context *ctx = data; + logprint(DEBUG, "wlroots: interface to register %s (Version: %u)",interface, ver); if (!strcmp(interface, wl_output_interface.name)) { struct xdpw_wlr_output *output = malloc(sizeof(*output)); output->id = id; - output->output = wl_registry_bind(reg, id, &wl_output_interface, 1); + logprint(DEBUG, "wlroots: |-- registered to interface %s (Version %u)", interface, WL_OUTPUT_VERSION); + output->output = wl_registry_bind(reg, id, &wl_output_interface, WL_OUTPUT_VERSION); wl_output_add_listener(output->output, &wlr_output_listener, output); wl_list_insert(&ctx->output_list, &output->link); } if (!strcmp(interface, zwlr_screencopy_manager_v1_interface.name)) { + uint32_t version = ver; + if (SC_MANAGER_VERSION < ver) { + version = SC_MANAGER_VERSION; + } else if (ver < SC_MANAGER_VERSION_MIN) { + version = SC_MANAGER_VERSION_MIN; + } + logprint(DEBUG, "wlroots: |-- registered to interface %s (Version %u)", interface, version); ctx->screencopy_manager = wl_registry_bind( - reg, id, &zwlr_screencopy_manager_v1_interface, SC_MANAGER_VERSION); + reg, id, &zwlr_screencopy_manager_v1_interface, version); } if (strcmp(interface, wl_shm_interface.name) == 0) { - ctx->shm = wl_registry_bind(reg, id, &wl_shm_interface, 1); + logprint(DEBUG, "wlroots: |-- registered to interface %s (Version %u)", interface, WL_SHM_VERSION); + ctx->shm = wl_registry_bind(reg, id, &wl_shm_interface, WL_SHM_VERSION); } if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { + logprint(DEBUG, "wlroots: |-- registered to interface %s (Version %u)", interface, XDG_OUTPUT_MANAGER_VERSION); ctx->xdg_output_manager = - wl_registry_bind(reg, id, &zxdg_output_manager_v1_interface, 3); + wl_registry_bind(reg, id, &zxdg_output_manager_v1_interface, XDG_OUTPUT_MANAGER_VERSION); } }