diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2017-08-26 16:59:42 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2017-08-26 16:59:42 +0000 |
commit | 81ece42815e80818f160cdd85fab57d65b56ad15 (patch) | |
tree | 1059ff094da1aa50334115952fcb1cfcbda3acc6 /lib/mesa/src/gallium/auxiliary/hud | |
parent | b0244145d5bb49623d58f6b5cab8143ada692b60 (diff) |
Revert to Mesa 13.0.6 to hopefully address rendering issues a handful of
people have reported with xpdf/fvwm on ivy bridge with modesetting driver.
Diffstat (limited to 'lib/mesa/src/gallium/auxiliary/hud')
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/hud/hud_context.c | 411 | ||||
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/hud/hud_cpu.c | 54 | ||||
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/hud/hud_cpufreq.c | 1 | ||||
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/hud/hud_driver_query.c | 276 | ||||
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/hud/hud_private.h | 46 |
5 files changed, 662 insertions, 126 deletions
diff --git a/lib/mesa/src/gallium/auxiliary/hud/hud_context.c b/lib/mesa/src/gallium/auxiliary/hud/hud_context.c index 95eed2698..3772f3cc2 100644 --- a/lib/mesa/src/gallium/auxiliary/hud/hud_context.c +++ b/lib/mesa/src/gallium/auxiliary/hud/hud_context.c @@ -33,6 +33,7 @@ * Set GALLIUM_HUD=help for more info. */ +#include <signal.h> #include <stdio.h> #include "hud/hud_context.h" @@ -41,6 +42,7 @@ #include "cso_cache/cso_context.h" #include "util/u_draw_quad.h" +#include "util/u_format.h" #include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_math.h" @@ -51,19 +53,22 @@ #include "tgsi/tgsi_text.h" #include "tgsi/tgsi_dump.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 u_upload_mgr *uploader; + struct hud_batch_query_context *batch_query; struct list_head pane_list; /* states */ - struct pipe_blend_state alpha_blend; + 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; + struct pipe_rasterizer_state rasterizer, rasterizer_aa_lines; void *vs; struct pipe_vertex_element velems[2]; @@ -93,8 +98,17 @@ struct hud_context { unsigned max_num_vertices; unsigned num_vertices; } text, bg, whitelines; + + bool has_srgb; }; +#ifdef PIPE_OS_UNIX +static void +signal_visible_handler(int sig, siginfo_t *siginfo, void *context) +{ + huds_visible = !huds_visible; +} +#endif static void hud_draw_colored_prims(struct hud_context *hud, unsigned prim, @@ -231,8 +245,8 @@ hud_draw_string(struct hud_context *hud, unsigned x, unsigned y, } static void -number_to_human_readable(uint64_t num, uint64_t max_value, - enum pipe_driver_query_type type, char *out) +number_to_human_readable(uint64_t num, enum pipe_driver_query_type type, + char *out) { static const char *byte_units[] = {" B", " KB", " MB", " GB", " TB", " PB", " EB"}; @@ -243,6 +257,11 @@ number_to_human_readable(uint64_t num, uint64_t max_value, static const char *hz_units[] = {" Hz", " KHz", " MHz", " GHz"}; static const char *percent_units[] = {"%"}; + static const char *dbm_units[] = {" (-dBm)"}; + static const char *temperature_units[] = {" C"}; + static const char *volt_units[] = {" mV", " V"}; + static const char *amp_units[] = {" mA", " A"}; + static const char *watt_units[] = {" mW", " W"}; const char **units; unsigned max_unit; @@ -255,6 +274,22 @@ number_to_human_readable(uint64_t num, uint64_t max_value, max_unit = ARRAY_SIZE(time_units)-1; units = time_units; break; + case PIPE_DRIVER_QUERY_TYPE_VOLTS: + max_unit = ARRAY_SIZE(volt_units)-1; + units = volt_units; + break; + case PIPE_DRIVER_QUERY_TYPE_AMPS: + max_unit = ARRAY_SIZE(amp_units)-1; + units = amp_units; + break; + case PIPE_DRIVER_QUERY_TYPE_DBM: + max_unit = ARRAY_SIZE(dbm_units)-1; + units = dbm_units; + break; + case PIPE_DRIVER_QUERY_TYPE_TEMPERATURE: + max_unit = ARRAY_SIZE(temperature_units)-1; + units = temperature_units; + break; case PIPE_DRIVER_QUERY_TYPE_PERCENTAGE: max_unit = ARRAY_SIZE(percent_units)-1; units = percent_units; @@ -267,14 +302,13 @@ number_to_human_readable(uint64_t num, uint64_t max_value, max_unit = ARRAY_SIZE(hz_units)-1; units = hz_units; break; + case PIPE_DRIVER_QUERY_TYPE_WATTS: + max_unit = ARRAY_SIZE(watt_units)-1; + units = watt_units; + break; default: - if (max_value == 100) { - max_unit = ARRAY_SIZE(percent_units)-1; - units = percent_units; - } else { - max_unit = ARRAY_SIZE(metric_units)-1; - units = metric_units; - } + max_unit = ARRAY_SIZE(metric_units)-1; + units = metric_units; } while (d > divisor && unit < max_unit) { @@ -282,12 +316,19 @@ number_to_human_readable(uint64_t num, uint64_t max_value, unit++; } - if (d >= 100 || d == (int)d) + /* Round to 3 decimal places so as not to print trailing zeros. */ + if (d*1000 != (int)(d*1000)) + d = round(d * 1000) / 1000; + + /* Show at least 4 digits with at most 3 decimal places, but not zeros. */ + if (d >= 1000 || d == (int)d) sprintf(out, "%.0f%s", d, units[unit]); - else if (d >= 10 || d*10 == (int)(d*10)) + else if (d >= 100 || d*10 == (int)(d*10)) sprintf(out, "%.1f%s", d, units[unit]); - else + else if (d >= 10 || d*100 == (int)(d*100)) sprintf(out, "%.2f%s", d, units[unit]); + else + sprintf(out, "%.3f%s", d, units[unit]); } static void @@ -323,6 +364,7 @@ hud_pane_accumulate_vertices(struct hud_context *hud, float *line_verts = hud->whitelines.vertices + hud->whitelines.num_vertices*2; unsigned i, num = 0; char str[32]; + const unsigned last_line = pane->last_line; /* draw background */ hud_draw_background_quad(hud, @@ -330,12 +372,13 @@ hud_pane_accumulate_vertices(struct hud_context *hud, pane->x2, pane->y2); /* draw numbers on the right-hand side */ - for (i = 0; i < 6; i++) { + for (i = 0; i <= last_line; i++) { unsigned x = pane->x2 + 2; - unsigned y = pane->inner_y1 + pane->inner_height * (5 - i) / 5 - + unsigned y = pane->inner_y1 + + pane->inner_height * (last_line - i) / last_line - hud->font.glyph_height / 2; - number_to_human_readable(pane->max_value * i / 5, pane->max_value, + number_to_human_readable(pane->max_value * i / last_line, pane->type, str); hud_draw_string(hud, x, y, "%s", str); } @@ -346,8 +389,7 @@ hud_pane_accumulate_vertices(struct hud_context *hud, unsigned x = pane->x1 + 2; unsigned y = pane->y2 + 2 + i*hud->font.glyph_height; - number_to_human_readable(gr->current_value, pane->max_value, - pane->type, str); + number_to_human_readable(gr->current_value, pane->type, str); hud_draw_string(hud, x, y, " %s: %s", gr->name, str); i++; } @@ -375,8 +417,9 @@ hud_pane_accumulate_vertices(struct hud_context *hud, line_verts[num++] = (float) pane->y2; /* draw horizontal lines inside the graph */ - for (i = 0; i <= 5; i++) { - float y = round((pane->max_value * i / 5.0) * pane->yscale + pane->inner_y2); + for (i = 0; i <= last_line; i++) { + float y = round((pane->max_value * i / (double)last_line) * + pane->yscale + pane->inner_y2); assert(hud->whitelines.num_vertices + num/2 + 2 <= hud->whitelines.max_num_vertices); line_verts[num++] = pane->x1; @@ -420,7 +463,7 @@ hud_alloc_vertices(struct hud_context *hud, struct vertex_queue *v, v->max_num_vertices = num_vertices; v->vbuf.stride = stride; u_upload_alloc(hud->uploader, 0, v->vbuf.stride * v->max_num_vertices, - &v->vbuf.buffer_offset, &v->vbuf.buffer, + 16, &v->vbuf.buffer_offset, &v->vbuf.buffer, (void**)&v->vertices); } @@ -441,34 +484,50 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex) struct hud_pane *pane; struct hud_graph *gr; + if (!huds_visible) + return; + hud->fb_width = tex->width0; hud->fb_height = tex->height0; hud->constants.two_div_fb_width = 2.0f / hud->fb_width; hud->constants.two_div_fb_height = 2.0f / hud->fb_height; - cso_save_framebuffer(cso); - cso_save_sample_mask(cso); - cso_save_min_samples(cso); - cso_save_blend(cso); - cso_save_depth_stencil_alpha(cso); - cso_save_fragment_shader(cso); - cso_save_fragment_sampler_views(cso); - cso_save_fragment_samplers(cso); - cso_save_rasterizer(cso); - cso_save_viewport(cso); - cso_save_stream_outputs(cso); - cso_save_geometry_shader(cso); - cso_save_tessctrl_shader(cso); - cso_save_tesseval_shader(cso); - cso_save_vertex_shader(cso); - cso_save_vertex_elements(cso); - cso_save_aux_vertex_buffer_slot(cso); + cso_save_state(cso, (CSO_BIT_FRAMEBUFFER | + CSO_BIT_SAMPLE_MASK | + CSO_BIT_MIN_SAMPLES | + CSO_BIT_BLEND | + CSO_BIT_DEPTH_STENCIL_ALPHA | + CSO_BIT_FRAGMENT_SHADER | + CSO_BIT_FRAGMENT_SAMPLER_VIEWS | + CSO_BIT_FRAGMENT_SAMPLERS | + CSO_BIT_RASTERIZER | + CSO_BIT_VIEWPORT | + CSO_BIT_STREAM_OUTPUTS | + CSO_BIT_GEOMETRY_SHADER | + CSO_BIT_TESSCTRL_SHADER | + CSO_BIT_TESSEVAL_SHADER | + CSO_BIT_VERTEX_SHADER | + CSO_BIT_VERTEX_ELEMENTS | + CSO_BIT_AUX_VERTEX_BUFFER_SLOT | + CSO_BIT_PAUSE_QUERIES | + CSO_BIT_RENDER_CONDITION)); cso_save_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX); - cso_save_render_condition(cso); /* set states */ memset(&surf_templ, 0, sizeof(surf_templ)); surf_templ.format = tex->format; + + /* Without this, AA lines look thinner if they are between 2 pixels + * because the alpha is 0.5 on both pixels. (it's ugly) + * + * sRGB makes the width of all AA lines look the same. + */ + if (hud->has_srgb) { + enum pipe_format srgb_format = util_format_srgb(tex->format); + + if (srgb_format != PIPE_FORMAT_NONE) + surf_templ.format = srgb_format; + } surf = pipe->create_surface(pipe, tex, &surf_templ); memset(&fb, 0, sizeof(fb)); @@ -488,7 +547,6 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex) cso_set_framebuffer(cso, &fb); cso_set_sample_mask(cso, ~0); cso_set_min_samples(cso, 1); - cso_set_blend(cso, &hud->alpha_blend); cso_set_depth_stencil_alpha(cso, &hud->dsa); cso_set_rasterizer(cso, &hud->rasterizer); cso_set_viewport(cso, &viewport); @@ -505,11 +563,13 @@ 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 * 128, 2 * sizeof(float)); + 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 * 512, 4 * sizeof(float)); + hud_alloc_vertices(hud, &hud->text, 4 * 1024, 4 * sizeof(float)); /* prepare all graphs */ + hud_batch_query_update(hud->batch_query); + LIST_FOR_EACH_ENTRY(pane, &hud->pane_list, head) { LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) { gr->query_new_value(gr); @@ -522,6 +582,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex) u_upload_unmap(hud->uploader); /* draw accumulated vertices for background quads */ + cso_set_blend(cso, &hud->alpha_blend); cso_set_fragment_shader_handle(hud->cso, hud->fs_color); if (hud->bg.num_vertices) { @@ -542,6 +603,8 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex) pipe_resource_reference(&hud->bg.vbuf.buffer, NULL); /* draw accumulated vertices for white lines */ + cso_set_blend(cso, &hud->no_blend); + hud->constants.color[0] = 1; hud->constants.color[1] = 1; hud->constants.color[2] = 1; @@ -561,6 +624,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex) pipe_resource_reference(&hud->whitelines.vbuf.buffer, NULL); /* draw accumulated vertices for text */ + cso_set_blend(cso, &hud->alpha_blend); if (hud->text.num_vertices) { cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, &hud->text.vbuf); @@ -570,35 +634,25 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex) pipe_resource_reference(&hud->text.vbuf.buffer, NULL); /* draw the rest */ + cso_set_rasterizer(cso, &hud->rasterizer_aa_lines); LIST_FOR_EACH_ENTRY(pane, &hud->pane_list, head) { if (pane) hud_pane_draw_colored_objects(hud, pane); } - /* restore states */ - cso_restore_framebuffer(cso); - cso_restore_sample_mask(cso); - cso_restore_min_samples(cso); - cso_restore_blend(cso); - cso_restore_depth_stencil_alpha(cso); - cso_restore_fragment_shader(cso); - cso_restore_fragment_sampler_views(cso); - cso_restore_fragment_samplers(cso); - cso_restore_rasterizer(cso); - cso_restore_viewport(cso); - cso_restore_stream_outputs(cso); - cso_restore_tessctrl_shader(cso); - cso_restore_tesseval_shader(cso); - cso_restore_geometry_shader(cso); - cso_restore_vertex_shader(cso); - cso_restore_vertex_elements(cso); - cso_restore_aux_vertex_buffer_slot(cso); + cso_restore_state(cso); cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX); - cso_restore_render_condition(cso); pipe_surface_reference(&surf, NULL); } +static void +fixup_bytes(enum pipe_driver_query_type type, int position, uint64_t *exp10) +{ + if (type == PIPE_DRIVER_QUERY_TYPE_BYTES && position % 3 == 0) + *exp10 = (*exp10 / 1000) * 1024; +} + /** * Set the maximum value for the Y axis of the graph. * This scales the graph accordingly. @@ -606,7 +660,74 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex) void hud_pane_set_max_value(struct hud_pane *pane, uint64_t value) { - pane->max_value = value; + double leftmost_digit; + uint64_t exp10; + int i; + + /* The following code determines the max_value in the graph as well as + * how many describing lines are drawn. The max_value is rounded up, + * so that all drawn numbers are rounded for readability. + * We want to print multiples of a simple number instead of multiples of + * hard-to-read numbers like 1.753. + */ + + /* Find the left-most digit. */ + exp10 = 1; + for (i = 0; value > 9 * exp10; i++) { + exp10 *= 10; + fixup_bytes(pane->type, i + 1, &exp10); + } + + leftmost_digit = DIV_ROUND_UP(value, exp10); + + /* Round 9 to 10. */ + if (leftmost_digit == 9) { + leftmost_digit = 1; + exp10 *= 10; + fixup_bytes(pane->type, i + 1, &exp10); + } + + switch ((unsigned)leftmost_digit) { + case 1: + pane->last_line = 5; /* lines in +1/5 increments */ + break; + case 2: + pane->last_line = 8; /* lines in +1/4 increments. */ + break; + case 3: + case 4: + pane->last_line = leftmost_digit * 2; /* lines in +1/2 increments */ + break; + case 5: + case 6: + case 7: + case 8: + pane->last_line = leftmost_digit; /* lines in +1 increments */ + break; + default: + assert(0); + } + + /* Truncate {3,4} to {2.5, 3.5} if possible. */ + for (i = 3; i <= 4; i++) { + if (leftmost_digit == i && value <= (i - 0.5) * exp10) { + leftmost_digit = i - 0.5; + pane->last_line = leftmost_digit * 2; /* lines in +1/2 increments. */ + } + } + + /* Truncate 2 to a multiple of 0.2 in (1, 1.6] if possible. */ + if (leftmost_digit == 2) { + for (i = 1; i <= 3; i++) { + if (value <= (1 + i*0.2) * exp10) { + leftmost_digit = 1 + i*0.2; + pane->last_line = 5 + i; /* lines in +1/5 increments. */ + break; + } + } + } + + pane->max_value = leftmost_digit * exp10; pane->yscale = -(int)pane->inner_height / (float)pane->max_value; } @@ -692,7 +813,7 @@ hud_pane_add_graph(struct hud_pane *pane, struct hud_graph *gr) name++; } - assert(pane->num_graphs < Elements(colors)); + 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]; @@ -891,6 +1012,9 @@ hud_parse_env_var(struct hud_context *hud, const char *env) } /* Add a graph. */ +#if HAVE_GALLIUM_EXTRA_HUD || HAVE_LIBSENSORS + char arg_name[64]; +#endif /* IF YOU CHANGE THIS, UPDATE print_help! */ if (strcmp(name, "fps") == 0) { hud_fps_graph_install(pane); @@ -901,19 +1025,82 @@ 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); } +#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); + } + else if (sscanf(name, "nic-tx-%s", arg_name) == 1) { + hud_nic_graph_install(pane, arg_name, NIC_DIRECTION_TX); + } + else if (sscanf(name, "nic-rssi-%s", arg_name) == 1) { + hud_nic_graph_install(pane, arg_name, NIC_RSSI_DBM); + pane->type = PIPE_DRIVER_QUERY_TYPE_DBM; + } + else if (sscanf(name, "diskstat-rd-%s", arg_name) == 1) { + hud_diskstat_graph_install(pane, arg_name, DISKSTAT_RD); + pane->type = PIPE_DRIVER_QUERY_TYPE_BYTES; + } + else if (sscanf(name, "diskstat-wr-%s", arg_name) == 1) { + hud_diskstat_graph_install(pane, arg_name, DISKSTAT_WR); + pane->type = PIPE_DRIVER_QUERY_TYPE_BYTES; + } + else if (sscanf(name, "cpufreq-min-cpu%u", &i) == 1) { + hud_cpufreq_graph_install(pane, i, CPUFREQ_MINIMUM); + pane->type = PIPE_DRIVER_QUERY_TYPE_HZ; + } + else if (sscanf(name, "cpufreq-cur-cpu%u", &i) == 1) { + hud_cpufreq_graph_install(pane, i, CPUFREQ_CURRENT); + pane->type = PIPE_DRIVER_QUERY_TYPE_HZ; + } + else if (sscanf(name, "cpufreq-max-cpu%u", &i) == 1) { + hud_cpufreq_graph_install(pane, i, CPUFREQ_MAXIMUM); + pane->type = PIPE_DRIVER_QUERY_TYPE_HZ; + } +#endif +#if HAVE_LIBSENSORS + else if (sscanf(name, "sensors_temp_cu-%s", arg_name) == 1) { + hud_sensors_temp_graph_install(pane, arg_name, + SENSORS_TEMP_CURRENT); + pane->type = PIPE_DRIVER_QUERY_TYPE_TEMPERATURE; + } + else if (sscanf(name, "sensors_temp_cr-%s", arg_name) == 1) { + hud_sensors_temp_graph_install(pane, arg_name, + SENSORS_TEMP_CRITICAL); + pane->type = PIPE_DRIVER_QUERY_TYPE_TEMPERATURE; + } + else if (sscanf(name, "sensors_volt_cu-%s", arg_name) == 1) { + hud_sensors_temp_graph_install(pane, arg_name, + SENSORS_VOLTAGE_CURRENT); + pane->type = PIPE_DRIVER_QUERY_TYPE_VOLTS; + } + else if (sscanf(name, "sensors_curr_cu-%s", arg_name) == 1) { + hud_sensors_temp_graph_install(pane, arg_name, + SENSORS_CURRENT_CURRENT); + pane->type = PIPE_DRIVER_QUERY_TYPE_AMPS; + } + else if (sscanf(name, "sensors_pow_cu-%s", arg_name) == 1) { + hud_sensors_temp_graph_install(pane, arg_name, + SENSORS_POWER_CURRENT); + pane->type = PIPE_DRIVER_QUERY_TYPE_WATTS; + } +#endif else if (strcmp(name, "samples-passed") == 0 && has_occlusion_query(hud->pipe->screen)) { - hud_pipe_query_install(pane, hud->pipe, "samples-passed", + hud_pipe_query_install(&hud->batch_query, pane, hud->pipe, + "samples-passed", PIPE_QUERY_OCCLUSION_COUNTER, 0, 0, PIPE_DRIVER_QUERY_TYPE_UINT64, - PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE); + PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE, + 0); } else if (strcmp(name, "primitives-generated") == 0 && has_streamout(hud->pipe->screen)) { - hud_pipe_query_install(pane, hud->pipe, "primitives-generated", + hud_pipe_query_install(&hud->batch_query, pane, hud->pipe, + "primitives-generated", PIPE_QUERY_PRIMITIVES_GENERATED, 0, 0, PIPE_DRIVER_QUERY_TYPE_UINT64, - PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE); + PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE, + 0); } else { boolean processed = FALSE; @@ -934,21 +1121,23 @@ hud_parse_env_var(struct hud_context *hud, const char *env) "ds-invocations", "cs-invocations" }; - for (i = 0; i < Elements(pipeline_statistics_names); ++i) + for (i = 0; i < ARRAY_SIZE(pipeline_statistics_names); ++i) if (strcmp(name, pipeline_statistics_names[i]) == 0) break; - if (i < Elements(pipeline_statistics_names)) { - hud_pipe_query_install(pane, hud->pipe, name, + if (i < ARRAY_SIZE(pipeline_statistics_names)) { + hud_pipe_query_install(&hud->batch_query, pane, hud->pipe, name, PIPE_QUERY_PIPELINE_STATISTICS, i, 0, PIPE_DRIVER_QUERY_TYPE_UINT64, - PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE); + PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE, + 0); processed = TRUE; } } /* driver queries */ if (!processed) { - if (!hud_driver_query_install(pane, hud->pipe, name)){ + if (!hud_driver_query_install(&hud->batch_query, pane, hud->pipe, + name)) { fprintf(stderr, "gallium_hud: unknown driver query '%s'\n", name); } } @@ -987,6 +1176,9 @@ hud_parse_env_var(struct hud_context *hud, const char *env) case ',': env++; + if (!pane) + break; + y += height + hud->font.glyph_height * (pane->num_graphs + 2); height = 100; @@ -999,7 +1191,7 @@ hud_parse_env_var(struct hud_context *hud, const char *env) case ';': env++; y = 10; - x += column_width + hud->font.glyph_width * 7; + x += column_width + hud->font.glyph_width * 9; height = 100; if (pane && pane->num_graphs) { @@ -1101,13 +1293,30 @@ print_help(struct pipe_screen *screen) puts(" cs-invocations"); } +#if HAVE_GALLIUM_EXTRA_HUD + hud_get_num_disks(1); + hud_get_num_nics(1); + hud_get_num_cpufreq(1); +#endif +#if HAVE_LIBSENSORS + hud_get_num_sensors(1); +#endif + if (screen->get_driver_query_info){ + boolean skipping = false; struct pipe_driver_query_info info; num_queries = screen->get_driver_query_info(screen, 0, NULL); for (i = 0; i < num_queries; i++){ screen->get_driver_query_info(screen, i, &info); - printf(" %s\n", info.name); + if (info.flags & PIPE_DRIVER_QUERY_FLAG_DONT_LIST) { + if (!skipping) + puts(" ..."); + skipping = true; + } else { + printf(" %s\n", info.name); + skipping = false; + } } } @@ -1118,10 +1327,17 @@ print_help(struct pipe_screen *screen) struct hud_context * hud_create(struct pipe_context *pipe, struct cso_context *cso) { + struct pipe_screen *screen = pipe->screen; struct hud_context *hud; struct pipe_sampler_view view_templ; unsigned i; const char *env = debug_get_option("GALLIUM_HUD", NULL); +#ifdef PIPE_OS_UNIX + unsigned signo = debug_get_num_option("GALLIUM_HUD_TOGGLE_SIGNAL", 0); + static boolean sig_handled = FALSE; + struct sigaction action = {}; +#endif + huds_visible = debug_get_bool_option("GALLIUM_HUD_VISIBLE", TRUE); if (!env || !*env) return NULL; @@ -1137,8 +1353,8 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso) hud->pipe = pipe; hud->cso = cso; - hud->uploader = u_upload_create(pipe, 256 * 1024, 16, - PIPE_BIND_VERTEX_BUFFER); + 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)) { @@ -1147,7 +1363,14 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso) return NULL; } + hud->has_srgb = screen->is_format_supported(screen, + PIPE_FORMAT_B8G8R8A8_SRGB, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET) != 0; + /* blend state */ + hud->no_blend.rt[0].colormask = PIPE_MASK_RGBA; + hud->alpha_blend.rt[0].colormask = PIPE_MASK_RGBA; hud->alpha_blend.rt[0].blend_enable = 1; hud->alpha_blend.rt[0].rgb_func = PIPE_BLEND_ADD; @@ -1170,6 +1393,7 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso) "FRAG\n" "DCL IN[0], GENERIC[0], LINEAR\n" "DCL SAMP[0]\n" + "DCL SVIEW[0], RECT, FLOAT\n" "DCL OUT[0], COLOR[0]\n" "DCL TEMP[0]\n" @@ -1179,16 +1403,16 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso) }; struct tgsi_token tokens[1000]; - struct pipe_shader_state state = {tokens}; + struct pipe_shader_state state; - if (!tgsi_text_translate(fragment_shader_text, tokens, Elements(tokens))) { + 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; } - + pipe_shader_state_from_tgsi(&state, tokens); hud->fs_text = pipe->create_fs_state(pipe, &state); } @@ -1199,6 +1423,9 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso) hud->rasterizer.line_width = 1; hud->rasterizer.line_last_pixel = 1; + hud->rasterizer_aa_lines = hud->rasterizer; + hud->rasterizer_aa_lines.line_smooth = 1; + /* vertex shader */ { static const char *vertex_shader_text = { @@ -1226,16 +1453,15 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso) }; struct tgsi_token tokens[1000]; - struct pipe_shader_state state = {tokens}; - - if (!tgsi_text_translate(vertex_shader_text, tokens, Elements(tokens))) { + struct pipe_shader_state state; + 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; } - + pipe_shader_state_from_tgsi(&state, tokens); hud->vs = pipe->create_vs_state(pipe, &state); } @@ -1264,6 +1490,22 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso) LIST_INITHEAD(&hud->pane_list); + /* setup sig handler once for all hud contexts */ +#ifdef PIPE_OS_UNIX + if (!sig_handled && signo != 0) { + action.sa_sigaction = &signal_visible_handler; + action.sa_flags = SA_SIGINFO; + + if (signo >= NSIG) + fprintf(stderr, "gallium_hud: invalid signal %u\n", signo); + else if (sigaction(signo, &action, NULL) < 0) + fprintf(stderr, "gallium_hud: unable to set handler for signal %u\n", signo); + fflush(stderr); + + sig_handled = TRUE; + } +#endif + hud_parse_env_var(hud, env); return hud; } @@ -1284,6 +1526,7 @@ hud_destroy(struct hud_context *hud) FREE(pane); } + hud_batch_query_cleanup(&hud->batch_query); pipe->delete_fs_state(pipe, hud->fs_color); pipe->delete_fs_state(pipe, hud->fs_text); pipe->delete_vs_state(pipe, hud->vs); diff --git a/lib/mesa/src/gallium/auxiliary/hud/hud_cpu.c b/lib/mesa/src/gallium/auxiliary/hud/hud_cpu.c index cd20deec9..c06e7770d 100644 --- a/lib/mesa/src/gallium/auxiliary/hud/hud_cpu.c +++ b/lib/mesa/src/gallium/auxiliary/hud/hud_cpu.c @@ -33,6 +33,58 @@ #include "util/u_memory.h" #include <stdio.h> #include <inttypes.h> +#ifdef PIPE_OS_WINDOWS +#include <windows.h> +#endif + + +#ifdef PIPE_OS_WINDOWS + +static inline uint64_t +filetime_to_scalar(FILETIME ft) +{ + ULARGE_INTEGER uli; + uli.LowPart = ft.dwLowDateTime; + uli.HighPart = ft.dwHighDateTime; + return uli.QuadPart; +} + +static boolean +get_cpu_stats(unsigned cpu_index, uint64_t *busy_time, uint64_t *total_time) +{ + SYSTEM_INFO sysInfo; + FILETIME ftNow, ftCreation, ftExit, ftKernel, ftUser; + + GetSystemInfo(&sysInfo); + assert(sysInfo.dwNumberOfProcessors >= 1); + if (cpu_index != ALL_CPUS && cpu_index >= sysInfo.dwNumberOfProcessors) { + /* Tell hud_get_num_cpus there are only this many CPUs. */ + return FALSE; + } + + /* Get accumulated user and sys time for all threads */ + if (!GetProcessTimes(GetCurrentProcess(), &ftCreation, &ftExit, + &ftKernel, &ftUser)) + return FALSE; + + GetSystemTimeAsFileTime(&ftNow); + + *busy_time = filetime_to_scalar(ftUser) + filetime_to_scalar(ftKernel); + *total_time = filetime_to_scalar(ftNow) - filetime_to_scalar(ftCreation); + + /* busy_time already has the time accross all cpus. + * XXX: if we want 100% to mean one CPU, 200% two cpus, eliminate the + * following line. + */ + *total_time *= sysInfo.dwNumberOfProcessors; + + /* XXX: we ignore cpu_index, i.e, we assume that the individual CPU usage + * and the system usage are one and the same. + */ + return TRUE; +} + +#else static boolean get_cpu_stats(unsigned cpu_index, uint64_t *busy_time, uint64_t *total_time) @@ -81,6 +133,8 @@ get_cpu_stats(unsigned cpu_index, uint64_t *busy_time, uint64_t *total_time) fclose(f); return FALSE; } +#endif + struct cpu_info { unsigned cpu_index; diff --git a/lib/mesa/src/gallium/auxiliary/hud/hud_cpufreq.c b/lib/mesa/src/gallium/auxiliary/hud/hud_cpufreq.c index 19a6f08c4..78754b28a 100644 --- a/lib/mesa/src/gallium/auxiliary/hud/hud_cpufreq.c +++ b/lib/mesa/src/gallium/auxiliary/hud/hud_cpufreq.c @@ -149,6 +149,7 @@ hud_cpufreq_graph_install(struct hud_pane *pane, int cpu_index, break; case CPUFREQ_MAXIMUM: snprintf(gr->name, sizeof(gr->name), "%s-Max", cfi->name); + break; default: return; } diff --git a/lib/mesa/src/gallium/auxiliary/hud/hud_driver_query.c b/lib/mesa/src/gallium/auxiliary/hud/hud_driver_query.c index f14305ea8..40ea120ef 100644 --- a/lib/mesa/src/gallium/auxiliary/hud/hud_driver_query.c +++ b/lib/mesa/src/gallium/auxiliary/hud/hud_driver_query.c @@ -34,13 +34,164 @@ #include "hud/hud_private.h" #include "pipe/p_screen.h" #include "os/os_time.h" +#include "util/u_math.h" #include "util/u_memory.h" #include <stdio.h> +// Must be a power of two #define NUM_QUERIES 8 +struct hud_batch_query_context { + struct pipe_context *pipe; + unsigned num_query_types; + unsigned allocated_query_types; + unsigned *query_types; + + boolean failed; + struct pipe_query *query[NUM_QUERIES]; + union pipe_query_result *result[NUM_QUERIES]; + unsigned head, pending, results; +}; + +void +hud_batch_query_update(struct hud_batch_query_context *bq) +{ + struct pipe_context *pipe; + + if (!bq || bq->failed) + return; + + pipe = bq->pipe; + + if (bq->query[bq->head]) + pipe->end_query(pipe, bq->query[bq->head]); + + bq->results = 0; + + while (bq->pending) { + unsigned idx = (bq->head - bq->pending + 1) % NUM_QUERIES; + struct pipe_query *query = bq->query[idx]; + + if (!bq->result[idx]) + bq->result[idx] = MALLOC(sizeof(bq->result[idx]->batch[0]) * + bq->num_query_types); + if (!bq->result[idx]) { + fprintf(stderr, "gallium_hud: out of memory.\n"); + bq->failed = TRUE; + return; + } + + if (!pipe->get_query_result(pipe, query, FALSE, bq->result[idx])) + break; + + ++bq->results; + --bq->pending; + } + + bq->head = (bq->head + 1) % NUM_QUERIES; + + if (bq->pending == NUM_QUERIES) { + fprintf(stderr, + "gallium_hud: all queries busy after %i frames, dropping data.\n", + NUM_QUERIES); + + assert(bq->query[bq->head]); + + pipe->destroy_query(bq->pipe, bq->query[bq->head]); + bq->query[bq->head] = NULL; + } + + ++bq->pending; + + if (!bq->query[bq->head]) { + bq->query[bq->head] = pipe->create_batch_query(pipe, + bq->num_query_types, + bq->query_types); + + if (!bq->query[bq->head]) { + fprintf(stderr, + "gallium_hud: create_batch_query failed. You may have " + "selected too many or incompatible queries.\n"); + bq->failed = TRUE; + return; + } + } + + if (!pipe->begin_query(pipe, bq->query[bq->head])) { + fprintf(stderr, + "gallium_hud: could not begin batch query. You may have " + "selected too many or incompatible queries.\n"); + bq->failed = TRUE; + } +} + +static boolean +batch_query_add(struct hud_batch_query_context **pbq, + struct pipe_context *pipe, unsigned query_type, + unsigned *result_index) +{ + struct hud_batch_query_context *bq = *pbq; + unsigned i; + + if (!bq) { + bq = CALLOC_STRUCT(hud_batch_query_context); + if (!bq) + return false; + bq->pipe = pipe; + *pbq = bq; + } + + for (i = 0; i < bq->num_query_types; ++i) { + if (bq->query_types[i] == query_type) { + *result_index = i; + return true; + } + } + + if (bq->num_query_types == bq->allocated_query_types) { + unsigned new_alloc = MAX2(16, bq->allocated_query_types * 2); + unsigned *new_query_types + = REALLOC(bq->query_types, + bq->allocated_query_types * sizeof(unsigned), + new_alloc * sizeof(unsigned)); + if (!new_query_types) + return false; + bq->query_types = new_query_types; + bq->allocated_query_types = new_alloc; + } + + bq->query_types[bq->num_query_types] = query_type; + *result_index = bq->num_query_types++; + return true; +} + +void +hud_batch_query_cleanup(struct hud_batch_query_context **pbq) +{ + struct hud_batch_query_context *bq = *pbq; + unsigned idx; + + if (!bq) + return; + + *pbq = NULL; + + if (bq->query[bq->head] && !bq->failed) + bq->pipe->end_query(bq->pipe, bq->query[bq->head]); + + for (idx = 0; idx < NUM_QUERIES; ++idx) { + if (bq->query[idx]) + bq->pipe->destroy_query(bq->pipe, bq->query[idx]); + FREE(bq->result[idx]); + } + + FREE(bq->query_types); + FREE(bq); +} + struct query_info { struct pipe_context *pipe; + struct hud_batch_query_context *batch; unsigned query_type; unsigned result_index; /* unit depends on query_type */ enum pipe_driver_query_result_type result_type; @@ -48,7 +199,6 @@ struct query_info { /* Ring of queries. If a query is busy, we use another slot. */ struct pipe_query *query[NUM_QUERIES]; unsigned head, tail; - unsigned num_queries; uint64_t last_time; uint64_t results_cumulative; @@ -56,11 +206,26 @@ struct query_info { }; static void -query_new_value(struct hud_graph *gr) +query_new_value_batch(struct query_info *info) +{ + struct hud_batch_query_context *bq = info->batch; + unsigned result_index = info->result_index; + unsigned idx = (bq->head - bq->pending) % NUM_QUERIES; + unsigned results = bq->results; + + while (results) { + info->results_cumulative += bq->result[idx]->batch[result_index].u64; + ++info->num_results; + + --results; + idx = (idx - 1) % NUM_QUERIES; + } +} + +static void +query_new_value_normal(struct query_info *info) { - struct query_info *info = gr->query_data; struct pipe_context *pipe = info->pipe; - uint64_t now = os_time_get(); if (info->last_time) { if (info->query[info->head]) @@ -107,30 +272,9 @@ query_new_value(struct hud_graph *gr) break; } } - - if (info->num_results && info->last_time + gr->pane->period <= now) { - uint64_t value; - - switch (info->result_type) { - default: - case PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE: - value = info->results_cumulative / info->num_results; - break; - case PIPE_DRIVER_QUERY_RESULT_TYPE_CUMULATIVE: - value = info->results_cumulative; - break; - } - - hud_graph_add_value(gr, value); - - info->last_time = now; - info->results_cumulative = 0; - info->num_results = 0; - } } else { /* initialize */ - info->last_time = now; info->query[info->head] = pipe->create_query(pipe, info->query_type, 0); } @@ -139,17 +283,55 @@ query_new_value(struct hud_graph *gr) } static void +query_new_value(struct hud_graph *gr) +{ + struct query_info *info = gr->query_data; + uint64_t now = os_time_get(); + + if (info->batch) { + query_new_value_batch(info); + } else { + query_new_value_normal(info); + } + + if (!info->last_time) { + info->last_time = now; + return; + } + + if (info->num_results && info->last_time + gr->pane->period <= now) { + uint64_t value; + + switch (info->result_type) { + default: + case PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE: + value = info->results_cumulative / info->num_results; + break; + case PIPE_DRIVER_QUERY_RESULT_TYPE_CUMULATIVE: + value = info->results_cumulative; + break; + } + + hud_graph_add_value(gr, value); + + info->last_time = now; + info->results_cumulative = 0; + info->num_results = 0; + } +} + +static void free_query_info(void *ptr) { struct query_info *info = ptr; - if (info->last_time) { + if (!info->batch && info->last_time) { struct pipe_context *pipe = info->pipe; int i; pipe->end_query(pipe, info->query[info->head]); - for (i = 0; i < Elements(info->query); i++) { + for (i = 0; i < ARRAY_SIZE(info->query); i++) { if (info->query[i]) { pipe->destroy_query(pipe, info->query[i]); } @@ -159,11 +341,13 @@ free_query_info(void *ptr) } void -hud_pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe, +hud_pipe_query_install(struct hud_batch_query_context **pbq, + struct hud_pane *pane, struct pipe_context *pipe, const char *name, unsigned query_type, unsigned result_index, uint64_t max_value, enum pipe_driver_query_type type, - enum pipe_driver_query_result_type result_type) + enum pipe_driver_query_result_type result_type, + unsigned flags) { struct hud_graph *gr; struct query_info *info; @@ -175,28 +359,41 @@ hud_pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe, strncpy(gr->name, name, sizeof(gr->name)); gr->name[sizeof(gr->name) - 1] = '\0'; gr->query_data = CALLOC_STRUCT(query_info); - if (!gr->query_data) { - FREE(gr); - return; - } + if (!gr->query_data) + goto fail_gr; gr->query_new_value = query_new_value; gr->free_query_data = free_query_info; info = gr->query_data; info->pipe = pipe; - info->query_type = query_type; - info->result_index = result_index; info->result_type = result_type; + if (flags & PIPE_DRIVER_QUERY_FLAG_BATCH) { + if (!batch_query_add(pbq, pipe, query_type, &info->result_index)) + goto fail_info; + info->batch = *pbq; + } else { + info->query_type = query_type; + info->result_index = result_index; + } + hud_pane_add_graph(pane, gr); + pane->type = type; /* must be set before updating the max_value */ + if (pane->max_value < max_value) hud_pane_set_max_value(pane, max_value); - pane->type = type; + return; + +fail_info: + FREE(info); +fail_gr: + FREE(gr); } boolean -hud_driver_query_install(struct hud_pane *pane, struct pipe_context *pipe, +hud_driver_query_install(struct hud_batch_query_context **pbq, + struct hud_pane *pane, struct pipe_context *pipe, const char *name) { struct pipe_screen *screen = pipe->screen; @@ -220,8 +417,9 @@ hud_driver_query_install(struct hud_pane *pane, struct pipe_context *pipe, if (!found) return FALSE; - hud_pipe_query_install(pane, pipe, query.name, query.query_type, 0, - query.max_value.u64, query.type, query.result_type); + hud_pipe_query_install(pbq, pane, pipe, query.name, query.query_type, 0, + query.max_value.u64, query.type, query.result_type, + query.flags); return TRUE; } diff --git a/lib/mesa/src/gallium/auxiliary/hud/hud_private.h b/lib/mesa/src/gallium/auxiliary/hud/hud_private.h index 01caf7b8b..c6d0dbf66 100644 --- a/lib/mesa/src/gallium/auxiliary/hud/hud_private.h +++ b/lib/mesa/src/gallium/auxiliary/hud/hud_private.h @@ -61,6 +61,7 @@ struct hud_pane { unsigned inner_height; float yscale; unsigned max_num_vertices; + unsigned last_line; /* index of the last describing line in the graph */ uint64_t max_value; uint64_t initial_max_value; uint64_t ceiling; @@ -80,19 +81,58 @@ void hud_pane_set_max_value(struct hud_pane *pane, uint64_t value); void hud_graph_add_value(struct hud_graph *gr, uint64_t value); /* graphs/queries */ +struct hud_batch_query_context; + #define ALL_CPUS ~0 /* optionally set as cpu_index */ int hud_get_num_cpus(void); void hud_fps_graph_install(struct hud_pane *pane); void hud_cpu_graph_install(struct hud_pane *pane, unsigned cpu_index); -void hud_pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe, +void hud_pipe_query_install(struct hud_batch_query_context **pbq, + struct hud_pane *pane, struct pipe_context *pipe, const char *name, unsigned query_type, unsigned result_index, uint64_t max_value, enum pipe_driver_query_type type, - enum pipe_driver_query_result_type result_type); -boolean hud_driver_query_install(struct hud_pane *pane, + enum pipe_driver_query_result_type result_type, + unsigned flags); +boolean hud_driver_query_install(struct hud_batch_query_context **pbq, + struct hud_pane *pane, struct pipe_context *pipe, const char *name); +void hud_batch_query_update(struct hud_batch_query_context *bq); +void hud_batch_query_cleanup(struct hud_batch_query_context **pbq); + +#if HAVE_GALLIUM_EXTRA_HUD +int hud_get_num_nics(bool displayhelp); +#define NIC_DIRECTION_RX 1 +#define NIC_DIRECTION_TX 2 +#define NIC_RSSI_DBM 3 +void hud_nic_graph_install(struct hud_pane *pane, const char *nic_index, + unsigned int mode); + +int hud_get_num_disks(bool displayhelp); +#define DISKSTAT_RD 1 +#define DISKSTAT_WR 2 +void hud_diskstat_graph_install(struct hud_pane *pane, const char *dev_name, + unsigned int mode); + +int hud_get_num_cpufreq(bool displayhelp); +#define CPUFREQ_MINIMUM 1 +#define CPUFREQ_CURRENT 2 +#define CPUFREQ_MAXIMUM 3 +void hud_cpufreq_graph_install(struct hud_pane *pane, int cpu_index, unsigned int mode); +#endif + +#if HAVE_LIBSENSORS +int hud_get_num_sensors(bool displayhelp); +#define SENSORS_TEMP_CURRENT 1 +#define SENSORS_TEMP_CRITICAL 2 +#define SENSORS_VOLTAGE_CURRENT 3 +#define SENSORS_CURRENT_CURRENT 4 +#define SENSORS_POWER_CURRENT 5 +void hud_sensors_temp_graph_install(struct hud_pane *pane, const char *dev_name, + unsigned int mode); +#endif #endif |