i965: Rework the modifier info map
[mesa.git] / src / gallium / auxiliary / hud / hud_context.c
index 6caf821e6d6e7f530c4290aafeb3108d76bcf811..2deb48d18e7609ec8f72a4bebfc0a72921d183d1 100644 (file)
@@ -39,7 +39,6 @@
 
 #include "hud/hud_context.h"
 #include "hud/hud_private.h"
-#include "hud/font.h"
 
 #include "cso_cache/cso_context.h"
 #include "util/u_draw_quad.h"
 /* Control the visibility of all HUD contexts */
 static boolean huds_visible = TRUE;
 
-struct hud_context {
-   struct pipe_context *pipe;
-   struct cso_context *cso;
-
-   struct hud_batch_query_context *batch_query;
-   struct list_head pane_list;
-
-   /* states */
-   struct pipe_blend_state no_blend, alpha_blend;
-   struct pipe_depth_stencil_alpha_state dsa;
-   void *fs_color, *fs_text;
-   struct pipe_rasterizer_state rasterizer, rasterizer_aa_lines;
-   void *vs;
-   struct pipe_vertex_element velems[2];
-
-   /* font */
-   struct util_font font;
-   struct pipe_sampler_view *font_sampler_view;
-   struct pipe_sampler_state font_sampler_state;
-
-   /* VS constant buffer */
-   struct {
-      float color[4];
-      float two_div_fb_width;
-      float two_div_fb_height;
-      float translate[2];
-      float scale[2];
-      float padding[2];
-   } constants;
-   struct pipe_constant_buffer constbuf;
-
-   unsigned fb_width, fb_height;
-
-   /* vertices for text and background drawing are accumulated here and then
-    * drawn all at once */
-   struct vertex_queue {
-      float *vertices;
-      struct pipe_vertex_buffer vbuf;
-      unsigned max_num_vertices;
-      unsigned num_vertices;
-   } text, bg, whitelines;
-
-   bool has_srgb;
-};
 
 #ifdef PIPE_OS_UNIX
 static void
@@ -117,7 +72,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;
@@ -129,13 +87,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
@@ -245,7 +204,7 @@ hud_draw_string(struct hud_context *hud, unsigned x, unsigned y,
 }
 
 static void
-number_to_human_readable(uint64_t num, enum pipe_driver_query_type type,
+number_to_human_readable(double num, enum pipe_driver_query_type type,
                          char *out)
 {
    static const char *byte_units[] =
@@ -456,15 +415,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->pipe->stream_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;
 }
 
 /**
@@ -563,9 +520,43 @@ 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, 16 * 256, 2 * sizeof(float));
-   hud_alloc_vertices(hud, &hud->whitelines, 4 * 256, 2 * sizeof(float));
-   hud_alloc_vertices(hud, &hud->text, 16 * 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.resource,
+                  (void**)&hud->bg.vertices);
+   if (!hud->bg.vertices) {
+      goto out;
+   }
+
+   pipe_resource_reference(&hud->whitelines.vbuf.buffer.resource, hud->bg.vbuf.buffer.resource);
+   pipe_resource_reference(&hud->text.vbuf.buffer.resource, hud->bg.vbuf.buffer.resource);
+   pipe_resource_reference(&hud->color_prims.vbuf.buffer.resource, hud->bg.vbuf.buffer.resource);
+
+   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);
@@ -617,7 +608,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
                              &hud->bg.vbuf);
       cso_draw_arrays(cso, PIPE_PRIM_QUADS, 0, hud->bg.num_vertices);
    }
-   pipe_resource_reference(&hud->bg.vbuf.buffer, NULL);
+   pipe_resource_reference(&hud->bg.vbuf.buffer.resource, NULL);
 
    /* draw accumulated vertices for white lines */
    cso_set_blend(cso, &hud->no_blend);
@@ -638,7 +629,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
       cso_set_fragment_shader_handle(hud->cso, hud->fs_color);
       cso_draw_arrays(cso, PIPE_PRIM_LINES, 0, hud->whitelines.num_vertices);
    }
-   pipe_resource_reference(&hud->whitelines.vbuf.buffer, NULL);
+   pipe_resource_reference(&hud->whitelines.vbuf.buffer.resource, NULL);
 
    /* draw accumulated vertices for text */
    cso_set_blend(cso, &hud->alpha_blend);
@@ -648,7 +639,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
       cso_set_fragment_shader_handle(hud->cso, hud->fs_text);
       cso_draw_arrays(cso, PIPE_PRIM_QUADS, 0, hud->text.num_vertices);
    }
-   pipe_resource_reference(&hud->text.vbuf.buffer, NULL);
+   pipe_resource_reference(&hud->text.vbuf.buffer.resource, NULL);
 
    /* draw the rest */
    cso_set_rasterizer(cso, &hud->rasterizer_aa_lines);
@@ -657,6 +648,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
          hud_pane_draw_colored_objects(hud, pane);
    }
 
+out:
    cso_restore_state(cso);
    cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
 
@@ -698,9 +690,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);
    }
@@ -785,7 +778,8 @@ 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,
+hud_pane_create(struct hud_context *hud,
+                unsigned x1, unsigned y1, unsigned x2, unsigned y2,
                 unsigned period, uint64_t max_value, uint64_t ceiling,
                 boolean dyn_ceiling, boolean sort_items)
 {
@@ -794,6 +788,7 @@ hud_pane_create(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
    if (!pane)
       return NULL;
 
+   pane->hud = hud;
    pane->x1 = x1;
    pane->y1 = y1;
    pane->x2 = x2;
@@ -866,13 +861,19 @@ hud_pane_add_graph(struct hud_pane *pane, struct hud_graph *gr)
 }
 
 void
-hud_graph_add_value(struct hud_graph *gr, uint64_t value)
+hud_graph_add_value(struct hud_graph *gr, double value)
 {
    gr->current_value = value;
    value = value > gr->pane->ceiling ? gr->pane->ceiling : value;
 
-   if (gr->fd)
-      fprintf(gr->fd, "%" PRIu64 "\n", value);
+   if (gr->fd) {
+      if (fabs(value - lround(value)) > FLT_EPSILON) {
+         fprintf(gr->fd, "%f\n", value);
+      }
+      else {
+         fprintf(gr->fd, "%" PRIu64 "\n", (uint64_t) lround(value));
+      }
+   }
 
    if (gr->index == gr->pane->max_num_vertices) {
       gr->vertices[0] = 0;
@@ -906,24 +907,63 @@ 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;
+}
+
+
+#ifdef PIPE_OS_WINDOWS
+#define W_OK 0
+static int
+access(const char *pathname, int mode)
+{
+   /* no-op */
+   return 0;
+}
+
+#define PATH_SEP "\\"
+
+#else
+
+#define PATH_SEP "/"
+
+#endif
+
+
+/**
+ * If the GALLIUM_HUD_DUMP_DIR env var is set, we'll write the raw
+ * HUD values to files at ${GALLIUM_HUD_DUMP_DIR}/<stat> where <stat>
+ * is a HUD variable such as "fps", or "cpu"
+ */
+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("/") + sizeof(gr->name));
+      char *dump_file = malloc(strlen(hud_dump_dir) + sizeof(PATH_SEP)
+                               + sizeof(gr->name));
       if (dump_file) {
          strcpy(dump_file, hud_dump_dir);
-         strcat(dump_file, "/");
-         strcat(dump_file, gr->name);
+         strcat(dump_file, PATH_SEP);
+         strcat_without_spaces(dump_file, gr->name);
          gr->fd = fopen(dump_file, "w+");
+         if (gr->fd) {
+            /* flush output after each line is written */
+            setvbuf(gr->fd, NULL, _IOLBF, 0);
+         }
          free(dump_file);
       }
    }
-#endif
 }
 
 /**
@@ -1091,8 +1131,8 @@ hud_parse_env_var(struct hud_context *hud, const char *env)
      column_width = width > column_width ? width : column_width;
 
       if (!pane) {
-         pane = hud_pane_create(x, y, x + width, y + height, period, 10,
-                         ceiling, dyn_ceiling, sort_items);
+         pane = hud_pane_create(hud, x, y, x + width, y + height, period, 10,
+                                ceiling, dyn_ceiling, sort_items);
          if (!pane)
             return;
       }
@@ -1116,6 +1156,21 @@ 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_thread_busy_install(pane, name, false);
+      }
+      else if (strcmp(name, "API-thread-offloaded-slots") == 0) {
+         hud_thread_counter_install(pane, name, HUD_COUNTER_OFFLOADED);
+      }
+      else if (strcmp(name, "API-thread-direct-slots") == 0) {
+         hud_thread_counter_install(pane, name, HUD_COUNTER_DIRECT);
+      }
+      else if (strcmp(name, "API-thread-num-syncs") == 0) {
+         hud_thread_counter_install(pane, name, HUD_COUNTER_SYNCS);
+      }
+      else if (strcmp(name, "main-thread-busy") == 0) {
+         hud_thread_busy_install(pane, name, true);
+      }
 #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);
@@ -1340,6 +1395,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
@@ -1651,3 +1714,11 @@ hud_destroy(struct hud_context *hud)
    pipe_resource_reference(&hud->font.texture, NULL);
    FREE(hud);
 }
+
+void
+hud_add_queue_for_monitoring(struct hud_context *hud,
+                             struct util_queue_monitoring *queue_info)
+{
+   assert(!hud->monitored_queue);
+   hud->monitored_queue = queue_info;
+}