diff --git a/examples/cairo-buffer.c b/examples/cairo-buffer.c index 7de4a053b..0e122f7fc 100644 --- a/examples/cairo-buffer.c +++ b/examples/cairo-buffer.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -103,10 +104,10 @@ static void server_handle_new_output(struct wl_listener *listener, void *data) { struct output *output = calloc(1, sizeof(*output)); output->wlr = wlr_output; output->server = server; - output->frame.notify = output_handle_frame; - wl_signal_add(&wlr_output->events.frame, &output->frame); output->scene_output = wlr_scene_output_create(server->scene, wlr_output); + output->frame.notify = output_handle_frame; + wl_signal_add(&output->scene_output->frame_scheduler->events.frame, &output->frame); struct wlr_output_state state; wlr_output_state_init(&state); diff --git a/examples/embedded.c b/examples/embedded.c index c488e0111..4206d9d52 100644 --- a/examples/embedded.c +++ b/examples/embedded.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -220,10 +221,10 @@ int main(int argc, char *argv[]) { wl_subsurface_set_position(subsurface, 20, 20); struct wlr_output *output = wlr_wl_output_create_from_surface(backend, child_surface); wlr_output_init_render(output, allocator, renderer); - scene_output = wlr_scene_output_create(scene, output); + scene_output = wlr_scene_output_create(scene, output); output_frame.notify = output_handle_frame; - wl_signal_add(&output->events.frame, &output_frame); + wl_signal_add(&scene_output->frame_scheduler->events.frame, &output_frame); struct wlr_output_state state; wlr_output_state_init(&state); diff --git a/examples/scene-graph.c b/examples/scene-graph.c index 421986534..88dc792d0 100644 --- a/examples/scene-graph.c +++ b/examples/scene-graph.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -74,10 +75,10 @@ static void server_handle_new_output(struct wl_listener *listener, void *data) { struct output *output = calloc(1, sizeof(*output)); output->wlr = wlr_output; output->server = server; - output->frame.notify = output_handle_frame; - wl_signal_add(&wlr_output->events.frame, &output->frame); output->scene_output = wlr_scene_output_create(server->scene, wlr_output); + output->frame.notify = output_handle_frame; + wl_signal_add(&output->scene_output->frame_scheduler->events.frame, &output->frame); struct wlr_output_state state; wlr_output_state_init(&state); diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 37abd20f5..ac1af2667 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -199,6 +199,7 @@ struct wlr_scene_output { struct wlr_output *output; struct wl_list link; // wlr_scene.outputs struct wlr_scene *scene; + struct wlr_frame_scheduler *frame_scheduler; struct wlr_addon addon; struct wlr_damage_ring damage_ring; @@ -218,7 +219,6 @@ struct wlr_scene_output { struct wl_listener output_commit; struct wl_listener output_damage; - struct wl_listener output_needs_frame; struct wl_list damage_highlight_regions; diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 6c043ed51..d61366865 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,7 @@ struct tinywl_output { struct wl_list link; struct tinywl_server *server; struct wlr_output *wlr_output; + struct wlr_frame_scheduler *frame_scheduler; struct wl_listener frame; struct wl_listener request_state; struct wl_listener destroy; @@ -590,6 +592,7 @@ static void output_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&output->request_state.link); wl_list_remove(&output->destroy.link); wl_list_remove(&output->link); + wlr_frame_scheduler_destroy(output->frame_scheduler); free(output); } @@ -628,10 +631,6 @@ static void server_new_output(struct wl_listener *listener, void *data) { output->wlr_output = wlr_output; output->server = server; - /* Sets up a listener for the frame event. */ - output->frame.notify = output_frame; - wl_signal_add(&wlr_output->events.frame, &output->frame); - /* Sets up a listener for the state request event. */ output->request_state.notify = output_request_state; wl_signal_add(&wlr_output->events.request_state, &output->request_state); @@ -655,6 +654,10 @@ static void server_new_output(struct wl_listener *listener, void *data) { wlr_output); struct wlr_scene_output *scene_output = wlr_scene_output_create(server->scene, wlr_output); wlr_scene_output_layout_add_output(server->scene_layout, l_output, scene_output); + + /* Sets up a listener for the frame event. */ + output->frame.notify = output_frame; + wl_signal_add(&scene_output->frame_scheduler->events.frame, &output->frame); } static void xdg_toplevel_map(struct wl_listener *listener, void *data) { diff --git a/types/scene/surface.c b/types/scene/surface.c index 11396e2fd..e55413d75 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include "types/wlr_scene.h" @@ -180,7 +181,7 @@ static void handle_scene_surface_surface_commit( if (!wl_list_empty(&surface->surface->current.frame_callback_list) && surface->buffer->primary_output != NULL && enabled) { - wlr_output_schedule_frame(surface->buffer->primary_output->output); + wlr_frame_scheduler_schedule_frame(surface->buffer->primary_output->frame_scheduler); } } diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 514c0e152..7a7dcd489 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -328,7 +329,7 @@ static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *dam -scene_output->x, -scene_output->y); scale_output_damage(&output_damage, scene_output->output->scale); if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) { - wlr_output_schedule_frame(scene_output->output); + wlr_frame_scheduler_schedule_frame(scene_output->frame_scheduler); } pixman_region32_fini(&output_damage); } @@ -797,7 +798,7 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff (int)round((lx - scene_output->x) * output_scale), (int)round((ly - scene_output->y) * output_scale)); if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) { - wlr_output_schedule_frame(scene_output->output); + wlr_frame_scheduler_schedule_frame(scene_output->frame_scheduler); } pixman_region32_fini(&output_damage); } @@ -1296,7 +1297,7 @@ static void scene_node_output_update(struct wlr_scene_node *node, static void scene_output_update_geometry(struct wlr_scene_output *scene_output, bool force_update) { wlr_damage_ring_add_whole(&scene_output->damage_ring); - wlr_output_schedule_frame(scene_output->output); + wlr_frame_scheduler_schedule_frame(scene_output->frame_scheduler); scene_node_output_update(&scene_output->scene->tree.node, &scene_output->scene->outputs, NULL, force_update ? scene_output : NULL); @@ -1346,16 +1347,10 @@ static void scene_output_handle_damage(struct wl_listener *listener, void *data) scene_output, output_damage); struct wlr_output_event_damage *event = data; if (wlr_damage_ring_add(&scene_output->damage_ring, event->damage)) { - wlr_output_schedule_frame(scene_output->output); + wlr_frame_scheduler_schedule_frame(scene_output->frame_scheduler); } } -static void scene_output_handle_needs_frame(struct wl_listener *listener, void *data) { - struct wlr_scene_output *scene_output = wl_container_of(listener, - scene_output, output_needs_frame); - wlr_output_schedule_frame(scene_output->output); -} - struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, struct wlr_output *output) { struct wlr_scene_output *scene_output = calloc(1, sizeof(*scene_output)); @@ -1363,6 +1358,12 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, return NULL; } + scene_output->frame_scheduler = wlr_frame_scheduler_autocreate(output); + if (scene_output->frame_scheduler == NULL) { + free(scene_output); + return NULL; + } + scene_output->output = output; scene_output->scene = scene; wlr_addon_init(&scene_output->addon, &output->addons, scene, &output_addon_impl); @@ -1396,9 +1397,6 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, scene_output->output_damage.notify = scene_output_handle_damage; wl_signal_add(&output->events.damage, &scene_output->output_damage); - scene_output->output_needs_frame.notify = scene_output_handle_needs_frame; - wl_signal_add(&output->events.needs_frame, &scene_output->output_needs_frame); - scene_output_update_geometry(scene_output, false); return scene_output; @@ -1426,12 +1424,12 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { } wlr_addon_finish(&scene_output->addon); + wlr_frame_scheduler_destroy(scene_output->frame_scheduler); wlr_damage_ring_finish(&scene_output->damage_ring); pixman_region32_fini(&scene_output->pending_commit_damage); wl_list_remove(&scene_output->link); wl_list_remove(&scene_output->output_commit.link); wl_list_remove(&scene_output->output_damage.link); - wl_list_remove(&scene_output->output_needs_frame.link); wl_array_release(&scene_output->render_list); free(scene_output); @@ -1671,11 +1669,6 @@ static bool scene_entry_try_direct_scanout(struct render_list_entry *entry, bool wlr_scene_output_commit(struct wlr_scene_output *scene_output, const struct wlr_scene_output_state_options *options) { - if (!scene_output->output->needs_frame && !pixman_region32_not_empty( - &scene_output->pending_commit_damage)) { - return true; - } - bool ok = false; struct wlr_output_state state; wlr_output_state_init(&state); @@ -1967,7 +1960,7 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT && !wl_list_empty(&scene_output->damage_highlight_regions)) { - wlr_output_schedule_frame(scene_output->output); + wlr_frame_scheduler_schedule_frame(scene_output->frame_scheduler); } return true;