• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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