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)
{
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;
&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);
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);
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);
}
surface->compositor->renderer->attach(surface, buffer);
weston_surface_calculate_size_from_buffer(surface);
+ weston_presentation_feedback_discard_list(&surface->feedback_list);
}
WL_EXPORT void
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);
}
}
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;
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
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;
&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;
}
output->destroying = 1;
+ weston_presentation_feedback_discard_list(&output->feedback_list);
+
weston_compositor_remove_output(output->compositor, output);
wl_list_remove(&output->link);
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;
}
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);
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 = {