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