compositor: Add REPAINT_DEFERRED repaint_status

Backends can end up in indeterminate/invalid state and be unable to
process updates.

Add a way for the backend to tell the core to stop scheduling repaints,
and a way for the backend to schedule all the repaints that should have
taken place during the invalid state period.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
Derek Foreman 2026-01-28 14:56:03 -06:00
parent b8d44cf358
commit 047193a058
4 changed files with 57 additions and 0 deletions

View file

@ -362,6 +362,10 @@ enum weston_repaint_status {
REPAINT_BEGIN_FROM_IDLE, /**< start_repaint_loop scheduled */
REPAINT_SCHEDULED, /**< repaint is scheduled to occur */
REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
/** Needs a repaint when the backend is ready. Backends must call
* weston_backend_clear_deferred() when ready.
*/
REPAINT_DEFERRED,
};
/** Content producer for heads

View file

@ -134,6 +134,12 @@ struct weston_backend {
* defined in weston_compositor_backend.
*/
enum weston_compositor_backend backend_type;
/** The backend is incapable of painting right now, but will
* call weston_backend_clear_deferred() at some point to
* exit deferred state.
*/
bool deferred;
};
/* weston_head */

View file

@ -4320,6 +4320,11 @@ weston_output_finish_frame(struct weston_output *output,
else
assert(presented_flags & WP_PRESENTATION_FEEDBACK_INVALID);
if (output->backend->deferred) {
output->repaint_status = REPAINT_DEFERRED;
return;
}
weston_compositor_read_presentation_clock(compositor, &now);
/* If we haven't been supplied any timestamp at all, we don't have a
@ -4688,6 +4693,11 @@ weston_output_schedule_repaint(struct weston_output *output)
if (output->repaint_status != REPAINT_NOT_SCHEDULED)
return;
if (output->backend->deferred) {
output->repaint_status = REPAINT_DEFERRED;
return;
}
output->repaint_status = REPAINT_BEGIN_FROM_IDLE;
assert(!output->idle_repaint_source);
output->idle_repaint_source = wl_event_loop_add_idle(loop, idle_repaint,
@ -9412,6 +9422,8 @@ output_repaint_status_text(struct weston_output *output)
return "repaint scheduled";
case REPAINT_AWAITING_COMPLETION:
return "awaiting completion";
case REPAINT_DEFERRED:
return "deferred";
}
assert(!"output_repaint_status_text missing enum");
@ -9750,6 +9762,8 @@ weston_compositor_print_scene_graph(struct weston_compositor *ec)
fprintf(fp, "\tto be presented at: %" PRId64 ".%09ld\n",
(int64_t)output->next_present.tv_sec,
output->next_present.tv_nsec);
} else if (output->repaint_status == REPAINT_DEFERRED) {
fprintf(fp, "\tDeferred pending backend recovery\n");
}
wl_list_for_each(head, &output->head_list, output_link) {
fprintf(fp, "\tHead %d (%s): %sconnected\n",
@ -10920,3 +10934,28 @@ weston_output_set_ready(struct weston_output *output)
weston_output_schedule_repaint(output);
}
}
WL_EXPORT void
weston_backend_set_deferred(struct weston_backend *backend)
{
backend->deferred = true;
}
WL_EXPORT void
weston_backend_clear_deferred(struct weston_backend *backend,
struct weston_compositor *compositor)
{
struct weston_output *output;
backend->deferred = false;
wl_list_for_each(output, &compositor->output_list, link) {
if (output->backend != backend)
continue;
if (output->repaint_status != REPAINT_DEFERRED)
continue;
output->repaint_status = REPAINT_NOT_SCHEDULED;
weston_output_schedule_repaint(output);
}
}

View file

@ -876,4 +876,12 @@ struct timespec
weston_output_repaint_from_present(const struct weston_output *output,
const struct timespec *now,
const struct timespec *present_time);
void
weston_backend_set_deferred(struct weston_backend *backend);
void
weston_backend_clear_deferred(struct weston_backend *backend,
struct weston_compositor *compositor);
#endif