diff --git a/examples/cairo-buffer.c b/examples/cairo-buffer.c index 6392b2ac5..2eb3b7264 100644 --- a/examples/cairo-buffer.c +++ b/examples/cairo-buffer.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -104,10 +105,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 f0f661198..647c8e38b 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 f6f97cfea..374a76917 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -224,6 +224,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; @@ -258,7 +259,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 fe242e1a9..d29eb2930 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,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; @@ -603,6 +605,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); } @@ -641,10 +644,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); @@ -668,6 +667,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 e6ea1333a..b5d1a314e 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -364,7 +365,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 7231422e8..10bf8d015 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -362,7 +363,7 @@ static void scene_output_damage(struct wlr_scene_output *scene_output, pixman_region32_intersect_rect(&clipped, damage, 0, 0, output->width, output->height); if (!pixman_region32_empty(&clipped)) { - wlr_output_schedule_frame(scene_output->output); + wlr_frame_scheduler_schedule_frame(scene_output->frame_scheduler); wlr_damage_ring_add(&scene_output->damage_ring, &clipped); pixman_region32_union(&scene_output->pending_commit_damage, @@ -1576,7 +1577,7 @@ static void scene_handle_gamma_control_manager_v1_set_gamma(struct wl_listener * output->gamma_lut = event->control; wlr_color_transform_unref(output->gamma_lut_color_transform); output->gamma_lut_color_transform = wlr_gamma_control_v1_get_color_transform(event->control); - wlr_output_schedule_frame(output->output); + wlr_frame_scheduler_schedule_frame(output->frame_scheduler); } static void scene_handle_gamma_control_manager_v1_destroy(struct wl_listener *listener, @@ -1691,7 +1692,7 @@ static void scene_output_handle_commit(struct wl_listener *listener, void *data) if (scene_output->scene->debug_damage_option == 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); } // Next time the output is enabled, try to re-apply the gamma LUT @@ -1720,12 +1721,6 @@ static void scene_output_handle_damage(struct wl_listener *listener, void *data) pixman_region32_fini(&damage); } -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)); @@ -1733,6 +1728,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); @@ -1778,9 +1779,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; @@ -1810,12 +1808,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); if (scene_output->in_timeline != NULL) { wlr_drm_syncobj_timeline_signal(scene_output->in_timeline, UINT64_MAX); wlr_drm_syncobj_timeline_unref(scene_output->in_timeline);