trace: Convert to automake
[mesa.git] / src / gallium / drivers / nv30 / nv30_draw.c
1 /*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 *
24 */
25
26 #include "draw/draw_context.h"
27 #include "draw/draw_vertex.h"
28 #include "draw/draw_pipe.h"
29 #include "draw/draw_vbuf.h"
30 #include "draw/draw_private.h"
31
32 #include "nouveau/nv_object.xml.h"
33 #include "nv30-40_3d.xml.h"
34 #include "nv30_context.h"
35 #include "nv30_format.h"
36
37 struct nv30_render {
38 struct vbuf_render base;
39 struct nv30_context *nv30;
40
41 struct pipe_transfer *transfer;
42 struct pipe_resource *buffer;
43 unsigned offset;
44 unsigned length;
45
46 struct vertex_info vertex_info;
47
48 struct nouveau_heap *vertprog;
49 uint32_t vtxprog[16][4];
50 uint32_t vtxfmt[16];
51 uint32_t vtxptr[16];
52 uint32_t prim;
53 };
54
55 static INLINE struct nv30_render *
56 nv30_render(struct vbuf_render *render)
57 {
58 return (struct nv30_render *)render;
59 }
60
61 static const struct vertex_info *
62 nv30_render_get_vertex_info(struct vbuf_render *render)
63 {
64 return &nv30_render(render)->vertex_info;
65 }
66
67 static boolean
68 nv30_render_allocate_vertices(struct vbuf_render *render,
69 ushort vertex_size, ushort nr_vertices)
70 {
71 struct nv30_render *r = nv30_render(render);
72 struct nv30_context *nv30 = r->nv30;
73
74 r->length = vertex_size * nr_vertices;
75
76 if (r->offset + r->length >= render->max_vertex_buffer_bytes) {
77 pipe_resource_reference(&r->buffer, NULL);
78 r->buffer = pipe_buffer_create(&nv30->screen->base.base,
79 PIPE_BIND_VERTEX_BUFFER, 0,
80 render->max_vertex_buffer_bytes);
81 if (!r->buffer)
82 return FALSE;
83
84 r->offset = 0;
85 }
86
87 return TRUE;
88 }
89
90 static void *
91 nv30_render_map_vertices(struct vbuf_render *render)
92 {
93 struct nv30_render *r = nv30_render(render);
94 char *map = pipe_buffer_map(&r->nv30->base.pipe, r->buffer,
95 PIPE_TRANSFER_WRITE |
96 PIPE_TRANSFER_UNSYNCHRONIZED, &r->transfer);
97 return map + r->offset;
98 }
99
100 static void
101 nv30_render_unmap_vertices(struct vbuf_render *render,
102 ushort min_index, ushort max_index)
103 {
104 struct nv30_render *r = nv30_render(render);
105 pipe_buffer_unmap(&r->nv30->base.pipe, r->transfer);
106 }
107
108 static void
109 nv30_render_set_primitive(struct vbuf_render *render, unsigned prim)
110 {
111 struct nv30_render *r = nv30_render(render);
112
113 r->prim = nv30_prim_gl(prim);
114 }
115
116 static void
117 nv30_render_draw_elements(struct vbuf_render *render,
118 const ushort *indices, uint count)
119 {
120 struct nv30_render *r = nv30_render(render);
121 struct nv30_context *nv30 = r->nv30;
122 struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
123 unsigned i;
124
125 BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
126 for (i = 0; i < r->vertex_info.num_attribs; i++) {
127 PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,
128 nv04_resource(r->buffer), r->offset + r->vtxptr[i],
129 NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
130 }
131
132 if (!nv30_state_validate(nv30, FALSE))
133 return;
134
135 BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
136 PUSH_DATA (push, r->prim);
137
138 if (count & 1) {
139 BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
140 PUSH_DATA (push, *indices++);
141 }
142
143 count >>= 1;
144 while (count) {
145 unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
146 count -= npush;
147
148 BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
149 while (npush--) {
150 PUSH_DATA(push, (indices[1] << 16) | indices[0]);
151 indices += 2;
152 }
153 }
154
155 BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
156 PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
157 PUSH_RESET(push, BUFCTX_VTXTMP);
158 }
159
160 static void
161 nv30_render_draw_arrays(struct vbuf_render *render, unsigned start, uint nr)
162 {
163 struct nv30_render *r = nv30_render(render);
164 struct nv30_context *nv30 = r->nv30;
165 struct nouveau_pushbuf *push = nv30->base.pushbuf;
166 unsigned fn = nr >> 8, pn = nr & 0xff;
167 unsigned ps = fn + (pn ? 1 : 0);
168 unsigned i;
169
170 BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
171 for (i = 0; i < r->vertex_info.num_attribs; i++) {
172 PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,
173 nv04_resource(r->buffer), r->offset + r->vtxptr[i],
174 NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
175 }
176
177 if (!nv30_state_validate(nv30, FALSE))
178 return;
179
180 BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
181 PUSH_DATA (push, r->prim);
182
183 BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), ps);
184 while (fn--) {
185 PUSH_DATA (push, 0xff000000 | start);
186 start += 256;
187 }
188
189 if (pn)
190 PUSH_DATA (push, ((pn - 1) << 24) | start);
191
192 BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
193 PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
194 PUSH_RESET(push, BUFCTX_VTXTMP);
195 }
196
197 static void
198 nv30_render_release_vertices(struct vbuf_render *render)
199 {
200 struct nv30_render *r = nv30_render(render);
201 r->offset += r->length;
202 }
203
204 static const struct {
205 unsigned emit;
206 unsigned interp;
207 unsigned vp30;
208 unsigned vp40;
209 unsigned ow40;
210 } vroute [] = {
211 [TGSI_SEMANTIC_POSITION] = { EMIT_4F, INTERP_PERSPECTIVE, 0, 0, 0x00000000 },
212 [TGSI_SEMANTIC_COLOR ] = { EMIT_4F, INTERP_LINEAR , 3, 1, 0x00000001 },
213 [TGSI_SEMANTIC_BCOLOR ] = { EMIT_4F, INTERP_LINEAR , 1, 3, 0x00000004 },
214 [TGSI_SEMANTIC_FOG ] = { EMIT_4F, INTERP_PERSPECTIVE, 5, 5, 0x00000010 },
215 [TGSI_SEMANTIC_PSIZE ] = { EMIT_1F_PSIZE, INTERP_POS , 6, 6, 0x00000020 },
216 [TGSI_SEMANTIC_GENERIC ] = { EMIT_4F, INTERP_PERSPECTIVE, 8, 7, 0x00004000 }
217 };
218
219 static boolean
220 vroute_add(struct nv30_render *r, uint attrib, uint sem, uint *idx)
221 {
222 struct pipe_screen *pscreen = &r->nv30->screen->base.base;
223 struct nv30_fragprog *fp = r->nv30->fragprog.program;
224 struct vertex_info *vinfo = &r->vertex_info;
225 enum pipe_format format;
226 uint emit = EMIT_OMIT;
227 uint result = *idx;
228
229 if (sem == TGSI_SEMANTIC_GENERIC && result >= 8) {
230 for (result = 0; result < 8; result++) {
231 if (fp->texcoord[result] == *idx) {
232 emit = vroute[sem].emit;
233 break;
234 }
235 }
236 } else {
237 emit = vroute[sem].emit;
238 }
239
240 if (emit == EMIT_OMIT)
241 return FALSE;
242
243 draw_emit_vertex_attr(vinfo, emit, vroute[sem].interp, attrib);
244 format = draw_translate_vinfo_format(emit);
245
246 r->vtxfmt[attrib] = nv30_vtxfmt(pscreen, format)->hw;
247 r->vtxptr[attrib] = vinfo->size | NV30_3D_VTXBUF_DMA1;
248 vinfo->size += draw_translate_vinfo_size(emit);
249
250 if (nv30_screen(pscreen)->eng3d->oclass < NV40_3D_CLASS) {
251 r->vtxprog[attrib][0] = 0x001f38d8;
252 r->vtxprog[attrib][1] = 0x0080001b | (attrib << 9);
253 r->vtxprog[attrib][2] = 0x0836106c;
254 r->vtxprog[attrib][3] = 0x2000f800 | (result + vroute[sem].vp30) << 2;
255 } else {
256 r->vtxprog[attrib][0] = 0x401f9c6c;
257 r->vtxprog[attrib][1] = 0x0040000d | (attrib << 8);
258 r->vtxprog[attrib][2] = 0x8106c083;
259 r->vtxprog[attrib][3] = 0x6041ff80 | (result + vroute[sem].vp40) << 2;
260 }
261
262 *idx = vroute[sem].ow40 << result;
263 return TRUE;
264 }
265
266 static boolean
267 nv30_render_validate(struct nv30_context *nv30)
268 {
269 struct nv30_render *r = nv30_render(nv30->draw->render);
270 struct nv30_rasterizer_stateobj *rast = nv30->rast;
271 struct pipe_screen *pscreen = &nv30->screen->base.base;
272 struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
273 struct nouveau_object *eng3d = nv30->screen->eng3d;
274 struct nv30_vertprog *vp = nv30->vertprog.program;
275 struct vertex_info *vinfo = &r->vertex_info;
276 unsigned vp_attribs = 0;
277 unsigned vp_results = 0;
278 unsigned attrib = 0;
279 unsigned pntc;
280 int i;
281
282 if (!r->vertprog) {
283 struct nouveau_heap *heap = nv30_screen(pscreen)->vp_exec_heap;
284 if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog)) {
285 while (heap->next && heap->size < 16) {
286 struct nouveau_heap **evict = heap->next->priv;
287 nouveau_heap_free(evict);
288 }
289
290 if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog))
291 return FALSE;
292 }
293 }
294
295 vinfo->num_attribs = 0;
296 vinfo->size = 0;
297
298 /* setup routing for all necessary vp outputs */
299 for (i = 0; i < vp->info.num_outputs && attrib < 16; i++) {
300 uint semantic = vp->info.output_semantic_name[i];
301 uint index = vp->info.output_semantic_index[i];
302 if (vroute_add(r, attrib, semantic, &index)) {
303 vp_attribs |= (1 << attrib++);
304 vp_results |= index;
305 }
306 }
307
308 /* setup routing for replaced point coords not written by vp */
309 if (rast && rast->pipe.point_quad_rasterization)
310 pntc = rast->pipe.sprite_coord_enable & 0x000002ff;
311 else
312 pntc = 0;
313
314 while (pntc && attrib < 16) {
315 uint index = ffs(pntc) - 1; pntc &= ~(1 << index);
316 if (vroute_add(r, attrib, TGSI_SEMANTIC_GENERIC, &index)) {
317 vp_attribs |= (1 << attrib++);
318 vp_results |= index;
319 }
320 }
321
322 /* modify vertex format for correct stride, and stub out unused ones */
323 BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1);
324 PUSH_DATA (push, r->vertprog->start);
325 r->vtxprog[attrib - 1][3] |= 1;
326 for (i = 0; i < attrib; i++) {
327 BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);
328 PUSH_DATAp(push, r->vtxprog[i], 4);
329 r->vtxfmt[i] |= vinfo->size << 8;
330 }
331 for (; i < 16; i++)
332 r->vtxfmt[i] = NV30_3D_VTXFMT_TYPE_V32_FLOAT;
333
334 BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
335 PUSH_DATAf(push, 0.0);
336 PUSH_DATAf(push, 0.0);
337 PUSH_DATAf(push, 0.0);
338 PUSH_DATAf(push, 0.0);
339 PUSH_DATAf(push, 1.0);
340 PUSH_DATAf(push, 1.0);
341 PUSH_DATAf(push, 1.0);
342 PUSH_DATAf(push, 1.0);
343 BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
344 PUSH_DATAf(push, 0.0);
345 PUSH_DATAf(push, 1.0);
346
347 BEGIN_NV04(push, NV30_3D(VTXFMT(0)), 16);
348 PUSH_DATAp(push, r->vtxfmt, 16);
349
350 BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);
351 PUSH_DATA (push, r->vertprog->start);
352 BEGIN_NV04(push, NV30_3D(ENGINE), 1);
353 PUSH_DATA (push, 0x00000103);
354 if (eng3d->oclass >= NV40_3D_CLASS) {
355 BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);
356 PUSH_DATA (push, vp_attribs);
357 PUSH_DATA (push, vp_results);
358 }
359
360 vinfo->size /= 4;
361 return TRUE;
362 }
363
364 void
365 nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
366 {
367 struct nv30_context *nv30 = nv30_context(pipe);
368 struct draw_context *draw = nv30->draw;
369 struct pipe_transfer *transfer[PIPE_MAX_ATTRIBS] = {NULL};
370 struct pipe_transfer *transferi = NULL;
371 int i;
372
373 nv30_render_validate(nv30);
374
375 if (nv30->draw_dirty & NV30_NEW_VIEWPORT)
376 draw_set_viewport_state(draw, &nv30->viewport);
377 if (nv30->draw_dirty & NV30_NEW_RASTERIZER)
378 draw_set_rasterizer_state(draw, &nv30->rast->pipe, NULL);
379 if (nv30->draw_dirty & NV30_NEW_CLIP)
380 draw_set_clip_state(draw, &nv30->clip);
381 if (nv30->draw_dirty & NV30_NEW_ARRAYS) {
382 draw_set_vertex_buffers(draw, 0, nv30->num_vtxbufs, nv30->vtxbuf);
383 draw_set_vertex_elements(draw, nv30->vertex->num_elements, nv30->vertex->pipe);
384 }
385 if (nv30->draw_dirty & NV30_NEW_FRAGPROG) {
386 struct nv30_fragprog *fp = nv30->fragprog.program;
387 if (!fp->draw)
388 fp->draw = draw_create_fragment_shader(draw, &fp->pipe);
389 draw_bind_fragment_shader(draw, fp->draw);
390 }
391 if (nv30->draw_dirty & NV30_NEW_VERTPROG) {
392 struct nv30_vertprog *vp = nv30->vertprog.program;
393 if (!vp->draw)
394 vp->draw = draw_create_vertex_shader(draw, &vp->pipe);
395 draw_bind_vertex_shader(draw, vp->draw);
396 }
397 if (nv30->draw_dirty & NV30_NEW_VERTCONST) {
398 if (nv30->vertprog.constbuf) {
399 void *map = nv04_resource(nv30->vertprog.constbuf)->data;
400 draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0,
401 map, nv30->vertprog.constbuf_nr);
402 }
403 }
404
405 for (i = 0; i < nv30->num_vtxbufs; i++) {
406 const void *map = nv30->vtxbuf[i].user_buffer;
407 if (!map) {
408 if (!nv30->vtxbuf[i].buffer) {
409 continue;
410 }
411 map = pipe_buffer_map(pipe, nv30->vtxbuf[i].buffer,
412 PIPE_TRANSFER_UNSYNCHRONIZED |
413 PIPE_TRANSFER_READ, &transfer[i]);
414 }
415 draw_set_mapped_vertex_buffer(draw, i, map);
416 }
417
418 if (info->indexed) {
419 const void *map = nv30->idxbuf.user_buffer;
420 if (!map)
421 pipe_buffer_map(pipe, nv30->idxbuf.buffer,
422 PIPE_TRANSFER_UNSYNCHRONIZED |
423 PIPE_TRANSFER_READ, &transferi);
424 draw_set_indexes(draw,
425 (ubyte *) map + nv30->idxbuf.offset,
426 nv30->idxbuf.index_size);
427 } else {
428 draw_set_indexes(draw, NULL, 0);
429 }
430
431 draw_vbo(draw, info);
432 draw_flush(draw);
433
434 if (info->indexed && transferi)
435 pipe_buffer_unmap(pipe, transferi);
436 for (i = 0; i < nv30->num_vtxbufs; i++)
437 if (transfer[i])
438 pipe_buffer_unmap(pipe, transfer[i]);
439
440 nv30->draw_dirty = 0;
441 nv30_state_release(nv30);
442 }
443
444 static void
445 nv30_render_destroy(struct vbuf_render *render)
446 {
447 FREE(render);
448 }
449
450 static struct vbuf_render *
451 nv30_render_create(struct nv30_context *nv30)
452 {
453 struct nv30_render *r = CALLOC_STRUCT(nv30_render);
454 if (!r)
455 return NULL;
456
457 r->nv30 = nv30;
458 r->offset = 1 * 1024 * 1024;
459
460 r->base.max_indices = 16 * 1024;
461 r->base.max_vertex_buffer_bytes = r->offset;
462
463 r->base.get_vertex_info = nv30_render_get_vertex_info;
464 r->base.allocate_vertices = nv30_render_allocate_vertices;
465 r->base.map_vertices = nv30_render_map_vertices;
466 r->base.unmap_vertices = nv30_render_unmap_vertices;
467 r->base.set_primitive = nv30_render_set_primitive;
468 r->base.draw_elements = nv30_render_draw_elements;
469 r->base.draw_arrays = nv30_render_draw_arrays;
470 r->base.release_vertices = nv30_render_release_vertices;
471 r->base.destroy = nv30_render_destroy;
472 return &r->base;
473 }
474
475 void
476 nv30_draw_init(struct pipe_context *pipe)
477 {
478 struct nv30_context *nv30 = nv30_context(pipe);
479 struct vbuf_render *render;
480 struct draw_context *draw;
481 struct draw_stage *stage;
482
483 draw = draw_create(pipe);
484 if (!draw)
485 return;
486
487 render = nv30_render_create(nv30);
488 if (!render) {
489 draw_destroy(draw);
490 return;
491 }
492
493 stage = draw_vbuf_stage(draw, render);
494 if (!stage) {
495 render->destroy(render);
496 draw_destroy(draw);
497 return;
498 }
499
500 draw_set_render(draw, render);
501 draw_set_rasterize_stage(draw, stage);
502 draw_wide_line_threshold(draw, 10000000.f);
503 draw_wide_point_threshold(draw, 10000000.f);
504 draw_wide_point_sprites(draw, TRUE);
505 nv30->draw = draw;
506 }