diff --git a/examples/pointer.c b/examples/pointer.c index f3ef5435e..5b0fb5b07 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -111,7 +111,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { state->clear_color[3], }, }); - wlr_output_add_software_cursors_to_render_pass(wlr_output, pass, NULL); + wlr_output_add_software_cursors_to_render_pass(wlr_output, pass, NULL, NULL, 0); wlr_render_pass_submit(pass); wlr_output_commit_state(wlr_output, &output_state); wlr_output_state_finish(&output_state); diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index c8e44b0e6..3611c2e98 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -36,6 +36,11 @@ struct wlr_output_mode { struct wl_list link; }; +struct wlr_output_cursor_texture_sample_event { + struct wlr_drm_syncobj_timeline *release_timeline; + uint64_t release_point; +}; + struct wlr_output_cursor { struct wlr_output *output; double x, y; @@ -51,6 +56,10 @@ struct wlr_output_cursor { uint64_t wait_point; struct wl_list link; + struct { + struct wl_signal texture_sample; // struct wlr_output_cursor_texture_sample_event + } events; + struct { struct wl_listener renderer_destroy; struct wlr_color_transform *color_transform; @@ -442,7 +451,8 @@ void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock); * This is a utility function that can be called when compositors render. */ void wlr_output_add_software_cursors_to_render_pass(struct wlr_output *output, - struct wlr_render_pass *render_pass, const pixman_region32_t *damage); + struct wlr_render_pass *render_pass, const pixman_region32_t *damage, + struct wlr_drm_syncobj_timeline *release_timeline, uint64_t release_point); /** * Get the set of DRM formats suitable for the primary buffer, assuming a * buffer with the specified capabilities. diff --git a/types/output/cursor.c b/types/output/cursor.c index 4a823dab1..895554ef9 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -89,7 +89,8 @@ static void output_cursor_get_box(struct wlr_output_cursor *cursor, } void wlr_output_add_software_cursors_to_render_pass(struct wlr_output *output, - struct wlr_render_pass *render_pass, const pixman_region32_t *damage) { + struct wlr_render_pass *render_pass, const pixman_region32_t *damage, + struct wlr_drm_syncobj_timeline *release_timeline, uint64_t release_point) { int width, height; wlr_output_transformed_resolution(output, &width, &height); @@ -128,7 +129,14 @@ void wlr_output_add_software_cursors_to_render_pass(struct wlr_output *output, .dst_box = box, .clip = &cursor_damage, .transform = output->transform, + .wait_timeline = cursor->wait_timeline, + .wait_point = cursor->wait_point, }); + struct wlr_output_cursor_texture_sample_event event = { + .release_timeline = release_timeline, + .release_point = release_point, + }; + wl_signal_emit_mutable(&cursor->events.texture_sample, &event); pixman_region32_fini(&cursor_damage); } @@ -285,6 +293,9 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor) return NULL; } + struct wlr_output_cursor_texture_sample_event event = {0}; + wl_signal_emit_mutable(&cursor->events.texture_sample, &event); + return buffer; } @@ -472,6 +483,7 @@ struct wlr_output_cursor *wlr_output_cursor_create(struct wlr_output *output) { cursor->output = output; wl_list_insert(&output->cursors, &cursor->link); cursor->visible = true; // default position is at (0, 0) + wl_signal_init(&cursor->events.texture_sample); wl_list_init(&cursor->renderer_destroy.link); output_cursor_refresh_color_transform(cursor, output->image_description); return cursor; @@ -493,6 +505,7 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) { } wlr_drm_syncobj_timeline_unref(cursor->wait_timeline); wl_list_remove(&cursor->link); + assert(wl_list_empty(&cursor->events.texture_sample.listener_list)); wlr_color_transform_unref(cursor->color_transform); free(cursor); } diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 7231422e8..d6a2a3573 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -2581,7 +2581,8 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, } } - wlr_output_add_software_cursors_to_render_pass(output, render_pass, &render_data.damage); + wlr_output_add_software_cursors_to_render_pass(output, render_pass, + &render_data.damage, scene_output->in_timeline, scene_output->in_point); pixman_region32_fini(&render_data.damage); if (!wlr_render_pass_submit(render_pass)) { diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 8d0d77475..1b9146c40 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -63,6 +63,7 @@ struct wlr_cursor_output_cursor { // only when using a surface as the cursor image struct wl_listener output_commit; + struct wl_listener texture_sample; // only when using an XCursor as the cursor image struct wlr_xcursor *xcursor; @@ -160,6 +161,7 @@ static void output_cursor_destroy(struct wlr_cursor_output_cursor *output_cursor wl_list_remove(&output_cursor->layout_output_destroy.link); wl_list_remove(&output_cursor->link); wl_list_remove(&output_cursor->output_commit.link); + wl_list_remove(&output_cursor->texture_sample.link); wlr_output_cursor_destroy(output_cursor->output_cursor); free(output_cursor); } @@ -579,13 +581,6 @@ static void cursor_output_cursor_update(struct wlr_cursor_output_cursor *output_ &src_box, dst_width, dst_height, surface->current.transform, hotspot_x, hotspot_y, wait_timeline, wait_point); - if (syncobj_surface_state != NULL && - surface->buffer != NULL && surface->buffer->source != NULL && - (surface->current.committed & WLR_SURFACE_STATE_BUFFER)) { - wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer(syncobj_surface_state, - surface->buffer->source); - } - if (output_cursor->output_cursor->visible) { wlr_surface_send_enter(surface, output); } else { @@ -645,6 +640,29 @@ static void output_cursor_output_handle_output_commit( } } +static void output_cursor_output_handle_texture_sample( + struct wl_listener *listener, void *data) { + struct wlr_cursor_output_cursor *output_cursor = + wl_container_of(listener, output_cursor, texture_sample); + const struct wlr_output_cursor_texture_sample_event *event = data; + + struct wlr_surface *surface = output_cursor->cursor->state->surface; + struct wlr_linux_drm_syncobj_surface_v1_state *syncobj_state = NULL; + if (surface != NULL) { + syncobj_state = wlr_linux_drm_syncobj_v1_get_surface_state(surface); + } + if (syncobj_state != NULL) { + struct wl_event_loop *event_loop = output_cursor->output_cursor->output->event_loop; + if (event->release_timeline != NULL) { + wlr_linux_drm_syncobj_v1_state_add_release_point(syncobj_state, + event->release_timeline, event->release_point, event_loop); + } else if (surface->buffer != NULL && surface->buffer->source != NULL) { + wlr_linux_drm_syncobj_v1_state_add_release_from_implicit_sync(syncobj_state, + surface->buffer->source, event_loop); + } + } +} + static void cursor_update_outputs(struct wlr_cursor *cur) { struct wlr_cursor_output_cursor *output_cursor; wl_list_for_each(output_cursor, &cur->state->output_cursors, link) { @@ -1167,6 +1185,9 @@ static void layout_add(struct wlr_cursor_state *state, wl_signal_add(&output_cursor->output_cursor->output->events.commit, &output_cursor->output_commit); output_cursor->output_commit.notify = output_cursor_output_handle_output_commit; + wl_signal_add(&output_cursor->output_cursor->events.texture_sample, + &output_cursor->texture_sample); + output_cursor->texture_sample.notify = output_cursor_output_handle_texture_sample; output_cursor_move(output_cursor); cursor_output_cursor_update(output_cursor);