From 67447d6cb407ac5b6405b4dbae01a38567feb111 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 14 Apr 2023 20:41:27 +0200 Subject: [PATCH] presentation-time: add separate helper for zero-copy The backend is not able to tell whether a surface is being presented via direct scan-out or not. The backend will set ZERO_COPY if the buffer submitted via the output commit was presented in a zero-copy fashion, but will no know whether the buffer comes from the compositor or the client. --- include/wlr/types/wlr_presentation_time.h | 20 +++++++++++++++----- types/scene/surface.c | 20 +++++++++++++------- types/wlr_presentation_time.c | 22 ++++++++++++++++++++-- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/include/wlr/types/wlr_presentation_time.h b/include/wlr/types/wlr_presentation_time.h index 817730b3..a8df292d 100644 --- a/include/wlr/types/wlr_presentation_time.h +++ b/include/wlr/types/wlr_presentation_time.h @@ -33,11 +33,12 @@ struct wlr_presentation { struct wlr_presentation_feedback { struct wl_list resources; // wl_resource_get_link() - // Only when the wlr_presentation_surface_sampled_on_output() helper has - // been called. + // Only when the wlr_presentation_surface_textured_on_output() or + // wlr_presentation_surface_scanned_out_on_output() helper has been called. struct wlr_output *output; bool output_committed; uint32_t output_commit_seq; + bool zero_copy; struct wl_listener output_commit; struct wl_listener output_present; @@ -85,14 +86,23 @@ void wlr_presentation_event_from_output(struct wlr_presentation_event *event, const struct wlr_output_event_present *output_event); /** - * Mark the current surface's buffer as sampled on the given output. + * Mark the current surface's buffer as textured on the given output. * * Instead of calling wlr_presentation_surface_sampled() and managing the * struct wlr_presentation_feedback itself, the compositor can call this function * before a wlr_output_commit() call to indicate that the surface's current - * contents will be displayed on the output. + * contents have been copied to a buffer which will be displayed on the output. */ -void wlr_presentation_surface_sampled_on_output( +void wlr_presentation_surface_textured_on_output( + struct wlr_presentation *presentation, struct wlr_surface *surface, + struct wlr_output *output); +/** + * Mark the current surface's buffer as scanned out on the given output. + * + * Same as wlr_presentation_surface_textured_on_output(), but indicates direct + * scan-out. + */ +void wlr_presentation_surface_scanned_out_on_output( struct wlr_presentation *presentation, struct wlr_surface *surface, struct wlr_output *output); diff --git a/types/scene/surface.c b/types/scene/surface.c index afefb917..1b585e8c 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -42,15 +42,21 @@ static void handle_scene_buffer_output_sample( wl_container_of(listener, surface, output_sample); const struct wlr_scene_output_sample_event *event = data; struct wlr_scene_output *scene_output = event->output; + if (surface->buffer->primary_output != scene_output) { + return; + } - if (surface->buffer->primary_output == scene_output) { - struct wlr_scene *root = scene_node_get_root(&surface->buffer->node); - struct wlr_presentation *presentation = root->presentation; + struct wlr_scene *root = scene_node_get_root(&surface->buffer->node); + if (!root->presentation) { + return; + } - if (presentation) { - wlr_presentation_surface_sampled_on_output( - presentation, surface->surface, scene_output->output); - } + if (event->direct_scanout) { + wlr_presentation_surface_scanned_out_on_output( + root->presentation, surface->surface, scene_output->output); + } else { + wlr_presentation_surface_textured_on_output( + root->presentation, surface->surface, scene_output->output); } } diff --git a/types/wlr_presentation_time.c b/types/wlr_presentation_time.c index 2a6610f4..f13f3179 100644 --- a/types/wlr_presentation_time.c +++ b/types/wlr_presentation_time.c @@ -295,6 +295,9 @@ static void feedback_handle_output_present(struct wl_listener *listener, if (output_event->presented) { struct wlr_presentation_event event = {0}; wlr_presentation_event_from_output(&event, output_event); + if (!feedback->zero_copy) { + event.flags &= ~WP_PRESENTATION_FEEDBACK_KIND_ZERO_COPY; + } wlr_presentation_feedback_send_presented(feedback, &event); } wlr_presentation_feedback_destroy(feedback); @@ -307,9 +310,9 @@ static void feedback_handle_output_destroy(struct wl_listener *listener, wlr_presentation_feedback_destroy(feedback); } -void wlr_presentation_surface_sampled_on_output( +static void presentation_surface_queued_on_output( struct wlr_presentation *presentation, struct wlr_surface *surface, - struct wlr_output *output) { + struct wlr_output *output, bool zero_copy) { struct wlr_presentation_feedback *feedback = wlr_presentation_surface_sampled(presentation, surface); if (feedback == NULL) { @@ -318,6 +321,7 @@ void wlr_presentation_surface_sampled_on_output( assert(feedback->output == NULL); feedback->output = output; + feedback->zero_copy = zero_copy; feedback->output_commit.notify = feedback_handle_output_commit; wl_signal_add(&output->events.commit, &feedback->output_commit); @@ -326,3 +330,17 @@ void wlr_presentation_surface_sampled_on_output( feedback->output_destroy.notify = feedback_handle_output_destroy; wl_signal_add(&output->events.destroy, &feedback->output_destroy); } + +void wlr_presentation_surface_textured_on_output( + struct wlr_presentation *presentation, struct wlr_surface *surface, + struct wlr_output *output) { + return presentation_surface_queued_on_output(presentation, surface, + output, false); +} + +void wlr_presentation_surface_scanned_out_on_output( + struct wlr_presentation *presentation, struct wlr_surface *surface, + struct wlr_output *output) { + return presentation_surface_queued_on_output(presentation, surface, + output, true); +}