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 39extern "C" { 40#endif 41 42struct 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 */ 51static inline enum pipe_prim_type 52u_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 */ 76static inline enum pipe_prim_type 77u_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 */ 96static inline enum pipe_prim_type 97u_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 */ 118static inline const struct u_prim_vertex_count * 119u_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 */ 145static inline unsigned 146u_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 159static inline boolean 160u_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 168static inline boolean 169u_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 184static inline unsigned 185u_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 */ 230static inline unsigned 231u_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 */ 277static inline unsigned 278u_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 292static inline enum pipe_prim_type 293u_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 318static inline enum pipe_prim_type 319u_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 333static inline unsigned 334u_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 356static inline unsigned 357u_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 377const char *u_prim_name(enum pipe_prim_type pipe_prim); 378 379 380#ifdef __cplusplus 381} 382#endif 383 384 385#endif 386