[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