ext_image_copy_capture_v1: replace schedule_frame with request_frame

schedule_frame is only called when the client has submitted damage
and a new frame should be rendered immediately. schedule_frame is
not called when the capture client is waiting for the next frame
but hasn't submitted damage.

Sources implementing a rendering loop based on the capture rate
need to know when a capture client is ready to accept a new frame.
Such sources want to trigger a redraw if and only if (1) they are
dirty (their contents have changed) and (2) the capture client is
ready to accept a new frame.

Replace schedule_frame with request_frame, triggered each time a
client sends a capture request. A flag indicates whether the capture
client has submitted damage.
This commit is contained in:
Simon Ser 2026-01-04 17:33:28 +01:00 committed by Simon Zeni
parent 6ae54dca23
commit f93865ed1f
4 changed files with 23 additions and 14 deletions

View file

@ -21,7 +21,7 @@ struct wlr_ext_image_capture_source_v1_interface {
// TODO: drop with_cursors flag // TODO: drop with_cursors flag
void (*start)(struct wlr_ext_image_capture_source_v1 *source, bool with_cursors); void (*start)(struct wlr_ext_image_capture_source_v1 *source, bool with_cursors);
void (*stop)(struct wlr_ext_image_capture_source_v1 *source); void (*stop)(struct wlr_ext_image_capture_source_v1 *source);
void (*schedule_frame)(struct wlr_ext_image_capture_source_v1 *source); void (*request_frame)(struct wlr_ext_image_capture_source_v1 *source, bool schedule_frame);
void (*copy_frame)(struct wlr_ext_image_capture_source_v1 *source, void (*copy_frame)(struct wlr_ext_image_capture_source_v1 *source,
struct wlr_ext_image_copy_capture_frame_v1 *dst_frame, struct wlr_ext_image_copy_capture_frame_v1 *dst_frame,
struct wlr_ext_image_capture_source_v1_frame_event *frame_event); struct wlr_ext_image_capture_source_v1_frame_event *frame_event);

View file

@ -70,9 +70,12 @@ static void output_source_stop(struct wlr_ext_image_capture_source_v1 *base) {
} }
} }
static void output_source_schedule_frame(struct wlr_ext_image_capture_source_v1 *base) { static void output_source_request_frame(struct wlr_ext_image_capture_source_v1 *base,
bool schedule_frame) {
struct wlr_ext_output_image_capture_source_v1 *source = wl_container_of(base, source, base); struct wlr_ext_output_image_capture_source_v1 *source = wl_container_of(base, source, base);
wlr_output_update_needs_frame(source->output); if (schedule_frame) {
wlr_output_update_needs_frame(source->output);
}
} }
static void output_source_copy_frame(struct wlr_ext_image_capture_source_v1 *base, static void output_source_copy_frame(struct wlr_ext_image_capture_source_v1 *base,
@ -99,7 +102,7 @@ static struct wlr_ext_image_capture_source_v1_cursor *output_source_get_pointer_
static const struct wlr_ext_image_capture_source_v1_interface output_source_impl = { static const struct wlr_ext_image_capture_source_v1_interface output_source_impl = {
.start = output_source_start, .start = output_source_start,
.stop = output_source_stop, .stop = output_source_stop,
.schedule_frame = output_source_schedule_frame, .request_frame = output_source_request_frame,
.copy_frame = output_source_copy_frame, .copy_frame = output_source_copy_frame,
.get_pointer_cursor = output_source_get_pointer_cursor, .get_pointer_cursor = output_source_get_pointer_cursor,
}; };
@ -258,10 +261,13 @@ struct wlr_ext_output_image_capture_source_manager_v1 *wlr_ext_output_image_capt
return manager; return manager;
} }
static void output_cursor_source_schedule_frame(struct wlr_ext_image_capture_source_v1 *base) { static void output_cursor_source_request_frame(struct wlr_ext_image_capture_source_v1 *base,
bool schedule_frame) {
struct output_cursor_source *cursor_source = wl_container_of(base, cursor_source, base); struct output_cursor_source *cursor_source = wl_container_of(base, cursor_source, base);
wlr_output_update_needs_frame(cursor_source->output); if (schedule_frame) {
cursor_source->needs_frame = true; wlr_output_update_needs_frame(cursor_source->output);
cursor_source->needs_frame = true;
}
} }
static void output_cursor_source_copy_frame(struct wlr_ext_image_capture_source_v1 *base, static void output_cursor_source_copy_frame(struct wlr_ext_image_capture_source_v1 *base,
@ -288,7 +294,7 @@ static void output_cursor_source_copy_frame(struct wlr_ext_image_capture_source_
} }
static const struct wlr_ext_image_capture_source_v1_interface output_cursor_source_impl = { static const struct wlr_ext_image_capture_source_v1_interface output_cursor_source_impl = {
.schedule_frame = output_cursor_source_schedule_frame, .request_frame = output_cursor_source_request_frame,
.copy_frame = output_cursor_source_copy_frame, .copy_frame = output_cursor_source_copy_frame,
}; };

View file

@ -128,9 +128,12 @@ static void source_stop(struct wlr_ext_image_capture_source_v1 *base) {
wlr_output_state_finish(&state); wlr_output_state_finish(&state);
} }
static void source_schedule_frame(struct wlr_ext_image_capture_source_v1 *base) { static void source_request_frame(struct wlr_ext_image_capture_source_v1 *base,
bool schedule_frame) {
struct scene_node_source *source = wl_container_of(base, source, base); struct scene_node_source *source = wl_container_of(base, source, base);
wlr_output_update_needs_frame(&source->output); if (schedule_frame) {
wlr_output_update_needs_frame(&source->output);
}
} }
static void source_copy_frame(struct wlr_ext_image_capture_source_v1 *base, static void source_copy_frame(struct wlr_ext_image_capture_source_v1 *base,
@ -149,7 +152,7 @@ static void source_copy_frame(struct wlr_ext_image_capture_source_v1 *base,
static const struct wlr_ext_image_capture_source_v1_interface source_impl = { static const struct wlr_ext_image_capture_source_v1_interface source_impl = {
.start = source_start, .start = source_start,
.stop = source_stop, .stop = source_stop,
.schedule_frame = source_schedule_frame, .request_frame = source_request_frame,
.copy_frame = source_copy_frame, .copy_frame = source_copy_frame,
}; };

View file

@ -281,10 +281,10 @@ static void frame_handle_capture(struct wl_client *client,
frame->capturing = true; frame->capturing = true;
bool need_frame = !pixman_region32_empty(&frame->session->damage); bool schedule_frame = !pixman_region32_empty(&frame->session->damage);
struct wlr_ext_image_capture_source_v1 *source = frame->session->source; struct wlr_ext_image_capture_source_v1 *source = frame->session->source;
if (need_frame && source->impl->schedule_frame) { if (source->impl->request_frame) {
source->impl->schedule_frame(source); source->impl->request_frame(source, schedule_frame);
} }
} }