• 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  * Decompose a primitive that is a loop, a strip, or a fan.  Return the
49  * original primitive if it is already decomposed.
50  */
51 static inline enum pipe_prim_type
u_decomposed_prim(enum pipe_prim_type prim)52 u_decomposed_prim(enum pipe_prim_type prim)
53 {
54    switch (prim) {
55    case PIPE_PRIM_LINE_LOOP:
56    case PIPE_PRIM_LINE_STRIP:
57       return PIPE_PRIM_LINES;
58    case PIPE_PRIM_TRIANGLE_STRIP:
59    case PIPE_PRIM_TRIANGLE_FAN:
60       return PIPE_PRIM_TRIANGLES;
61    case PIPE_PRIM_QUAD_STRIP:
62       return PIPE_PRIM_QUADS;
63    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
64       return PIPE_PRIM_LINES_ADJACENCY;
65    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
66       return PIPE_PRIM_TRIANGLES_ADJACENCY;
67    default:
68       return prim;
69    }
70 }
71 
72 /**
73  * Reduce a primitive to one of PIPE_PRIM_POINTS, PIPE_PRIM_LINES, and
74  * PIPE_PRIM_TRIANGLES.
75  */
76 static inline enum pipe_prim_type
u_reduced_prim(enum pipe_prim_type prim)77 u_reduced_prim(enum pipe_prim_type prim)
78 {
79    switch (prim) {
80    case PIPE_PRIM_POINTS:
81       return PIPE_PRIM_POINTS;
82    case PIPE_PRIM_LINES:
83    case PIPE_PRIM_LINE_LOOP:
84    case PIPE_PRIM_LINE_STRIP:
85    case PIPE_PRIM_LINES_ADJACENCY:
86    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
87       return PIPE_PRIM_LINES;
88    default:
89       return PIPE_PRIM_TRIANGLES;
90    }
91 }
92 
93 /**
94  * Re-assemble a primitive to remove its adjacency.
95  */
96 static inline enum pipe_prim_type
u_assembled_prim(enum pipe_prim_type prim)97 u_assembled_prim(enum pipe_prim_type prim)
98 {
99    switch (prim) {
100    case PIPE_PRIM_LINES_ADJACENCY:
101    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
102       return PIPE_PRIM_LINES;
103    case PIPE_PRIM_TRIANGLES_ADJACENCY:
104    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
105       return PIPE_PRIM_TRIANGLES;
106    default:
107       return prim;
108    }
109 }
110 
111 /**
112  * Return the vertex count information for a primitive.
113  *
114  * Note that if this function is called directly or indirectly anywhere in a
115  * source file, it will increase the size of the binary slightly more than
116  * expected because of the use of a table.
117  */
118 static inline const struct u_prim_vertex_count *
u_prim_vertex_count(enum pipe_prim_type prim)119 u_prim_vertex_count(enum pipe_prim_type prim)
120 {
121    static const struct u_prim_vertex_count prim_table[PIPE_PRIM_MAX] = {
122       { 1, 1 }, /* PIPE_PRIM_POINTS */
123       { 2, 2 }, /* PIPE_PRIM_LINES */
124       { 2, 1 }, /* PIPE_PRIM_LINE_LOOP */
125       { 2, 1 }, /* PIPE_PRIM_LINE_STRIP */
126       { 3, 3 }, /* PIPE_PRIM_TRIANGLES */
127       { 3, 1 }, /* PIPE_PRIM_TRIANGLE_STRIP */
128       { 3, 1 }, /* PIPE_PRIM_TRIANGLE_FAN */
129       { 4, 4 }, /* PIPE_PRIM_QUADS */
130       { 4, 2 }, /* PIPE_PRIM_QUAD_STRIP */
131       { 3, 1 }, /* PIPE_PRIM_POLYGON */
132       { 4, 4 }, /* PIPE_PRIM_LINES_ADJACENCY */
133       { 4, 1 }, /* PIPE_PRIM_LINE_STRIP_ADJACENCY */
134       { 6, 6 }, /* PIPE_PRIM_TRIANGLES_ADJACENCY */
135       { 6, 2 }, /* PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY */
136    };
137 
138    return (likely(prim < PIPE_PRIM_MAX)) ? &prim_table[prim] : NULL;
139 }
140 
141 /**
142  * Given a vertex count, return the number of primitives.
143  * For polygons, return the number of triangles.
144  */
145 static inline unsigned
u_prims_for_vertices(enum pipe_prim_type prim,unsigned num)146 u_prims_for_vertices(enum pipe_prim_type prim, unsigned num)
147 {
148    const struct u_prim_vertex_count *info = u_prim_vertex_count(prim);
149 
150    assert(info);
151    assert(info->incr != 0);
152 
153    if (num < info->min)
154       return 0;
155 
156    return 1 + ((num - info->min) / info->incr);
157 }
158 
159 static inline boolean
u_validate_pipe_prim(enum pipe_prim_type pipe_prim,unsigned nr)160 u_validate_pipe_prim(enum pipe_prim_type pipe_prim, unsigned nr)
161 {
162    const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
163 
164    return (count && nr >= count->min);
165 }
166 
167 
168 static inline boolean
u_trim_pipe_prim(enum pipe_prim_type pipe_prim,unsigned * nr)169 u_trim_pipe_prim(enum pipe_prim_type pipe_prim, unsigned *nr)
170 {
171    const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
172 
173    if (count && *nr >= count->min) {
174       if (count->incr > 1)
175          *nr -= (*nr % count->incr);
176       return TRUE;
177    }
178    else {
179       *nr = 0;
180       return FALSE;
181    }
182 }
183 
184 static inline unsigned
u_vertices_per_prim(enum pipe_prim_type primitive)185 u_vertices_per_prim(enum pipe_prim_type primitive)
186 {
187    switch(primitive) {
188    case PIPE_PRIM_POINTS:
189       return 1;
190    case PIPE_PRIM_LINES:
191    case PIPE_PRIM_LINE_LOOP:
192    case PIPE_PRIM_LINE_STRIP:
193       return 2;
194    case PIPE_PRIM_TRIANGLES:
195    case PIPE_PRIM_TRIANGLE_STRIP:
196    case PIPE_PRIM_TRIANGLE_FAN:
197       return 3;
198    case PIPE_PRIM_LINES_ADJACENCY:
199    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
200       return 4;
201    case PIPE_PRIM_TRIANGLES_ADJACENCY:
202    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
203       return 6;
204 
205    case PIPE_PRIM_QUADS:
206    case PIPE_PRIM_QUAD_STRIP:
207       /* these won't be seen from geometry shaders
208          but prim assembly might for prim id. */
209       return 4;
210 
211    /* following primitives should never be used
212     * with geometry shaders abd their size is
213     * undefined */
214    case PIPE_PRIM_POLYGON:
215    default:
216       debug_printf("Unrecognized geometry shader primitive");
217       return 3;
218    }
219 }
220 
221 /**
222  * Returns the number of decomposed primitives for the given
223  * vertex count.
224  * Parts of the pipline are invoked once for each triangle in
225  * triangle strip, triangle fans and triangles and once
226  * for each line in line strip, line loop, lines. Also
227  * statistics depend on knowing the exact number of decomposed
228  * primitives for a set of vertices.
229  */
230 static inline unsigned
u_decomposed_prims_for_vertices(enum pipe_prim_type primitive,int vertices)231 u_decomposed_prims_for_vertices(enum pipe_prim_type primitive, int vertices)
232 {
233    switch (primitive) {
234    case PIPE_PRIM_POINTS:
235       return vertices;
236    case PIPE_PRIM_LINES:
237       return vertices / 2;
238    case PIPE_PRIM_LINE_LOOP:
239       return (vertices >= 2) ? vertices : 0;
240    case PIPE_PRIM_LINE_STRIP:
241       return (vertices >= 2) ? vertices - 1 : 0;
242    case PIPE_PRIM_TRIANGLES:
243       return vertices / 3;
244    case PIPE_PRIM_TRIANGLE_STRIP:
245       return (vertices >= 3) ? vertices - 2 : 0;
246    case PIPE_PRIM_TRIANGLE_FAN:
247       return (vertices >= 3) ? vertices - 2 : 0;
248    case PIPE_PRIM_LINES_ADJACENCY:
249       return vertices / 4;
250    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
251       return (vertices >= 4) ? vertices - 3 : 0;
252    case PIPE_PRIM_TRIANGLES_ADJACENCY:
253       return vertices / 6;
254    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
255       return (vertices >= 6) ? 1 + (vertices - 6) / 2 : 0;
256    case PIPE_PRIM_QUADS:
257       return vertices / 4;
258    case PIPE_PRIM_QUAD_STRIP:
259       return (vertices >= 4) ? (vertices - 2) / 2 : 0;
260    /* Polygons can't be decomposed
261     * because the number of their vertices isn't known so
262     * for them and whatever else we don't recognize just
263     * return 1 if the number of vertices is greater than
264     * or equal to 3 and zero otherwise */
265    case PIPE_PRIM_POLYGON:
266    default:
267       debug_printf("Invalid decomposition primitive!\n");
268       return (vertices >= 3) ? 1 : 0;
269    }
270 }
271 
272 /**
273  * Returns the number of reduced/tessellated primitives for the given vertex
274  * count.  Each quad is treated as two triangles.  Polygons are treated as
275  * triangle fans.
276  */
277 static inline unsigned
u_reduced_prims_for_vertices(enum pipe_prim_type primitive,int vertices)278 u_reduced_prims_for_vertices(enum pipe_prim_type primitive, int vertices)
279 {
280    switch (primitive) {
281    case PIPE_PRIM_QUADS:
282    case PIPE_PRIM_QUAD_STRIP:
283       return u_decomposed_prims_for_vertices(primitive, vertices) * 2;
284    case PIPE_PRIM_POLYGON:
285       primitive = PIPE_PRIM_TRIANGLE_FAN;
286       FALLTHROUGH;
287    default:
288       return u_decomposed_prims_for_vertices(primitive, vertices);
289    }
290 }
291 
292 static inline enum pipe_prim_type
u_base_prim_type(enum pipe_prim_type prim_type)293 u_base_prim_type(enum pipe_prim_type prim_type)
294 {
295    switch(prim_type) {
296       case PIPE_PRIM_POINTS:
297          return PIPE_PRIM_POINTS;
298       case PIPE_PRIM_LINES:
299       case PIPE_PRIM_LINE_LOOP:
300       case PIPE_PRIM_LINE_STRIP:
301       case PIPE_PRIM_LINES_ADJACENCY:
302       case PIPE_PRIM_LINE_STRIP_ADJACENCY:
303          return PIPE_PRIM_LINES;
304       case PIPE_PRIM_TRIANGLES:
305       case PIPE_PRIM_TRIANGLE_STRIP:
306       case PIPE_PRIM_TRIANGLE_FAN:
307       case PIPE_PRIM_TRIANGLES_ADJACENCY:
308       case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
309          return PIPE_PRIM_TRIANGLES;
310       case PIPE_PRIM_QUADS:
311       case PIPE_PRIM_QUAD_STRIP:
312          return PIPE_PRIM_QUADS;
313       default:
314          return prim_type;
315    }
316 }
317 
318 static inline enum pipe_prim_type
u_tess_prim_from_shader(enum tess_primitive_mode shader_mode)319 u_tess_prim_from_shader(enum tess_primitive_mode shader_mode)
320 {
321    switch (shader_mode) {
322    case TESS_PRIMITIVE_TRIANGLES:
323       return PIPE_PRIM_TRIANGLES;
324    case TESS_PRIMITIVE_QUADS:
325       return PIPE_PRIM_QUADS;
326    case TESS_PRIMITIVE_ISOLINES:
327       return PIPE_PRIM_LINES;
328    default:
329       return PIPE_PRIM_POINTS;
330    }
331 }
332 
333 static inline unsigned
u_vertices_for_prims(enum pipe_prim_type prim_type,int count)334 u_vertices_for_prims(enum pipe_prim_type prim_type, int count)
335 {
336    if (count <= 0)
337       return 0;
338 
339    /* We can only figure out the number of vertices from a number of primitives
340     * if we are using basic primitives (so no loops, strips, fans, etc).
341     */
342    assert(prim_type == u_base_prim_type(prim_type) &&
343           prim_type != PIPE_PRIM_PATCHES && prim_type != PIPE_PRIM_POLYGON);
344 
345    const struct u_prim_vertex_count *info = u_prim_vertex_count(prim_type);
346    assert(info);
347 
348    return info->min + (count - 1) * info->incr;
349 }
350 
351 /**
352  * Returns the number of stream out outputs for a given number of vertices and
353  * primitive type.
354  */
355 
356 static inline unsigned
u_stream_outputs_for_vertices(enum pipe_prim_type primitive,unsigned nr)357 u_stream_outputs_for_vertices(enum pipe_prim_type primitive, unsigned nr)
358 {
359    /* Extraneous vertices don't contribute to stream outputs */
360    u_trim_pipe_prim(primitive, &nr);
361 
362    /* Polygons are special, since they are a single primitive with many
363     * vertices. In this case, we just have an output for each vertex (after
364     * trimming) */
365 
366    if (primitive == PIPE_PRIM_POLYGON)
367       return nr;
368 
369    /* Normally, consider how many primitives are actually generated */
370    unsigned prims = u_decomposed_prims_for_vertices(primitive, nr);
371 
372    /* One output per vertex after decomposition */
373    enum pipe_prim_type base = u_base_prim_type(primitive);
374    return u_vertices_for_prims(base, prims);
375 }
376 
377 const char *u_prim_name(enum pipe_prim_type pipe_prim);
378 
379 
380 #ifdef __cplusplus
381 }
382 #endif
383 
384 
385 #endif
386