xref: /aosp_15_r20/external/mesa3d/src/gallium/auxiliary/util/u_prim.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 2008 VMware, Inc.
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
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 
29 #ifndef U_PRIM_H
30 #define U_PRIM_H
31 
32 
33 #include "pipe/p_defines.h"
34 #include "util/compiler.h"
35 #include "util/u_debug.h"
36 #include "compiler/shader_enums.h"
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 struct u_prim_vertex_count {
43    unsigned min;
44    unsigned incr;
45 };
46 
47 /**
48  * Re-assemble a primitive to remove its adjacency.
49  */
50 static inline enum mesa_prim
u_assembled_prim(enum mesa_prim prim)51 u_assembled_prim(enum mesa_prim prim)
52 {
53    switch (prim) {
54    case MESA_PRIM_LINES_ADJACENCY:
55    case MESA_PRIM_LINE_STRIP_ADJACENCY:
56       return MESA_PRIM_LINES;
57    case MESA_PRIM_TRIANGLES_ADJACENCY:
58    case MESA_PRIM_TRIANGLE_STRIP_ADJACENCY:
59       return MESA_PRIM_TRIANGLES;
60    default:
61       return prim;
62    }
63 }
64 
65 /**
66  * Return the vertex count information for a primitive.
67  *
68  * Note that if this function is called directly or indirectly anywhere in a
69  * source file, it will increase the size of the binary slightly more than
70  * expected because of the use of a table.
71  */
72 static inline const struct u_prim_vertex_count *
u_prim_vertex_count(enum mesa_prim prim)73 u_prim_vertex_count(enum mesa_prim prim)
74 {
75    static const struct u_prim_vertex_count prim_table[MESA_PRIM_COUNT] = {
76       { 1, 1 }, /* MESA_PRIM_POINTS */
77       { 2, 2 }, /* MESA_PRIM_LINES */
78       { 2, 1 }, /* MESA_PRIM_LINE_LOOP */
79       { 2, 1 }, /* MESA_PRIM_LINE_STRIP */
80       { 3, 3 }, /* MESA_PRIM_TRIANGLES */
81       { 3, 1 }, /* MESA_PRIM_TRIANGLE_STRIP */
82       { 3, 1 }, /* MESA_PRIM_TRIANGLE_FAN */
83       { 4, 4 }, /* MESA_PRIM_QUADS */
84       { 4, 2 }, /* MESA_PRIM_QUAD_STRIP */
85       { 3, 1 }, /* MESA_PRIM_POLYGON */
86       { 4, 4 }, /* MESA_PRIM_LINES_ADJACENCY */
87       { 4, 1 }, /* MESA_PRIM_LINE_STRIP_ADJACENCY */
88       { 6, 6 }, /* MESA_PRIM_TRIANGLES_ADJACENCY */
89       { 6, 2 }, /* MESA_PRIM_TRIANGLE_STRIP_ADJACENCY */
90    };
91 
92    return (likely(prim < MESA_PRIM_COUNT)) ? &prim_table[prim] : NULL;
93 }
94 
95 /**
96  * Given a vertex count, return the number of primitives.
97  * For polygons, return the number of triangles.
98  */
99 static inline unsigned
u_prims_for_vertices(enum mesa_prim prim,unsigned num)100 u_prims_for_vertices(enum mesa_prim prim, unsigned num)
101 {
102    const struct u_prim_vertex_count *info = u_prim_vertex_count(prim);
103 
104    assert(info);
105    assert(info->incr != 0);
106 
107    if (num < info->min)
108       return 0;
109 
110    return 1 + ((num - info->min) / info->incr);
111 }
112 
113 static inline bool
u_validate_pipe_prim(enum mesa_prim pipe_prim,unsigned nr)114 u_validate_pipe_prim(enum mesa_prim pipe_prim, unsigned nr)
115 {
116    const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
117 
118    return (count && nr >= count->min);
119 }
120 
121 
122 static inline bool
u_trim_pipe_prim(enum mesa_prim pipe_prim,unsigned * nr)123 u_trim_pipe_prim(enum mesa_prim pipe_prim, unsigned *nr)
124 {
125    const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
126 
127    if (count && *nr >= count->min) {
128       if (count->incr > 1)
129          *nr -= (*nr % count->incr);
130       return true;
131    }
132    else {
133       *nr = 0;
134       return false;
135    }
136 }
137 
138 
139 /**
140  * Returns the number of reduced/tessellated primitives for the given vertex
141  * count.  Each quad is treated as two triangles.  Polygons are treated as
142  * triangle fans.
143  */
144 static inline unsigned
u_reduced_prims_for_vertices(enum mesa_prim primitive,int vertices)145 u_reduced_prims_for_vertices(enum mesa_prim primitive, int vertices)
146 {
147    switch (primitive) {
148    case MESA_PRIM_QUADS:
149    case MESA_PRIM_QUAD_STRIP:
150       return u_decomposed_prims_for_vertices(primitive, vertices) * 2;
151    case MESA_PRIM_POLYGON:
152       primitive = MESA_PRIM_TRIANGLE_FAN;
153       FALLTHROUGH;
154    default:
155       return u_decomposed_prims_for_vertices(primitive, vertices);
156    }
157 }
158 
159 static inline enum mesa_prim
u_base_prim_type(enum mesa_prim prim_type)160 u_base_prim_type(enum mesa_prim prim_type)
161 {
162    switch(prim_type) {
163       case MESA_PRIM_POINTS:
164          return MESA_PRIM_POINTS;
165       case MESA_PRIM_LINES:
166       case MESA_PRIM_LINE_LOOP:
167       case MESA_PRIM_LINE_STRIP:
168       case MESA_PRIM_LINES_ADJACENCY:
169       case MESA_PRIM_LINE_STRIP_ADJACENCY:
170          return MESA_PRIM_LINES;
171       case MESA_PRIM_TRIANGLES:
172       case MESA_PRIM_TRIANGLE_STRIP:
173       case MESA_PRIM_TRIANGLE_FAN:
174       case MESA_PRIM_TRIANGLES_ADJACENCY:
175       case MESA_PRIM_TRIANGLE_STRIP_ADJACENCY:
176          return MESA_PRIM_TRIANGLES;
177       case MESA_PRIM_QUADS:
178       case MESA_PRIM_QUAD_STRIP:
179          return MESA_PRIM_QUADS;
180       default:
181          return prim_type;
182    }
183 }
184 
185 static inline enum mesa_prim
u_tess_prim_from_shader(enum tess_primitive_mode shader_mode)186 u_tess_prim_from_shader(enum tess_primitive_mode shader_mode)
187 {
188    switch (shader_mode) {
189    case TESS_PRIMITIVE_TRIANGLES:
190       return MESA_PRIM_TRIANGLES;
191    case TESS_PRIMITIVE_QUADS:
192       return MESA_PRIM_QUADS;
193    case TESS_PRIMITIVE_ISOLINES:
194       return MESA_PRIM_LINES;
195    default:
196       return MESA_PRIM_POINTS;
197    }
198 }
199 
200 static inline unsigned
u_vertices_for_prims(enum mesa_prim prim_type,int count)201 u_vertices_for_prims(enum mesa_prim prim_type, int count)
202 {
203    if (count <= 0)
204       return 0;
205 
206    /* We can only figure out the number of vertices from a number of primitives
207     * if we are using basic primitives (so no loops, strips, fans, etc).
208     */
209    assert(prim_type == u_base_prim_type(prim_type) &&
210           prim_type != MESA_PRIM_PATCHES && prim_type != MESA_PRIM_POLYGON);
211 
212    const struct u_prim_vertex_count *info = u_prim_vertex_count(prim_type);
213    assert(info);
214 
215    return info->min + (count - 1) * info->incr;
216 }
217 
218 /**
219  * Returns the number of stream out outputs for a given number of vertices and
220  * primitive type.
221  */
222 
223 static inline unsigned
u_stream_outputs_for_vertices(enum mesa_prim primitive,unsigned nr)224 u_stream_outputs_for_vertices(enum mesa_prim primitive, unsigned nr)
225 {
226    /* Extraneous vertices don't contribute to stream outputs */
227    u_trim_pipe_prim(primitive, &nr);
228 
229    /* Polygons are special, since they are a single primitive with many
230     * vertices. In this case, we just have an output for each vertex (after
231     * trimming) */
232 
233    if (primitive == MESA_PRIM_POLYGON)
234       return nr;
235 
236    /* Normally, consider how many primitives are actually generated */
237    unsigned prims = u_decomposed_prims_for_vertices(primitive, nr);
238 
239    /* One output per vertex after decomposition */
240    enum mesa_prim base = u_base_prim_type(primitive);
241 
242    /* The GL 4.6 compatibility spec says
243     *
244     *    When quads and polygons are provided to transform feedback with a
245     *    primitive mode of TRIANGLES, they will be tessellated and recorded as
246     *    triangles (the order of tessellation within a primitive is undefined)
247     *
248     * Further, quads and polygons are always provided as TRIANGLES. So
249     * tessellate quads into triangles.
250     */
251    if (base == MESA_PRIM_QUADS) {
252       base = MESA_PRIM_TRIANGLES;
253       prims *= 2;
254    }
255 
256    return u_vertices_for_prims(base, prims);
257 }
258 
259 const char *u_prim_name(enum mesa_prim pipe_prim);
260 
261 
262 #ifdef __cplusplus
263 }
264 #endif
265 
266 
267 #endif
268