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_class.h"
12 #include "nouveau/nouveau_pushbuf.h"
13 #include "nouveau/nouveau_util.h"
16 nvfx_vbo_format_to_hw(enum pipe_format pipe
, unsigned *fmt
, unsigned *ncomp
)
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
;
25 case PIPE_FORMAT_R16_FLOAT
:
26 case PIPE_FORMAT_R16G16_FLOAT
:
27 case PIPE_FORMAT_R16G16B16_FLOAT
:
28 case PIPE_FORMAT_R16G16B16A16_FLOAT
:
29 *fmt
= NV34TCL_VTXFMT_TYPE_HALF
;
31 case PIPE_FORMAT_R8_UNORM
:
32 case PIPE_FORMAT_R8G8_UNORM
:
33 case PIPE_FORMAT_R8G8B8_UNORM
:
34 case PIPE_FORMAT_R8G8B8A8_UNORM
:
35 *fmt
= NV34TCL_VTXFMT_TYPE_UBYTE
;
37 case PIPE_FORMAT_R16_SSCALED
:
38 case PIPE_FORMAT_R16G16_SSCALED
:
39 case PIPE_FORMAT_R16G16B16_SSCALED
:
40 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
41 *fmt
= NV34TCL_VTXFMT_TYPE_USHORT
;
44 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe
));
49 case PIPE_FORMAT_R8_UNORM
:
50 case PIPE_FORMAT_R32_FLOAT
:
51 case PIPE_FORMAT_R16_FLOAT
:
52 case PIPE_FORMAT_R16_SSCALED
:
55 case PIPE_FORMAT_R8G8_UNORM
:
56 case PIPE_FORMAT_R32G32_FLOAT
:
57 case PIPE_FORMAT_R16G16_FLOAT
:
58 case PIPE_FORMAT_R16G16_SSCALED
:
61 case PIPE_FORMAT_R8G8B8_UNORM
:
62 case PIPE_FORMAT_R32G32B32_FLOAT
:
63 case PIPE_FORMAT_R16G16B16_FLOAT
:
64 case PIPE_FORMAT_R16G16B16_SSCALED
:
67 case PIPE_FORMAT_R8G8B8A8_UNORM
:
68 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
69 case PIPE_FORMAT_R16G16B16A16_FLOAT
:
70 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
74 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe
));
82 nvfx_vbo_set_idxbuf(struct nvfx_context
*nvfx
, struct pipe_resource
*ib
,
89 nvfx
->idxbuf_format
= 0xdeadbeef;
93 if (!nvfx
->screen
->index_buffer_reloc_flags
|| ib_size
== 1)
98 type
= NV34TCL_IDXBUF_FORMAT_TYPE_U16
;
101 type
= NV34TCL_IDXBUF_FORMAT_TYPE_U32
;
107 if (ib
!= nvfx
->idxbuf
||
108 type
!= nvfx
->idxbuf_format
) {
109 nvfx
->dirty
|= NVFX_NEW_ARRAYS
;
111 nvfx
->idxbuf_format
= type
;
117 // type must be floating point
119 nvfx_vbo_static_attrib(struct nvfx_context
*nvfx
,
120 int attrib
, struct pipe_vertex_element
*ve
,
121 struct pipe_vertex_buffer
*vb
, unsigned ncomp
)
123 struct pipe_transfer
*transfer
;
124 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
128 map
= pipe_buffer_map(&nvfx
->pipe
, vb
->buffer
, PIPE_TRANSFER_READ
, &transfer
);
129 map
= (uint8_t *) map
+ vb
->buffer_offset
+ ve
->src_offset
;
135 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_4F_X(attrib
), 4));
136 OUT_RING(chan
, fui(v
[0]));
137 OUT_RING(chan
, fui(v
[1]));
138 OUT_RING(chan
, fui(v
[2]));
139 OUT_RING(chan
, fui(v
[3]));
142 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_3F_X(attrib
), 3));
143 OUT_RING(chan
, fui(v
[0]));
144 OUT_RING(chan
, fui(v
[1]));
145 OUT_RING(chan
, fui(v
[2]));
148 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_2F_X(attrib
), 2));
149 OUT_RING(chan
, fui(v
[0]));
150 OUT_RING(chan
, fui(v
[1]));
153 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_1F(attrib
), 1));
154 OUT_RING(chan
, fui(v
[0]));
158 pipe_buffer_unmap(&nvfx
->pipe
, vb
->buffer
, transfer
);
162 nvfx_draw_arrays(struct pipe_context
*pipe
,
163 unsigned mode
, unsigned start
, unsigned count
)
165 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
166 struct nvfx_screen
*screen
= nvfx
->screen
;
167 struct nouveau_channel
*chan
= screen
->base
.channel
;
168 unsigned restart
= 0;
170 nvfx_vbo_set_idxbuf(nvfx
, NULL
, 0);
171 if (nvfx
->screen
->force_swtnl
|| !nvfx_state_validate(nvfx
)) {
172 nvfx_draw_elements_swtnl(pipe
, NULL
, 0, 0,
178 unsigned vc
, nr
, avail
;
180 nvfx_state_emit(nvfx
);
182 avail
= AVAIL_RING(chan
);
183 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
185 vc
= nouveau_vbuf_split(avail
, 6, 256,
186 mode
, start
, count
, &restart
);
192 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
193 OUT_RING (chan
, nvgl_primitive(mode
));
197 OUT_RING(chan
, RING_3D(NV34TCL_VB_VERTEX_BATCH
, 1));
198 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
204 unsigned push
= nr
> 2047 ? 2047 : nr
;
208 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_VERTEX_BATCH
, push
));
210 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
215 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
222 pipe
->flush(pipe
, 0, NULL
);
226 nvfx_draw_elements_u08(struct nvfx_context
*nvfx
, void *ib
,
227 unsigned mode
, unsigned start
, unsigned count
)
229 struct nvfx_screen
*screen
= nvfx
->screen
;
230 struct nouveau_channel
*chan
= screen
->base
.channel
;
233 uint8_t *elts
= (uint8_t *)ib
+ start
;
234 unsigned vc
, push
, restart
= 0, avail
;
236 nvfx_state_emit(nvfx
);
238 avail
= AVAIL_RING(chan
);
239 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
241 vc
= nouveau_vbuf_split(avail
, 6, 2,
242 mode
, start
, count
, &restart
);
249 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
250 OUT_RING (chan
, nvgl_primitive(mode
));
253 OUT_RING(chan
, RING_3D(NV34TCL_VB_ELEMENT_U32
, 1));
254 OUT_RING (chan
, elts
[0]);
261 push
= MIN2(vc
, 2047 * 2);
263 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U16
, push
>> 1));
264 for (i
= 0; i
< push
; i
+=2)
265 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
271 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
279 nvfx_draw_elements_u16(struct nvfx_context
*nvfx
, void *ib
,
280 unsigned mode
, unsigned start
, unsigned count
)
282 struct nvfx_screen
*screen
= nvfx
->screen
;
283 struct nouveau_channel
*chan
= screen
->base
.channel
;
286 uint16_t *elts
= (uint16_t *)ib
+ start
;
287 unsigned vc
, push
, restart
= 0, avail
;
289 nvfx_state_emit(nvfx
);
291 avail
= AVAIL_RING(chan
);
292 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
294 vc
= nouveau_vbuf_split(avail
, 6, 2,
295 mode
, start
, count
, &restart
);
302 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
303 OUT_RING (chan
, nvgl_primitive(mode
));
306 OUT_RING(chan
, RING_3D(NV34TCL_VB_ELEMENT_U32
, 1));
307 OUT_RING (chan
, elts
[0]);
314 push
= MIN2(vc
, 2047 * 2);
316 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U16
, push
>> 1));
317 for (i
= 0; i
< push
; i
+=2)
318 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
324 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
332 nvfx_draw_elements_u32(struct nvfx_context
*nvfx
, void *ib
,
333 unsigned mode
, unsigned start
, unsigned count
)
335 struct nvfx_screen
*screen
= nvfx
->screen
;
336 struct nouveau_channel
*chan
= screen
->base
.channel
;
339 uint32_t *elts
= (uint32_t *)ib
+ start
;
340 unsigned vc
, push
, restart
= 0, avail
;
342 nvfx_state_emit(nvfx
);
344 avail
= AVAIL_RING(chan
);
345 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
347 vc
= nouveau_vbuf_split(avail
, 5, 1,
348 mode
, start
, count
, &restart
);
355 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
356 OUT_RING (chan
, nvgl_primitive(mode
));
359 push
= MIN2(vc
, 2047);
361 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U32
, push
));
362 OUT_RINGp (chan
, elts
, push
);
368 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
376 nvfx_draw_elements_inline(struct pipe_context
*pipe
,
377 struct pipe_resource
*ib
,
378 unsigned ib_size
, int ib_bias
,
379 unsigned mode
, unsigned start
, unsigned count
)
381 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
382 struct pipe_transfer
*transfer
;
385 map
= pipe_buffer_map(pipe
, ib
, PIPE_TRANSFER_READ
, &transfer
);
387 NOUVEAU_ERR("failed mapping ib\n");
391 assert(ib_bias
== 0);
395 nvfx_draw_elements_u08(nvfx
, map
, mode
, start
, count
);
398 nvfx_draw_elements_u16(nvfx
, map
, mode
, start
, count
);
401 nvfx_draw_elements_u32(nvfx
, map
, mode
, start
, count
);
404 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
408 pipe_buffer_unmap(pipe
, ib
, transfer
);
412 nvfx_draw_elements_vbo(struct pipe_context
*pipe
,
413 unsigned mode
, unsigned start
, unsigned count
)
415 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
416 struct nvfx_screen
*screen
= nvfx
->screen
;
417 struct nouveau_channel
*chan
= screen
->base
.channel
;
418 unsigned restart
= 0;
421 unsigned nr
, vc
, avail
;
423 nvfx_state_emit(nvfx
);
425 avail
= AVAIL_RING(chan
);
426 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
428 vc
= nouveau_vbuf_split(avail
, 6, 256,
429 mode
, start
, count
, &restart
);
435 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
436 OUT_RING (chan
, nvgl_primitive(mode
));
440 OUT_RING(chan
, RING_3D(NV34TCL_VB_INDEX_BATCH
, 1));
441 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
447 unsigned push
= nr
> 2047 ? 2047 : nr
;
451 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_INDEX_BATCH
, push
));
453 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
458 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
467 nvfx_draw_elements(struct pipe_context
*pipe
,
468 struct pipe_resource
*indexBuffer
,
469 unsigned indexSize
, int indexBias
,
470 unsigned mode
, unsigned start
, unsigned count
)
472 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
475 idxbuf
= nvfx_vbo_set_idxbuf(nvfx
, indexBuffer
, indexSize
);
476 if (nvfx
->screen
->force_swtnl
|| !nvfx_state_validate(nvfx
)) {
477 nvfx_draw_elements_swtnl(pipe
,
478 indexBuffer
, indexSize
, indexBias
,
484 nvfx_draw_elements_vbo(pipe
, mode
, start
, count
);
486 nvfx_draw_elements_inline(pipe
,
487 indexBuffer
, indexSize
, indexBias
,
491 pipe
->flush(pipe
, 0, NULL
);
495 nvfx_vbo_validate(struct nvfx_context
*nvfx
)
497 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
498 struct pipe_resource
*ib
= nvfx
->idxbuf
;
499 unsigned ib_format
= nvfx
->idxbuf_format
;
501 int elements
= MAX2(nvfx
->vtxelt
->num_elements
, nvfx
->hw_vtxelt_nr
);
503 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_reloc_flags
| NOUVEAU_BO_RD
;
510 MARK_RING(chan
, (5 + 2) * 16 + 2 + 11, 16 + 2);
511 for (i
= 0; i
< nvfx
->vtxelt
->num_elements
; i
++) {
512 struct pipe_vertex_element
*ve
;
513 struct pipe_vertex_buffer
*vb
;
514 unsigned type
, ncomp
;
516 ve
= &nvfx
->vtxelt
->pipe
[i
];
517 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
519 if (nvfx_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
)) {
521 nvfx
->fallback_swtnl
|= NVFX_NEW_ARRAYS
;
525 if (!vb
->stride
&& type
== NV34TCL_VTXFMT_TYPE_FLOAT
) {
526 nvfx_vbo_static_attrib(nvfx
, i
, ve
, vb
, ncomp
);
529 vtxfmt
[i
] = ((vb
->stride
<< NV34TCL_VTXFMT_STRIDE_SHIFT
) |
530 (ncomp
<< NV34TCL_VTXFMT_SIZE_SHIFT
) | type
);
531 nvfx
->vbo_bo
|= (1 << i
);
535 for(; i
< elements
; ++i
)
536 vtxfmt
[i
] = NV34TCL_VTXFMT_TYPE_FLOAT
;
538 OUT_RING(chan
, RING_3D(NV34TCL_VTXFMT(0), elements
));
539 OUT_RINGp(chan
, vtxfmt
, elements
);
543 /* seems to be some kind of cache flushing */
544 for(i
= 0; i
< 3; ++i
) {
545 OUT_RING(chan
, RING_3D(0x1718, 1));
550 OUT_RING(chan
, RING_3D(NV34TCL_VTXBUF_ADDRESS(0), elements
));
551 for (i
= 0; i
< nvfx
->vtxelt
->num_elements
; i
++) {
552 struct pipe_vertex_element
*ve
;
553 struct pipe_vertex_buffer
*vb
;
555 ve
= &nvfx
->vtxelt
->pipe
[i
];
556 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
558 if (!(nvfx
->vbo_bo
& (1 << i
)))
562 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
564 vb
->buffer_offset
+ ve
->src_offset
,
565 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
566 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
570 for (; i
< elements
; i
++)
573 OUT_RING(chan
, RING_3D(0x1710, 1));
577 unsigned ib_flags
= nvfx
->screen
->index_buffer_reloc_flags
| NOUVEAU_BO_RD
;
578 struct nouveau_bo
* bo
= nvfx_resource(ib
)->bo
;
580 assert(nvfx
->screen
->index_buffer_reloc_flags
);
582 OUT_RING(chan
, RING_3D(NV34TCL_IDXBUF_ADDRESS
, 2));
583 OUT_RELOC(chan
, bo
, 0, ib_flags
| NOUVEAU_BO_LOW
, 0, 0);
584 OUT_RELOC(chan
, bo
, ib_format
, ib_flags
| NOUVEAU_BO_OR
,
585 0, NV34TCL_IDXBUF_FORMAT_DMA1
);
588 nvfx
->hw_vtxelt_nr
= nvfx
->vtxelt
->num_elements
;
593 nvfx_vbo_relocate(struct nvfx_context
*nvfx
)
595 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
596 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_reloc_flags
| NOUVEAU_BO_RD
| NOUVEAU_BO_DUMMY
;
599 MARK_RING(chan
, 2 * 16 + 3, 2 * 16 + 3);
600 for(i
= 0; i
< nvfx
->vtxelt
->num_elements
; ++i
) {
601 if(nvfx
->vbo_bo
& (1 << i
)) {
602 struct pipe_vertex_element
*ve
= &nvfx
->vtxelt
->pipe
[i
];
603 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
604 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
605 OUT_RELOC(chan
, bo
, RING_3D(NV34TCL_VTXBUF_ADDRESS(i
), 1),
607 OUT_RELOC(chan
, bo
, vb
->buffer_offset
+ ve
->src_offset
,
608 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
609 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
615 unsigned ib_flags
= nvfx
->screen
->index_buffer_reloc_flags
| NOUVEAU_BO_RD
| NOUVEAU_BO_DUMMY
;
616 struct nouveau_bo
* bo
= nvfx_resource(nvfx
->idxbuf
)->bo
;
618 assert(nvfx
->screen
->index_buffer_reloc_flags
);
620 OUT_RELOC(chan
, bo
, RING_3D(NV34TCL_IDXBUF_ADDRESS
, 2),
622 OUT_RELOC(chan
, bo
, 0,
623 ib_flags
| NOUVEAU_BO_LOW
, 0, 0);
624 OUT_RELOC(chan
, bo
, nvfx
->idxbuf_format
,
625 ib_flags
| NOUVEAU_BO_OR
,
626 0, NV34TCL_IDXBUF_FORMAT_DMA1
);