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