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