• 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/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 enum pipe_prim_type
u_decomposed_prim(enum pipe_prim_type prim)50 u_decomposed_prim(enum pipe_prim_type 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 enum pipe_prim_type
u_reduced_prim(enum pipe_prim_type prim)75 u_reduced_prim(enum pipe_prim_type 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 enum pipe_prim_type
u_assembled_prim(enum pipe_prim_type prim)95 u_assembled_prim(enum pipe_prim_type 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(enum pipe_prim_type prim)117 u_prim_vertex_count(enum pipe_prim_type 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 
139 /**
140  * Given a vertex count, return the number of primitives.
141  * For polygons, return the number of triangles.
142  */
143 static inline unsigned
u_prims_for_vertices(enum pipe_prim_type prim,unsigned num)144 u_prims_for_vertices(enum pipe_prim_type prim, unsigned num)
145 {
146    const struct u_prim_vertex_count *info = u_prim_vertex_count(prim);
147 
148    assert(info);
149    assert(info->incr != 0);
150 
151    if (num < info->min)
152       return 0;
153 
154    return 1 + ((num - info->min) / info->incr);
155 }
156 
157 static inline boolean
u_validate_pipe_prim(enum pipe_prim_type pipe_prim,unsigned nr)158 u_validate_pipe_prim(enum pipe_prim_type pipe_prim, unsigned nr)
159 {
160    const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
161 
162    return (count && nr >= count->min);
163 }
164 
165 
166 static inline boolean
u_trim_pipe_prim(enum pipe_prim_type pipe_prim,unsigned * nr)167 u_trim_pipe_prim(enum pipe_prim_type pipe_prim, unsigned *nr)
168 {
169    const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
170 
171    if (count && *nr >= count->min) {
172       if (count->incr > 1)
173          *nr -= (*nr % count->incr);
174       return TRUE;
175    }
176    else {
177       *nr = 0;
178       return FALSE;
179    }
180 }
181 
182 static inline unsigned
u_vertices_per_prim(enum pipe_prim_type primitive)183 u_vertices_per_prim(enum pipe_prim_type primitive)
184 {
185    switch(primitive) {
186    case PIPE_PRIM_POINTS:
187       return 1;
188    case PIPE_PRIM_LINES:
189    case PIPE_PRIM_LINE_LOOP:
190    case PIPE_PRIM_LINE_STRIP:
191       return 2;
192    case PIPE_PRIM_TRIANGLES:
193    case PIPE_PRIM_TRIANGLE_STRIP:
194    case PIPE_PRIM_TRIANGLE_FAN:
195       return 3;
196    case PIPE_PRIM_LINES_ADJACENCY:
197    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
198       return 4;
199    case PIPE_PRIM_TRIANGLES_ADJACENCY:
200    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
201       return 6;
202 
203    /* following primitives should never be used
204     * with geometry shaders abd their size is
205     * undefined */
206    case PIPE_PRIM_POLYGON:
207    case PIPE_PRIM_QUADS:
208    case PIPE_PRIM_QUAD_STRIP:
209    default:
210       debug_printf("Unrecognized geometry shader primitive");
211       return 3;
212    }
213 }
214 
215 /**
216  * Returns the number of decomposed primitives for the given
217  * vertex count.
218  * Parts of the pipline are invoked once for each triangle in
219  * triangle strip, triangle fans and triangles and once
220  * for each line in line strip, line loop, lines. Also
221  * statistics depend on knowing the exact number of decomposed
222  * primitives for a set of vertices.
223  */
224 static inline unsigned
u_decomposed_prims_for_vertices(enum pipe_prim_type primitive,int vertices)225 u_decomposed_prims_for_vertices(enum pipe_prim_type primitive, int vertices)
226 {
227    switch (primitive) {
228    case PIPE_PRIM_POINTS:
229       return vertices;
230    case PIPE_PRIM_LINES:
231       return vertices / 2;
232    case PIPE_PRIM_LINE_LOOP:
233       return (vertices >= 2) ? vertices : 0;
234    case PIPE_PRIM_LINE_STRIP:
235       return (vertices >= 2) ? vertices - 1 : 0;
236    case PIPE_PRIM_TRIANGLES:
237       return vertices / 3;
238    case PIPE_PRIM_TRIANGLE_STRIP:
239       return (vertices >= 3) ? vertices - 2 : 0;
240    case PIPE_PRIM_TRIANGLE_FAN:
241       return (vertices >= 3) ? vertices - 2 : 0;
242    case PIPE_PRIM_LINES_ADJACENCY:
243       return vertices / 4;
244    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
245       return (vertices >= 4) ? vertices - 3 : 0;
246    case PIPE_PRIM_TRIANGLES_ADJACENCY:
247       return vertices / 6;
248    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
249       return (vertices >= 6) ? 1 + (vertices - 6) / 2 : 0;
250    case PIPE_PRIM_QUADS:
251       return vertices / 4;
252    case PIPE_PRIM_QUAD_STRIP:
253       return (vertices >= 4) ? (vertices - 2) / 2 : 0;
254    /* Polygons can't be decomposed
255     * because the number of their vertices isn't known so
256     * for them and whatever else we don't recognize just
257     * return 1 if the number of vertices is greater than
258     * or equal to 3 and zero otherwise */
259    case PIPE_PRIM_POLYGON:
260    default:
261       debug_printf("Invalid decomposition primitive!\n");
262       return (vertices >= 3) ? 1 : 0;
263    }
264 }
265 
266 /**
267  * Returns the number of reduced/tessellated primitives for the given vertex
268  * count.  Each quad is treated as two triangles.  Polygons are treated as
269  * triangle fans.
270  */
271 static inline unsigned
u_reduced_prims_for_vertices(enum pipe_prim_type primitive,int vertices)272 u_reduced_prims_for_vertices(enum pipe_prim_type primitive, int vertices)
273 {
274    switch (primitive) {
275    case PIPE_PRIM_QUADS:
276    case PIPE_PRIM_QUAD_STRIP:
277       return u_decomposed_prims_for_vertices(primitive, vertices) * 2;
278    case PIPE_PRIM_POLYGON:
279       primitive = PIPE_PRIM_TRIANGLE_FAN;
280       /* fall through */
281    default:
282       return u_decomposed_prims_for_vertices(primitive, vertices);
283    }
284 }
285 
286 const char *u_prim_name(enum pipe_prim_type pipe_prim);
287 
288 
289 #ifdef __cplusplus
290 }
291 #endif
292 
293 
294 #endif
295