Home | History | Annotate | Download | only in draw
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 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 /* Authors:  Keith Whitwell <keithw (at) vmware.com>
     29  */
     30 
     31 #include "util/u_math.h"
     32 #include "util/u_memory.h"
     33 
     34 #include "pipe/p_shader_tokens.h"
     35 #include "draw_vs.h"
     36 #include "draw_fs.h"
     37 #include "draw_pipe.h"
     38 
     39 
     40 /** subclass of draw_stage */
     41 struct flat_stage
     42 {
     43    struct draw_stage stage;
     44 
     45    uint num_flat_attribs;
     46    uint flat_attribs[PIPE_MAX_SHADER_OUTPUTS];  /* flatshaded attribs */
     47 };
     48 
     49 
     50 static inline struct flat_stage *
     51 flat_stage(struct draw_stage *stage)
     52 {
     53    return (struct flat_stage *) stage;
     54 }
     55 
     56 
     57 /** Copy all the constant attributes from 'src' vertex to 'dst' vertex */
     58 static inline void copy_flats( struct draw_stage *stage,
     59                                struct vertex_header *dst,
     60                                const struct vertex_header *src )
     61 {
     62    const struct flat_stage *flat = flat_stage(stage);
     63    uint i;
     64 
     65    for (i = 0; i < flat->num_flat_attribs; i++) {
     66       const uint attr = flat->flat_attribs[i];
     67       COPY_4FV(dst->data[attr], src->data[attr]);
     68    }
     69 }
     70 
     71 
     72 /** Copy all the color attributes from src vertex to dst0 & dst1 vertices */
     73 static inline void copy_flats2( struct draw_stage *stage,
     74                                 struct vertex_header *dst0,
     75                                 struct vertex_header *dst1,
     76                                 const struct vertex_header *src )
     77 {
     78    const struct flat_stage *flat = flat_stage(stage);
     79    uint i;
     80    for (i = 0; i < flat->num_flat_attribs; i++) {
     81       const uint attr = flat->flat_attribs[i];
     82       COPY_4FV(dst0->data[attr], src->data[attr]);
     83       COPY_4FV(dst1->data[attr], src->data[attr]);
     84    }
     85 }
     86 
     87 
     88 /**
     89  * Flatshade tri. Not required for clipping which handles this on its own,
     90  * but required for unfilled tris and other primitive-changing stages
     91  * (like widelines). If no such stages are active, handled by hardware.
     92  */
     93 static void flatshade_tri_0( struct draw_stage *stage,
     94                              struct prim_header *header )
     95 {
     96    struct prim_header tmp;
     97 
     98    tmp.det = header->det;
     99    tmp.flags = header->flags;
    100    tmp.pad = header->pad;
    101    tmp.v[0] = header->v[0];
    102    tmp.v[1] = dup_vert(stage, header->v[1], 0);
    103    tmp.v[2] = dup_vert(stage, header->v[2], 1);
    104 
    105    copy_flats2(stage, tmp.v[1], tmp.v[2], tmp.v[0]);
    106 
    107    stage->next->tri( stage->next, &tmp );
    108 }
    109 
    110 
    111 static void flatshade_tri_2( struct draw_stage *stage,
    112                              struct prim_header *header )
    113 {
    114    struct prim_header tmp;
    115 
    116    tmp.det = header->det;
    117    tmp.flags = header->flags;
    118    tmp.pad = header->pad;
    119    tmp.v[0] = dup_vert(stage, header->v[0], 0);
    120    tmp.v[1] = dup_vert(stage, header->v[1], 1);
    121    tmp.v[2] = header->v[2];
    122 
    123    copy_flats2(stage, tmp.v[0], tmp.v[1], tmp.v[2]);
    124 
    125    stage->next->tri( stage->next, &tmp );
    126 }
    127 
    128 
    129 /**
    130  * Flatshade line.
    131  */
    132 static void flatshade_line_0( struct draw_stage *stage,
    133                               struct prim_header *header )
    134 {
    135    struct prim_header tmp;
    136 
    137    tmp.det = header->det;
    138    tmp.flags = header->flags;
    139    tmp.pad = header->pad;
    140    tmp.v[0] = header->v[0];
    141    tmp.v[1] = dup_vert(stage, header->v[1], 0);
    142 
    143    copy_flats(stage, tmp.v[1], tmp.v[0]);
    144 
    145    stage->next->line( stage->next, &tmp );
    146 }
    147 
    148 
    149 static void flatshade_line_1( struct draw_stage *stage,
    150                               struct prim_header *header )
    151 {
    152    struct prim_header tmp;
    153 
    154    tmp.det = header->det;
    155    tmp.flags = header->flags;
    156    tmp.pad = header->pad;
    157    tmp.v[0] = dup_vert(stage, header->v[0], 0);
    158    tmp.v[1] = header->v[1];
    159 
    160    copy_flats(stage, tmp.v[0], tmp.v[1]);
    161 
    162    stage->next->line( stage->next, &tmp );
    163 }
    164 
    165 
    166 static int
    167 find_interp(const struct draw_fragment_shader *fs, int *indexed_interp,
    168             uint semantic_name, uint semantic_index)
    169 {
    170    int interp;
    171    /* If it's gl_{Front,Back}{,Secondary}Color, pick up the mode
    172     * from the array we've filled before. */
    173    if (semantic_name == TGSI_SEMANTIC_COLOR ||
    174        semantic_name == TGSI_SEMANTIC_BCOLOR) {
    175       interp = indexed_interp[semantic_index];
    176    } else {
    177       /* Otherwise, search in the FS inputs, with a decent default
    178        * if we don't find it.
    179        */
    180       uint j;
    181       interp = TGSI_INTERPOLATE_PERSPECTIVE;
    182       if (fs) {
    183          for (j = 0; j < fs->info.num_inputs; j++) {
    184             if (semantic_name == fs->info.input_semantic_name[j] &&
    185                 semantic_index == fs->info.input_semantic_index[j]) {
    186                interp = fs->info.input_interpolate[j];
    187                break;
    188             }
    189          }
    190       }
    191    }
    192    return interp;
    193 }
    194 
    195 
    196 static void flatshade_init_state( struct draw_stage *stage )
    197 {
    198    struct flat_stage *flat = flat_stage(stage);
    199    const struct draw_context *draw = stage->draw;
    200    const struct draw_fragment_shader *fs = draw->fs.fragment_shader;
    201    const struct tgsi_shader_info *info = draw_get_shader_info(draw);
    202    uint i, j;
    203 
    204    /* Find which vertex shader outputs need constant interpolation, make a list */
    205 
    206    /* XXX: this code is a near exact copy of the one in clip_init_state.
    207     * The latter also cares about perspective though.
    208     */
    209 
    210    /* First pick up the interpolation mode for
    211     * gl_Color/gl_SecondaryColor, with the correct default.
    212     */
    213    int indexed_interp[2];
    214    indexed_interp[0] = indexed_interp[1] = draw->rasterizer->flatshade ?
    215       TGSI_INTERPOLATE_CONSTANT : TGSI_INTERPOLATE_PERSPECTIVE;
    216 
    217    if (fs) {
    218       for (i = 0; i < fs->info.num_inputs; i++) {
    219          if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_COLOR) {
    220             if (fs->info.input_interpolate[i] != TGSI_INTERPOLATE_COLOR)
    221                indexed_interp[fs->info.input_semantic_index[i]] = fs->info.input_interpolate[i];
    222          }
    223       }
    224    }
    225 
    226    /* Then resolve the interpolation mode for every output attribute.
    227     *
    228     * Given how the rest of the code, the most efficient way is to
    229     * have a vector of flat-mode attributes.
    230     */
    231    flat->num_flat_attribs = 0;
    232    for (i = 0; i < info->num_outputs; i++) {
    233       /* Find the interpolation mode for a specific attribute */
    234       int interp = find_interp(fs, indexed_interp,
    235                                info->output_semantic_name[i],
    236                                info->output_semantic_index[i]);
    237       /* If it's flat, add it to the flat vector. */
    238 
    239       if (interp == TGSI_INTERPOLATE_CONSTANT) {
    240          flat->flat_attribs[flat->num_flat_attribs] = i;
    241          flat->num_flat_attribs++;
    242       }
    243    }
    244    /* Search the extra vertex attributes */
    245    for (j = 0; j < draw->extra_shader_outputs.num; j++) {
    246       /* Find the interpolation mode for a specific attribute */
    247       int interp = find_interp(fs, indexed_interp,
    248                                draw->extra_shader_outputs.semantic_name[j],
    249                                draw->extra_shader_outputs.semantic_index[j]);
    250       /* If it's flat, add it to the flat vector. */
    251       if (interp == TGSI_INTERPOLATE_CONSTANT) {
    252          flat->flat_attribs[flat->num_flat_attribs] = i + j;
    253          flat->num_flat_attribs++;
    254       }
    255    }
    256 
    257    /* Choose flatshade routine according to provoking vertex:
    258     */
    259    if (draw->rasterizer->flatshade_first) {
    260       stage->line = flatshade_line_0;
    261       stage->tri = flatshade_tri_0;
    262    }
    263    else {
    264       stage->line = flatshade_line_1;
    265       stage->tri = flatshade_tri_2;
    266    }
    267 }
    268 
    269 static void flatshade_first_tri( struct draw_stage *stage,
    270                                  struct prim_header *header )
    271 {
    272    flatshade_init_state( stage );
    273    stage->tri( stage, header );
    274 }
    275 
    276 static void flatshade_first_line( struct draw_stage *stage,
    277                                   struct prim_header *header )
    278 {
    279    flatshade_init_state( stage );
    280    stage->line( stage, header );
    281 }
    282 
    283 
    284 static void flatshade_flush( struct draw_stage *stage,
    285                              unsigned flags )
    286 {
    287    stage->tri = flatshade_first_tri;
    288    stage->line = flatshade_first_line;
    289    stage->next->flush( stage->next, flags );
    290 }
    291 
    292 
    293 static void flatshade_reset_stipple_counter( struct draw_stage *stage )
    294 {
    295    stage->next->reset_stipple_counter( stage->next );
    296 }
    297 
    298 
    299 static void flatshade_destroy( struct draw_stage *stage )
    300 {
    301    draw_free_temp_verts( stage );
    302    FREE( stage );
    303 }
    304 
    305 
    306 /**
    307  * Create flatshading drawing stage.
    308  */
    309 struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
    310 {
    311    struct flat_stage *flatshade = CALLOC_STRUCT(flat_stage);
    312    if (!flatshade)
    313       goto fail;
    314 
    315    flatshade->stage.draw = draw;
    316    flatshade->stage.name = "flatshade";
    317    flatshade->stage.next = NULL;
    318    flatshade->stage.point = draw_pipe_passthrough_point;
    319    flatshade->stage.line = flatshade_first_line;
    320    flatshade->stage.tri = flatshade_first_tri;
    321    flatshade->stage.flush = flatshade_flush;
    322    flatshade->stage.reset_stipple_counter = flatshade_reset_stipple_counter;
    323    flatshade->stage.destroy = flatshade_destroy;
    324 
    325    if (!draw_alloc_temp_verts( &flatshade->stage, 2 ))
    326       goto fail;
    327 
    328    return &flatshade->stage;
    329 
    330  fail:
    331    if (flatshade)
    332       flatshade->stage.destroy( &flatshade->stage );
    333 
    334    return NULL;
    335 }
    336 
    337 
    338