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 * Reduce a primitive to one of MESA_PRIM_POINTS, MESA_PRIM_LINES, and
49 * MESA_PRIM_TRIANGLES.
50 */
51 static inline enum mesa_prim
u_reduced_prim(enum mesa_prim prim)52 u_reduced_prim(enum mesa_prim prim)
53 {
54 switch (prim) {
55 case MESA_PRIM_POINTS:
56 return MESA_PRIM_POINTS;
57 case MESA_PRIM_LINES:
58 case MESA_PRIM_LINE_LOOP:
59 case MESA_PRIM_LINE_STRIP:
60 case MESA_PRIM_LINES_ADJACENCY:
61 case MESA_PRIM_LINE_STRIP_ADJACENCY:
62 return MESA_PRIM_LINES;
63 default:
64 return MESA_PRIM_TRIANGLES;
65 }
66 }
67
68 /**
69 * Re-assemble a primitive to remove its adjacency.
70 */
71 static inline enum mesa_prim
u_assembled_prim(enum mesa_prim prim)72 u_assembled_prim(enum mesa_prim prim)
73 {
74 switch (prim) {
75 case MESA_PRIM_LINES_ADJACENCY:
76 case MESA_PRIM_LINE_STRIP_ADJACENCY:
77 return MESA_PRIM_LINES;
78 case MESA_PRIM_TRIANGLES_ADJACENCY:
79 case MESA_PRIM_TRIANGLE_STRIP_ADJACENCY:
80 return MESA_PRIM_TRIANGLES;
81 default:
82 return prim;
83 }
84 }
85
86 /**
87 * Return the vertex count information for a primitive.
88 *
89 * Note that if this function is called directly or indirectly anywhere in a
90 * source file, it will increase the size of the binary slightly more than
91 * expected because of the use of a table.
92 */
93 static inline const struct u_prim_vertex_count *
u_prim_vertex_count(enum mesa_prim prim)94 u_prim_vertex_count(enum mesa_prim prim)
95 {
96 static const struct u_prim_vertex_count prim_table[MESA_PRIM_COUNT] = {
97 { 1, 1 }, /* MESA_PRIM_POINTS */
98 { 2, 2 }, /* MESA_PRIM_LINES */
99 { 2, 1 }, /* MESA_PRIM_LINE_LOOP */
100 { 2, 1 }, /* MESA_PRIM_LINE_STRIP */
101 { 3, 3 }, /* MESA_PRIM_TRIANGLES */
102 { 3, 1 }, /* MESA_PRIM_TRIANGLE_STRIP */
103 { 3, 1 }, /* MESA_PRIM_TRIANGLE_FAN */
104 { 4, 4 }, /* MESA_PRIM_QUADS */
105 { 4, 2 }, /* MESA_PRIM_QUAD_STRIP */
106 { 3, 1 }, /* MESA_PRIM_POLYGON */
107 { 4, 4 }, /* MESA_PRIM_LINES_ADJACENCY */
108 { 4, 1 }, /* MESA_PRIM_LINE_STRIP_ADJACENCY */
109 { 6, 6 }, /* MESA_PRIM_TRIANGLES_ADJACENCY */
110 { 6, 2 }, /* MESA_PRIM_TRIANGLE_STRIP_ADJACENCY */
111 };
112
113 return (likely(prim < MESA_PRIM_COUNT)) ? &prim_table[prim] : NULL;
114 }
115
116 /**
117 * Given a vertex count, return the number of primitives.
118 * For polygons, return the number of triangles.
119 */
120 static inline unsigned
u_prims_for_vertices(enum mesa_prim prim,unsigned num)121 u_prims_for_vertices(enum mesa_prim prim, unsigned num)
122 {
123 const struct u_prim_vertex_count *info = u_prim_vertex_count(prim);
124
125 assert(info);
126 assert(info->incr != 0);
127
128 if (num < info->min)
129 return 0;
130
131 return 1 + ((num - info->min) / info->incr);
132 }
133
134 static inline bool
u_validate_pipe_prim(enum mesa_prim pipe_prim,unsigned nr)135 u_validate_pipe_prim(enum mesa_prim pipe_prim, unsigned nr)
136 {
137 const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
138
139 return (count && nr >= count->min);
140 }
141
142
143 static inline bool
u_trim_pipe_prim(enum mesa_prim pipe_prim,unsigned * nr)144 u_trim_pipe_prim(enum mesa_prim pipe_prim, unsigned *nr)
145 {
146 const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
147
148 if (count && *nr >= count->min) {
149 if (count->incr > 1)
150 *nr -= (*nr % count->incr);
151 return true;
152 }
153 else {
154 *nr = 0;
155 return false;
156 }
157 }
158
159
160 /**
161 * Returns the number of reduced/tessellated primitives for the given vertex
162 * count. Each quad is treated as two triangles. Polygons are treated as
163 * triangle fans.
164 */
165 static inline unsigned
u_reduced_prims_for_vertices(enum mesa_prim primitive,int vertices)166 u_reduced_prims_for_vertices(enum mesa_prim primitive, int vertices)
167 {
168 switch (primitive) {
169 case MESA_PRIM_QUADS:
170 case MESA_PRIM_QUAD_STRIP:
171 return u_decomposed_prims_for_vertices(primitive, vertices) * 2;
172 case MESA_PRIM_POLYGON:
173 primitive = MESA_PRIM_TRIANGLE_FAN;
174 FALLTHROUGH;
175 default:
176 return u_decomposed_prims_for_vertices(primitive, vertices);
177 }
178 }
179
180 static inline enum mesa_prim
u_base_prim_type(enum mesa_prim prim_type)181 u_base_prim_type(enum mesa_prim prim_type)
182 {
183 switch(prim_type) {
184 case MESA_PRIM_POINTS:
185 return MESA_PRIM_POINTS;
186 case MESA_PRIM_LINES:
187 case MESA_PRIM_LINE_LOOP:
188 case MESA_PRIM_LINE_STRIP:
189 case MESA_PRIM_LINES_ADJACENCY:
190 case MESA_PRIM_LINE_STRIP_ADJACENCY:
191 return MESA_PRIM_LINES;
192 case MESA_PRIM_TRIANGLES:
193 case MESA_PRIM_TRIANGLE_STRIP:
194 case MESA_PRIM_TRIANGLE_FAN:
195 case MESA_PRIM_TRIANGLES_ADJACENCY:
196 case MESA_PRIM_TRIANGLE_STRIP_ADJACENCY:
197 return MESA_PRIM_TRIANGLES;
198 case MESA_PRIM_QUADS:
199 case MESA_PRIM_QUAD_STRIP:
200 return MESA_PRIM_QUADS;
201 default:
202 return prim_type;
203 }
204 }
205
206 static inline enum mesa_prim
u_tess_prim_from_shader(enum tess_primitive_mode shader_mode)207 u_tess_prim_from_shader(enum tess_primitive_mode shader_mode)
208 {
209 switch (shader_mode) {
210 case TESS_PRIMITIVE_TRIANGLES:
211 return MESA_PRIM_TRIANGLES;
212 case TESS_PRIMITIVE_QUADS:
213 return MESA_PRIM_QUADS;
214 case TESS_PRIMITIVE_ISOLINES:
215 return MESA_PRIM_LINES;
216 default:
217 return MESA_PRIM_POINTS;
218 }
219 }
220
221 static inline unsigned
u_vertices_for_prims(enum mesa_prim prim_type,int count)222 u_vertices_for_prims(enum mesa_prim prim_type, int count)
223 {
224 if (count <= 0)
225 return 0;
226
227 /* We can only figure out the number of vertices from a number of primitives
228 * if we are using basic primitives (so no loops, strips, fans, etc).
229 */
230 assert(prim_type == u_base_prim_type(prim_type) &&
231 prim_type != MESA_PRIM_PATCHES && prim_type != MESA_PRIM_POLYGON);
232
233 const struct u_prim_vertex_count *info = u_prim_vertex_count(prim_type);
234 assert(info);
235
236 return info->min + (count - 1) * info->incr;
237 }
238
239 /**
240 * Returns the number of stream out outputs for a given number of vertices and
241 * primitive type.
242 */
243
244 static inline unsigned
u_stream_outputs_for_vertices(enum mesa_prim primitive,unsigned nr)245 u_stream_outputs_for_vertices(enum mesa_prim primitive, unsigned nr)
246 {
247 /* Extraneous vertices don't contribute to stream outputs */
248 u_trim_pipe_prim(primitive, &nr);
249
250 /* Polygons are special, since they are a single primitive with many
251 * vertices. In this case, we just have an output for each vertex (after
252 * trimming) */
253
254 if (primitive == MESA_PRIM_POLYGON)
255 return nr;
256
257 /* Normally, consider how many primitives are actually generated */
258 unsigned prims = u_decomposed_prims_for_vertices(primitive, nr);
259
260 /* One output per vertex after decomposition */
261 enum mesa_prim base = u_base_prim_type(primitive);
262
263 /* The GL 4.6 compatibility spec says
264 *
265 * When quads and polygons are provided to transform feedback with a
266 * primitive mode of TRIANGLES, they will be tessellated and recorded as
267 * triangles (the order of tessellation within a primitive is undefined)
268 *
269 * Further, quads and polygons are always provided as TRIANGLES. So
270 * tessellate quads into triangles.
271 */
272 if (base == MESA_PRIM_QUADS) {
273 base = MESA_PRIM_TRIANGLES;
274 prims *= 2;
275 }
276
277 return u_vertices_for_prims(base, prims);
278 }
279
280 const char *u_prim_name(enum mesa_prim pipe_prim);
281
282
283 #ifdef __cplusplus
284 }
285 #endif
286
287
288 #endif
289