1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "util/u_inlines.h"
4 #include "util/u_format.h"
5 #include "util/u_split_prim.h"
7 #include "nv50_context.h"
8 #include "nv50_resource.h"
11 struct nv50_context
*nv50
;
27 void (*push
)(struct nouveau_channel
*, void *);
33 emit_b32_1(struct nouveau_channel
*chan
, void *data
)
41 emit_b32_2(struct nouveau_channel
*chan
, void *data
)
50 emit_b32_3(struct nouveau_channel
*chan
, void *data
)
60 emit_b32_4(struct nouveau_channel
*chan
, void *data
)
71 emit_b16_1(struct nouveau_channel
*chan
, void *data
)
79 emit_b16_3(struct nouveau_channel
*chan
, void *data
)
83 OUT_RING(chan
, (v
[1] << 16) | v
[0]);
88 emit_b08_1(struct nouveau_channel
*chan
, void *data
)
96 emit_b08_3(struct nouveau_channel
*chan
, void *data
)
100 OUT_RING(chan
, (v
[2] << 16) | (v
[1] << 8) | v
[0]);
104 emit_vertex(struct push_context
*ctx
, unsigned n
)
106 struct nouveau_grobj
*tesla
= ctx
->nv50
->screen
->tesla
;
107 struct nouveau_channel
*chan
= tesla
->channel
;
110 if (ctx
->edgeflag_attr
< 16) {
111 float *edgeflag
= (float *)
112 ((uint8_t *)ctx
->attr
[ctx
->edgeflag_attr
].map
+
113 ctx
->attr
[ctx
->edgeflag_attr
].stride
* n
);
115 if (*edgeflag
!= ctx
->edgeflag
) {
116 BEGIN_RING(chan
, tesla
, NV50TCL_EDGEFLAG_ENABLE
, 1);
117 OUT_RING (chan
, *edgeflag
? 1 : 0);
118 ctx
->edgeflag
= *edgeflag
;
122 BEGIN_RING_NI(chan
, tesla
, NV50TCL_VERTEX_DATA
, ctx
->vtx_size
);
123 for (i
= 0; i
< ctx
->attr_nr
; i
++)
124 ctx
->attr
[i
].push(chan
,
125 (uint8_t *)ctx
->attr
[i
].map
+ ctx
->attr
[i
].stride
* n
);
129 emit_edgeflag(void *priv
, boolean enabled
)
131 struct push_context
*ctx
= priv
;
132 struct nouveau_grobj
*tesla
= ctx
->nv50
->screen
->tesla
;
133 struct nouveau_channel
*chan
= tesla
->channel
;
135 BEGIN_RING(chan
, tesla
, NV50TCL_EDGEFLAG_ENABLE
, 1);
136 OUT_RING (chan
, enabled
? 1 : 0);
140 emit_elt08(void *priv
, unsigned start
, unsigned count
)
142 struct push_context
*ctx
= priv
;
143 uint8_t *idxbuf
= ctx
->idxbuf
;
146 emit_vertex(ctx
, idxbuf
[start
++]);
150 emit_elt08_biased(void *priv
, unsigned start
, unsigned count
)
152 struct push_context
*ctx
= priv
;
153 uint8_t *idxbuf
= ctx
->idxbuf
;
156 emit_vertex(ctx
, idxbuf
[start
++] + ctx
->idxbias
);
160 emit_elt16(void *priv
, unsigned start
, unsigned count
)
162 struct push_context
*ctx
= priv
;
163 uint16_t *idxbuf
= ctx
->idxbuf
;
166 emit_vertex(ctx
, idxbuf
[start
++]);
170 emit_elt16_biased(void *priv
, unsigned start
, unsigned count
)
172 struct push_context
*ctx
= priv
;
173 uint16_t *idxbuf
= ctx
->idxbuf
;
176 emit_vertex(ctx
, idxbuf
[start
++] + ctx
->idxbias
);
180 emit_elt32(void *priv
, unsigned start
, unsigned count
)
182 struct push_context
*ctx
= priv
;
183 uint32_t *idxbuf
= ctx
->idxbuf
;
186 emit_vertex(ctx
, idxbuf
[start
++]);
190 emit_elt32_biased(void *priv
, unsigned start
, unsigned count
)
192 struct push_context
*ctx
= priv
;
193 uint32_t *idxbuf
= ctx
->idxbuf
;
196 emit_vertex(ctx
, idxbuf
[start
++] + ctx
->idxbias
);
200 emit_verts(void *priv
, unsigned start
, unsigned count
)
203 emit_vertex(priv
, start
++);
207 nv50_push_elements_instanced(struct pipe_context
*pipe
,
208 struct pipe_resource
*idxbuf
,
209 unsigned idxsize
, int idxbias
,
210 unsigned mode
, unsigned start
, unsigned count
,
211 unsigned i_start
, unsigned i_count
)
213 struct nv50_context
*nv50
= nv50_context(pipe
);
214 struct nouveau_grobj
*tesla
= nv50
->screen
->tesla
;
215 struct nouveau_channel
*chan
= tesla
->channel
;
216 struct push_context ctx
;
217 const unsigned p_overhead
= 4 + /* begin/end */
218 4; /* potential edgeflag enable/disable */
219 const unsigned v_overhead
= 1 + /* VERTEX_DATA packet header */
220 2; /* potential edgeflag modification */
221 struct util_split_prim s
;
231 ctx
.edgeflag_attr
= nv50
->vertprog
->cfg
.edgeflag_in
;
233 /* map vertex buffers, determine vertex size */
234 for (i
= 0; i
< nv50
->vtxelt
->num_elements
; i
++) {
235 struct pipe_vertex_element
*ve
= &nv50
->vtxelt
->pipe
[i
];
236 struct pipe_vertex_buffer
*vb
= &nv50
->vtxbuf
[ve
->vertex_buffer_index
];
237 struct nouveau_bo
*bo
= nv50_resource(vb
->buffer
)->bo
;
238 unsigned size
, nr_components
, n
;
240 if (!(nv50
->vbo_fifo
& (1 << i
)))
244 if (nouveau_bo_map(bo
, NOUVEAU_BO_RD
)) {
248 ctx
.attr
[n
].map
= (uint8_t *)bo
->map
+ vb
->buffer_offset
+ ve
->src_offset
;
249 nouveau_bo_unmap(bo
);
251 ctx
.attr
[n
].stride
= vb
->stride
;
252 ctx
.attr
[n
].divisor
= ve
->instance_divisor
;
253 if (ctx
.attr
[n
].divisor
) {
254 ctx
.attr
[n
].step
= i_start
% ve
->instance_divisor
;
255 ctx
.attr
[n
].map
= (uint8_t *)ctx
.attr
[n
].map
+ i_start
* vb
->stride
;
258 size
= util_format_get_component_bits(ve
->src_format
,
259 UTIL_FORMAT_COLORSPACE_RGB
, 0);
260 nr_components
= util_format_get_nr_components(ve
->src_format
);
263 switch (nr_components
) {
264 case 1: ctx
.attr
[n
].push
= emit_b08_1
; break;
265 case 2: ctx
.attr
[n
].push
= emit_b16_1
; break;
266 case 3: ctx
.attr
[n
].push
= emit_b08_3
; break;
267 case 4: ctx
.attr
[n
].push
= emit_b32_1
; break;
272 switch (nr_components
) {
273 case 1: ctx
.attr
[n
].push
= emit_b16_1
; break;
274 case 2: ctx
.attr
[n
].push
= emit_b32_1
; break;
275 case 3: ctx
.attr
[n
].push
= emit_b16_3
; break;
276 case 4: ctx
.attr
[n
].push
= emit_b32_2
; break;
278 ctx
.vtx_size
+= (nr_components
+ 1) >> 1;
281 switch (nr_components
) {
282 case 1: ctx
.attr
[n
].push
= emit_b32_1
; break;
283 case 2: ctx
.attr
[n
].push
= emit_b32_2
; break;
284 case 3: ctx
.attr
[n
].push
= emit_b32_3
; break;
285 case 4: ctx
.attr
[n
].push
= emit_b32_4
; break;
287 ctx
.vtx_size
+= nr_components
;
294 vtx_size
= ctx
.vtx_size
+ v_overhead
;
296 /* map index buffer, if present */
298 struct nouveau_bo
*bo
= nv50_resource(idxbuf
)->bo
;
300 if (nouveau_bo_map(bo
, NOUVEAU_BO_RD
)) {
304 ctx
.idxbuf
= bo
->map
;
305 ctx
.idxbias
= idxbias
;
306 ctx
.idxsize
= idxsize
;
307 nouveau_bo_unmap(bo
);
311 s
.edge
= emit_edgeflag
;
314 s
.emit
= idxbias
? emit_elt08_biased
: emit_elt08
;
317 s
.emit
= idxbias
? emit_elt16_biased
: emit_elt16
;
319 s
.emit
= idxbias
? emit_elt32_biased
: emit_elt32
;
323 /* per-instance loop */
324 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 2);
325 OUT_RING (chan
, NV50_CB_AUX
| (24 << 8));
326 OUT_RING (chan
, i_start
);
331 for (i
= 0; i
< ctx
.attr_nr
; i
++) {
332 if (!ctx
.attr
[i
].divisor
||
333 ctx
.attr
[i
].divisor
!= ++ctx
.attr
[i
].step
)
335 ctx
.attr
[i
].step
= 0;
336 ctx
.attr
[i
].map
= (uint8_t *)ctx
.attr
[i
].map
+ ctx
.attr
[i
].stride
;
339 util_split_prim_init(&s
, mode
, start
, count
);
341 if (AVAIL_RING(chan
) < p_overhead
+ (6 * vtx_size
)) {
343 if (!nv50_state_validate(nv50
, p_overhead
+ (6 * vtx_size
))) {
349 max_verts
= AVAIL_RING(chan
);
350 max_verts
-= p_overhead
;
351 max_verts
/= vtx_size
;
353 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_BEGIN
, 1);
354 OUT_RING (chan
, nv50_prim(s
.mode
) | (nzi
? (1 << 28) : 0));
355 done
= util_split_prim_next(&s
, max_verts
);
356 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_END
, 1);