[Mesa-dev] [PATCH 2/5] gallium: implement a head-up display module
Brian Paul
brianp at vmware.com
Mon Mar 25 08:26:30 PDT 2013
On 03/22/2013 05:51 PM, Marek Olšák wrote:
Just a bunch of minor nits...
> +static void
> +hud_draw_graph_line_strip(struct hud_context *hud, struct hud_graph *gr,
> + unsigned xoffset, unsigned yoffset, float yscale)
const gr?
> +{
> + if (gr->num_vertices<= 1)
> + return;
> +
> + assert(gr->index<= gr->num_vertices);
> +
> + hud_draw_colored_prims(hud, PIPE_PRIM_LINE_STRIP,
> + gr->vertices, gr->index,
> + gr->color[0], gr->color[1], gr->color[2], 1,
> + xoffset + (gr->pane->max_num_vertices - gr->index - 1) * 2 - 1,
> + yoffset, yscale);
> +
> + if (gr->num_vertices<= gr->index)
> + return;
> +
> + hud_draw_colored_prims(hud, PIPE_PRIM_LINE_STRIP,
> + gr->vertices + gr->index*2,
> + gr->num_vertices - gr->index,
> + gr->color[0], gr->color[1], gr->color[2], 1,
> + xoffset - gr->index*2 - 1, yoffset, yscale);
> +}
> +
> +static void
> +hud_pane_accumulate_vertices(struct hud_context *hud, struct hud_pane *pane)
const pane?
> +{
> + struct hud_graph *gr;
> + float *line_verts = hud->whitelines.vertices + hud->whitelines.num_vertices*2;
> + unsigned i, num = 0;
> + char str[32];
> +
> + /* draw background */
> + hud_draw_background_quad(hud,
> + pane->x1, pane->y1,
> + pane->x2, pane->y2);
> +
> + /* draw numbers on the right-hand side */
> + for (i = 0; i< 6; i++) {
> + unsigned x = pane->x2 + 2;
> + unsigned y = pane->inner_y1 + pane->inner_height * (5 - i) / 5 -
> + hud->font.glyph_height / 2;
> +
> + number_to_human_readable(pane->max_value * i / 5,
> + pane->uses_byte_units, str);
> + hud_draw_string(hud, x, y, str);
> + }
> +
> + /* draw info below the pane */
> + i = 0;
> + LIST_FOR_EACH_ENTRY(gr,&pane->graph_list, head) {
> + unsigned x = pane->x1 + 2;
> + unsigned y = pane->y2 + 2 + i*hud->font.glyph_height;
> +
> + number_to_human_readable(gr->current_value,
> + pane->uses_byte_units, str);
> + hud_draw_string(hud, x, y, " %s: %s", gr->name, str);
> + i++;
> + }
> +
> + /* draw border */
> + assert(hud->whitelines.num_vertices + num/2 + 8<= hud->whitelines.max_num_vertices);
> + line_verts[num++] = pane->x1;
> + line_verts[num++] = pane->y1;
> + line_verts[num++] = pane->x2;
> + line_verts[num++] = pane->y1;
> +
> + line_verts[num++] = pane->x2;
> + line_verts[num++] = pane->y1;
> + line_verts[num++] = pane->x2;
> + line_verts[num++] = pane->y2;
> +
> + line_verts[num++] = pane->x1;
> + line_verts[num++] = pane->y2;
> + line_verts[num++] = pane->x2;
> + line_verts[num++] = pane->y2;
> +
> + line_verts[num++] = pane->x1;
> + line_verts[num++] = pane->y1;
> + line_verts[num++] = pane->x1;
> + line_verts[num++] = 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);
> +
> + assert(hud->whitelines.num_vertices + num/2 + 2<= hud->whitelines.max_num_vertices);
> + line_verts[num++] = pane->x1;
> + line_verts[num++] = y;
> + line_verts[num++] = pane->x2;
> + line_verts[num++] = y;
> + }
> +
> + hud->whitelines.num_vertices += num/2;
> +}
> +
> +static void
> +hud_pane_draw_colored_objects(struct hud_context *hud, struct hud_pane *pane)
const pane?
> +{
> + struct hud_graph *gr;
> + unsigned i;
> +
> + /* draw colored quads below the pane */
> + i = 0;
> + LIST_FOR_EACH_ENTRY(gr,&pane->graph_list, head) {
> + unsigned x = pane->x1 + 2;
> + unsigned y = pane->y2 + 2 + i*hud->font.glyph_height;
> +
> + hud_draw_colored_quad(hud, PIPE_PRIM_QUADS, x + 1, y + 1, x + 12, y + 13,
> + gr->color[0], gr->color[1], gr->color[2], 1);
> + i++;
> + }
> +
> + /* draw the line strips */
> + LIST_FOR_EACH_ENTRY(gr,&pane->graph_list, head) {
> + hud_draw_graph_line_strip(hud, gr, pane->inner_x1, pane->inner_y2, pane->yscale);
> + }
> +}
> +
> +static void
> +hud_alloc_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,
> +&v->vbuf.buffer_offset,&v->vbuf.buffer,
> + (void**)&v->vertices);
> +}
> +
> +void
> +hud_draw(struct hud_context *hud, struct pipe_resource *tex)
Looks like hud_draw() and the next few functions are the main
entrypoints to this module. Could you add more comments, such as what
is 'tex' here?
> +{
> + struct cso_context *cso = hud->cso;
> + struct pipe_context *pipe = hud->pipe;
> + struct pipe_framebuffer_state fb;
> + struct pipe_surface surf_templ, *surf;
> + struct pipe_viewport_state viewport;
> + const struct pipe_sampler_state *sampler_states[] =
> + {&hud->font_sampler_state };
> + struct hud_pane *pane;
> + struct hud_graph *gr;
> +
> + hud->fb_width = tex->width0;
> + hud->fb_height = tex->height0;
> + hud->constants.two_div_fb_width = 2.0 / hud->fb_width;
> + hud->constants.two_div_fb_height = 2.0 / hud->fb_height;
> +
> + cso_save_framebuffer(cso);
> + cso_save_sample_mask(cso);
> + cso_save_blend(cso);
> + cso_save_depth_stencil_alpha(cso);
> + cso_save_fragment_shader(cso);
> + cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT);
> + cso_save_samplers(cso, PIPE_SHADER_FRAGMENT);
> + cso_save_rasterizer(cso);
> + cso_save_viewport(cso);
> + cso_save_stream_outputs(cso);
> + cso_save_geometry_shader(cso);
> + cso_save_vertex_shader(cso);
> + cso_save_vertex_elements(cso);
> + cso_save_aux_vertex_buffer_slot(cso);
> + 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;
> + surf = pipe->create_surface(pipe, tex,&surf_templ);
> +
> + memset(&fb, 0, sizeof(fb));
> + fb.nr_cbufs = 1;
> + fb.cbufs[0] = surf;
> + fb.zsbuf = NULL;
> + fb.width = hud->fb_width;
> + fb.height = hud->fb_height;
> +
> + viewport.scale[0] = 0.5f * hud->fb_width;
> + viewport.scale[1] = 0.5f * hud->fb_height;
> + viewport.scale[2] = 1.0f;
> + viewport.scale[3] = 1.0f;
> + viewport.translate[0] = 0.5f * hud->fb_width;
> + viewport.translate[1] = 0.5f * hud->fb_height;
> + viewport.translate[2] = 0.0f;
> + viewport.translate[3] = 0.0f;
> +
> + cso_set_framebuffer(cso,&fb);
> + cso_set_sample_mask(cso, ~0);
> + 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);
> + cso_set_stream_outputs(cso, 0, NULL, 0);
> + cso_set_geometry_shader_handle(cso, NULL);
> + cso_set_vertex_shader_handle(cso, hud->vs);
> + cso_set_vertex_elements(cso, 2, hud->velems);
> + cso_set_render_condition(cso, NULL, 0);
> + cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, 1,
> +&hud->font_sampler_view);
> + cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, 1, sampler_states);
> + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0,&hud->constbuf);
> +
> + /* prepare vertex buffers */
> + hud_alloc_vertices(hud,&hud->bg, 4 * 64, 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));
> +
> + /* prepare all graphs */
> + LIST_FOR_EACH_ENTRY(pane,&hud->pane_list, head) {
> + LIST_FOR_EACH_ENTRY(gr,&pane->graph_list, head) {
> + gr->query_new_value(gr);
> + }
> +
> + hud_pane_accumulate_vertices(hud, pane);
> + }
> +
> + /* draw accumulated vertices for background quads */
> + cso_set_fragment_shader_handle(hud->cso, hud->fs_color);
> +
> + if (hud->bg.num_vertices) {
> + hud->constants.color[0] = 0;
> + hud->constants.color[1] = 0;
> + hud->constants.color[2] = 0;
> + hud->constants.color[3] = 0.666;
> + hud->constants.translate[0] = 0;
> + hud->constants.translate[1] = 0;
> + hud->constants.scale[0] = 1;
> + hud->constants.scale[1] = 1;
> +
> + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0,&hud->constbuf);
> + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1,
> +&hud->bg.vbuf);
> + cso_draw_arrays(cso, PIPE_PRIM_QUADS, 0, hud->bg.num_vertices);
> + }
> + pipe_resource_reference(&hud->bg.vbuf.buffer, NULL);
> +
> + /* draw accumulated vertices for white lines */
> + hud->constants.color[0] = 1;
> + hud->constants.color[1] = 1;
> + hud->constants.color[2] = 1;
> + hud->constants.color[3] = 1;
> + hud->constants.translate[0] = 0;
> + hud->constants.translate[1] = 0;
> + hud->constants.scale[0] = 1;
> + hud->constants.scale[1] = 1;
> + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0,&hud->constbuf);
> +
> + if (hud->whitelines.num_vertices) {
> + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1,
> +&hud->whitelines.vbuf);
> + 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);
> +
> + /* draw accumulated vertices for text */
> + if (hud->text.num_vertices) {
> + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1,
> +&hud->text.vbuf);
> + cso_set_fragment_shader_handle(hud->cso, hud->fs_texture);
> + cso_draw_arrays(cso, PIPE_PRIM_QUADS, 0, hud->text.num_vertices);
> + }
> + pipe_resource_reference(&hud->text.vbuf.buffer, NULL);
> +
> + /* draw the rest */
> + LIST_FOR_EACH_ENTRY(pane,&hud->pane_list, head) {
> + hud_pane_draw_colored_objects(hud, pane);
> + }
> +
> + /* restore states */
> + cso_restore_framebuffer(cso);
> + cso_restore_sample_mask(cso);
> + cso_restore_blend(cso);
> + cso_restore_depth_stencil_alpha(cso);
> + cso_restore_fragment_shader(cso);
> + cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT);
> + cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT);
> + cso_restore_rasterizer(cso);
> + cso_restore_viewport(cso);
> + cso_restore_stream_outputs(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_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
> + cso_restore_render_condition(cso);
> +
> + pipe_surface_reference(&surf, NULL);
> +}
> +
> +void
> +hud_pane_set_max_value(struct hud_pane *pane, uint64_t value)
> +{
> + pane->max_value = value;
> + pane->yscale = -(int)pane->inner_height / (double)pane->max_value;
> +}
> +
> +static struct hud_pane *
> +hud_pane_create(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
> + unsigned period, uint64_t max_value)
> +{
> + struct hud_pane *pane = CALLOC_STRUCT(hud_pane);
I'd put an "if (pane)" here, to silence coverity warnings, if nothing
else.
> + pane->x1 = x1;
> + pane->y1 = y1;
> + pane->x2 = x2;
> + pane->y2 = y2;
> + pane->inner_x1 = x1 + 1;
> + pane->inner_x2 = x2 - 1;
> + pane->inner_y1 = y1 + 1;
> + pane->inner_y2 = y2 - 1;
> + pane->inner_width = pane->inner_x2 - pane->inner_x1;
> + pane->inner_height = pane->inner_y2 - pane->inner_y1;
> + pane->period = period;
> + pane->max_num_vertices = (x2 - x1 + 2) / 2;
> + hud_pane_set_max_value(pane, max_value);
> + LIST_INITHEAD(&pane->graph_list);
> + return pane;
> +}
> +
> +void
> +hud_pane_add_graph(struct hud_pane *pane, struct hud_graph *gr)
> +{
> + static float colors[][3] = {
static const
> + {0, 1, 0},
> + {1, 0, 0},
> + {0, 1, 1},
> + {1, 0, 1},
> + {1, 1, 0},
> + {0.5, 0.5, 1},
> + {0.5, 0.5, 0.5},
> + };
> + char *name = gr->name;
> +
> + /* replace '-' with a space */
why?
> + while (*name) {
> + if (*name == '-')
> + *name = ' ';
> + name++;
> + }
> +
> + assert(pane->num_graphs< Elements(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->pane = pane;
> + LIST_ADDTAIL(&gr->head,&pane->graph_list);
> + pane->num_graphs++;
> +}
> +
> +void
> +hud_graph_add_value(struct hud_graph *gr, uint64_t value)
> +{
> + if (gr->index == gr->pane->max_num_vertices) {
> + gr->vertices[0] = 0;
> + gr->vertices[1] = gr->vertices[(gr->index-1)*2+1];
> + gr->index = 1;
> + }
> + gr->vertices[(gr->index)*2+0] = gr->index*2;
> + gr->vertices[(gr->index)*2+1] = value;
> + gr->index++;
> +
> + if (gr->num_vertices< gr->pane->max_num_vertices) {
> + gr->num_vertices++;
> + }
> +
> + gr->current_value = value;
> + if (value> gr->pane->max_value) {
> + hud_pane_set_max_value(gr->pane, value);
> + }
> +}
> +
> +static void
> +hud_graph_destroy(struct hud_graph *graph)
> +{
> + FREE(graph->vertices);
> + if (graph->free_query_data)
> + graph->free_query_data(graph->query_data);
> + FREE(graph);
> +}
> +
> +static int
> +get_string(const char *s, char *out)
Comment?
> +{
> + int i;
> +
> + for (i = 0; *s&& *s != '+'&& *s != ','&& *s != ':'&& *s != ';';
> + s++, out++, i++)
> + *out = *s;
> +
> + *out = 0;
> +
> + if (*s&& !i)
> + fprintf(stderr, "gallium_hud: syntax error: unexpected '%c' (%i) while "
> + "parsing a string\n", *s, *s);
> + return i;
> +}
> +
> +static boolean
> +has_occlusion_query(struct pipe_screen *screen)
> +{
> + return screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY) != 0;
> +}
> +
> +static boolean
> +has_streamout(struct pipe_screen *screen)
> +{
> + return screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;
> +}
> +
> +static void
> +hud_parse_env_var(struct hud_context *hud, const char *env)
> +{
> + unsigned num, i;
> + char name[256], s[256];
> + struct hud_pane *pane = NULL;
> + unsigned x = 10, y = 10;
> + unsigned width = 251, height = 100;
> +
> + while ((num = get_string(env, name)) != 0) {
> + env += num;
> +
> + if (!pane) {
> + pane = hud_pane_create(x, y, x + width, y + height, 40000, 10);
> + LIST_ADDTAIL(&pane->head,&hud->pane_list);
> + }
> +
> + /* add a graph */
> + if (strcmp(name, "fps") == 0) {
> + fps_graph_install(pane);
> + }
> + else if (strcmp(name, "cpu") == 0) {
> + cpu_graph_install(pane, ALL_CPUS);
> + }
> + else if (sscanf(name, "cpu%u%s",&i, s) == 1) {
> + cpu_graph_install(pane, i);
> + }
> + else if (strcmp(name, "pixels-rendered") == 0&&
> + has_occlusion_query(hud->pipe->screen)) {
> + pipe_query_install(pane, hud->pipe, "pixels-rendered",
> + PIPE_QUERY_OCCLUSION_COUNTER, 0, FALSE);
> + }
> + else if (strcmp(name, "primitives-generated") == 0&&
> + has_streamout(hud->pipe->screen)) {
> + pipe_query_install(pane, hud->pipe, "primitives-generated",
> + PIPE_QUERY_PRIMITIVES_GENERATED, 0, FALSE);
> + }
> + else {
> + if (!driver_query_install(pane, hud->pipe, name)){
> + fprintf(stderr, "gallium_hud: unknown driver query '%s'\n", name);
> + }
> + }
> +
> + if (*env == ':') {
> + env++;
> +
> + if (!pane) {
> + fprintf(stderr, "gallium_hud: syntax error: unexpected ':', "
> + "expected a name\n");
> + break;
> + }
> +
> + num = get_string(env, s);
> + env += num;
> +
> + if (num&& sscanf(s, "%u",&i) == 1) {
> + hud_pane_set_max_value(pane, i);
> + }
> + else {
> + fprintf(stderr, "gallium_hud: syntax error: unexpected '%c' (%i) "
> + "after ':'\n", *env, *env);
> + }
> + }
> +
> + if (*env == 0)
> + break;
> +
> + /* parse a separator */
> + switch (*env) {
> + case '+':
> + env++;
> + break;
> +
> + case ',':
> + env++;
> + y += height + hud->font.glyph_height * (pane->num_graphs + 2);
> + pane = NULL;
> + break;
> +
> + case ';':
> + env++;
> + y = 10;
> + x += width + hud->font.glyph_width * 7;
> + pane = NULL;
> + break;
> +
> + default:
> + fprintf(stderr, "gallium_hud: syntax error: unexpected '%c'\n", *env);
> + }
> + }
> +}
> +
> +static void
> +print_help(struct pipe_screen *screen)
> +{
> + int i, num_queries, num_cpus = get_num_cpus();
> +
> + puts("Syntax: GALLIUM_HUD=name1[+name2][...][:value1][,nameI...][;nameJ...]");
> + puts("");
> + puts(" Names are identifiers of data sources which will be drawn as graphs");
> + puts(" in panes. Multiple graphs can be drawn in the same pane.");
> + puts(" There can be multiple panes placed in rows and columns.");
> + puts("");
> + puts(" '+' separates names which will share a pane.");
> + puts(" ':[value]' specifies the initial maximum value of the Y axis");
> + 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("");
> + puts(" Example: GALLIUM_HUD=\"cpu,fps;primitives-generated\"");
> + puts("");
> + puts(" Available names:");
> + puts(" fps");
> + puts(" cpu");
> +
> + for (i = 0; i< num_cpus; i++)
> + printf(" cpu%i\n", i);
> +
> + if (has_occlusion_query(screen))
> + puts(" pixels-rendered");
> + if (has_streamout(screen))
> + puts(" primitives-generated");
> +
> + if (screen->get_driver_query_info){
> + 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);
> + }
> + }
> +
> + puts("");
> +}
> +
> +struct hud_context *
> +hud_create(struct pipe_context *pipe, struct cso_context *cso)
> +{
> + struct hud_context *hud;
> + struct pipe_sampler_view view_templ;
> + unsigned i;
> + const char *env = debug_get_option("GALLIUM_HUD", NULL);
> +
> + if (!env || !*env)
> + return NULL;
> +
> + if (strcmp(env, "help") == 0) {
> + print_help(pipe->screen);
> + return NULL;
> + }
> +
> + hud = CALLOC_STRUCT(hud_context);
> + if (!hud)
> + return NULL;
> +
> + hud->pipe = pipe;
> + hud->cso = cso;
> + hud->uploader = u_upload_create(pipe, 256 * 1024, 16,
> + PIPE_BIND_VERTEX_BUFFER);
> +
> + /* font */
> + if (!util_font_create(pipe, UTIL_FONT_FIXED_8X13,&hud->font)) {
> + u_upload_destroy(hud->uploader);
> + FREE(hud);
> + return NULL;
> + }
> +
> + /* blend state */
> + 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;
> + hud->alpha_blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
> + hud->alpha_blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
> + hud->alpha_blend.rt[0].alpha_func = PIPE_BLEND_ADD;
> + hud->alpha_blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
> + hud->alpha_blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
> +
> + /* fragment shader */
> + hud->fs_color =
> + util_make_fragment_passthrough_shader(pipe,
> + TGSI_SEMANTIC_COLOR,
> + TGSI_INTERPOLATE_CONSTANT);
> +
> + hud->fs_texture =
> + util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_RECT,
> + TGSI_INTERPOLATE_PERSPECTIVE);
> +
> + /* rasterizer */
> + hud->rasterizer.gl_rasterization_rules = 1;
> + hud->rasterizer.depth_clip = 1;
> + hud->rasterizer.line_width = 1;
> + hud->rasterizer.line_last_pixel = 1;
> +
> + /* vertex shader */
> + {
> + static const char *vertex_shader_text = {
> + "VERT\n"
> + "DCL IN[0..1]\n"
> + "DCL OUT[0], POSITION\n"
> + "DCL OUT[1], COLOR[0]\n" /* color */
> + "DCL OUT[2], GENERIC[0]\n" /* texcoord */
> + /* [0] = color,
> + * [1] = (2/fb_width, 2/fb_height, xoffset, yoffset)
> + * [2] = (xscale, yscale, 0, 0) */
> + "DCL CONST[0..2]\n"
> + "DCL TEMP[0]\n"
> + "IMM[0] FLT32 { -1, 0, 0, 1 }\n"
> +
> + /* v = in * (xscale, yscale) + (xoffset, yoffset) */
> + "MAD TEMP[0].xy, IN[0], CONST[2].xyyy, CONST[1].zwww\n"
> + /* pos = v * (2 / fb_width, 2 / fb_height) - (1, 1) */
> + "MAD OUT[0].xy, TEMP[0], CONST[1].xyyy, IMM[0].xxxx\n"
> + "MOV OUT[0].zw, IMM[0]\n"
> +
> + "MOV OUT[1], CONST[0]\n"
> + "MOV OUT[2], IN[1]\n"
> + "END\n"
> + };
> +
> + struct tgsi_token tokens[1000];
> + struct pipe_shader_state state = {tokens};
> +
> + if (!tgsi_text_translate(vertex_shader_text, tokens, Elements(tokens))) {
> + assert(0);
> + pipe_resource_reference(&hud->font.texture, NULL);
> + u_upload_destroy(hud->uploader);
> + FREE(hud);
> + return NULL;
> + }
> +
> + hud->vs = pipe->create_vs_state(pipe,&state);
> + }
> +
> + /* vertex elements */
> + for (i = 0; i< 2; i++) {
> + hud->velems[i].src_offset = i * 2 * sizeof(float);
> + hud->velems[i].src_format = PIPE_FORMAT_R32G32_FLOAT;
> + hud->velems[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso);
> + }
> +
> + /* sampler view */
> + memset(&view_templ, 0, sizeof(view_templ));
> + view_templ.format = hud->font.texture->format;
> + view_templ.swizzle_r = PIPE_SWIZZLE_RED;
> + view_templ.swizzle_g = PIPE_SWIZZLE_GREEN;
> + view_templ.swizzle_b = PIPE_SWIZZLE_BLUE;
> + view_templ.swizzle_a = PIPE_SWIZZLE_ALPHA;
> + hud->font_sampler_view = pipe->create_sampler_view(pipe, hud->font.texture,
> +&view_templ);
> +
> + /* constants */
> + hud->constbuf.buffer_size = sizeof(hud->constants);
> + hud->constbuf.user_buffer =&hud->constants;
> +
> + LIST_INITHEAD(&hud->pane_list);
> +
> + hud_parse_env_var(hud, env);
> + return hud;
> +}
> +
> +void
> +hud_destroy(struct hud_context *hud)
> +{
> + struct pipe_context *pipe = hud->pipe;
> + struct hud_pane *pane, *pane_tmp;
> + struct hud_graph *graph, *graph_tmp;
> +
> + LIST_FOR_EACH_ENTRY_SAFE(pane, pane_tmp,&hud->pane_list, head) {
> + LIST_FOR_EACH_ENTRY_SAFE(graph, graph_tmp,&pane->graph_list, head) {
> + LIST_DEL(&graph->head);
> + hud_graph_destroy(graph);
> + }
> + LIST_DEL(&pane->head);
> + FREE(pane);
> + }
> +
> + pipe->delete_fs_state(pipe, hud->fs_color);
> + pipe->delete_fs_state(pipe, hud->fs_texture);
> + 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);
> +}
> diff --git a/src/gallium/auxiliary/hud/hud_context.h b/src/gallium/auxiliary/hud/hud_context.h
> new file mode 100644
> index 0000000..abf2ad5
> --- /dev/null
> +++ b/src/gallium/auxiliary/hud/hud_context.h
> @@ -0,0 +1,45 @@
> +/**************************************************************************
> + *
> + * Copyright 2013 Marek Olšák<maraeo at gmail.com>
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + **************************************************************************/
> +
> +#ifndef HUD_CONTEXT_H
> +#define HUD_CONTEXT_H
> +
> +struct hud_context;
> +struct cso_context;
> +struct pipe_context;
> +struct pipe_resource;
> +
> +struct hud_context *
> +hud_create(struct pipe_context *pipe, struct cso_context *cso);
> +
> +void
> +hud_destroy(struct hud_context *hud);
> +
> +void
> +hud_draw(struct hud_context *hud, struct pipe_resource *tex);
> +
> +#endif
> diff --git a/src/gallium/auxiliary/hud/hud_cpu.c b/src/gallium/auxiliary/hud/hud_cpu.c
> new file mode 100644
> index 0000000..5b84fd9
> --- /dev/null
> +++ b/src/gallium/auxiliary/hud/hud_cpu.c
> @@ -0,0 +1,153 @@
> +/**************************************************************************
> + *
> + * Copyright 2013 Marek Olšák<maraeo at gmail.com>
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + **************************************************************************/
> +
> +/* This file contains code for reading CPU load for displaying on the HUD.
> + */
> +
> +#include "hud/hud_private.h"
> +#include "os/os_time.h"
> +#include "util/u_memory.h"
> +#include<stdio.h>
> +
> +static boolean
> +get_cpu_stats(unsigned cpu_index, uint64_t *busy_time, uint64_t *total_time)
> +{
> + char cpuname[32];
> + char line[1024];
> + FILE *f;
> +
> + if (cpu_index == ALL_CPUS)
> + strcpy(cpuname, "cpu");
> + else
> + sprintf(cpuname, "cpu%u", cpu_index);
> +
> + f = fopen("/proc/stat", "r");
Obviously, this won't work on Windows. We don't want to crash there
if we mis-set the HUD env var, so let's at least put an "if (f)" in here.
> + while (!feof(f)&& fgets(line, sizeof(line), f)) {
> + if (strstr(line, cpuname) == line) {
> + uint64_t v[12];
> + int i, num;
> +
> + num = sscanf(line,
> + "%s %llu %llu %llu %llu %llu %llu %llu %llu %llu "
> + "%llu %llu %llu",
> + cpuname,&v[0],&v[1],&v[2],&v[3],&v[4],&v[5],
> +&v[6],&v[7],&v[8],&v[9],&v[10],&v[11]);
> + if (num< 5) {
> + fclose(f);
> + return FALSE;
> + }
> +
> + /* user + nice + system */
> + *busy_time = v[0] + v[1] + v[2];
> + *total_time = *busy_time;
> +
> + /* ... + idle + iowait + irq + softirq + ... */
> + for (i = 3; i< num-1; i++) {
> + *total_time += v[i];
> + }
> + fclose(f);
> + return TRUE;
> + }
> + }
> + fclose(f);
> + return FALSE;
> +}
> +
> +struct cpu_info {
> + unsigned cpu_index;
> + uint64_t last_cpu_busy, last_cpu_total, last_time;
> +};
> +
> +static void
> +query_cpu_load(struct hud_graph *gr)
> +{
> + struct cpu_info *info = gr->query_data;
> + uint64_t now = os_time_get();
> +
> + if (info->last_time) {
> + if (info->last_time + gr->pane->period<= now) {
> + uint64_t cpu_busy, cpu_total, cpu_load;
> +
> + get_cpu_stats(info->cpu_index,&cpu_busy,&cpu_total);
> +
> + cpu_load = (cpu_busy - info->last_cpu_busy) * 100 /
> + (double)(cpu_total - info->last_cpu_total);
> + hud_graph_add_value(gr, cpu_load);
> +
> + info->last_cpu_busy = cpu_busy;
> + info->last_cpu_total = cpu_total;
> + info->last_time = now;
> + }
> + }
> + else {
> + /* initialize */
> + info->last_time = now;
> + get_cpu_stats(info->cpu_index,&info->last_cpu_busy,
> +&info->last_cpu_total);
> + }
> +}
> +
> +void
> +cpu_graph_install(struct hud_pane *pane, unsigned cpu_index)
> +{
> + struct hud_graph *gr;
> + struct cpu_info *info;
> + uint64_t busy, total;
> +
> + /* see if the cpu exists */
> + if (cpu_index != ALL_CPUS&& !get_cpu_stats(cpu_index,&busy,&total)) {
> + return;
> + }
> +
> + gr = CALLOC_STRUCT(hud_graph);
if (gr)
> +
> + if (cpu_index == ALL_CPUS)
> + strcpy(gr->name, "cpu");
> + else
> + sprintf(gr->name, "cpu%u", cpu_index);
> + gr->query_data = CALLOC_STRUCT(cpu_info);
> + gr->query_new_value = query_cpu_load;
> + gr->free_query_data = free;
> +
> + info = gr->query_data;
> + info->cpu_index = cpu_index;
> +
> + hud_pane_add_graph(pane, gr);
> + hud_pane_set_max_value(pane, 100);
> +}
> +
> +int
> +get_num_cpus(void)
> +{
> + uint64_t busy, total;
> + int i = 0;
> +
> + while (get_cpu_stats(i,&busy,&total))
> + i++;
> +
> + return i;
> +}
I wonder if some of this CPU-related code could go into src/gallum/util/
> diff --git a/src/gallium/auxiliary/hud/hud_driver_query.c b/src/gallium/auxiliary/hud/hud_driver_query.c
> new file mode 100644
> index 0000000..1c85d76
> --- /dev/null
> +++ b/src/gallium/auxiliary/hud/hud_driver_query.c
> @@ -0,0 +1,200 @@
> +/**************************************************************************
> + *
> + * Copyright 2013 Marek Olšák<maraeo at gmail.com>
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + **************************************************************************/
> +
> +/* This file contains code for reading values from pipe queries
> + * for displaying on the HUD. To prevent stalls when reading queries, we
> + * keep a list of busy queries in a ring. We read only those queries which
> + * are idle.
> + */
> +
> +#include "hud/hud_private.h"
> +#include "pipe/p_screen.h"
> +#include "os/os_time.h"
> +#include "util/u_memory.h"
> +#include<stdio.h>
> +
> +#define NUM_QUERIES 8
> +
> +struct query_info {
> + struct pipe_context *pipe;
> + unsigned query_type;
> +
> + /* 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;
> + unsigned num_results;
> +};
> +
> +static void
> +query_new_value(struct hud_graph *gr)
> +{
> + struct query_info *info = gr->query_data;
> + struct pipe_context *pipe = info->pipe;
> + uint64_t now = os_time_get();
> +
> + if (info->last_time) {
> + pipe->end_query(pipe, info->query[info->head]);
> +
> + /* read query results */
> + while (1) {
> + struct pipe_query *query = info->query[info->tail];
> + union pipe_query_result result;
> + result.u64 = 0;
> +
> + if (pipe->get_query_result(pipe, query, FALSE,&result)) {
> + info->results_cumulative += result.u64;
> + info->num_results++;
> +
> + if (info->tail == info->head)
> + break;
> +
> + info->tail = (info->tail+1) % NUM_QUERIES;
> + }
> + else {
> + /* the oldest query is busy */
> + if ((info->head+1) % NUM_QUERIES == info->tail) {
> + /* all queries are busy, throw away the last query and create
> + * a new one */
> + fprintf(stderr,
> + "gallium_hud: all queries are busy after %i frames, "
> + "can't add another query\n",
> + NUM_QUERIES);
> + pipe->destroy_query(pipe, info->query[info->head]);
> + info->query[info->head] =
> + pipe->create_query(pipe, info->query_type);
> + }
> + else {
> + /* the last query is busy, we need to add a new one we can use
> + * for this frame */
> + info->head = (info->head+1) % NUM_QUERIES;
> + if (!info->query[info->head]) {
> + info->query[info->head] =
> + pipe->create_query(pipe, info->query_type);
> + }
> + }
> + break;
> + }
> + }
> +
> + if (info->num_results&& info->last_time + gr->pane->period<= now) {
> + /* compute the average value across all frames */
> + hud_graph_add_value(gr, info->results_cumulative / info->num_results);
> +
> + info->last_time = now;
> + info->results_cumulative = 0;
> + info->num_results = 0;
> + }
> +
> + pipe->begin_query(pipe, info->query[info->head]);
> + }
> + else {
> + /* initialize */
> + info->last_time = now;
> + info->query[info->head] = pipe->create_query(pipe, info->query_type);
> + pipe->begin_query(pipe, info->query[info->head]);
> + }
> +}
> +
> +static void
> +free_query_info(void *ptr)
> +{
> + struct query_info *info = ptr;
> +
> + if (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++) {
> + if (info->query[i]) {
> + pipe->destroy_query(pipe, info->query[i]);
> + }
> + }
> + }
> + FREE(info);
> +}
> +
> +void
> +pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe,
> + const char *name, unsigned query_type, uint64_t max_value,
> + boolean uses_byte_units)
> +{
> + struct hud_graph *gr;
> + struct query_info *info;
> +
> + gr = CALLOC_STRUCT(hud_graph);
if (gr)
> +
> + strcpy(gr->name, name);
> + gr->query_data = CALLOC_STRUCT(query_info);
> + 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;
> +
> + hud_pane_add_graph(pane, gr);
> + if (pane->max_value< max_value)
> + hud_pane_set_max_value(pane, max_value);
> + if (uses_byte_units)
> + pane->uses_byte_units = TRUE;
> +}
> +
> +boolean
> +driver_query_install(struct hud_pane *pane, struct pipe_context *pipe,
> + const char *name)
> +{
> + struct pipe_screen *screen = pipe->screen;
> + struct pipe_driver_query_info query;
> + unsigned num_queries, i;
> + boolean found = FALSE;
> +
> + if (!screen->get_driver_query_info)
> + return FALSE;
> +
> + num_queries = screen->get_driver_query_info(screen, 0, NULL);
> +
> + for (i = 0; i< num_queries; i++) {
> + if (screen->get_driver_query_info(screen, i,&query)&&
> + strcmp(query.name, name) == 0) {
> + found = TRUE;
> + break;
> + }
> + }
> +
> + if (!found)
> + return FALSE;
> +
> + pipe_query_install(pane, pipe, query.name, query.query_type,
> + query.max_value, query.uses_byte_units);
> + return TRUE;
> +}
> diff --git a/src/gallium/auxiliary/hud/hud_fps.c b/src/gallium/auxiliary/hud/hud_fps.c
> new file mode 100644
> index 0000000..af59222
> --- /dev/null
> +++ b/src/gallium/auxiliary/hud/hud_fps.c
> @@ -0,0 +1,73 @@
> +/**************************************************************************
> + *
> + * Copyright 2013 Marek Olšák<maraeo at gmail.com>
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + **************************************************************************/
> +
> +/* This file contains code for calculating framerate for displaying on the HUD.
> + */
> +
> +#include "hud/hud_private.h"
> +#include "os/os_time.h"
> +#include "util/u_memory.h"
> +
> +struct fps_info {
> + int frames;
> + uint64_t last_time;
> +};
> +
> +static void
> +query_fps(struct hud_graph *gr)
> +{
> + struct fps_info *info = gr->query_data;
> + uint64_t now = os_time_get();
> +
> + info->frames++;
> +
> + if (info->last_time) {
> + if (info->last_time + gr->pane->period<= now) {
> + double fps = info->frames * 1000000 / (double)(now - info->last_time);
> + info->frames = 0;
> + info->last_time = now;
> +
> + hud_graph_add_value(gr, fps);
> + }
> + }
> + else {
> + info->last_time = now;
> + }
> +}
> +
> +void
> +fps_graph_install(struct hud_pane *pane)
hud_fps_graph_install()?
> +{
> + struct hud_graph *gr = CALLOC_STRUCT(hud_graph);
> +
> + strcpy(gr->name, "fps");
> + gr->query_data = CALLOC_STRUCT(fps_info);
> + gr->query_new_value = query_fps;
> + gr->free_query_data = free;
> +
> + hud_pane_add_graph(pane, gr);
> +}
> diff --git a/src/gallium/auxiliary/hud/hud_private.h b/src/gallium/auxiliary/hud/hud_private.h
> new file mode 100644
> index 0000000..8054b23
> --- /dev/null
> +++ b/src/gallium/auxiliary/hud/hud_private.h
> @@ -0,0 +1,91 @@
> +/**************************************************************************
> + *
> + * Copyright 2013 Marek Olšák<maraeo at gmail.com>
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + **************************************************************************/
> +
> +#ifndef HUD_PRIVATE_H
> +#define HUD_PRIVATE_H
> +
> +#include "pipe/p_context.h"
> +#include "util/u_double_list.h"
> +
> +struct hud_graph {
> + /* initialized by common code */
> + struct list_head head;
> + struct hud_pane *pane;
> + float color[3];
> + float *vertices; /* ring buffer of vertices */
> +
> + /* name and query */
> + char name[128];
> + void *query_data;
> + void (*query_new_value)(struct hud_graph *gr);
> + void (*free_query_data)(void *ptr);
> +
> + /* mutable variables */
> + unsigned num_vertices;
> + unsigned index; /* vertex index being updated */
> + uint64_t current_value;
> +};
> +
> +struct hud_pane {
> + struct list_head head;
> + unsigned x1, y1, x2, y2;
> + unsigned inner_x1;
> + unsigned inner_y1;
> + unsigned inner_x2;
> + unsigned inner_y2;
> + unsigned inner_width;
> + unsigned inner_height;
> + float yscale;
> + unsigned max_num_vertices;
> + uint64_t max_value;
> + boolean uses_byte_units;
> + uint64_t period; /* in microseconds */
> +
> + struct list_head graph_list;
> + unsigned num_graphs;
> +};
> +
> +
> +/* core */
> +void hud_pane_add_graph(struct hud_pane *pane, struct hud_graph *gr);
> +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 */
> +#define ALL_CPUS ~0 /* optionally set as cpu_index */
> +
> +int get_num_cpus(void);
> +
> +void fps_graph_install(struct hud_pane *pane);
> +void cpu_graph_install(struct hud_pane *pane, unsigned cpu_index);
> +void pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe,
> + const char *name, unsigned query_type, uint64_t max_value,
> + boolean uses_byte_units);
> +boolean driver_query_install(struct hud_pane *pane, struct pipe_context *pipe,
> + const char *name);
> +
> +#endif
More information about the mesa-dev
mailing list