1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2013 Marek Olšák <maraeo@gmail.com>
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/* This file contains code for reading values from pipe queries
29bf215546Sopenharmony_ci * for displaying on the HUD. To prevent stalls when reading queries, we
30bf215546Sopenharmony_ci * keep a list of busy queries in a ring. We read only those queries which
31bf215546Sopenharmony_ci * are idle.
32bf215546Sopenharmony_ci */
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#include "hud/hud_private.h"
35bf215546Sopenharmony_ci#include "pipe/p_screen.h"
36bf215546Sopenharmony_ci#include "util/os_time.h"
37bf215546Sopenharmony_ci#include "util/u_math.h"
38bf215546Sopenharmony_ci#include "util/u_memory.h"
39bf215546Sopenharmony_ci#include <stdio.h>
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci// Must be a power of two
42bf215546Sopenharmony_ci#define NUM_QUERIES 8
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_cistruct hud_batch_query_context {
45bf215546Sopenharmony_ci   unsigned num_query_types;
46bf215546Sopenharmony_ci   unsigned allocated_query_types;
47bf215546Sopenharmony_ci   unsigned *query_types;
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   boolean failed;
50bf215546Sopenharmony_ci   struct pipe_query *query[NUM_QUERIES];
51bf215546Sopenharmony_ci   union pipe_query_result *result[NUM_QUERIES];
52bf215546Sopenharmony_ci   unsigned head, pending, results;
53bf215546Sopenharmony_ci};
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_civoid
56bf215546Sopenharmony_cihud_batch_query_update(struct hud_batch_query_context *bq,
57bf215546Sopenharmony_ci                       struct pipe_context *pipe)
58bf215546Sopenharmony_ci{
59bf215546Sopenharmony_ci   if (!bq || bq->failed)
60bf215546Sopenharmony_ci      return;
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   if (bq->query[bq->head])
63bf215546Sopenharmony_ci      pipe->end_query(pipe, bq->query[bq->head]);
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   bq->results = 0;
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   while (bq->pending) {
68bf215546Sopenharmony_ci      unsigned idx = (bq->head - bq->pending + 1) % NUM_QUERIES;
69bf215546Sopenharmony_ci      struct pipe_query *query = bq->query[idx];
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci      if (!bq->result[idx])
72bf215546Sopenharmony_ci         bq->result[idx] = MALLOC(sizeof(bq->result[idx]->batch[0]) *
73bf215546Sopenharmony_ci                                  bq->num_query_types);
74bf215546Sopenharmony_ci      if (!bq->result[idx]) {
75bf215546Sopenharmony_ci         fprintf(stderr, "gallium_hud: out of memory.\n");
76bf215546Sopenharmony_ci         bq->failed = TRUE;
77bf215546Sopenharmony_ci         return;
78bf215546Sopenharmony_ci      }
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci      if (!pipe->get_query_result(pipe, query, FALSE, bq->result[idx]))
81bf215546Sopenharmony_ci         break;
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci      ++bq->results;
84bf215546Sopenharmony_ci      --bq->pending;
85bf215546Sopenharmony_ci   }
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   bq->head = (bq->head + 1) % NUM_QUERIES;
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   if (bq->pending == NUM_QUERIES) {
90bf215546Sopenharmony_ci      fprintf(stderr,
91bf215546Sopenharmony_ci              "gallium_hud: all queries busy after %i frames, dropping data.\n",
92bf215546Sopenharmony_ci              NUM_QUERIES);
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci      assert(bq->query[bq->head]);
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci      pipe->destroy_query(pipe, bq->query[bq->head]);
97bf215546Sopenharmony_ci      bq->query[bq->head] = NULL;
98bf215546Sopenharmony_ci   }
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   ++bq->pending;
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   if (!bq->query[bq->head]) {
103bf215546Sopenharmony_ci      bq->query[bq->head] = pipe->create_batch_query(pipe,
104bf215546Sopenharmony_ci                                                     bq->num_query_types,
105bf215546Sopenharmony_ci                                                     bq->query_types);
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci      if (!bq->query[bq->head]) {
108bf215546Sopenharmony_ci         fprintf(stderr,
109bf215546Sopenharmony_ci                 "gallium_hud: create_batch_query failed. You may have "
110bf215546Sopenharmony_ci                 "selected too many or incompatible queries.\n");
111bf215546Sopenharmony_ci         bq->failed = TRUE;
112bf215546Sopenharmony_ci         return;
113bf215546Sopenharmony_ci      }
114bf215546Sopenharmony_ci   }
115bf215546Sopenharmony_ci}
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_civoid
118bf215546Sopenharmony_cihud_batch_query_begin(struct hud_batch_query_context *bq,
119bf215546Sopenharmony_ci                      struct pipe_context *pipe)
120bf215546Sopenharmony_ci{
121bf215546Sopenharmony_ci   if (!bq || bq->failed || !bq->query[bq->head])
122bf215546Sopenharmony_ci      return;
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   if (!pipe->begin_query(pipe, bq->query[bq->head])) {
125bf215546Sopenharmony_ci      fprintf(stderr,
126bf215546Sopenharmony_ci              "gallium_hud: could not begin batch query. You may have "
127bf215546Sopenharmony_ci              "selected too many or incompatible queries.\n");
128bf215546Sopenharmony_ci      bq->failed = TRUE;
129bf215546Sopenharmony_ci   }
130bf215546Sopenharmony_ci}
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_cistatic boolean
133bf215546Sopenharmony_cibatch_query_add(struct hud_batch_query_context **pbq,
134bf215546Sopenharmony_ci                unsigned query_type, unsigned *result_index)
135bf215546Sopenharmony_ci{
136bf215546Sopenharmony_ci   struct hud_batch_query_context *bq = *pbq;
137bf215546Sopenharmony_ci   unsigned i;
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci   if (!bq) {
140bf215546Sopenharmony_ci      bq = CALLOC_STRUCT(hud_batch_query_context);
141bf215546Sopenharmony_ci      if (!bq)
142bf215546Sopenharmony_ci         return false;
143bf215546Sopenharmony_ci      *pbq = bq;
144bf215546Sopenharmony_ci   }
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   for (i = 0; i < bq->num_query_types; ++i) {
147bf215546Sopenharmony_ci      if (bq->query_types[i] == query_type) {
148bf215546Sopenharmony_ci         *result_index = i;
149bf215546Sopenharmony_ci         return true;
150bf215546Sopenharmony_ci      }
151bf215546Sopenharmony_ci   }
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   if (bq->num_query_types == bq->allocated_query_types) {
154bf215546Sopenharmony_ci      unsigned new_alloc = MAX2(16, bq->allocated_query_types * 2);
155bf215546Sopenharmony_ci      unsigned *new_query_types
156bf215546Sopenharmony_ci         = REALLOC(bq->query_types,
157bf215546Sopenharmony_ci                   bq->allocated_query_types * sizeof(unsigned),
158bf215546Sopenharmony_ci                   new_alloc * sizeof(unsigned));
159bf215546Sopenharmony_ci      if (!new_query_types)
160bf215546Sopenharmony_ci         return false;
161bf215546Sopenharmony_ci      bq->query_types = new_query_types;
162bf215546Sopenharmony_ci      bq->allocated_query_types = new_alloc;
163bf215546Sopenharmony_ci   }
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   bq->query_types[bq->num_query_types] = query_type;
166bf215546Sopenharmony_ci   *result_index = bq->num_query_types++;
167bf215546Sopenharmony_ci   return true;
168bf215546Sopenharmony_ci}
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_civoid
171bf215546Sopenharmony_cihud_batch_query_cleanup(struct hud_batch_query_context **pbq,
172bf215546Sopenharmony_ci                        struct pipe_context *pipe)
173bf215546Sopenharmony_ci{
174bf215546Sopenharmony_ci   struct hud_batch_query_context *bq = *pbq;
175bf215546Sopenharmony_ci   unsigned idx;
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   if (!bq)
178bf215546Sopenharmony_ci      return;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   *pbq = NULL;
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   if (bq->query[bq->head] && !bq->failed)
183bf215546Sopenharmony_ci      pipe->end_query(pipe, bq->query[bq->head]);
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   for (idx = 0; idx < NUM_QUERIES; ++idx) {
186bf215546Sopenharmony_ci      if (bq->query[idx])
187bf215546Sopenharmony_ci         pipe->destroy_query(pipe, bq->query[idx]);
188bf215546Sopenharmony_ci      FREE(bq->result[idx]);
189bf215546Sopenharmony_ci   }
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci   FREE(bq->query_types);
192bf215546Sopenharmony_ci   FREE(bq);
193bf215546Sopenharmony_ci}
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_cistruct query_info {
196bf215546Sopenharmony_ci   struct hud_batch_query_context *batch;
197bf215546Sopenharmony_ci   enum pipe_query_type query_type;
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   /** index to choose fields in pipe_query_data_pipeline_statistics,
200bf215546Sopenharmony_ci    * for example.
201bf215546Sopenharmony_ci    */
202bf215546Sopenharmony_ci   unsigned result_index;
203bf215546Sopenharmony_ci   enum pipe_driver_query_result_type result_type;
204bf215546Sopenharmony_ci   enum pipe_driver_query_type type;
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   /* Ring of queries. If a query is busy, we use another slot. */
207bf215546Sopenharmony_ci   struct pipe_query *query[NUM_QUERIES];
208bf215546Sopenharmony_ci   unsigned head, tail;
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   uint64_t last_time;
211bf215546Sopenharmony_ci   uint64_t results_cumulative;
212bf215546Sopenharmony_ci   unsigned num_results;
213bf215546Sopenharmony_ci};
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_cistatic void
216bf215546Sopenharmony_ciquery_new_value_batch(struct query_info *info)
217bf215546Sopenharmony_ci{
218bf215546Sopenharmony_ci   struct hud_batch_query_context *bq = info->batch;
219bf215546Sopenharmony_ci   unsigned result_index = info->result_index;
220bf215546Sopenharmony_ci   unsigned idx = (bq->head - bq->pending) % NUM_QUERIES;
221bf215546Sopenharmony_ci   unsigned results = bq->results;
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci   while (results) {
224bf215546Sopenharmony_ci      info->results_cumulative += bq->result[idx]->batch[result_index].u64;
225bf215546Sopenharmony_ci      ++info->num_results;
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci      --results;
228bf215546Sopenharmony_ci      idx = (idx - 1) % NUM_QUERIES;
229bf215546Sopenharmony_ci   }
230bf215546Sopenharmony_ci}
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_cistatic void
233bf215546Sopenharmony_ciquery_new_value_normal(struct query_info *info, struct pipe_context *pipe)
234bf215546Sopenharmony_ci{
235bf215546Sopenharmony_ci   if (info->last_time) {
236bf215546Sopenharmony_ci      if (info->query[info->head])
237bf215546Sopenharmony_ci         pipe->end_query(pipe, info->query[info->head]);
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci      /* read query results */
240bf215546Sopenharmony_ci      while (1) {
241bf215546Sopenharmony_ci         struct pipe_query *query = info->query[info->tail];
242bf215546Sopenharmony_ci         union pipe_query_result result;
243bf215546Sopenharmony_ci         uint64_t *res64 = (uint64_t *)&result;
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci         if (query && pipe->get_query_result(pipe, query, FALSE, &result)) {
246bf215546Sopenharmony_ci            if (info->type == PIPE_DRIVER_QUERY_TYPE_FLOAT) {
247bf215546Sopenharmony_ci               assert(info->result_index == 0);
248bf215546Sopenharmony_ci               info->results_cumulative += (uint64_t) (result.f * 1000.0f);
249bf215546Sopenharmony_ci            }
250bf215546Sopenharmony_ci            else {
251bf215546Sopenharmony_ci               info->results_cumulative += res64[info->result_index];
252bf215546Sopenharmony_ci            }
253bf215546Sopenharmony_ci            info->num_results++;
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci            if (info->tail == info->head)
256bf215546Sopenharmony_ci               break;
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci            info->tail = (info->tail+1) % NUM_QUERIES;
259bf215546Sopenharmony_ci         }
260bf215546Sopenharmony_ci         else {
261bf215546Sopenharmony_ci            /* the oldest query is busy */
262bf215546Sopenharmony_ci            if ((info->head+1) % NUM_QUERIES == info->tail) {
263bf215546Sopenharmony_ci               /* all queries are busy, throw away the last query and create
264bf215546Sopenharmony_ci                * a new one */
265bf215546Sopenharmony_ci               fprintf(stderr,
266bf215546Sopenharmony_ci                       "gallium_hud: all queries are busy after %i frames, "
267bf215546Sopenharmony_ci                       "can't add another query\n",
268bf215546Sopenharmony_ci                       NUM_QUERIES);
269bf215546Sopenharmony_ci               if (info->query[info->head])
270bf215546Sopenharmony_ci                  pipe->destroy_query(pipe, info->query[info->head]);
271bf215546Sopenharmony_ci               info->query[info->head] =
272bf215546Sopenharmony_ci                     pipe->create_query(pipe, info->query_type, 0);
273bf215546Sopenharmony_ci            }
274bf215546Sopenharmony_ci            else {
275bf215546Sopenharmony_ci               /* the last query is busy, we need to add a new one we can use
276bf215546Sopenharmony_ci                * for this frame */
277bf215546Sopenharmony_ci               info->head = (info->head+1) % NUM_QUERIES;
278bf215546Sopenharmony_ci               if (!info->query[info->head]) {
279bf215546Sopenharmony_ci                  info->query[info->head] =
280bf215546Sopenharmony_ci                        pipe->create_query(pipe, info->query_type, 0);
281bf215546Sopenharmony_ci               }
282bf215546Sopenharmony_ci            }
283bf215546Sopenharmony_ci            break;
284bf215546Sopenharmony_ci         }
285bf215546Sopenharmony_ci      }
286bf215546Sopenharmony_ci   }
287bf215546Sopenharmony_ci   else {
288bf215546Sopenharmony_ci      /* initialize */
289bf215546Sopenharmony_ci      info->query[info->head] = pipe->create_query(pipe, info->query_type, 0);
290bf215546Sopenharmony_ci   }
291bf215546Sopenharmony_ci}
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_cistatic void
294bf215546Sopenharmony_cibegin_query(struct hud_graph *gr, struct pipe_context *pipe)
295bf215546Sopenharmony_ci{
296bf215546Sopenharmony_ci   struct query_info *info = gr->query_data;
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   assert(!info->batch);
299bf215546Sopenharmony_ci   if (info->query[info->head])
300bf215546Sopenharmony_ci      pipe->begin_query(pipe, info->query[info->head]);
301bf215546Sopenharmony_ci}
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_cistatic void
304bf215546Sopenharmony_ciquery_new_value(struct hud_graph *gr, struct pipe_context *pipe)
305bf215546Sopenharmony_ci{
306bf215546Sopenharmony_ci   struct query_info *info = gr->query_data;
307bf215546Sopenharmony_ci   uint64_t now = os_time_get();
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci   if (info->batch) {
310bf215546Sopenharmony_ci      query_new_value_batch(info);
311bf215546Sopenharmony_ci   } else {
312bf215546Sopenharmony_ci      query_new_value_normal(info, pipe);
313bf215546Sopenharmony_ci   }
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   if (!info->last_time) {
316bf215546Sopenharmony_ci      info->last_time = now;
317bf215546Sopenharmony_ci      return;
318bf215546Sopenharmony_ci   }
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci   if (info->num_results && info->last_time + gr->pane->period <= now) {
321bf215546Sopenharmony_ci      double value;
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci      switch (info->result_type) {
324bf215546Sopenharmony_ci      default:
325bf215546Sopenharmony_ci      case PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE:
326bf215546Sopenharmony_ci         value = info->results_cumulative / info->num_results;
327bf215546Sopenharmony_ci         break;
328bf215546Sopenharmony_ci      case PIPE_DRIVER_QUERY_RESULT_TYPE_CUMULATIVE:
329bf215546Sopenharmony_ci         value = info->results_cumulative;
330bf215546Sopenharmony_ci         break;
331bf215546Sopenharmony_ci      }
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci      if (info->type == PIPE_DRIVER_QUERY_TYPE_FLOAT) {
334bf215546Sopenharmony_ci         value /= 1000.0;
335bf215546Sopenharmony_ci      }
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci      hud_graph_add_value(gr, value);
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci      info->last_time = now;
340bf215546Sopenharmony_ci      info->results_cumulative = 0;
341bf215546Sopenharmony_ci      info->num_results = 0;
342bf215546Sopenharmony_ci   }
343bf215546Sopenharmony_ci}
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_cistatic void
346bf215546Sopenharmony_cifree_query_info(void *ptr, struct pipe_context *pipe)
347bf215546Sopenharmony_ci{
348bf215546Sopenharmony_ci   struct query_info *info = ptr;
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci   if (!info->batch && info->last_time) {
351bf215546Sopenharmony_ci      int i;
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci      pipe->end_query(pipe, info->query[info->head]);
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci      for (i = 0; i < ARRAY_SIZE(info->query); i++) {
356bf215546Sopenharmony_ci         if (info->query[i]) {
357bf215546Sopenharmony_ci            pipe->destroy_query(pipe, info->query[i]);
358bf215546Sopenharmony_ci         }
359bf215546Sopenharmony_ci      }
360bf215546Sopenharmony_ci   }
361bf215546Sopenharmony_ci   FREE(info);
362bf215546Sopenharmony_ci}
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci/**
366bf215546Sopenharmony_ci * \param result_index  to select fields of pipe_query_data_pipeline_statistics,
367bf215546Sopenharmony_ci *                      for example.
368bf215546Sopenharmony_ci */
369bf215546Sopenharmony_civoid
370bf215546Sopenharmony_cihud_pipe_query_install(struct hud_batch_query_context **pbq,
371bf215546Sopenharmony_ci                       struct hud_pane *pane,
372bf215546Sopenharmony_ci                       const char *name,
373bf215546Sopenharmony_ci                       enum pipe_query_type query_type,
374bf215546Sopenharmony_ci                       unsigned result_index,
375bf215546Sopenharmony_ci                       uint64_t max_value, enum pipe_driver_query_type type,
376bf215546Sopenharmony_ci                       enum pipe_driver_query_result_type result_type,
377bf215546Sopenharmony_ci                       unsigned flags)
378bf215546Sopenharmony_ci{
379bf215546Sopenharmony_ci   struct hud_graph *gr;
380bf215546Sopenharmony_ci   struct query_info *info;
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci   gr = CALLOC_STRUCT(hud_graph);
383bf215546Sopenharmony_ci   if (!gr)
384bf215546Sopenharmony_ci      return;
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci   strncpy(gr->name, name, sizeof(gr->name));
387bf215546Sopenharmony_ci   gr->name[sizeof(gr->name) - 1] = '\0';
388bf215546Sopenharmony_ci   gr->query_data = CALLOC_STRUCT(query_info);
389bf215546Sopenharmony_ci   if (!gr->query_data)
390bf215546Sopenharmony_ci      goto fail_gr;
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci   gr->query_new_value = query_new_value;
393bf215546Sopenharmony_ci   gr->free_query_data = free_query_info;
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   info = gr->query_data;
396bf215546Sopenharmony_ci   info->result_type = result_type;
397bf215546Sopenharmony_ci   info->type = type;
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   if (flags & PIPE_DRIVER_QUERY_FLAG_BATCH) {
400bf215546Sopenharmony_ci      if (!batch_query_add(pbq, query_type, &info->result_index))
401bf215546Sopenharmony_ci         goto fail_info;
402bf215546Sopenharmony_ci      info->batch = *pbq;
403bf215546Sopenharmony_ci   } else {
404bf215546Sopenharmony_ci      gr->begin_query = begin_query;
405bf215546Sopenharmony_ci      info->query_type = query_type;
406bf215546Sopenharmony_ci      info->result_index = result_index;
407bf215546Sopenharmony_ci   }
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci   hud_pane_add_graph(pane, gr);
410bf215546Sopenharmony_ci   pane->type = type; /* must be set before updating the max_value */
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci   if (pane->max_value < max_value)
413bf215546Sopenharmony_ci      hud_pane_set_max_value(pane, max_value);
414bf215546Sopenharmony_ci   return;
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_cifail_info:
417bf215546Sopenharmony_ci   FREE(info);
418bf215546Sopenharmony_cifail_gr:
419bf215546Sopenharmony_ci   FREE(gr);
420bf215546Sopenharmony_ci}
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ciboolean
423bf215546Sopenharmony_cihud_driver_query_install(struct hud_batch_query_context **pbq,
424bf215546Sopenharmony_ci                         struct hud_pane *pane, struct pipe_screen *screen,
425bf215546Sopenharmony_ci                         const char *name)
426bf215546Sopenharmony_ci{
427bf215546Sopenharmony_ci   struct pipe_driver_query_info query = { 0 };
428bf215546Sopenharmony_ci   unsigned num_queries, i;
429bf215546Sopenharmony_ci   boolean found = FALSE;
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci   if (!screen->get_driver_query_info)
432bf215546Sopenharmony_ci      return FALSE;
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci   num_queries = screen->get_driver_query_info(screen, 0, NULL);
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci   for (i = 0; i < num_queries; i++) {
437bf215546Sopenharmony_ci      if (screen->get_driver_query_info(screen, i, &query) &&
438bf215546Sopenharmony_ci          strcmp(query.name, name) == 0) {
439bf215546Sopenharmony_ci         found = TRUE;
440bf215546Sopenharmony_ci         break;
441bf215546Sopenharmony_ci      }
442bf215546Sopenharmony_ci   }
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   if (!found)
445bf215546Sopenharmony_ci      return FALSE;
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci   hud_pipe_query_install(pbq, pane, query.name, query.query_type, 0,
448bf215546Sopenharmony_ci                          query.max_value.u64, query.type, query.result_type,
449bf215546Sopenharmony_ci                          query.flags);
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci   return TRUE;
452bf215546Sopenharmony_ci}
453