#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;
- unsigned buffer_size;
- } text, bg, whitelines, color_prims;
-
- bool has_srgb;
-};
#ifdef PIPE_OS_UNIX
static void
}
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[] =
hud->whitelines.buffer_size +
hud->text.buffer_size +
hud->color_prims.buffer_size,
- 16, &hud->bg.vbuf.buffer_offset, &hud->bg.vbuf.buffer,
+ 16, &hud->bg.vbuf.buffer_offset, &hud->bg.vbuf.buffer.resource,
(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);
+ 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->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);
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);
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);
hud_pane_draw_colored_objects(hud, pane);
}
+out:
cso_restore_state(cso);
cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
* 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);
}
}
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)
{
if (!pane)
return NULL;
+ pane->hud = hud;
pane->x1 = x1;
pane->y1 = y1;
pane->x2 = x2;
}
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;
*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, 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
}
/**
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;
}
hud_cpu_graph_install(pane, i);
}
else if (strcmp(name, "API-thread-busy") == 0) {
- hud_api_thread_busy_install(pane);
+ 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) {
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;
+}