gallium/util: remove pipe_static_mutex()
[mesa.git] / src / gallium / auxiliary / hud / hud_context.c
index 779c11693c807a6ec5ee14ef3ae1d46007bec9f8..c44f8c01a31fd404288c34c09833ce0116bd8abf 100644 (file)
@@ -60,7 +60,6 @@ static boolean huds_visible = TRUE;
 struct hud_context {
    struct pipe_context *pipe;
    struct cso_context *cso;
-   struct u_upload_mgr *uploader;
 
    struct hud_batch_query_context *batch_query;
    struct list_head pane_list;
@@ -98,7 +97,8 @@ struct hud_context {
       struct pipe_vertex_buffer vbuf;
       unsigned max_num_vertices;
       unsigned num_vertices;
-   } text, bg, whitelines;
+      unsigned buffer_size;
+   } text, bg, whitelines, color_prims;
 
    bool has_srgb;
 };
@@ -118,7 +118,10 @@ hud_draw_colored_prims(struct hud_context *hud, unsigned prim,
                        int xoffset, int yoffset, float yscale)
 {
    struct cso_context *cso = hud->cso;
-   struct pipe_vertex_buffer vbuffer = {0};
+   unsigned size = num_vertices * hud->color_prims.vbuf.stride;
+
+   assert(size <= hud->color_prims.buffer_size);
+   memcpy(hud->color_prims.vertices, buffer, size);
 
    hud->constants.color[0] = r;
    hud->constants.color[1] = g;
@@ -130,13 +133,14 @@ hud_draw_colored_prims(struct hud_context *hud, unsigned prim,
    hud->constants.scale[1] = yscale;
    cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf);
 
-   vbuffer.user_buffer = buffer;
-   vbuffer.stride = 2 * sizeof(float);
-
    cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso),
-                          1, &vbuffer);
+                          1, &hud->color_prims.vbuf);
    cso_set_fragment_shader_handle(hud->cso, hud->fs_color);
    cso_draw_arrays(cso, prim, 0, num_vertices);
+
+   hud->color_prims.vertices += size / sizeof(float);
+   hud->color_prims.vbuf.buffer_offset += size;
+   hud->color_prims.buffer_size -= size;
 }
 
 static void
@@ -457,15 +461,13 @@ hud_pane_draw_colored_objects(struct hud_context *hud,
 }
 
 static void
-hud_alloc_vertices(struct hud_context *hud, struct vertex_queue *v,
-                   unsigned num_vertices, unsigned stride)
+hud_prepare_vertices(struct hud_context *hud, struct vertex_queue *v,
+                     unsigned num_vertices, unsigned stride)
 {
    v->num_vertices = 0;
    v->max_num_vertices = num_vertices;
    v->vbuf.stride = stride;
-   u_upload_alloc(hud->uploader, 0, v->vbuf.stride * v->max_num_vertices,
-                  16, &v->vbuf.buffer_offset, &v->vbuf.buffer,
-                  (void**)&v->vertices);
+   v->buffer_size = stride * num_vertices;
 }
 
 /**
@@ -483,7 +485,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
    const struct pipe_sampler_state *sampler_states[] =
          { &hud->font_sampler_state };
    struct hud_pane *pane;
-   struct hud_graph *gr;
+   struct hud_graph *gr, *next;
 
    if (!huds_visible)
       return;
@@ -564,9 +566,39 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
    cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf);
 
    /* prepare vertex buffers */
-   hud_alloc_vertices(hud, &hud->bg, 4 * 256, 2 * sizeof(float));
-   hud_alloc_vertices(hud, &hud->whitelines, 4 * 256, 2 * sizeof(float));
-   hud_alloc_vertices(hud, &hud->text, 4 * 1024, 4 * sizeof(float));
+   hud_prepare_vertices(hud, &hud->bg, 16 * 256, 2 * sizeof(float));
+   hud_prepare_vertices(hud, &hud->whitelines, 4 * 256, 2 * sizeof(float));
+   hud_prepare_vertices(hud, &hud->text, 16 * 1024, 4 * sizeof(float));
+   hud_prepare_vertices(hud, &hud->color_prims, 32 * 1024, 2 * sizeof(float));
+
+   /* Allocate everything once and divide the storage into 3 portions
+    * manually, because u_upload_alloc can unmap memory from previous calls.
+    */
+   u_upload_alloc(hud->pipe->stream_uploader, 0,
+                  hud->bg.buffer_size +
+                  hud->whitelines.buffer_size +
+                  hud->text.buffer_size +
+                  hud->color_prims.buffer_size,
+                  16, &hud->bg.vbuf.buffer_offset, &hud->bg.vbuf.buffer,
+                  (void**)&hud->bg.vertices);
+   pipe_resource_reference(&hud->whitelines.vbuf.buffer, hud->bg.vbuf.buffer);
+   pipe_resource_reference(&hud->text.vbuf.buffer, hud->bg.vbuf.buffer);
+   pipe_resource_reference(&hud->color_prims.vbuf.buffer, hud->bg.vbuf.buffer);
+
+   hud->whitelines.vbuf.buffer_offset = hud->bg.vbuf.buffer_offset +
+                                        hud->bg.buffer_size;
+   hud->whitelines.vertices = hud->bg.vertices +
+                              hud->bg.buffer_size / sizeof(float);
+
+   hud->text.vbuf.buffer_offset = hud->whitelines.vbuf.buffer_offset +
+                                  hud->whitelines.buffer_size;
+   hud->text.vertices = hud->whitelines.vertices +
+                        hud->whitelines.buffer_size / sizeof(float);
+
+   hud->color_prims.vbuf.buffer_offset = hud->text.vbuf.buffer_offset +
+                                         hud->text.buffer_size;
+   hud->color_prims.vertices = hud->text.vertices +
+                               hud->text.buffer_size / sizeof(float);
 
    /* prepare all graphs */
    hud_batch_query_update(hud->batch_query);
@@ -576,11 +608,28 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
          gr->query_new_value(gr);
       }
 
+      if (pane->sort_items) {
+         LIST_FOR_EACH_ENTRY_SAFE(gr, next, &pane->graph_list, head) {
+            /* ignore the last one */
+            if (&gr->head == pane->graph_list.prev)
+               continue;
+
+            /* This is an incremental bubble sort, because we only do one pass
+             * per frame. It will eventually reach an equilibrium.
+             */
+            if (gr->current_value <
+                LIST_ENTRY(struct hud_graph, next, head)->current_value) {
+               LIST_DEL(&gr->head);
+               LIST_ADD(&gr->head, &next->head);
+            }
+         }
+      }
+
       hud_pane_accumulate_vertices(hud, pane);
    }
 
    /* unmap the uploader's vertex buffer before drawing */
-   u_upload_unmap(hud->uploader);
+   u_upload_unmap(pipe->stream_uploader);
 
    /* draw accumulated vertices for background quads */
    cso_set_blend(cso, &hud->alpha_blend);
@@ -645,6 +694,16 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
    cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
 
    pipe_surface_reference(&surf, NULL);
+
+   /* Start queries. */
+   hud_batch_query_begin(hud->batch_query);
+
+   LIST_FOR_EACH_ENTRY(pane, &hud->pane_list, head) {
+      LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) {
+         if (gr->begin_query)
+            gr->begin_query(gr);
+      }
+   }
 }
 
 static void
@@ -672,9 +731,10 @@ hud_pane_set_max_value(struct hud_pane *pane, uint64_t value)
     * hard-to-read numbers like 1.753.
     */
 
-   /* Find the left-most digit. */
+   /* Find the left-most digit. Make sure exp10 * 10 and fixup_bytes doesn't
+    * overflow. (11 is safe) */
    exp10 = 1;
-   for (i = 0; value > 9 * exp10; i++) {
+   for (i = 0; exp10 <= UINT64_MAX / 11 && exp10 * 9 < value; i++) {
       exp10 *= 10;
       fixup_bytes(pane->type, i + 1, &exp10);
    }
@@ -761,7 +821,7 @@ hud_pane_update_dyn_ceiling(struct hud_graph *gr, struct hud_pane *pane)
 static struct hud_pane *
 hud_pane_create(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
                 unsigned period, uint64_t max_value, uint64_t ceiling,
-                boolean dyn_ceiling)
+                boolean dyn_ceiling, boolean sort_items)
 {
    struct hud_pane *pane = CALLOC_STRUCT(hud_pane);
 
@@ -783,12 +843,24 @@ hud_pane_create(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
    pane->ceiling = ceiling;
    pane->dyn_ceiling = dyn_ceiling;
    pane->dyn_ceil_last_ran = 0;
+   pane->sort_items = sort_items;
    pane->initial_max_value = max_value;
    hud_pane_set_max_value(pane, max_value);
    LIST_INITHEAD(&pane->graph_list);
    return pane;
 }
 
+/* replace '-' with a space */
+static void
+strip_hyphens(char *s)
+{
+   while (*s) {
+      if (*s == '-')
+         *s = ' ';
+      s++;
+   }
+}
+
 /**
  * Add a graph to an existing pane.
  * One pane can contain multiple graphs over each other.
@@ -802,26 +874,29 @@ hud_pane_add_graph(struct hud_pane *pane, struct hud_graph *gr)
       {0, 1, 1},
       {1, 0, 1},
       {1, 1, 0},
-      {0.5, 0.5, 1},
-      {0.5, 0.5, 0.5},
+      {0.5, 1, 0.5},
+      {1, 0.5, 0.5},
+      {0.5, 1, 1},
+      {1, 0.5, 1},
+      {1, 1, 0.5},
+      {0, 0.5, 0},
+      {0.5, 0, 0},
+      {0, 0.5, 0.5},
+      {0.5, 0, 0.5},
+      {0.5, 0.5, 0},
    };
-   char *name = gr->name;
+   unsigned color = pane->next_color % ARRAY_SIZE(colors);
 
-   /* replace '-' with a space */
-   while (*name) {
-      if (*name == '-')
-         *name = ' ';
-      name++;
-   }
+   strip_hyphens(gr->name);
 
-   assert(pane->num_graphs < ARRAY_SIZE(colors));
    gr->vertices = MALLOC(pane->max_num_vertices * sizeof(float) * 2);
-   gr->color[0] = colors[pane->num_graphs][0];
-   gr->color[1] = colors[pane->num_graphs][1];
-   gr->color[2] = colors[pane->num_graphs][2];
+   gr->color[0] = colors[color][0];
+   gr->color[1] = colors[color][1];
+   gr->color[2] = colors[color][2];
    gr->pane = pane;
    LIST_ADDTAIL(&gr->head, &pane->graph_list);
    pane->num_graphs++;
+   pane->next_color++;
 }
 
 void
@@ -865,21 +940,37 @@ hud_graph_destroy(struct hud_graph *graph)
    FREE(graph);
 }
 
-void
+static void strcat_without_spaces(char *dst, const char *src)
+{
+   dst += strlen(dst);
+   while (*src) {
+      if (*src == ' ')
+         *dst++ = '_';
+      else
+         *dst++ = *src;
+      src++;
+   }
+   *dst = 0;
+}
+
+static void
 hud_graph_set_dump_file(struct hud_graph *gr)
 {
+#ifndef PIPE_OS_WINDOWS
    const char *hud_dump_dir = getenv("GALLIUM_HUD_DUMP_DIR");
    char *dump_file;
 
    if (hud_dump_dir && access(hud_dump_dir, W_OK) == 0) {
-      dump_file = malloc(strlen(hud_dump_dir) + sizeof(gr->name));
+      dump_file = malloc(strlen(hud_dump_dir) + sizeof("/") + sizeof(gr->name));
       if (dump_file) {
          strcpy(dump_file, hud_dump_dir);
-         strcat(dump_file, gr->name);
+         strcat(dump_file, "/");
+         strcat_without_spaces(dump_file, gr->name);
          gr->fd = fopen(dump_file, "w+");
          free(dump_file);
       }
    }
+#endif
 }
 
 /**
@@ -892,7 +983,7 @@ parse_string(const char *s, char *out)
 {
    int i;
 
-   for (i = 0; *s && *s != '+' && *s != ',' && *s != ':' && *s != ';';
+   for (i = 0; *s && *s != '+' && *s != ',' && *s != ':' && *s != ';' && *s != '=';
         s++, out++, i++)
       *out = *s;
 
@@ -910,7 +1001,8 @@ parse_string(const char *s, char *out)
 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)
+               uint64_t * const ceiling, boolean * const dyn_ceiling,
+               boolean *reset_colors, boolean *sort_items)
 {
    char *ret = str;
    unsigned tmp;
@@ -961,6 +1053,18 @@ read_pane_settings(char *str, unsigned * const x, unsigned * const y,
          *dyn_ceiling = true;
          break;
 
+      case 'r':
+         ++str;
+         ret = str;
+         *reset_colors = true;
+         break;
+
+      case 's':
+         ++str;
+         ret = str;
+         *sort_items = true;
+         break;
+
       default:
          fprintf(stderr, "gallium_hud: syntax error: unexpected '%c'\n", *str);
          fflush(stderr);
@@ -1002,6 +1106,8 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
    uint64_t ceiling = UINT64_MAX;
    unsigned column_width = 251;
    boolean dyn_ceiling = false;
+   boolean reset_colors = false;
+   boolean sort_items = false;
    const char *period_env;
 
    /*
@@ -1022,7 +1128,7 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
 
       /* check for explicit location, size and etc. settings */
       name = read_pane_settings(name_a, &x, &y, &width, &height, &ceiling,
-                         &dyn_ceiling);
+                                &dyn_ceiling, &reset_colors, &sort_items);
 
      /*
       * Keep track of overall column width to avoid pane overlapping in case
@@ -1033,11 +1139,16 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
 
       if (!pane) {
          pane = hud_pane_create(x, y, x + width, y + height, period, 10,
-                         ceiling, dyn_ceiling);
+                         ceiling, dyn_ceiling, sort_items);
          if (!pane)
             return;
       }
 
+      if (reset_colors) {
+         pane->next_color = 0;
+         reset_colors = false;
+      }
+
       /* Add a graph. */
 #if HAVE_GALLIUM_EXTRA_HUD || HAVE_LIBSENSORS
       char arg_name[64];
@@ -1052,6 +1163,9 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
       else if (sscanf(name, "cpu%u%s", &i, s) == 1) {
          hud_cpu_graph_install(pane, i);
       }
+      else if (strcmp(name, "API-thread-busy") == 0) {
+         hud_api_thread_busy_install(pane);
+      }
 #if HAVE_GALLIUM_EXTRA_HUD
       else if (sscanf(name, "nic-rx-%s", arg_name) == 1) {
          hud_nic_graph_install(pane, arg_name, NIC_DIRECTION_RX);
@@ -1190,11 +1304,33 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
          }
          else {
             fprintf(stderr, "gallium_hud: syntax error: unexpected '%c' (%i) "
-                    "after ':'\n", *env, *env);
+                            "after ':'\n", *env, *env);
             fflush(stderr);
          }
       }
 
+      if (*env == '=') {
+         env++;
+
+         if (!pane) {
+            fprintf(stderr, "gallium_hud: syntax error: unexpected '=', "
+                    "expected a name\n");
+            fflush(stderr);
+            break;
+         }
+
+         num = parse_string(env, s);
+         env += num;
+
+         strip_hyphens(s);
+         if (!LIST_IS_EMPTY(&pane->graph_list)) {
+            struct hud_graph *graph;
+            graph = LIST_ENTRY(struct hud_graph, pane->graph_list.prev, head);
+            strncpy(graph->name, s, sizeof(graph->name)-1);
+            graph->name[sizeof(graph->name)-1] = 0;
+         }
+      }
+
       if (*env == 0)
          break;
 
@@ -1242,6 +1378,7 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
       width = 251;
       ceiling = UINT64_MAX;
       dyn_ceiling = false;
+      sort_items = false;
 
    }
 
@@ -1253,6 +1390,14 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
          FREE(pane);
       }
    }
+
+   LIST_FOR_EACH_ENTRY(pane, &hud->pane_list, head) {
+      struct hud_graph *gr;
+
+      LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) {
+         hud_graph_set_dump_file(gr);
+      }
+   }
 }
 
 static void
@@ -1271,6 +1416,8 @@ print_help(struct pipe_screen *screen)
    puts("             for the given pane.");
    puts("  ',' creates a new pane below the last one.");
    puts("  ';' creates a new pane at the top of the next column.");
+   puts("  '=' followed by a string, changes the name of the last data source");
+   puts("      to that string");
    puts("");
    puts("  Example: GALLIUM_HUD=\"cpu,fps;primitives-generated\"");
    puts("");
@@ -1291,6 +1438,8 @@ print_help(struct pipe_screen *screen)
    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("  'r' resets the color counter (the next color will be green)");
+   puts("  's' sort items below graphs in descending order");
    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");
@@ -1384,12 +1533,9 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso)
 
    hud->pipe = pipe;
    hud->cso = cso;
-   hud->uploader = u_upload_create(pipe, 256 * 1024,
-                                   PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM);
 
    /* font */
    if (!util_font_create(pipe, UTIL_FONT_FIXED_8X13, &hud->font)) {
-      u_upload_destroy(hud->uploader);
       FREE(hud);
       return NULL;
    }
@@ -1439,7 +1585,6 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso)
       if (!tgsi_text_translate(fragment_shader_text, tokens, ARRAY_SIZE(tokens))) {
          assert(0);
          pipe_resource_reference(&hud->font.texture, NULL);
-         u_upload_destroy(hud->uploader);
          FREE(hud);
          return NULL;
       }
@@ -1488,7 +1633,6 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso)
       if (!tgsi_text_translate(vertex_shader_text, tokens, ARRAY_SIZE(tokens))) {
          assert(0);
          pipe_resource_reference(&hud->font.texture, NULL);
-         u_upload_destroy(hud->uploader);
          FREE(hud);
          return NULL;
       }
@@ -1563,6 +1707,5 @@ hud_destroy(struct hud_context *hud)
    pipe->delete_vs_state(pipe, hud->vs);
    pipe_sampler_view_reference(&hud->font_sampler_view, NULL);
    pipe_resource_reference(&hud->font.texture, NULL);
-   u_upload_destroy(hud->uploader);
    FREE(hud);
 }