1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "util/u_inlines.h"
4 #include "util/u_format.h"
6 #include "nvfx_context.h"
7 #include "nvfx_state.h"
8 #include "nvfx_resource.h"
10 #include "nouveau/nouveau_channel.h"
11 #include "nouveau/nouveau_pushbuf.h"
12 #include "nouveau/nouveau_util.h"
15 nvfx_force_swtnl(struct nvfx_context *nvfx)
17 static int force_swtnl = -1;
19 force_swtnl = debug_get_bool_option("NOUVEAU_SWTNL", 0);
24 nvfx_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp)
27 case PIPE_FORMAT_R32_FLOAT:
28 case PIPE_FORMAT_R32G32_FLOAT:
29 case PIPE_FORMAT_R32G32B32_FLOAT:
30 case PIPE_FORMAT_R32G32B32A32_FLOAT:
31 *fmt = NV34TCL_VTXFMT_TYPE_FLOAT;
33 case PIPE_FORMAT_R8_UNORM:
34 case PIPE_FORMAT_R8G8_UNORM:
35 case PIPE_FORMAT_R8G8B8_UNORM:
36 case PIPE_FORMAT_R8G8B8A8_UNORM:
37 *fmt = NV34TCL_VTXFMT_TYPE_UBYTE;
39 case PIPE_FORMAT_R16_SSCALED:
40 case PIPE_FORMAT_R16G16_SSCALED:
41 case PIPE_FORMAT_R16G16B16_SSCALED:
42 case PIPE_FORMAT_R16G16B16A16_SSCALED:
43 *fmt = NV34TCL_VTXFMT_TYPE_USHORT;
46 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe));
51 case PIPE_FORMAT_R8_UNORM:
52 case PIPE_FORMAT_R32_FLOAT:
53 case PIPE_FORMAT_R16_SSCALED:
56 case PIPE_FORMAT_R8G8_UNORM:
57 case PIPE_FORMAT_R32G32_FLOAT:
58 case PIPE_FORMAT_R16G16_SSCALED:
61 case PIPE_FORMAT_R8G8B8_UNORM:
62 case PIPE_FORMAT_R32G32B32_FLOAT:
63 case PIPE_FORMAT_R16G16B16_SSCALED:
66 case PIPE_FORMAT_R8G8B8A8_UNORM:
67 case PIPE_FORMAT_R32G32B32A32_FLOAT:
68 case PIPE_FORMAT_R16G16B16A16_SSCALED:
72 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe));
80 nvfx_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_resource *ib,
83 struct pipe_screen *pscreen = &nvfx->screen->base.base;
88 nvfx->idxbuf_format = 0xdeadbeef;
92 if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1)
97 type = NV34TCL_IDXBUF_FORMAT_TYPE_U16;
100 type = NV34TCL_IDXBUF_FORMAT_TYPE_U32;
106 if (ib != nvfx->idxbuf ||
107 type != nvfx->idxbuf_format) {
108 nvfx->dirty |= NVFX_NEW_ARRAYS;
110 nvfx->idxbuf_format = type;
117 nvfx_vbo_static_attrib(struct nvfx_context *nvfx, struct nouveau_stateobj *so,
118 int attrib, struct pipe_vertex_element *ve,
119 struct pipe_vertex_buffer *vb)
121 struct pipe_context *pipe = &nvfx->pipe;
122 struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
123 struct pipe_transfer *transfer;
124 unsigned type, ncomp;
127 if (nvfx_vbo_format_to_hw(ve->src_format, &type, &ncomp))
130 map = pipe_buffer_map(pipe, vb->buffer, PIPE_TRANSFER_READ, &transfer);
131 map += vb->buffer_offset + ve->src_offset;
134 case NV34TCL_VTXFMT_TYPE_FLOAT:
136 float *v = (float *)map;
140 so_method(so, eng3d, NV34TCL_VTX_ATTR_4F_X(attrib), 4);
141 so_data (so, fui(v[0]));
142 so_data (so, fui(v[1]));
143 so_data (so, fui(v[2]));
144 so_data (so, fui(v[3]));
147 so_method(so, eng3d, NV34TCL_VTX_ATTR_3F_X(attrib), 3);
148 so_data (so, fui(v[0]));
149 so_data (so, fui(v[1]));
150 so_data (so, fui(v[2]));
153 so_method(so, eng3d, NV34TCL_VTX_ATTR_2F_X(attrib), 2);
154 so_data (so, fui(v[0]));
155 so_data (so, fui(v[1]));
158 so_method(so, eng3d, NV34TCL_VTX_ATTR_1F(attrib), 1);
159 so_data (so, fui(v[0]));
162 pipe_buffer_unmap(pipe, vb->buffer, transfer);
168 pipe_buffer_unmap(pipe, vb->buffer, transfer);
172 pipe_buffer_unmap(pipe, vb->buffer, transfer);
177 nvfx_draw_arrays(struct pipe_context *pipe,
178 unsigned mode, unsigned start, unsigned count)
180 struct nvfx_context *nvfx = nvfx_context(pipe);
181 struct nvfx_screen *screen = nvfx->screen;
182 struct nouveau_channel *chan = screen->base.channel;
183 struct nouveau_grobj *eng3d = screen->eng3d;
184 unsigned restart = 0;
186 nvfx_vbo_set_idxbuf(nvfx, NULL, 0);
187 if (nvfx_force_swtnl(nvfx) || !nvfx_state_validate(nvfx)) {
188 nvfx_draw_elements_swtnl(pipe, NULL, 0,
196 nvfx_state_emit(nvfx);
198 vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256,
199 mode, start, count, &restart);
205 BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1);
206 OUT_RING (chan, nvgl_primitive(mode));
210 BEGIN_RING(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, 1);
211 OUT_RING (chan, ((nr - 1) << 24) | start);
217 unsigned push = nr > 2047 ? 2047 : nr;
221 BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, push);
223 OUT_RING(chan, ((0x100 - 1) << 24) | start);
228 BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1);
235 pipe->flush(pipe, 0, NULL);
239 nvfx_draw_elements_u08(struct nvfx_context *nvfx, void *ib,
240 unsigned mode, unsigned start, unsigned count)
242 struct nvfx_screen *screen = nvfx->screen;
243 struct nouveau_channel *chan = screen->base.channel;
244 struct nouveau_grobj *eng3d = screen->eng3d;
247 uint8_t *elts = (uint8_t *)ib + start;
248 unsigned vc, push, restart = 0;
250 nvfx_state_emit(nvfx);
252 vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2,
253 mode, start, count, &restart);
260 BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1);
261 OUT_RING (chan, nvgl_primitive(mode));
264 BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1);
265 OUT_RING (chan, elts[0]);
272 push = MIN2(vc, 2047 * 2);
274 BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1);
275 for (i = 0; i < push; i+=2)
276 OUT_RING(chan, (elts[i+1] << 16) | elts[i]);
282 BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1);
290 nvfx_draw_elements_u16(struct nvfx_context *nvfx, void *ib,
291 unsigned mode, unsigned start, unsigned count)
293 struct nvfx_screen *screen = nvfx->screen;
294 struct nouveau_channel *chan = screen->base.channel;
295 struct nouveau_grobj *eng3d = screen->eng3d;
298 uint16_t *elts = (uint16_t *)ib + start;
299 unsigned vc, push, restart = 0;
301 nvfx_state_emit(nvfx);
303 vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2,
304 mode, start, count, &restart);
311 BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1);
312 OUT_RING (chan, nvgl_primitive(mode));
315 BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1);
316 OUT_RING (chan, elts[0]);
323 push = MIN2(vc, 2047 * 2);
325 BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1);
326 for (i = 0; i < push; i+=2)
327 OUT_RING(chan, (elts[i+1] << 16) | elts[i]);
333 BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1);
341 nvfx_draw_elements_u32(struct nvfx_context *nvfx, void *ib,
342 unsigned mode, unsigned start, unsigned count)
344 struct nvfx_screen *screen = nvfx->screen;
345 struct nouveau_channel *chan = screen->base.channel;
346 struct nouveau_grobj *eng3d = screen->eng3d;
349 uint32_t *elts = (uint32_t *)ib + start;
350 unsigned vc, push, restart = 0;
352 nvfx_state_emit(nvfx);
354 vc = nouveau_vbuf_split(AVAIL_RING(chan), 5, 1,
355 mode, start, count, &restart);
362 BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1);
363 OUT_RING (chan, nvgl_primitive(mode));
366 push = MIN2(vc, 2047);
368 BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U32, push);
369 OUT_RINGp (chan, elts, push);
375 BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1);
383 nvfx_draw_elements_inline(struct pipe_context *pipe,
384 struct pipe_resource *ib, unsigned ib_size,
385 unsigned mode, unsigned start, unsigned count)
387 struct nvfx_context *nvfx = nvfx_context(pipe);
388 struct pipe_transfer *transfer;
391 map = pipe_buffer_map(pipe, ib, PIPE_TRANSFER_READ, &transfer);
393 NOUVEAU_ERR("failed mapping ib\n");
399 nvfx_draw_elements_u08(nvfx, map, mode, start, count);
402 nvfx_draw_elements_u16(nvfx, map, mode, start, count);
405 nvfx_draw_elements_u32(nvfx, map, mode, start, count);
408 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
412 pipe_buffer_unmap(pipe, ib, transfer);
416 nvfx_draw_elements_vbo(struct pipe_context *pipe,
417 unsigned mode, unsigned start, unsigned count)
419 struct nvfx_context *nvfx = nvfx_context(pipe);
420 struct nvfx_screen *screen = nvfx->screen;
421 struct nouveau_channel *chan = screen->base.channel;
422 struct nouveau_grobj *eng3d = screen->eng3d;
423 unsigned restart = 0;
428 nvfx_state_emit(nvfx);
430 vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256,
431 mode, start, count, &restart);
437 BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1);
438 OUT_RING (chan, nvgl_primitive(mode));
442 BEGIN_RING(chan, eng3d, NV34TCL_VB_INDEX_BATCH, 1);
443 OUT_RING (chan, ((nr - 1) << 24) | start);
449 unsigned push = nr > 2047 ? 2047 : nr;
453 BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_INDEX_BATCH, push);
455 OUT_RING(chan, ((0x100 - 1) << 24) | start);
460 BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1);
469 nvfx_draw_elements(struct pipe_context *pipe,
470 struct pipe_resource *indexBuffer, unsigned indexSize,
471 unsigned mode, unsigned start, unsigned count)
473 struct nvfx_context *nvfx = nvfx_context(pipe);
476 idxbuf = nvfx_vbo_set_idxbuf(nvfx, indexBuffer, indexSize);
477 if (nvfx_force_swtnl(nvfx) || !nvfx_state_validate(nvfx)) {
478 nvfx_draw_elements_swtnl(pipe, indexBuffer, indexSize,
484 nvfx_draw_elements_vbo(pipe, mode, start, count);
486 nvfx_draw_elements_inline(pipe, indexBuffer, indexSize,
490 pipe->flush(pipe, 0, NULL);
494 nvfx_vbo_validate(struct nvfx_context *nvfx)
496 struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL;
497 struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
498 struct pipe_resource *ib = nvfx->idxbuf;
499 unsigned ib_format = nvfx->idxbuf_format;
500 unsigned vb_flags = nvfx->screen->vertex_buffer_flags | NOUVEAU_BO_RD;
503 vtxbuf = so_new(3, 17, 18);
504 so_method(vtxbuf, eng3d, NV34TCL_VTXBUF_ADDRESS(0), nvfx->vtxelt->num_elements);
505 vtxfmt = so_new(1, 16, 0);
506 so_method(vtxfmt, eng3d, NV34TCL_VTXFMT(0), nvfx->vtxelt->num_elements);
508 for (hw = 0; hw < nvfx->vtxelt->num_elements; hw++) {
509 struct pipe_vertex_element *ve;
510 struct pipe_vertex_buffer *vb;
511 unsigned type, ncomp;
513 ve = &nvfx->vtxelt->pipe[hw];
514 vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
518 sattr = so_new(16, 16 * 4, 0);
520 if (nvfx_vbo_static_attrib(nvfx, sattr, hw, ve, vb)) {
522 so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT);
527 if (nvfx_vbo_format_to_hw(ve->src_format, &type, &ncomp)) {
528 nvfx->fallback_swtnl |= NVFX_NEW_ARRAYS;
529 so_ref(NULL, &vtxbuf);
530 so_ref(NULL, &vtxfmt);
534 so_reloc(vtxbuf, nvfx_resource(vb->buffer)->bo,
535 vb->buffer_offset + ve->src_offset,
536 vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
537 0, NV34TCL_VTXBUF_ADDRESS_DMA1);
538 so_data (vtxfmt, ((vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT) |
539 (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type));
543 struct nouveau_bo *bo = nvfx_resource(ib)->bo;
545 so_method(vtxbuf, eng3d, NV34TCL_IDXBUF_ADDRESS, 2);
546 so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
547 so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR,
548 0, NV34TCL_IDXBUF_FORMAT_DMA1);
551 so_method(vtxbuf, eng3d, 0x1710, 1);
554 so_ref(vtxbuf, &nvfx->state.hw[NVFX_STATE_VTXBUF]);
555 so_ref(NULL, &vtxbuf);
556 nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXBUF);
557 so_ref(vtxfmt, &nvfx->state.hw[NVFX_STATE_VTXFMT]);
558 so_ref(NULL, &vtxfmt);
559 nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXFMT);
560 so_ref(sattr, &nvfx->state.hw[NVFX_STATE_VTXATTR]);
561 so_ref(NULL, &sattr);
562 nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXATTR);
566 struct nvfx_state_entry nvfx_state_vbo = {
567 .validate = nvfx_vbo_validate,
569 .pipe = NVFX_NEW_ARRAYS,