nvc0: import nvc0 gallium driver
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_push2.c
1
2 #include "pipe/p_context.h"
3 #include "pipe/p_state.h"
4 #include "util/u_inlines.h"
5 #include "util/u_format.h"
6 #include "translate/translate.h"
7
8 #include "nvc0_context.h"
9 #include "nvc0_resource.h"
10
11 #include "nvc0_3d.xml.h"
12
13 struct push_context {
14 struct nvc0_context *nvc0;
15
16 uint vertex_size;
17
18 void *idxbuf;
19 uint idxsize;
20
21 float edgeflag;
22 int edgeflag_input;
23
24 struct {
25 void *map;
26 void (*push)(struct nouveau_channel *, void *);
27 uint32_t stride;
28 uint32_t divisor;
29 uint32_t step;
30 } attr[32];
31 int num_attrs;
32 };
33
34 static void
35 emit_b32_1(struct nouveau_channel *chan, void *data)
36 {
37 uint32_t *v = data;
38
39 OUT_RING(chan, v[0]);
40 }
41
42 static void
43 emit_b32_2(struct nouveau_channel *chan, void *data)
44 {
45 uint32_t *v = data;
46
47 OUT_RING(chan, v[0]);
48 OUT_RING(chan, v[1]);
49 }
50
51 static void
52 emit_b32_3(struct nouveau_channel *chan, void *data)
53 {
54 uint32_t *v = data;
55
56 OUT_RING(chan, v[0]);
57 OUT_RING(chan, v[1]);
58 OUT_RING(chan, v[2]);
59 }
60
61 static void
62 emit_b32_4(struct nouveau_channel *chan, void *data)
63 {
64 uint32_t *v = data;
65
66 OUT_RING(chan, v[0]);
67 OUT_RING(chan, v[1]);
68 OUT_RING(chan, v[2]);
69 OUT_RING(chan, v[3]);
70 }
71
72 static void
73 emit_b16_1(struct nouveau_channel *chan, void *data)
74 {
75 uint16_t *v = data;
76
77 OUT_RING(chan, v[0]);
78 }
79
80 static void
81 emit_b16_3(struct nouveau_channel *chan, void *data)
82 {
83 uint16_t *v = data;
84
85 OUT_RING(chan, (v[1] << 16) | v[0]);
86 OUT_RING(chan, v[2]);
87 }
88
89 static void
90 emit_b08_1(struct nouveau_channel *chan, void *data)
91 {
92 uint8_t *v = data;
93
94 OUT_RING(chan, v[0]);
95 }
96
97 static void
98 emit_b08_3(struct nouveau_channel *chan, void *data)
99 {
100 uint8_t *v = data;
101
102 OUT_RING(chan, (v[2] << 16) | (v[1] << 8) | v[0]);
103 }
104
105 static void
106 emit_b64_1(struct nouveau_channel *chan, void *data)
107 {
108 double *v = data;
109
110 OUT_RINGf(chan, v[0]);
111 }
112
113 static void
114 emit_b64_2(struct nouveau_channel *chan, void *data)
115 {
116 double *v = data;
117
118 OUT_RINGf(chan, v[0]);
119 OUT_RINGf(chan, v[1]);
120 }
121
122 static void
123 emit_b64_3(struct nouveau_channel *chan, void *data)
124 {
125 double *v = data;
126
127 OUT_RINGf(chan, v[0]);
128 OUT_RINGf(chan, v[1]);
129 OUT_RINGf(chan, v[2]);
130 }
131
132 static void
133 emit_b64_4(struct nouveau_channel *chan, void *data)
134 {
135 double *v = data;
136
137 OUT_RINGf(chan, v[0]);
138 OUT_RINGf(chan, v[1]);
139 OUT_RINGf(chan, v[2]);
140 OUT_RINGf(chan, v[3]);
141 }
142
143 static INLINE void
144 emit_vertex(struct push_context *ctx, unsigned n)
145 {
146 struct nouveau_channel *chan = ctx->nvc0->screen->base.channel;
147 int i;
148
149 if (ctx->edgeflag_input < 32) {
150 /* TODO */
151 }
152
153 BEGIN_RING_NI(chan, RING_3D(VERTEX_DATA), ctx->vertex_size);
154 for (i = 0; i < ctx->num_attrs; ++i)
155 ctx->attr[i].push(chan,
156 (uint8_t *)ctx->attr[i].map + n * ctx->attr[i].stride);
157 }
158
159 static void
160 emit_edgeflag(struct push_context *ctx, boolean enabled)
161 {
162 struct nouveau_channel *chan = ctx->nvc0->screen->base.channel;
163
164 INLIN_RING(chan, RING_3D(EDGEFLAG_ENABLE), enabled);
165 }
166
167 static void
168 emit_elt08(struct push_context *ctx, unsigned start, unsigned count)
169 {
170 uint8_t *idxbuf = ctx->idxbuf;
171
172 while (count--)
173 emit_vertex(ctx, idxbuf[start++]);
174 }
175
176 static void
177 emit_elt16(struct push_context *ctx, unsigned start, unsigned count)
178 {
179 uint16_t *idxbuf = ctx->idxbuf;
180
181 while (count--)
182 emit_vertex(ctx, idxbuf[start++]);
183 }
184
185 static void
186 emit_elt32(struct push_context *ctx, unsigned start, unsigned count)
187 {
188 uint32_t *idxbuf = ctx->idxbuf;
189
190 while (count--)
191 emit_vertex(ctx, idxbuf[start++]);
192 }
193
194 static void
195 emit_seq(struct push_context *ctx, unsigned start, unsigned count)
196 {
197 while (count--)
198 emit_vertex(ctx, start++);
199 }
200
201 #define NVC0_PRIM_GL_CASE(n) \
202 case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n
203
204 static INLINE unsigned
205 nvc0_prim_gl(unsigned prim)
206 {
207 switch (prim) {
208 NVC0_PRIM_GL_CASE(POINTS);
209 NVC0_PRIM_GL_CASE(LINES);
210 NVC0_PRIM_GL_CASE(LINE_LOOP);
211 NVC0_PRIM_GL_CASE(LINE_STRIP);
212 NVC0_PRIM_GL_CASE(TRIANGLES);
213 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP);
214 NVC0_PRIM_GL_CASE(TRIANGLE_FAN);
215 NVC0_PRIM_GL_CASE(QUADS);
216 NVC0_PRIM_GL_CASE(QUAD_STRIP);
217 NVC0_PRIM_GL_CASE(POLYGON);
218 NVC0_PRIM_GL_CASE(LINES_ADJACENCY);
219 NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY);
220 NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY);
221 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY);
222 /*
223 NVC0_PRIM_GL_CASE(PATCHES); */
224 default:
225 return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS;
226 break;
227 }
228 }
229
230 void
231 nvc0_push_vbo2(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
232 {
233 struct push_context ctx;
234 unsigned i, n;
235 unsigned inst = info->instance_count;
236 unsigned prim = nvc0_prim_gl(info->mode);
237
238 ctx.nvc0 = nvc0;
239 ctx.vertex_size = nvc0->vertex->vtx_size;
240 ctx.idxbuf = NULL;
241 ctx.num_attrs = 0;
242 ctx.edgeflag = 0.5f;
243 ctx.edgeflag_input = 32;
244
245 for (i = 0; i < nvc0->vertex->num_elements; ++i) {
246 struct pipe_vertex_element *ve = &nvc0->vertex->element[i].pipe;
247 struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[ve->vertex_buffer_index];
248 struct nouveau_bo *bo = nvc0_resource(vb->buffer)->bo;
249 unsigned nr_components;
250
251 if (!(nvc0->vbo_fifo & (1 << i)))
252 continue;
253 n = ctx.num_attrs++;
254
255 if (nouveau_bo_map(bo, NOUVEAU_BO_RD))
256 return;
257 ctx.attr[n].map = (uint8_t *)bo->map + vb->buffer_offset + ve->src_offset;
258
259 nouveau_bo_unmap(bo);
260
261 ctx.attr[n].stride = vb->stride;
262 ctx.attr[n].divisor = ve->instance_divisor;
263
264 nr_components = util_format_get_nr_components(ve->src_format);
265 switch (util_format_get_component_bits(ve->src_format,
266 UTIL_FORMAT_COLORSPACE_RGB, 0)) {
267 case 8:
268 switch (nr_components) {
269 case 1: ctx.attr[n].push = emit_b08_1; break;
270 case 2: ctx.attr[n].push = emit_b16_1; break;
271 case 3: ctx.attr[n].push = emit_b08_3; break;
272 case 4: ctx.attr[n].push = emit_b32_1; break;
273 }
274 break;
275 case 16:
276 switch (nr_components) {
277 case 1: ctx.attr[n].push = emit_b16_1; break;
278 case 2: ctx.attr[n].push = emit_b32_1; break;
279 case 3: ctx.attr[n].push = emit_b16_3; break;
280 case 4: ctx.attr[n].push = emit_b32_2; break;
281 }
282 break;
283 case 32:
284 switch (nr_components) {
285 case 1: ctx.attr[n].push = emit_b32_1; break;
286 case 2: ctx.attr[n].push = emit_b32_2; break;
287 case 3: ctx.attr[n].push = emit_b32_3; break;
288 case 4: ctx.attr[n].push = emit_b32_4; break;
289 }
290 break;
291 default:
292 assert(0);
293 break;
294 }
295 }
296
297 if (info->indexed) {
298 struct nvc0_resource *res = nvc0_resource(nvc0->idxbuf.buffer);
299 if (!res || nouveau_bo_map(res->bo, NOUVEAU_BO_RD))
300 return;
301 ctx.idxbuf = res->bo->map;
302 nouveau_bo_unmap(res->bo);
303 ctx.idxsize = nvc0->idxbuf.index_size;
304 } else {
305 ctx.idxsize = 0;
306 }
307
308 while (inst--) {
309 BEGIN_RING(nvc0->screen->base.channel, RING_3D(VERTEX_BEGIN_GL), 1);
310 OUT_RING (nvc0->screen->base.channel, prim);
311 switch (ctx.idxsize) {
312 case 0:
313 emit_seq(&ctx, info->start, info->count);
314 break;
315 case 1:
316 emit_elt08(&ctx, info->start, info->count);
317 break;
318 case 2:
319 emit_elt16(&ctx, info->start, info->count);
320 break;
321 case 4:
322 emit_elt32(&ctx, info->start, info->count);
323 break;
324 }
325 INLIN_RING(nvc0->screen->base.channel, RING_3D(VERTEX_END_GL), 0);
326
327 prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
328 }
329 }