Merge branch 'mesa_7_5_branch'
[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_inlines.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->base.base;
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_screen *pscreen = nv30->pipe.screen;
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 = pipe_buffer_map(pscreen, 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 pipe_buffer_unmap(pscreen, vb->buffer);
153 return FALSE;
154 }
155 }
156 break;
157 default:
158 pipe_buffer_unmap(pscreen, vb->buffer);
159 return FALSE;
160 }
161
162 pipe_buffer_unmap(pscreen, vb->buffer);
163 return TRUE;
164 }
165
166 boolean
167 nv30_draw_arrays(struct pipe_context *pipe,
168 unsigned mode, unsigned start, unsigned count)
169 {
170 struct nv30_context *nv30 = nv30_context(pipe);
171 struct nouveau_channel *chan = nv30->screen->base.channel;
172 unsigned restart = 0;
173
174 nv30_vbo_set_idxbuf(nv30, NULL, 0);
175 if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
176 /*return nv30_draw_elements_swtnl(pipe, NULL, 0,
177 mode, start, count);*/
178 return FALSE;
179 }
180
181 while (count) {
182 unsigned vc, nr;
183
184 nv30_state_emit(nv30);
185
186 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
187 mode, start, count, &restart);
188 if (!vc) {
189 FIRE_RING(NULL);
190 continue;
191 }
192
193 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
194 OUT_RING (nvgl_primitive(mode));
195
196 nr = (vc & 0xff);
197 if (nr) {
198 BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1);
199 OUT_RING (((nr - 1) << 24) | start);
200 start += nr;
201 }
202
203 nr = vc >> 8;
204 while (nr) {
205 unsigned push = nr > 2047 ? 2047 : nr;
206
207 nr -= push;
208
209 BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push);
210 while (push--) {
211 OUT_RING(((0x100 - 1) << 24) | start);
212 start += 0x100;
213 }
214 }
215
216 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
217 OUT_RING (0);
218
219 count -= vc;
220 start = restart;
221 }
222
223 pipe->flush(pipe, 0, NULL);
224 return TRUE;
225 }
226
227 static INLINE void
228 nv30_draw_elements_u08(struct nv30_context *nv30, void *ib,
229 unsigned mode, unsigned start, unsigned count)
230 {
231 struct nouveau_channel *chan = nv30->screen->base.channel;
232
233 while (count) {
234 uint8_t *elts = (uint8_t *)ib + start;
235 unsigned vc, push, restart = 0;
236
237 nv30_state_emit(nv30);
238
239 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
240 mode, start, count, &restart);
241 if (vc == 0) {
242 FIRE_RING(NULL);
243 continue;
244 }
245 count -= vc;
246
247 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
248 OUT_RING (nvgl_primitive(mode));
249
250 if (vc & 1) {
251 BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
252 OUT_RING (elts[0]);
253 elts++; vc--;
254 }
255
256 while (vc) {
257 unsigned i;
258
259 push = MIN2(vc, 2047 * 2);
260
261 BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
262 for (i = 0; i < push; i+=2)
263 OUT_RING((elts[i+1] << 16) | elts[i]);
264
265 vc -= push;
266 elts += push;
267 }
268
269 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
270 OUT_RING (0);
271
272 start = restart;
273 }
274 }
275
276 static INLINE void
277 nv30_draw_elements_u16(struct nv30_context *nv30, void *ib,
278 unsigned mode, unsigned start, unsigned count)
279 {
280 struct nouveau_channel *chan = nv30->screen->base.channel;
281
282 while (count) {
283 uint16_t *elts = (uint16_t *)ib + start;
284 unsigned vc, push, restart = 0;
285
286 nv30_state_emit(nv30);
287
288 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
289 mode, start, count, &restart);
290 if (vc == 0) {
291 FIRE_RING(NULL);
292 continue;
293 }
294 count -= vc;
295
296 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
297 OUT_RING (nvgl_primitive(mode));
298
299 if (vc & 1) {
300 BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
301 OUT_RING (elts[0]);
302 elts++; vc--;
303 }
304
305 while (vc) {
306 unsigned i;
307
308 push = MIN2(vc, 2047 * 2);
309
310 BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
311 for (i = 0; i < push; i+=2)
312 OUT_RING((elts[i+1] << 16) | elts[i]);
313
314 vc -= push;
315 elts += push;
316 }
317
318 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
319 OUT_RING (0);
320
321 start = restart;
322 }
323 }
324
325 static INLINE void
326 nv30_draw_elements_u32(struct nv30_context *nv30, void *ib,
327 unsigned mode, unsigned start, unsigned count)
328 {
329 struct nouveau_channel *chan = nv30->screen->base.channel;
330
331 while (count) {
332 uint32_t *elts = (uint32_t *)ib + start;
333 unsigned vc, push, restart = 0;
334
335 nv30_state_emit(nv30);
336
337 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1,
338 mode, start, count, &restart);
339 if (vc == 0) {
340 FIRE_RING(NULL);
341 continue;
342 }
343 count -= vc;
344
345 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
346 OUT_RING (nvgl_primitive(mode));
347
348 while (vc) {
349 push = MIN2(vc, 2047);
350
351 BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U32, push);
352 OUT_RINGp (elts, push);
353
354 vc -= push;
355 elts += push;
356 }
357
358 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
359 OUT_RING (0);
360
361 start = restart;
362 }
363 }
364
365 static boolean
366 nv30_draw_elements_inline(struct pipe_context *pipe,
367 struct pipe_buffer *ib, unsigned ib_size,
368 unsigned mode, unsigned start, unsigned count)
369 {
370 struct nv30_context *nv30 = nv30_context(pipe);
371 struct pipe_screen *pscreen = pipe->screen;
372 void *map;
373
374 map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ);
375 if (!ib) {
376 NOUVEAU_ERR("failed mapping ib\n");
377 return FALSE;
378 }
379
380 switch (ib_size) {
381 case 1:
382 nv30_draw_elements_u08(nv30, map, mode, start, count);
383 break;
384 case 2:
385 nv30_draw_elements_u16(nv30, map, mode, start, count);
386 break;
387 case 4:
388 nv30_draw_elements_u32(nv30, map, mode, start, count);
389 break;
390 default:
391 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
392 break;
393 }
394
395 pipe_buffer_unmap(pscreen, ib);
396 return TRUE;
397 }
398
399 static boolean
400 nv30_draw_elements_vbo(struct pipe_context *pipe,
401 unsigned mode, unsigned start, unsigned count)
402 {
403 struct nv30_context *nv30 = nv30_context(pipe);
404 struct nouveau_channel *chan = nv30->screen->base.channel;
405 unsigned restart = 0;
406
407 while (count) {
408 unsigned nr, vc;
409
410 nv30_state_emit(nv30);
411
412 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
413 mode, start, count, &restart);
414 if (!vc) {
415 FIRE_RING(NULL);
416 continue;
417 }
418
419 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
420 OUT_RING (nvgl_primitive(mode));
421
422 nr = (vc & 0xff);
423 if (nr) {
424 BEGIN_RING(rankine, NV34TCL_VB_INDEX_BATCH, 1);
425 OUT_RING (((nr - 1) << 24) | start);
426 start += nr;
427 }
428
429 nr = vc >> 8;
430 while (nr) {
431 unsigned push = nr > 2047 ? 2047 : nr;
432
433 nr -= push;
434
435 BEGIN_RING_NI(rankine, NV34TCL_VB_INDEX_BATCH, push);
436 while (push--) {
437 OUT_RING(((0x100 - 1) << 24) | start);
438 start += 0x100;
439 }
440 }
441
442 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
443 OUT_RING (0);
444
445 count -= vc;
446 start = restart;
447 }
448
449 return TRUE;
450 }
451
452 boolean
453 nv30_draw_elements(struct pipe_context *pipe,
454 struct pipe_buffer *indexBuffer, unsigned indexSize,
455 unsigned mode, unsigned start, unsigned count)
456 {
457 struct nv30_context *nv30 = nv30_context(pipe);
458 boolean idxbuf;
459
460 idxbuf = nv30_vbo_set_idxbuf(nv30, indexBuffer, indexSize);
461 if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
462 /*return nv30_draw_elements_swtnl(pipe, NULL, 0,
463 mode, start, count);*/
464 return FALSE;
465 }
466
467 if (idxbuf) {
468 nv30_draw_elements_vbo(pipe, mode, start, count);
469 } else {
470 nv30_draw_elements_inline(pipe, indexBuffer, indexSize,
471 mode, start, count);
472 }
473
474 pipe->flush(pipe, 0, NULL);
475 return TRUE;
476 }
477
478 static boolean
479 nv30_vbo_validate(struct nv30_context *nv30)
480 {
481 struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL;
482 struct nouveau_grobj *rankine = nv30->screen->rankine;
483 struct pipe_buffer *ib = nv30->idxbuf;
484 unsigned ib_format = nv30->idxbuf_format;
485 unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
486 int hw;
487
488 if (nv30->edgeflags) {
489 /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/
490 return FALSE;
491 }
492
493 vtxbuf = so_new(20, 18);
494 so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt_nr);
495 vtxfmt = so_new(17, 0);
496 so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt_nr);
497
498 for (hw = 0; hw < nv30->vtxelt_nr; hw++) {
499 struct pipe_vertex_element *ve;
500 struct pipe_vertex_buffer *vb;
501 unsigned type, ncomp;
502
503 ve = &nv30->vtxelt[hw];
504 vb = &nv30->vtxbuf[ve->vertex_buffer_index];
505
506 if (!vb->stride) {
507 if (!sattr)
508 sattr = so_new(16 * 5, 0);
509
510 if (nv30_vbo_static_attrib(nv30, sattr, hw, ve, vb)) {
511 so_data(vtxbuf, 0);
512 so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT);
513 continue;
514 }
515 }
516
517 if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) {
518 /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/
519 so_ref(NULL, &vtxbuf);
520 so_ref(NULL, &vtxfmt);
521 return FALSE;
522 }
523
524 so_reloc(vtxbuf, nouveau_bo(vb->buffer), vb->buffer_offset +
525 ve->src_offset, vb_flags | NOUVEAU_BO_LOW |
526 NOUVEAU_BO_OR, 0, NV34TCL_VTXBUF_ADDRESS_DMA1);
527 so_data (vtxfmt, ((vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT) |
528 (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type));
529 }
530
531 if (ib) {
532 struct nouveau_bo *bo = nouveau_bo(ib);
533
534 so_method(vtxbuf, rankine, NV34TCL_IDXBUF_ADDRESS, 2);
535 so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
536 so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR,
537 0, NV34TCL_IDXBUF_FORMAT_DMA1);
538 }
539
540 so_method(vtxbuf, rankine, 0x1710, 1);
541 so_data (vtxbuf, 0);
542
543 so_ref(vtxbuf, &nv30->state.hw[NV30_STATE_VTXBUF]);
544 so_ref(NULL, &vtxbuf);
545 nv30->state.dirty |= (1ULL << NV30_STATE_VTXBUF);
546 so_ref(vtxfmt, &nv30->state.hw[NV30_STATE_VTXFMT]);
547 so_ref(NULL, &vtxfmt);
548 nv30->state.dirty |= (1ULL << NV30_STATE_VTXFMT);
549 so_ref(sattr, &nv30->state.hw[NV30_STATE_VTXATTR]);
550 so_ref(NULL, &sattr);
551 nv30->state.dirty |= (1ULL << NV30_STATE_VTXATTR);
552 return FALSE;
553 }
554
555 struct nv30_state_entry nv30_state_vbo = {
556 .validate = nv30_vbo_validate,
557 .dirty = {
558 .pipe = NV30_NEW_ARRAYS,
559 .hw = 0,
560 }
561 };