diff --git a/include/wlr/types/wlr_export_dmabuf_v1.h b/include/wlr/types/wlr_export_dmabuf_v1.h index 204da985..42c88e5c 100644 --- a/include/wlr/types/wlr_export_dmabuf_v1.h +++ b/include/wlr/types/wlr_export_dmabuf_v1.h @@ -35,7 +35,7 @@ struct wlr_export_dmabuf_frame_v1 { bool cursor_locked; - struct wl_listener output_swap_buffers; + struct wl_listener output_precommit; }; struct wlr_export_dmabuf_manager_v1 *wlr_export_dmabuf_manager_v1_create( diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index b2f4cff9..e50f9ba3 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -56,7 +56,7 @@ enum wlr_output_state_field { */ struct wlr_output_state { uint32_t committed; // enum wlr_output_state_field - pixman_region32_t damage; + pixman_region32_t damage; // output-buffer-local coordinates }; struct wlr_output_impl; @@ -111,8 +111,8 @@ struct wlr_output { // Emitted when buffers need to be swapped (because software cursors or // fullscreen damage or because of backend-specific logic) struct wl_signal needs_commit; - // Emitted right before buffer swap - struct wl_signal swap_buffers; // wlr_output_event_swap_buffers + // Emitted right before buffer commit + struct wl_signal precommit; // wlr_output_event_precommit // Emitted right after the buffer has been presented to the user struct wl_signal present; // wlr_output_event_present struct wl_signal enable; @@ -133,10 +133,9 @@ struct wlr_output { void *data; }; -struct wlr_output_event_swap_buffers { +struct wlr_output_event_precommit { struct wlr_output *output; struct timespec *when; - pixman_region32_t *damage; // output-buffer-local coordinates }; enum wlr_output_present_flag { diff --git a/include/wlr/types/wlr_screencopy_v1.h b/include/wlr/types/wlr_screencopy_v1.h index c7197bab..ff76d829 100644 --- a/include/wlr/types/wlr_screencopy_v1.h +++ b/include/wlr/types/wlr_screencopy_v1.h @@ -42,7 +42,7 @@ struct wlr_screencopy_frame_v1 { struct wl_listener buffer_destroy; struct wlr_output *output; - struct wl_listener output_swap_buffers; + struct wl_listener output_precommit; void *data; }; diff --git a/types/wlr_export_dmabuf_v1.c b/types/wlr_export_dmabuf_v1.c index 3af7e69f..fa3ae5dc 100644 --- a/types/wlr_export_dmabuf_v1.c +++ b/types/wlr_export_dmabuf_v1.c @@ -38,7 +38,7 @@ static void frame_destroy(struct wlr_export_dmabuf_frame_v1 *frame) { wlr_output_lock_software_cursors(frame->output, false); } wl_list_remove(&frame->link); - wl_list_remove(&frame->output_swap_buffers.link); + wl_list_remove(&frame->output_precommit.link); wlr_dmabuf_attributes_finish(&frame->attribs); // Make the frame resource inert wl_resource_set_user_data(frame->resource, NULL); @@ -50,14 +50,18 @@ static void frame_handle_resource_destroy(struct wl_resource *resource) { frame_destroy(frame); } -static void frame_output_handle_swap_buffers(struct wl_listener *listener, +static void frame_output_handle_precommit(struct wl_listener *listener, void *data) { struct wlr_export_dmabuf_frame_v1 *frame = - wl_container_of(listener, frame, output_swap_buffers); - struct wlr_output_event_swap_buffers *event = data; + wl_container_of(listener, frame, output_precommit); + struct wlr_output_event_precommit *event = data; - wl_list_remove(&frame->output_swap_buffers.link); - wl_list_init(&frame->output_swap_buffers.link); + if (!(event->output->pending.committed & WLR_OUTPUT_STATE_BUFFER)) { + return; + } + + wl_list_remove(&frame->output_precommit.link); + wl_list_init(&frame->output_precommit.link); time_t tv_sec = event->when->tv_sec; uint32_t tv_sec_hi = (sizeof(tv_sec) > 4) ? tv_sec >> 32 : 0; @@ -92,7 +96,7 @@ static void manager_handle_capture_output(struct wl_client *client, } frame->manager = manager; frame->output = output; - wl_list_init(&frame->output_swap_buffers.link); + wl_list_init(&frame->output_precommit.link); uint32_t version = wl_resource_get_version(manager_resource); frame->resource = wl_resource_create(client, @@ -142,9 +146,9 @@ static void manager_handle_capture_output(struct wl_client *client, attribs->fd[i], size, attribs->offset[i], attribs->stride[i], i); } - wl_list_remove(&frame->output_swap_buffers.link); - wl_signal_add(&output->events.swap_buffers, &frame->output_swap_buffers); - frame->output_swap_buffers.notify = frame_output_handle_swap_buffers; + wl_list_remove(&frame->output_precommit.link); + wl_signal_add(&output->events.precommit, &frame->output_precommit); + frame->output_precommit.notify = frame_output_handle_precommit; } static void manager_handle_destroy(struct wl_client *client, diff --git a/types/wlr_output.c b/types/wlr_output.c index 26ccb779..8297fe2c 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -274,7 +274,7 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, wl_list_init(&output->resources); wl_signal_init(&output->events.frame); wl_signal_init(&output->events.needs_commit); - wl_signal_init(&output->events.swap_buffers); + wl_signal_init(&output->events.precommit); wl_signal_init(&output->events.present); wl_signal_init(&output->events.enable); wl_signal_init(&output->events.mode); @@ -415,17 +415,11 @@ bool wlr_output_commit(struct wlr_output *output) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - pixman_region32_t *damage = NULL; - if (output->pending.committed & WLR_OUTPUT_STATE_DAMAGE) { - damage = &output->pending.damage; - } - - struct wlr_output_event_swap_buffers event = { + struct wlr_output_event_precommit event = { .output = output, .when = &now, - .damage = damage, }; - wlr_signal_emit_safe(&output->events.swap_buffers, &event); + wlr_signal_emit_safe(&output->events.precommit, &event); if (!output->impl->commit(output)) { return false; diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c index a7f8db59..320c0a39 100644 --- a/types/wlr_screencopy_v1.c +++ b/types/wlr_screencopy_v1.c @@ -27,24 +27,28 @@ static void frame_destroy(struct wlr_screencopy_frame_v1 *frame) { wlr_output_lock_software_cursors(frame->output, false); } wl_list_remove(&frame->link); - wl_list_remove(&frame->output_swap_buffers.link); + wl_list_remove(&frame->output_precommit.link); wl_list_remove(&frame->buffer_destroy.link); // Make the frame resource inert wl_resource_set_user_data(frame->resource, NULL); free(frame); } -static void frame_handle_output_swap_buffers(struct wl_listener *listener, +static void frame_handle_output_precommit(struct wl_listener *listener, void *_data) { struct wlr_screencopy_frame_v1 *frame = - wl_container_of(listener, frame, output_swap_buffers); - struct wlr_output_event_swap_buffers *event = _data; + wl_container_of(listener, frame, output_precommit); + struct wlr_output_event_precommit *event = _data; struct wlr_output *output = frame->output; struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend); assert(renderer); - wl_list_remove(&frame->output_swap_buffers.link); - wl_list_init(&frame->output_swap_buffers.link); + if (!(output->pending.committed & WLR_OUTPUT_STATE_BUFFER)) { + return; + } + + wl_list_remove(&frame->output_precommit.link); + wl_list_init(&frame->output_precommit.link); int x = frame->box.x; int y = frame->box.y; @@ -119,7 +123,7 @@ static void frame_handle_copy(struct wl_client *client, return; } - if (!wl_list_empty(&frame->output_swap_buffers.link) || + if (!wl_list_empty(&frame->output_precommit.link) || frame->buffer != NULL) { wl_resource_post_error(frame->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_ALREADY_USED, @@ -129,8 +133,8 @@ static void frame_handle_copy(struct wl_client *client, frame->buffer = buffer; - wl_signal_add(&output->events.swap_buffers, &frame->output_swap_buffers); - frame->output_swap_buffers.notify = frame_handle_output_swap_buffers; + wl_signal_add(&output->events.precommit, &frame->output_precommit); + frame->output_precommit.notify = frame_handle_output_precommit; wl_resource_add_destroy_listener(buffer_resource, &frame->buffer_destroy); frame->buffer_destroy.notify = frame_handle_buffer_destroy; @@ -213,7 +217,7 @@ static void capture_output(struct wl_client *client, wl_list_insert(&manager->frames, &frame->link); - wl_list_init(&frame->output_swap_buffers.link); + wl_list_init(&frame->output_precommit.link); wl_list_init(&frame->buffer_destroy.link); struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend); diff --git a/types/wlr_screenshooter.c b/types/wlr_screenshooter.c index 9ced6b19..b0145752 100644 --- a/types/wlr_screenshooter.c +++ b/types/wlr_screenshooter.c @@ -45,6 +45,10 @@ static void output_handle_frame(struct wl_listener *listener, void *_data) { struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend); struct wl_shm_buffer *shm_buffer = state->shm_buffer; + if (!(output->pending.committed & WLR_OUTPUT_STATE_BUFFER)) { + return; + } + enum wl_shm_format format = wl_shm_buffer_get_format(shm_buffer); int32_t width = wl_shm_buffer_get_width(shm_buffer); int32_t height = wl_shm_buffer_get_height(shm_buffer); @@ -143,7 +147,7 @@ static void screenshooter_shoot(struct wl_client *client, state->shm_buffer = shm_buffer; state->screenshot = screenshot; state->frame_listener.notify = output_handle_frame; - wl_signal_add(&output->events.swap_buffers, &state->frame_listener); + wl_signal_add(&output->events.precommit, &state->frame_listener); // Schedule a buffer commit output->needs_commit = true;