[mutter/gbsneto/charts: 3/4] Add frame time chart



commit fa30d7ce6431a71a5edd760244cadc656f4759b1
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Fri Mar 22 01:29:36 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 covers both layout time (green) and paint time (blue).
    
    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   |   4 ++
 clutter/clutter/clutter-stage.c           |   9 +++
 clutter/clutter/cogl/clutter-stage-cogl.c | 113 ++++++++++++++++++++++++++++++
 5 files changed, 128 insertions(+)
---
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..04c13ce04 100644
--- a/clutter/clutter/clutter-stage-private.h
+++ b/clutter/clutter/clutter-stage-private.h
@@ -134,6 +134,10 @@ void            _clutter_stage_presented                (ClutterStage      *stag
 
 GList *         _clutter_stage_peek_stage_views         (ClutterStage *stage);
 
+void            clutter_stage_get_frame_times           (ClutterStage *stage,
+                                                         double       *paint_time,
+                                                         double       *layout_time);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_STAGE_PRIVATE_H__ */
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 25ce9d899..98622c4a1 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -5091,3 +5091,12 @@ _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
   *view_scale = scale;
   return TRUE;
 }
+
+void
+clutter_stage_get_frame_times (ClutterStage *stage,
+                               double       *paint_time,
+                               double       *layout_time)
+{
+  *paint_time = stage->priv->last_paint_time;
+  *layout_time = stage->priv->last_layout_time;
+}
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
index e0c39185b..c6efbc080 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
@@ -405,6 +405,115 @@ 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 CoglPipeline *layout_time_pipeline = NULL;
+  static GArray *frame_times = NULL;
+  CoglMatrix modelview;
+  double paint_time;
+  double layout_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 (layout_time_pipeline == NULL))
+    {
+      layout_time_pipeline = cogl_pipeline_new (ctx);
+      cogl_pipeline_set_color4ub (layout_time_pipeline, 0x00, 0x60, 0x00, 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 times array composed by (paint_time, layout_time) pairs */
+  n_points = width / CHART_COLUMN_WIDTH;
+
+  if (G_UNLIKELY (frame_times == NULL))
+    frame_times = g_array_sized_new (FALSE, TRUE, sizeof (double), n_points * 2);
+
+  clutter_stage_get_frame_times (stage_cogl->wrapper, &paint_time, &layout_time);
+
+  g_array_append_val (frame_times, paint_time);
+  g_array_append_val (frame_times, layout_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 paint_time_entry = g_array_index (frame_times, double, element);
+      double layout_time_entry = g_array_index (frame_times, double, element + 1);
+      double refresh_rate_ms = 1000.0 / stage_cogl->refresh_rate;
+      double refresh_rate_bar_height = height * 0.1;
+      double x_1 = width - (i + 1) * CHART_COLUMN_WIDTH;
+      double x_2 = width - i * CHART_COLUMN_WIDTH;
+      double layout_bar_height;
+      double paint_bar_height;
+
+      /* Layout time section */
+      layout_bar_height =
+        layout_time_entry / refresh_rate_ms * refresh_rate_bar_height;
+      cogl_framebuffer_draw_rectangle (framebuffer,
+                                       layout_time_pipeline,
+                                       x_1,
+                                       height - layout_bar_height,
+                                       x_2,
+                                       height);
+
+      /* Paint time section */
+      paint_bar_height =
+        paint_time_entry / refresh_rate_ms * refresh_rate_bar_height;
+      cogl_framebuffer_draw_rectangle (framebuffer,
+                                       paint_time_pipeline,
+                                       x_1,
+                                       height - paint_bar_height - layout_bar_height,
+                                       x_2,
+                                       height - layout_bar_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 +536,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 +684,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]