mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-21 20:35:58 +01:00
scene_output: optionally record and report timings
This commit is contained in:
parent
f4eaab12a0
commit
214df8eda0
4 changed files with 73 additions and 8 deletions
|
@ -57,7 +57,7 @@ struct output {
|
||||||
static void output_handle_frame(struct wl_listener *listener, void *data) {
|
static void output_handle_frame(struct wl_listener *listener, void *data) {
|
||||||
struct output *output = wl_container_of(listener, output, frame);
|
struct output *output = wl_container_of(listener, output, frame);
|
||||||
|
|
||||||
if (!wlr_scene_output_commit(output->scene_output)) {
|
if (!wlr_scene_output_commit(output->scene_output, NULL)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -209,6 +209,11 @@ struct wlr_scene_output {
|
||||||
struct wl_array render_list;
|
struct wl_array render_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wlr_scene_timer {
|
||||||
|
int64_t pre_render_duration;
|
||||||
|
struct wlr_render_timer *render_timer;
|
||||||
|
};
|
||||||
|
|
||||||
/** A layer shell scene helper */
|
/** A layer shell scene helper */
|
||||||
struct wlr_scene_layer_surface_v1 {
|
struct wlr_scene_layer_surface_v1 {
|
||||||
struct wlr_scene_tree *tree;
|
struct wlr_scene_tree *tree;
|
||||||
|
@ -455,16 +460,30 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output);
|
||||||
void wlr_scene_output_set_position(struct wlr_scene_output *scene_output,
|
void wlr_scene_output_set_position(struct wlr_scene_output *scene_output,
|
||||||
int lx, int ly);
|
int lx, int ly);
|
||||||
|
|
||||||
|
struct wlr_scene_output_state_options {
|
||||||
|
struct wlr_scene_timer *timer;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render and commit an output.
|
* Render and commit an output.
|
||||||
*/
|
*/
|
||||||
bool wlr_scene_output_commit(struct wlr_scene_output *scene_output);
|
bool wlr_scene_output_commit(struct wlr_scene_output *scene_output,
|
||||||
|
const struct wlr_scene_output_state_options *options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render and populate given output state.
|
* Render and populate given output state.
|
||||||
*/
|
*/
|
||||||
bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
||||||
struct wlr_output_state *state);
|
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
|
* Call wlr_surface_send_frame_done() on all surfaces in the scene rendered by
|
||||||
|
|
|
@ -559,7 +559,7 @@ static void output_frame(struct wl_listener *listener, void *data) {
|
||||||
scene, output->wlr_output);
|
scene, output->wlr_output);
|
||||||
|
|
||||||
/* Render the scene if needed and commit the output */
|
/* Render the scene if needed and commit the output */
|
||||||
wlr_scene_output_commit(scene_output);
|
wlr_scene_output_commit(scene_output, NULL);
|
||||||
|
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
|
@ -1584,7 +1584,8 @@ static bool scene_entry_try_direct_scanout(struct render_list_entry *entry,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) {
|
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(
|
if (!scene_output->output->needs_frame && !pixman_region32_not_empty(
|
||||||
&scene_output->damage_ring.current)) {
|
&scene_output->damage_ring.current)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1593,7 +1594,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
struct wlr_output_state state;
|
struct wlr_output_state state;
|
||||||
wlr_output_state_init(&state);
|
wlr_output_state_init(&state);
|
||||||
if (!wlr_scene_output_build_state(scene_output, &state)) {
|
if (!wlr_scene_output_build_state(scene_output, &state, options)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1610,7 +1611,19 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
||||||
struct wlr_output_state *state) {
|
struct wlr_output_state *state, const struct wlr_scene_output_state_options *options) {
|
||||||
|
struct wlr_scene_output_state_options default_options = {0};
|
||||||
|
if (!options) {
|
||||||
|
options = &default_options;
|
||||||
|
}
|
||||||
|
struct wlr_scene_timer *timer = options->timer;
|
||||||
|
struct timespec start_time;
|
||||||
|
if (timer) {
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &start_time);
|
||||||
|
wlr_scene_timer_finish(timer);
|
||||||
|
*timer = (struct wlr_scene_timer){0};
|
||||||
|
}
|
||||||
|
|
||||||
if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && !state->enabled) {
|
if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && !state->enabled) {
|
||||||
// if the state is being disabled, do nothing.
|
// if the state is being disabled, do nothing.
|
||||||
return true;
|
return true;
|
||||||
|
@ -1683,6 +1696,12 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scanout) {
|
if (scanout) {
|
||||||
|
if (timer) {
|
||||||
|
struct timespec end_time, duration;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &end_time);
|
||||||
|
timespec_sub(&duration, &end_time, &start_time);
|
||||||
|
timer->pre_render_duration = timespec_to_nsec(&duration);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1742,7 +1761,19 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass(output->renderer, buffer, NULL);
|
if (timer) {
|
||||||
|
timer->render_timer = wlr_render_timer_create(output->renderer);
|
||||||
|
|
||||||
|
struct timespec end_time, duration;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &end_time);
|
||||||
|
timespec_sub(&duration, &end_time, &start_time);
|
||||||
|
timer->pre_render_duration = timespec_to_nsec(&duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass(output->renderer, buffer,
|
||||||
|
&(struct wlr_buffer_pass_options){
|
||||||
|
.timer = timer ? timer->render_timer : NULL,
|
||||||
|
});
|
||||||
if (render_pass == NULL) {
|
if (render_pass == NULL) {
|
||||||
wlr_buffer_unlock(buffer);
|
wlr_buffer_unlock(buffer);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1859,6 +1890,21 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t wlr_scene_timer_get_duration_ns(struct wlr_scene_timer *timer) {
|
||||||
|
int64_t pre_render = timer->pre_render_duration;
|
||||||
|
if (!timer->render_timer) {
|
||||||
|
return pre_render;
|
||||||
|
}
|
||||||
|
int64_t render = wlr_render_timer_get_duration_ns(timer->render_timer);
|
||||||
|
return render != -1 ? pre_render + render : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_scene_timer_finish(struct wlr_scene_timer *timer) {
|
||||||
|
if (timer->render_timer) {
|
||||||
|
wlr_render_timer_destroy(timer->render_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void scene_node_send_frame_done(struct wlr_scene_node *node,
|
static void scene_node_send_frame_done(struct wlr_scene_node *node,
|
||||||
struct wlr_scene_output *scene_output, struct timespec *now) {
|
struct wlr_scene_output *scene_output, struct timespec *now) {
|
||||||
if (!node->enabled) {
|
if (!node->enabled) {
|
||||||
|
|
Loading…
Reference in a new issue