backend/wayland: add support for presentation-time

This commit is contained in:
Simon Ser 2019-11-16 21:05:46 +01:00 committed by Drew DeVault
parent 2122e49bea
commit e959b882d5
4 changed files with 99 additions and 5 deletions

View file

@ -19,6 +19,7 @@
#include "util/signal.h" #include "util/signal.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h" #include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "pointer-gestures-unstable-v1-client-protocol.h" #include "pointer-gestures-unstable-v1-client-protocol.h"
#include "presentation-time-client-protocol.h"
#include "xdg-decoration-unstable-v1-client-protocol.h" #include "xdg-decoration-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h" #include "xdg-shell-client-protocol.h"
#include "tablet-unstable-v2-client-protocol.h" #include "tablet-unstable-v2-client-protocol.h"
@ -108,6 +109,9 @@ static void registry_global(void *data, struct wl_registry *registry,
} else if (strcmp(iface, zwp_pointer_gestures_v1_interface.name) == 0) { } else if (strcmp(iface, zwp_pointer_gestures_v1_interface.name) == 0) {
wl->zwp_pointer_gestures_v1 = wl_registry_bind(registry, name, wl->zwp_pointer_gestures_v1 = wl_registry_bind(registry, name,
&zwp_pointer_gestures_v1_interface, 1); &zwp_pointer_gestures_v1_interface, 1);
} else if (strcmp(iface, wp_presentation_interface.name) == 0) {
wl->presentation = wl_registry_bind(registry, name,
&wp_presentation_interface, 1);
} else if (strcmp(iface, zwp_tablet_manager_v2_interface.name) == 0) { } else if (strcmp(iface, zwp_tablet_manager_v2_interface.name) == 0) {
wl->tablet_manager = wl_registry_bind(registry, name, wl->tablet_manager = wl_registry_bind(registry, name,
&zwp_tablet_manager_v2_interface, 1); &zwp_tablet_manager_v2_interface, 1);
@ -202,6 +206,9 @@ static void backend_destroy(struct wlr_backend *backend) {
if (wl->zwp_pointer_gestures_v1) { if (wl->zwp_pointer_gestures_v1) {
zwp_pointer_gestures_v1_destroy(wl->zwp_pointer_gestures_v1); zwp_pointer_gestures_v1_destroy(wl->zwp_pointer_gestures_v1);
} }
if (wl->presentation) {
wp_presentation_destroy(wl->presentation);
}
if (wl->zwp_linux_dmabuf_v1) { if (wl->zwp_linux_dmabuf_v1) {
zwp_linux_dmabuf_v1_destroy(wl->zwp_linux_dmabuf_v1); zwp_linux_dmabuf_v1_destroy(wl->zwp_linux_dmabuf_v1);
} }

View file

@ -17,6 +17,7 @@
#include "backend/wayland.h" #include "backend/wayland.h"
#include "util/signal.h" #include "util/signal.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h" #include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "presentation-time-client-protocol.h"
#include "xdg-decoration-unstable-v1-client-protocol.h" #include "xdg-decoration-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h" #include "xdg-shell-client-protocol.h"
@ -26,8 +27,6 @@ static struct wlr_wl_output *get_wl_output_from_output(
return (struct wlr_wl_output *)wlr_output; return (struct wlr_wl_output *)wlr_output;
} }
static struct wl_callback_listener frame_listener;
static void surface_frame_callback(void *data, struct wl_callback *cb, static void surface_frame_callback(void *data, struct wl_callback *cb,
uint32_t time) { uint32_t time) {
struct wlr_wl_output *output = data; struct wlr_wl_output *output = data;
@ -38,10 +37,60 @@ static void surface_frame_callback(void *data, struct wl_callback *cb,
wlr_output_send_frame(&output->wlr_output); wlr_output_send_frame(&output->wlr_output);
} }
static struct wl_callback_listener frame_listener = { static const struct wl_callback_listener frame_listener = {
.done = surface_frame_callback .done = surface_frame_callback
}; };
static void presentation_feedback_destroy(
struct wlr_wl_presentation_feedback *feedback) {
wl_list_remove(&feedback->link);
wp_presentation_feedback_destroy(feedback->feedback);
free(feedback);
}
static void presentation_feedback_handle_sync_output(void *data,
struct wp_presentation_feedback *feedback, struct wl_output *output) {
// This space is intentionally left blank
}
static void presentation_feedback_handle_presented(void *data,
struct wp_presentation_feedback *wp_feedback, uint32_t tv_sec_hi,
uint32_t tv_sec_lo, uint32_t tv_nsec, uint32_t refresh_ns,
uint32_t seq_hi, uint32_t seq_lo, uint32_t flags) {
struct wlr_wl_presentation_feedback *feedback = data;
struct timespec t = {
.tv_sec = ((uint64_t)tv_sec_hi << 32) | tv_sec_lo,
.tv_nsec = tv_nsec,
};
struct wlr_output_event_present event = {
.commit_seq = feedback->commit_seq,
.when = &t,
.seq = ((uint64_t)seq_hi << 32) | seq_lo,
.refresh = refresh_ns,
.flags = flags,
};
wlr_output_send_present(&feedback->output->wlr_output, &event);
presentation_feedback_destroy(feedback);
}
static void presentation_feedback_handle_discarded(void *data,
struct wp_presentation_feedback *wp_feedback) {
struct wlr_wl_presentation_feedback *feedback = data;
wlr_output_send_present(&feedback->output->wlr_output, NULL);
presentation_feedback_destroy(feedback);
}
static const struct wp_presentation_feedback_listener
presentation_feedback_listener = {
.sync_output = presentation_feedback_handle_sync_output,
.presented = presentation_feedback_handle_presented,
.discarded = presentation_feedback_handle_discarded,
};
static bool output_set_custom_mode(struct wlr_output *wlr_output, static bool output_set_custom_mode(struct wlr_output *wlr_output,
int32_t width, int32_t height, int32_t refresh) { int32_t width, int32_t height, int32_t refresh) {
struct wlr_wl_output *output = get_wl_output_from_output(wlr_output); struct wlr_wl_output *output = get_wl_output_from_output(wlr_output);
@ -137,6 +186,12 @@ static bool output_commit(struct wlr_output *wlr_output) {
output->current_wl_buffer = NULL; output->current_wl_buffer = NULL;
} }
struct wp_presentation_feedback *wp_feedback = NULL;
if (output->backend->presentation != NULL) {
wp_feedback = wp_presentation_feedback(output->backend->presentation,
output->surface);
}
assert(wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER); assert(wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER);
switch (wlr_output->pending.buffer_type) { switch (wlr_output->pending.buffer_type) {
case WLR_OUTPUT_STATE_BUFFER_RENDER: case WLR_OUTPUT_STATE_BUFFER_RENDER:
@ -167,8 +222,23 @@ static bool output_commit(struct wlr_output *wlr_output) {
break; break;
} }
// TODO: if available, use the presentation-time protocol if (wp_feedback != NULL) {
wlr_output_send_present(wlr_output, NULL); struct wlr_wl_presentation_feedback *feedback =
calloc(1, sizeof(*feedback));
if (feedback == NULL) {
wp_presentation_feedback_destroy(wp_feedback);
return false;
}
feedback->output = output;
feedback->feedback = wp_feedback;
feedback->commit_seq = output->wlr_output.commit_seq + 1;
wl_list_insert(&output->presentation_feedbacks, &feedback->link);
wp_presentation_feedback_add_listener(wp_feedback,
&presentation_feedback_listener, feedback);
} else {
wlr_output_send_present(wlr_output, NULL);
}
return true; return true;
} }
@ -267,6 +337,12 @@ static void output_destroy(struct wlr_output *wlr_output) {
wl_callback_destroy(output->frame_callback); wl_callback_destroy(output->frame_callback);
} }
struct wlr_wl_presentation_feedback *feedback, *feedback_tmp;
wl_list_for_each_safe(feedback, feedback_tmp,
&output->presentation_feedbacks, link) {
presentation_feedback_destroy(feedback);
}
wlr_egl_destroy_surface(&output->backend->egl, output->egl_surface); wlr_egl_destroy_surface(&output->backend->egl, output->egl_surface);
wl_egl_window_destroy(output->egl_window); wl_egl_window_destroy(output->egl_window);
if (output->zxdg_toplevel_decoration_v1) { if (output->zxdg_toplevel_decoration_v1) {
@ -383,6 +459,7 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) {
++backend->last_output_num); ++backend->last_output_num);
output->backend = backend; output->backend = backend;
wl_list_init(&output->presentation_feedbacks);
output->surface = wl_compositor_create_surface(backend->compositor); output->surface = wl_compositor_create_surface(backend->compositor);
if (!output->surface) { if (!output->surface) {

View file

@ -35,6 +35,7 @@ struct wlr_wl_backend {
struct xdg_wm_base *xdg_wm_base; struct xdg_wm_base *xdg_wm_base;
struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1; struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1;
struct zwp_pointer_gestures_v1 *zwp_pointer_gestures_v1; struct zwp_pointer_gestures_v1 *zwp_pointer_gestures_v1;
struct wp_presentation *presentation;
struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1; struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1;
struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1; struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1;
struct wl_seat *seat; struct wl_seat *seat;
@ -46,6 +47,13 @@ struct wlr_wl_backend {
struct wlr_drm_format_set linux_dmabuf_v1_formats; struct wlr_drm_format_set linux_dmabuf_v1_formats;
}; };
struct wlr_wl_presentation_feedback {
struct wlr_wl_output *output;
struct wl_list link;
struct wp_presentation_feedback *feedback;
uint32_t commit_seq;
};
struct wlr_wl_output { struct wlr_wl_output {
struct wlr_output wlr_output; struct wlr_output wlr_output;
@ -61,6 +69,7 @@ struct wlr_wl_output {
EGLSurface egl_surface; EGLSurface egl_surface;
struct wl_buffer *pending_wl_buffer, *current_wl_buffer; struct wl_buffer *pending_wl_buffer, *current_wl_buffer;
struct wlr_buffer *current_buffer; struct wlr_buffer *current_buffer;
struct wl_list presentation_feedbacks;
uint32_t enter_serial; uint32_t enter_serial;

View file

@ -41,6 +41,7 @@ protocols = [
] ]
client_protocols = [ client_protocols = [
[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'],
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], [wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'], [wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],