Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2013 Marek Olšák <maraeo@gmail.com>
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. /* This file contains code for reading values from pipe queries
  29.  * for displaying on the HUD. To prevent stalls when reading queries, we
  30.  * keep a list of busy queries in a ring. We read only those queries which
  31.  * are idle.
  32.  */
  33.  
  34. #include "hud/hud_private.h"
  35. #include "pipe/p_screen.h"
  36. #include "os/os_time.h"
  37. #include "util/u_memory.h"
  38. #include <stdio.h>
  39.  
  40. #define NUM_QUERIES 8
  41.  
  42. struct query_info {
  43.    struct pipe_context *pipe;
  44.    unsigned query_type;
  45.    unsigned result_index; /* unit depends on query_type */
  46.  
  47.    /* Ring of queries. If a query is busy, we use another slot. */
  48.    struct pipe_query *query[NUM_QUERIES];
  49.    unsigned head, tail;
  50.    unsigned num_queries;
  51.  
  52.    uint64_t last_time;
  53.    uint64_t results_cumulative;
  54.    unsigned num_results;
  55. };
  56.  
  57. static void
  58. query_new_value(struct hud_graph *gr)
  59. {
  60.    struct query_info *info = gr->query_data;
  61.    struct pipe_context *pipe = info->pipe;
  62.    uint64_t now = os_time_get();
  63.  
  64.    if (info->last_time) {
  65.       pipe->end_query(pipe, info->query[info->head]);
  66.  
  67.       /* read query results */
  68.       while (1) {
  69.          struct pipe_query *query = info->query[info->tail];
  70.          union pipe_query_result result;
  71.          uint64_t *res64 = (uint64_t *)&result;
  72.  
  73.          if (pipe->get_query_result(pipe, query, FALSE, &result)) {
  74.             info->results_cumulative += res64[info->result_index];
  75.             info->num_results++;
  76.  
  77.             if (info->tail == info->head)
  78.                break;
  79.  
  80.             info->tail = (info->tail+1) % NUM_QUERIES;
  81.          }
  82.          else {
  83.             /* the oldest query is busy */
  84.             if ((info->head+1) % NUM_QUERIES == info->tail) {
  85.                /* all queries are busy, throw away the last query and create
  86.                 * a new one */
  87.                fprintf(stderr,
  88.                        "gallium_hud: all queries are busy after %i frames, "
  89.                        "can't add another query\n",
  90.                        NUM_QUERIES);
  91.                pipe->destroy_query(pipe, info->query[info->head]);
  92.                info->query[info->head] =
  93.                      pipe->create_query(pipe, info->query_type, 0);
  94.             }
  95.             else {
  96.                /* the last query is busy, we need to add a new one we can use
  97.                 * for this frame */
  98.                info->head = (info->head+1) % NUM_QUERIES;
  99.                if (!info->query[info->head]) {
  100.                   info->query[info->head] =
  101.                         pipe->create_query(pipe, info->query_type, 0);
  102.                }
  103.             }
  104.             break;
  105.          }
  106.       }
  107.  
  108.       if (info->num_results && info->last_time + gr->pane->period <= now) {
  109.          /* compute the average value across all frames */
  110.          hud_graph_add_value(gr, info->results_cumulative / info->num_results);
  111.  
  112.          info->last_time = now;
  113.          info->results_cumulative = 0;
  114.          info->num_results = 0;
  115.       }
  116.  
  117.       pipe->begin_query(pipe, info->query[info->head]);
  118.    }
  119.    else {
  120.       /* initialize */
  121.       info->last_time = now;
  122.       info->query[info->head] = pipe->create_query(pipe, info->query_type, 0);
  123.       pipe->begin_query(pipe, info->query[info->head]);
  124.    }
  125. }
  126.  
  127. static void
  128. free_query_info(void *ptr)
  129. {
  130.    struct query_info *info = ptr;
  131.  
  132.    if (info->last_time) {
  133.       struct pipe_context *pipe = info->pipe;
  134.       int i;
  135.  
  136.       pipe->end_query(pipe, info->query[info->head]);
  137.  
  138.       for (i = 0; i < Elements(info->query); i++) {
  139.          if (info->query[i]) {
  140.             pipe->destroy_query(pipe, info->query[i]);
  141.          }
  142.       }
  143.    }
  144.    FREE(info);
  145. }
  146.  
  147. void
  148. hud_pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe,
  149.                        const char *name, unsigned query_type,
  150.                        unsigned result_index,
  151.                        uint64_t max_value, boolean uses_byte_units)
  152. {
  153.    struct hud_graph *gr;
  154.    struct query_info *info;
  155.  
  156.    gr = CALLOC_STRUCT(hud_graph);
  157.    if (!gr)
  158.       return;
  159.  
  160.    strncpy(gr->name, name, sizeof(gr->name));
  161.    gr->name[sizeof(gr->name) - 1] = '\0';
  162.    gr->query_data = CALLOC_STRUCT(query_info);
  163.    if (!gr->query_data) {
  164.       FREE(gr);
  165.       return;
  166.    }
  167.  
  168.    gr->query_new_value = query_new_value;
  169.    gr->free_query_data = free_query_info;
  170.  
  171.    info = gr->query_data;
  172.    info->pipe = pipe;
  173.    info->query_type = query_type;
  174.    info->result_index = result_index;
  175.  
  176.    hud_pane_add_graph(pane, gr);
  177.    if (pane->max_value < max_value)
  178.       hud_pane_set_max_value(pane, max_value);
  179.    if (uses_byte_units)
  180.       pane->uses_byte_units = TRUE;
  181. }
  182.  
  183. boolean
  184. hud_driver_query_install(struct hud_pane *pane, struct pipe_context *pipe,
  185.                          const char *name)
  186. {
  187.    struct pipe_screen *screen = pipe->screen;
  188.    struct pipe_driver_query_info query;
  189.    unsigned num_queries, i;
  190.    boolean uses_byte_units;
  191.    boolean found = FALSE;
  192.  
  193.    if (!screen->get_driver_query_info)
  194.       return FALSE;
  195.  
  196.    num_queries = screen->get_driver_query_info(screen, 0, NULL);
  197.  
  198.    for (i = 0; i < num_queries; i++) {
  199.       if (screen->get_driver_query_info(screen, i, &query) &&
  200.           strcmp(query.name, name) == 0) {
  201.          found = TRUE;
  202.          break;
  203.       }
  204.    }
  205.  
  206.    if (!found)
  207.       return FALSE;
  208.  
  209.    uses_byte_units = query.type == PIPE_DRIVER_QUERY_TYPE_BYTES;
  210.    hud_pipe_query_install(pane, pipe, query.name, query.query_type, 0,
  211.                           query.max_value.u64, uses_byte_units);
  212.  
  213.    return TRUE;
  214. }
  215.