1 #include "pipe/p_context.h"
3 #include "nvfx_context.h"
7 struct nouveau_resource
*object
;
13 static INLINE
struct nvfx_query
*
14 nvfx_query(struct pipe_query
*pipe
)
16 return (struct nvfx_query
*)pipe
;
19 static struct pipe_query
*
20 nvfx_query_create(struct pipe_context
*pipe
, unsigned query_type
)
24 q
= CALLOC(1, sizeof(struct nvfx_query
));
27 assert(q
->type
== PIPE_QUERY_OCCLUSION_COUNTER
);
29 return (struct pipe_query
*)q
;
33 nvfx_query_destroy(struct pipe_context
*pipe
, struct pipe_query
*pq
)
35 struct nvfx_query
*q
= nvfx_query(pq
);
39 nouveau_resource_free(&q
->object
);
46 nvfx_query_begin(struct pipe_context
*pipe
, struct pipe_query
*pq
)
48 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
49 struct nvfx_query
*q
= nvfx_query(pq
);
50 struct nvfx_screen
*screen
= nvfx
->screen
;
51 struct nouveau_channel
*chan
= screen
->base
.channel
;
52 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
57 /* Happens when end_query() is called, then another begin_query()
58 * without querying the result in-between. For now we'll wait for
59 * the existing query to notify completion, but it could be better.
62 pipe
->get_query_result(pipe
, pq
, 1, &tmp
);
64 while (nouveau_resource_alloc(nvfx
->screen
->query_heap
, 1, NULL
, &q
->object
))
66 struct nvfx_query
* oldestq
;
67 assert(!LIST_IS_EMPTY(&nvfx
->screen
->query_list
));
68 oldestq
= LIST_ENTRY(struct nvfx_query
, nvfx
->screen
->query_list
.next
, list
);
69 pipe
->get_query_result(pipe
, (struct pipe_query
*)oldestq
, 1, &tmp
);
72 LIST_ADDTAIL(&q
->list
, &nvfx
->screen
->query_list
);
74 nouveau_notifier_reset(nvfx
->screen
->query
, q
->object
->start
);
76 BEGIN_RING(chan
, eng3d
, NV30_3D_QUERY_RESET
, 1);
78 BEGIN_RING(chan
, eng3d
, NV30_3D_QUERY_ENABLE
, 1);
87 nvfx_query_end(struct pipe_context
*pipe
, struct pipe_query
*pq
)
89 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
90 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
91 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
92 struct nvfx_query
*q
= nvfx_query(pq
);
94 assert(nvfx
->query
== pq
);
96 BEGIN_RING(chan
, eng3d
, NV30_3D_QUERY_GET
, 1);
97 OUT_RING (chan
, (0x01 << NV30_3D_QUERY_GET_UNK24__SHIFT
) |
98 ((q
->object
->start
* 32) << NV30_3D_QUERY_GET_OFFSET__SHIFT
));
99 BEGIN_RING(chan
, eng3d
, NV30_3D_QUERY_ENABLE
, 1);
107 nvfx_query_result(struct pipe_context
*pipe
, struct pipe_query
*pq
,
108 boolean wait
, void *vresult
)
110 uint64_t *result
= (uint64_t *)vresult
;
111 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
112 struct nvfx_query
*q
= nvfx_query(pq
);
117 status
= nouveau_notifier_status(nvfx
->screen
->query
,
119 if (status
!= NV_NOTIFY_STATE_STATUS_COMPLETED
) {
123 nouveau_notifier_wait_status(nvfx
->screen
->query
,
125 NV_NOTIFY_STATE_STATUS_COMPLETED
, 0);
128 q
->result
= nouveau_notifier_return_val(nvfx
->screen
->query
,
131 nouveau_resource_free(&q
->object
);
140 nvfx_init_query_functions(struct nvfx_context
*nvfx
)
142 nvfx
->pipe
.create_query
= nvfx_query_create
;
143 nvfx
->pipe
.destroy_query
= nvfx_query_destroy
;
144 nvfx
->pipe
.begin_query
= nvfx_query_begin
;
145 nvfx
->pipe
.end_query
= nvfx_query_end
;
146 nvfx
->pipe
.get_query_result
= nvfx_query_result
;