From c1809b230c5225a4d65513bf1a69c825e609369a Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Sun, 21 Jun 2015 21:25:16 +0200 Subject: [PATCH] presentation-shm: Allow setting of delay before surface.commit A new optional parameter "-d msecs" allows to specify a delay before the surface attach/damage/commit to shift the point in time when a surface update is committed. This allows to test how different client timings interact with the compositors repaint timing. Suggested by Pekka Paalanen. Signed-off-by: Mario Kleiner Acked-by: Pekka Paalanen v2: Clarify the intent, doing a delay in window_create_feedback() is a bit surprising. Use nanosleep() instead of clock_nanosleep(), which may not support the chosen presentation clock. Signed-off-by: Pekka Paalanen --- clients/presentation-shm.c | 48 ++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/clients/presentation-shm.c b/clients/presentation-shm.c index cf4517c7..120c40ce 100644 --- a/clients/presentation-shm.c +++ b/clients/presentation-shm.c @@ -101,6 +101,7 @@ struct window { int num_buffers; int next; int refresh_nsec; + int commit_delay_msecs; struct wl_callback *callback; struct wl_list feedback_list; @@ -201,19 +202,21 @@ static const struct wl_shell_surface_listener shell_surface_listener = { static struct window * create_window(struct display *display, int width, int height, - enum run_mode mode) + enum run_mode mode, int commit_delay_msecs) { struct window *window; char title[128]; int ret; snprintf(title, sizeof(title), - "presentation-shm: %s", run_mode_name[mode]); + "presentation-shm: %s [Delay %i msecs]", run_mode_name[mode], + commit_delay_msecs); window = calloc(1, sizeof *window); if (!window) return NULL; + window->commit_delay_msecs = commit_delay_msecs; window->mode = mode; window->callback = NULL; wl_list_init(&window->feedback_list); @@ -468,6 +471,23 @@ static const struct presentation_feedback_listener feedback_listener = { feedback_discarded }; +static void +window_emulate_rendering(struct window *window) +{ + struct timespec delay; + int ret; + + if (window->commit_delay_msecs <= 0) + return; + + delay.tv_sec = window->commit_delay_msecs / 1000; + delay.tv_nsec = (window->commit_delay_msecs % 1000) * 1000000; + + ret = nanosleep(&delay, NULL); + if (ret) + printf("nanosleep failed: %m\n"); +} + static void window_create_feedback(struct window *window, uint32_t frame_stamp) { @@ -490,6 +510,7 @@ window_create_feedback(struct window *window, uint32_t frame_stamp) &feedback_listener, feedback); feedback->frame_no = seq; + clock_gettime(window->display->clk_id, &feedback->commit); feedback->frame_stamp = frame_stamp; feedback->target = feedback->commit; @@ -524,6 +545,8 @@ redraw_mode_feedback(void *data, struct wl_callback *callback, uint32_t time) if (callback) wl_callback_destroy(callback); + window_emulate_rendering(window); + window->callback = wl_surface_frame(window->surface); wl_callback_add_listener(window->callback, &frame_listener_mode_feedback, window); @@ -566,6 +589,7 @@ feedkick_presented(void *data, switch (window->mode) { case RUN_MODE_PRESENT: + window_emulate_rendering(window); window_create_feedback(window, 0); window_feedkick(window); window_commit_next(window); @@ -586,6 +610,7 @@ feedkick_discarded(void *data, switch (window->mode) { case RUN_MODE_PRESENT: + window_emulate_rendering(window); window_create_feedback(window, 0); window_feedkick(window); window_commit_next(window); @@ -605,6 +630,8 @@ static const struct presentation_feedback_listener feedkick_listener = { static void firstdraw_mode_burst(struct window *window) { + window_emulate_rendering(window); + switch (window->mode) { case RUN_MODE_PRESENT: window_create_feedback(window, 0); @@ -807,10 +834,12 @@ usage(const char *prog, int exit_code) { fprintf(stderr, "Usage: %s [mode] [options]\n" "where 'mode' is one of\n" - " -f\trun in feedback mode (default)\n" - " -i\trun in feedback-idle mode; sleep 1s between frames\n" - " -p\trun in low-latency presentation mode\n" - "and 'options' may include\n", + " -f\t\trun in feedback mode (default)\n" + " -i\t\trun in feedback-idle mode; sleep 1s between frames\n" + " -p\t\trun in low-latency presentation mode\n" + "and 'options' may include\n" + " -d msecs\temulate the time used for rendering by a delay \n" + "\t\tof the given milliseconds before commit\n\n", prog); fprintf(stderr, "Printed timing statistics, depending on mode:\n" @@ -835,6 +864,7 @@ main(int argc, char **argv) int ret = 0; enum run_mode mode = RUN_MODE_FEEDBACK; int i; + int commit_delay_msecs = 0; for (i = 1; i < argc; i++) { if (strcmp("-f", argv[i]) == 0) @@ -843,12 +873,16 @@ main(int argc, char **argv) mode = RUN_MODE_FEEDBACK_IDLE; else if (strcmp("-p", argv[i]) == 0) mode = RUN_MODE_PRESENT; + else if ((strcmp("-d", argv[i]) == 0) && (i + 1 < argc)) { + i++; + commit_delay_msecs = atoi(argv[i]); + } else usage(argv[0], EXIT_FAILURE); } display = create_display(); - window = create_window(display, 250, 250, mode); + window = create_window(display, 250, 250, mode, commit_delay_msecs); if (!window) return 1;