1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 2008 VMware, Inc.
4848b8605Smrg * All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the
8848b8605Smrg * "Software"), to deal in the Software without restriction, including
9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
12848b8605Smrg * the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice (including the
15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
16848b8605Smrg * of the Software.
17848b8605Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25848b8605Smrg *
26848b8605Smrg **************************************************************************/
27848b8605Smrg
28848b8605Smrg
29848b8605Smrg#ifndef U_PRIM_H
30848b8605Smrg#define U_PRIM_H
31848b8605Smrg
32848b8605Smrg
33848b8605Smrg#include "pipe/p_defines.h"
34848b8605Smrg#include "util/u_debug.h"
35848b8605Smrg
36848b8605Smrg#ifdef __cplusplus
37848b8605Smrgextern "C" {
38848b8605Smrg#endif
39848b8605Smrg
40848b8605Smrgstruct u_prim_vertex_count {
41848b8605Smrg   unsigned min;
42848b8605Smrg   unsigned incr;
43848b8605Smrg};
44848b8605Smrg
45848b8605Smrg/**
46848b8605Smrg * Decompose a primitive that is a loop, a strip, or a fan.  Return the
47848b8605Smrg * original primitive if it is already decomposed.
48848b8605Smrg */
49b8e80941Smrgstatic inline enum pipe_prim_type
50b8e80941Smrgu_decomposed_prim(enum pipe_prim_type prim)
51848b8605Smrg{
52848b8605Smrg   switch (prim) {
53848b8605Smrg   case PIPE_PRIM_LINE_LOOP:
54848b8605Smrg   case PIPE_PRIM_LINE_STRIP:
55848b8605Smrg      return PIPE_PRIM_LINES;
56848b8605Smrg   case PIPE_PRIM_TRIANGLE_STRIP:
57848b8605Smrg   case PIPE_PRIM_TRIANGLE_FAN:
58848b8605Smrg      return PIPE_PRIM_TRIANGLES;
59848b8605Smrg   case PIPE_PRIM_QUAD_STRIP:
60848b8605Smrg      return PIPE_PRIM_QUADS;
61848b8605Smrg   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
62848b8605Smrg      return PIPE_PRIM_LINES_ADJACENCY;
63848b8605Smrg   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
64848b8605Smrg      return PIPE_PRIM_TRIANGLES_ADJACENCY;
65848b8605Smrg   default:
66848b8605Smrg      return prim;
67848b8605Smrg   }
68848b8605Smrg}
69848b8605Smrg
70848b8605Smrg/**
71848b8605Smrg * Reduce a primitive to one of PIPE_PRIM_POINTS, PIPE_PRIM_LINES, and
72848b8605Smrg * PIPE_PRIM_TRIANGLES.
73848b8605Smrg */
74b8e80941Smrgstatic inline enum pipe_prim_type
75b8e80941Smrgu_reduced_prim(enum pipe_prim_type prim)
76848b8605Smrg{
77848b8605Smrg   switch (prim) {
78848b8605Smrg   case PIPE_PRIM_POINTS:
79848b8605Smrg      return PIPE_PRIM_POINTS;
80848b8605Smrg   case PIPE_PRIM_LINES:
81848b8605Smrg   case PIPE_PRIM_LINE_LOOP:
82848b8605Smrg   case PIPE_PRIM_LINE_STRIP:
83848b8605Smrg   case PIPE_PRIM_LINES_ADJACENCY:
84848b8605Smrg   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
85848b8605Smrg      return PIPE_PRIM_LINES;
86848b8605Smrg   default:
87848b8605Smrg      return PIPE_PRIM_TRIANGLES;
88848b8605Smrg   }
89848b8605Smrg}
90848b8605Smrg
91848b8605Smrg/**
92848b8605Smrg * Re-assemble a primitive to remove its adjacency.
93848b8605Smrg */
94b8e80941Smrgstatic inline enum pipe_prim_type
95b8e80941Smrgu_assembled_prim(enum pipe_prim_type prim)
96848b8605Smrg{
97848b8605Smrg   switch (prim) {
98848b8605Smrg   case PIPE_PRIM_LINES_ADJACENCY:
99848b8605Smrg   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
100848b8605Smrg      return PIPE_PRIM_LINES;
101848b8605Smrg   case PIPE_PRIM_TRIANGLES_ADJACENCY:
102848b8605Smrg   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
103848b8605Smrg      return PIPE_PRIM_TRIANGLES;
104848b8605Smrg   default:
105848b8605Smrg      return prim;
106848b8605Smrg   }
107848b8605Smrg}
108848b8605Smrg
109848b8605Smrg/**
110848b8605Smrg * Return the vertex count information for a primitive.
111848b8605Smrg *
112848b8605Smrg * Note that if this function is called directly or indirectly anywhere in a
113848b8605Smrg * source file, it will increase the size of the binary slightly more than
114848b8605Smrg * expected because of the use of a table.
115848b8605Smrg */
116b8e80941Smrgstatic inline const struct u_prim_vertex_count *
117b8e80941Smrgu_prim_vertex_count(enum pipe_prim_type prim)
118848b8605Smrg{
119848b8605Smrg   static const struct u_prim_vertex_count prim_table[PIPE_PRIM_MAX] = {
120848b8605Smrg      { 1, 1 }, /* PIPE_PRIM_POINTS */
121848b8605Smrg      { 2, 2 }, /* PIPE_PRIM_LINES */
122848b8605Smrg      { 2, 1 }, /* PIPE_PRIM_LINE_LOOP */
123848b8605Smrg      { 2, 1 }, /* PIPE_PRIM_LINE_STRIP */
124848b8605Smrg      { 3, 3 }, /* PIPE_PRIM_TRIANGLES */
125848b8605Smrg      { 3, 1 }, /* PIPE_PRIM_TRIANGLE_STRIP */
126848b8605Smrg      { 3, 1 }, /* PIPE_PRIM_TRIANGLE_FAN */
127848b8605Smrg      { 4, 4 }, /* PIPE_PRIM_QUADS */
128848b8605Smrg      { 4, 2 }, /* PIPE_PRIM_QUAD_STRIP */
129848b8605Smrg      { 3, 1 }, /* PIPE_PRIM_POLYGON */
130848b8605Smrg      { 4, 4 }, /* PIPE_PRIM_LINES_ADJACENCY */
131848b8605Smrg      { 4, 1 }, /* PIPE_PRIM_LINE_STRIP_ADJACENCY */
132848b8605Smrg      { 6, 6 }, /* PIPE_PRIM_TRIANGLES_ADJACENCY */
133848b8605Smrg      { 6, 2 }, /* PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY */
134848b8605Smrg   };
135848b8605Smrg
136848b8605Smrg   return (likely(prim < PIPE_PRIM_MAX)) ? &prim_table[prim] : NULL;
137848b8605Smrg}
138848b8605Smrg
139848b8605Smrg/**
140848b8605Smrg * Given a vertex count, return the number of primitives.
141848b8605Smrg * For polygons, return the number of triangles.
142848b8605Smrg */
143b8e80941Smrgstatic inline unsigned
144b8e80941Smrgu_prims_for_vertices(enum pipe_prim_type prim, unsigned num)
145848b8605Smrg{
146848b8605Smrg   const struct u_prim_vertex_count *info = u_prim_vertex_count(prim);
147848b8605Smrg
148b8e80941Smrg   assert(info);
149b8e80941Smrg   assert(info->incr != 0);
150b8e80941Smrg
151848b8605Smrg   if (num < info->min)
152848b8605Smrg      return 0;
153848b8605Smrg
154848b8605Smrg   return 1 + ((num - info->min) / info->incr);
155848b8605Smrg}
156848b8605Smrg
157b8e80941Smrgstatic inline boolean
158b8e80941Smrgu_validate_pipe_prim(enum pipe_prim_type pipe_prim, unsigned nr)
159848b8605Smrg{
160848b8605Smrg   const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
161848b8605Smrg
162848b8605Smrg   return (count && nr >= count->min);
163848b8605Smrg}
164848b8605Smrg
165848b8605Smrg
166b8e80941Smrgstatic inline boolean
167b8e80941Smrgu_trim_pipe_prim(enum pipe_prim_type pipe_prim, unsigned *nr)
168848b8605Smrg{
169848b8605Smrg   const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
170848b8605Smrg
171848b8605Smrg   if (count && *nr >= count->min) {
172848b8605Smrg      if (count->incr > 1)
173848b8605Smrg         *nr -= (*nr % count->incr);
174848b8605Smrg      return TRUE;
175848b8605Smrg   }
176848b8605Smrg   else {
177848b8605Smrg      *nr = 0;
178848b8605Smrg      return FALSE;
179848b8605Smrg   }
180848b8605Smrg}
181848b8605Smrg
182b8e80941Smrgstatic inline unsigned
183b8e80941Smrgu_vertices_per_prim(enum pipe_prim_type primitive)
184848b8605Smrg{
185848b8605Smrg   switch(primitive) {
186848b8605Smrg   case PIPE_PRIM_POINTS:
187848b8605Smrg      return 1;
188848b8605Smrg   case PIPE_PRIM_LINES:
189848b8605Smrg   case PIPE_PRIM_LINE_LOOP:
190848b8605Smrg   case PIPE_PRIM_LINE_STRIP:
191848b8605Smrg      return 2;
192848b8605Smrg   case PIPE_PRIM_TRIANGLES:
193848b8605Smrg   case PIPE_PRIM_TRIANGLE_STRIP:
194848b8605Smrg   case PIPE_PRIM_TRIANGLE_FAN:
195848b8605Smrg      return 3;
196848b8605Smrg   case PIPE_PRIM_LINES_ADJACENCY:
197848b8605Smrg   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
198848b8605Smrg      return 4;
199848b8605Smrg   case PIPE_PRIM_TRIANGLES_ADJACENCY:
200848b8605Smrg   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
201848b8605Smrg      return 6;
202848b8605Smrg
203848b8605Smrg   /* following primitives should never be used
204848b8605Smrg    * with geometry shaders abd their size is
205848b8605Smrg    * undefined */
206848b8605Smrg   case PIPE_PRIM_POLYGON:
207848b8605Smrg   case PIPE_PRIM_QUADS:
208848b8605Smrg   case PIPE_PRIM_QUAD_STRIP:
209848b8605Smrg   default:
210848b8605Smrg      debug_printf("Unrecognized geometry shader primitive");
211848b8605Smrg      return 3;
212848b8605Smrg   }
213848b8605Smrg}
214848b8605Smrg
215848b8605Smrg/**
216848b8605Smrg * Returns the number of decomposed primitives for the given
217848b8605Smrg * vertex count.
218848b8605Smrg * Parts of the pipline are invoked once for each triangle in
219848b8605Smrg * triangle strip, triangle fans and triangles and once
220848b8605Smrg * for each line in line strip, line loop, lines. Also
221848b8605Smrg * statistics depend on knowing the exact number of decomposed
222848b8605Smrg * primitives for a set of vertices.
223848b8605Smrg */
224b8e80941Smrgstatic inline unsigned
225b8e80941Smrgu_decomposed_prims_for_vertices(enum pipe_prim_type primitive, int vertices)
226848b8605Smrg{
227848b8605Smrg   switch (primitive) {
228848b8605Smrg   case PIPE_PRIM_POINTS:
229848b8605Smrg      return vertices;
230848b8605Smrg   case PIPE_PRIM_LINES:
231848b8605Smrg      return vertices / 2;
232848b8605Smrg   case PIPE_PRIM_LINE_LOOP:
233848b8605Smrg      return (vertices >= 2) ? vertices : 0;
234848b8605Smrg   case PIPE_PRIM_LINE_STRIP:
235848b8605Smrg      return (vertices >= 2) ? vertices - 1 : 0;
236848b8605Smrg   case PIPE_PRIM_TRIANGLES:
237848b8605Smrg      return vertices / 3;
238848b8605Smrg   case PIPE_PRIM_TRIANGLE_STRIP:
239848b8605Smrg      return (vertices >= 3) ? vertices - 2 : 0;
240848b8605Smrg   case PIPE_PRIM_TRIANGLE_FAN:
241848b8605Smrg      return (vertices >= 3) ? vertices - 2 : 0;
242848b8605Smrg   case PIPE_PRIM_LINES_ADJACENCY:
243848b8605Smrg      return vertices / 4;
244848b8605Smrg   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
245848b8605Smrg      return (vertices >= 4) ? vertices - 3 : 0;
246848b8605Smrg   case PIPE_PRIM_TRIANGLES_ADJACENCY:
247848b8605Smrg      return vertices / 6;
248848b8605Smrg   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
249848b8605Smrg      return (vertices >= 6) ? 1 + (vertices - 6) / 2 : 0;
250848b8605Smrg   case PIPE_PRIM_QUADS:
251848b8605Smrg      return vertices / 4;
252848b8605Smrg   case PIPE_PRIM_QUAD_STRIP:
253848b8605Smrg      return (vertices >= 4) ? (vertices - 2) / 2 : 0;
254848b8605Smrg   /* Polygons can't be decomposed
255848b8605Smrg    * because the number of their vertices isn't known so
256848b8605Smrg    * for them and whatever else we don't recognize just
257848b8605Smrg    * return 1 if the number of vertices is greater than
258848b8605Smrg    * or equal to 3 and zero otherwise */
259848b8605Smrg   case PIPE_PRIM_POLYGON:
260848b8605Smrg   default:
261848b8605Smrg      debug_printf("Invalid decomposition primitive!\n");
262848b8605Smrg      return (vertices >= 3) ? 1 : 0;
263848b8605Smrg   }
264848b8605Smrg}
265848b8605Smrg
266848b8605Smrg/**
267848b8605Smrg * Returns the number of reduced/tessellated primitives for the given vertex
268848b8605Smrg * count.  Each quad is treated as two triangles.  Polygons are treated as
269848b8605Smrg * triangle fans.
270848b8605Smrg */
271b8e80941Smrgstatic inline unsigned
272b8e80941Smrgu_reduced_prims_for_vertices(enum pipe_prim_type primitive, int vertices)
273848b8605Smrg{
274848b8605Smrg   switch (primitive) {
275848b8605Smrg   case PIPE_PRIM_QUADS:
276848b8605Smrg   case PIPE_PRIM_QUAD_STRIP:
277848b8605Smrg      return u_decomposed_prims_for_vertices(primitive, vertices) * 2;
278848b8605Smrg   case PIPE_PRIM_POLYGON:
279848b8605Smrg      primitive = PIPE_PRIM_TRIANGLE_FAN;
280848b8605Smrg      /* fall through */
281848b8605Smrg   default:
282848b8605Smrg      return u_decomposed_prims_for_vertices(primitive, vertices);
283848b8605Smrg   }
284848b8605Smrg}
285848b8605Smrg
286b8e80941Smrgconst char *u_prim_name(enum pipe_prim_type pipe_prim);
287b8e80941Smrg
288b8e80941Smrg
289b8e80941Smrg#ifdef __cplusplus
290b8e80941Smrg}
291b8e80941Smrg#endif
292b8e80941Smrg
293848b8605Smrg
294848b8605Smrg#endif
295