[PATCH 3/8] compositor, shell: Add animation to measure desktop fps
Tomeu Vizoso
tomeu at tomeuvizoso.net
Mon Jul 1 08:29:13 PDT 2013
From: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
On the first output, count the number of frames rendered for each
second, and report the fps in the Weston log.
To ensure a busy rendering loop, the debug key binding starting the
measurement also creates a bouncing box animation on screen. The box is
simply a solid color surface that moves around randomly.
This crude benchmark mode is useful for seeing whether the compositor
can consistently hit the screen refresh rate.
[pq: wrote the commit message, ported over the great input rework]
---
src/compositor.c | 33 +++++++++++++++
src/compositor.h | 10 +++++
src/shell.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+)
diff --git a/src/compositor.c b/src/compositor.c
index 43d8965..3869cac 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1358,6 +1358,22 @@ weston_output_finish_frame(struct weston_output *output, uint32_t msecs)
wl_display_get_event_loop(compositor->wl_display);
int fd;
+ if (output->benchmark.enabled) {
+ if (output->benchmark.update_time == 0) {
+ output->benchmark.update_time = msecs;
+ } else {
+ uint32_t d = msecs - output->benchmark.update_time;
+ float fps;
+ output->benchmark.frame_counter++;
+ if (d >= 1000) {
+ fps = output->benchmark.frame_counter * 1000.0f / d;
+ weston_log("FPS = %f\n", fps);
+ output->benchmark.update_time = msecs;
+ output->benchmark.frame_counter = 0;
+ }
+ }
+ }
+
output->frame_time = msecs;
if (output->repaint_needed) {
weston_output_repaint(output, msecs);
@@ -2716,6 +2732,9 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
output->mm_height = mm_height;
output->dirty = 1;
output->origin_scale = scale;
+ output->benchmark.enabled = 0;
+ output->benchmark.update_time = 0;
+ output->benchmark.frame_counter = 0;
weston_output_transform_scale_init(output, transform, scale);
weston_output_init_zoom(output);
@@ -2737,6 +2756,20 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
wl_signal_emit(&c->output_created_signal, output);
}
+WL_EXPORT void
+weston_output_enable_benchmark(struct weston_output *output)
+{
+ output->benchmark.enabled = 1;
+ output->benchmark.update_time = 0;
+ output->benchmark.frame_counter = 0;
+}
+
+WL_EXPORT void
+weston_output_disable_benchmark(struct weston_output *output)
+{
+ output->benchmark.enabled = 0;
+}
+
static void
compositor_bind(struct wl_client *client,
void *data, uint32_t version, uint32_t id)
diff --git a/src/compositor.h b/src/compositor.h
index 773d67e..1de1239 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -201,6 +201,12 @@ struct weston_output {
int32_t origin_scale;
struct wl_list mode_list;
+ struct {
+ int enabled;
+ uint32_t update_time;
+ int frame_counter;
+ } benchmark;
+
void (*start_repaint_loop)(struct weston_output *output);
void (*repaint)(struct weston_output *output,
pixman_region32_t *damage);
@@ -909,6 +915,10 @@ weston_output_schedule_repaint(struct weston_output *output);
void
weston_output_damage(struct weston_output *output);
void
+weston_output_enable_benchmark(struct weston_output *output);
+void
+weston_output_disable_benchmark(struct weston_output *output);
+void
weston_compositor_schedule_repaint(struct weston_compositor *compositor);
void
weston_compositor_fade(struct weston_compositor *compositor, float tint);
diff --git a/src/shell.c b/src/shell.c
index 8b858e5..80b3e8b 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -161,6 +161,18 @@ struct desktop_shell {
} screensaver;
struct {
+ struct weston_layer layer;
+ struct weston_surface *surface;
+ struct weston_animation animation;
+ struct weston_transform transform;
+ uint32_t anim_timestamp;
+ double anim_current;
+ double anim_duration;
+ int32_t anim_dx;
+ int32_t anim_dy;
+ } benchmark;
+
+ struct {
struct wl_resource *binding;
struct wl_list surfaces;
} input_panel;
@@ -4310,6 +4322,111 @@ backlight_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
output->set_backlight(output, output->backlight_current);
}
+static void
+benchmark_animation_frame(struct weston_animation *animation,
+ struct weston_output *output, uint32_t msecs)
+{
+ struct desktop_shell *shell =
+ container_of(animation, struct desktop_shell,
+ benchmark.animation);
+ struct weston_surface *surface = shell->benchmark.surface;
+ uint32_t t;
+ uint32_t target_x, target_y;
+ double dx, dy;
+
+
+ if (shell->benchmark.anim_timestamp == 0)
+ shell->benchmark.anim_timestamp = msecs;
+ t = msecs - shell->benchmark.anim_timestamp;
+
+ if (t >= shell->benchmark.anim_duration) {
+ t = 0;
+ weston_surface_set_position(surface,
+ surface->geometry.x + shell->benchmark.anim_dx,
+ surface->geometry.y + shell->benchmark.anim_dy);
+ }
+
+ if (t == 0) {
+ target_x = 10 + random() % (output->width - 110);
+ target_y = 10 + random() % (output->height - 110);
+
+ shell->benchmark.anim_timestamp = msecs;
+ shell->benchmark.anim_duration = 2000;
+ shell->benchmark.anim_dx = target_x - surface->geometry.x;
+ shell->benchmark.anim_dy = target_y - surface->geometry.y;
+ }
+
+ dx = t / shell->benchmark.anim_duration * shell->benchmark.anim_dx;
+ dy = t / shell->benchmark.anim_duration * shell->benchmark.anim_dy;
+
+ weston_compositor_schedule_repaint(shell->compositor);
+
+ if (wl_list_empty(&shell->benchmark.transform.link))
+ wl_list_insert(surface->geometry.transformation_list.prev,
+ &shell->benchmark.transform.link);
+
+ weston_matrix_init(&shell->benchmark.transform.matrix);
+ weston_matrix_translate(&shell->benchmark.transform.matrix,
+ dx, dy, 0.0);
+ weston_surface_geometry_dirty(surface);
+
+ weston_compositor_schedule_repaint(shell->compositor);
+}
+
+static void
+benchmark_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
+ void *data)
+{
+ struct desktop_shell *shell = data;
+ struct weston_compositor *compositor = shell->compositor;
+ struct weston_output *output;
+ struct weston_surface *surface;
+
+ output = get_default_output(compositor);
+ if (!output)
+ return;
+
+ if (shell->benchmark.surface == NULL) {
+ weston_log("Benchmark mode started\n");
+ weston_output_enable_benchmark(output);
+ surface = weston_surface_create(compositor);
+ if (surface == NULL) {
+ return;
+ }
+
+ surface->output = output;
+ weston_surface_configure(surface, 0, 0, 100, 100);
+ weston_surface_set_color(surface, 0.6, 0.2, 0.2, 1.0);
+ pixman_region32_fini(&surface->opaque);
+ pixman_region32_init_rect(&surface->opaque, 0, 0, 100, 100);
+ pixman_region32_fini(&surface->input);
+ pixman_region32_init(&surface->input);
+
+ shell->benchmark.surface = surface;
+ shell->benchmark.anim_timestamp = 0;
+ shell->benchmark.animation.frame = benchmark_animation_frame;
+
+ wl_list_insert(&shell->panel_layer.link,
+ &shell->benchmark.layer.link);
+ wl_list_insert(&shell->benchmark.layer.surface_list,
+ &surface->layer_link);
+ wl_list_insert(&output->animation_list,
+ &shell->benchmark.animation.link);
+
+ weston_compositor_schedule_repaint(compositor);
+ } else {
+ weston_log("Benchmark mode stopped\n");
+ weston_output_disable_benchmark(output);
+ surface = shell->benchmark.surface;
+ wl_list_remove(&shell->benchmark.animation.link);
+ wl_list_remove(&shell->benchmark.layer.link);
+ wl_list_remove(&shell->benchmark.transform.link);
+ wl_list_init(&shell->benchmark.transform.link);
+ weston_surface_destroy(surface);
+ shell->benchmark.surface = NULL;
+ }
+}
+
struct debug_binding_grab {
struct weston_keyboard_grab grab;
struct weston_seat *seat;
@@ -4628,6 +4745,8 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
/* Debug bindings */
weston_compositor_add_key_binding(ec, KEY_SPACE, mod | MODIFIER_SHIFT,
debug_binding, shell);
+ weston_compositor_add_debug_binding(ec, KEY_B,
+ benchmark_binding, shell);
}
WL_EXPORT int
@@ -4676,6 +4795,7 @@ module_init(struct weston_compositor *ec,
weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
weston_layer_init(&shell->lock_layer, NULL);
weston_layer_init(&shell->input_panel_layer, NULL);
+ weston_layer_init(&shell->benchmark.layer, NULL);
wl_array_init(&shell->workspaces.array);
wl_list_init(&shell->workspaces.client_list);
@@ -4693,6 +4813,7 @@ module_init(struct weston_compositor *ec,
}
activate_workspace(shell, 0);
+ wl_list_init(&shell->benchmark.transform.link);
wl_list_init(&shell->workspaces.anim_sticky_list);
wl_list_init(&shell->workspaces.animation.link);
shell->workspaces.animation.frame = animate_workspace_change_frame;
--
1.8.3.1
More information about the wayland-devel
mailing list