1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "pipe/p_util.h"
5 #include "nv40_context.h"
6 #include "nv40_state.h"
8 #include "nouveau/nouveau_channel.h"
9 #include "nouveau/nouveau_pushbuf.h"
10 #include "nouveau/nouveau_util.h"
15 nv40_vbo_format_to_hw(enum pipe_format pipe
, unsigned *fmt
, unsigned *ncomp
)
20 case PIPE_FORMAT_R32_FLOAT
:
21 case PIPE_FORMAT_R32G32_FLOAT
:
22 case PIPE_FORMAT_R32G32B32_FLOAT
:
23 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
24 *fmt
= NV40TCL_VTXFMT_TYPE_FLOAT
;
26 case PIPE_FORMAT_R8_UNORM
:
27 case PIPE_FORMAT_R8G8_UNORM
:
28 case PIPE_FORMAT_R8G8B8_UNORM
:
29 case PIPE_FORMAT_R8G8B8A8_UNORM
:
30 *fmt
= NV40TCL_VTXFMT_TYPE_UBYTE
;
32 case PIPE_FORMAT_R16_SSCALED
:
33 case PIPE_FORMAT_R16G16_SSCALED
:
34 case PIPE_FORMAT_R16G16B16_SSCALED
:
35 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
36 *fmt
= NV40TCL_VTXFMT_TYPE_USHORT
;
39 pf_sprint_name(fs
, pipe
);
40 NOUVEAU_ERR("Unknown format %s\n", fs
);
45 case PIPE_FORMAT_R8_UNORM
:
46 case PIPE_FORMAT_R32_FLOAT
:
47 case PIPE_FORMAT_R16_SSCALED
:
50 case PIPE_FORMAT_R8G8_UNORM
:
51 case PIPE_FORMAT_R32G32_FLOAT
:
52 case PIPE_FORMAT_R16G16_SSCALED
:
55 case PIPE_FORMAT_R8G8B8_UNORM
:
56 case PIPE_FORMAT_R32G32B32_FLOAT
:
57 case PIPE_FORMAT_R16G16B16_SSCALED
:
60 case PIPE_FORMAT_R8G8B8A8_UNORM
:
61 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
62 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
66 pf_sprint_name(fs
, pipe
);
67 NOUVEAU_ERR("Unknown format %s\n", fs
);
75 nv40_vbo_set_idxbuf(struct nv40_context
*nv40
, struct pipe_buffer
*ib
,
82 nv40
->idxbuf_format
= 0xdeadbeef;
86 /* No support for 8bit indices, no support at all on 0x4497 chips */
87 if (nv40
->screen
->curie
->grclass
== NV44TCL
|| ib_size
== 1)
92 type
= NV40TCL_IDXBUF_FORMAT_TYPE_U16
;
95 type
= NV40TCL_IDXBUF_FORMAT_TYPE_U32
;
101 if (ib
!= nv40
->idxbuf
||
102 type
!= nv40
->idxbuf_format
) {
103 nv40
->dirty
|= NV40_NEW_ARRAYS
;
105 nv40
->idxbuf_format
= type
;
112 nv40_vbo_static_attrib(struct nv40_context
*nv40
, int attrib
,
113 struct pipe_vertex_element
*ve
,
114 struct pipe_vertex_buffer
*vb
)
116 struct pipe_winsys
*ws
= nv40
->pipe
.winsys
;
117 unsigned type
, ncomp
;
120 if (nv40_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
))
123 map
= ws
->buffer_map(ws
, vb
->buffer
, PIPE_BUFFER_USAGE_CPU_READ
);
124 map
+= vb
->buffer_offset
+ ve
->src_offset
;
127 case NV40TCL_VTXFMT_TYPE_FLOAT
:
131 BEGIN_RING(curie
, NV40TCL_VTX_ATTR_4F_X(attrib
), 4);
158 ws
->buffer_unmap(ws
, vb
->buffer
);
164 ws
->buffer_unmap(ws
, vb
->buffer
);
168 ws
->buffer_unmap(ws
, vb
->buffer
);
174 nv40_draw_arrays(struct pipe_context
*pipe
,
175 unsigned mode
, unsigned start
, unsigned count
)
177 struct nv40_context
*nv40
= nv40_context(pipe
);
178 struct nouveau_channel
*chan
= nv40
->nvws
->channel
;
181 nv40_vbo_set_idxbuf(nv40
, NULL
, 0);
182 if (FORCE_SWTNL
|| !nv40_state_validate(nv40
)) {
183 return nv40_draw_elements_swtnl(pipe
, NULL
, 0,
190 nv40_state_emit(nv40
);
192 vc
= nouveau_vbuf_split(chan
->pushbuf
->remaining
, 6, 256,
193 mode
, start
, count
, &restart
);
199 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
200 OUT_RING (nvgl_primitive(mode
));
204 BEGIN_RING(curie
, NV40TCL_VB_VERTEX_BATCH
, 1);
205 OUT_RING (((nr
- 1) << 24) | start
);
211 unsigned push
= nr
> 2047 ? 2047 : nr
;
215 BEGIN_RING_NI(curie
, NV40TCL_VB_VERTEX_BATCH
, push
);
217 OUT_RING(((0x100 - 1) << 24) | start
);
222 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
229 pipe
->flush(pipe
, 0, NULL
);
234 nv40_draw_elements_u08(struct nv40_context
*nv40
, void *ib
,
235 unsigned mode
, unsigned start
, unsigned count
)
237 struct nouveau_channel
*chan
= nv40
->nvws
->channel
;
240 uint8_t *elts
= (uint8_t *)ib
+ start
;
241 unsigned vc
, push
, restart
;
243 nv40_state_emit(nv40
);
245 vc
= nouveau_vbuf_split(chan
->pushbuf
->remaining
, 6, 2,
246 mode
, start
, count
, &restart
);
253 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
254 OUT_RING (nvgl_primitive(mode
));
257 BEGIN_RING(curie
, NV40TCL_VB_ELEMENT_U32
, 1);
265 push
= MIN2(vc
, 2047 * 2);
267 BEGIN_RING_NI(curie
, NV40TCL_VB_ELEMENT_U16
, push
>> 1);
268 for (i
= 0; i
< push
; i
+=2)
269 OUT_RING((elts
[i
+1] << 16) | elts
[i
]);
275 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
283 nv40_draw_elements_u16(struct nv40_context
*nv40
, void *ib
,
284 unsigned mode
, unsigned start
, unsigned count
)
286 struct nouveau_channel
*chan
= nv40
->nvws
->channel
;
289 uint16_t *elts
= (uint16_t *)ib
+ start
;
290 unsigned vc
, push
, restart
;
292 nv40_state_emit(nv40
);
294 vc
= nouveau_vbuf_split(chan
->pushbuf
->remaining
, 6, 2,
295 mode
, start
, count
, &restart
);
302 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
303 OUT_RING (nvgl_primitive(mode
));
306 BEGIN_RING(curie
, NV40TCL_VB_ELEMENT_U32
, 1);
314 push
= MIN2(vc
, 2047 * 2);
316 BEGIN_RING_NI(curie
, NV40TCL_VB_ELEMENT_U16
, push
>> 1);
317 for (i
= 0; i
< push
; i
+=2)
318 OUT_RING((elts
[i
+1] << 16) | elts
[i
]);
324 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
332 nv40_draw_elements_u32(struct nv40_context
*nv40
, void *ib
,
333 unsigned mode
, unsigned start
, unsigned count
)
335 struct nouveau_channel
*chan
= nv40
->nvws
->channel
;
338 uint32_t *elts
= (uint32_t *)ib
+ start
;
339 unsigned vc
, push
, restart
;
341 nv40_state_emit(nv40
);
343 vc
= nouveau_vbuf_split(chan
->pushbuf
->remaining
, 5, 1,
344 mode
, start
, count
, &restart
);
351 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
352 OUT_RING (nvgl_primitive(mode
));
355 push
= MIN2(vc
, 2047);
357 BEGIN_RING_NI(curie
, NV40TCL_VB_ELEMENT_U32
, push
);
358 OUT_RINGp (elts
, push
);
364 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
372 nv40_draw_elements_inline(struct pipe_context
*pipe
,
373 struct pipe_buffer
*ib
, unsigned ib_size
,
374 unsigned mode
, unsigned start
, unsigned count
)
376 struct nv40_context
*nv40
= nv40_context(pipe
);
377 struct pipe_winsys
*ws
= pipe
->winsys
;
380 nv40_state_emit(nv40
);
382 map
= ws
->buffer_map(ws
, ib
, PIPE_BUFFER_USAGE_CPU_READ
);
384 NOUVEAU_ERR("failed mapping ib\n");
390 nv40_draw_elements_u08(nv40
, map
, mode
, start
, count
);
393 nv40_draw_elements_u16(nv40
, map
, mode
, start
, count
);
396 nv40_draw_elements_u32(nv40
, map
, mode
, start
, count
);
399 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
403 ws
->buffer_unmap(ws
, ib
);
408 nv40_draw_elements_vbo(struct pipe_context
*pipe
,
409 unsigned mode
, unsigned start
, unsigned count
)
411 struct nv40_context
*nv40
= nv40_context(pipe
);
412 struct nouveau_channel
*chan
= nv40
->nvws
->channel
;
418 nv40_state_emit(nv40
);
420 vc
= nouveau_vbuf_split(chan
->pushbuf
->remaining
, 6, 256,
421 mode
, start
, count
, &restart
);
427 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
428 OUT_RING (nvgl_primitive(mode
));
432 BEGIN_RING(curie
, NV40TCL_VB_INDEX_BATCH
, 1);
433 OUT_RING (((nr
- 1) << 24) | start
);
439 unsigned push
= nr
> 2047 ? 2047 : nr
;
443 BEGIN_RING_NI(curie
, NV40TCL_VB_INDEX_BATCH
, push
);
445 OUT_RING(((0x100 - 1) << 24) | start
);
450 BEGIN_RING(curie
, NV40TCL_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 nv40_context
*nv40
= nv40_context(pipe
);
468 idxbuf
= nv40_vbo_set_idxbuf(nv40
, indexBuffer
, indexSize
);
469 if (FORCE_SWTNL
|| !nv40_state_validate(nv40
)) {
470 return nv40_draw_elements_swtnl(pipe
, NULL
, 0,
473 nv40_state_emit(nv40
);
476 nv40_draw_elements_vbo(pipe
, mode
, start
, count
);
478 nv40_draw_elements_inline(pipe
, indexBuffer
, indexSize
,
482 pipe
->flush(pipe
, 0, NULL
);
487 nv40_vbo_validate(struct nv40_context
*nv40
)
489 struct nv40_vertex_program
*vp
= nv40
->vertprog
;
490 struct nouveau_stateobj
*vtxbuf
, *vtxfmt
;
491 struct pipe_buffer
*ib
= nv40
->idxbuf
;
492 unsigned ib_format
= nv40
->idxbuf_format
;
493 unsigned inputs
, hw
, num_hw
;
494 unsigned vb_flags
= NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
;
497 for (hw
= 0; hw
< 16 && inputs
; hw
++) {
498 if (inputs
& (1 << hw
)) {
500 inputs
&= ~(1 << hw
);
505 vtxbuf
= so_new(20, 18);
506 so_method(vtxbuf
, nv40
->screen
->curie
, NV40TCL_VTXBUF_ADDRESS(0), num_hw
);
507 vtxfmt
= so_new(17, 0);
508 so_method(vtxfmt
, nv40
->screen
->curie
, NV40TCL_VTXFMT(0), num_hw
);
511 for (hw
= 0; hw
< num_hw
; hw
++) {
512 struct pipe_vertex_element
*ve
;
513 struct pipe_vertex_buffer
*vb
;
514 unsigned type
, ncomp
;
516 if (!(inputs
& (1 << hw
))) {
518 so_data(vtxfmt
, NV40TCL_VTXFMT_TYPE_FLOAT
);
522 ve
= &nv40
->vtxelt
[hw
];
523 vb
= &nv40
->vtxbuf
[ve
->vertex_buffer_index
];
525 if (!vb
->pitch
&& nv40_vbo_static_attrib(nv40
, hw
, ve
, vb
)) {
527 so_data(vtxfmt
, NV40TCL_VTXFMT_TYPE_FLOAT
);
531 if (nv40_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
)) {
532 nv40
->fallback_swtnl
|= NV40_NEW_ARRAYS
;
533 so_ref(NULL
, &vtxbuf
);
534 so_ref(NULL
, &vtxfmt
);
538 so_reloc(vtxbuf
, vb
->buffer
, vb
->buffer_offset
+ ve
->src_offset
,
539 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
540 0, NV40TCL_VTXBUF_ADDRESS_DMA1
);
541 so_data (vtxfmt
, ((vb
->pitch
<< NV40TCL_VTXFMT_STRIDE_SHIFT
) |
542 (ncomp
<< NV40TCL_VTXFMT_SIZE_SHIFT
) | type
));
546 so_method(vtxbuf
, nv40
->screen
->curie
, NV40TCL_IDXBUF_ADDRESS
, 2);
547 so_reloc (vtxbuf
, ib
, 0, vb_flags
| NOUVEAU_BO_LOW
, 0, 0);
548 so_reloc (vtxbuf
, ib
, ib_format
, vb_flags
| NOUVEAU_BO_OR
,
549 0, NV40TCL_IDXBUF_FORMAT_DMA1
);
552 so_method(vtxbuf
, nv40
->screen
->curie
, 0x1710, 1);
555 so_ref(vtxbuf
, &nv40
->state
.hw
[NV40_STATE_VTXBUF
]);
556 nv40
->state
.dirty
|= (1ULL << NV40_STATE_VTXBUF
);
557 so_ref(vtxfmt
, &nv40
->state
.hw
[NV40_STATE_VTXFMT
]);
558 nv40
->state
.dirty
|= (1ULL << NV40_STATE_VTXFMT
);
562 struct nv40_state_entry nv40_state_vbo
= {
563 .validate
= nv40_vbo_validate
,
565 .pipe
= NV40_NEW_ARRAYS
,