2 * Copyright 2012 Red Hat Inc.
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, sublicense,
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "nv_object.xml.h"
27 #include "nv30/nv30-40_3d.xml.h"
28 #include "nv30/nv30_screen.h"
29 #include "nv30/nv30_context.h"
31 #define LIST_FIRST_ENTRY(__type, __item, __field) \
32 LIST_ENTRY(__type, (__item)->next, __field)
34 struct nv30_query_object
{
35 struct list_head list
;
36 struct nouveau_heap
*hw
;
39 static volatile void *
40 nv30_ntfy(struct nv30_screen
*screen
, struct nv30_query_object
*qo
)
42 struct nv04_notify
*query
= screen
->query
->data
;
43 struct nouveau_bo
*notify
= screen
->notify
;
44 volatile void *ntfy
= NULL
;
47 ntfy
= (char *)notify
->map
+ query
->offset
+ qo
->hw
->start
;
53 nv30_query_object_del(struct nv30_screen
*screen
, struct nv30_query_object
**po
)
55 struct nv30_query_object
*qo
= *po
; *po
= NULL
;
57 volatile uint32_t *ntfy
= nv30_ntfy(screen
, qo
);
58 while (ntfy
[3] & 0xff000000) {
60 nouveau_heap_free(&qo
->hw
);
66 static struct nv30_query_object
*
67 nv30_query_object_new(struct nv30_screen
*screen
)
69 struct nv30_query_object
*oq
, *qo
= CALLOC_STRUCT(nv30_query_object
);
70 volatile uint32_t *ntfy
;
75 /* allocate a new hw query object, if no hw objects left we need to
76 * spin waiting for one to become free
78 while (nouveau_heap_alloc(screen
->query_heap
, 32, NULL
, &qo
->hw
)) {
79 oq
= LIST_FIRST_ENTRY(struct nv30_query_object
, &screen
->queries
, list
);
80 nv30_query_object_del(screen
, &oq
);
83 LIST_ADDTAIL(&qo
->list
, &screen
->queries
);
85 ntfy
= nv30_ntfy(screen
, qo
);
94 struct nv30_query_object
*qo
[2];
101 static inline struct nv30_query
*
102 nv30_query(struct pipe_query
*pipe
)
104 return (struct nv30_query
*)pipe
;
107 static struct pipe_query
*
108 nv30_query_create(struct pipe_context
*pipe
, unsigned type
, unsigned index
)
110 struct nv30_query
*q
= CALLOC_STRUCT(nv30_query
);
117 case PIPE_QUERY_TIMESTAMP
:
118 case PIPE_QUERY_TIME_ELAPSED
:
122 case PIPE_QUERY_OCCLUSION_COUNTER
:
123 case PIPE_QUERY_OCCLUSION_PREDICATE
:
124 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
125 q
->enable
= NV30_3D_QUERY_ENABLE
;
128 case NV30_QUERY_ZCULL_0
:
129 case NV30_QUERY_ZCULL_1
:
130 case NV30_QUERY_ZCULL_2
:
131 case NV30_QUERY_ZCULL_3
:
133 q
->report
= 2 + (q
->type
- NV30_QUERY_ZCULL_0
);
140 return (struct pipe_query
*)q
;
144 nv30_query_destroy(struct pipe_context
*pipe
, struct pipe_query
*pq
)
150 nv30_query_begin(struct pipe_context
*pipe
, struct pipe_query
*pq
)
152 struct nv30_context
*nv30
= nv30_context(pipe
);
153 struct nv30_query
*q
= nv30_query(pq
);
154 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
157 case PIPE_QUERY_TIME_ELAPSED
:
158 q
->qo
[0] = nv30_query_object_new(nv30
->screen
);
160 BEGIN_NV04(push
, NV30_3D(QUERY_GET
), 1);
161 PUSH_DATA (push
, (q
->report
<< 24) | q
->qo
[0]->hw
->start
);
164 case PIPE_QUERY_TIMESTAMP
:
167 BEGIN_NV04(push
, NV30_3D(QUERY_RESET
), 1);
168 PUSH_DATA (push
, q
->report
);
173 BEGIN_NV04(push
, SUBC_3D(q
->enable
), 1);
180 nv30_query_end(struct pipe_context
*pipe
, struct pipe_query
*pq
)
182 struct nv30_context
*nv30
= nv30_context(pipe
);
183 struct nv30_screen
*screen
= nv30
->screen
;
184 struct nv30_query
*q
= nv30_query(pq
);
185 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
187 q
->qo
[1] = nv30_query_object_new(screen
);
189 BEGIN_NV04(push
, NV30_3D(QUERY_GET
), 1);
190 PUSH_DATA (push
, (q
->report
<< 24) | q
->qo
[1]->hw
->start
);
194 BEGIN_NV04(push
, SUBC_3D(q
->enable
), 1);
202 nv30_query_result(struct pipe_context
*pipe
, struct pipe_query
*pq
,
203 boolean wait
, union pipe_query_result
*result
)
205 struct nv30_screen
*screen
= nv30_screen(pipe
->screen
);
206 struct nv30_query
*q
= nv30_query(pq
);
207 volatile uint32_t *ntfy0
= nv30_ntfy(screen
, q
->qo
[0]);
208 volatile uint32_t *ntfy1
= nv30_ntfy(screen
, q
->qo
[1]);
211 while (ntfy1
[3] & 0xff000000) {
217 case PIPE_QUERY_TIMESTAMP
:
218 q
->result
= *(uint64_t *)&ntfy1
[0];
220 case PIPE_QUERY_TIME_ELAPSED
:
221 q
->result
= *(uint64_t *)&ntfy1
[0] - *(uint64_t *)&ntfy0
[0];
224 q
->result
= ntfy1
[2];
228 nv30_query_object_del(screen
, &q
->qo
[0]);
229 nv30_query_object_del(screen
, &q
->qo
[1]);
232 if (q
->type
== PIPE_QUERY_OCCLUSION_PREDICATE
||
233 q
->type
== PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
)
234 result
->b
= !!q
->result
;
236 result
->u64
= q
->result
;
241 nv40_query_render_condition(struct pipe_context
*pipe
,
242 struct pipe_query
*pq
,
243 boolean condition
, enum pipe_render_cond_flag mode
)
245 struct nv30_context
*nv30
= nv30_context(pipe
);
246 struct nv30_query
*q
= nv30_query(pq
);
247 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
249 nv30
->render_cond_query
= pq
;
250 nv30
->render_cond_mode
= mode
;
251 nv30
->render_cond_cond
= condition
;
254 BEGIN_NV04(push
, SUBC_3D(0x1e98), 1);
255 PUSH_DATA (push
, 0x01000000);
259 if (mode
== PIPE_RENDER_COND_WAIT
||
260 mode
== PIPE_RENDER_COND_BY_REGION_WAIT
) {
261 BEGIN_NV04(push
, SUBC_3D(0x0110), 1);
265 BEGIN_NV04(push
, SUBC_3D(0x1e98), 1);
266 PUSH_DATA (push
, 0x02000000 | q
->qo
[1]->hw
->start
);
270 nv30_set_active_query_state(struct pipe_context
*pipe
, boolean enable
)
275 nv30_query_init(struct pipe_context
*pipe
)
277 struct nouveau_object
*eng3d
= nv30_context(pipe
)->screen
->eng3d
;
279 pipe
->create_query
= nv30_query_create
;
280 pipe
->destroy_query
= nv30_query_destroy
;
281 pipe
->begin_query
= nv30_query_begin
;
282 pipe
->end_query
= nv30_query_end
;
283 pipe
->get_query_result
= nv30_query_result
;
284 pipe
->set_active_query_state
= nv30_set_active_query_state
;
285 if (eng3d
->oclass
>= NV40_3D_CLASS
)
286 pipe
->render_condition
= nv40_query_render_condition
;