X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Futil%2Fu_prim.h;h=b4c06df01e0fae902ac181aca366848f9c881530;hb=979e7e3680792dc23d434295edd10b161af8aee3;hp=a9b533eea700458bf512607aa8b5fd9f29c4ce7f;hpb=9615daa9324341f6a56932dc46b807f402d18283;p=mesa.git diff --git a/src/gallium/auxiliary/util/u_prim.h b/src/gallium/auxiliary/util/u_prim.h index a9b533eea70..b4c06df01e0 100644 --- a/src/gallium/auxiliary/util/u_prim.h +++ b/src/gallium/auxiliary/util/u_prim.h @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2008 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -26,113 +26,339 @@ **************************************************************************/ -#ifndef U_BLIT_H -#define U_BLIT_H +#ifndef U_PRIM_H +#define U_PRIM_H +#include "pipe/p_defines.h" +#include "util/u_debug.h" + #ifdef __cplusplus extern "C" { #endif -#include "pipe/p_defines.h" +struct u_prim_vertex_count { + unsigned min; + unsigned incr; +}; -static INLINE boolean u_validate_pipe_prim( unsigned pipe_prim, unsigned nr ) +/** + * Decompose a primitive that is a loop, a strip, or a fan. Return the + * original primitive if it is already decomposed. + */ +static inline enum pipe_prim_type +u_decomposed_prim(enum pipe_prim_type prim) { - boolean ok = TRUE; + switch (prim) { + case PIPE_PRIM_LINE_LOOP: + case PIPE_PRIM_LINE_STRIP: + return PIPE_PRIM_LINES; + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_TRIANGLE_FAN: + return PIPE_PRIM_TRIANGLES; + case PIPE_PRIM_QUAD_STRIP: + return PIPE_PRIM_QUADS; + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return PIPE_PRIM_LINES_ADJACENCY; + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + return PIPE_PRIM_TRIANGLES_ADJACENCY; + default: + return prim; + } +} - switch (pipe_prim) { +/** + * Reduce a primitive to one of PIPE_PRIM_POINTS, PIPE_PRIM_LINES, and + * PIPE_PRIM_TRIANGLES. + */ +static inline enum pipe_prim_type +u_reduced_prim(enum pipe_prim_type prim) +{ + switch (prim) { case PIPE_PRIM_POINTS: - ok = (nr >= 1); - break; + return PIPE_PRIM_POINTS; case PIPE_PRIM_LINES: - ok = (nr >= 2); - break; + case PIPE_PRIM_LINE_LOOP: case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_LINES_ADJACENCY: + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return PIPE_PRIM_LINES; + default: + return PIPE_PRIM_TRIANGLES; + } +} + +/** + * Re-assemble a primitive to remove its adjacency. + */ +static inline enum pipe_prim_type +u_assembled_prim(enum pipe_prim_type prim) +{ + switch (prim) { + case PIPE_PRIM_LINES_ADJACENCY: + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return PIPE_PRIM_LINES; + case PIPE_PRIM_TRIANGLES_ADJACENCY: + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + return PIPE_PRIM_TRIANGLES; + default: + return prim; + } +} + +/** + * Return the vertex count information for a primitive. + * + * Note that if this function is called directly or indirectly anywhere in a + * source file, it will increase the size of the binary slightly more than + * expected because of the use of a table. + */ +static inline const struct u_prim_vertex_count * +u_prim_vertex_count(enum pipe_prim_type prim) +{ + static const struct u_prim_vertex_count prim_table[PIPE_PRIM_MAX] = { + { 1, 1 }, /* PIPE_PRIM_POINTS */ + { 2, 2 }, /* PIPE_PRIM_LINES */ + { 2, 1 }, /* PIPE_PRIM_LINE_LOOP */ + { 2, 1 }, /* PIPE_PRIM_LINE_STRIP */ + { 3, 3 }, /* PIPE_PRIM_TRIANGLES */ + { 3, 1 }, /* PIPE_PRIM_TRIANGLE_STRIP */ + { 3, 1 }, /* PIPE_PRIM_TRIANGLE_FAN */ + { 4, 4 }, /* PIPE_PRIM_QUADS */ + { 4, 2 }, /* PIPE_PRIM_QUAD_STRIP */ + { 3, 1 }, /* PIPE_PRIM_POLYGON */ + { 4, 4 }, /* PIPE_PRIM_LINES_ADJACENCY */ + { 4, 1 }, /* PIPE_PRIM_LINE_STRIP_ADJACENCY */ + { 6, 6 }, /* PIPE_PRIM_TRIANGLES_ADJACENCY */ + { 6, 2 }, /* PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY */ + }; + + return (likely(prim < PIPE_PRIM_MAX)) ? &prim_table[prim] : NULL; +} + +/** + * Given a vertex count, return the number of primitives. + * For polygons, return the number of triangles. + */ +static inline unsigned +u_prims_for_vertices(enum pipe_prim_type prim, unsigned num) +{ + const struct u_prim_vertex_count *info = u_prim_vertex_count(prim); + + assert(info); + assert(info->incr != 0); + + if (num < info->min) + return 0; + + return 1 + ((num - info->min) / info->incr); +} + +static inline boolean +u_validate_pipe_prim(enum pipe_prim_type pipe_prim, unsigned nr) +{ + const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim); + + return (count && nr >= count->min); +} + + +static inline boolean +u_trim_pipe_prim(enum pipe_prim_type pipe_prim, unsigned *nr) +{ + const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim); + + if (count && *nr >= count->min) { + if (count->incr > 1) + *nr -= (*nr % count->incr); + return TRUE; + } + else { + *nr = 0; + return FALSE; + } +} + +static inline unsigned +u_vertices_per_prim(enum pipe_prim_type primitive) +{ + switch(primitive) { + case PIPE_PRIM_POINTS: + return 1; + case PIPE_PRIM_LINES: case PIPE_PRIM_LINE_LOOP: - ok = (nr >= 2); - break; + case PIPE_PRIM_LINE_STRIP: + return 2; case PIPE_PRIM_TRIANGLES: - ok = (nr >= 3); - break; case PIPE_PRIM_TRIANGLE_STRIP: case PIPE_PRIM_TRIANGLE_FAN: + return 3; + case PIPE_PRIM_LINES_ADJACENCY: + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return 4; + case PIPE_PRIM_TRIANGLES_ADJACENCY: + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + return 6; + + /* following primitives should never be used + * with geometry shaders abd their size is + * undefined */ case PIPE_PRIM_POLYGON: - ok = (nr >= 3); - break; case PIPE_PRIM_QUADS: - ok = (nr >= 4); - break; case PIPE_PRIM_QUAD_STRIP: - ok = (nr >= 4); - break; default: - ok = 0; - break; + debug_printf("Unrecognized geometry shader primitive"); + return 3; } - - return ok; } - -static INLINE boolean u_trim_pipe_prim( unsigned pipe_prim, unsigned *nr ) +/** + * Returns the number of decomposed primitives for the given + * vertex count. + * Parts of the pipline are invoked once for each triangle in + * triangle strip, triangle fans and triangles and once + * for each line in line strip, line loop, lines. Also + * statistics depend on knowing the exact number of decomposed + * primitives for a set of vertices. + */ +static inline unsigned +u_decomposed_prims_for_vertices(enum pipe_prim_type primitive, int vertices) { - boolean ok = TRUE; - - switch (pipe_prim) { + switch (primitive) { case PIPE_PRIM_POINTS: - ok = (*nr >= 1); - break; + return vertices; case PIPE_PRIM_LINES: - ok = (*nr >= 2); - *nr -= (*nr % 2); - break; - case PIPE_PRIM_LINE_STRIP: + return vertices / 2; case PIPE_PRIM_LINE_LOOP: - ok = (*nr >= 2); - break; + return (vertices >= 2) ? vertices : 0; + case PIPE_PRIM_LINE_STRIP: + return (vertices >= 2) ? vertices - 1 : 0; case PIPE_PRIM_TRIANGLES: - ok = (*nr >= 3); - *nr -= (*nr % 3); - break; + return vertices / 3; case PIPE_PRIM_TRIANGLE_STRIP: + return (vertices >= 3) ? vertices - 2 : 0; case PIPE_PRIM_TRIANGLE_FAN: + return (vertices >= 3) ? vertices - 2 : 0; + case PIPE_PRIM_LINES_ADJACENCY: + return vertices / 4; + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return (vertices >= 4) ? vertices - 3 : 0; + case PIPE_PRIM_TRIANGLES_ADJACENCY: + return vertices / 6; + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + return (vertices >= 6) ? 1 + (vertices - 6) / 2 : 0; + case PIPE_PRIM_QUADS: + return vertices / 4; + case PIPE_PRIM_QUAD_STRIP: + return (vertices >= 4) ? (vertices - 2) / 2 : 0; + /* Polygons can't be decomposed + * because the number of their vertices isn't known so + * for them and whatever else we don't recognize just + * return 1 if the number of vertices is greater than + * or equal to 3 and zero otherwise */ case PIPE_PRIM_POLYGON: - ok = (*nr >= 3); - break; + default: + debug_printf("Invalid decomposition primitive!\n"); + return (vertices >= 3) ? 1 : 0; + } +} + +/** + * Returns the number of reduced/tessellated primitives for the given vertex + * count. Each quad is treated as two triangles. Polygons are treated as + * triangle fans. + */ +static inline unsigned +u_reduced_prims_for_vertices(enum pipe_prim_type primitive, int vertices) +{ + switch (primitive) { case PIPE_PRIM_QUADS: - ok = (*nr >= 4); - *nr -= (*nr % 4); - break; case PIPE_PRIM_QUAD_STRIP: - ok = (*nr >= 4); - *nr -= (*nr % 2); - break; + return u_decomposed_prims_for_vertices(primitive, vertices) * 2; + case PIPE_PRIM_POLYGON: + primitive = PIPE_PRIM_TRIANGLE_FAN; + /* fall through */ default: - ok = 0; - break; + return u_decomposed_prims_for_vertices(primitive, vertices); } +} - if (!ok) - *nr = 0; +static inline enum pipe_prim_type +u_base_prim_type(enum pipe_prim_type prim_type) +{ + switch(prim_type) { + case PIPE_PRIM_POINTS: + return PIPE_PRIM_POINTS; + case PIPE_PRIM_LINES: + case PIPE_PRIM_LINE_LOOP: + case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_LINES_ADJACENCY: + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return PIPE_PRIM_LINES; + case PIPE_PRIM_TRIANGLES: + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_TRIANGLE_FAN: + case PIPE_PRIM_TRIANGLES_ADJACENCY: + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + return PIPE_PRIM_TRIANGLES; + case PIPE_PRIM_QUADS: + case PIPE_PRIM_QUAD_STRIP: + return PIPE_PRIM_QUADS; + default: + return prim_type; + } +} + +static inline unsigned +u_vertices_for_prims(enum pipe_prim_type prim_type, int count) +{ + if (count <= 0) + return 0; + + /* We can only figure out the number of vertices from a number of primitives + * if we are using basic primitives (so no loops, strips, fans, etc). + */ + assert(prim_type == u_base_prim_type(prim_type) && + prim_type != PIPE_PRIM_PATCHES && prim_type != PIPE_PRIM_POLYGON); + + const struct u_prim_vertex_count *info = u_prim_vertex_count(prim_type); + assert(info); - return ok; + return info->min + (count - 1) * info->incr; } +/** + * Returns the number of stream out outputs for a given number of vertices and + * primitive type. + */ -static INLINE unsigned u_reduced_prim( unsigned pipe_prim ) +static inline unsigned +u_stream_outputs_for_vertices(enum pipe_prim_type primitive, unsigned nr) { - switch (pipe_prim) { - case PIPE_PRIM_POINTS: - return PIPE_PRIM_POINTS; + /* Extraneous vertices don't contribute to stream outputs */ + u_trim_pipe_prim(primitive, &nr); - case PIPE_PRIM_LINES: - case PIPE_PRIM_LINE_STRIP: - case PIPE_PRIM_LINE_LOOP: - return PIPE_PRIM_LINES; + /* Polygons are special, since they are a single primitive with many + * vertices. In this case, we just have an output for each vertex (after + * trimming) */ - default: - return PIPE_PRIM_TRIANGLES; - } + if (primitive == PIPE_PRIM_POLYGON) + return nr; + + /* Normally, consider how many primitives are actually generated */ + unsigned prims = u_decomposed_prims_for_vertices(primitive, nr); + + /* One output per vertex after decomposition */ + enum pipe_prim_type base = u_base_prim_type(primitive); + return u_vertices_for_prims(base, prims); +} + +const char *u_prim_name(enum pipe_prim_type pipe_prim); + + +#ifdef __cplusplus } +#endif + #endif