Home | History | Annotate | Download | only in util
      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
     37 extern "C" {
     38 #endif
     39 
     40 struct 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  */
     49 static inline enum pipe_prim_type
     50 u_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  */
     74 static inline enum pipe_prim_type
     75 u_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  */
     94 static inline enum pipe_prim_type
     95 u_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  */
    116 static inline const struct u_prim_vertex_count *
    117 u_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  */
    143 static inline unsigned
    144 u_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 
    157 static inline boolean
    158 u_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 
    166 static inline boolean
    167 u_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 
    182 static inline unsigned
    183 u_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  */
    224 static inline unsigned
    225 u_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  */
    271 static inline unsigned
    272 u_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 
    286 const char *u_prim_name(enum pipe_prim_type pipe_prim);
    287 
    288 
    289 #ifdef __cplusplus
    290 }
    291 #endif
    292 
    293 
    294 #endif
    295