xref: /aosp_15_r20/external/virglrenderer/src/gallium/auxiliary/util/u_prim.h (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
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/u_debug.h"
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 struct u_prim_vertex_count {
41    unsigned min;
42    unsigned incr;
43 };
44 
45 /**
46  * Decompose a primitive that is a loop, a strip, or a fan.  Return the
47  * original primitive if it is already decomposed.
48  */
49 static inline unsigned
u_decomposed_prim(unsigned prim)50 u_decomposed_prim(unsigned prim)
51 {
52    switch (prim) {
53    case PIPE_PRIM_LINE_LOOP:
54    case PIPE_PRIM_LINE_STRIP:
55       return PIPE_PRIM_LINES;
56    case PIPE_PRIM_TRIANGLE_STRIP:
57    case PIPE_PRIM_TRIANGLE_FAN:
58       return PIPE_PRIM_TRIANGLES;
59    case PIPE_PRIM_QUAD_STRIP:
60       return PIPE_PRIM_QUADS;
61    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
62       return PIPE_PRIM_LINES_ADJACENCY;
63    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
64       return PIPE_PRIM_TRIANGLES_ADJACENCY;
65    default:
66       return prim;
67    }
68 }
69 
70 /**
71  * Reduce a primitive to one of PIPE_PRIM_POINTS, PIPE_PRIM_LINES, and
72  * PIPE_PRIM_TRIANGLES.
73  */
74 static inline unsigned
u_reduced_prim(unsigned prim)75 u_reduced_prim(unsigned prim)
76 {
77    switch (prim) {
78    case PIPE_PRIM_POINTS:
79       return PIPE_PRIM_POINTS;
80    case PIPE_PRIM_LINES:
81    case PIPE_PRIM_LINE_LOOP:
82    case PIPE_PRIM_LINE_STRIP:
83    case PIPE_PRIM_LINES_ADJACENCY:
84    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
85       return PIPE_PRIM_LINES;
86    default:
87       return PIPE_PRIM_TRIANGLES;
88    }
89 }
90 
91 /**
92  * Re-assemble a primitive to remove its adjacency.
93  */
94 static inline unsigned
u_assembled_prim(unsigned prim)95 u_assembled_prim(unsigned prim)
96 {
97    switch (prim) {
98    case PIPE_PRIM_LINES_ADJACENCY:
99    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
100       return PIPE_PRIM_LINES;
101    case PIPE_PRIM_TRIANGLES_ADJACENCY:
102    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
103       return PIPE_PRIM_TRIANGLES;
104    default:
105       return prim;
106    }
107 }
108 
109 /**
110  * Return the vertex count information for a primitive.
111  *
112  * Note that if this function is called directly or indirectly anywhere in a
113  * source file, it will increase the size of the binary slightly more than
114  * expected because of the use of a table.
115  */
116 static inline const struct u_prim_vertex_count *
u_prim_vertex_count(unsigned prim)117 u_prim_vertex_count(unsigned prim)
118 {
119    static const struct u_prim_vertex_count prim_table[PIPE_PRIM_MAX] = {
120       { 1, 1 }, /* PIPE_PRIM_POINTS */
121       { 2, 2 }, /* PIPE_PRIM_LINES */
122       { 2, 1 }, /* PIPE_PRIM_LINE_LOOP */
123       { 2, 1 }, /* PIPE_PRIM_LINE_STRIP */
124       { 3, 3 }, /* PIPE_PRIM_TRIANGLES */
125       { 3, 1 }, /* PIPE_PRIM_TRIANGLE_STRIP */
126       { 3, 1 }, /* PIPE_PRIM_TRIANGLE_FAN */
127       { 4, 4 }, /* PIPE_PRIM_QUADS */
128       { 4, 2 }, /* PIPE_PRIM_QUAD_STRIP */
129       { 3, 1 }, /* PIPE_PRIM_POLYGON */
130       { 4, 4 }, /* PIPE_PRIM_LINES_ADJACENCY */
131       { 4, 1 }, /* PIPE_PRIM_LINE_STRIP_ADJACENCY */
132       { 6, 6 }, /* PIPE_PRIM_TRIANGLES_ADJACENCY */
133       { 6, 2 }, /* PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY */
134    };
135 
136    return (likely(prim < PIPE_PRIM_MAX)) ? &prim_table[prim] : NULL;
137 }
138 
u_validate_pipe_prim(unsigned pipe_prim,unsigned nr)139 static inline boolean u_validate_pipe_prim( unsigned pipe_prim, unsigned nr )
140 {
141    const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
142 
143    return (count && nr >= count->min);
144 }
145 
146 
u_trim_pipe_prim(unsigned pipe_prim,unsigned * nr)147 static inline boolean u_trim_pipe_prim( unsigned pipe_prim, unsigned *nr )
148 {
149    const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
150 
151    if (count && *nr >= count->min) {
152       if (count->incr > 1)
153          *nr -= (*nr % count->incr);
154       return TRUE;
155    }
156    else {
157       *nr = 0;
158       return FALSE;
159    }
160 }
161 
162 static inline unsigned
u_vertices_per_prim(int primitive)163 u_vertices_per_prim(int primitive)
164 {
165    switch(primitive) {
166    case PIPE_PRIM_POINTS:
167       return 1;
168    case PIPE_PRIM_LINES:
169    case PIPE_PRIM_LINE_LOOP:
170    case PIPE_PRIM_LINE_STRIP:
171       return 2;
172    case PIPE_PRIM_TRIANGLES:
173    case PIPE_PRIM_TRIANGLE_STRIP:
174    case PIPE_PRIM_TRIANGLE_FAN:
175       return 3;
176    case PIPE_PRIM_LINES_ADJACENCY:
177    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
178       return 4;
179    case PIPE_PRIM_TRIANGLES_ADJACENCY:
180    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
181       return 6;
182 
183    /* following primitives should never be used
184     * with geometry shaders abd their size is
185     * undefined */
186    case PIPE_PRIM_POLYGON:
187    case PIPE_PRIM_QUADS:
188    case PIPE_PRIM_QUAD_STRIP:
189    default:
190       debug_printf("Unrecognized geometry shader primitive");
191       return 3;
192    }
193 }
194 
195 /**
196  * Returns the number of decomposed primitives for the given
197  * vertex count.
198  * Parts of the pipline are invoked once for each triangle in
199  * triangle strip, triangle fans and triangles and once
200  * for each line in line strip, line loop, lines. Also
201  * statistics depend on knowing the exact number of decomposed
202  * primitives for a set of vertices.
203  */
204 static inline unsigned
u_decomposed_prims_for_vertices(int primitive,int vertices)205 u_decomposed_prims_for_vertices(int primitive, int vertices)
206 {
207    switch (primitive) {
208    case PIPE_PRIM_POINTS:
209       return vertices;
210    case PIPE_PRIM_LINES:
211       return vertices / 2;
212    case PIPE_PRIM_LINE_LOOP:
213       return (vertices >= 2) ? vertices : 0;
214    case PIPE_PRIM_LINE_STRIP:
215       return (vertices >= 2) ? vertices - 1 : 0;
216    case PIPE_PRIM_TRIANGLES:
217       return vertices / 3;
218    case PIPE_PRIM_TRIANGLE_STRIP:
219       return (vertices >= 3) ? vertices - 2 : 0;
220    case PIPE_PRIM_TRIANGLE_FAN:
221       return (vertices >= 3) ? vertices - 2 : 0;
222    case PIPE_PRIM_LINES_ADJACENCY:
223       return vertices / 4;
224    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
225       return (vertices >= 4) ? vertices - 3 : 0;
226    case PIPE_PRIM_TRIANGLES_ADJACENCY:
227       return vertices / 6;
228    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
229       return (vertices >= 6) ? 1 + (vertices - 6) / 2 : 0;
230    case PIPE_PRIM_QUADS:
231       return vertices / 4;
232    case PIPE_PRIM_QUAD_STRIP:
233       return (vertices >= 4) ? (vertices - 2) / 2 : 0;
234    /* Polygons can't be decomposed
235     * because the number of their vertices isn't known so
236     * for them and whatever else we don't recognize just
237     * return 1 if the number of vertices is greater than
238     * or equal to 3 and zero otherwise */
239    case PIPE_PRIM_POLYGON:
240    default:
241       debug_printf("Invalid decomposition primitive!\n");
242       return (vertices >= 3) ? 1 : 0;
243    }
244 }
245 
246 /**
247  * Returns the number of reduced/tessellated primitives for the given vertex
248  * count.  Each quad is treated as two triangles.  Polygons are treated as
249  * triangle fans.
250  */
251 static inline unsigned
u_reduced_prims_for_vertices(int primitive,int vertices)252 u_reduced_prims_for_vertices(int primitive, int vertices)
253 {
254    switch (primitive) {
255    case PIPE_PRIM_QUADS:
256    case PIPE_PRIM_QUAD_STRIP:
257       return u_decomposed_prims_for_vertices(primitive, vertices) * 2;
258    case PIPE_PRIM_POLYGON:
259       primitive = PIPE_PRIM_TRIANGLE_FAN;
260       /* fall through */
261    default:
262       return u_decomposed_prims_for_vertices(primitive, vertices);
263    }
264 }
265 
266 const char *u_prim_name( unsigned pipe_prim );
267 
268 #endif
269