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