From: Louis-Francis RatteĢ-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