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_vbo_format_to_hw(enum pipe_format pipe
, unsigned *fmt
, unsigned *ncomp
)
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
;
24 case PIPE_FORMAT_R16_FLOAT
:
25 case PIPE_FORMAT_R16G16_FLOAT
:
26 case PIPE_FORMAT_R16G16B16_FLOAT
:
27 case PIPE_FORMAT_R16G16B16A16_FLOAT
:
28 *fmt
= NV34TCL_VTXFMT_TYPE_HALF
;
30 case PIPE_FORMAT_R8_UNORM
:
31 case PIPE_FORMAT_R8G8_UNORM
:
32 case PIPE_FORMAT_R8G8B8_UNORM
:
33 case PIPE_FORMAT_R8G8B8A8_UNORM
:
34 *fmt
= NV34TCL_VTXFMT_TYPE_UBYTE
;
36 case PIPE_FORMAT_R16_SSCALED
:
37 case PIPE_FORMAT_R16G16_SSCALED
:
38 case PIPE_FORMAT_R16G16B16_SSCALED
:
39 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
40 *fmt
= NV34TCL_VTXFMT_TYPE_USHORT
;
43 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe
));
48 case PIPE_FORMAT_R8_UNORM
:
49 case PIPE_FORMAT_R32_FLOAT
:
50 case PIPE_FORMAT_R16_FLOAT
:
51 case PIPE_FORMAT_R16_SSCALED
:
54 case PIPE_FORMAT_R8G8_UNORM
:
55 case PIPE_FORMAT_R32G32_FLOAT
:
56 case PIPE_FORMAT_R16G16_FLOAT
:
57 case PIPE_FORMAT_R16G16_SSCALED
:
60 case PIPE_FORMAT_R8G8B8_UNORM
:
61 case PIPE_FORMAT_R32G32B32_FLOAT
:
62 case PIPE_FORMAT_R16G16B16_FLOAT
:
63 case PIPE_FORMAT_R16G16B16_SSCALED
:
66 case PIPE_FORMAT_R8G8B8A8_UNORM
:
67 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
68 case PIPE_FORMAT_R16G16B16A16_FLOAT
:
69 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
73 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe
));
81 nvfx_vbo_set_idxbuf(struct nvfx_context
*nvfx
, struct pipe_resource
*ib
,
88 nvfx
->idxbuf_format
= 0xdeadbeef;
92 if (!nvfx
->screen
->index_buffer_reloc_flags
|| 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
;
116 // type must be floating point
118 nvfx_vbo_static_attrib(struct nvfx_context
*nvfx
,
119 int attrib
, struct pipe_vertex_element
*ve
,
120 struct pipe_vertex_buffer
*vb
, unsigned ncomp
)
122 struct pipe_transfer
*transfer
;
123 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
127 map
= pipe_buffer_map(&nvfx
->pipe
, vb
->buffer
, PIPE_TRANSFER_READ
, &transfer
);
128 map
= (uint8_t *) map
+ vb
->buffer_offset
+ ve
->src_offset
;
134 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_4F_X(attrib
), 4));
135 OUT_RING(chan
, fui(v
[0]));
136 OUT_RING(chan
, fui(v
[1]));
137 OUT_RING(chan
, fui(v
[2]));
138 OUT_RING(chan
, fui(v
[3]));
141 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_3F_X(attrib
), 3));
142 OUT_RING(chan
, fui(v
[0]));
143 OUT_RING(chan
, fui(v
[1]));
144 OUT_RING(chan
, fui(v
[2]));
147 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_2F_X(attrib
), 2));
148 OUT_RING(chan
, fui(v
[0]));
149 OUT_RING(chan
, fui(v
[1]));
152 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_1F(attrib
), 1));
153 OUT_RING(chan
, fui(v
[0]));
157 pipe_buffer_unmap(&nvfx
->pipe
, vb
->buffer
, transfer
);
161 nvfx_draw_arrays(struct pipe_context
*pipe
,
162 unsigned mode
, unsigned start
, unsigned count
)
164 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
165 struct nvfx_screen
*screen
= nvfx
->screen
;
166 struct nouveau_channel
*chan
= screen
->base
.channel
;
167 unsigned restart
= 0;
169 nvfx_vbo_set_idxbuf(nvfx
, NULL
, 0);
170 if (nvfx
->screen
->force_swtnl
|| !nvfx_state_validate(nvfx
)) {
171 nvfx_draw_elements_swtnl(pipe
, NULL
, 0, 0,
177 unsigned vc
, nr
, avail
;
179 nvfx_state_emit(nvfx
);
181 avail
= AVAIL_RING(chan
);
182 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
184 vc
= nouveau_vbuf_split(avail
, 6, 256,
185 mode
, start
, count
, &restart
);
191 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
192 OUT_RING (chan
, nvgl_primitive(mode
));
196 OUT_RING(chan
, RING_3D(NV34TCL_VB_VERTEX_BATCH
, 1));
197 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
203 unsigned push
= nr
> 2047 ? 2047 : nr
;
207 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_VERTEX_BATCH
, push
));
209 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
214 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
221 pipe
->flush(pipe
, 0, NULL
);
225 nvfx_draw_elements_u08(struct nvfx_context
*nvfx
, void *ib
,
226 unsigned mode
, unsigned start
, unsigned count
)
228 struct nvfx_screen
*screen
= nvfx
->screen
;
229 struct nouveau_channel
*chan
= screen
->base
.channel
;
232 uint8_t *elts
= (uint8_t *)ib
+ start
;
233 unsigned vc
, push
, restart
= 0, avail
;
235 nvfx_state_emit(nvfx
);
237 avail
= AVAIL_RING(chan
);
238 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
240 vc
= nouveau_vbuf_split(avail
, 6, 2,
241 mode
, start
, count
, &restart
);
248 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
249 OUT_RING (chan
, nvgl_primitive(mode
));
252 OUT_RING(chan
, RING_3D(NV34TCL_VB_ELEMENT_U32
, 1));
253 OUT_RING (chan
, elts
[0]);
260 push
= MIN2(vc
, 2047 * 2);
262 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U16
, push
>> 1));
263 for (i
= 0; i
< push
; i
+=2)
264 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
270 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
278 nvfx_draw_elements_u16(struct nvfx_context
*nvfx
, void *ib
,
279 unsigned mode
, unsigned start
, unsigned count
)
281 struct nvfx_screen
*screen
= nvfx
->screen
;
282 struct nouveau_channel
*chan
= screen
->base
.channel
;
285 uint16_t *elts
= (uint16_t *)ib
+ start
;
286 unsigned vc
, push
, restart
= 0, avail
;
288 nvfx_state_emit(nvfx
);
290 avail
= AVAIL_RING(chan
);
291 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
293 vc
= nouveau_vbuf_split(avail
, 6, 2,
294 mode
, start
, count
, &restart
);
301 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
302 OUT_RING (chan
, nvgl_primitive(mode
));
305 OUT_RING(chan
, RING_3D(NV34TCL_VB_ELEMENT_U32
, 1));
306 OUT_RING (chan
, elts
[0]);
313 push
= MIN2(vc
, 2047 * 2);
315 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U16
, push
>> 1));
316 for (i
= 0; i
< push
; i
+=2)
317 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
323 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
331 nvfx_draw_elements_u32(struct nvfx_context
*nvfx
, void *ib
,
332 unsigned mode
, unsigned start
, unsigned count
)
334 struct nvfx_screen
*screen
= nvfx
->screen
;
335 struct nouveau_channel
*chan
= screen
->base
.channel
;
338 uint32_t *elts
= (uint32_t *)ib
+ start
;
339 unsigned vc
, push
, restart
= 0, avail
;
341 nvfx_state_emit(nvfx
);
343 avail
= AVAIL_RING(chan
);
344 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
346 vc
= nouveau_vbuf_split(avail
, 5, 1,
347 mode
, start
, count
, &restart
);
354 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
355 OUT_RING (chan
, nvgl_primitive(mode
));
358 push
= MIN2(vc
, 2047);
360 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U32
, push
));
361 OUT_RINGp (chan
, elts
, push
);
367 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
375 nvfx_draw_elements_inline(struct pipe_context
*pipe
,
376 struct pipe_resource
*ib
,
377 unsigned ib_size
, int ib_bias
,
378 unsigned mode
, unsigned start
, unsigned count
)
380 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
381 struct pipe_transfer
*transfer
;
384 map
= pipe_buffer_map(pipe
, ib
, PIPE_TRANSFER_READ
, &transfer
);
386 NOUVEAU_ERR("failed mapping ib\n");
390 assert(ib_bias
== 0);
394 nvfx_draw_elements_u08(nvfx
, map
, mode
, start
, count
);
397 nvfx_draw_elements_u16(nvfx
, map
, mode
, start
, count
);
400 nvfx_draw_elements_u32(nvfx
, map
, mode
, start
, count
);
403 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
407 pipe_buffer_unmap(pipe
, ib
, transfer
);
411 nvfx_draw_elements_vbo(struct pipe_context
*pipe
,
412 unsigned mode
, unsigned start
, unsigned count
)
414 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
415 struct nvfx_screen
*screen
= nvfx
->screen
;
416 struct nouveau_channel
*chan
= screen
->base
.channel
;
417 unsigned restart
= 0;
420 unsigned nr
, vc
, avail
;
422 nvfx_state_emit(nvfx
);
424 avail
= AVAIL_RING(chan
);
425 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
427 vc
= nouveau_vbuf_split(avail
, 6, 256,
428 mode
, start
, count
, &restart
);
434 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
435 OUT_RING (chan
, nvgl_primitive(mode
));
439 OUT_RING(chan
, RING_3D(NV34TCL_VB_INDEX_BATCH
, 1));
440 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
446 unsigned push
= nr
> 2047 ? 2047 : nr
;
450 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_INDEX_BATCH
, push
));
452 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
457 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
466 nvfx_draw_elements(struct pipe_context
*pipe
,
467 struct pipe_resource
*indexBuffer
,
468 unsigned indexSize
, int indexBias
,
469 unsigned mode
, unsigned start
, unsigned count
)
471 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
474 idxbuf
= nvfx_vbo_set_idxbuf(nvfx
, indexBuffer
, indexSize
);
475 if (nvfx
->screen
->force_swtnl
|| !nvfx_state_validate(nvfx
)) {
476 nvfx_draw_elements_swtnl(pipe
,
477 indexBuffer
, indexSize
, indexBias
,
483 nvfx_draw_elements_vbo(pipe
, mode
, start
, count
);
485 nvfx_draw_elements_inline(pipe
,
486 indexBuffer
, indexSize
, indexBias
,
490 pipe
->flush(pipe
, 0, NULL
);
494 nvfx_vbo_validate(struct nvfx_context
*nvfx
)
496 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
497 struct pipe_resource
*ib
= nvfx
->idxbuf
;
498 unsigned ib_format
= nvfx
->idxbuf_format
;
500 int elements
= MAX2(nvfx
->vtxelt
->num_elements
, nvfx
->hw_vtxelt_nr
);
502 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_reloc_flags
| NOUVEAU_BO_RD
;
509 MARK_RING(chan
, (5 + 2) * 16 + 2 + 11, 16 + 2);
510 for (i
= 0; i
< nvfx
->vtxelt
->num_elements
; i
++) {
511 struct pipe_vertex_element
*ve
;
512 struct pipe_vertex_buffer
*vb
;
513 unsigned type
, ncomp
;
515 ve
= &nvfx
->vtxelt
->pipe
[i
];
516 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
518 if (nvfx_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
)) {
520 nvfx
->fallback_swtnl
|= NVFX_NEW_ARRAYS
;
524 if (!vb
->stride
&& type
== NV34TCL_VTXFMT_TYPE_FLOAT
) {
525 nvfx_vbo_static_attrib(nvfx
, i
, ve
, vb
, ncomp
);
528 vtxfmt
[i
] = ((vb
->stride
<< NV34TCL_VTXFMT_STRIDE_SHIFT
) |
529 (ncomp
<< NV34TCL_VTXFMT_SIZE_SHIFT
) | type
);
530 nvfx
->vbo_bo
|= (1 << i
);
534 for(; i
< elements
; ++i
)
535 vtxfmt
[i
] = NV34TCL_VTXFMT_TYPE_FLOAT
;
537 OUT_RING(chan
, RING_3D(NV34TCL_VTXFMT(0), elements
));
538 OUT_RINGp(chan
, vtxfmt
, elements
);
542 /* seems to be some kind of cache flushing */
543 for(i
= 0; i
< 3; ++i
) {
544 OUT_RING(chan
, RING_3D(0x1718, 1));
549 OUT_RING(chan
, RING_3D(NV34TCL_VTXBUF_ADDRESS(0), elements
));
550 for (i
= 0; i
< nvfx
->vtxelt
->num_elements
; i
++) {
551 struct pipe_vertex_element
*ve
;
552 struct pipe_vertex_buffer
*vb
;
554 ve
= &nvfx
->vtxelt
->pipe
[i
];
555 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
557 if (!(nvfx
->vbo_bo
& (1 << i
)))
561 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
563 vb
->buffer_offset
+ ve
->src_offset
,
564 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
565 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
569 for (; i
< elements
; i
++)
572 OUT_RING(chan
, RING_3D(0x1710, 1));
576 unsigned ib_flags
= nvfx
->screen
->index_buffer_reloc_flags
| NOUVEAU_BO_RD
;
577 struct nouveau_bo
* bo
= nvfx_resource(ib
)->bo
;
579 assert(nvfx
->screen
->index_buffer_reloc_flags
);
581 OUT_RING(chan
, RING_3D(NV34TCL_IDXBUF_ADDRESS
, 2));
582 OUT_RELOC(chan
, bo
, 0, ib_flags
| NOUVEAU_BO_LOW
, 0, 0);
583 OUT_RELOC(chan
, bo
, ib_format
, ib_flags
| NOUVEAU_BO_OR
,
584 0, NV34TCL_IDXBUF_FORMAT_DMA1
);
587 nvfx
->hw_vtxelt_nr
= nvfx
->vtxelt
->num_elements
;
592 nvfx_vbo_relocate(struct nvfx_context
*nvfx
)
594 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
595 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_reloc_flags
| NOUVEAU_BO_RD
| NOUVEAU_BO_DUMMY
;
598 MARK_RING(chan
, 2 * 16 + 3, 2 * 16 + 3);
599 for(i
= 0; i
< nvfx
->vtxelt
->num_elements
; ++i
) {
600 if(nvfx
->vbo_bo
& (1 << i
)) {
601 struct pipe_vertex_element
*ve
= &nvfx
->vtxelt
->pipe
[i
];
602 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
603 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
604 OUT_RELOC(chan
, bo
, RING_3D(NV34TCL_VTXBUF_ADDRESS(i
), 1),
606 OUT_RELOC(chan
, bo
, vb
->buffer_offset
+ ve
->src_offset
,
607 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
608 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
614 unsigned ib_flags
= nvfx
->screen
->index_buffer_reloc_flags
| NOUVEAU_BO_RD
| NOUVEAU_BO_DUMMY
;
615 struct nouveau_bo
* bo
= nvfx_resource(nvfx
->idxbuf
)->bo
;
617 assert(nvfx
->screen
->index_buffer_reloc_flags
);
619 OUT_RELOC(chan
, bo
, RING_3D(NV34TCL_IDXBUF_ADDRESS
, 2),
621 OUT_RELOC(chan
, bo
, 0,
622 ib_flags
| NOUVEAU_BO_LOW
, 0, 0);
623 OUT_RELOC(chan
, bo
, nvfx
->idxbuf_format
,
624 ib_flags
| NOUVEAU_BO_OR
,
625 0, NV34TCL_IDXBUF_FORMAT_DMA1
);