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