1/*
2 * Copyright (c) 2016 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 *    Rob Clark <robclark@freedesktop.org>
25 *    Christian Gmeiner <christian.gmeiner@gmail.com>
26 */
27
28#include "util/os_time.h"
29#include "pipe/p_state.h"
30#include "util/u_memory.h"
31#include "util/u_string.h"
32
33#include "etnaviv_context.h"
34#include "etnaviv_query_sw.h"
35
36static void
37etna_sw_destroy_query(struct etna_context *ctx, struct etna_query *q)
38{
39   struct etna_sw_query *sq = etna_sw_query(q);
40
41   FREE(sq);
42}
43
44static uint64_t
45read_counter(struct etna_context *ctx, unsigned type)
46{
47   switch (type) {
48   case PIPE_QUERY_PRIMITIVES_GENERATED:
49      return ctx->stats.prims_generated;
50   case ETNA_QUERY_DRAW_CALLS:
51      return ctx->stats.draw_calls;
52   case ETNA_QUERY_RS_OPERATIONS:
53      return ctx->stats.rs_operations;
54   }
55
56   return 0;
57}
58
59static void
60etna_sw_begin_query(struct etna_context *ctx, struct etna_query *q)
61{
62   struct etna_sw_query *sq = etna_sw_query(q);
63
64   sq->begin_value = read_counter(ctx, q->type);
65}
66
67static void
68etna_sw_end_query(struct etna_context *ctx, struct etna_query *q)
69{
70   struct etna_sw_query *sq = etna_sw_query(q);
71
72   sq->end_value = read_counter(ctx, q->type);
73}
74
75static bool
76etna_sw_get_query_result(struct etna_context *ctx, struct etna_query *q,
77                         bool wait, union pipe_query_result *result)
78{
79   struct etna_sw_query *sq = etna_sw_query(q);
80
81   result->u64 = sq->end_value - sq->begin_value;
82
83   return true;
84}
85
86static const struct etna_query_funcs sw_query_funcs = {
87   .destroy_query = etna_sw_destroy_query,
88   .begin_query = etna_sw_begin_query,
89   .end_query = etna_sw_end_query,
90   .get_query_result = etna_sw_get_query_result,
91};
92
93struct etna_query *
94etna_sw_create_query(struct etna_context *ctx, unsigned query_type)
95{
96   struct etna_sw_query *sq;
97   struct etna_query *q;
98
99   switch (query_type) {
100   case PIPE_QUERY_PRIMITIVES_GENERATED:
101   case ETNA_QUERY_DRAW_CALLS:
102   case ETNA_QUERY_RS_OPERATIONS:
103      break;
104   default:
105      return NULL;
106   }
107
108   sq = CALLOC_STRUCT(etna_sw_query);
109   if (!sq)
110      return NULL;
111
112   q = &sq->base;
113   q->funcs = &sw_query_funcs;
114   q->type = query_type;
115
116   return q;
117}
118
119static const struct pipe_driver_query_info list[] = {
120   {"prims-generated", PIPE_QUERY_PRIMITIVES_GENERATED, { 0 }},
121   {"draw-calls", ETNA_QUERY_DRAW_CALLS, { 0 }},
122   {"rs-operations", ETNA_QUERY_RS_OPERATIONS, { 0 }},
123};
124
125int
126etna_sw_get_driver_query_info(struct pipe_screen *pscreen, unsigned index,
127                              struct pipe_driver_query_info *info)
128{
129   if (!info)
130      return ARRAY_SIZE(list);
131
132   if (index >= ARRAY_SIZE(list))
133      return 0;
134
135   *info = list[index];
136
137   return 1;
138}
139
140int
141etna_sw_get_driver_query_group_info(struct pipe_screen *pscreen,
142                                    unsigned index,
143                                    struct pipe_driver_query_group_info *info)
144{
145   if (!info)
146      return 1;
147
148   if (index != 0)
149      return 0;
150
151   info->name = "driver";
152   info->max_active_queries = ARRAY_SIZE(list);
153   info->num_queries = ARRAY_SIZE(list);
154
155   return 1;
156}
157