b1c73793bf2e8c73a6d037b7c8e1cc454599c0ca
[mesa.git] / src / gallium / drivers / nv30 / nv30_vbo.c
1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "pipe/p_util.h"
4
5 #include "nv30_context.h"
6 #include "nv30_state.h"
7
8 #include "nouveau/nouveau_channel.h"
9 #include "nouveau/nouveau_pushbuf.h"
10 #include "nouveau/nouveau_util.h"
11
12 #define FORCE_SWTNL 0
13
14 static INLINE int
15 nv30_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp)
16 {
17 switch (pipe) {
18 case PIPE_FORMAT_R32_FLOAT:
19 case PIPE_FORMAT_R32G32_FLOAT:
20 case PIPE_FORMAT_R32G32B32_FLOAT:
21 case PIPE_FORMAT_R32G32B32A32_FLOAT:
22 *fmt = NV34TCL_VTXFMT_TYPE_FLOAT;
23 break;
24 case PIPE_FORMAT_R8_UNORM:
25 case PIPE_FORMAT_R8G8_UNORM:
26 case PIPE_FORMAT_R8G8B8_UNORM:
27 case PIPE_FORMAT_R8G8B8A8_UNORM:
28 *fmt = NV34TCL_VTXFMT_TYPE_UBYTE;
29 break;
30 case PIPE_FORMAT_R16_SSCALED:
31 case PIPE_FORMAT_R16G16_SSCALED:
32 case PIPE_FORMAT_R16G16B16_SSCALED:
33 case PIPE_FORMAT_R16G16B16A16_SSCALED:
34 *fmt = NV34TCL_VTXFMT_TYPE_USHORT;
35 break;
36 default:
37 NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe));
38 return 1;
39 }
40
41 switch (pipe) {
42 case PIPE_FORMAT_R8_UNORM:
43 case PIPE_FORMAT_R32_FLOAT:
44 case PIPE_FORMAT_R16_SSCALED:
45 *ncomp = 1;
46 break;
47 case PIPE_FORMAT_R8G8_UNORM:
48 case PIPE_FORMAT_R32G32_FLOAT:
49 case PIPE_FORMAT_R16G16_SSCALED:
50 *ncomp = 2;
51 break;
52 case PIPE_FORMAT_R8G8B8_UNORM:
53 case PIPE_FORMAT_R32G32B32_FLOAT:
54 case PIPE_FORMAT_R16G16B16_SSCALED:
55 *ncomp = 3;
56 break;
57 case PIPE_FORMAT_R8G8B8A8_UNORM:
58 case PIPE_FORMAT_R32G32B32A32_FLOAT:
59 case PIPE_FORMAT_R16G16B16A16_SSCALED:
60 *ncomp = 4;
61 break;
62 default:
63 NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe));
64 return 1;
65 }
66
67 return 0;
68 }
69
70 static boolean
71 nv30_vbo_set_idxbuf(struct nv30_context *nv30, struct pipe_buffer *ib,
72 unsigned ib_size)
73 {
74 struct pipe_screen *pscreen = &nv30->screen->pipe;
75 unsigned type;
76
77 if (!ib) {
78 nv30->idxbuf = NULL;
79 nv30->idxbuf_format = 0xdeadbeef;
80 return FALSE;
81 }
82
83 if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1)
84 return FALSE;
85
86 switch (ib_size) {
87 case 2:
88 type = NV34TCL_IDXBUF_FORMAT_TYPE_U16;
89 break;
90 case 4:
91 type = NV34TCL_IDXBUF_FORMAT_TYPE_U32;
92 break;
93 default:
94 return FALSE;
95 }
96
97 if (ib != nv30->idxbuf ||
98 type != nv30->idxbuf_format) {
99 nv30->dirty |= NV30_NEW_ARRAYS;
100 nv30->idxbuf = ib;
101 nv30->idxbuf_format = type;
102 }
103
104 return TRUE;
105 }
106
107 static boolean
108 nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so,
109 int attrib, struct pipe_vertex_element *ve,
110 struct pipe_vertex_buffer *vb)
111 {
112 struct pipe_winsys *ws = nv30->pipe.winsys;
113 struct nouveau_grobj *rankine = nv30->screen->rankine;
114 unsigned type, ncomp;
115 void *map;
116
117 if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp))
118 return FALSE;
119
120 map = ws->buffer_map(ws, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ);
121 map += vb->buffer_offset + ve->src_offset;
122
123 switch (type) {
124 case NV34TCL_VTXFMT_TYPE_FLOAT:
125 {
126 float *v = map;
127
128 switch (ncomp) {
129 case 4:
130 so_method(so, rankine, NV34TCL_VTX_ATTR_4F_X(attrib), 4);
131 so_data (so, fui(v[0]));
132 so_data (so, fui(v[1]));
133 so_data (so, fui(v[2]));
134 so_data (so, fui(v[3]));
135 break;
136 case 3:
137 so_method(so, rankine, NV34TCL_VTX_ATTR_3F_X(attrib), 3);
138 so_data (so, fui(v[0]));
139 so_data (so, fui(v[1]));
140 so_data (so, fui(v[2]));
141 break;
142 case 2:
143 so_method(so, rankine, NV34TCL_VTX_ATTR_2F_X(attrib), 2);
144 so_data (so, fui(v[0]));
145 so_data (so, fui(v[1]));
146 break;
147 case 1:
148 so_method(so, rankine, NV34TCL_VTX_ATTR_1F(attrib), 1);
149 so_data (so, fui(v[0]));
150 break;
151 default:
152 ws->buffer_unmap(ws, vb->buffer);
153 return FALSE;
154 }
155 }
156 break;
157 default:
158 ws->buffer_unmap(ws, vb->buffer);
159 return FALSE;
160 }
161
162 ws->buffer_unmap(ws, vb->buffer);
163
164 return TRUE;
165 }
166
167 boolean
168 nv30_draw_arrays(struct pipe_context *pipe,
169 unsigned mode, unsigned start, unsigned count)
170 {
171 struct nv30_context *nv30 = nv30_context(pipe);
172 struct nouveau_channel *chan = nv30->nvws->channel;
173 unsigned restart = 0;
174
175 nv30_vbo_set_idxbuf(nv30, NULL, 0);
176 if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
177 /*return nv30_draw_elements_swtnl(pipe, NULL, 0,
178 mode, start, count);*/
179 return FALSE;
180 }
181
182 while (count) {
183 unsigned vc, nr;
184
185 nv30_state_emit(nv30);
186
187 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
188 mode, start, count, &restart);
189 if (!vc) {
190 FIRE_RING(NULL);
191 continue;
192 }
193
194 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
195 OUT_RING (nvgl_primitive(mode));
196
197 nr = (vc & 0xff);
198 if (nr) {
199 BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1);
200 OUT_RING (((nr - 1) << 24) | start);
201 start += nr;
202 }
203
204 nr = vc >> 8;
205 while (nr) {
206 unsigned push = nr > 2047 ? 2047 : nr;
207
208 nr -= push;
209
210 BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push);
211 while (push--) {
212 OUT_RING(((0x100 - 1) << 24) | start);
213 start += 0x100;
214 }
215 }
216
217 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
218 OUT_RING (0);
219
220 count -= vc;
221 start = restart;
222 }
223
224 pipe->flush(pipe, 0, NULL);
225 return TRUE;
226 }
227
228 static INLINE void
229 nv30_draw_elements_u08(struct nv30_context *nv30, void *ib,
230 unsigned mode, unsigned start, unsigned count)
231 {
232 struct nouveau_channel *chan = nv30->nvws->channel;
233
234 while (count) {
235 uint8_t *elts = (uint8_t *)ib + start;
236 unsigned vc, push, restart = 0;
237
238 nv30_state_emit(nv30);
239
240 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
241 mode, start, count, &restart);
242 if (vc == 0) {
243 FIRE_RING(NULL);
244 continue;
245 }
246 count -= vc;
247
248 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
249 OUT_RING (nvgl_primitive(mode));
250
251 if (vc & 1) {
252 BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
253 OUT_RING (elts[0]);
254 elts++; vc--;
255 }
256
257 while (vc) {
258 unsigned i;
259
260 push = MIN2(vc, 2047 * 2);
261
262 BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
263 for (i = 0; i < push; i+=2)
264 OUT_RING((elts[i+1] << 16) | elts[i]);
265
266 vc -= push;
267 elts += push;
268 }
269
270 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
271 OUT_RING (0);
272
273 start = restart;
274 }
275 }
276
277 static INLINE void
278 nv30_draw_elements_u16(struct nv30_context *nv30, void *ib,
279 unsigned mode, unsigned start, unsigned count)
280 {
281 struct nouveau_channel *chan = nv30->nvws->channel;
282
283 while (count) {
284 uint16_t *elts = (uint16_t *)ib + start;
285 unsigned vc, push, restart = 0;
286
287 nv30_state_emit(nv30);
288
289 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
290 mode, start, count, &restart);
291 if (vc == 0) {
292 FIRE_RING(NULL);
293 continue;
294 }
295 count -= vc;
296
297 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
298 OUT_RING (nvgl_primitive(mode));
299
300 if (vc & 1) {
301 BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
302 OUT_RING (elts[0]);
303 elts++; vc--;
304 }
305
306 while (vc) {
307 unsigned i;
308
309 push = MIN2(vc, 2047 * 2);
310
311 BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
312 for (i = 0; i < push; i+=2)
313 OUT_RING((elts[i+1] << 16) | elts[i]);
314
315 vc -= push;
316 elts += push;
317 }
318
319 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
320 OUT_RING (0);
321
322 start = restart;
323 }
324 }
325
326 static INLINE void
327 nv30_draw_elements_u32(struct nv30_context *nv30, void *ib,
328 unsigned mode, unsigned start, unsigned count)
329 {
330 struct nouveau_channel *chan = nv30->nvws->channel;
331
332 while (count) {
333 uint32_t *elts = (uint32_t *)ib + start;
334 unsigned vc, push, restart = 0;
335
336 nv30_state_emit(nv30);
337
338 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1,
339 mode, start, count, &restart);
340 if (vc == 0) {
341 FIRE_RING(NULL);
342 continue;
343 }
344 count -= vc;
345
346 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
347 OUT_RING (nvgl_primitive(mode));
348
349 while (vc) {
350 push = MIN2(vc, 2047);
351
352 BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U32, push);
353 OUT_RINGp (elts, push);
354
355 vc -= push;
356 elts += push;
357 }
358
359 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
360 OUT_RING (0);
361
362 start = restart;
363 }
364 }
365
366 static boolean
367 nv30_draw_elements_inline(struct pipe_context *pipe,
368 struct pipe_buffer *ib, unsigned ib_size,
369 unsigned mode, unsigned start, unsigned count)
370 {
371 struct nv30_context *nv30 = nv30_context(pipe);
372 struct pipe_winsys *ws = pipe->winsys;
373 void *map;
374
375 map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ);
376 if (!ib) {
377 NOUVEAU_ERR("failed mapping ib\n");
378 return FALSE;
379 }
380
381 switch (ib_size) {
382 case 1:
383 nv30_draw_elements_u08(nv30, map, mode, start, count);
384 break;
385 case 2:
386 nv30_draw_elements_u16(nv30, map, mode, start, count);
387 break;
388 case 4:
389 nv30_draw_elements_u32(nv30, map, mode, start, count);
390 break;
391 default:
392 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
393 break;
394 }
395
396 ws->buffer_unmap(ws, ib);
397 return TRUE;
398 }
399
400 static boolean
401 nv30_draw_elements_vbo(struct pipe_context *pipe,
402 unsigned mode, unsigned start, unsigned count)
403 {
404 struct nv30_context *nv30 = nv30_context(pipe);
405 struct nouveau_channel *chan = nv30->nvws->channel;
406 unsigned restart = 0;
407
408 while (count) {
409 unsigned nr, vc;
410
411 nv30_state_emit(nv30);
412
413 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
414 mode, start, count, &restart);
415 if (!vc) {
416 FIRE_RING(NULL);
417 continue;
418 }
419
420 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
421 OUT_RING (nvgl_primitive(mode));
422
423 nr = (vc & 0xff);
424 if (nr) {
425 BEGIN_RING(rankine, NV34TCL_VB_INDEX_BATCH, 1);
426 OUT_RING (((nr - 1) << 24) | start);
427 start += nr;
428 }
429
430 nr = vc >> 8;
431 while (nr) {
432 unsigned push = nr > 2047 ? 2047 : nr;
433
434 nr -= push;
435
436 BEGIN_RING_NI(rankine, NV34TCL_VB_INDEX_BATCH, push);
437 while (push--) {
438 OUT_RING(((0x100 - 1) << 24) | start);
439 start += 0x100;
440 }
441 }
442
443 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
444 OUT_RING (0);
445
446 count -= vc;
447 start = restart;
448 }
449
450 return TRUE;
451 }
452
453 boolean
454 nv30_draw_elements(struct pipe_context *pipe,
455 struct pipe_buffer *indexBuffer, unsigned indexSize,
456 unsigned mode, unsigned start, unsigned count)
457 {
458 struct nv30_context *nv30 = nv30_context(pipe);
459 boolean idxbuf;
460
461 idxbuf = nv30_vbo_set_idxbuf(nv30, indexBuffer, indexSize);
462 if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
463 /*return nv30_draw_elements_swtnl(pipe, NULL, 0,
464 mode, start, count);*/
465 return FALSE;
466 }
467
468 if (idxbuf) {
469 nv30_draw_elements_vbo(pipe, mode, start, count);
470 } else {
471 nv30_draw_elements_inline(pipe, indexBuffer, indexSize,
472 mode, start, count);
473 }
474
475 pipe->flush(pipe, 0, NULL);
476 return TRUE;
477 }
478
479 static boolean
480 nv30_vbo_validate(struct nv30_context *nv30)
481 {
482 struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL;
483 struct nouveau_grobj *rankine = nv30->screen->rankine;
484 struct pipe_buffer *ib = nv30->idxbuf;
485 unsigned ib_format = nv30->idxbuf_format;
486 unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
487 int hw;
488
489 if (nv30->edgeflags) {
490 /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/
491 return FALSE;
492 }
493
494 vtxbuf = so_new(20, 18);
495 so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt_nr);
496 vtxfmt = so_new(17, 0);
497 so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt_nr);
498
499 for (hw = 0; hw < nv30->vtxelt_nr; hw++) {
500 struct pipe_vertex_element *ve;
501 struct pipe_vertex_buffer *vb;
502 unsigned type, ncomp;
503
504 ve = &nv30->vtxelt[hw];
505 vb = &nv30->vtxbuf[ve->vertex_buffer_index];
506
507 if (!vb->pitch) {
508 if (!sattr)
509 sattr = so_new(16 * 5, 0);
510
511 if (nv30_vbo_static_attrib(nv30, sattr, hw, ve, vb)) {
512 so_data(vtxbuf, 0);
513 so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT);
514 continue;
515 }
516 }
517
518 if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) {
519 /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/
520 so_ref(NULL, &vtxbuf);
521 so_ref(NULL, &vtxfmt);
522 return FALSE;
523 }
524
525 so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset,
526 vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
527 0, NV34TCL_VTXBUF_ADDRESS_DMA1);
528 so_data (vtxfmt, ((vb->pitch << NV34TCL_VTXFMT_STRIDE_SHIFT) |
529 (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type));
530 }
531
532 if (ib) {
533 so_method(vtxbuf, rankine, NV34TCL_IDXBUF_ADDRESS, 2);
534 so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
535 so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR,
536 0, NV34TCL_IDXBUF_FORMAT_DMA1);
537 }
538
539 so_method(vtxbuf, rankine, 0x1710, 1);
540 so_data (vtxbuf, 0);
541
542 so_ref(vtxbuf, &nv30->state.hw[NV30_STATE_VTXBUF]);
543 nv30->state.dirty |= (1ULL << NV30_STATE_VTXBUF);
544 so_ref(vtxfmt, &nv30->state.hw[NV30_STATE_VTXFMT]);
545 nv30->state.dirty |= (1ULL << NV30_STATE_VTXFMT);
546 so_ref(sattr, &nv30->state.hw[NV30_STATE_VTXATTR]);
547 nv30->state.dirty |= (1ULL << NV30_STATE_VTXATTR);
548 return FALSE;
549 }
550
551 struct nv30_state_entry nv30_state_vbo = {
552 .validate = nv30_vbo_validate,
553 .dirty = {
554 .pipe = NV30_NEW_ARRAYS,
555 .hw = 0,
556 }
557 };