Merge branch 'upstream-gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / src / mesa / pipe / nv40 / nv40_query.c
1 #include "pipe/p_context.h"
2
3 #include "nv40_context.h"
4
5 struct nv40_query {
6 struct nouveau_resource *object;
7 unsigned type;
8 boolean ready;
9 uint64_t result;
10 };
11
12 static INLINE struct nv40_query *
13 nv40_query(struct pipe_query *pipe)
14 {
15 return (struct nv40_query *)pipe;
16 }
17
18 static struct pipe_query *
19 nv40_query_create(struct pipe_context *pipe, unsigned query_type)
20 {
21 struct nv40_query *q;
22
23 q = CALLOC(1, sizeof(struct nv40_query));
24 q->type = query_type;
25
26 return (struct pipe_query *)q;
27 }
28
29 static void
30 nv40_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
31 {
32 struct nv40_context *nv40 = nv40_context(pipe);
33 struct nv40_query *q = nv40_query(pq);
34
35 if (q->object)
36 nv40->nvws->res_free(&q->object);
37 free(q);
38 }
39
40 static void
41 nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
42 {
43 struct nv40_context *nv40 = nv40_context(pipe);
44 struct nv40_query *q = nv40_query(pq);
45
46 assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
47
48 if (nv40->nvws->res_alloc(nv40->hw->query_heap, 1, NULL, &q->object))
49 assert(0);
50 nv40->nvws->notifier_reset(nv40->hw->query, q->object->start);
51
52 BEGIN_RING(curie, NV40TCL_QUERY_RESET, 1);
53 OUT_RING (1);
54 BEGIN_RING(curie, NV40TCL_QUERY_UNK17CC, 1);
55 OUT_RING (1);
56
57 q->ready = FALSE;
58 }
59
60 static void
61 nv40_query_end(struct pipe_context *pipe, struct pipe_query *pq)
62 {
63 struct nv40_context *nv40 = nv40_context(pipe);
64 struct nv40_query *q = nv40_query(pq);
65
66 BEGIN_RING(curie, NV40TCL_QUERY_GET, 1);
67 OUT_RING ((0x01 << NV40TCL_QUERY_GET_UNK24_SHIFT) |
68 ((q->object->start * 32) << NV40TCL_QUERY_GET_OFFSET_SHIFT));
69 FIRE_RING();
70 }
71
72 static boolean
73 nv40_query_result(struct pipe_context *pipe, struct pipe_query *pq,
74 boolean wait, uint64 *result)
75 {
76 struct nv40_context *nv40 = nv40_context(pipe);
77 struct nv40_query *q = nv40_query(pq);
78 struct nouveau_winsys *nvws = nv40->nvws;
79
80 assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER);
81
82 if (!q->ready) {
83 unsigned status;
84
85 status = nvws->notifier_status(nv40->hw->query,
86 q->object->start);
87 if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) {
88 if (wait == FALSE)
89 return FALSE;
90 nvws->notifier_wait(nv40->hw->query, q->object->start,
91 NV_NOTIFY_STATE_STATUS_COMPLETED,
92 0);
93 }
94
95 q->result = nvws->notifier_retval(nv40->hw->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 nv40_init_query_functions(struct nv40_context *nv40)
107 {
108 nv40->pipe.create_query = nv40_query_create;
109 nv40->pipe.destroy_query = nv40_query_destroy;
110 nv40->pipe.begin_query = nv40_query_begin;
111 nv40->pipe.end_query = nv40_query_end;
112 nv40->pipe.get_query_result = nv40_query_result;
113 }