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 <mario.kleiner.de@gmail.com>
Acked-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>

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 <pekka.paalanen@collabora.co.uk>
dev
Mario Kleiner 10 years ago committed by Pekka Paalanen
parent 2abe445546
commit c1809b230c
  1. 48
      clients/presentation-shm.c

@ -101,6 +101,7 @@ struct window {
int num_buffers; int num_buffers;
int next; int next;
int refresh_nsec; int refresh_nsec;
int commit_delay_msecs;
struct wl_callback *callback; struct wl_callback *callback;
struct wl_list feedback_list; struct wl_list feedback_list;
@ -201,19 +202,21 @@ static const struct wl_shell_surface_listener shell_surface_listener = {
static struct window * static struct window *
create_window(struct display *display, int width, int height, create_window(struct display *display, int width, int height,
enum run_mode mode) enum run_mode mode, int commit_delay_msecs)
{ {
struct window *window; struct window *window;
char title[128]; char title[128];
int ret; int ret;
snprintf(title, sizeof(title), 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); window = calloc(1, sizeof *window);
if (!window) if (!window)
return NULL; return NULL;
window->commit_delay_msecs = commit_delay_msecs;
window->mode = mode; window->mode = mode;
window->callback = NULL; window->callback = NULL;
wl_list_init(&window->feedback_list); wl_list_init(&window->feedback_list);
@ -468,6 +471,23 @@ static const struct presentation_feedback_listener feedback_listener = {
feedback_discarded 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 static void
window_create_feedback(struct window *window, uint32_t frame_stamp) 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_listener, feedback);
feedback->frame_no = seq; feedback->frame_no = seq;
clock_gettime(window->display->clk_id, &feedback->commit); clock_gettime(window->display->clk_id, &feedback->commit);
feedback->frame_stamp = frame_stamp; feedback->frame_stamp = frame_stamp;
feedback->target = feedback->commit; feedback->target = feedback->commit;
@ -524,6 +545,8 @@ redraw_mode_feedback(void *data, struct wl_callback *callback, uint32_t time)
if (callback) if (callback)
wl_callback_destroy(callback); wl_callback_destroy(callback);
window_emulate_rendering(window);
window->callback = wl_surface_frame(window->surface); window->callback = wl_surface_frame(window->surface);
wl_callback_add_listener(window->callback, wl_callback_add_listener(window->callback,
&frame_listener_mode_feedback, window); &frame_listener_mode_feedback, window);
@ -566,6 +589,7 @@ feedkick_presented(void *data,
switch (window->mode) { switch (window->mode) {
case RUN_MODE_PRESENT: case RUN_MODE_PRESENT:
window_emulate_rendering(window);
window_create_feedback(window, 0); window_create_feedback(window, 0);
window_feedkick(window); window_feedkick(window);
window_commit_next(window); window_commit_next(window);
@ -586,6 +610,7 @@ feedkick_discarded(void *data,
switch (window->mode) { switch (window->mode) {
case RUN_MODE_PRESENT: case RUN_MODE_PRESENT:
window_emulate_rendering(window);
window_create_feedback(window, 0); window_create_feedback(window, 0);
window_feedkick(window); window_feedkick(window);
window_commit_next(window); window_commit_next(window);
@ -605,6 +630,8 @@ static const struct presentation_feedback_listener feedkick_listener = {
static void static void
firstdraw_mode_burst(struct window *window) firstdraw_mode_burst(struct window *window)
{ {
window_emulate_rendering(window);
switch (window->mode) { switch (window->mode) {
case RUN_MODE_PRESENT: case RUN_MODE_PRESENT:
window_create_feedback(window, 0); window_create_feedback(window, 0);
@ -807,10 +834,12 @@ usage(const char *prog, int exit_code)
{ {
fprintf(stderr, "Usage: %s [mode] [options]\n" fprintf(stderr, "Usage: %s [mode] [options]\n"
"where 'mode' is one of\n" "where 'mode' is one of\n"
" -f\trun in feedback mode (default)\n" " -f\t\trun in feedback mode (default)\n"
" -i\trun in feedback-idle mode; sleep 1s between frames\n" " -i\t\trun in feedback-idle mode; sleep 1s between frames\n"
" -p\trun in low-latency presentation mode\n" " -p\t\trun in low-latency presentation mode\n"
"and 'options' may include\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); prog);
fprintf(stderr, "Printed timing statistics, depending on mode:\n" fprintf(stderr, "Printed timing statistics, depending on mode:\n"
@ -835,6 +864,7 @@ main(int argc, char **argv)
int ret = 0; int ret = 0;
enum run_mode mode = RUN_MODE_FEEDBACK; enum run_mode mode = RUN_MODE_FEEDBACK;
int i; int i;
int commit_delay_msecs = 0;
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
if (strcmp("-f", argv[i]) == 0) if (strcmp("-f", argv[i]) == 0)
@ -843,12 +873,16 @@ main(int argc, char **argv)
mode = RUN_MODE_FEEDBACK_IDLE; mode = RUN_MODE_FEEDBACK_IDLE;
else if (strcmp("-p", argv[i]) == 0) else if (strcmp("-p", argv[i]) == 0)
mode = RUN_MODE_PRESENT; mode = RUN_MODE_PRESENT;
else if ((strcmp("-d", argv[i]) == 0) && (i + 1 < argc)) {
i++;
commit_delay_msecs = atoi(argv[i]);
}
else else
usage(argv[0], EXIT_FAILURE); usage(argv[0], EXIT_FAILURE);
} }
display = create_display(); display = create_display();
window = create_window(display, 250, 250, mode); window = create_window(display, 250, 250, mode, commit_delay_msecs);
if (!window) if (!window)
return 1; return 1;

Loading…
Cancel
Save