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