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

Rob Clark robdclark at gmail.com
Thu Apr 9 16:37:26 PDT 2015


On Thu, Apr 9, 2015 at 7:05 PM, Gediminas Jakutis <gediminas at varciai.lt> wrote:
> 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.

jfwiw, I'd find an option to set max axis on Y axis (I assume this is
what you meant?) hugely useful..  some of the graphs that I use (like
# of batches/submits) get blown out of the water on the first few
frames while game is doing texture uploads, etc.  Or auto-adjusting
the scale on the Y axis back down would have the same result.

BR,
-R


> ---
>  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
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list