Home | History | Annotate | Download | only in indices
      1 /*
      2  * Copyright 2009 VMware, Inc.
      3  * All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * on the rights to use, copy, modify, merge, publish, distribute, sub
      9  * license, and/or sell copies of the Software, and to permit persons to whom
     10  * the Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
     19  * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     22  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 #include "u_indices.h"
     26 #include "u_indices_priv.h"
     27 
     28 static void translate_memcpy_ushort( const void *in,
     29                                      unsigned start,
     30                                      unsigned in_nr,
     31                                      unsigned out_nr,
     32                                      unsigned restart_index,
     33                                      void *out )
     34 {
     35    memcpy(out, &((short *)in)[start], out_nr*sizeof(short));
     36 }
     37 
     38 static void translate_memcpy_uint( const void *in,
     39                                    unsigned start,
     40                                    unsigned in_nr,
     41                                    unsigned out_nr,
     42                                    unsigned restart_index,
     43                                    void *out )
     44 {
     45    memcpy(out, &((int *)in)[start], out_nr*sizeof(int));
     46 }
     47 
     48 
     49 /**
     50  * Translate indexes when a driver can't support certain types
     51  * of drawing.  Example include:
     52  * - Translate 1-byte indexes into 2-byte indexes
     53  * - Translate PIPE_PRIM_QUADS into PIPE_PRIM_TRIANGLES when the hardware
     54  *   doesn't support the former.
     55  * - Translate from first provoking vertex to last provoking vertex and
     56  *   vice versa.
     57  *
     58  * Note that this function is used for indexed primitives.
     59  *
     60  * \param hw_mask  mask of (1 << PIPE_PRIM_x) flags indicating which types
     61  *                 of primitives are supported by the hardware.
     62  * \param prim  incoming PIPE_PRIM_x
     63  * \param in_index_size  bytes per index value (1, 2 or 4)
     64  * \param nr  number of incoming vertices
     65  * \param in_pv  incoming provoking vertex convention (PV_FIRST or PV_LAST)
     66  * \param out_pv  desired provoking vertex convention (PV_FIRST or PV_LAST)
     67  * \param prim_restart  whether primitive restart is disable or enabled
     68  * \param out_prim  returns new PIPE_PRIM_x we'll translate to
     69  * \param out_index_size  returns bytes per new index value (2 or 4)
     70  * \param out_nr  returns number of new vertices
     71  * \param out_translate  returns the translation function to use by the caller
     72  */
     73 enum indices_mode
     74 u_index_translator(unsigned hw_mask,
     75                    enum pipe_prim_type prim,
     76                    unsigned in_index_size,
     77                    unsigned nr,
     78                    unsigned in_pv,
     79                    unsigned out_pv,
     80                    unsigned prim_restart,
     81                    enum pipe_prim_type *out_prim,
     82                    unsigned *out_index_size,
     83                    unsigned *out_nr,
     84                    u_translate_func *out_translate)
     85 {
     86    unsigned in_idx;
     87    unsigned out_idx;
     88    enum indices_mode ret = U_TRANSLATE_NORMAL;
     89 
     90    assert(in_index_size == 1 ||
     91           in_index_size == 2 ||
     92           in_index_size == 4);
     93 
     94    u_index_init();
     95 
     96    in_idx = in_size_idx(in_index_size);
     97    *out_index_size = (in_index_size == 4) ? 4 : 2;
     98    out_idx = out_size_idx(*out_index_size);
     99 
    100    if ((hw_mask & (1<<prim)) &&
    101        in_index_size == *out_index_size &&
    102        in_pv == out_pv)
    103    {
    104       /* Index translation not really needed */
    105       if (in_index_size == 4)
    106          *out_translate = translate_memcpy_uint;
    107       else
    108          *out_translate = translate_memcpy_ushort;
    109 
    110       *out_prim = prim;
    111       *out_nr = nr;
    112 
    113       return U_TRANSLATE_MEMCPY;
    114    }
    115    else {
    116       *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
    117 
    118       switch (prim) {
    119       case PIPE_PRIM_POINTS:
    120          *out_prim = PIPE_PRIM_POINTS;
    121          *out_nr = nr;
    122          break;
    123 
    124       case PIPE_PRIM_LINES:
    125          *out_prim = PIPE_PRIM_LINES;
    126          *out_nr = nr;
    127          break;
    128 
    129       case PIPE_PRIM_LINE_STRIP:
    130          *out_prim = PIPE_PRIM_LINES;
    131          *out_nr = (nr - 1) * 2;
    132          break;
    133 
    134       case PIPE_PRIM_LINE_LOOP:
    135          *out_prim = PIPE_PRIM_LINES;
    136          *out_nr = nr * 2;
    137          break;
    138 
    139       case PIPE_PRIM_TRIANGLES:
    140          *out_prim = PIPE_PRIM_TRIANGLES;
    141          *out_nr = nr;
    142          break;
    143 
    144       case PIPE_PRIM_TRIANGLE_STRIP:
    145          *out_prim = PIPE_PRIM_TRIANGLES;
    146          *out_nr = (nr - 2) * 3;
    147          break;
    148 
    149       case PIPE_PRIM_TRIANGLE_FAN:
    150          *out_prim = PIPE_PRIM_TRIANGLES;
    151          *out_nr = (nr - 2) * 3;
    152          break;
    153 
    154       case PIPE_PRIM_QUADS:
    155          *out_prim = PIPE_PRIM_TRIANGLES;
    156          *out_nr = (nr / 4) * 6;
    157          break;
    158 
    159       case PIPE_PRIM_QUAD_STRIP:
    160          *out_prim = PIPE_PRIM_TRIANGLES;
    161          *out_nr = (nr - 2) * 3;
    162          break;
    163 
    164       case PIPE_PRIM_POLYGON:
    165          *out_prim = PIPE_PRIM_TRIANGLES;
    166          *out_nr = (nr - 2) * 3;
    167          break;
    168 
    169       case PIPE_PRIM_LINES_ADJACENCY:
    170          *out_prim = PIPE_PRIM_LINES_ADJACENCY;
    171          *out_nr = nr;
    172          break;
    173 
    174       case PIPE_PRIM_LINE_STRIP_ADJACENCY:
    175          *out_prim = PIPE_PRIM_LINES_ADJACENCY;
    176          *out_nr = (nr - 3) * 4;
    177          break;
    178 
    179       case PIPE_PRIM_TRIANGLES_ADJACENCY:
    180          *out_prim = PIPE_PRIM_TRIANGLES_ADJACENCY;
    181          *out_nr = nr;
    182          break;
    183 
    184       case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
    185          *out_prim = PIPE_PRIM_TRIANGLES_ADJACENCY;
    186          *out_nr = ((nr - 4) / 2) * 6;
    187          break;
    188 
    189       default:
    190          assert(0);
    191          *out_prim = PIPE_PRIM_POINTS;
    192          *out_nr = nr;
    193          return U_TRANSLATE_ERROR;
    194       }
    195    }
    196 
    197    return ret;
    198 }
    199 
    200 
    201 /**
    202  * If a driver does not support a particular gallium primitive type
    203  * (such as PIPE_PRIM_QUAD_STRIP) this function can be used to help
    204  * convert the primitive into a simpler type (like PIPE_PRIM_TRIANGLES).
    205  *
    206  * The generator functions generates a number of ushort or uint indexes
    207  * for drawing the new type of primitive.
    208  *
    209  * Note that this function is used for non-indexed primitives.
    210  *
    211  * \param hw_mask  a bitmask of (1 << PIPE_PRIM_x) values that indicates
    212  *                 kind of primitives are supported by the driver.
    213  * \param prim  the PIPE_PRIM_x that the user wants to draw
    214  * \param start  index of first vertex to draw
    215  * \param nr  number of vertices to draw
    216  * \param in_pv  user's provoking vertex (PV_FIRST/LAST)
    217  * \param out_pv  desired proking vertex for the hardware (PV_FIRST/LAST)
    218  * \param out_prim  returns the new primitive type for the driver
    219  * \param out_index_size  returns OUT_USHORT or OUT_UINT
    220  * \param out_nr  returns new number of vertices to draw
    221  * \param out_generate  returns pointer to the generator function
    222  */
    223 enum indices_mode
    224 u_index_generator(unsigned hw_mask,
    225                   enum pipe_prim_type prim,
    226                   unsigned start,
    227                   unsigned nr,
    228                   unsigned in_pv,
    229                   unsigned out_pv,
    230                   enum pipe_prim_type *out_prim,
    231                   unsigned *out_index_size,
    232                   unsigned *out_nr,
    233                   u_generate_func *out_generate)
    234 {
    235    unsigned out_idx;
    236 
    237    u_index_init();
    238 
    239    *out_index_size = ((start + nr) > 0xfffe) ? 4 : 2;
    240    out_idx = out_size_idx(*out_index_size);
    241 
    242    if ((hw_mask & (1<<prim)) &&
    243        (in_pv == out_pv)) {
    244 
    245       *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
    246       *out_prim = prim;
    247       *out_nr = nr;
    248       return U_GENERATE_LINEAR;
    249    }
    250    else {
    251       *out_generate = generate[out_idx][in_pv][out_pv][prim];
    252 
    253       switch (prim) {
    254       case PIPE_PRIM_POINTS:
    255          *out_prim = PIPE_PRIM_POINTS;
    256          *out_nr = nr;
    257          return U_GENERATE_REUSABLE;
    258 
    259       case PIPE_PRIM_LINES:
    260          *out_prim = PIPE_PRIM_LINES;
    261          *out_nr = nr;
    262          return U_GENERATE_REUSABLE;
    263 
    264       case PIPE_PRIM_LINE_STRIP:
    265          *out_prim = PIPE_PRIM_LINES;
    266          *out_nr = (nr - 1) * 2;
    267          return U_GENERATE_REUSABLE;
    268 
    269       case PIPE_PRIM_LINE_LOOP:
    270          *out_prim = PIPE_PRIM_LINES;
    271          *out_nr = nr * 2;
    272          return U_GENERATE_ONE_OFF;
    273 
    274       case PIPE_PRIM_TRIANGLES:
    275          *out_prim = PIPE_PRIM_TRIANGLES;
    276          *out_nr = nr;
    277          return U_GENERATE_REUSABLE;
    278 
    279       case PIPE_PRIM_TRIANGLE_STRIP:
    280          *out_prim = PIPE_PRIM_TRIANGLES;
    281          *out_nr = (nr - 2) * 3;
    282          return U_GENERATE_REUSABLE;
    283 
    284       case PIPE_PRIM_TRIANGLE_FAN:
    285          *out_prim = PIPE_PRIM_TRIANGLES;
    286          *out_nr = (nr - 2) * 3;
    287          return U_GENERATE_REUSABLE;
    288 
    289       case PIPE_PRIM_QUADS:
    290          *out_prim = PIPE_PRIM_TRIANGLES;
    291          *out_nr = (nr / 4) * 6;
    292          return U_GENERATE_REUSABLE;
    293 
    294       case PIPE_PRIM_QUAD_STRIP:
    295          *out_prim = PIPE_PRIM_TRIANGLES;
    296          *out_nr = (nr - 2) * 3;
    297          return U_GENERATE_REUSABLE;
    298 
    299       case PIPE_PRIM_POLYGON:
    300          *out_prim = PIPE_PRIM_TRIANGLES;
    301          *out_nr = (nr - 2) * 3;
    302          return U_GENERATE_REUSABLE;
    303 
    304       case PIPE_PRIM_LINES_ADJACENCY:
    305          *out_prim = PIPE_PRIM_LINES_ADJACENCY;
    306          *out_nr = nr;
    307          return U_GENERATE_REUSABLE;
    308 
    309       case PIPE_PRIM_LINE_STRIP_ADJACENCY:
    310          *out_prim = PIPE_PRIM_LINES_ADJACENCY;
    311          *out_nr = (nr - 3) * 4;
    312          return U_GENERATE_REUSABLE;
    313 
    314       case PIPE_PRIM_TRIANGLES_ADJACENCY:
    315          *out_prim = PIPE_PRIM_TRIANGLES_ADJACENCY;
    316          *out_nr = nr;
    317          return U_GENERATE_REUSABLE;
    318 
    319       case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
    320          *out_prim = PIPE_PRIM_TRIANGLES_ADJACENCY;
    321          *out_nr = ((nr - 4) / 2) * 6;
    322          return U_GENERATE_REUSABLE;
    323 
    324       default:
    325          assert(0);
    326          *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
    327          *out_prim = PIPE_PRIM_POINTS;
    328          *out_nr = nr;
    329          return U_TRANSLATE_ERROR;
    330       }
    331    }
    332 }
    333