nv30_query.c revision 7b389f8d2f307fa0714494f2a43e9141cc04ed3e
1#include "pipe/p_context.h"
2#include "pipe/p_util.h"
3
4#include "nv30_context.h"
5
6struct nv30_query {
7	struct nouveau_resource *object;
8	unsigned type;
9	boolean ready;
10	uint64_t result;
11};
12
13static inline struct nv30_query *
14nv30_query(struct pipe_query *pipe)
15{
16	return (struct nv30_query *)pipe;
17}
18
19static struct pipe_query *
20nv30_query_create(struct pipe_context *pipe, unsigned query_type)
21{
22	struct nv30_query *q;
23
24	q = CALLOC(1, sizeof(struct nv30_query));
25	q->type = query_type;
26
27	return (struct pipe_query *)q;
28}
29
30static void
31nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
32{
33	struct nv30_context *nv30 = nv30_context(pipe);
34	struct nv30_query *q = nv30_query(pq);
35
36	if (q->object)
37		nv30->nvws->res_free(&q->object);
38	FREE(q);
39}
40
41static void
42nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
43{
44	struct nv30_context *nv30 = nv30_context(pipe);
45	struct nv30_query *q = nv30_query(pq);
46
47	assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
48
49	if (nv30->nvws->res_alloc(nv30->query_heap, 1, NULL, &q->object))
50		assert(0);
51	nv30->nvws->notifier_reset(nv30->query, q->object->start);
52
53	BEGIN_RING(rankine, NV34TCL_QUERY_RESET, 1);
54	OUT_RING  (1);
55	BEGIN_RING(rankine, NV34TCL_QUERY_UNK17CC, 1);
56	OUT_RING  (1);
57
58	q->ready = FALSE;
59}
60
61static void
62nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq)
63{
64	struct nv30_context *nv30 = nv30_context(pipe);
65	struct nv30_query *q = nv30_query(pq);
66
67	BEGIN_RING(rankine, NV34TCL_QUERY_GET, 1);
68	OUT_RING  ((0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) |
69		   ((q->object->start * 32) << NV34TCL_QUERY_GET_OFFSET_SHIFT));
70	FIRE_RING(NULL);
71}
72
73static boolean
74nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq,
75		  boolean wait, uint64 *result)
76{
77	struct nv30_context *nv30 = nv30_context(pipe);
78	struct nv30_query *q = nv30_query(pq);
79	struct nouveau_winsys *nvws = nv30->nvws;
80
81	assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER);
82
83	if (!q->ready) {
84		unsigned status;
85
86		status = nvws->notifier_status(nv30->query, q->object->start);
87		if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) {
88			if (wait == FALSE)
89				return FALSE;
90			nvws->notifier_wait(nv30->query, q->object->start,
91					    NV_NOTIFY_STATE_STATUS_COMPLETED,
92					    0);
93		}
94
95		q->result = nvws->notifier_retval(nv30->query,
96						  q->object->start);
97		q->ready = TRUE;
98		nvws->res_free(&q->object);
99	}
100
101	*result = q->result;
102	return TRUE;
103}
104
105void
106nv30_init_query_functions(struct nv30_context *nv30)
107{
108	nv30->pipe.create_query = nv30_query_create;
109	nv30->pipe.destroy_query = nv30_query_destroy;
110	nv30->pipe.begin_query = nv30_query_begin;
111	nv30->pipe.end_query = nv30_query_end;
112	nv30->pipe.get_query_result = nv30_query_result;
113}
114