compositor: implement presentation_feedback
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. Changes in v4: * add 'flags' argument to 'presented' event without implementation Changes in v5: * remove the 'destroy' method implementation for feedback objects [Pekka Paalanen: do not leak struct feedback.] Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> v3 Reviewed-by: Mario Kleiner <mario.kleiner.de@gmail.com>
This commit is contained in:
parent
b5eedade36
commit
133e439674
148
src/compositor.c
148
src/compositor.c
@ -439,6 +439,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_resource_destroy(feedback->resource);
|
||||
}
|
||||
|
||||
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;
|
||||
uint32_t flags = 0;
|
||||
|
||||
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,
|
||||
flags);
|
||||
wl_resource_destroy(feedback->resource);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_state_handle_buffer_destroy(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@ -464,6 +532,7 @@ weston_surface_state_init(struct weston_surface_state *state)
|
||||
region_init_infinite(&state->input);
|
||||
|
||||
wl_list_init(&state->frame_callback_list);
|
||||
wl_list_init(&state->feedback_list);
|
||||
|
||||
state->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
state->buffer_viewport.buffer.scale = 1;
|
||||
@ -481,6 +550,8 @@ weston_surface_state_fini(struct weston_surface_state *state)
|
||||
&state->frame_callback_list, link)
|
||||
wl_resource_destroy(cb->resource);
|
||||
|
||||
weston_presentation_feedback_discard_list(&state->feedback_list);
|
||||
|
||||
pixman_region32_fini(&state->input);
|
||||
pixman_region32_fini(&state->opaque);
|
||||
pixman_region32_fini(&state->damage);
|
||||
@ -539,6 +610,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);
|
||||
|
||||
wl_list_init(&surface->subsurface_list);
|
||||
wl_list_init(&surface->subsurface_list_pending);
|
||||
@ -1555,6 +1627,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);
|
||||
}
|
||||
|
||||
@ -1656,6 +1730,7 @@ weston_surface_attach(struct weston_surface *surface,
|
||||
surface->compositor->renderer->attach(surface, buffer);
|
||||
|
||||
weston_surface_calculate_size_from_buffer(surface);
|
||||
weston_presentation_feedback_discard_list(&surface->feedback_list);
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
@ -1927,6 +2002,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1981,6 +2060,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;
|
||||
|
||||
@ -2274,6 +2359,16 @@ weston_surface_commit_state(struct weston_surface *surface,
|
||||
wl_list_insert_list(&surface->frame_callback_list,
|
||||
&state->frame_callback_list);
|
||||
wl_list_init(&state->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,
|
||||
&state->feedback_list);
|
||||
wl_list_init(&state->feedback_list);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2501,6 +2596,8 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
|
||||
surface->pending.buffer);
|
||||
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;
|
||||
@ -2522,6 +2619,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->has_cached_data = 1;
|
||||
}
|
||||
|
||||
@ -3254,6 +3355,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);
|
||||
|
||||
@ -3462,6 +3565,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;
|
||||
@ -3737,6 +3841,17 @@ bind_scaler(struct wl_client *client,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -3745,12 +3860,37 @@ 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, NULL, 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 const struct presentation_interface presentation_implementation = {
|
||||
|
@ -205,6 +205,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;
|
||||
@ -835,6 +836,9 @@ struct weston_surface_state {
|
||||
/* 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 */
|
||||
@ -874,6 +878,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;
|
||||
|
Loading…
Reference in New Issue
Block a user