diff --git a/src/compositor-drm.c b/src/compositor-drm.c index ead04a74..86adfee1 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -50,6 +50,7 @@ #include "libinput-seat.h" #include "launcher-util.h" #include "vaapi-recorder.h" +#include "presentation_timing-server-protocol.h" #ifndef DRM_CAP_TIMESTAMP_MONOTONIC #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 @@ -720,7 +721,8 @@ drm_output_start_repaint_loop(struct weston_output *output_base) finish_frame: /* if we cannot page-flip, immediately finish frame */ clock_gettime(compositor->base.presentation_clock, &ts); - weston_output_finish_frame(output_base, &ts); + weston_output_finish_frame(output_base, &ts, + PRESENTATION_FEEDBACK_INVALID); } static void @@ -741,6 +743,8 @@ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, struct drm_sprite *s = (struct drm_sprite *)data; struct drm_output *output = s->output; struct timespec ts; + uint32_t flags = PRESENTATION_FEEDBACK_KIND_HW_COMPLETION | + PRESENTATION_FEEDBACK_KIND_HW_CLOCK; drm_output_update_msc(output, frame); output->vblank_pending = 0; @@ -752,7 +756,7 @@ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, if (!output->page_flip_pending) { ts.tv_sec = sec; ts.tv_nsec = usec * 1000; - weston_output_finish_frame(&output->base, &ts); + weston_output_finish_frame(&output->base, &ts, flags); } } @@ -765,6 +769,9 @@ page_flip_handler(int fd, unsigned int frame, { struct drm_output *output = (struct drm_output *) data; struct timespec ts; + uint32_t flags = PRESENTATION_FEEDBACK_KIND_VSYNC | + PRESENTATION_FEEDBACK_KIND_HW_COMPLETION | + PRESENTATION_FEEDBACK_KIND_HW_CLOCK; drm_output_update_msc(output, frame); @@ -784,7 +791,7 @@ page_flip_handler(int fd, unsigned int frame, else if (!output->vblank_pending) { ts.tv_sec = sec; ts.tv_nsec = usec * 1000; - weston_output_finish_frame(&output->base, &ts); + weston_output_finish_frame(&output->base, &ts, flags); /* We can't call this from frame_notify, because the output's * repaint needed flag is cleared just after that */ diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c index 805a195a..eedf252b 100644 --- a/src/compositor-fbdev.c +++ b/src/compositor-fbdev.c @@ -44,6 +44,7 @@ #include "pixman-renderer.h" #include "libinput-seat.h" #include "gl-renderer.h" +#include "presentation_timing-server-protocol.h" struct fbdev_compositor { struct weston_compositor base; @@ -117,7 +118,7 @@ fbdev_output_start_repaint_loop(struct weston_output *output) struct timespec ts; clock_gettime(output->compositor->presentation_clock, &ts); - weston_output_finish_frame(output, &ts); + weston_output_finish_frame(output, &ts, PRESENTATION_FEEDBACK_INVALID); } static void @@ -220,8 +221,10 @@ static int finish_frame_handler(void *data) { struct fbdev_output *output = data; + struct timespec ts; - fbdev_output_start_repaint_loop(&output->base); + clock_gettime(output->base.compositor->presentation_clock, &ts); + weston_output_finish_frame(&output->base, &ts, 0); return 1; } diff --git a/src/compositor-headless.c b/src/compositor-headless.c index 945c84b7..1e6df9a7 100644 --- a/src/compositor-headless.c +++ b/src/compositor-headless.c @@ -30,6 +30,7 @@ #include "compositor.h" #include "pixman-renderer.h" +#include "presentation_timing-server-protocol.h" struct headless_compositor { struct weston_compositor base; @@ -58,13 +59,17 @@ headless_output_start_repaint_loop(struct weston_output *output) struct timespec ts; clock_gettime(output->compositor->presentation_clock, &ts); - weston_output_finish_frame(output, &ts); + weston_output_finish_frame(output, &ts, PRESENTATION_FEEDBACK_INVALID); } static int finish_frame_handler(void *data) { - headless_output_start_repaint_loop(data); + struct headless_output *output = data; + struct timespec ts; + + clock_gettime(output->base.compositor->presentation_clock, &ts); + weston_output_finish_frame(&output->base, &ts, 0); return 1; } diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c index 2048f8f3..1c3f9889 100644 --- a/src/compositor-rdp.c +++ b/src/compositor-rdp.c @@ -308,7 +308,7 @@ rdp_output_start_repaint_loop(struct weston_output *output) struct timespec ts; clock_gettime(output->compositor->presentation_clock, &ts); - weston_output_finish_frame(output, &ts); + weston_output_finish_frame(output, &ts, PRESENTATION_FEEDBACK_INVALID); } static int @@ -350,7 +350,11 @@ rdp_output_destroy(struct weston_output *output_base) static int finish_frame_handler(void *data) { - rdp_output_start_repaint_loop(data); + struct rdp_output *output = data; + struct timespec ts; + + clock_gettime(output->base.compositor->presentation_clock, &ts); + weston_output_finish_frame(&output->base, &ts, 0); return 1; } diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c index a064a86b..2d726866 100644 --- a/src/compositor-rpi.c +++ b/src/compositor-rpi.c @@ -47,6 +47,7 @@ #include "rpi-renderer.h" #include "launcher-util.h" #include "libinput-seat.h" +#include "presentation_timing-server-protocol.h" #if 0 #define DBG(...) \ @@ -215,8 +216,9 @@ rpi_output_start_repaint_loop(struct weston_output *output) { struct timespec ts; + /* XXX: do a phony dispmanx update and trigger on its completion? */ clock_gettime(output->compositor->presentation_clock, &ts); - weston_output_finish_frame(output, &ts); + weston_output_finish_frame(output, &ts, PRESENTATION_FEEDBACK_INVALID); } static int @@ -250,10 +252,13 @@ static void rpi_output_update_complete(struct rpi_output *output, const struct timespec *stamp) { + uint32_t flags = PRESENTATION_FEEDBACK_KIND_VSYNC | + PRESENTATION_FEEDBACK_KIND_HW_COMPLETION; + DBG("frame update complete(%ld.%09ld)\n", (long)stamp->tv_sec, (long)stamp->tv_nsec); rpi_renderer_finish_frame(&output->base); - weston_output_finish_frame(&output->base, stamp); + weston_output_finish_frame(&output->base, stamp, flags); } static void diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index 65bce39b..04a2331e 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -43,6 +43,7 @@ #include "../shared/os-compatibility.h" #include "../shared/cairo-util.h" #include "fullscreen-shell-client-protocol.h" +#include "presentation_timing-server-protocol.h" #define WINDOW_TITLE "Weston Compositor" @@ -313,7 +314,7 @@ frame_done(void *data, struct wl_callback *callback, uint32_t time) /* XXX: use the presentation extension for proper timings */ ts.tv_sec = time / 1000; ts.tv_nsec = (time % 1000) * 1000000; - weston_output_finish_frame(output, &ts); + weston_output_finish_frame(output, &ts, 0); } static const struct wl_callback_listener frame_listener = { diff --git a/src/compositor-x11.c b/src/compositor-x11.c index 29f21192..58634461 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -51,6 +51,7 @@ #include "pixman-renderer.h" #include "../shared/config-parser.h" #include "../shared/image-loader.h" +#include "presentation_timing-server-protocol.h" #define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10) @@ -341,7 +342,7 @@ x11_output_start_repaint_loop(struct weston_output *output) struct timespec ts; clock_gettime(output->compositor->presentation_clock, &ts); - weston_output_finish_frame(output, &ts); + weston_output_finish_frame(output, &ts, PRESENTATION_FEEDBACK_INVALID); } static int @@ -450,8 +451,10 @@ static int finish_frame_handler(void *data) { struct x11_output *output = data; + struct timespec ts; - x11_output_start_repaint_loop(&output->base); + clock_gettime(output->base.compositor->presentation_clock, &ts); + weston_output_finish_frame(&output->base, &ts, 0); return 1; } diff --git a/src/compositor.c b/src/compositor.c index b84658a8..8085b055 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -495,12 +495,12 @@ weston_presentation_feedback_present( struct weston_output *output, uint32_t refresh_nsec, const struct timespec *ts, - uint64_t seq) + uint64_t seq, + uint32_t flags) { 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) @@ -524,13 +524,18 @@ weston_presentation_feedback_present_list(struct wl_list *list, struct weston_output *output, uint32_t refresh_nsec, const struct timespec *ts, - uint64_t seq) + uint64_t seq, + uint32_t flags) { struct weston_presentation_feedback *feedback, *tmp; + assert(!(flags & PRESENTATION_FEEDBACK_INVALID) || + wl_list_empty(list)); + wl_list_for_each_safe(feedback, tmp, list, link) weston_presentation_feedback_present(feedback, output, - refresh_nsec, ts, seq); + refresh_nsec, ts, seq, + flags); } static void @@ -2083,7 +2088,8 @@ weston_compositor_read_input(int fd, uint32_t mask, void *data) WL_EXPORT void weston_output_finish_frame(struct weston_output *output, - const struct timespec *stamp) + const struct timespec *stamp, + uint32_t presented_flags) { struct weston_compositor *compositor = output->compositor; struct wl_event_loop *loop = @@ -2097,7 +2103,8 @@ weston_output_finish_frame(struct weston_output *output, refresh_nsec = 1000000000000UL / output->current_mode->refresh; weston_presentation_feedback_present_list(&output->feedback_list, output, refresh_nsec, stamp, - output->msc); + output->msc, + presented_flags); output->frame_time = stamp->tv_sec * 1000 + stamp->tv_nsec / 1000000; diff --git a/src/compositor.h b/src/compositor.h index 3f7ed4a1..3a266356 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -1066,9 +1066,13 @@ weston_compositor_stack_plane(struct weston_compositor *ec, struct weston_plane *plane, struct weston_plane *above); +/* An invalid flag in presented_flags to catch logic errors. */ +#define PRESENTATION_FEEDBACK_INVALID (1U << 31) + void weston_output_finish_frame(struct weston_output *output, - const struct timespec *stamp); + const struct timespec *stamp, + uint32_t presented_flags); void weston_output_schedule_repaint(struct weston_output *output); void