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 enum pipe_prim_type
50u_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 */
74static inline enum pipe_prim_type
75u_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 */
94static inline enum pipe_prim_type
95u_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 */
116static inline const struct u_prim_vertex_count *
117u_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 */
143static inline unsigned
144u_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
157static inline boolean
158u_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
166static inline boolean
167u_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
182static inline unsigned
183u_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 */
224static inline unsigned
225u_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 */
271static inline unsigned
272u_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
286const char *u_prim_name(enum pipe_prim_type pipe_prim);
287
288
289#ifdef __cplusplus
290}
291#endif
292
293
294#endif
295