[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