[RFCv3 weston 10/15] compositor: implement presentation_feedback

Pekka Paalanen ppaalanen at gmail.com
Fri Mar 7 04:03:58 PST 2014


From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>

Implement the presentation.feedback request, and the
presentation_feedback protocol interface. Feedback information is
delivered to clients as the backend reports it, except the refresh
counter (MSC) which is always reported as zero.

Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
 src/compositor.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/compositor.h |   8 +++
 2 files changed, 174 insertions(+), 4 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index f1029ef..c11e82b 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -418,6 +418,7 @@ weston_surface_create(struct weston_compositor *compositor)
 	wl_list_init(&surface->views);
 
 	wl_list_init(&surface->frame_callback_list);
+	wl_list_init(&surface->feedback_list);
 
 	surface->pending.buffer_destroy_listener.notify =
 		surface_handle_pending_buffer_destroy;
@@ -425,6 +426,7 @@ weston_surface_create(struct weston_compositor *compositor)
 	pixman_region32_init(&surface->pending.opaque);
 	region_init_infinite(&surface->pending.input);
 	wl_list_init(&surface->pending.frame_callback_list);
+	wl_list_init(&surface->pending.feedback_list);
 
 	wl_list_init(&surface->subsurface_list);
 	wl_list_init(&surface->subsurface_list_pending);
@@ -1334,6 +1336,74 @@ struct weston_frame_callback {
 	struct wl_list link;
 };
 
+struct weston_presentation_feedback {
+	struct wl_resource *resource;
+
+	/* XXX: could use just wl_resource_get_link() instead */
+	struct wl_list link;
+};
+
+static void
+weston_presentation_feedback_discard(
+		struct weston_presentation_feedback *feedback)
+{
+	presentation_feedback_send_discarded(feedback->resource);
+	wl_list_remove(&feedback->link);
+	wl_list_init(&feedback->link);
+}
+
+static void
+weston_presentation_feedback_discard_list(struct wl_list *list)
+{
+	struct weston_presentation_feedback *feedback, *tmp;
+
+	wl_list_for_each_safe(feedback, tmp, list, link)
+		weston_presentation_feedback_discard(feedback);
+}
+
+static void
+weston_presentation_feedback_present(
+		struct weston_presentation_feedback *feedback,
+		struct weston_output *output,
+		uint32_t refresh_nsec,
+		const struct timespec *ts,
+		uint64_t seq)
+{
+	struct wl_client *client = wl_resource_get_client(feedback->resource);
+	struct wl_resource *o;
+	uint64_t secs;
+
+	wl_resource_for_each(o, &output->resource_list) {
+		if (wl_resource_get_client(o) != client)
+			continue;
+
+		presentation_feedback_send_sync_output(feedback->resource, o);
+	}
+
+	secs = ts->tv_sec;
+	presentation_feedback_send_presented(feedback->resource,
+					     secs >> 32, secs & 0xffffffff,
+					     ts->tv_nsec,
+					     refresh_nsec,
+					     seq >> 32, seq & 0xffffffff);
+	wl_list_remove(&feedback->link);
+	wl_list_init(&feedback->link);
+}
+
+static void
+weston_presentation_feedback_present_list(struct wl_list *list,
+					  struct weston_output *output,
+					  uint32_t refresh_nsec,
+					  const struct timespec *ts,
+					  uint64_t seq)
+{
+	struct weston_presentation_feedback *feedback, *tmp;
+
+	wl_list_for_each_safe(feedback, tmp, list, link)
+		weston_presentation_feedback_present(feedback, output,
+						     refresh_nsec, ts, seq);
+}
+
 WL_EXPORT void
 weston_view_destroy(struct weston_view *view)
 {
@@ -1380,6 +1450,9 @@ weston_surface_destroy(struct weston_surface *surface)
 			      &surface->pending.frame_callback_list, link)
 		wl_resource_destroy(cb->resource);
 
+	weston_presentation_feedback_discard_list(
+		&surface->pending.feedback_list);
+
 	pixman_region32_fini(&surface->pending.input);
 	pixman_region32_fini(&surface->pending.opaque);
 	pixman_region32_fini(&surface->pending.damage);
@@ -1396,6 +1469,8 @@ weston_surface_destroy(struct weston_surface *surface)
 	wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link)
 		wl_resource_destroy(cb->resource);
 
+	weston_presentation_feedback_discard_list(&surface->feedback_list);
+
 	free(surface);
 }
 
@@ -1497,6 +1572,7 @@ weston_surface_attach(struct weston_surface *surface,
 	surface->compositor->renderer->attach(surface, buffer);
 
 	weston_surface_set_size_from_buffer(surface);
+	weston_presentation_feedback_discard_list(&surface->feedback_list);
 }
 
 WL_EXPORT void
@@ -1762,6 +1838,10 @@ weston_output_repaint(struct weston_output *output)
 			wl_list_insert_list(&frame_callback_list,
 					    &ev->surface->frame_callback_list);
 			wl_list_init(&ev->surface->frame_callback_list);
+
+			wl_list_insert_list(&output->feedback_list,
+					    &ev->surface->feedback_list);
+			wl_list_init(&ev->surface->feedback_list);
 		}
 	}
 
@@ -1816,6 +1896,12 @@ weston_output_finish_frame(struct weston_output *output,
 	struct wl_event_loop *loop =
 		wl_display_get_event_loop(compositor->wl_display);
 	int fd, r;
+	uint32_t refresh_nsec;
+
+	refresh_nsec = 1000000000000UL / output->current_mode->refresh;
+	weston_presentation_feedback_present_list(&output->feedback_list,
+						  output, refresh_nsec, stamp,
+						  0);
 
 	output->frame_time = stamp->tv_sec * 1000 + stamp->tv_nsec / 1000000;
 
@@ -2078,6 +2164,16 @@ weston_surface_commit(struct weston_surface *surface)
 			    &surface->pending.frame_callback_list);
 	wl_list_init(&surface->pending.frame_callback_list);
 
+	/* XXX:
+	 * What should happen with a feedback request, if there
+	 * is no wl_buffer attached for this commit?
+	 */
+
+	/* presentation.feedback */
+	wl_list_insert_list(&surface->feedback_list,
+			    &surface->pending.feedback_list);
+	wl_list_init(&surface->pending.feedback_list);
+
 	weston_surface_commit_subsurface_order(surface);
 
 	weston_surface_schedule_repaint(surface);
@@ -2298,6 +2394,11 @@ weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
 			    &sub->cached.frame_callback_list);
 	wl_list_init(&sub->cached.frame_callback_list);
 
+	/* presentation.feedback */
+	wl_list_insert_list(&surface->feedback_list,
+			    &sub->cached.feedback_list);
+	wl_list_init(&sub->cached.feedback_list);
+
 	weston_surface_commit_subsurface_order(surface);
 
 	weston_surface_schedule_repaint(surface);
@@ -2326,6 +2427,8 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
 		sub->cached.newly_attached = 1;
 		weston_buffer_reference(&sub->cached.buffer_ref,
 					surface->pending.buffer);
+		weston_presentation_feedback_discard_list(
+					&sub->cached.feedback_list);
 	}
 	sub->cached.sx += surface->pending.sx;
 	sub->cached.sy += surface->pending.sy;
@@ -2342,6 +2445,10 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
 			    &surface->pending.frame_callback_list);
 	wl_list_init(&surface->pending.frame_callback_list);
 
+	wl_list_insert_list(&sub->cached.feedback_list,
+			    &surface->pending.feedback_list);
+	wl_list_init(&surface->pending.feedback_list);
+
 	sub->cached.has_data = 1;
 }
 
@@ -2610,6 +2717,7 @@ weston_subsurface_cache_init(struct weston_subsurface *sub)
 	pixman_region32_init(&sub->cached.opaque);
 	pixman_region32_init(&sub->cached.input);
 	wl_list_init(&sub->cached.frame_callback_list);
+	wl_list_init(&sub->cached.feedback_list);
 	sub->cached.buffer_ref.buffer = NULL;
 }
 
@@ -2621,6 +2729,8 @@ weston_subsurface_cache_fini(struct weston_subsurface *sub)
 	wl_list_for_each_safe(cb, tmp, &sub->cached.frame_callback_list, link)
 		wl_resource_destroy(cb->resource);
 
+	weston_presentation_feedback_discard_list(&sub->cached.feedback_list);
+
 	weston_buffer_reference(&sub->cached.buffer_ref, NULL);
 	pixman_region32_fini(&sub->cached.damage);
 	pixman_region32_fini(&sub->cached.opaque);
@@ -3087,6 +3197,8 @@ weston_output_destroy(struct weston_output *output)
 {
 	output->destroying = 1;
 
+	weston_presentation_feedback_discard_list(&output->feedback_list);
+
 	weston_compositor_remove_output(output->compositor, output);
 	wl_list_remove(&output->link);
 
@@ -3292,6 +3404,7 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
 	wl_signal_init(&output->destroy_signal);
 	wl_list_init(&output->animation_list);
 	wl_list_init(&output->resource_list);
+	wl_list_init(&output->feedback_list);
 
 	output->id = ffs(~output->compositor->output_id_pool) - 1;
 	output->compositor->output_id_pool |= 1 << output->id;
@@ -3477,6 +3590,29 @@ bind_scaler(struct wl_client *client,
 }
 
 static void
+presentation_feedback_destroy(struct wl_client *client,
+			      struct wl_resource *feedback_resource)
+{
+	wl_resource_destroy(feedback_resource);
+}
+
+static const struct presentation_feedback_interface
+presentation_feedback_implementation = {
+	presentation_feedback_destroy
+};
+
+static void
+destroy_presentation_feedback(struct wl_resource *feedback_resource)
+{
+	struct weston_presentation_feedback *feedback;
+
+	feedback = wl_resource_get_user_data(feedback_resource);
+
+	wl_list_remove(&feedback->link);
+	free(feedback);
+}
+
+static void
 presentation_destroy(struct wl_client *client, struct wl_resource *resource)
 {
 	wl_resource_destroy(resource);
@@ -3484,12 +3620,38 @@ presentation_destroy(struct wl_client *client, struct wl_resource *resource)
 
 static void
 presentation_feedback(struct wl_client *client,
-		      struct wl_resource *resource,
-		      struct wl_resource *surface,
+		      struct wl_resource *presentation_resource,
+		      struct wl_resource *surface_resource,
 		      uint32_t callback)
 {
-	wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_METHOD,
-			       "presentation_feedback unimplemented");
+	struct weston_surface *surface;
+	struct weston_presentation_feedback *feedback;
+
+	surface = wl_resource_get_user_data(surface_resource);
+
+	feedback = calloc(1, sizeof *feedback);
+	if (!feedback)
+		goto err_calloc;
+
+	feedback->resource = wl_resource_create(client,
+					&presentation_feedback_interface,
+					1, callback);
+	if (!feedback->resource)
+		goto err_create;
+
+	wl_resource_set_implementation(feedback->resource,
+				       &presentation_feedback_implementation,
+				       feedback, destroy_presentation_feedback);
+
+	wl_list_insert(&surface->pending.feedback_list, &feedback->link);
+
+	return;
+
+err_create:
+	free(feedback);
+
+err_calloc:
+	wl_client_post_no_memory(client);
 }
 
 static void
diff --git a/src/compositor.h b/src/compositor.h
index 250f3e2..0dcc414 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -200,6 +200,7 @@ struct weston_output {
 	uint32_t frame_time; /* presentation timestamp in milliseconds */
 	int disable_planes;
 	int destroying;
+	struct wl_list feedback_list;
 
 	char *make, *model, *serial_number;
 	uint32_t subpixel;
@@ -726,6 +727,9 @@ struct weston_subsurface {
 		/* wl_surface.frame */
 		struct wl_list frame_callback_list;
 
+		/* presentation.feedback */
+		struct wl_list feedback_list;
+
 		/* wl_surface.set_buffer_transform */
 		/* wl_surface.set_buffer_scale */
 		struct weston_buffer_viewport buffer_viewport;
@@ -864,6 +868,7 @@ struct weston_surface {
 	uint32_t output_mask;
 
 	struct wl_list frame_callback_list;
+	struct wl_list feedback_list;
 
 	struct weston_buffer_reference buffer_ref;
 	struct weston_buffer_viewport buffer_viewport;
@@ -893,6 +898,9 @@ struct weston_surface {
 		/* wl_surface.frame */
 		struct wl_list frame_callback_list;
 
+		/* presentation.feedback */
+		struct wl_list feedback_list;
+
 		/* wl_surface.set_buffer_transform */
 		/* wl_surface.set_scaling_factor */
 		/* wl_viewport.set */
-- 
1.8.3.2



More information about the wayland-devel mailing list