Merge branch 'scheduling-2-better-this-time' into 'master'

Add new frame scheduler interface

See merge request wlroots/wlroots!4307
This commit is contained in:
Rose Hudson 2024-04-24 15:04:24 +00:00
commit a06c728a05
29 changed files with 507 additions and 153 deletions

View file

@ -4,8 +4,6 @@
#include <wlr/backend/headless.h>
#include <wlr/backend/interface.h>
#define HEADLESS_DEFAULT_REFRESH (60 * 1000) // 60 Hz
struct wlr_headless_backend {
struct wlr_backend backend;
struct wl_event_loop *event_loop;
@ -19,9 +17,6 @@ struct wlr_headless_output {
struct wlr_headless_backend *backend;
struct wl_list link;
struct wl_event_source *frame_timer;
int frame_delay; // ms
};
struct wlr_headless_backend *headless_backend_from_backend(

View file

@ -48,6 +48,11 @@ struct wlr_output *wlr_wl_output_create_from_surface(struct wlr_backend *backend
*/
bool wlr_backend_is_wl(struct wlr_backend *backend);
/**
* Check whether the Wayland server advertises the wp_presentation protocol.
*/
bool wlr_wl_backend_has_presentation_time(struct wlr_backend *backend);
/**
* Check whether the provided input device is a Wayland input device.
*/

View file

@ -0,0 +1,26 @@
/*
* This an unstable interface of wlroots. No guarantees are made regarding the
* future consistency of this API.
*/
#ifndef WLR_USE_UNSTABLE
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
#endif
#ifndef WLR_INTERFACES_WLR_FRAME_SCHEDULER_H
#define WLR_INTERFACES_WLR_FRAME_SCHEDULER_H
struct wlr_frame_scheduler;
struct wlr_output;
struct wlr_frame_scheduler_impl {
/**
* Ensure that the scheduler->frame signal will be fired in the future.
*/
void (*schedule_frame)(struct wlr_frame_scheduler *scheduler);
void (*destroy)(struct wlr_frame_scheduler *scheduler);
};
void wlr_frame_scheduler_init(struct wlr_frame_scheduler *scheduler,
const struct wlr_frame_scheduler_impl *impl, struct wlr_output *output);
#endif

View file

@ -108,12 +108,6 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
* output changes.
*/
void wlr_output_update_needs_frame(struct wlr_output *output);
/**
* Send a frame event.
*
* See wlr_output.events.frame.
*/
void wlr_output_send_frame(struct wlr_output *output);
/**
* Send a present event.
*

View file

@ -0,0 +1,68 @@
/*
* This an unstable interface of wlroots. No guarantees are made regarding the
* future consistency of this API.
*/
#ifndef WLR_USE_UNSTABLE
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
#endif
#ifndef WLR_TYPES_WLR_FRAME_SCHEDULER_H
#define WLR_TYPES_WLR_FRAME_SCHEDULER_H
#include <stdbool.h>
#include <wayland-server-core.h>
struct wlr_frame_scheduler_impl;
struct wlr_frame_scheduler {
struct wlr_output *output;
struct {
struct wl_signal frame;
} events;
// Whether the render loop should be kept awake. True iff wlr_frame_scheduler_schedule_frame() was
// called since the last frame event.
bool needs_frame;
// private state
const struct wlr_frame_scheduler_impl *impl;
struct wl_listener backend_needs_frame;
};
/**
* The present scheduler maintains a render loop based on `wlr_output.events.present`. To wake the
* render loop, it emits the frame signal when the compositor's event loop is idle.
*/
struct wlr_frame_scheduler *wlr_present_scheduler_create(struct wlr_output *output);
/**
* The Wayland scheduler maintains a render loop based on wl_surface.frame callbacks. To wake the
* render loop, it emits the frame signal when the compositor's event loop is idle.
*/
struct wlr_frame_scheduler *wlr_wl_scheduler_create(struct wlr_output *output);
/**
* The interval scheduler maintains a render loop based on a timer. To wake the render loop, it
* emits the frame signal when the compositor's event loop is idle.
*/
struct wlr_frame_scheduler *wlr_interval_scheduler_create(struct wlr_output *output);
/**
* Creates an appropriate frame scheduler for the given output's backend capabilities.
*/
struct wlr_frame_scheduler *wlr_frame_scheduler_autocreate(struct wlr_output *output);
/**
* Inform the scheduler that a frame signal is needed. The scheduler implementation will choose a
* good time to emit the signal. The signal is emitted only if this function has been called at
* least once since the last signal.
*/
void wlr_frame_scheduler_schedule_frame(struct wlr_frame_scheduler *scheduler);
/**
* Emits a frame signal iff `wlr_frame_scheduler_schedule_frame()` has been called since the last
* frame signal.
*/
void wlr_frame_scheduler_emit_frame(struct wlr_frame_scheduler *scheduler);
void wlr_frame_scheduler_destroy(struct wlr_frame_scheduler *scheduler);
#endif

View file

@ -150,10 +150,6 @@ struct wlr_output {
enum wlr_output_adaptive_sync_status adaptive_sync_status;
uint32_t render_format;
bool needs_frame;
// damage for cursors and fullscreen surface, in output-local coordinates
bool frame_pending;
// true for example with VR headsets
bool non_desktop;
@ -161,8 +157,6 @@ struct wlr_output {
uint32_t commit_seq;
struct {
// Request to render a frame
struct wl_signal frame;
// Emitted when software cursors or backend-specific logic damage the
// output
struct wl_signal damage; // struct wlr_output_event_damage
@ -183,7 +177,6 @@ struct wlr_output {
struct wl_signal destroy;
} events;
struct wl_event_source *idle_frame;
struct wl_event_source *idle_done;
int attach_render_locks; // number of locks forcing rendering
@ -334,11 +327,6 @@ bool wlr_output_test_state(struct wlr_output *output,
*/
bool wlr_output_commit_state(struct wlr_output *output,
const struct wlr_output_state *state);
/**
* Manually schedules a `frame` event. If a `frame` event is already pending,
* it is a no-op.
*/
void wlr_output_schedule_frame(struct wlr_output *output);
/**
* Returns the maximum length of each gamma ramp, or 0 if unsupported.
*/

View file

@ -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;