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"
12 nv40_vbo_ncomp(uint format
)
16 if (pf_size_x(format
)) ncomp
++;
17 if (pf_size_y(format
)) ncomp
++;
18 if (pf_size_z(format
)) ncomp
++;
19 if (pf_size_w(format
)) ncomp
++;
25 nv40_vbo_type(uint format
)
27 switch (pf_type(format
)) {
28 case PIPE_FORMAT_TYPE_FLOAT
:
29 return NV40TCL_VTXFMT_TYPE_FLOAT
;
30 case PIPE_FORMAT_TYPE_UNORM
:
31 return NV40TCL_VTXFMT_TYPE_UBYTE
;
33 NOUVEAU_ERR("Unknown format 0x%08x\n", format
);
34 return NV40TCL_VTXFMT_TYPE_FLOAT
;
39 nv40_vbo_static_attrib(struct nv40_context
*nv40
, int attrib
,
40 struct pipe_vertex_element
*ve
,
41 struct pipe_vertex_buffer
*vb
)
43 struct pipe_winsys
*ws
= nv40
->pipe
.winsys
;
47 type
= nv40_vbo_type(ve
->src_format
);
48 ncomp
= nv40_vbo_ncomp(ve
->src_format
);
50 map
= ws
->buffer_map(ws
, vb
->buffer
, PIPE_BUFFER_USAGE_CPU_READ
);
51 map
+= vb
->buffer_offset
+ ve
->src_offset
;
54 case NV40TCL_VTXFMT_TYPE_FLOAT
:
58 BEGIN_RING(curie
, NV40TCL_VTX_ATTR_4F_X(attrib
), 4);
85 ws
->buffer_unmap(ws
, vb
->buffer
);
91 ws
->buffer_unmap(ws
, vb
->buffer
);
95 ws
->buffer_unmap(ws
, vb
->buffer
);
101 nv40_vbo_arrays_update(struct nv40_context
*nv40
, struct pipe_buffer
*ib
,
104 struct nv40_vertex_program
*vp
= nv40
->pipe_state
.vertprog
;
105 struct nouveau_stateobj
*vtxbuf
, *vtxfmt
;
106 unsigned inputs
, hw
, num_hw
;
107 unsigned vb_flags
= NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
;
110 for (hw
= 0; hw
< 16 && inputs
; hw
++) {
111 if (inputs
& (1 << hw
)) {
113 inputs
&= ~(1 << hw
);
118 vtxbuf
= so_new(20, 18);
119 so_method(vtxbuf
, nv40
->hw
->curie
, NV40TCL_VTXBUF_ADDRESS(0), num_hw
);
120 vtxfmt
= so_new(17, 0);
121 so_method(vtxfmt
, nv40
->hw
->curie
, NV40TCL_VTXFMT(0), num_hw
);
124 for (hw
= 0; hw
< num_hw
; hw
++) {
125 struct pipe_vertex_element
*ve
;
126 struct pipe_vertex_buffer
*vb
;
128 if (!(inputs
& (1 << hw
))) {
130 so_data(vtxfmt
, NV40TCL_VTXFMT_TYPE_FLOAT
);
134 ve
= &nv40
->vtxelt
[hw
];
135 vb
= &nv40
->vtxbuf
[ve
->vertex_buffer_index
];
137 if (!vb
->pitch
&& nv40_vbo_static_attrib(nv40
, hw
, ve
, vb
)) {
139 so_data(vtxfmt
, NV40TCL_VTXFMT_TYPE_FLOAT
);
143 so_reloc(vtxbuf
, vb
->buffer
, vb
->buffer_offset
+ ve
->src_offset
,
144 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
145 0, NV40TCL_VTXBUF_ADDRESS_DMA1
);
146 so_data (vtxfmt
, ((vb
->pitch
<< NV40TCL_VTXFMT_STRIDE_SHIFT
) |
147 (nv40_vbo_ncomp(ve
->src_format
) <<
148 NV40TCL_VTXFMT_SIZE_SHIFT
) |
149 nv40_vbo_type(ve
->src_format
)));
153 so_method(vtxbuf
, nv40
->hw
->curie
, NV40TCL_IDXBUF_ADDRESS
, 2);
154 so_reloc (vtxbuf
, ib
, 0, vb_flags
| NOUVEAU_BO_LOW
, 0, 0);
155 so_reloc (vtxbuf
, ib
, ib_format
, vb_flags
| NOUVEAU_BO_OR
,
156 0, NV40TCL_IDXBUF_FORMAT_DMA1
);
159 so_emit(nv40
->nvws
, vtxfmt
);
160 so_emit(nv40
->nvws
, vtxbuf
);
161 so_ref (vtxbuf
, &nv40
->so_vtxbuf
);
162 so_ref (NULL
, &vtxfmt
);
166 nv40_vbo_validate_state(struct nv40_context
*nv40
,
167 struct pipe_buffer
*ib
, unsigned ib_format
)
169 unsigned vdn
= nv40
->dirty
& NV40_NEW_ARRAYS
;
171 nv40_emit_hw_state(nv40
);
173 nv40_vbo_arrays_update(nv40
, ib
, ib_format
);
174 nv40
->dirty
&= ~NV40_NEW_ARRAYS
;
177 so_emit_reloc_markers(nv40
->nvws
, nv40
->so_vtxbuf
);
179 BEGIN_RING(curie
, 0x1710, 1);
180 OUT_RING (0); /* vtx cache flush */
186 nv40_draw_arrays(struct pipe_context
*pipe
, unsigned mode
, unsigned start
,
189 struct nv40_context
*nv40
= nv40_context(pipe
);
193 ret
= nv40_vbo_validate_state(nv40
, NULL
, 0);
195 NOUVEAU_ERR("state validate failed\n");
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);
225 pipe
->flush(pipe
, 0);
230 nv40_draw_elements_u08(struct nv40_context
*nv40
, void *ib
,
231 unsigned start
, unsigned count
)
233 uint8_t *elts
= (uint8_t *)ib
+ start
;
237 BEGIN_RING(curie
, NV40TCL_VB_ELEMENT_U32
, 1);
243 push
= MIN2(count
, 2047 * 2);
245 BEGIN_RING_NI(curie
, NV40TCL_VB_ELEMENT_U16
, push
>> 1);
246 for (i
= 0; i
< push
; i
+=2)
247 OUT_RING((elts
[i
+1] << 16) | elts
[i
]);
255 nv40_draw_elements_u16(struct nv40_context
*nv40
, void *ib
,
256 unsigned start
, unsigned count
)
258 uint16_t *elts
= (uint16_t *)ib
+ start
;
262 BEGIN_RING(curie
, NV40TCL_VB_ELEMENT_U32
, 1);
268 push
= MIN2(count
, 2047 * 2);
270 BEGIN_RING_NI(curie
, NV40TCL_VB_ELEMENT_U16
, push
>> 1);
271 for (i
= 0; i
< push
; i
+=2)
272 OUT_RING((elts
[i
+1] << 16) | elts
[i
]);
280 nv40_draw_elements_u32(struct nv40_context
*nv40
, void *ib
,
281 unsigned start
, unsigned count
)
283 uint32_t *elts
= (uint32_t *)ib
+ start
;
287 push
= MIN2(count
, 2047);
289 BEGIN_RING_NI(curie
, NV40TCL_VB_ELEMENT_U32
, push
);
290 OUT_RINGp (elts
, push
);
298 nv40_draw_elements_inline(struct pipe_context
*pipe
,
299 struct pipe_buffer
*ib
, unsigned ib_size
,
300 unsigned mode
, unsigned start
, unsigned count
)
302 struct nv40_context
*nv40
= nv40_context(pipe
);
303 struct pipe_winsys
*ws
= pipe
->winsys
;
307 ret
= nv40_vbo_validate_state(nv40
, NULL
, 0);
309 NOUVEAU_ERR("state validate failed\n");
313 map
= ws
->buffer_map(ws
, ib
, PIPE_BUFFER_USAGE_CPU_READ
);
315 NOUVEAU_ERR("failed mapping ib\n");
319 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
320 OUT_RING (nvgl_primitive(mode
));
324 nv40_draw_elements_u08(nv40
, map
, start
, count
);
327 nv40_draw_elements_u16(nv40
, map
, start
, count
);
330 nv40_draw_elements_u32(nv40
, map
, start
, count
);
333 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
337 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
340 ws
->buffer_unmap(ws
, ib
);
346 nv40_draw_elements_vbo(struct pipe_context
*pipe
,
347 struct pipe_buffer
*ib
, unsigned ib_size
,
348 unsigned mode
, unsigned start
, unsigned count
)
350 struct nv40_context
*nv40
= nv40_context(pipe
);
356 type
= NV40TCL_IDXBUF_FORMAT_TYPE_U16
;
359 type
= NV40TCL_IDXBUF_FORMAT_TYPE_U32
;
362 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
366 ret
= nv40_vbo_validate_state(nv40
, ib
, type
);
368 NOUVEAU_ERR("failed state validation\n");
372 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
373 OUT_RING (nvgl_primitive(mode
));
377 BEGIN_RING(curie
, NV40TCL_VB_INDEX_BATCH
, 1);
378 OUT_RING (((nr
- 1) << 24) | start
);
384 unsigned push
= nr
> 2047 ? 2047 : nr
;
388 BEGIN_RING_NI(curie
, NV40TCL_VB_INDEX_BATCH
, push
);
390 OUT_RING(((0x100 - 1) << 24) | start
);
395 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
402 nv40_draw_elements(struct pipe_context
*pipe
,
403 struct pipe_buffer
*indexBuffer
, unsigned indexSize
,
404 unsigned mode
, unsigned start
, unsigned count
)
406 struct nv40_context
*nv40
= nv40_context(pipe
);
408 /* 0x4497 doesn't support real index buffers, and there doesn't appear
409 * to be support on any chipset for 8-bit indices.
411 if (nv40
->hw
->curie
->grclass
== NV44TCL
|| indexSize
== 1) {
412 nv40_draw_elements_inline(pipe
, indexBuffer
, indexSize
,
415 nv40_draw_elements_vbo(pipe
, indexBuffer
, indexSize
,
419 pipe
->flush(pipe
, 0);