xref: /aosp_15_r20/external/mesa3d/src/gallium/auxiliary/draw/draw_mesh_prim.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 2023 Red Hat.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  **************************************************************************/
25 
26 /*
27  * Mesh primitive assembler
28  *
29  * This takes vertex and per-primitive data, and assembles a linear set
30  * of draw compatible vertices.
31  */
32 #include "draw_mesh_prim.h"
33 
34 #include "draw/draw_context.h"
35 #include "draw/draw_private.h"
36 #include "util/u_debug.h"
37 #include "util/u_memory.h"
38 
39 #include "pipe/p_defines.h"
40 
41 struct draw_mesh_prim
42 {
43    struct draw_context *draw;
44 
45    struct draw_prim_info *output_prims;
46    struct draw_vertex_info *output_verts;
47 
48    const struct draw_prim_info *input_prims;
49    const struct draw_vertex_info *input_verts;
50 
51    unsigned num_prims;
52    const char *per_prim;
53    uint32_t num_per_prim;
54    uint32_t added_prim_size;
55    int cull_prim_idx;
56 };
57 
58 static void
add_prim(struct draw_mesh_prim * asmblr,unsigned length)59 add_prim(struct draw_mesh_prim *asmblr, unsigned length)
60 {
61    struct draw_prim_info *output_prims = asmblr->output_prims;
62 
63    output_prims->primitive_lengths = realloc(output_prims->primitive_lengths, sizeof(unsigned) * (output_prims->primitive_count + 1));
64    output_prims->primitive_lengths[output_prims->primitive_count] = length;
65    output_prims->primitive_count++;
66 }
67 
68 
69 /*
70  * Copy the vertex header along with its data from the current
71  * vertex buffer into a buffer holding vertices arranged
72  * into decomposed primitives (i.e. buffer without the
73  * adjacency vertices)
74  */
75 static void
copy_verts(struct draw_mesh_prim * asmblr,unsigned * indices,unsigned num_indices)76 copy_verts(struct draw_mesh_prim *asmblr,
77            unsigned *indices, unsigned num_indices)
78 {
79    char *output = (char*)asmblr->output_verts->verts;
80    const char *input = (const char*)asmblr->input_verts->verts;
81 
82    for (unsigned i = 0; i < num_indices; ++i) {
83       unsigned idx = indices[i];
84       unsigned output_offset =
85          asmblr->output_verts->count * asmblr->output_verts->stride;
86       unsigned input_offset = asmblr->input_verts->stride * idx;
87       memcpy(output + output_offset, input + input_offset,
88              asmblr->input_verts->vertex_size);
89 
90       memcpy(output + output_offset + asmblr->input_verts->vertex_size,
91              asmblr->per_prim + (asmblr->num_prims * asmblr->added_prim_size * 8),
92              asmblr->added_prim_size);
93       asmblr->output_verts->count += 1;
94    }
95    ++asmblr->num_prims;
96 }
97 
98 static bool
cull_prim(struct draw_mesh_prim * asmblr)99 cull_prim(struct draw_mesh_prim *asmblr)
100 {
101    if (asmblr->cull_prim_idx == -1)
102       return false;
103 
104    const uint32_t *cull_prim_ptr = (uint32_t *)(asmblr->per_prim + (asmblr->num_prims * asmblr->added_prim_size * 8));
105    cull_prim_ptr += (asmblr->cull_prim_idx * 4);
106 
107    return (*cull_prim_ptr) ? true : false;
108 }
109 
110 
111 static void
prim_point(struct draw_mesh_prim * asmblr,unsigned idx)112 prim_point(struct draw_mesh_prim *asmblr,
113            unsigned idx)
114 {
115    unsigned indices[1];
116 
117    indices[0] = idx;
118 
119    if (cull_prim(asmblr)) {
120       ++asmblr->num_prims;
121       return;
122    }
123    add_prim(asmblr, 1);
124    copy_verts(asmblr, indices, 1);
125 }
126 
127 
128 static void
prim_line(struct draw_mesh_prim * asmblr,unsigned i0,unsigned i1)129 prim_line(struct draw_mesh_prim *asmblr,
130           unsigned i0, unsigned i1)
131 {
132    unsigned indices[2];
133 
134    indices[0] = i0;
135    indices[1] = i1;
136 
137    if (cull_prim(asmblr)) {
138       ++asmblr->num_prims;
139       return;
140    }
141    add_prim(asmblr, 2);
142    copy_verts(asmblr, indices, 2);
143 }
144 
145 
146 static void
prim_tri(struct draw_mesh_prim * asmblr,unsigned i0,unsigned i1,unsigned i2)147 prim_tri(struct draw_mesh_prim *asmblr,
148          unsigned i0, unsigned i1, unsigned i2)
149 {
150    unsigned indices[3];
151 
152    indices[0] = i0;
153    indices[1] = i1;
154    indices[2] = i2;
155 
156    if (cull_prim(asmblr)) {
157       ++asmblr->num_prims;
158       return;
159    }
160    add_prim(asmblr, 3);
161    copy_verts(asmblr, indices, 3);
162 }
163 
164 
165 #define FUNC assembler_run_linear
166 #define GET_ELT(idx) (start + (idx))
167 #include "draw_mesh_prim_tmp.h"
168 
169 #define FUNC assembler_run_elts
170 #define LOCAL_VARS   const uint16_t *elts = input_prims->elts;
171 #define GET_ELT(idx) (elts[start + (idx)])
172 #include "draw_mesh_prim_tmp.h"
173 
174 
175 void
draw_mesh_prim_run(struct draw_context * draw,unsigned num_per_prim_inputs,void * per_prim_inputs,int cull_prim_idx,const struct draw_prim_info * input_prims,const struct draw_vertex_info * input_verts,struct draw_prim_info * output_prims,struct draw_vertex_info * output_verts)176 draw_mesh_prim_run(struct draw_context *draw,
177                    unsigned num_per_prim_inputs,
178                    void *per_prim_inputs,
179                    int cull_prim_idx,
180                    const struct draw_prim_info *input_prims,
181                    const struct draw_vertex_info *input_verts,
182                    struct draw_prim_info *output_prims,
183                    struct draw_vertex_info *output_verts)
184 {
185    struct draw_mesh_prim asmblr_mesh;
186    struct draw_mesh_prim *asmblr = &asmblr_mesh;
187    unsigned start, i;
188    unsigned max_primitives = input_prims->primitive_count;
189    unsigned max_verts = mesa_vertices_per_prim(input_prims->prim) * max_primitives;
190 
191    asmblr->output_prims = output_prims;
192    asmblr->output_verts = output_verts;
193    asmblr->input_prims = input_prims;
194    asmblr->input_verts = input_verts;
195    asmblr->num_prims = 0;
196    asmblr->num_per_prim = num_per_prim_inputs;
197    asmblr->per_prim = per_prim_inputs;
198    asmblr->cull_prim_idx = cull_prim_idx;
199 
200    output_prims->linear = true;
201    output_prims->elts = NULL;
202    output_prims->start = 0;
203    output_prims->prim = input_prims->prim;
204    output_prims->flags = 0x0;
205    output_prims->primitive_lengths = MALLOC(sizeof(unsigned));
206    output_prims->primitive_lengths[0] = 0;
207    output_prims->primitive_count = 0;
208 
209    asmblr->added_prim_size = asmblr->num_per_prim * (4 * sizeof(float));
210    output_verts->vertex_size = input_verts->vertex_size + asmblr->added_prim_size;
211    output_verts->stride = output_verts->vertex_size;
212    output_verts->verts = (struct vertex_header*)MALLOC(
213       output_verts->vertex_size * max_verts);
214    output_verts->count = 0;
215 
216    for (start = i = 0; i < input_prims->primitive_count;
217         start += input_prims->primitive_lengths[i], i++) {
218       unsigned count = input_prims->primitive_lengths[i];
219       if (input_prims->linear) {
220          assembler_run_linear(asmblr, input_prims, input_verts,
221                               start, count);
222       } else {
223          assembler_run_elts(asmblr, input_prims, input_verts,
224                             start, count);
225       }
226    }
227 
228    output_prims->count = output_verts->count;
229 }
230