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>
This commit is contained in:
committed by
Pekka Paalanen
parent
2abe445546
commit
c1809b230c
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user