Skip to content
Commits on Source (8)
......@@ -249,10 +249,6 @@ static int
finish_frame_handler(void *data)
{
struct pipewire_output *output = data;
int refresh_nsec = millihz_to_nsec(output->base.current_mode->refresh);
struct timespec ts;
struct timespec now;
int64_t delta;
/*
* Skip weston_output_finish_frame() if the repaint state machine was
......@@ -261,20 +257,7 @@ finish_frame_handler(void *data)
if (output->base.repaint_status != REPAINT_AWAITING_COMPLETION)
return 1;
/*
* The timer only has msec precision, but if the 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 = timespec_sub_to_nsec(&now, &ts);
if (delta > 1500000)
ts = now;
weston_output_finish_frame(&output->base, &ts, 0);
weston_output_finish_frame_from_timer(&output->base);
return 1;
}
......@@ -739,24 +722,6 @@ pipewire_submit_buffer(struct pipewire_output *output,
output->seq++;
}
static void
pipewire_output_arm_timer(struct pipewire_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
pipewire_output_repaint(struct weston_output *base, pixman_region32_t *damage)
{
......@@ -787,7 +752,7 @@ pipewire_output_repaint(struct weston_output *base, pixman_region32_t *damage)
out:
pipewire_output_arm_timer(output);
weston_output_arm_frame_timer(base, output->finish_frame_timer);
return 0;
}
......
......@@ -278,20 +278,6 @@ rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
struct weston_compositor *ec = output->base.compositor;
struct rdp_backend *b = output->backend;
struct rdp_peers_item *peer;
struct timespec now, target;
int refresh_nsec = millihz_to_nsec(output_base->current_mode->refresh);
int64_t delay_nsec;
/* Calculate the time we should complete this frame such that frames
are spaced out by the specified monitor refresh. Note that our timer
mechanism only has msec precision, so we won't exactly hit our
target refresh rate.
*/
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);
assert(output);
......@@ -313,8 +299,8 @@ rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
pixman_region32_fini(&transformed_damage);
}
wl_event_source_timer_update(output->finish_frame_timer,
DIV_ROUND_UP(delay_nsec, 1000000));
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
return 0;
}
......@@ -322,10 +308,8 @@ static int
finish_frame_handler(void *data)
{
struct rdp_output *output = data;
struct timespec ts;
weston_compositor_read_presentation_clock(output->base.compositor, &ts);
weston_output_finish_frame(&output->base, &ts, 0);
weston_output_finish_frame_from_timer(&output->base);
return 1;
}
......
......@@ -709,28 +709,12 @@ vnc_new_client(struct nvnc_client *client)
weston_output_schedule_repaint(&output->base);
}
static int
finish_frame_handler(void *data)
{
struct vnc_output *output = data;
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_output_finish_frame(&output->base, &ts, 0);
weston_output_finish_frame_from_timer(&output->base);
return 1;
}
......@@ -949,11 +933,7 @@ static int
vnc_output_repaint(struct weston_output *base, pixman_region32_t *damage)
{
struct vnc_output *output = to_vnc_output(base);
struct weston_compositor *ec = output->base.compositor;
struct vnc_backend *backend = output->backend;
struct timespec now, target;
int refresh_nsec = millihz_to_nsec(output->base.current_mode->refresh);
int64_t delay_nsec;
assert(output);
......@@ -972,13 +952,7 @@ vnc_output_repaint(struct weston_output *base, pixman_region32_t *damage)
*/
aml_dispatch(backend->aml);
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));
weston_output_arm_frame_timer(base, output->finish_frame_timer);
return 0;
}
......
......@@ -428,24 +428,6 @@ x11_output_start_repaint_loop(struct weston_output *output)
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
x11_output_repaint_gl(struct weston_output *output_base,
pixman_region32_t *damage)
......@@ -459,7 +441,7 @@ x11_output_repaint_gl(struct weston_output *output_base,
ec->renderer->repaint_output(output_base, damage, NULL);
x11_output_arm_timer(output);
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
return 0;
}
......@@ -552,7 +534,7 @@ x11_output_repaint_shm(struct weston_output *output_base,
free(err);
}
x11_output_arm_timer(output);
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
return 0;
}
......@@ -560,23 +542,8 @@ static int
finish_frame_handler(void *data)
{
struct x11_output *output = data;
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_output_finish_frame(&output->base, &ts, 0);
weston_output_finish_frame_from_timer(&output->base);
return 1;
}
......
......@@ -194,6 +194,12 @@ weston_region_global_to_output(pixman_region32_t *dst,
const struct weston_hdr_metadata_type1 *
weston_output_get_hdr_metadata_type1(const struct weston_output *output);
void
weston_output_arm_frame_timer(struct weston_output *output,
struct wl_event_source *frame_timer);
void
weston_output_finish_frame_from_timer(struct weston_output *output);
/* weston_seat */
void
......
......@@ -9736,3 +9736,58 @@ weston_renderer_resize_output(struct weston_output *output,
output->name);
}
}
/** Queue a frame timer callback
*
* \param output The output to queue a frame timer callback for.
* \param frame_timer The timer that calls weston_output_finish_frame().
*
* This function calculates the time when the current frame should be completed
* such that frames are spaced out evenly by the specified refresh rate.
*/
WL_EXPORT void
weston_output_arm_frame_timer(struct weston_output *output,
struct wl_event_source *frame_timer)
{
struct weston_compositor *ec = output->compositor;
struct timespec now;
struct timespec target;
int refresh_nsec = millihz_to_nsec(output->current_mode->refresh);
int64_t delay_nsec;
weston_compositor_read_presentation_clock(ec, &now);
timespec_add_nsec(&target, &output->frame_time, refresh_nsec);
delay_nsec = CLIP(timespec_sub_to_nsec(&target, &now), 1, refresh_nsec);
/* The libwayland event source timer API only has msec precision. */
wl_event_source_timer_update(frame_timer,
DIV_ROUND_UP(delay_nsec, 1000000));
}
/** Helper to call weston_output_finish_frame() from frame timer callbacks
*
* \param output The output to call weston_output_finish_frame() for.
*/
WL_EXPORT void
weston_output_finish_frame_from_timer(struct weston_output *output)
{
int refresh_nsec = millihz_to_nsec(output->current_mode->refresh);
struct timespec ts;
struct timespec now;
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->frame_time, refresh_nsec);
/* If we are more than 1.5 ms late, report the current time instead. */
weston_compositor_read_presentation_clock(output->compositor, &now);
delta = (int)timespec_sub_to_nsec(&now, &ts);
if (delta > 1500000)
ts = now;
weston_output_finish_frame(output, &ts, 0);
}