From: Louis-Francis Ratté-Boulianne <l...@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

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to