[mutter/gbsneto/charts: 4/4] Add frame time chart
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/gbsneto/charts: 4/4] Add frame time chart
- Date: Thu, 21 Mar 2019 17:28:13 +0000 (UTC)
commit 920be4da7bc22139ff2bce948c5abb5a19e19705
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Thu Mar 21 17:01:08 2019 +0000
Add frame time chart
Add a chart at the bottom 10% of the screen where each
bar represents the time the frame took to be painted. The
red line represents the maximum time to draw. For example,
if you are on a 60Hz monitor, the red line means 16.6667
miliseconds.
This only covers paint time; it makes sense to augment this
chart with layout time as well.
Enjoy.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/502
clutter/clutter/clutter-main.c | 1 +
clutter/clutter/clutter-main.h | 1 +
clutter/clutter/clutter-stage-private.h | 2 +
clutter/clutter/clutter-stage.c | 11 +++-
clutter/clutter/cogl/clutter-stage-cogl.c | 89 +++++++++++++++++++++++++++++++
5 files changed, 103 insertions(+), 1 deletion(-)
---
diff --git a/clutter/clutter/clutter-main.c b/clutter/clutter/clutter-main.c
index 7616eaae0..cff072331 100644
--- a/clutter/clutter/clutter-main.c
+++ b/clutter/clutter/clutter-main.c
@@ -143,6 +143,7 @@ static const GDebugKey clutter_paint_debug_keys[] = {
{ "continuous-redraw", CLUTTER_DEBUG_CONTINUOUS_REDRAW },
{ "paint-deform-tiles", CLUTTER_DEBUG_PAINT_DEFORM_TILES },
{ "damage-region", CLUTTER_DEBUG_PAINT_DAMAGE_REGION },
+ { "frame-time", CLUTTER_DEBUG_PAINT_FRAME_TIME },
};
static void
diff --git a/clutter/clutter/clutter-main.h b/clutter/clutter/clutter-main.h
index e0f10c892..6846cef7a 100644
--- a/clutter/clutter/clutter-main.h
+++ b/clutter/clutter/clutter-main.h
@@ -74,6 +74,7 @@ typedef enum
CLUTTER_DEBUG_CONTINUOUS_REDRAW = 1 << 6,
CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 7,
CLUTTER_DEBUG_PAINT_DAMAGE_REGION = 1 << 8,
+ CLUTTER_DEBUG_PAINT_FRAME_TIME = 1 << 9,
} ClutterDrawDebugFlag;
/**
diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h
index 4799c29e1..b5357b26f 100644
--- a/clutter/clutter/clutter-stage-private.h
+++ b/clutter/clutter/clutter-stage-private.h
@@ -134,6 +134,8 @@ void _clutter_stage_presented (ClutterStage *stag
GList * _clutter_stage_peek_stage_views (ClutterStage *stage);
+double _clutter_stage_get_previous_frame_time (ClutterStage *stage);
+
G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 3440d19a0..8455917d3 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -146,6 +146,8 @@ struct _ClutterStagePrivate
int update_freeze_count;
+ double last_frame_time;
+
guint relayout_pending : 1;
guint redraw_pending : 1;
guint is_fullscreen : 1;
@@ -1123,7 +1125,8 @@ clutter_stage_do_redraw (ClutterStage *stage)
end = g_get_monotonic_time ();
- CLUTTER_NOTE (FRAME_TIME, "%lf", (end - start) / 1000.0);
+ priv->last_frame_time = (end - start) / 1000.0;
+ CLUTTER_NOTE (FRAME_TIME, "%lf", priv->last_frame_time);
CLUTTER_NOTE (PAINT, "Redraw finished for stage '%s'[%p]",
_clutter_actor_get_debug_name (actor),
@@ -5078,3 +5081,9 @@ _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
*view_scale = scale;
return TRUE;
}
+
+double
+_clutter_stage_get_previous_frame_time (ClutterStage *stage)
+{
+ return stage->priv->last_frame_time;
+}
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
index e0c39185b..86bf4bb45 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
@@ -405,6 +405,91 @@ paint_damage_region (ClutterStageWindow *stage_window,
cogl_framebuffer_pop_matrix (framebuffer);
}
+#define CHART_COLUMN_WIDTH 6 //px
+#define THRESHOLD_LINE_HEIGHT 2 //px
+
+static void
+paint_frame_time_chart (ClutterStageWindow *stage_window,
+ ClutterStageView *view)
+{
+ CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
+ CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+ ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
+ ClutterActor *actor = CLUTTER_ACTOR (stage_cogl->wrapper);
+ static CoglPipeline *threshold_pipeline = NULL;
+ static CoglPipeline *paint_time_pipeline = NULL;
+ static GArray *frame_times = NULL;
+ CoglMatrix modelview;
+ double frame_time;
+ float green_line_y;
+ int width, height;
+ int n_points;
+ int i;
+
+ if (G_UNLIKELY (paint_time_pipeline == NULL))
+ {
+ paint_time_pipeline = cogl_pipeline_new (ctx);
+ cogl_pipeline_set_color4ub (paint_time_pipeline, 0x00, 0x00, 0x60, 0xa0);
+ }
+
+ if (G_UNLIKELY (threshold_pipeline == NULL))
+ {
+ threshold_pipeline = cogl_pipeline_new (ctx);
+ cogl_pipeline_set_color4ub (threshold_pipeline, 0x40, 0x00, 0x00, 0x80);
+ }
+
+ cogl_framebuffer_push_matrix (framebuffer);
+ cogl_matrix_init_identity (&modelview);
+ _clutter_actor_apply_modelview_transform (actor, &modelview);
+ cogl_framebuffer_set_modelview_matrix (framebuffer, &modelview);
+
+ width = cogl_framebuffer_get_width (framebuffer);
+ height = cogl_framebuffer_get_height (framebuffer);
+
+ /* Frame time */
+ n_points = width / CHART_COLUMN_WIDTH;
+
+ if (G_UNLIKELY (frame_times == NULL))
+ frame_times = g_array_sized_new (FALSE, TRUE, sizeof (double), n_points);
+
+ frame_time = _clutter_stage_get_previous_frame_time (stage_cogl->wrapper);
+ g_array_append_val (frame_times, frame_time);
+
+ if (frame_times->len > n_points)
+ g_array_remove_range (frame_times, 0, frame_times->len - n_points);
+
+ /* Chart */
+ for (i = 0; i < MIN (frame_times->len, n_points); i++)
+ {
+ int element = frame_times->len - i - 1;
+ double refresh_rate_ms = 1000.0 / stage_cogl->refresh_rate;
+ double refresh_rate_height = height * 0.1;
+ double frame_time_entry = g_array_index (frame_times, double, element);
+ double bar_height =
+ frame_time_entry / refresh_rate_ms * refresh_rate_height;
+ double x_1 = width - (i + 1) * CHART_COLUMN_WIDTH;
+ double x_2 = width - i * CHART_COLUMN_WIDTH;
+
+ cogl_framebuffer_draw_rectangle (framebuffer,
+ paint_time_pipeline,
+ x_1,
+ height - bar_height,
+ x_2,
+ height);
+ }
+
+ /* Green line (16.667ms) */
+ green_line_y = height * 0.9;
+ cogl_framebuffer_draw_rectangle (framebuffer,
+ threshold_pipeline,
+ 0.0f,
+ green_line_y,
+ width,
+ green_line_y + THRESHOLD_LINE_HEIGHT);
+
+ cogl_framebuffer_pop_matrix (framebuffer);
+}
+
static gboolean
swap_framebuffer (ClutterStageWindow *stage_window,
ClutterStageView *view,
@@ -427,6 +512,9 @@ swap_framebuffer (ClutterStageWindow *stage_window,
if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)))
paint_damage_region (stage_window, view, swap_region);
+ if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_FRAME_TIME)))
+ paint_frame_time_chart (stage_window, view);
+
if (cogl_is_onscreen (framebuffer))
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
@@ -572,6 +660,7 @@ is_buffer_age_enabled (void)
/* Buffer age is disabled when running with CLUTTER_PAINT=damage-region,
* to ensure the red damage represents the currently damaged area */
return !(clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION) &&
+ !(clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_FRAME_TIME) &&
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]