[Mesa-dev] [PATCH] gallium/hud: add more options to customize HUD panes

Gediminas Jakutis gediminas at varciai.lt
Thu Apr 9 16:05:55 PDT 2015


Extends the syntax of GALLIUM_HUD environment variable to:
Add options to set the size and exact location of each pane.
Add an option to limit the maximum allowed value of the X axis
on a pane, clamping down the graph to not go above this value.
Add an option to, on set short intervals, auto-adjust the value
of the Y axis down to match the highest value in still visible
on the graph at the given moment.
Syntax extensions maintains full compatibility with the existing
GALLIUM_HUD environment variable syntax.
---
 src/gallium/auxiliary/hud/hud_context.c | 184 ++++++++++++++++++++++++++++++--
 src/gallium/auxiliary/hud/hud_private.h |   7 ++
 2 files changed, 185 insertions(+), 6 deletions(-)

diff --git a/src/gallium/auxiliary/hud/hud_context.c b/src/gallium/auxiliary/hud/hud_context.c
index e46c68c..731a3c7 100644
--- a/src/gallium/auxiliary/hud/hud_context.c
+++ b/src/gallium/auxiliary/hud/hud_context.c
@@ -569,11 +569,56 @@ hud_pane_set_max_value(struct hud_pane *pane, uint64_t value)
    pane->yscale = -(int)pane->inner_height / (float)pane->max_value;
 }
 
+static void
+hud_pane_update_dyn_ceiling(struct hud_graph *gr, struct hud_pane *pane,
+                            uint64_t value)
+{
+   unsigned i;
+   uint64_t max;
+
+   pane->dyn_ceil_current_max = value > pane->dyn_ceil_current_max ?
+                                value : pane->dyn_ceil_current_max;
+
+   /* Avoid updating more than once per panel change. */
+   if (pane->dyn_ceil_last_ran == gr->index) {
+      return;
+   }
+
+   /*
+    * When dynamic ceiling is enabled, perform readjustment once every time
+    * a fifth of a panel worth of graph passes. Avoid using floating point
+    * arithmetic due to expensive integer <-> float conversions.
+    */
+   if (pane->dyn_ceiling == true &&
+      (gr->index == pane->max_num_vertices / 5 ||     /* 1/5 of the panel */
+       gr->index == pane->max_num_vertices / 5 * 2 || /* 2/5 of the panel */
+       gr->index == pane->max_num_vertices / 5 * 3 || /* 3/5 of the panel */
+       gr->index == pane->max_num_vertices / 5 * 4 || /* 4/5 of the panel */
+       gr->index == pane->max_num_vertices)) {        /* whole panel */
+
+       max = pane->dyn_ceil_current_max;
+       for (i = 0; i < 4; ++i) {
+          max = pane->dyn_ceil_max[i] > max ?
+                pane->dyn_ceil_max[i] : max;
+       }
+       /* Prevent going lower than the initial panel Y axis. */
+       max = max > pane->initial_max_value ? max : pane->initial_max_value;
+       hud_pane_set_max_value(pane, max);
+       pane->dyn_ceil_max[pane->dyn_ceil_index] = pane->dyn_ceil_current_max;
+       pane->dyn_ceil_current_max = 0;
+       pane->dyn_ceil_index = pane->dyn_ceil_index != 3 ?
+                              pane->dyn_ceil_index + 1 : 0;
+       pane->dyn_ceil_last_ran = gr->index;
+   }
+}
+
 static struct hud_pane *
 hud_pane_create(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
-                unsigned period, uint64_t max_value)
+                unsigned period, uint64_t max_value, uint64_t ceiling,
+                boolean dyn_ceiling)
 {
    struct hud_pane *pane = CALLOC_STRUCT(hud_pane);
+   unsigned i;
 
    if (!pane)
       return NULL;
@@ -590,6 +635,15 @@ hud_pane_create(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
    pane->inner_height = pane->inner_y2 - pane->inner_y1;
    pane->period = period;
    pane->max_num_vertices = (x2 - x1 + 2) / 2;
+   pane->ceiling = ceiling;
+   pane->dyn_ceiling = dyn_ceiling;
+   pane->dyn_ceil_index = 0;
+   pane->dyn_ceil_current_max = 0;
+   pane->dyn_ceil_last_ran = 0;
+   pane->initial_max_value = 10;
+   for (i = 0; i < 4; ++i) {
+      pane->dyn_ceil_max[i] = 0;
+   }
    hud_pane_set_max_value(pane, max_value);
    LIST_INITHEAD(&pane->graph_list);
    return pane;
@@ -633,6 +687,10 @@ hud_pane_add_graph(struct hud_pane *pane, struct hud_graph *gr)
 void
 hud_graph_add_value(struct hud_graph *gr, uint64_t value)
 {
+   gr->current_value = value;
+   value = value > gr->pane->ceiling ? gr->pane->ceiling : value;
+   hud_pane_update_dyn_ceiling(gr, gr->pane, value);
+
    if (gr->index == gr->pane->max_num_vertices) {
       gr->vertices[0] = 0;
       gr->vertices[1] = gr->vertices[(gr->index-1)*2+1];
@@ -646,7 +704,6 @@ hud_graph_add_value(struct hud_graph *gr, uint64_t value)
       gr->num_vertices++;
    }
 
-   gr->current_value = value;
    if (value > gr->pane->max_value) {
       hud_pane_set_max_value(gr->pane, value);
    }
@@ -683,6 +740,70 @@ parse_string(const char *s, char *out)
    return i;
 }
 
+static char *
+read_pane_settings(char *str, unsigned * const x, unsigned * const y,
+               unsigned * const width, unsigned * const height,
+               uint64_t * const ceiling, boolean * const dyn_ceiling)
+{
+   char *ret = str;
+   unsigned tmp;
+
+   while (*str == '.') {
+      ++str;
+      switch (*str) {
+      case 'x':
+         ++str;
+         *x = strtoul(str, &ret, 10);
+         str = ret;
+         break;
+
+      case 'y':
+         ++str;
+         *y = strtoul(str, &ret, 10);
+         str = ret;
+         break;
+
+      case 'w':
+         ++str;
+         tmp = strtoul(str, &ret, 10);
+         *width = tmp > 80 ? tmp : 80; /* 80 is chosen arbitrarily */
+         str = ret;
+         break;
+
+      /*
+       * Prevent setting height to less than 50.
+       * If the height is set to less, the text of the Y axis labels
+       * on the graph will start overlapping.
+       */
+      case 'h':
+         ++str;
+         tmp = strtoul(str, &ret, 10);
+         *height = tmp > 50 ? tmp : 50;
+         str = ret;
+         break;
+
+      case 'c':
+         ++str;
+         tmp = strtoul(str, &ret, 10);
+         *ceiling = tmp > 10 ? tmp : 10;
+         str = ret;
+         break;
+
+      case 'd':
+         ++str;
+         ret = str;
+         *dyn_ceiling = true;
+         break;
+
+      default:
+         fprintf(stderr, "gallium_hud: syntax error: unexpected '%c'\n", *str);
+      }
+
+   }
+
+   return ret;
+}
+
 static boolean
 has_occlusion_query(struct pipe_screen *screen)
 {
@@ -705,11 +826,15 @@ static void
 hud_parse_env_var(struct hud_context *hud, const char *env)
 {
    unsigned num, i;
-   char name[256], s[256];
+   char name_a[256], s[256];
+   char *name;
    struct hud_pane *pane = NULL;
    unsigned x = 10, y = 10;
    unsigned width = 251, height = 100;
    unsigned period = 500 * 1000;  /* default period (1/2 second) */
+   uint64_t ceiling = UINT64_MAX;
+   unsigned column_width = 251;
+   boolean dyn_ceiling = false;
    const char *period_env;
 
    /*
@@ -725,11 +850,23 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
       }
    }
 
-   while ((num = parse_string(env, name)) != 0) {
+   while ((num = parse_string(env, name_a)) != 0) {
       env += num;
 
+      /* check for explicit location, size and etc. settings */
+      name = read_pane_settings(name_a, &x, &y, &width, &height, &ceiling,
+                         &dyn_ceiling);
+
+     /*
+      * Keep track of over column width to avoid pane overlapping in case
+      * later we create a new column  while the bottom pane in the current
+      * column is less wide than the rest of the panes in it.
+      */
+     column_width = width > column_width ? width : column_width;
+
       if (!pane) {
-         pane = hud_pane_create(x, y, x + width, y + height, period, 10);
+         pane = hud_pane_create(x, y, x + width, y + height, period, 10,
+                         ceiling, dyn_ceiling);
          if (!pane)
             return;
       }
@@ -807,6 +944,7 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
 
          if (num && sscanf(s, "%u", &i) == 1) {
             hud_pane_set_max_value(pane, i);
+            pane->initial_max_value = i;
          }
          else {
             fprintf(stderr, "gallium_hud: syntax error: unexpected '%c' (%i) "
@@ -836,17 +974,27 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
       case ';':
          env++;
          y = 10;
-         x += width + hud->font.glyph_width * 7;
+         x += column_width + hud->font.glyph_width * 7;
 
          if (pane && pane->num_graphs) {
             LIST_ADDTAIL(&pane->head, &hud->pane_list);
             pane = NULL;
          }
+
+         /* Starting a new column; reset column width. */
+         column_width = 251;
          break;
 
       default:
          fprintf(stderr, "gallium_hud: syntax error: unexpected '%c'\n", *env);
       }
+
+      /* Reset to defaults for the next pane in case these were modified. */
+      width = 251;
+      height = 100;
+      ceiling = UINT64_MAX;
+      dyn_ceiling = false;
+
    }
 
    if (pane) {
@@ -878,6 +1026,30 @@ print_help(struct pipe_screen *screen)
    puts("");
    puts("  Example: GALLIUM_HUD=\"cpu,fps;primitives-generated\"");
    puts("");
+   puts("  Additionally, by prepending '.[identifier][value]' modifiers to");
+   puts("  a name, it is possible to explicitly set the location and size");
+   puts("  of a pane, along with limiting overall maximum value of the");
+   puts("  Y axis and activating dynamic readjustment of the Y axis.");
+   puts("  Several modifiers may be applied to the same pane simultaneously.");
+   puts("");
+   puts("  'x[value]' sets the location of the pane on the x axis relative");
+   puts("             to the upper-left corner of the viewport, in pixels.");
+   puts("  'y[value]' sets the location of the pane on the y axis relative");
+   puts("             to the upper-left corner of the viewport, in pixels.");
+   puts("  'w[value]' sets width of the graph pixels.");
+   puts("  'h[value]' sets height of the graph in pixels.");
+   puts("  'c[value]' sets the ceiling of the value of the Y axis.");
+   puts("             If the graph needs to draw values higher than");
+   puts("             the ceiling allows, the value is clamped.");
+   puts("  'd' activates dynamic Y axis readjustment to set the value of");
+   puts("      the Y axis to match the highest value still visible in the graph.");
+   puts("");
+   puts("  If 'c' and 'd' modifiers are used simultaneously, both are in effect:");
+   puts("  the Y axis does not go above the restriction imposed by 'c' while");
+   puts("  still adjusting the value of the Y axis down when appropriate.");
+   puts("");
+   puts("  Example: GALLIUM_HUD=\".w256.h64.x1600.y520.d.c1000fps+cpu,.datom-count\"");
+   puts("");
    puts("  Available names:");
    puts("    fps");
    puts("    cpu");
diff --git a/src/gallium/auxiliary/hud/hud_private.h b/src/gallium/auxiliary/hud/hud_private.h
index 1606ada..eb5bf0f 100644
--- a/src/gallium/auxiliary/hud/hud_private.h
+++ b/src/gallium/auxiliary/hud/hud_private.h
@@ -62,6 +62,13 @@ struct hud_pane {
    float yscale;
    unsigned max_num_vertices;
    uint64_t max_value;
+   uint64_t initial_max_value;
+   uint64_t ceiling;
+   unsigned dyn_ceil_index;
+   unsigned dyn_ceil_last_ran;
+   uint64_t dyn_ceil_max[4];
+   uint64_t dyn_ceil_current_max;
+   boolean dyn_ceiling;
    boolean uses_byte_units;
    uint64_t period; /* in microseconds */
 
-- 
2.3.5



More information about the mesa-dev mailing list