backend-x11: fix output repaint timing
Copy the output repaint timing code from the PipeWire backend. This evens frame pacing under varying render time and allows to actually reach 60 fps. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
This commit is contained in:
parent
d62c1b7f7b
commit
d9a8073568
|
@ -428,6 +428,24 @@ x11_output_start_repaint_loop(struct weston_output *output)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
x11_output_arm_timer(struct x11_output *output)
|
||||||
|
{
|
||||||
|
struct weston_compositor *ec = output->base.compositor;
|
||||||
|
struct timespec now;
|
||||||
|
struct timespec target;
|
||||||
|
int refresh_nsec = millihz_to_nsec(output->base.current_mode->refresh);
|
||||||
|
int64_t delay_nsec;
|
||||||
|
|
||||||
|
weston_compositor_read_presentation_clock(ec, &now);
|
||||||
|
timespec_add_nsec(&target, &output->base.frame_time, refresh_nsec);
|
||||||
|
|
||||||
|
delay_nsec = CLIP(timespec_sub_to_nsec(&target, &now), 1, refresh_nsec);
|
||||||
|
|
||||||
|
wl_event_source_timer_update(output->finish_frame_timer,
|
||||||
|
DIV_ROUND_UP(delay_nsec, 1000000));
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
x11_output_repaint_gl(struct weston_output *output_base,
|
x11_output_repaint_gl(struct weston_output *output_base,
|
||||||
pixman_region32_t *damage)
|
pixman_region32_t *damage)
|
||||||
|
@ -441,7 +459,7 @@ x11_output_repaint_gl(struct weston_output *output_base,
|
||||||
|
|
||||||
ec->renderer->repaint_output(output_base, damage, NULL);
|
ec->renderer->repaint_output(output_base, damage, NULL);
|
||||||
|
|
||||||
wl_event_source_timer_update(output->finish_frame_timer, 10);
|
x11_output_arm_timer(output);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +552,7 @@ x11_output_repaint_shm(struct weston_output *output_base,
|
||||||
free(err);
|
free(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_event_source_timer_update(output->finish_frame_timer, 10);
|
x11_output_arm_timer(output);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,9 +560,22 @@ static int
|
||||||
finish_frame_handler(void *data)
|
finish_frame_handler(void *data)
|
||||||
{
|
{
|
||||||
struct x11_output *output = data;
|
struct x11_output *output = data;
|
||||||
struct timespec ts;
|
int refresh_nsec = millihz_to_nsec(output->base.current_mode->refresh);
|
||||||
|
struct timespec now, ts;
|
||||||
|
int delta;
|
||||||
|
|
||||||
|
/* The timer only has msec precision, but if we approximately hit our
|
||||||
|
* target, report an exact time stamp by adding to the previous frame
|
||||||
|
* time.
|
||||||
|
*/
|
||||||
|
timespec_add_nsec(&ts, &output->base.frame_time, refresh_nsec);
|
||||||
|
|
||||||
|
/* If we are more than 1.5 ms late, report the current time instead. */
|
||||||
|
weston_compositor_read_presentation_clock(output->base.compositor, &now);
|
||||||
|
delta = (int)timespec_sub_to_nsec(&now, &ts);
|
||||||
|
if (delta > 1500000)
|
||||||
|
ts = now;
|
||||||
|
|
||||||
weston_compositor_read_presentation_clock(output->base.compositor, &ts);
|
|
||||||
weston_output_finish_frame(&output->base, &ts, 0);
|
weston_output_finish_frame(&output->base, &ts, 0);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in New Issue