1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
4 #include "nv40_context.h"
5 #include "nv40_state.h"
7 #include "nouveau/nouveau_channel.h"
8 #include "nouveau/nouveau_pushbuf.h"
9 #include "nouveau/nouveau_util.h"
14 nv40_vbo_format_to_hw(enum pipe_format pipe
, unsigned *fmt
, unsigned *ncomp
)
17 case PIPE_FORMAT_R32_FLOAT
:
18 case PIPE_FORMAT_R32G32_FLOAT
:
19 case PIPE_FORMAT_R32G32B32_FLOAT
:
20 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
21 *fmt
= NV40TCL_VTXFMT_TYPE_FLOAT
;
23 case PIPE_FORMAT_R8_UNORM
:
24 case PIPE_FORMAT_R8G8_UNORM
:
25 case PIPE_FORMAT_R8G8B8_UNORM
:
26 case PIPE_FORMAT_R8G8B8A8_UNORM
:
27 *fmt
= NV40TCL_VTXFMT_TYPE_UBYTE
;
29 case PIPE_FORMAT_R16_SSCALED
:
30 case PIPE_FORMAT_R16G16_SSCALED
:
31 case PIPE_FORMAT_R16G16B16_SSCALED
:
32 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
33 *fmt
= NV40TCL_VTXFMT_TYPE_USHORT
;
36 NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe
));
41 case PIPE_FORMAT_R8_UNORM
:
42 case PIPE_FORMAT_R32_FLOAT
:
43 case PIPE_FORMAT_R16_SSCALED
:
46 case PIPE_FORMAT_R8G8_UNORM
:
47 case PIPE_FORMAT_R32G32_FLOAT
:
48 case PIPE_FORMAT_R16G16_SSCALED
:
51 case PIPE_FORMAT_R8G8B8_UNORM
:
52 case PIPE_FORMAT_R32G32B32_FLOAT
:
53 case PIPE_FORMAT_R16G16B16_SSCALED
:
56 case PIPE_FORMAT_R8G8B8A8_UNORM
:
57 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
58 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
62 NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe
));
70 nv40_vbo_set_idxbuf(struct nv40_context
*nv40
, struct pipe_buffer
*ib
,
73 struct pipe_screen
*pscreen
= &nv40
->screen
->pipe
;
78 nv40
->idxbuf_format
= 0xdeadbeef;
82 if (!pscreen
->get_param(pscreen
, NOUVEAU_CAP_HW_IDXBUF
) || ib_size
== 1)
87 type
= NV40TCL_IDXBUF_FORMAT_TYPE_U16
;
90 type
= NV40TCL_IDXBUF_FORMAT_TYPE_U32
;
96 if (ib
!= nv40
->idxbuf
||
97 type
!= nv40
->idxbuf_format
) {
98 nv40
->dirty
|= NV40_NEW_ARRAYS
;
100 nv40
->idxbuf_format
= type
;
107 nv40_vbo_static_attrib(struct nv40_context
*nv40
, struct nouveau_stateobj
*so
,
108 int attrib
, struct pipe_vertex_element
*ve
,
109 struct pipe_vertex_buffer
*vb
)
111 struct pipe_winsys
*ws
= nv40
->pipe
.winsys
;
112 struct nouveau_grobj
*curie
= nv40
->screen
->curie
;
113 unsigned type
, ncomp
;
116 if (nv40_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
))
119 map
= ws
->buffer_map(ws
, vb
->buffer
, PIPE_BUFFER_USAGE_CPU_READ
);
120 map
+= vb
->buffer_offset
+ ve
->src_offset
;
123 case NV40TCL_VTXFMT_TYPE_FLOAT
:
129 so_method(so
, curie
, NV40TCL_VTX_ATTR_4F_X(attrib
), 4);
130 so_data (so
, fui(v
[0]));
131 so_data (so
, fui(v
[1]));
132 so_data (so
, fui(v
[2]));
133 so_data (so
, fui(v
[3]));
136 so_method(so
, curie
, NV40TCL_VTX_ATTR_3F_X(attrib
), 3);
137 so_data (so
, fui(v
[0]));
138 so_data (so
, fui(v
[1]));
139 so_data (so
, fui(v
[2]));
142 so_method(so
, curie
, NV40TCL_VTX_ATTR_2F_X(attrib
), 2);
143 so_data (so
, fui(v
[0]));
144 so_data (so
, fui(v
[1]));
147 so_method(so
, curie
, NV40TCL_VTX_ATTR_1F(attrib
), 1);
148 so_data (so
, fui(v
[0]));
151 ws
->buffer_unmap(ws
, vb
->buffer
);
157 ws
->buffer_unmap(ws
, vb
->buffer
);
161 ws
->buffer_unmap(ws
, vb
->buffer
);
167 nv40_draw_arrays(struct pipe_context
*pipe
,
168 unsigned mode
, unsigned start
, unsigned count
)
170 struct nv40_context
*nv40
= nv40_context(pipe
);
171 struct nouveau_channel
*chan
= nv40
->nvws
->channel
;
174 nv40_vbo_set_idxbuf(nv40
, NULL
, 0);
175 if (FORCE_SWTNL
|| !nv40_state_validate(nv40
)) {
176 return nv40_draw_elements_swtnl(pipe
, NULL
, 0,
183 nv40_state_emit(nv40
);
185 vc
= nouveau_vbuf_split(chan
->pushbuf
->remaining
, 6, 256,
186 mode
, start
, count
, &restart
);
192 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
193 OUT_RING (nvgl_primitive(mode
));
197 BEGIN_RING(curie
, NV40TCL_VB_VERTEX_BATCH
, 1);
198 OUT_RING (((nr
- 1) << 24) | start
);
204 unsigned push
= nr
> 2047 ? 2047 : nr
;
208 BEGIN_RING_NI(curie
, NV40TCL_VB_VERTEX_BATCH
, push
);
210 OUT_RING(((0x100 - 1) << 24) | start
);
215 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
222 pipe
->flush(pipe
, 0, NULL
);
227 nv40_draw_elements_u08(struct nv40_context
*nv40
, void *ib
,
228 unsigned mode
, unsigned start
, unsigned count
)
230 struct nouveau_channel
*chan
= nv40
->nvws
->channel
;
233 uint8_t *elts
= (uint8_t *)ib
+ start
;
234 unsigned vc
, push
, restart
;
236 nv40_state_emit(nv40
);
238 vc
= nouveau_vbuf_split(chan
->pushbuf
->remaining
, 6, 2,
239 mode
, start
, count
, &restart
);
246 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
247 OUT_RING (nvgl_primitive(mode
));
250 BEGIN_RING(curie
, NV40TCL_VB_ELEMENT_U32
, 1);
258 push
= MIN2(vc
, 2047 * 2);
260 BEGIN_RING_NI(curie
, NV40TCL_VB_ELEMENT_U16
, push
>> 1);
261 for (i
= 0; i
< push
; i
+=2)
262 OUT_RING((elts
[i
+1] << 16) | elts
[i
]);
268 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
276 nv40_draw_elements_u16(struct nv40_context
*nv40
, void *ib
,
277 unsigned mode
, unsigned start
, unsigned count
)
279 struct nouveau_channel
*chan
= nv40
->nvws
->channel
;
282 uint16_t *elts
= (uint16_t *)ib
+ start
;
283 unsigned vc
, push
, restart
;
285 nv40_state_emit(nv40
);
287 vc
= nouveau_vbuf_split(chan
->pushbuf
->remaining
, 6, 2,
288 mode
, start
, count
, &restart
);
295 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
296 OUT_RING (nvgl_primitive(mode
));
299 BEGIN_RING(curie
, NV40TCL_VB_ELEMENT_U32
, 1);
307 push
= MIN2(vc
, 2047 * 2);
309 BEGIN_RING_NI(curie
, NV40TCL_VB_ELEMENT_U16
, push
>> 1);
310 for (i
= 0; i
< push
; i
+=2)
311 OUT_RING((elts
[i
+1] << 16) | elts
[i
]);
317 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
325 nv40_draw_elements_u32(struct nv40_context
*nv40
, void *ib
,
326 unsigned mode
, unsigned start
, unsigned count
)
328 struct nouveau_channel
*chan
= nv40
->nvws
->channel
;
331 uint32_t *elts
= (uint32_t *)ib
+ start
;
332 unsigned vc
, push
, restart
;
334 nv40_state_emit(nv40
);
336 vc
= nouveau_vbuf_split(chan
->pushbuf
->remaining
, 5, 1,
337 mode
, start
, count
, &restart
);
344 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
345 OUT_RING (nvgl_primitive(mode
));
348 push
= MIN2(vc
, 2047);
350 BEGIN_RING_NI(curie
, NV40TCL_VB_ELEMENT_U32
, push
);
351 OUT_RINGp (elts
, push
);
357 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
365 nv40_draw_elements_inline(struct pipe_context
*pipe
,
366 struct pipe_buffer
*ib
, unsigned ib_size
,
367 unsigned mode
, unsigned start
, unsigned count
)
369 struct nv40_context
*nv40
= nv40_context(pipe
);
370 struct pipe_winsys
*ws
= pipe
->winsys
;
373 map
= ws
->buffer_map(ws
, ib
, PIPE_BUFFER_USAGE_CPU_READ
);
375 NOUVEAU_ERR("failed mapping ib\n");
381 nv40_draw_elements_u08(nv40
, map
, mode
, start
, count
);
384 nv40_draw_elements_u16(nv40
, map
, mode
, start
, count
);
387 nv40_draw_elements_u32(nv40
, map
, mode
, start
, count
);
390 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
394 ws
->buffer_unmap(ws
, ib
);
399 nv40_draw_elements_vbo(struct pipe_context
*pipe
,
400 unsigned mode
, unsigned start
, unsigned count
)
402 struct nv40_context
*nv40
= nv40_context(pipe
);
403 struct nouveau_channel
*chan
= nv40
->nvws
->channel
;
409 nv40_state_emit(nv40
);
411 vc
= nouveau_vbuf_split(chan
->pushbuf
->remaining
, 6, 256,
412 mode
, start
, count
, &restart
);
418 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
419 OUT_RING (nvgl_primitive(mode
));
423 BEGIN_RING(curie
, NV40TCL_VB_INDEX_BATCH
, 1);
424 OUT_RING (((nr
- 1) << 24) | start
);
430 unsigned push
= nr
> 2047 ? 2047 : nr
;
434 BEGIN_RING_NI(curie
, NV40TCL_VB_INDEX_BATCH
, push
);
436 OUT_RING(((0x100 - 1) << 24) | start
);
441 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
452 nv40_draw_elements(struct pipe_context
*pipe
,
453 struct pipe_buffer
*indexBuffer
, unsigned indexSize
,
454 unsigned mode
, unsigned start
, unsigned count
)
456 struct nv40_context
*nv40
= nv40_context(pipe
);
459 idxbuf
= nv40_vbo_set_idxbuf(nv40
, indexBuffer
, indexSize
);
460 if (FORCE_SWTNL
|| !nv40_state_validate(nv40
)) {
461 return nv40_draw_elements_swtnl(pipe
, NULL
, 0,
466 nv40_draw_elements_vbo(pipe
, mode
, start
, count
);
468 nv40_draw_elements_inline(pipe
, indexBuffer
, indexSize
,
472 pipe
->flush(pipe
, 0, NULL
);
477 nv40_vbo_validate(struct nv40_context
*nv40
)
479 struct nouveau_stateobj
*vtxbuf
, *vtxfmt
, *sattr
= NULL
;
480 struct nouveau_grobj
*curie
= nv40
->screen
->curie
;
481 struct pipe_buffer
*ib
= nv40
->idxbuf
;
482 unsigned ib_format
= nv40
->idxbuf_format
;
483 unsigned vb_flags
= NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
;
486 if (nv40
->edgeflags
) {
487 nv40
->fallback_swtnl
|= NV40_NEW_ARRAYS
;
491 vtxbuf
= so_new(20, 18);
492 so_method(vtxbuf
, curie
, NV40TCL_VTXBUF_ADDRESS(0), nv40
->vtxelt_nr
);
493 vtxfmt
= so_new(17, 0);
494 so_method(vtxfmt
, curie
, NV40TCL_VTXFMT(0), nv40
->vtxelt_nr
);
496 for (hw
= 0; hw
< nv40
->vtxelt_nr
; hw
++) {
497 struct pipe_vertex_element
*ve
;
498 struct pipe_vertex_buffer
*vb
;
499 unsigned type
, ncomp
;
501 ve
= &nv40
->vtxelt
[hw
];
502 vb
= &nv40
->vtxbuf
[ve
->vertex_buffer_index
];
506 sattr
= so_new(16 * 5, 0);
508 if (nv40_vbo_static_attrib(nv40
, sattr
, hw
, ve
, vb
)) {
510 so_data(vtxfmt
, NV40TCL_VTXFMT_TYPE_FLOAT
);
515 if (nv40_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
)) {
516 nv40
->fallback_swtnl
|= NV40_NEW_ARRAYS
;
517 so_ref(NULL
, &vtxbuf
);
518 so_ref(NULL
, &vtxfmt
);
522 so_reloc(vtxbuf
, vb
->buffer
, vb
->buffer_offset
+ ve
->src_offset
,
523 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
524 0, NV40TCL_VTXBUF_ADDRESS_DMA1
);
525 so_data (vtxfmt
, ((vb
->stride
<< NV40TCL_VTXFMT_STRIDE_SHIFT
) |
526 (ncomp
<< NV40TCL_VTXFMT_SIZE_SHIFT
) | type
));
530 so_method(vtxbuf
, curie
, NV40TCL_IDXBUF_ADDRESS
, 2);
531 so_reloc (vtxbuf
, ib
, 0, vb_flags
| NOUVEAU_BO_LOW
, 0, 0);
532 so_reloc (vtxbuf
, ib
, ib_format
, vb_flags
| NOUVEAU_BO_OR
,
533 0, NV40TCL_IDXBUF_FORMAT_DMA1
);
536 so_method(vtxbuf
, curie
, 0x1710, 1);
539 so_ref(vtxbuf
, &nv40
->state
.hw
[NV40_STATE_VTXBUF
]);
540 nv40
->state
.dirty
|= (1ULL << NV40_STATE_VTXBUF
);
541 so_ref(vtxfmt
, &nv40
->state
.hw
[NV40_STATE_VTXFMT
]);
542 nv40
->state
.dirty
|= (1ULL << NV40_STATE_VTXFMT
);
543 so_ref(sattr
, &nv40
->state
.hw
[NV40_STATE_VTXATTR
]);
544 nv40
->state
.dirty
|= (1ULL << NV40_STATE_VTXATTR
);
548 struct nv40_state_entry nv40_state_vbo
= {
549 .validate
= nv40_vbo_validate
,
551 .pipe
= NV40_NEW_ARRAYS
,