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