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        semantic_index < 2) {
    176       interp = indexed_interp[semantic_index];
    177    } else {
    178       /* Otherwise, search in the FS inputs, with a decent default
    179        * if we don't find it.
    180        */
    181       uint j;
    182       interp = TGSI_INTERPOLATE_PERSPECTIVE;
    183       if (fs) {
    184          for (j = 0; j < fs->info.num_inputs; j++) {
    185             if (semantic_name == fs->info.input_semantic_name[j] &&
    186                 semantic_index == fs->info.input_semantic_index[j]) {
    187                interp = fs->info.input_interpolate[j];
    188                break;
    189             }
    190          }
    191       }
    192    }
    193    return interp;
    194 }
    195 
    196 
    197 static void flatshade_init_state( struct draw_stage *stage )
    198 {
    199    struct flat_stage *flat = flat_stage(stage);
    200    const struct draw_context *draw = stage->draw;
    201    const struct draw_fragment_shader *fs = draw->fs.fragment_shader;
    202    const struct tgsi_shader_info *info = draw_get_shader_info(draw);
    203    uint i, j;
    204 
    205    /* Find which vertex shader outputs need constant interpolation, make a list */
    206 
    207    /* XXX: this code is a near exact copy of the one in clip_init_state.
    208     * The latter also cares about perspective though.
    209     */
    210 
    211    /* First pick up the interpolation mode for
    212     * gl_Color/gl_SecondaryColor, with the correct default.
    213     */
    214    int indexed_interp[2];
    215    indexed_interp[0] = indexed_interp[1] = draw->rasterizer->flatshade ?
    216       TGSI_INTERPOLATE_CONSTANT : TGSI_INTERPOLATE_PERSPECTIVE;
    217 
    218    if (fs) {
    219       for (i = 0; i < fs->info.num_inputs; i++) {
    220          if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_COLOR &&
    221              fs->info.input_semantic_index[i] < 2) {
    222             if (fs->info.input_interpolate[i] != TGSI_INTERPOLATE_COLOR)
    223                indexed_interp[fs->info.input_semantic_index[i]] = fs->info.input_interpolate[i];
    224          }
    225       }
    226    }
    227 
    228    /* Then resolve the interpolation mode for every output attribute.
    229     *
    230     * Given how the rest of the code, the most efficient way is to
    231     * have a vector of flat-mode attributes.
    232     */
    233    flat->num_flat_attribs = 0;
    234    for (i = 0; i < info->num_outputs; i++) {
    235       /* Find the interpolation mode for a specific attribute */
    236       int interp = find_interp(fs, indexed_interp,
    237                                info->output_semantic_name[i],
    238                                info->output_semantic_index[i]);
    239       /* If it's flat, add it to the flat vector. */
    240 
    241       if (interp == TGSI_INTERPOLATE_CONSTANT ||
    242           (interp == TGSI_INTERPOLATE_COLOR && draw->rasterizer->flatshade)) {
    243          flat->flat_attribs[flat->num_flat_attribs] = i;
    244          flat->num_flat_attribs++;
    245       }
    246    }
    247    /* Search the extra vertex attributes */
    248    for (j = 0; j < draw->extra_shader_outputs.num; j++) {
    249       /* Find the interpolation mode for a specific attribute */
    250       int interp = find_interp(fs, indexed_interp,
    251                                draw->extra_shader_outputs.semantic_name[j],
    252                                draw->extra_shader_outputs.semantic_index[j]);
    253       /* If it's flat, add it to the flat vector. */
    254       if (interp == TGSI_INTERPOLATE_CONSTANT) {
    255          flat->flat_attribs[flat->num_flat_attribs] = i + j;
    256          flat->num_flat_attribs++;
    257       }
    258    }
    259 
    260    /* Choose flatshade routine according to provoking vertex:
    261     */
    262    if (draw->rasterizer->flatshade_first) {
    263       stage->line = flatshade_line_0;
    264       stage->tri = flatshade_tri_0;
    265    }
    266    else {
    267       stage->line = flatshade_line_1;
    268       stage->tri = flatshade_tri_2;
    269    }
    270 }
    271 
    272 static void flatshade_first_tri( struct draw_stage *stage,
    273                                  struct prim_header *header )
    274 {
    275    flatshade_init_state( stage );
    276    stage->tri( stage, header );
    277 }
    278 
    279 static void flatshade_first_line( struct draw_stage *stage,
    280                                   struct prim_header *header )
    281 {
    282    flatshade_init_state( stage );
    283    stage->line( stage, header );
    284 }
    285 
    286 
    287 static void flatshade_flush( struct draw_stage *stage,
    288                              unsigned flags )
    289 {
    290    stage->tri = flatshade_first_tri;
    291    stage->line = flatshade_first_line;
    292    stage->next->flush( stage->next, flags );
    293 }
    294 
    295 
    296 static void flatshade_reset_stipple_counter( struct draw_stage *stage )
    297 {
    298    stage->next->reset_stipple_counter( stage->next );
    299 }
    300 
    301 
    302 static void flatshade_destroy( struct draw_stage *stage )
    303 {
    304    draw_free_temp_verts( stage );
    305    FREE( stage );
    306 }
    307 
    308 
    309 /**
    310  * Create flatshading drawing stage.
    311  */
    312 struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
    313 {
    314    struct flat_stage *flatshade = CALLOC_STRUCT(flat_stage);
    315    if (!flatshade)
    316       goto fail;
    317 
    318    flatshade->stage.draw = draw;
    319    flatshade->stage.name = "flatshade";
    320    flatshade->stage.next = NULL;
    321    flatshade->stage.point = draw_pipe_passthrough_point;
    322    flatshade->stage.line = flatshade_first_line;
    323    flatshade->stage.tri = flatshade_first_tri;
    324    flatshade->stage.flush = flatshade_flush;
    325    flatshade->stage.reset_stipple_counter = flatshade_reset_stipple_counter;
    326    flatshade->stage.destroy = flatshade_destroy;
    327 
    328    if (!draw_alloc_temp_verts( &flatshade->stage, 2 ))
    329       goto fail;
    330 
    331    return &flatshade->stage;
    332 
    333  fail:
    334    if (flatshade)
    335       flatshade->stage.destroy( &flatshade->stage );
    336 
    337    return NULL;
    338 }
    339 
    340 
    341