Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / src / gallium / drivers / nv30 / nv30_query.c
1 #include "pipe/p_context.h"
2 #include "pipe/p_util.h"
3
4 #include "nv30_context.h"
5
6 struct nv30_query {
7 struct nouveau_resource *object;
8 unsigned type;
9 boolean ready;
10 uint64_t result;
11 };
12
13 static inline struct nv30_query *
14 nv30_query(struct pipe_query *pipe)
15 {
16 return (struct nv30_query *)pipe;
17 }
18
19 static struct pipe_query *
20 nv30_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
30 static void
31 nv30_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
41 static void
42 nv30_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
61 static void
62 nv30_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();
71 }
72
73 static boolean
74 nv30_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
105 void
106 nv30_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 }