nv40: dump meaningful names for surface formats
[mesa.git] / src / gallium / drivers / nv40 / nv40_vbo.c
1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "pipe/p_util.h"
4
5 #include "nv40_context.h"
6 #include "nv40_state.h"
7
8 #include "nouveau/nouveau_channel.h"
9 #include "nouveau/nouveau_pushbuf.h"
10
11 static INLINE int
12 nv40_vbo_ncomp(uint format)
13 {
14 int ncomp = 0;
15
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++;
20
21 return ncomp;
22 }
23
24 static INLINE int
25 nv40_vbo_type(uint format)
26 {
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;
32 default:
33 {
34 char fs[128];
35 pf_sprint_name(fs, format);
36 NOUVEAU_ERR("Unknown format %s\n", fs);
37 return NV40TCL_VTXFMT_TYPE_FLOAT;
38 }
39 }
40 }
41
42 static boolean
43 nv40_vbo_static_attrib(struct nv40_context *nv40, int attrib,
44 struct pipe_vertex_element *ve,
45 struct pipe_vertex_buffer *vb)
46 {
47 struct pipe_winsys *ws = nv40->pipe.winsys;
48 int type, ncomp;
49 void *map;
50
51 type = nv40_vbo_type(ve->src_format);
52 ncomp = nv40_vbo_ncomp(ve->src_format);
53
54 map = ws->buffer_map(ws, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ);
55 map += vb->buffer_offset + ve->src_offset;
56
57 switch (type) {
58 case NV40TCL_VTXFMT_TYPE_FLOAT:
59 {
60 float *v = map;
61
62 BEGIN_RING(curie, NV40TCL_VTX_ATTR_4F_X(attrib), 4);
63 switch (ncomp) {
64 case 4:
65 OUT_RINGf(v[0]);
66 OUT_RINGf(v[1]);
67 OUT_RINGf(v[2]);
68 OUT_RINGf(v[3]);
69 break;
70 case 3:
71 OUT_RINGf(v[0]);
72 OUT_RINGf(v[1]);
73 OUT_RINGf(v[2]);
74 OUT_RINGf(1.0);
75 break;
76 case 2:
77 OUT_RINGf(v[0]);
78 OUT_RINGf(v[1]);
79 OUT_RINGf(0.0);
80 OUT_RINGf(1.0);
81 break;
82 case 1:
83 OUT_RINGf(v[0]);
84 OUT_RINGf(0.0);
85 OUT_RINGf(0.0);
86 OUT_RINGf(1.0);
87 break;
88 default:
89 ws->buffer_unmap(ws, vb->buffer);
90 return FALSE;
91 }
92 }
93 break;
94 default:
95 ws->buffer_unmap(ws, vb->buffer);
96 return FALSE;
97 }
98
99 ws->buffer_unmap(ws, vb->buffer);
100
101 return TRUE;
102 }
103
104 static void
105 nv40_vbo_arrays_update(struct nv40_context *nv40, struct pipe_buffer *ib,
106 unsigned ib_format)
107 {
108 struct nv40_vertex_program *vp = nv40->pipe_state.vertprog;
109 struct nouveau_stateobj *vtxbuf, *vtxfmt;
110 unsigned inputs, hw, num_hw;
111 unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
112
113 inputs = vp->ir;
114 for (hw = 0; hw < 16 && inputs; hw++) {
115 if (inputs & (1 << hw)) {
116 num_hw = hw;
117 inputs &= ~(1 << hw);
118 }
119 }
120 num_hw++;
121
122 vtxbuf = so_new(20, 18);
123 so_method(vtxbuf, nv40->hw->curie, NV40TCL_VTXBUF_ADDRESS(0), num_hw);
124 vtxfmt = so_new(17, 0);
125 so_method(vtxfmt, nv40->hw->curie, NV40TCL_VTXFMT(0), num_hw);
126
127 inputs = vp->ir;
128 for (hw = 0; hw < num_hw; hw++) {
129 struct pipe_vertex_element *ve;
130 struct pipe_vertex_buffer *vb;
131
132 if (!(inputs & (1 << hw))) {
133 so_data(vtxbuf, 0);
134 so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
135 continue;
136 }
137
138 ve = &nv40->vtxelt[hw];
139 vb = &nv40->vtxbuf[ve->vertex_buffer_index];
140
141 if (!vb->pitch && nv40_vbo_static_attrib(nv40, hw, ve, vb)) {
142 so_data(vtxbuf, 0);
143 so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
144 continue;
145 }
146
147 so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset,
148 vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
149 0, NV40TCL_VTXBUF_ADDRESS_DMA1);
150 so_data (vtxfmt, ((vb->pitch << NV40TCL_VTXFMT_STRIDE_SHIFT) |
151 (nv40_vbo_ncomp(ve->src_format) <<
152 NV40TCL_VTXFMT_SIZE_SHIFT) |
153 nv40_vbo_type(ve->src_format)));
154 }
155
156 if (ib) {
157 so_method(vtxbuf, nv40->hw->curie, NV40TCL_IDXBUF_ADDRESS, 2);
158 so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
159 so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR,
160 0, NV40TCL_IDXBUF_FORMAT_DMA1);
161 }
162
163 so_emit(nv40->nvws, vtxfmt);
164 so_emit(nv40->nvws, vtxbuf);
165 so_ref (vtxbuf, &nv40->so_vtxbuf);
166 so_ref (NULL, &vtxfmt);
167 }
168
169 static boolean
170 nv40_vbo_validate_state(struct nv40_context *nv40,
171 struct pipe_buffer *ib, unsigned ib_format)
172 {
173 unsigned vdn = nv40->dirty & NV40_NEW_ARRAYS;
174
175 nv40_emit_hw_state(nv40);
176 if (vdn || ib) {
177 nv40_vbo_arrays_update(nv40, ib, ib_format);
178 nv40->dirty &= ~NV40_NEW_ARRAYS;
179 }
180
181 so_emit_reloc_markers(nv40->nvws, nv40->so_vtxbuf);
182
183 BEGIN_RING(curie, 0x1710, 1);
184 OUT_RING (0); /* vtx cache flush */
185
186 return TRUE;
187 }
188
189 boolean
190 nv40_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
191 unsigned count)
192 {
193 struct nv40_context *nv40 = nv40_context(pipe);
194 unsigned nr;
195 boolean ret;
196
197 ret = nv40_vbo_validate_state(nv40, NULL, 0);
198 if (!ret) {
199 NOUVEAU_ERR("state validate failed\n");
200 return FALSE;
201 }
202
203 BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
204 OUT_RING (nvgl_primitive(mode));
205
206 nr = (count & 0xff);
207 if (nr) {
208 BEGIN_RING(curie, NV40TCL_VB_VERTEX_BATCH, 1);
209 OUT_RING (((nr - 1) << 24) | start);
210 start += nr;
211 }
212
213 nr = count >> 8;
214 while (nr) {
215 unsigned push = nr > 2047 ? 2047 : nr;
216
217 nr -= push;
218
219 BEGIN_RING_NI(curie, NV40TCL_VB_VERTEX_BATCH, push);
220 while (push--) {
221 OUT_RING(((0x100 - 1) << 24) | start);
222 start += 0x100;
223 }
224 }
225
226 BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
227 OUT_RING (0);
228
229 pipe->flush(pipe, 0);
230 return TRUE;
231 }
232
233 static INLINE void
234 nv40_draw_elements_u08(struct nv40_context *nv40, void *ib,
235 unsigned start, unsigned count)
236 {
237 uint8_t *elts = (uint8_t *)ib + start;
238 int push, i;
239
240 if (count & 1) {
241 BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
242 OUT_RING (elts[0]);
243 elts++; count--;
244 }
245
246 while (count) {
247 push = MIN2(count, 2047 * 2);
248
249 BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push >> 1);
250 for (i = 0; i < push; i+=2)
251 OUT_RING((elts[i+1] << 16) | elts[i]);
252
253 count -= push;
254 elts += push;
255 }
256 }
257
258 static INLINE void
259 nv40_draw_elements_u16(struct nv40_context *nv40, void *ib,
260 unsigned start, unsigned count)
261 {
262 uint16_t *elts = (uint16_t *)ib + start;
263 int push, i;
264
265 if (count & 1) {
266 BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
267 OUT_RING (elts[0]);
268 elts++; count--;
269 }
270
271 while (count) {
272 push = MIN2(count, 2047 * 2);
273
274 BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push >> 1);
275 for (i = 0; i < push; i+=2)
276 OUT_RING((elts[i+1] << 16) | elts[i]);
277
278 count -= push;
279 elts += push;
280 }
281 }
282
283 static INLINE void
284 nv40_draw_elements_u32(struct nv40_context *nv40, void *ib,
285 unsigned start, unsigned count)
286 {
287 uint32_t *elts = (uint32_t *)ib + start;
288 int push;
289
290 while (count) {
291 push = MIN2(count, 2047);
292
293 BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U32, push);
294 OUT_RINGp (elts, push);
295
296 count -= push;
297 elts += push;
298 }
299 }
300
301 static boolean
302 nv40_draw_elements_inline(struct pipe_context *pipe,
303 struct pipe_buffer *ib, unsigned ib_size,
304 unsigned mode, unsigned start, unsigned count)
305 {
306 struct nv40_context *nv40 = nv40_context(pipe);
307 struct pipe_winsys *ws = pipe->winsys;
308 boolean ret;
309 void *map;
310
311 ret = nv40_vbo_validate_state(nv40, NULL, 0);
312 if (!ret) {
313 NOUVEAU_ERR("state validate failed\n");
314 return FALSE;
315 }
316
317 map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ);
318 if (!ib) {
319 NOUVEAU_ERR("failed mapping ib\n");
320 return FALSE;
321 }
322
323 BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
324 OUT_RING (nvgl_primitive(mode));
325
326 switch (ib_size) {
327 case 1:
328 nv40_draw_elements_u08(nv40, map, start, count);
329 break;
330 case 2:
331 nv40_draw_elements_u16(nv40, map, start, count);
332 break;
333 case 4:
334 nv40_draw_elements_u32(nv40, map, start, count);
335 break;
336 default:
337 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
338 break;
339 }
340
341 BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
342 OUT_RING (0);
343
344 ws->buffer_unmap(ws, ib);
345
346 return TRUE;
347 }
348
349 static boolean
350 nv40_draw_elements_vbo(struct pipe_context *pipe,
351 struct pipe_buffer *ib, unsigned ib_size,
352 unsigned mode, unsigned start, unsigned count)
353 {
354 struct nv40_context *nv40 = nv40_context(pipe);
355 unsigned nr, type;
356 boolean ret;
357
358 switch (ib_size) {
359 case 2:
360 type = NV40TCL_IDXBUF_FORMAT_TYPE_U16;
361 break;
362 case 4:
363 type = NV40TCL_IDXBUF_FORMAT_TYPE_U32;
364 break;
365 default:
366 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
367 return FALSE;
368 }
369
370 ret = nv40_vbo_validate_state(nv40, ib, type);
371 if (!ret) {
372 NOUVEAU_ERR("failed state validation\n");
373 return FALSE;
374 }
375
376 BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
377 OUT_RING (nvgl_primitive(mode));
378
379 nr = (count & 0xff);
380 if (nr) {
381 BEGIN_RING(curie, NV40TCL_VB_INDEX_BATCH, 1);
382 OUT_RING (((nr - 1) << 24) | start);
383 start += nr;
384 }
385
386 nr = count >> 8;
387 while (nr) {
388 unsigned push = nr > 2047 ? 2047 : nr;
389
390 nr -= push;
391
392 BEGIN_RING_NI(curie, NV40TCL_VB_INDEX_BATCH, push);
393 while (push--) {
394 OUT_RING(((0x100 - 1) << 24) | start);
395 start += 0x100;
396 }
397 }
398
399 BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
400 OUT_RING (0);
401
402 return TRUE;
403 }
404
405 boolean
406 nv40_draw_elements(struct pipe_context *pipe,
407 struct pipe_buffer *indexBuffer, unsigned indexSize,
408 unsigned mode, unsigned start, unsigned count)
409 {
410 struct nv40_context *nv40 = nv40_context(pipe);
411
412 /* 0x4497 doesn't support real index buffers, and there doesn't appear
413 * to be support on any chipset for 8-bit indices.
414 */
415 if (nv40->hw->curie->grclass == NV44TCL || indexSize == 1) {
416 nv40_draw_elements_inline(pipe, indexBuffer, indexSize,
417 mode, start, count);
418 } else {
419 nv40_draw_elements_vbo(pipe, indexBuffer, indexSize,
420 mode, start, count);
421 }
422
423 pipe->flush(pipe, 0);
424 return TRUE;
425 }
426
427