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 "nv40_context.h"
7 #include "nvfx_state.h"
9 #include "nouveau/nouveau_channel.h"
10 #include "nouveau/nouveau_pushbuf.h"
11 #include "nouveau/nouveau_util.h"
16 nv40_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_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
;
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
;
38 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe
));
43 case PIPE_FORMAT_R8_UNORM
:
44 case PIPE_FORMAT_R32_FLOAT
:
45 case PIPE_FORMAT_R16_SSCALED
:
48 case PIPE_FORMAT_R8G8_UNORM
:
49 case PIPE_FORMAT_R32G32_FLOAT
:
50 case PIPE_FORMAT_R16G16_SSCALED
:
53 case PIPE_FORMAT_R8G8B8_UNORM
:
54 case PIPE_FORMAT_R32G32B32_FLOAT
:
55 case PIPE_FORMAT_R16G16B16_SSCALED
:
58 case PIPE_FORMAT_R8G8B8A8_UNORM
:
59 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
60 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
64 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe
));
72 nv40_vbo_set_idxbuf(struct nvfx_context
*nvfx
, struct pipe_buffer
*ib
,
75 struct pipe_screen
*pscreen
= &nvfx
->screen
->base
.base
;
80 nvfx
->idxbuf_format
= 0xdeadbeef;
84 if (!pscreen
->get_param(pscreen
, NOUVEAU_CAP_HW_IDXBUF
) || ib_size
== 1)
89 type
= NV34TCL_IDXBUF_FORMAT_TYPE_U16
;
92 type
= NV34TCL_IDXBUF_FORMAT_TYPE_U32
;
98 if (ib
!= nvfx
->idxbuf
||
99 type
!= nvfx
->idxbuf_format
) {
100 nvfx
->dirty
|= NVFX_NEW_ARRAYS
;
102 nvfx
->idxbuf_format
= type
;
109 nv40_vbo_static_attrib(struct nvfx_context
*nvfx
, struct nouveau_stateobj
*so
,
110 int attrib
, struct pipe_vertex_element
*ve
,
111 struct pipe_vertex_buffer
*vb
)
113 struct pipe_screen
*pscreen
= nvfx
->pipe
.screen
;
114 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
115 unsigned type
, ncomp
;
118 if (nv40_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
))
121 map
= pipe_buffer_map(pscreen
, vb
->buffer
, PIPE_BUFFER_USAGE_CPU_READ
);
122 map
+= vb
->buffer_offset
+ ve
->src_offset
;
125 case NV34TCL_VTXFMT_TYPE_FLOAT
:
131 so_method(so
, eng3d
, 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]));
138 so_method(so
, eng3d
, 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]));
144 so_method(so
, eng3d
, NV34TCL_VTX_ATTR_2F_X(attrib
), 2);
145 so_data (so
, fui(v
[0]));
146 so_data (so
, fui(v
[1]));
149 so_method(so
, eng3d
, NV34TCL_VTX_ATTR_1F(attrib
), 1);
150 so_data (so
, fui(v
[0]));
153 pipe_buffer_unmap(pscreen
, vb
->buffer
);
159 pipe_buffer_unmap(pscreen
, vb
->buffer
);
163 pipe_buffer_unmap(pscreen
, vb
->buffer
);
169 nv40_draw_arrays(struct pipe_context
*pipe
,
170 unsigned mode
, unsigned start
, unsigned count
)
172 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
173 struct nvfx_screen
*screen
= nvfx
->screen
;
174 struct nouveau_channel
*chan
= screen
->base
.channel
;
175 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
178 nv40_vbo_set_idxbuf(nvfx
, NULL
, 0);
179 if (FORCE_SWTNL
|| !nvfx_state_validate(nvfx
)) {
180 nvfx_draw_elements_swtnl(pipe
, NULL
, 0,
188 nvfx_state_emit(nvfx
);
190 vc
= nouveau_vbuf_split(AVAIL_RING(chan
), 6, 256,
191 mode
, start
, count
, &restart
);
197 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
198 OUT_RING (chan
, nvgl_primitive(mode
));
202 BEGIN_RING(chan
, eng3d
, NV34TCL_VB_VERTEX_BATCH
, 1);
203 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
209 unsigned push
= nr
> 2047 ? 2047 : nr
;
213 BEGIN_RING_NI(chan
, eng3d
, NV34TCL_VB_VERTEX_BATCH
, push
);
215 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
220 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
227 pipe
->flush(pipe
, 0, NULL
);
231 nv40_draw_elements_u08(struct nvfx_context
*nvfx
, void *ib
,
232 unsigned mode
, unsigned start
, unsigned count
)
234 struct nvfx_screen
*screen
= nvfx
->screen
;
235 struct nouveau_channel
*chan
= screen
->base
.channel
;
236 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
239 uint8_t *elts
= (uint8_t *)ib
+ start
;
240 unsigned vc
, push
, restart
;
242 nvfx_state_emit(nvfx
);
244 vc
= nouveau_vbuf_split(AVAIL_RING(chan
), 6, 2,
245 mode
, start
, count
, &restart
);
252 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
253 OUT_RING (chan
, nvgl_primitive(mode
));
256 BEGIN_RING(chan
, eng3d
, NV34TCL_VB_ELEMENT_U32
, 1);
257 OUT_RING (chan
, elts
[0]);
264 push
= MIN2(vc
, 2047 * 2);
266 BEGIN_RING_NI(chan
, eng3d
, NV34TCL_VB_ELEMENT_U16
, push
>> 1);
267 for (i
= 0; i
< push
; i
+=2)
268 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
274 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
282 nv40_draw_elements_u16(struct nvfx_context
*nvfx
, void *ib
,
283 unsigned mode
, unsigned start
, unsigned count
)
285 struct nvfx_screen
*screen
= nvfx
->screen
;
286 struct nouveau_channel
*chan
= screen
->base
.channel
;
287 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
290 uint16_t *elts
= (uint16_t *)ib
+ start
;
291 unsigned vc
, push
, restart
;
293 nvfx_state_emit(nvfx
);
295 vc
= nouveau_vbuf_split(AVAIL_RING(chan
), 6, 2,
296 mode
, start
, count
, &restart
);
303 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
304 OUT_RING (chan
, nvgl_primitive(mode
));
307 BEGIN_RING(chan
, eng3d
, NV34TCL_VB_ELEMENT_U32
, 1);
308 OUT_RING (chan
, elts
[0]);
315 push
= MIN2(vc
, 2047 * 2);
317 BEGIN_RING_NI(chan
, eng3d
, NV34TCL_VB_ELEMENT_U16
, push
>> 1);
318 for (i
= 0; i
< push
; i
+=2)
319 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
325 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
333 nv40_draw_elements_u32(struct nvfx_context
*nvfx
, void *ib
,
334 unsigned mode
, unsigned start
, unsigned count
)
336 struct nvfx_screen
*screen
= nvfx
->screen
;
337 struct nouveau_channel
*chan
= screen
->base
.channel
;
338 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
341 uint32_t *elts
= (uint32_t *)ib
+ start
;
342 unsigned vc
, push
, restart
;
344 nvfx_state_emit(nvfx
);
346 vc
= nouveau_vbuf_split(AVAIL_RING(chan
), 5, 1,
347 mode
, start
, count
, &restart
);
354 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
355 OUT_RING (chan
, nvgl_primitive(mode
));
358 push
= MIN2(vc
, 2047);
360 BEGIN_RING_NI(chan
, eng3d
, NV34TCL_VB_ELEMENT_U32
, push
);
361 OUT_RINGp (chan
, elts
, push
);
367 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
375 nv40_draw_elements_inline(struct pipe_context
*pipe
,
376 struct pipe_buffer
*ib
, unsigned ib_size
,
377 unsigned mode
, unsigned start
, unsigned count
)
379 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
380 struct pipe_screen
*pscreen
= pipe
->screen
;
383 map
= pipe_buffer_map(pscreen
, ib
, PIPE_BUFFER_USAGE_CPU_READ
);
385 NOUVEAU_ERR("failed mapping ib\n");
391 nv40_draw_elements_u08(nvfx
, map
, mode
, start
, count
);
394 nv40_draw_elements_u16(nvfx
, map
, mode
, start
, count
);
397 nv40_draw_elements_u32(nvfx
, map
, mode
, start
, count
);
400 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
404 pipe_buffer_unmap(pscreen
, ib
);
408 nv40_draw_elements_vbo(struct pipe_context
*pipe
,
409 unsigned mode
, unsigned start
, unsigned count
)
411 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
412 struct nvfx_screen
*screen
= nvfx
->screen
;
413 struct nouveau_channel
*chan
= screen
->base
.channel
;
414 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
420 nvfx_state_emit(nvfx
);
422 vc
= nouveau_vbuf_split(AVAIL_RING(chan
), 6, 256,
423 mode
, start
, count
, &restart
);
429 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
430 OUT_RING (chan
, nvgl_primitive(mode
));
434 BEGIN_RING(chan
, eng3d
, NV34TCL_VB_INDEX_BATCH
, 1);
435 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
441 unsigned push
= nr
> 2047 ? 2047 : nr
;
445 BEGIN_RING_NI(chan
, eng3d
, NV34TCL_VB_INDEX_BATCH
, push
);
447 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
452 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
461 nv40_draw_elements(struct pipe_context
*pipe
,
462 struct pipe_buffer
*indexBuffer
, unsigned indexSize
,
463 unsigned mode
, unsigned start
, unsigned count
)
465 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
468 idxbuf
= nv40_vbo_set_idxbuf(nvfx
, indexBuffer
, indexSize
);
469 if (FORCE_SWTNL
|| !nvfx_state_validate(nvfx
)) {
470 nvfx_draw_elements_swtnl(pipe
, NULL
, 0,
476 nv40_draw_elements_vbo(pipe
, mode
, start
, count
);
478 nv40_draw_elements_inline(pipe
, indexBuffer
, indexSize
,
482 pipe
->flush(pipe
, 0, NULL
);
486 nv40_vbo_validate(struct nvfx_context
*nvfx
)
488 struct nouveau_stateobj
*vtxbuf
, *vtxfmt
, *sattr
= NULL
;
489 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
490 struct pipe_buffer
*ib
= nvfx
->idxbuf
;
491 unsigned ib_format
= nvfx
->idxbuf_format
;
492 unsigned vb_flags
= NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
;
495 vtxbuf
= so_new(3, 17, 18);
496 so_method(vtxbuf
, eng3d
, NV34TCL_VTXBUF_ADDRESS(0), nvfx
->vtxelt
->num_elements
);
497 vtxfmt
= so_new(1, 16, 0);
498 so_method(vtxfmt
, eng3d
, NV34TCL_VTXFMT(0), nvfx
->vtxelt
->num_elements
);
500 for (hw
= 0; hw
< nvfx
->vtxelt
->num_elements
; hw
++) {
501 struct pipe_vertex_element
*ve
;
502 struct pipe_vertex_buffer
*vb
;
503 unsigned type
, ncomp
;
505 ve
= &nvfx
->vtxelt
->pipe
[hw
];
506 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
510 sattr
= so_new(16, 16 * 4, 0);
512 if (nv40_vbo_static_attrib(nvfx
, sattr
, hw
, ve
, vb
)) {
514 so_data(vtxfmt
, NV34TCL_VTXFMT_TYPE_FLOAT
);
519 if (nv40_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
)) {
520 nvfx
->fallback_swtnl
|= NVFX_NEW_ARRAYS
;
521 so_ref(NULL
, &vtxbuf
);
522 so_ref(NULL
, &vtxfmt
);
526 so_reloc(vtxbuf
, nouveau_bo(vb
->buffer
),
527 vb
->buffer_offset
+ ve
->src_offset
,
528 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
529 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
530 so_data (vtxfmt
, ((vb
->stride
<< NV34TCL_VTXFMT_STRIDE_SHIFT
) |
531 (ncomp
<< NV34TCL_VTXFMT_SIZE_SHIFT
) | type
));
535 struct nouveau_bo
*bo
= nouveau_bo(ib
);
537 so_method(vtxbuf
, eng3d
, NV34TCL_IDXBUF_ADDRESS
, 2);
538 so_reloc (vtxbuf
, bo
, 0, vb_flags
| NOUVEAU_BO_LOW
, 0, 0);
539 so_reloc (vtxbuf
, bo
, ib_format
, vb_flags
| NOUVEAU_BO_OR
,
540 0, NV34TCL_IDXBUF_FORMAT_DMA1
);
543 so_method(vtxbuf
, eng3d
, 0x1710, 1);
546 so_ref(vtxbuf
, &nvfx
->state
.hw
[NVFX_STATE_VTXBUF
]);
547 so_ref(NULL
, &vtxbuf
);
548 nvfx
->state
.dirty
|= (1ULL << NVFX_STATE_VTXBUF
);
549 so_ref(vtxfmt
, &nvfx
->state
.hw
[NVFX_STATE_VTXFMT
]);
550 so_ref(NULL
, &vtxfmt
);
551 nvfx
->state
.dirty
|= (1ULL << NVFX_STATE_VTXFMT
);
552 so_ref(sattr
, &nvfx
->state
.hw
[NVFX_STATE_VTXATTR
]);
553 so_ref(NULL
, &sattr
);
554 nvfx
->state
.dirty
|= (1ULL << NVFX_STATE_VTXATTR
);
558 struct nvfx_state_entry nv40_state_vbo
= {
559 .validate
= nv40_vbo_validate
,
561 .pipe
= NVFX_NEW_ARRAYS
,