mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-13 08:22:16 -04:00
Merge branch 'predictive-frame-scheduling' into 'master'
Draft: wlr_frame_scheduler: Add predictive frame scheduler See merge request wlroots/wlroots!5332
This commit is contained in:
commit
651f85cb81
34 changed files with 882 additions and 220 deletions
|
|
@ -48,6 +48,11 @@ struct wlr_output *wlr_wl_output_create_from_surface(struct wlr_backend *backend
|
|||
*/
|
||||
bool wlr_backend_is_wl(const 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.
|
||||
*/
|
||||
|
|
|
|||
26
include/wlr/interfaces/wlr_frame_scheduler.h
Normal file
26
include/wlr/interfaces/wlr_frame_scheduler.h
Normal 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
|
||||
|
|
@ -117,12 +117,6 @@ void wlr_output_finish(struct wlr_output *output);
|
|||
* 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.
|
||||
*
|
||||
|
|
|
|||
89
include/wlr/types/wlr_frame_scheduler.h
Normal file
89
include/wlr/types/wlr_frame_scheduler.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
struct wlr_frame_scheduler_impl;
|
||||
struct wlr_render_timer;
|
||||
|
||||
struct wlr_frame_scheduler {
|
||||
struct wlr_output *output;
|
||||
|
||||
struct {
|
||||
struct wl_signal frame;
|
||||
} events;
|
||||
|
||||
// Whether the render loop should be kept awake. True if 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 if `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);
|
||||
|
||||
/**
|
||||
* The predictive scheduler maintains a render loop based on `wlr_output.events.present`, and
|
||||
* schedules frame signals to arrive just before the estimated render deadline. It learns from
|
||||
* historic render times provided via wlr_frame_scheduler_inform_render().
|
||||
*/
|
||||
struct wlr_frame_scheduler *wlr_predictive_frame_scheduler_create(struct wlr_output *output);
|
||||
/**
|
||||
* Provide render timing feedback to the scheduler. Must be called after each output commit.
|
||||
*
|
||||
* pre_render_duration_ns is the wall time from the frame signal to the start of the render pass.
|
||||
*
|
||||
* render_timer is the GPU render timer for this frame. May be NULL if no rendering was performed
|
||||
* (e.g. direct scanout), in which case GPU render time is assumed to be zero.
|
||||
*
|
||||
* This is a no-op for non-predictive schedulers.
|
||||
*/
|
||||
void wlr_frame_scheduler_inform_render(struct wlr_frame_scheduler *scheduler,
|
||||
int64_t pre_render_duration_ns, struct wlr_render_timer *render_timer);
|
||||
|
||||
#endif
|
||||
|
|
@ -219,10 +219,6 @@ struct wlr_output {
|
|||
// true, changes may either succeed or fail.
|
||||
bool adaptive_sync_supported;
|
||||
|
||||
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;
|
||||
|
||||
|
|
@ -230,8 +226,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
|
||||
|
|
@ -252,7 +246,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
|
||||
|
|
@ -406,11 +399,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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -268,12 +268,9 @@ struct wlr_scene_output {
|
|||
uint64_t in_point;
|
||||
struct wlr_drm_syncobj_timeline *out_timeline;
|
||||
uint64_t out_point;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_scene_timer {
|
||||
int64_t pre_render_duration;
|
||||
struct wlr_render_timer *render_timer;
|
||||
struct wlr_render_timer *render_timer;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
/** A layer shell scene helper */
|
||||
|
|
@ -592,10 +589,15 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output);
|
|||
*/
|
||||
void wlr_scene_output_set_position(struct wlr_scene_output *scene_output,
|
||||
int lx, int ly);
|
||||
/**
|
||||
* Replace the frame scheduler for this scene output, destroying the previous
|
||||
* scheduler. If scene output currently needs a new frame, a frame will be
|
||||
* scheduled on the new frame scheduler.
|
||||
*/
|
||||
void wlr_scene_output_set_frame_scheduler(struct wlr_scene_output *scene_output,
|
||||
struct wlr_frame_scheduler *scheduler);
|
||||
|
||||
struct wlr_scene_output_state_options {
|
||||
struct wlr_scene_timer *timer;
|
||||
|
||||
/**
|
||||
* Color transform to apply before the output's color transform. Cannot be
|
||||
* used when the output has a non-NULL image description set.
|
||||
|
|
@ -610,12 +612,6 @@ struct wlr_scene_output_state_options {
|
|||
struct wlr_swapchain *swapchain;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if scene wants to render a new frame. False, if no new frame
|
||||
* is needed and an output commit can be skipped for the current frame.
|
||||
*/
|
||||
bool wlr_scene_output_needs_frame(struct wlr_scene_output *scene_output);
|
||||
|
||||
/**
|
||||
* Render and commit an output.
|
||||
*/
|
||||
|
|
@ -628,15 +624,6 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output,
|
|||
bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
||||
struct wlr_output_state *state, const struct wlr_scene_output_state_options *options);
|
||||
|
||||
/**
|
||||
* Retrieve the duration in nanoseconds between the last wlr_scene_output_commit() call and the end
|
||||
* of its operations, including those on the GPU that may have finished after the call returned.
|
||||
*
|
||||
* Returns -1 if the duration is unavailable.
|
||||
*/
|
||||
int64_t wlr_scene_timer_get_duration_ns(struct wlr_scene_timer *timer);
|
||||
void wlr_scene_timer_finish(struct wlr_scene_timer *timer);
|
||||
|
||||
/**
|
||||
* Call wlr_surface_send_frame_done() on all surfaces in the scene rendered by
|
||||
* wlr_scene_output_commit() for which wlr_scene_surface.primary_output
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue